def divide_intervals(self, stages, table): divided_intervals = {i: intervaltree.IntervalTree() for i in stages} for r in table.iterrows(): n = r["substagenum"] divided_intervals[n].add(intervaltree.Interval(long(r["minaddr"]), long(r["maxaddr"]))) if self.interval_type == self.CUMULATIVE: for i in range(n + 1, len(stages)): divided_intervals[i].add(intervaltree.Interval(long(r["minaddr"]), long(r["maxaddr"]))) for i in divided_intervals.itervalues(): i.merge_overlaps() return divided_intervals
def lookup_symbol_interval(self, name, num): (startaddr, endaddr) = db_info.get(self.stage).mmap_var_loc(name) reloc_names = db_info.get(self.stage).reloc_names_in_substage(num) varloc = intervaltree.Interval(long(startaddr), long(endaddr)) for (rname, rbegin, rsize, roffset) in db_info.get(self.stage).reloc_info_by_cardinal(reloc_names): relrange = intervaltree.Interval(long(rbegin), long(rbegin + rsize)) if relrange.contains_interval(varloc): offset = roffset varloc = intervaltree.Interval(long(varloc.begin + offset), long(varloc.end + offset)) return varloc
def update_writes(self, line, pc, lo, hi, stage, origpc=None, substage=None): if not pc: (path, lineno) = line.split(':') lineno = int(lineno) else: (path, lineno) = ('', 0) if not origpc: origpc = pc w = WriteDstResult(path, lineno, '', [intervaltree.Interval(long(lo), long(hi))], pc, origpc, substage_name=substage) if lo > hi: print "%x > %x at %x" % (lo, hi, pc) traceback.print_stack() self.writerangetable.add_dsts_entry(w)
def from_line(cls, line, stage): res = cls.regexp.match(line.strip()) if res is None: raise Exception("%s is not a framac dst result") else: min_value = long(res.group(1), 0) max_value = long(res.group(2), 0) #if max_value > 0xFFFFFFFF: # max_value = 0xFFFFFFFF lvalue = res.group(3) path = res.group(4) # somewhat of a hack to get relative path root = Main.get_target_cfg().software_cfg.root if path.startswith(root): path = os.path.relpath(path, root) path = os.path.join(Main.raw.runtime.temp_target_src_dir, path) elif path.startswith( Main.test_suite_path): # not sure why this happens path = os.path.relpath(path, Main.test_suite_path) path = os.path.join(Main.raw.runtime.temp_target_src_dir, path) elif path.startswith("/tmp/tmp"): path = "/".join(path.split("/")[3:]) path = os.path.join(Main.raw.runtime.temp_target_src_dir, path) lineno = int(res.group(5)) callstack = res.group(6) # somewhat of a hack for muxconf return cls(path, lineno, lvalue, [intervaltree.Interval(min_value, max_value)], callstack=callstack, stage=stage)
def _add_addr_range(self, start, end): if isinstance(start, (int, long)) and isinstance(end, (int, long)): if not end >= start: raise Exception( "start addr %x must be smaller than end address %x for %s" % (start, end, self.short_name)) self.addresses.add(intervaltree.Interval(long(start), long(end))) else: raise Exception( "One of start addr (%s) end addr (%s) is not an int for %s" % (start, end, self.short_name))
def setup(self): if not self.attr_exists("setup_done"): self.populate_path_from_name("hw_info_path", or_default=True, do_setattr=True) self._check_path("hw_info_path") self._update_raw("hw_info_path", self.hw_info_path) self.setup_done = True self.host_cfgs = {} for h in self.hosts: self.host_cfgs[h] = self.object_config_lookup("HostConfig", h) if not self.attr_exists("addr_range"): self.addr_range = Main.default_raw.HardwareClass._hw.addr_range lo = long(self.addr_range[0]) hi = long(self.addr_range[1]) self.addr_range = intervaltree.IntervalTree( [intervaltree.Interval(lo, hi)]) range_intervals = [] self.addr_range_names = [] if self.attr_exists("named_addr_ranges"): for (k, [lo, hi]) in self.named_addr_ranges.iteritems(): self.addr_range_names.append(k) inter = intervaltree.Interval(long(lo), long(hi)) range_intervals.append(inter) setattr(self, k, inter) self._update_raw(k, inter) self.ram_ranges = intervaltree.IntervalTree(range_intervals) self.ram_ranges.merge_overlaps() self.non_ram_ranges = self.addr_range for r in self.ram_ranges: self.non_ram_ranges.chop(r.begin, r.end) self.non_ram_ranges.remove_overlap(r) if not hasattr(self, "default_host"): self.default_host = self.hosts[0]
def calculate_framac_intervals(self, substages): intervals = {n: intervaltree.IntervalTree() for n in substages} for num in substages: for r in pytable_utils.get_rows(self.trace_intervals_table, 'substagenum == %s' % num): # lookup writes performed by this function f = r['functionname'] (lopc, hipc) = self.fun_info(f) res = db_info.get(self.stage).write_interval_info(tracename, lopc, hipc) intervals[num] += intervaltree.IntervalTree([intervaltree.Interval(long(r[0]), long(r[1])) for r in res]) return intervals
def _relocated(regname, fullname): r = allregions[regname] ret = s rend = fullname.rsplit(".", 1)[1] cardinalres = re.match("([\d])+_relocated", rend) cardinal = cardinalres.group(1) relocindex = re.sub("[._relocated]+", "", rend) if r.addresses_resolved: start = min(r.addresses).begin end = max(r.addresses).end (offset, mod) = db_info.get( self.stage).reloc_offset_and_mod_from_cardinal( relocindex) ret = intervaltree.Interval(long((start + offset) % mod), long((end + offset) % mod)) return ret
def allowed_writes(self, substage): n = substage query = "(substagenum == %d) & (writable == True)" % (n) drs = self.substage_region_policy_table.where(query) iis = intervaltree.IntervalTree() for region in drs: if region['allowed_symbol']: sname = region['symbol_elf_name'] iis.add(self.lookup_symbol_interval(sname, n)) else: query = 'short_name == "%s"' % region['short_name'] for r in self.substage_mmap_addr_table.where(query): iis.add(intervaltree.Interval(long(r['startaddr']), long(r['endaddr']))) iis.merge_overlaps() iis.merge_equals() return iis
def resolve_addresses(self, all_regions={}, values={}): all_resolved = True if self.addresses_resolved is True: return elif self._csv: (f, parsed) = parse_am37x_register_tables.parsecsv(self._csv) addrs = intervaltree.IntervalTree() for p in parsed: addr = p[parse_am37x_register_tables.TITable.ADDRESS] if addr: addr = long(addr, 0) else: continue wid = p[parse_am37x_register_tables.TITable.WIDTH] name = p[parse_am37x_register_tables.TITable.NAME] # create a unique name without spaces name = re.sub("[\s]", "", name) + (".%x" % addr) size = long(wid) / 8 if wid else 4 i = intervaltree.Interval(long(addr), long(addr + size)) addrs.add(i) raw_perms = p[parse_am37x_register_tables.TITable.TYPE].lower() perms = "readonly" if 'w' not in raw_perms else 'global' self._raw_subregions[name] = { 'addresses': [i.begin, i.end], 'include_children': False, 'type': perms, } self.children_names.append("%s.%s" % (self.short_name, name)) self.addresses = addrs f.close() all_resolved = True elif (type(self._raw_addresses) == list): if type(self._raw_addresses[0] ) == list: # its a list of lists of subregions for a in self._raw_addresses: all_resolved = all_resolved and self._resolve_addr_region( a, all_regions, values) else: all_resolved = self._resolve_addr_region( self._raw_addresses, all_regions, values) else: all_resolved = self._resolve_special_addr_region( self._raw_addresses, all_regions, values) self.addresses_resolved = all_resolved
def find_thumb_ranges(stage, noop=False): cc = Main.cc elf = stage.elf thumb = intervaltree.IntervalTree() arm = intervaltree.IntervalTree() data = intervaltree.IntervalTree() if noop: return (thumb, arm, data) cmd = "%snm -S -n --special-syms %s 2>/dev/null" % (cc, elf) output = subprocess.check_output(cmd, shell=True).split('\n') prev = None lo = 0 dta = re.compile('\s+[a-zA-Z]\s+\$[tad]$') for o in output: o = o.strip() if dta.search(o): hi = long(o[:8], 16) if (prev is not None) and (not lo == hi): i = intervaltree.Interval(lo, hi) if prev == 't': thumb.add(i) elif prev == 'a': arm.add(i) elif prev == 'd': data.add(i) else: raise Exception lo = hi prev = o[-1] else: continue res = (thumb, arm, data) for r in res: r.merge_overlaps() r.merge_equals() return res
def create_writes_table(self, start=0, stop=0): self.writestable = self.h5file.create_table( self.group, 'writes', WriteEntry, "statically determined pc \ values for write instructions" ) self.smcstable = self.h5file.create_table( self.group, 'smcs', SmcEntry, "statically determined pc values \ for smc instructions") self.srcstable = self.h5file.create_table(self.group, 'srcs', SrcEntry, "source code info") # now look at instructions if not self.is_arm(): return srcdir = Main.get_runtime_config("temp_target_src_dir") allranges = intervaltree.IntervalTree() for s in utils.get_section_headers(self.stage): if s['flags'].endswith('x'): if s['size'] == 0: continue allranges.add( intervaltree.Interval(long(s['address']), long(s['address'] + s['size']))) allranges.merge_overlaps() r = self.writestable.row smcr = self.smcstable.row allranges = self.thumbranges | self.armranges # loop through all instructions as according to debug symbols for (ra, thumb) in [(self.thumbranges, True), (self.armranges, False)]: for ir in ra: pc_next = ir.begin while pc_next < ir.end: pc = pc_next p = False r2.gets(self.stage.elf, "s 0x%x" % pc) if thumb: # force r2 to use the correct instruction size. sigh. r2.gets(self.stage.elf, "ahb 16") r2.gets(self.stage.elf, "e asm.bits=16") else: r2.gets(self.stage.elf, "ahb 32") r2.gets(self.stage.elf, "e asm.bits=32") r2.get(self.stage.elf, "pd 1") ins_info = r2.get(self.stage.elf, "pdj 1")[0] if p: for k, v in ins_info.iteritems(): print "%s: %s" % (k, v) print "offset %x" % ins_info["offset"] insadded = False if not "disasm" in ins_info or u"invalid" == ins_info[ "type"] or u"invalid" == ins_info["disasm"]: print "invalid instruction according to r2: pc: %x, is thumb? %s. Using capstone to disassemble" % ( pc, thumb) if 'bytes' in ins_info: # get results of capstone disassembly inscheck = self.ia.disasm( b"%s" % ins_info['bytes'].decode("hex"), thumb, pc) ins_info[ 'disasm'] = inscheck.mnemonic + " " + inscheck.op_str else: print ins_info raise Exception() pc = ins_info['offset'] dis = ins_info['disasm'] val = ins_info['bytes'] mne = dis.split()[0] ins = b"%s" % val.decode('hex') pc_next += ins_info['size'] #... just in case radare2 doesn't properly report invalid instructions try: inscheck = self.ia.disasm(ins, thumb, pc) except StopIteration: print "Radare2 disassembled invalid instruction 0x%x (%s) as %s" % ( pc, val, ins_info) continue if mne != inscheck.mnemonic: if thumb: r2.gets(self.stage.elf, "e asm.bits=16") r2.gets(self.stage.elf, "ahb 16") else: r2.gets(self.stage.elf, "ahb 32") r2.gets(self.stage.elf, "e asm.bits=32") print "R2 and capstone disagree at %x %s" % (pc, thumb) print "CAPSTONE --->" print "addr: %x" % inscheck.address print "op: %s" % inscheck.op_str print "mne: %s" % inscheck.mnemonic print "byres: %s" % ["%x" % b for b in inscheck.bytes] print "size: %s" % inscheck.size print "r2 ------------------------>" print r2.gets(self.stage.elf, "e asm.bits") for (k, v) in ins_info.iteritems(): print "%s: %s" % (k, v) r2.get(self.stage.elf, "s 0x%x" % pc) print r2.gets(self.stage.elf, "pd 1") if self.ia.is_mne_memstore( mne) or self.ia.is_mne_memstore( inscheck.mnemonic): raise Exception print "... But I guess it doesn't matter because neither instruction modifies memory." if mne and self.ia.is_mne_memstore(mne): if self.dataranges.overlaps_point(pc): continue r['thumb'] = thumb r['pc'] = pc r['pclo'] = utils.addr_lo(pc) r['pchi'] = utils.addr_hi(pc) r['halt'] = True regs = self.ia.needed_regs(inscheck) if len(regs) > 4: raise Exception("Sorry, too many registers") for i in range(len(regs)): r['reg%d' % i] = regs[i] size = self.ia.calculate_store_size(inscheck) r['writesize'] = size insadded = True r.append() elif mne == 'smc': # add to smcs table smcr['pc'] = pc smcr['pclo'] = utils.addr_lo(pc) smcr['pchi'] = utils.addr_hi(pc) mne = 'smc' thumb = False if self.thumbranges.overlaps_point(pc): thumb = True smcr['thumb'] = thumb insadded = True smcr.append() if self.verbose: print "smc at 0x%x" % pc if insadded: # also cache source code information related to instruction s = self.srcstable.where( "(addrlo == 0x%x) & (addrhi == 0x%x)" % (utils.addr_lo(pc), utils.addr_hi(pc))) try: s = next(s) # is in table, do nothing except StopIteration: srcr = self.srcstable.row srcr['addr'] = pc srcr['addrlo'] = utils.addr_lo(pc) srcr['addrhi'] = utils.addr_hi(pc) srcr['line'] = utils.addr2line(pc, self.stage) srcr['src'] = utils.line2src(srcr['line']) srcr['ivalue'] = ins srcr['ilength'] = len(ins) srcr['thumb'] = thumb srcr['disasm'] = dis srcr['mne'] = mne srcr.append() self.srcstable.flush() insadded = False self.writestable.flush() self.writestable.cols.pclo.create_index(kind='full') self.writestable.cols.pchi.create_index(kind='full') self.smcstable.flush() self.smcstable.cols.pclo.create_index(kind='full') self.smcstable.cols.pchi.create_index(kind='full') self.srcstable.flush() self.srcstable.cols.addrlo.create_index(kind='full') self.srcstable.cols.addrhi.create_index(kind='full') self.srcstable.cols.line.create_index(kind='full') self.smcstable.flush() self.h5file.flush()