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.__data[0:0] = [d_tag, d_un] self.refresh_name_label()
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()
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()))
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)))
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)))
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))
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
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()
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
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()
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()