Skip to content

Commit

Permalink
Debugger: Apply unwinding table compression
Browse files Browse the repository at this point in the history
Signed-off-by: iipeace <[email protected]>
  • Loading branch information
iipeace committed May 27, 2024
1 parent 7a53835 commit 5d18486
Showing 1 changed file with 129 additions and 57 deletions.
186 changes: 129 additions & 57 deletions guider/guider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
__credits__ = "Peace Lee"
__license__ = "GPLv2"
__version__ = "3.9.8"
__revision__ = "240526"
__revision__ = "240527"
__maintainer__ = "Peace Lee"
__email__ = "[email protected]"
__repository__ = "https://github.com/iipeace/guider"
Expand Down Expand Up @@ -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 #
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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"
) % (
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -100431,6 +100460,9 @@ class ElfAnalyzer(object):

DT_VERSIONTAGNUM = 16

ruleCacheList = {}
regCacheList = {}

rustChars = [
[",", "$C$"],
["@", "$SP$"],
Expand Down Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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):
Expand All @@ -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 #
Expand All @@ -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

Expand All @@ -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):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 5d18486

Please sign in to comment.