def _add_subtree(self, parent_id, br): def get_values(sr): if hasattr(sr.data, 'name'): desc = sr.data.name else: desc = str(sr.data) (start, stop) = sr.abs_range() return desc, format(start, ','), format(stop, ',') pi = ProgressIndicator('show byte ranges...', 1) for idx in xrange(len(br.subranges)): subrange = br.subranges[idx] child_id = parent_id + '.%d' % idx if not self.byte_range_tree.tree.exists(child_id): child_id = self.byte_range_tree.add( parent_id, idx, values=get_values(subrange)) if len(subrange.subranges) > 0: # if there are subsubranges, just insert 1st row so that the open icon is shown if not self.byte_range_tree.tree.exists(child_id + '.0'): subsubrange = subrange.subranges[0] self.byte_range_tree.add(child_id, 0, values=get_values(subsubrange)) pi.click() pi.done()
def parse(self, symtab_command): if symtab_command is None: return self.initialize(0, len(self.byte_range)) if ProgressIndicator.ENABLED: progress = ProgressIndicator('parsing symbol table...', 4096) else: progress = None # Add nlist entries and string table section. sym_tab = SymbolTable(symtab_command.nsyms) sym_str_tab = SymbolStringTable() sym_br = self.add_section(symtab_command.symoff, symtab_command.nsyms * self.nlist_size, data=sym_tab) self.add_section(symtab_command.stroff, symtab_command.strsize, data=sym_str_tab) str_bytes_ = self.byte_range.bytes( symtab_command.stroff, symtab_command.stroff + symtab_command.strsize) # Parse all nlist entries for idx in xrange(symtab_command.nsyms): if progress is not None: progress.click() start = idx * self.nlist_size stop = start + self.nlist_size bytes_ = sym_br.bytes(start, stop) nlist = self.nlist_class(bytes_) # The original code was: # # sym_br.add_subrange(start, self.nlist_size, data=nlist) # # The problem is that for a real iOS app, there can be hundreds of thousands if not # millions of symbols and these Nlist and BytesRange objects consume a lot of memory. # (Each python object with attribute seems to consume at least 300B.) # # The solution is to deviate the framework and save the values of these nlist headers # into a big list. sym_tab.add(nlist) if nlist.n_strx == 0: # From nlist.h: # # Symbols with a index into the string table of zero (n_un.n_strx == 0) are # defined to have a null, "", name. Therefore all string indexes to non null # names must not have a zero string index. This is bit historical information # that has never been well documented. pass else: (sym_name, total_len) = self._find_string(str_bytes_, nlist.n_strx) # Original code is: # # str_br.add_subrange(nlist.n_strx, total_len, data=SymtabString(nlist.n_strx, sym_name)) # # Again, we avoid creating the byte range in order to reduce memory consumption. sym_str_tab.add(nlist.n_strx, sym_name) sym_tab.correlate_string_table(sym_str_tab) if progress is not None: progress.done()