diff --git a/guider/guider.py b/guider/guider.py index f3475a89..0aad31bf 100755 --- a/guider/guider.py +++ b/guider/guider.py @@ -7,7 +7,7 @@ __credits__ = "Peace Lee" __license__ = "GPLv2" __version__ = "3.9.8" -__revision__ = "240526" +__revision__ = "240527" __maintainer__ = "Peace Lee" __email__ = "iipeace5@gmail.com" __repository__ = "https://github.com/iipeace/guider" @@ -7005,6 +7005,30 @@ def ungzip(path): gzip = SysMgr.getPkg("gzip") return gzip.open(path, "rb").read() + @staticmethod + def compObj(obj): + try: + return SysMgr.getPkg("zlib", False).compress( + SysMgr.getPicklePkg(False).dumps(obj) + ) + except SystemExit: + sys.exit(0) + except: + SysMgr.printWarn("failed to compress object", reason=True) + return obj + + @staticmethod + def decompObj(obj): + try: + return SysMgr.getPicklePkg(False).loads( + SysMgr.getPkg("zlib", False).decompress(obj) + ) + except SystemExit: + sys.exit(0) + except: + SysMgr.printWarn("failed to decompress object", reason=True) + return obj + @staticmethod def unzip(fd, name): # get pkg # @@ -12886,7 +12910,7 @@ def read_struct(self, structure, offset, platform64=None): return structure._from_buffer_copy( raw, platform64=platform64 - if platform64 != None + if platform64 is not None else self.platform64, ) else: @@ -12936,7 +12960,7 @@ def __len__(self): return int(self.inode.i_size) def __repr__(self): - if self.inode_idx != None: + if self.inode_idx is not None: return ( "%s(inode_idx = %s, offset = 0x%X, volume_uuid = %s" ) % ( @@ -13548,7 +13572,7 @@ def read_block(self, fileBlkIdx): """ diskBlkIdx = self.get_block_mapping(fileBlkIdx) - if diskBlkIdx != None: + if diskBlkIdx is not None: return self.volume.read( diskBlkIdx * self.volume.block_size, self.volume.block_size, @@ -37025,6 +37049,9 @@ def printHelp(force=False, isExit=True): # {0:1} {1:1} {2:1} -q DEBUGINFO -H # {0:1} {1:1} {2:1} -q DEBUGINFO:/usr/lib/libc.so + - Use debug info without compression + # {0:1} {1:1} {2:1} -q NODEBUGCOMP + - Apply DWARF file filter # {0:1} {1:1} {2:1} -eD -q TARGETDWARF:"*deno" # {0:1} {1:1} {2:1} -eD -q EXCEPTDWARF:"*deno" @@ -57588,7 +57615,7 @@ def _enableSigPipe(): break # check process status # - if procObj.poll() != None: + if procObj.poll() is not None: break SysMgr.printInfo("terminated '%s' for %s" % (value, addr)) @@ -65380,7 +65407,7 @@ def _waitAndKill(tobj, pid, comm, cond, sig, purpose, hookCmd=None): utime = long(procData[utimeIdx]) stime = long(procData[stimeIdx]) ttime = utime + stime - if prevCpu != None: + if prevCpu is not None: cpu = ttime - prevCpu cpustr = "%.1f" % (cpu / SysMgr.uptimeDiff) else: @@ -93754,7 +93781,10 @@ def _getRetAddr(): # get CFA rules # rules = dwarf["CFATable"].get(faddr) - if not rules: + # decompress rules # + if not isinstance(rules, list): + dwarf["CFATable"][faddr] = rules = UtilMgr.decompObj(rules) + elif not rules: SysMgr.printWarn( "failed to find CFA table info for %s(%s) in %s" % (sym, hex(faddr), fname) @@ -93820,7 +93850,6 @@ def _getRetAddr(): continue offset = value[argIdx] if offset is None: - print(rule) continue rval = readMem(cfa + offset) reg = ConfigMgr.regList[num] @@ -100431,6 +100460,9 @@ class ElfAnalyzer(object): DT_VERSIONTAGNUM = 16 + ruleCacheList = {} + regCacheList = {} + rustChars = [ [",", "$C$"], ["@", "$SP$"], @@ -102470,11 +102502,18 @@ class RegisterRule(object): TYPE = 0 ARG = 1 - def __init__(self, type, arg=None): + def __init__(self, t, arg=None): pass - def __new__(self, type, arg=None): - return (type, arg) + def __new__(self, t, arg=None): + if not t in ElfAnalyzer.ruleCacheList: + ElfAnalyzer.ruleCacheList[t] = {} + + args = str(arg) if type(arg) is list else arg + + if not args in ElfAnalyzer.ruleCacheList[t]: + ElfAnalyzer.ruleCacheList[t][args] = (t, arg) + return ElfAnalyzer.ruleCacheList[t][args] class CFARule(object): """ @@ -103557,13 +103596,13 @@ def getRangeBySymbol(self, symbol): return None # use each symbol tables # - val = self.attr["symTable"].get(symbol) - if val: - return [val["value"], val["value"] + val["size"]] + for sname in ("symTable", "dynsymTable", "dwarfsymTable"): + if not sname in self.attr: + continue - val = self.attr["dynsymTable"].get(symbol) - if val: - return [val["value"], val["value"] + val["size"]] + val = self.attr[sname].get(symbol) + if val: + return [val["value"], val["value"] + val["size"]] return None @@ -106579,7 +106618,7 @@ def _getAugData(string, table, pos, size): return augdict, adstr.strip(), augdata - def _decodeCFI(self, entry, cfi, cie, offset): + def _decodeCFI(self, entry, cfi, cie, offset, prt): def _add2Order(regnum): """ DW_CFA_restore and others remove registers from curLine, @@ -106727,7 +106766,7 @@ def _add2Order(regnum): try: if len(curLine[n]) != 2: continue - elif curLine[n][1] != None: + elif curLine[n][1] is not None: continue curLine.pop(n) @@ -106743,11 +106782,22 @@ def _add2Order(regnum): if curLine["cfa"][regIdx] is not None or len(curLine) > 2: table.append(curLine) - # save result # + # compress dwarf table # + if ( + entry == "FDE" + and not prt + and not "NODEBUGCOMP" in SysMgr.environList + ): + table = UtilMgr.compObj(table) + + # save table # myObj["table"] = table - myObj["regOrder"] = regOrder - return table, regOrder + # save regOrder # + regOrders = str(regOrder) + if not regOrders in ElfAnalyzer.regCacheList: + ElfAnalyzer.regCacheList[regOrders] = regOrder + myObj["regOrder"] = ElfAnalyzer.regCacheList[regOrders] def _makeCFATable(self, entry, offset, regList, prt=False): def _getCFARule(cfa): @@ -106773,10 +106823,9 @@ def _getRegRule(reg): return s + # get values # myObj = self.attr["dwarf"][entry][offset] table = myObj["table"] - regOrder = myObj["regOrder"] - initLoc = myObj.get("initLoc", 0) # get return address register # @@ -106790,48 +106839,49 @@ def _getRegRule(reg): self.attr["dwarf"]["CFAIndex"].append(initLoc) self.attr["dwarf"]["CFATable"][initLoc] = table - if prt: - # remove return address register # + if not prt: + # remove FDE to save memory # + if entry == "FDE": + self.attr["dwarf"][entry].pop(offset) + return + + # remove return address register # + regOrder = myObj["regOrder"] + try: + regOrder.remove(rar) + except SystemExit: + sys.exit(0) + except: + pass + + # define default title # + if not self.cfaTableTitle: + self.cfaTableTitle = "{0:^16} {1:<10}".format("LOC", "CFA") + + # copy default title # + s = str(self.cfaTableTitle) + + # add reg name # + for regnum in regOrder: try: - regOrder.remove(rar) + s += "%-6s" % regList[regnum] except SystemExit: sys.exit(0) except: - pass - - # define default title # - if not self.cfaTableTitle: - self.cfaTableTitle = "{0:^16} {1:<10}".format( - "LOC", "CFA" + SysMgr.printWarn( + "failed to get register name", reason=True ) - # copy default title # - s = str(self.cfaTableTitle) + s += "%-6s\n" % "ra" + regOrder.append(rar) - # add reg name # - for regnum in regOrder: - try: - s += "%-6s" % regList[regnum] - except SystemExit: - sys.exit(0) - except: - SysMgr.printWarn( - "failed to get register name", reason=True - ) - - s += "%-6s\n" % "ra" - regOrder.append(rar) - - # mark line # - s = "." * len(s) + "\n" + s + # mark line # + s = "." * len(s) + "\n" + s # add decoded CFA lines # for line in table: pc = line["pc"] - if not prt: - continue - # pc # s += "%016x" % pc @@ -106852,8 +106902,16 @@ def _getRegRule(reg): s += "\n" - if prt: - printer(s) + printer(s) + + # remove FDE to save memory # + if entry == "FDE": + self.attr["dwarf"][entry].pop(offset) + + # compress CFA table # + if initLoc > 0 and not "NODEBUGCOMP" in SysMgr.environList: + table = UtilMgr.compObj(table) + self.attr["dwarf"]["CFATable"][initLoc] = table def _printCFIs(cfi, cie=None, pc=None, regList=None): def _convRegName(arg, regList): @@ -107363,7 +107421,7 @@ def _decodeData2(table, pos): printer(printStr) # decode instructions to make CFA table # - _decodeCFI(self, entry, cfi, cie, offset) + _decodeCFI(self, entry, cfi, cie, offset, prt=printable) # print CFI # if printable: @@ -109465,6 +109523,20 @@ def _addEntryOldState(cmd, args, isExtended=False): except: SysMgr.printErr("failed to parse %s" % secName, True) + # compress dwarf table # + if not "NODEBUGCOMP" in SysMgr.environList: + for x in list( + self.attr.get("dwarf", {}).get("CFATable", {}).keys() + ): + obj = self.attr["dwarf"]["CFATable"][x] + if not isinstance(obj, list): + continue + self.attr["dwarf"]["CFATable"][x] = UtilMgr.compObj(obj) + + # remove dwarf caches # + ElfAnalyzer.ruleCacheList = {} + ElfAnalyzer.regCacheList = {} + # check dynamic section # if e_shdynamic < 0: return None