Beispiel #1
0
 def crunch_align(self):
     """Replace all .align declarations with minimal byte alignment."""
     desired = int(PlatformVar("align"))
     adjustments = []
     for ii in range(len(self.__content)):
         line = self.__content[ii]
         match = re.match(r'(\s*)\.align\s+(\d+).*', line, re.I)
         if not match:
             continue
         # Compiler thinking aligning to less than desired platform alignment is probably ok.
         align = get_align_bytes(int(match.group(2)))
         if align <= desired:
             continue
         # Some alignment directives are necessary due to data access.
         if not can_minimize_align(align):
             continue
         self.__content[ii] = "%s.balign %i\n" % (match.group(1), desired)
         adjustments += ["%i -> %i" % (align, desired)]
     # Data sections may be reshuffled and require minimal align as first line.
     if self.__name in ["data", "rodata"]:
         match = re.match(r'(\s*)\.b?align\s.*', self.__content[0], re.I)
         if not match:
             first_align = "\t.balign %i\n" % (int(PlatformVar("align")))
             self.__content.insert(0, first_align)
     if is_verbose() and adjustments:
         print("Alignment adjustment(%s): %s" %
               (self.get_name(), ", ".join(adjustments)))
Beispiel #2
0
 def generate_compiler_flags(self):
     """Generate compiler flags."""
     self.__compiler_flags = []
     if self.command_basename_startswith(
             "g++") or self.command_basename_startswith("gcc"):
         self.__compiler_flags += [
             "-Os", "-ffast-math", "-fno-asynchronous-unwind-tables",
             "-fno-enforce-eh-specs", "-fno-exceptions",
             "-fno-implicit-templates", "-fno-rtti", "-fno-stack-protector",
             "-fno-threadsafe-statics", "-fno-use-cxa-atexit",
             "-fno-use-cxa-get-exception-ptr", "-fnothrow-opt",
             "-fomit-frame-pointer", "-funsafe-math-optimizations",
             "-fvisibility=hidden",
             "-march=%s" % (str(PlatformVar("march"))), "-Wall"
         ]
         self.__compiler_flags_whole_program += ["-fwhole-program"]
         # Some flags are platform-specific.
         stack_boundary = int(PlatformVar("mpreferred-stack-boundary"))
         if 0 < stack_boundary:
             self.__compiler_flags += [
                 "-mpreferred-stack-boundary=%i" % (stack_boundary)
             ]
     elif self.command_basename_startswith("clang"):
         self.__compiler_flags += [
             "-Os", "-ffast-math", "-fno-asynchronous-unwind-tables",
             "-fno-exceptions", "-fno-rtti", "-fno-threadsafe-statics",
             "-fomit-frame-pointer", "-funsafe-math-optimizations",
             "-fvisibility=hidden",
             "-march=%s" % (str(PlatformVar("march"))), "-Wall"
         ]
     else:
         raise RuntimeError("compilation not supported with compiler '%s'" %
                            (self.get_command_basename()))
Beispiel #3
0
 def add_dt_needed(self, op):
     """Add requirement to given library."""
     d_tag = AssemblerVariable(
         ("d_tag, DT_NEEDED = 1", PlatformVar("addr"), 1))
     d_un = AssemblerVariable(
         ("d_un, library name offset in strtab", PlatformVar("addr"),
          "strtab_%s - strtab" % labelify(op)))
     self.add_dt_element(d_tag, d_un)
Beispiel #4
0
def generate_loader_hash(symbols, hash_function):
    """Generate import by hash loader code."""
    subst = {
        "BASE_ADDRESS_64BIT": str(PlatformVar("entry", "", "64-bit")),
        "BASE_ADDRESS_ARM32L": str(PlatformVar("entry", "", "arm32l")),
        "BASE_ADDRESS_IA32": str(PlatformVar("entry", "", "ia32")),
        "SYMBOL_COUNT": str(len(symbols)),
    }
    if hash_function == "crc32":
        subst["HASH_FUNCTION"] = g_template_hash_function_crc32.format()
    elif hash_function == "sdbm":
        subst["HASH_FUNCTION"] = g_template_hash_function_sdbm.format()
    else:
        raise RuntimeError("unknown hash function: '%s'" % (hash_function))
    return g_template_loader_hash.format(subst)
