def add_dsts_entry(self, dstinfo): num = dstinfo.substage if num not in self.tables.iterkeys(): self._init_table(num) r = self.tables[num].row for v in dstinfo.values: r['dstlo'] = v.begin r['dstlolo'] = utils.addr_lo(v.begin) r['dstlohi'] = utils.addr_hi(v.begin) r['dsthi'] = v.end r['dsthilo'] = utils.addr_lo(v.end) r['dsthihi'] = utils.addr_hi(v.end) r['dst_not_in_ram'] = self._addr_inter_is_not_ram(v) r['substage'] = dstinfo.substage line = dstinfo.key() r['line'] = line r['lvalue'] = dstinfo.lvalue if not dstinfo.pc: if hasattr(self.stage, "write_dest_hook"): hook = getattr(self, getattr(self.stge, "write_dest_hook")) hook(dstinfo) if dstinfo.pc == 0: print "cannot resove just one write instruction from %s" % dstinfo.__dict__ continue r['writepc'] = dstinfo.pc r['writepclo'] = utils.addr_lo(dstinfo.pc) r['writepchi'] = utils.addr_hi(dstinfo.pc) r['origpc'] = dstinfo.origpc if dstinfo.origpc else long( r['writepc']) r['origpclo'] = utils.addr_lo(long(r['origpc'])) r['origpchi'] = utils.addr_hi(long(r['origpc'])) r.append()
def _create_var_table(self, substage=-1): fields = ["startaddr", "size", "kind", "name"] vtab = self.var_table if vtab.nrows > 0: return cc = Main.cc stage = self.stage sname = stage.stagename elf = stage.elf cmd = "%snm -n -S %s" % (cc, elf) f = StringIO.StringIO(Main.shell.run_cmd(cmd)) reader = csv.DictReader(f, fields, delimiter=" ", lineterminator="\n", skipinitialspace=True) row = vtab.row for r in reader: if r['name'] is not None: row['name'] = r['name'].strip() row['startaddr'] = long(r['startaddr'].strip(), 16) row['startaddrlo'] = utils.addr_lo(long(row['startaddr'])) row['startaddrhi'] = utils.addr_hi(long(row['startaddr'])) row['endaddr'] = row['startaddr'] + long(r['size'].strip(), 16) row['endaddrlo'] = utils.addr_lo(long(row['endaddr'])) row['endaddrhi'] = utils.addr_hi(long(row['endaddr'])) row['rawkind'] = r['kind'].strip() k = row['rawkind'].lower() if ('t' == k) or ('w' == k): row['kind'] = getattr(addr_space.var_type, 'text') else: row['kind'] = getattr(addr_space.var_type, 'staticvar') row['perms'] = getattr(addr_space.var_perms, 'rw') row['substage'] = substage row.append() vtab.flush()
def create_funcs_table( self ): # using symbol information to get function location and length # symbol information (lenfth) does not always agree with objdump, but that's ok # (example: u-boot, get_tbclk) self.funcstable = self.h5file.create_table(self.group, 'funcs', FuncEntry, "function info") cmd = "%snm -S -n --special-syms %s 2>/dev/null" % (Main.cc, self.stage.elf) output = subprocess.check_output(cmd, shell=True).split('\n') r = self.funcstable.row for o in output: cols = o.split() if len(cols) == 4: (addr, size, typ, name) = cols addr = long(addr, 16) size = long(size, 16) r['fname'] = name r['startaddr'] = addr r['startaddrlo'] = utils.addr_lo(addr) r['startaddrhi'] = utils.addr_hi(addr) r['endaddr'] = addr + size r['endaddrlo'] = utils.addr_lo(addr + size) r['endaddrhi'] = utils.addr_hi(addr + size) r.append() self.funcstable.cols.startaddrlo.create_index(kind='full') self.funcstable.cols.endaddrlo.create_index(kind='full') self.funcstable.cols.startaddrhi.create_index(kind='full') self.funcstable.cols.endaddrhi.create_index(kind='full') self.funcstable.flush() self.h5file.flush()
def write_interval_info(self, hwname, pclo=None, pchi=None, substage_names=[], substage_entries={}): wt = self._get_writestable(hwname) if "framac" in hwname: return [(r['destlo'], r['desthi']) for r in pytable_utils.get_rows('(%d <= writepclo) & (%d <= writepchi) & (writepclo < %d) & (writepchi <= %d)' % \ (utils.addr_lo(pclo), utils.addr_hi(pclo), utils.addr_lo(pchi), utils.addr_hi(pchi)))] else: fns = substage_entries substages = substage_names num = 0 intervals = {n: intervaltree.IntervalTree() for n in substages} for r in wt.read_sorted('index'): pc = long(r['pc']) if num < len(fns) - 1: # check if we found the entrypoint to the next stage (lopc, hipc) = substage_entries[num + 1] if (lopc <= pc) and (pc < hipc): num += 1 if num in substages: start = long(r['dest']) end = start + pytable_utils.get_rows( wt, '(pclo == %d) & (pchi == %d)' % utils.addr_lo(long(r['pc'])), utils.addr_hi(long(r['pc']))[0]['writesize']) intervals[num].add(intervaltree.Interval(start, end)) return intervals
def addr2functionname(self, addr): # print "%x -> %x %x" % (addr, utils.addr_hi(addr), utils.addr_lo(addr)) addr = long(addr) rs = pytable_utils.get_rows(self._sdb.db.funcstable, ( "(startaddrlo <= 0x%x) & (startaddrhi <= 0x%x) & (0x%x < endaddrlo) & (0x%x <= endaddrhi)" % (utils.addr_lo(addr), utils.addr_hi(addr), utils.addr_lo(addr), utils.addr_hi(addr)))) if rs: return rs[0]['fname'] else: return ''
def write_trace_intervals(self, interval, table): r = table.row for (num, iset) in interval.iteritems(): for i in iset: lo = i.begin hi = i.end r['minaddr'] = lo r['minaddrlo'] = utils.addr_lo(lo) r['minaddrhi'] = utils.addr_hi(lo) r['maxaddr'] = hi r['maxaddrlo'] = utils.addr_lo(hi) r['maxaddrhi'] = utils.addr_hi(hi) r['substagenum'] = num r.append() table.flush()
def create_longwrites_table(self): self.longwritestable = self.h5file.create_table( self.group, 'longwrites', LongWrites, "long writes to precompute") skips = [] if not self.is_arm(): return r2.run_aab(self.stage.elf) # run basic block analysis for r in self.stage.longwrites: skips.append(LongWriteDescriptorGenerator(r.name, r.inplace, self)) for s in skips: r = self.longwritestable.row sdesc = s.generate_descriptor() if not sdesc: print "We didn't find any longwrite labels for %s" % s.name continue # to prevent duplicate entries query = "(breakaddrlo == 0x%x) & (breakaddrhi == 0x%x)" % \ (utils.addr_lo(sdesc.breakaddr), utils.addr_hi(sdesc.breakaddr)) descs = pytable_utils.get_rows(self.longwritestable, query) if len(descs) > 0: print "found duplicate longwrite at breakpoint 0x%x" % sdesc.breakaddr continue if not sdesc.valid: "longwrite is not value, continuing" continue sdesc.populate_row(r) if self.verbose: print sdesc.get_info() r.append() self.longwritestable.flush() self.longwritestable.cols.breakaddrlo.create_index(kind='full') self.longwritestable.cols.breakaddrhi.create_index(kind='full') self.longwritestable.flush() self.writestable.flush() self.h5file.flush()
def create_stageexit_table(self): self.stageexits = self.h5file.create_table(self.group, 'stageexits', StageExitInfo, "stage exit info") sls = WriteSearch.find_labels(labeltool.StageinfoLabel, "EXIT", self.stage, "") r = self.stageexits.row for l in sls: lineno = self._get_real_lineno(l) if lineno < 0: print "couldn't find label at %s" % l continue loc = "%s:%d" % (l.filename, lineno) addr = utils.get_line_addr( loc, True, self.stage, srcdir=Main.get_runtime_config("temp_target_src_dir")) success = True if l.name == "success" else False r['addr'] = addr r['addrlo'] = utils.addr_lo(addr) r['addrhi'] = utils.addr_hi(addr) r['line'] = loc r['success'] = success r.append() self.stageexits.flush()
def disasm_and_src_from_pc(self, pc): r = pytable_utils.query( self._sdb.db.srcstable, "(addrlo == 0x%x) & (addrhi == 0x%x)" % (utils.addr_lo(long(pc)), utils.addr_hi(long(pc)))) r = next(r) return (r["disasm"], r["src"])
def create_substage_memmap_table(self): for c in self.csvs: with open(c) as csvfile: fields = ['name', 'startaddr', 'endaddr', 'perms', 'kind'] reader = csv.DictReader(csvfile, fields) r = self.memmap_table.row for entry in reader: for f in fields: if "addr" in f: entry[f] = long(entry[f], 0) entry[f+"lo"] = utils.addr_lo(long(entry[f])) entry[f+"hi"] = utils.addr_hi(long(entry[f])) else: entry[f] = entry[f].strip().lower() if f == 'perms': entry[f] = getattr(mmap_perms, entry[f]) elif f == 'kind': entry[f] = getattr(mmap_type, entry[f]) r[f] = entry[f] #r['substage'] = substage r.append() self.memmap_table.cols.startaddrlo.create_index(kind='full') self.memmap_table.cols.startaddrhi.create_index(kind='full') self.memmap_table.cols.endaddrlo.create_index(kind='full') self.memmap_table.cols.endaddrhi.create_index(kind='full') self.memmap_table.flush()
def stepper_write_info(self, pc): fields = self._sdb.db.writestable.colnames query = "(pclo == 0x%x) & (pchi == 0x%x)" % \ (utils.addr_lo(pc), utils.addr_hi(pc)) for r in pytable_utils.query(self._sdb.db.writestable, query): yield {f: r[f] for f in fields}
def src_write_info(self, pc): fields = self._sdb.db.srcstable.colnames query = "(addrlo == 0x%x) & (addrhi == 0x%x)" % \ (utils.addr_lo(pc), utils.addr_hi(pc)) # query = "addr == 0x%x" % pc r = pytable_utils.get_unique_result(self._sdb.db.srcstable, query) return {f: r[f] for f in fields}
def get_row_information(self): # DST, CPYSTART, CPYEND, BEGIN, READY info = { 'relocpc': self.readyaddr, 'relocpclo': utils.addr_lo(self.readyaddr), 'relocpchi': utils.addr_hi(self.readyaddr), 'relmod': self.relmod, 'startaddr': self.cpystartaddr, 'startaddrlo': utils.addr_lo(self.cpystartaddr), 'startaddrhi': utils.addr_hi(self.cpystartaddr), 'relbegin': self.beginaddr, 'size': self.cpyendaddr - self.cpystartaddr, 'reloffset': self.reloffset, 'reldelorig': self.delorig, 'symname': self.symname, 'name': self.name, } return info
def pc_write_size(self, pc): res = pytable_utils.query( self._sdb.db.writestable, "(pclo == 0x%x) & (pchi == 0x%x)" % (utils.addr_lo(pc), utils.addr_hi(pc))) try: r = next(res) return r['writesize'] except: return 0
def skip_info(self, pc): query = "(pclo == 0x%x) & (pchi == 0x%x)" % \ (utils.addr_lo(pc), utils.addr_hi(pc)) return [{ "resumepc": r["resumepc"], "thumb": r["thumb"] } for r in pytable_utils.query(self._sdb.db.skipstable, query)]
def populate_row(self, r): if not self.valid: return r['breakaddr'] = self.breakaddr r['breakaddrlo'] = utils.addr_lo(self.breakaddr) r['breakaddrhi'] = utils.addr_hi(self.breakaddr) r['contaddr'] = self.contaddr r['inplace'] = self.inplace r['writeaddr'] = self.writeaddr r['writeaddrlo'] = utils.addr_lo(self.writeaddr) r['writeaddrhi'] = utils.addr_hi(self.writeaddr) r['thumb'] = self.thumb r['writesize'] = self.writesize r['start'] = self.start r['startlo'] = utils.addr_lo(self.start) r['starthi'] = utils.addr_hi(self.start) r['end'] = self.end r['endlo'] = utils.addr_lo(self.end) r['endhi'] = utils.addr_hi(self.end)
def _get_write_pc_or_zero(self, dstinfo): framac = True startlineaddr = self._get_line_addr(dstinfo.key(), True, framac) endlineaddr = self._get_line_addr(dstinfo.key(), False, framac) if (startlineaddr < 0) or (endlineaddr < 0): return 0 query = "(0x%x <= pclo) & (0x%x <= pchi) & (pclo < 0x%x) & (pchi <= 0x%x)" % \ (utils.addr_lo(startlineaddr), utils.addr_hi(startlineaddr), utils.addr_lo(endlineaddr), utils.addr_hi(endlineaddr)) write = pytable_utils.get_rows(self.writestable, query) if len(write) == 1: return write[0]['pc'] else: print "0 or more than 1 write (%d) in %s" % (len(write), query) #raise Exception('?') # either 0 or more than zero results return 0
def _add_intervals_to_table(self, table, intervals, pc, line, lvalue, dst, substage): intervals.merge_overlaps() intervals.merge_equals() intervals.merge_overlaps() r = table.row for i in intervals: r['writepc'] = pc r['writepclo'] = utils.addr_lo(long(pc)) r['writepchi'] = utils.addr_hi(long(pc)) r['line'] = line r['lvalue'] = lvalue r['dst_not_in_ram'] = dst r['substage'] = substage r['dstlo'] = i.begin r['dstlolo'] = utils.addr_lo(i.begin) r['dstlohi'] = utils.addr_hi(i.begin) r['dsthi'] = i.end r['dsthilo'] = utils.addr_lo(i.end) r['dsthihi'] = utils.addr_hi(i.end) r.append()
def add_source_code_info_row(self, thumb, addr, ivalue, disasm): r = self._sdb.db.srcstable.row r['thumb'] = thumb r['addr'] = addr r['addrlo'] = utils.addr_lo(addr) r['addrhi'] = utils.addr_hi(addr) r['ivalue'] = ivalue r['ilength'] = len(ivalue) r['mne'] = (disasm.split())[0] r['disasm'] = disasm r.append() self._sdb.db.srcstable.flush()
def pc_writes_info(self, pc): fields = [ 'pc', 'pclo', 'pchi', 'thumb', 'reg0', 'reg1', 'reg2', 'reg3', 'reg4', 'writesize', 'halt' ] return { f: r[f] for f in fields for r in pytable_utils.query( self._sdb.db.writestable, "(pclo == 0x%x) & (pchi == 0x%x)" % (utils.addr_lo(pc), utils.addr_hi(pc))) }
def update_from_trace(self, tracewrites): for w in tracewrites: pc = long(w["pc"]) thumb = self.thumbranges.overlaps_point(pc) 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: r2.gets(self.stage.elf, "s 0x%x" % pc) i = r2.get(self.stage.elf, "pdj 1")[0] ins = b"%s" % i["bytes"] dis = i["disasm"] mne = dis.split()[0] 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() ws = self.writestable.row ws['thumb'] = thumb ws['pc'] = pc ws['pclo'] = utils.addr_lo(pc) ws['pchi'] = utils.addr_hi(pc) ws['writesize'] = w['reportedsize'] ws['halt'] = False ws.append self.srcstable.flush() self.srcstable.reindex() self.writestable.flush() self.writestable.reindex() self.h5file.flush()
def populate_mmap_tables(self, mmap_info): info_table = self.substage_mmap_info_table addr_table = self.substage_mmap_addr_table if addr_table.nrows > 0 or info_table.nrows > 0: return info_row = info_table.row for (short_name, region) in mmap_info.regions.iteritems(): info_row['short_name'] = short_name info_row['parent_name'] = region.parent.short_name if region.parent else '' info_row['name'] = region.name info_row['comments'] = region.contents info_row['include_children'] = region.include_children info_row['do_print'] = True if region.parent and region.parent._csv: info_row['do_print'] = False info_row['reclassifiable'] = region.reclassifiable info_row.append() info_table.flush() info_table.cols.short_name.reindex() info_table.cols.parent_name.reindex() addr_row = addr_table.row for (short_name, region) in mmap_info.regions.iteritems(): for a in region.addresses: addr_row['short_name'] = short_name addr_row['startaddr'] = a.begin addr_row['startaddrlo'] = utils.addr_lo(a.begin) addr_row['startaddrhi'] = utils.addr_hi(a.begin) addr_row['endaddr'] = a.end addr_row['endaddrlo'] = utils.addr_lo(a.end) addr_row['endaddrhi'] = utils.addr_hi(a.end) addr_row.append() addr_table.flush() addr_table.cols.short_name.reindex() addr_table.cols.startaddrlo.reindex() addr_table.cols.startaddrhi.reindex() addr_table.cols.endaddrlo.reindex() addr_table.cols.endaddrhi.reindex() self.h5mmap.flush()
def __init__(self, start, end, inplace, table): self.stage = table.stage self.table = table self.inplace = inplace self.valid = False self.start = start self.end = end self.thumb = self.table.thumbranges.overlaps_point(self.start) self.info = LongWriteInfo(self.stage.elf, self.start, self.end, self.thumb) self.info.calculate_info() ins = self.table.ia.disasm( b"%s" % self.info.write_ins["bytes"].decode("hex"), self.thumb, self.info.write_ins["offset"]) self.write_size = self.table.ia.calculate_store_size(ins) self.breakaddr = self.info.start_ins_addr self.writeaddr = self.info.write_ins_addr self.contaddr = self.info.finish_ins_addr writes = self.table.writestable.where( "(0x%x == pclo) & (0x%x == pchi)" % (utils.addr_lo(self.writeaddr), utils.addr_hi(self.writeaddr))) try: write = next(writes) except Exception as e: print e print "Longwrite not found at %x (%s)" % (self.writeaddr, self.__dict__) return self.valid = True self.writesize = write['writesize'] r2.get(self.stage.elf, "s 0x%x" % self.writeaddr) if self.thumb: r2.get(self.stage.elf, "e asm.bits=16") r2.gets(self.stage.elf, "ahb 16") else: r2.get(self.stage.elf, "e asm.bits=32") r2.gets(self.stage.elf, "ahb 32") r2.get(self.stage.elf, "pd 1") i = r2.get(self.stage.elf, "pdj 1")[0] self.value = b"%s" % i["bytes"] self.disasm = i["disasm"] write['halt'] = False write.update() self.funname = db_info.get(self.stage).addr2functionname( self.writeaddr) self.instr = self.table.ia.disasm(self.value, self.thumb, self.writeaddr) self.table.writestable.flush()
def _create_reg_table(self): for c in self.reg_csvs: (f, reader) = parse_am37x_register_tables.parsecsv(c) row = self.reg_table.row for r in reader: row['address'] = long(r['address'].strip(), 16) if r['address'] else 0 row['addresslo'] = utils.addr_lo(long(row['address'])) row['addresshi'] = utils.addr_hi(long(row['address'])) row["offset"] = long(r["offset"].strip(), 16) if r["offset"] else 0 row['offsetlo'] = utils.addr_lo(long(row['offset'])) row['offsethi'] = utils.addr_hi(long(row['offset'])) row["table"] = r["table"] if r["table"] else "" row["typ"] = r["typ"] if r["typ"] else "" row["width"] = long(r["width"]) if r["width"] else 0 row["reset"] = r["reset"] if r["reset"] else "" row["name"] = r["name"] if r["name"] else "" if row['address'] == 0: print "addr not found in %s" % r row.append() f.close() self.reg_table.cols.addresslo.create_index(kind='full') self.reg_table.cols.addresshi.create_index(kind='full') self.reg_table.flush()
def add_write_entry(self, time, pid, size, dest, pc, lr, cpsr, callindex=0, substagenum=None): #if self.pcmin > self.pcmax: # print "PC not in range %x %x (%x)" % (self.pcmin, self.pcmax, pc) # traceback.print_stack() #if (pc <= self.pcmax) and (pc >= self.pcmin): # get relocation info from writesearch database #index = self.trace_count r = self.writestable.row r['pid'] = pid r['dest'] = dest r['relocatedpc'] = pc r['relocatedpclo'] = utils.addr_lo(pc) r['relocatedpchi'] = utils.addr_hi(pc) r['relocatedlr'] = lr r['relocatedlrlo'] = utils.addr_lo(lr) r['relocatedlrhi'] = utils.addr_hi(lr) r['time'] = time r['reportedsize'] = size r['callindex'] = callindex r['index'] = self.trace_count r['cpsr'] = cpsr r['pc'] = pc r['pclo'] = utils.addr_lo(pc) r['pchi'] = utils.addr_hi(pc) r['lr'] = lr r['lrlo'] = utils.addr_lo(lr) r['lrhi'] = utils.addr_hi(lr) if substagenum is not None: r['substage'] = substagenum for rinfo in self.rinfos: offset = rinfo['reloffset'] start = (rinfo['startaddr'] + offset) end = start + rinfo['size'] + offset # if pc is in a relocated dest range (for now we assume no overlap) if (start <= pc) and (pc <= end): r['pc'] = pc - offset r['pclo'] = utils.addr_lo(long(r['pc'])) r['pchi'] = utils.addr_hi(long(r['pc'])) r['lr'] = lr - offset r['lrlo'] = utils.addr_lo(long(r['lr'])) r['lrhi'] = utils.addr_hi(long(r['lr'])) break self.trace_count += 1 r.append()
def _find_mux_pc(self, dst): user = {'res': None, 'dst': long(dst)} def code_hook(emu, access, addr, size, value, user): dst = long(user['dst']) if long(addr) == dst: pc = emu.reg_read(UC_ARM_REG_PC) user['res'] = pc return True user['dst'] = dst user['dstlo'] = utils.addr_lo(dst) user['dsthi'] = utils.addr_hi(dst) h = self.emu.hook_add(UC_HOOK_MEM_WRITE, code_hook, user_data=user) if self._thumb: self.emu.emu_start(self._mux_start | 1, self._mux_end) else: self.emu.emu_start(self._mux_start, self._mux_end) self.emu.hook_del(h) if user['res'] is None: raise Exception("DSF %x" % dst) return user['res']
def addr_in_funcs_table(self, pc): return pytable_utils.has_results( self._sdb.db.funcstable, "(startaddrlo <= 0x%x) & (startaddrhi <= 0x%x) & (0x%x < endaddrlo) & (0x%x <= endaddrhi)" % (utils.addr_lo(pc), utils.addr_hi(pc), utils.addr_lo(pc), utils.addr_hi(pc)))
def histogram(self): group = self.get_group() if hasattr(group, 'writerange'): # make the table again, just in case group.writerange.remove() self.histotable = self.h5file.create_table(group, 'writerange', TraceWriteRange, "qemu memory write ranges") self.histotable.cols.index.create_index(kind='full') histotable = self.histotable srcdir = Main.raw.runtime.temp_target_src_dir relocatedpc = 0 relocatedlr = 0 size = 0 byteswritten = 0 destlo = 0 currentrow = None line = '' index = 0 push = False pc = -1 sub = -1 for writerow in self.writestable.read_sorted('index'): if (long(writerow['relocatedpc']) == relocatedpc) and \ (long(writerow['relocatedlr']) == relocatedlr) and \ ((destlo + byteswritten) == long(writerow['dest'])): # append to current row currentrow['byteswritten'] += size byteswritten = currentrow['byteswritten'] if push: currentrow['destlo'] = currentrow['desthi'] - byteswritten currentrow['destlolo'] = utils.addr_lo( long(currentrow['destlo'])) currentrow['destlohi'] = utils.addr_hi( long(currentrow['destlo'])) else: currentrow['desthi'] = currentrow['destlo'] + byteswritten currentrow['desthilo'] = utils.addr_lo( long(currentrow['desthi'])) currentrow['desthihi'] = utils.addr_hi( long(currentrow['desthi'])) currentrow['numops'] += 1 else: # create a new row if currentrow is not None: if push: push = False currentrow.append() # start a new row currentrow = self.histotable.row pc = long(writerow['pc']) relocatedpc = long(writerow['relocatedpc']) relocatedpclo = utils.addr_lo(relocatedpc) relocatedpchi = utils.addr_hi(relocatedpc) relocatedlr = long(writerow['relocatedlr']) relocatedlrlo = utils.addr_lo(relocatedlr) relocatedlrhi = utils.addr_hi(relocatedlr) currentrow['cpsr'] = writerow['cpsr'] currentrow['lr'] = long(writerow['lr']) currentrow['lrlo'] = utils.addr_lo(long(writerow['lr'])) currentrow['lrhi'] = utils.addr_hi(long(writerow['lr'])) lr = writerow['lr'] sub = writerow['substage'] currentrow['numops'] = 1 currentrow['pc'] = pc currentrow['pclo'] = utils.addr_lo(pc) currentrow['pchi'] = utils.addr_hi(pc) currentrow['relocatedpc'] = relocatedpc currentrow['relocatedpclo'] = utils.addr_lo(relocatedpc) currentrow['relocatedpchi'] = utils.addr_hi(relocatedpc) currentrow['relocatedlr'] = relocatedlr currentrow['relocatedlrlo'] = utils.addr_lo(relocatedlr) currentrow['relocatedlrhi'] = utils.addr_hi(relocatedlr) currentrow['substage'] = sub currentrow['index'] = index index += 1 size = db_info.get(self.stage).pc_write_size(pc) if size < 0: desthi = long(writerow['dest']) currentrow['desthi'] = desthi currentrow['desthilo'] = utils.addr_lo(desthi) currentrow['desthihi'] = utils.addr_hi(desthi) currentrow['destlo'] = long(desthi - size) currentrow['destlolo'] = utils.addr_lo( long(currentrow['destlo'])) currentrow['destlohi'] = utils.addr_hi( long(currentrow['destlo'])) size = -1 * size push = True else: push = False destlo = long(writerow['dest']) currentrow['destlo'] = destlo currentrow['destlolo'] = utils.addr_lo(destlo) currentrow['destlohi'] = utils.addr_hi(destlo) currentrow['desthi'] = long(destlo + size) currentrow['desthilo'] = utils.addr_lo( long(currentrow['desthi'])) currentrow['desthihi'] = utils.addr_hi( long(currentrow['desthi'])) byteswritten = size currentrow['byteswritten'] = size if currentrow is not None: currentrow.append() # append last row histotable.flush() histotable.reindex() substagenums = substage.SubstagesInfo.substage_numbers(self.stage) print histotable.nrows for i in substagenums: print "# block writes for substage %d: %d" % ( i, len([n for n in histotable.where("substage == %d" % i)])) self.h5file.flush()
def get_row_information(self): row = {} labels = WriteSearch.find_labels(labeltool.SkipLabel, "", self.stage, self.name) startaddr = -1 endaddr = -1 start = "" end = "" elf = self.stage.elf srcdir = Main.get_runtime_config("temp_target_src_dir") isfunc = False for l in labels: if not l.name == self.name: continue if l.value == "START": lineno = self.table._get_real_lineno(l, False) start = "%s:%d" % (l.filename, lineno) elif l.value == "END": lineno = self.table._get_real_lineno(l, True) end = "%s:%d" % (l.filename, lineno) elif l.value == "FUNC": isfunc = True lineno = self.table._get_real_lineno(l, False) start = "%s:%d" % (l.filename, lineno) startaddr = self.table._get_line_addr(start, True) f = pytable_utils.get_unique_result(self.table.funcstable, ( "(startaddrlo <= 0x%x) & (0x%x < endaddrlo) & (startaddrhi <= 0x%x) & (0x%x <= endaddrhi)" % (utils.addr_lo(startaddr), utils.addr_lo(startaddr), utils.addr_hi(startaddr), utils.addr_hi(startaddr)))) (startaddr, endaddr) = (f['startaddr'], f['endaddr']) r2.get(elf, "s 0x%x" % startaddr) thumb = False if self.table.thumbranges.overlaps_point(startaddr): thumb = True if thumb: r2.get(self.stage.elf, "e asm.bits=16") r2.gets(self.stage.elf, "ahb 16") else: r2.get(self.stage.elf, "e asm.bits=32") r2.gets(self.stage.elf, "ahb 32") disasm = r2.get(elf, "pd 2") disasm = r2.get(elf, "pdj 2") if disasm[0]["disasm"].startswith("push"): firstins = disasm[1] else: firstins = disasm[0] startaddr = firstins["offset"] #print "start %s,%x" % (startaddr, endaddr) elif l.value == "NEXT": lineno = self.table._get_real_lineno(l, False) start = "%s:%d" % (l.filename, lineno) end = "%s:%d" % (l.filename, lineno) if lineno == -1: return None if (startaddr < 0) and (endaddr < 0): # move startaddr after any push instructions startaddr = self.table._get_line_addr(start, True) endaddr = self.table._get_line_addr(end, False) r2.get(elf, "s 0x%x" % startaddr) thumb = False if self.table.thumbranges.overlaps_point(startaddr): thumb = True if thumb: r2.gets(self.stage.elf, "ahb 16") r2.get(self.stage.elf, "e asm.bits=16") else: r2.gets(self.stage.elf, "ahb 32") r2.get(self.stage.elf, "e asm.bits=32") disasm = r2.get(elf, "pd 2") disasm = r2.get(elf, "pdj 2") if "disasm" in disasm[0]: if (disasm[0][u"disasm"].startswith("push")): # don't include push instruction startins = disasm[1] else: startins = disasm[0] startaddr = startins["offset"] s = long(startaddr + self.adjuststart) e = long(endaddr + self.adjustend) if e < s: t = s s = e e = t row['pc'] = s row['pclo'] = utils.addr_lo(s) row['pchi'] = utils.addr_hi(s) row['resumepc'] = e row['resumepclo'] = utils.addr_lo(e) row['resumepchi'] = utils.addr_hi(e) row['isfunction'] = isfunc row['thumb'] = self.table.thumbranges.overlaps_point(row['pc']) return row
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()