def get_relocate_entries(elf_file): entries=[] readelf_relocs_process=subprocess.Popen([SDK.arm_tool("readelf"),'-r',elf_file],stdout=subprocess.PIPE) readelf_relocs_output=readelf_relocs_process.communicate()[0].decode("utf-8") lines=readelf_relocs_output.splitlines() i=0 reading_section=False while i<len(lines): if not reading_section: if lines[i].startswith("Relocation section '.rel.data"): reading_section=True i+=1 else: if len(lines[i])==0: reading_section=False else: entries.append(int(lines[i].split(' ')[0],16)) i+=1 readelf_relocs_process=subprocess.Popen([SDK.arm_tool("readelf"),'--sections',elf_file],stdout=subprocess.PIPE) readelf_relocs_output=readelf_relocs_process.communicate()[0].decode("utf-8") lines=readelf_relocs_output.splitlines() for line in lines: if'.got'in line and'.got.plt'not in line: words=line.split(' ') while''in words: words.remove('') section_label_idx=words.index('.got') addr=int(words[section_label_idx+2],16) length=int(words[section_label_idx+4],16) for i in range(addr,addr+length,4): entries.append(i) break return entries
def __init__(self, name, arch, max_binary_size, max_memory_size, cflags=[], fallback_platforms=[], directory=""): self.name = name self.arch = arch self.includes = [SDK.include_path(name)] self.lib = os.path.join(SDK.lib_path(name), "libpebble.a") self.max_binary_size = max_binary_size self.max_memory_size = max_memory_size self.cflags = cflags self._syscall_table = None # Lazy-loaded self._patched = False self.fallback_platforms = fallback_platforms self.directory = directory
def _compile(self, infiles, outfile, cflags=None, linkflags=None): if not hasattr(infiles, "__iter__"): infiles = [infiles] cflags = cflags if cflags else [] linkflags = linkflags if linkflags else [] if "-c" not in cflags: # To avoid the harmless warning infiles = infiles + [self._platform.lib] # Common flags cflags = [ "-mcpu=%s" % self._platform.arch, "-mthumb", "-fPIC", "-fPIE", "-ffunction-sections", "-fdata-sections", "-std=c99", "-Os", "-nostdlib"] + ["-I%s" % path for path in self._platform.includes] + cflags if self._platform.cflags: cflags = cflags + self._platform.cflags linkflags = ["-e_entry", "--gc-sections"] + linkflags linkflags = ["-Wl,%s" % flag for flag in linkflags] # Since we're letting gcc link too cmd = [SDK.arm_tool("gcc")] + cflags + linkflags + ["-o", outfile] + infiles logger.debug("Compiling with %s" % cmd) compile_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) result, _ = compile_proc.communicate() if compile_proc.poll(): raise CompilationError("Compilation failed:\n%s" % result)
def syscall_table(self): if not self._syscall_table: self._syscall_table = {} libpebble_dsm_output = subprocess.check_output([SDK.arm_tool("objdump"), "-d", self.lib]).decode("utf-8") for call_match in re.finditer(r"<(?P<fcn>[^>]+)>:(?:\n.+){4}8:\s*(?P<idx>[0-9a-f]{8})", libpebble_dsm_output): self._syscall_table[call_match.group("fcn")] = int(call_match.group("idx"), 16) logger.info("Read %d syscall table entries for %s", len(self.syscall_table.items()), self.name) return self._syscall_table
def _compile_mod_bin(self, infiles, intermdiatefile, outfile, app_addr, bss_addr, bss_section="BSS", cflags=None): ldfile_template = open(os.path.join(os.path.dirname(__file__), "mods_layout.template.ld"), "r").read() ldfile_template = check_replace(ldfile_template, "@BSS@", hex(bss_addr)) # The end of their BSS, plus what we'll insert ldfile_template = check_replace(ldfile_template, "@BSS_SECTION@", bss_section) # Where to put it at all ldfile_template = check_replace(ldfile_template, "@APP@", hex(app_addr)) # Where the rest of the app will get mounted ldfile_out_path = os.path.join(self._scratch_dir, "mods.ld") map_out_path = os.path.join(self._scratch_dir, "mods.map") open(ldfile_out_path, "w").write(ldfile_template) self._compile(infiles, intermdiatefile, linkflags=["-T" + ldfile_out_path, "-Map,%s,--emit-relocs" % map_out_path], cflags=cflags) subprocess.check_call([SDK.arm_tool("objcopy"), "-S", "-R", ".stack", "-R", ".priv_bss", "-R", ".bss", "-O", "binary", intermdiatefile, outfile])
def _get_nm_output(self, elf_file, raw=False): # This is from the SDK nm_process=subprocess.Popen([SDK.arm_tool("nm"),elf_file],stdout=subprocess.PIPE) nm_output=nm_process.communicate()[0] if not nm_output: raise BinaryPatcher.EmptyBinaryError() nm_output = nm_output.decode("utf-8") if raw: return nm_output nm_output=[line.split()for line in nm_output.splitlines()] return nm_output
def get_virtual_size(elf_file): readelf_bss_process=subprocess.Popen([SDK.arm_tool("readelf"), "-S", elf_file], stdout=subprocess.PIPE) readelf_bss_output=readelf_bss_process.communicate()[0].decode("utf-8") last_section_end_addr=0 for line in readelf_bss_output.splitlines(): if len(line)<10: continue line=line[6:] columns=line.split() if len(columns)<6: continue if columns[0]=='.bss': addr=int(columns[2],16) size=int(columns[4],16) last_section_end_addr=addr+size elif columns[0]=='.data'and last_section_end_addr==0: addr=int(columns[2],16) size=int(columns[4],16) last_section_end_addr=addr+size if last_section_end_addr!=0: return last_section_end_addr raise Exception("Failed to parse ELF sections while calculating the virtual size", readelf_bss_output)