Beispiel #5
0
def generate_loader_hash(symbols):
    """Generate import by hash loader code."""
    subst = {
        "BASE_ADDRESS": str(PlatformVar("entry")),
        "SYMBOL_COUNT": str(len(symbols))
    }
    return g_template_loader_hash.format(subst)
Beispiel #6
0
 def link_binary(self, objcopy, src, dst):
     """Link a binary file with no bells and whistles."""
     ld_target = dst
     cmd = [
         self.__command, "--entry=" + str(PlatformVar("entry"))
     ] + listify(src) + self.__linker_script + self.__linker_flags_extra
     # Use objcopy if it was given.
     if objcopy:
         (dst_base, dst_ext) = os.path.splitext(dst)
         dst_bin = dst_base + ".out"
         objcopy_cmd = [objcopy, "--output-target=binary", dst_bin, dst]
         ld_target = dst_bin
     # Otherwise link directly into binary.
     else:
         cmd += ["--oformat=binary"]
     cmd += ["-o", ld_target]
     # Run linker command.
     (so, se) = run_command(cmd)
     if 0 < len(se) and is_verbose():
         print(se)
     # Only run objcopy commad if it was required.
     if objcopy:
         (so_add, se) = run_command(objcopy_cmd)
         if 0 < len(se) and is_verbose():
             print(se)
         so += so_add
     return so
Beispiel #7
0
 def generate_linker_script(self, dst, modify_start=False):
     """Get linker script from linker, improve it, write improved linker script to given file."""
     (so, se) = run_command([self.__command, "--verbose"] +
                            self.__linker_flags_extra)
     if 0 < len(se) and is_verbose():
         print(se)
     # Linker script is the block of code between lines of multiple '=':s.
     match = re.match(r'.*\n=+\s*\n(.*)\n=+\s*\n.*', so, re.DOTALL)
     if not match:
         raise RuntimeError("could not extract script from linker output")
     ld_script = match.group(1)
     # Remove unwanted symbol definitions one at a time.
     unwanted_symbols = [
         "__bss_end__", "__bss_start__", "__end__", "__bss_start",
         "_bss_end__", "_edata", "_end"
     ]
     for ii in unwanted_symbols:
         ld_script = re.sub(r'\n([ \f\r\t\v]+)(%s)(\s*=[^\n]+)\n' % (ii),
                            r'\n\1/*\2\3*/\n', ld_script, re.MULTILINE)
     ld_script = re.sub(
         r'SEGMENT_START\s*\(\s*(\S+)\s*,\s*\d*x?\d+\s*\)',
         r'SEGMENT_START(\1, %s)' % (str(PlatformVar("entry"))), ld_script,
         re.MULTILINE)
     if modify_start:
         ld_script = re.sub(
             r'(SEGMENT_START.*\S)\s*\+\s*SIZEOF_HEADERS\s*;', r'\1;',
             ld_script, re.MULTILINE)
     fd = open(dst, "w")
     fd.write(ld_script)
     fd.close()
     if is_verbose():
         print("Wrote linker script '%s'." % (dst))
     return ld_script
Beispiel #8
0
 def generate_linker_flags(self):
     """Generate linker command for given mode."""
     self.__linker_flags = []
     if self.__command_basename.startswith(
             "g++") or self.__command_basename.startswith("gcc"):
         self.__linker_flags += [
             "-nostartfiles", "-nostdlib", "-Xlinker", "--strip-all"
         ]
     elif self.__command_basename.startswith("clang"):
         self.__linker_flags += ["-nostdlib", "-Xlinker", "--strip-all"]
     elif self.__command_basename.startswith("ld"):
         dynamic_linker = str(PlatformVar("interp"))
         if dynamic_linker.startswith("\"") and dynamic_linker.endswith(
                 "\""):
             dynamic_linker = dynamic_linker[1:-1]
         else:
             raise RuntimeError(
                 "dynamic liner definition '%s' should be quoeted" %
                 (dynamic_linker))
         self.__linker_flags += [
             "-nostdlib", "--strip-all",
             "--dynamic-linker=%s" % (dynamic_linker)
         ]
     else:
         raise RuntimeError("compilation not supported with compiler '%s'" %
                            (op))
Beispiel #9
0
 def get_size(self):
     """Get size of this."""
     platform_align = int(PlatformVar("align"))
     excess_align = self.__size % platform_align
     if excess_align > 0:
         ret = self.__size + (platform_align - excess_align)
         return ret
     return self.__size
Beispiel #10
0
 def add_symbol_empty(self):
   """Add an empty symbol."""
   if osarch_is_32_bit():
     self.add_data(("empty symbol", 4, (0, 0, 0, 0)))
   elif osarch_is_64_bit():
     self.add_data(("empty symbol", 4, (0, 0)))
     self.add_data(("empty symbol", PlatformVar("addr"), (0, 0)))
   else:
     raise_unknown_address_size()
Beispiel #11
0
 def link_binary(self, src, dst):
     """Link a binary file with no bells and whistles."""
     cmd = [self.__command,
            "--entry=" + str(PlatformVar("entry"))] + listify(src) + [
                "-o", dst
            ] + self.__linker_script + self.__linker_flags_extra
     (so, se) = run_command(cmd)
     if 0 < len(se) and is_verbose():
         print(se)
     return so
Beispiel #12
0
 def create_content(self, assembler, prepend_label=None):
     """Generate assembler content."""
     self.clear_content()
     if prepend_label:
         self.add_content(assembler.format_label(prepend_label))
     if 0 < self.__size:
         self.add_content(assembler.format_align(int(PlatformVar("addr"))))
         self.add_content(assembler.format_label("aligned_end"))
     if 0 < self.get_alignment():
         self.add_content(assembler.format_align(self.get_alignment()))
     self.add_content(assembler.format_label("bss_start"))
     cumulative = 0
     for ii in self.__elements:
         self.add_content(
             assembler.format_equ(ii.get_name(),
                                  "bss_start + %i" % (cumulative)))
         cumulative += ii.get_size()
     self.add_content(
         assembler.format_equ("bss_end", "bss_start + %i" % (cumulative)))
Beispiel #13
0
 def minimal_align(self):
   """Remove all .align declarations, replace with desired alignment."""
   desired = int(PlatformVar("align"))
   adjustments = []
   for ii in range(len(self.__content)):
     line = self.__content[ii]
     match = re.match(r'(\s*)\.align\s+(\d+).*', line)
     if not match:
       continue
     # Get actual align byte count.
     align = get_align_bytes(int(match.group(2)))
     if align == desired:
       continue
     # Some alignment directives are necessary due to data access.
     if not can_minimize_align(align):
       continue
     self.__content[ii] = "%s.balign %i\n" % (match.group(1), desired)
     adjustments += ["%i -> %i" % (align, desired)]
   if is_verbose() and adjustments:
     print("Alignment adjustment(%s): %s" % (self.get_name(), ", ".join(adjustments)))
Beispiel #14
0
 def deconstruct_single(self, op):
     """Desconstruct a single value."""
     bom = str(PlatformVar("bom"))
     int_size = int(self.__size)
     if 1 == int_size:
         return struct.pack(bom + "B", op)
     if 2 == int_size:
         if 0 > op:
             return struct.pack(bom + "h", op)
         else:
             return struct.pack(bom + "H", op)
     elif 4 == int_size:
         if 0 > op:
             return struct.pack(bom + "i", op)
         else:
             return struct.pack(bom + "I", op)
     elif 8 == int_size:
         if 0 > op:
             return struct.pack(bom + "q", op)
         else:
             return struct.pack(bom + "Q", op)
     raise RuntimeError("cannot pack value of size %i" % (int_size))
Beispiel #15
0
 def reconstruct(self, lst):
     """Reconstruct variable from a listing."""
     original_size = int(self.__original_size)
     self.__original_size = -1
     if 1 >= original_size:
         return False
     if len(lst) < original_size - 1:
         return False
     ret = chr(self.__value)
     for ii in range(original_size - 1):
         op = lst[ii]
         if not op.reconstructable((original_size - 2) == ii):
             return False
         self.__label_post = listify(self.__label_post, op.label_post)
         ret += chr(op.value)
     bom = str(PlatformVar("bom"))
     if 2 == original_size:
         self.__value = struct.unpack(bom + "H", ret)[0]
     elif 4 == original_size:
         self.__value = struct.unpack(bom + "I", ret)[0]
     elif 8 == original_size:
         self.__value = struct.unpack(bom + "Q", ret)[0]
     self.__size = original_size
     return original_size - 1
Beispiel #16
0
 def add_symbol_und(self, name):
   """Add a symbol to satisfy UND from external source."""
   label_name = "symtab_" + name
   if osarch_is_32_bit():
     self.add_data(("st_name", 4, "strtab_%s - strtab" % (name)))
     self.add_data(("st_value", PlatformVar("addr"), label_name, label_name))
     self.add_data(("st_size", PlatformVar("addr"), PlatformVar("addr")))
     self.add_data(("st_info", 1, 17))
     self.add_data(("st_other", 1, 0))
     self.add_data(("st_shndx", 2, 1))
   elif osarch_is_64_bit():
     self.add_data(("st_name", 4, "strtab_%s - strtab" % (name)))
     self.add_data(("st_info", 1, 17))
     self.add_data(("st_other", 1, 0))
     self.add_data(("st_shndx", 2, 1))
     self.add_data(("st_value", PlatformVar("addr"), label_name, label_name))
     self.add_data(("st_size", PlatformVar("addr"), PlatformVar("addr")))
   else:
     raise_unknown_address_size()
Beispiel #17
0
 def add_dt_hash(self, op):
   """Add hash dynamic structure."""
   d_tag = AssemblerVariable(("d_tag, DT_HASH = 4", PlatformVar("addr"), 4))
   d_un = AssemblerVariable(("d_un", PlatformVar("addr"), op))
   self.__data[0:0] = [d_tag, d_un]
   self.refresh_name_label()
Beispiel #18
0
g_library_definition_c = LibraryDefinition("c", (
    ("int", "fclose", "FILE*"),
    ("FILE*", "fopen", "const char*", "const char*"),
    ("void", "free", "void*"),
    ("size_t", "fwrite", "const void*", "size_t", "size_t", "FILE*"),
    ("void*", "malloc", "size_t"),
    ("void*", "memset", "void*", "int", "size_t"),
    ("int", "printf", "const char* __restrict", "..."),
    ("int", "putc", "int", "FILE*"),
    ("int", "putchar", "int"),
    ("int", "puts", "const char*"),
    ("void", "qsort", "void*", "size_t", "size_t",
     "int (*)(const void*, const void*)"),
    ("void*", "realloc", "void*", "size_t"),
    ("int", ("rand", PlatformVar("function_rand"))),
    ("int", "random"),
    ("unsigned", "sleep", "unsigned"),
    ("void", ("srand", PlatformVar("function_srand")), "unsigned int"),
    ("void", "srandom", "unsigned int"),
))

g_library_definition_bcm_host = LibraryDefinition("bcm_host", (
    ("void", "bcm_host_deinit"),
    ("void", "bcm_host_init"),
    ("DISPMANX_DISPLAY_HANDLE_T", "vc_dispmanx_display_open", "uint32_t"),
    ("DISPMANX_ELEMENT_HANDLE_T", "vc_dispmanx_element_add",
     "DISPMANX_UPDATE_HANDLE_T", "DISPMANX_DISPLAY_HANDLE_T", "int32_t",
     "const VC_RECT_T*", "DISPMANX_RESOURCE_HANDLE_T", "const VC_RECT_T*",
     "DISPMANX_PROTECTION_T", "VC_DISPMANX_ALPHA_T*", "DISPMANX_CLAMP_T*",
     "DISPMANX_TRANSFORM_T"),
Beispiel #19
0
 def get_alignment(self):
     """Get alignment. May be zero."""
     # TODO: Probably creates incorrect binaries at values very close but less than 128M due to code size.
     if 128 * 1024 * 1024 < self.get_size():
         return int(PlatformVar("memory_page"))
     return 0
Beispiel #20
0
 def add_dt_hash(self, op):
     """Add hash dynamic structure."""
     d_tag = AssemblerVariable(
         ("d_tag, DT_HASH = 4", PlatformVar("addr"), 4))
     d_un = AssemblerVariable(("d_un", PlatformVar("addr"), op))
     self.add_dt_element(d_tag, d_un)
Beispiel #21
0
 def add_dt_symtab(self, op):
     """Add symtab dynamic structure."""
     d_tag = AssemblerVariable(
         ("d_tag, DT_SYMTAB = 6", PlatformVar("addr"), 6))
     d_un = AssemblerVariable(("d_un", PlatformVar("addr"), op))
     self.add_dt_element(d_tag, d_un)
Beispiel #22
0
 def add_dt_symtab(self, op):
   """Add symtab dynamic structure."""
   d_tag = AssemblerVariable(("d_tag, DT_SYMTAB = 6", PlatformVar("addr"), 6))
   d_un = AssemblerVariable(("d_un", PlatformVar("addr"), op))
   self.__data[0:0] = [d_tag, d_un]
   self.refresh_name_label()