1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
from ptrace.ctypes_tools import formatAddress, formatWordHex
from ptrace.cpu_info import CPU_WORD_SIZE, CPU_MAX_UINT
from ptrace import PtraceError
from ptrace.six.moves import xrange
class BacktraceFrame(object):
"""
Backtrace frame.
Attributes:
- ip: instruction pointer
- name: name of the function
- arguments: value of the arguments
"""
def __init__(self, ip):
self.ip = ip
self.name = u"???"
self.arguments = []
def __str__(self):
arguments = (formatWordHex(arg) for arg in self.arguments)
return u"IP=%s: %s (%s)" % (formatAddress(self.ip), self.name, ", ".join(arguments))
class Backtrace(object):
"""
Backtrace: all process frames since the start function.
"""
def __init__(self):
self.frames = []
self.truncated = False
def append(self, frame):
self.frames.append(frame)
def __iter__(self):
return iter(self.frames)
def __len__(self):
return len(self.frames)
def getBacktrace(process, max_args=6, max_depth=20):
"""
Get the current backtrace of the specified process:
- max_args: maximum number of arguments in a frame
- max_depth: maximum number of frames
Return a Backtrace object.
"""
backtrace = Backtrace()
# Get current instruction and frame pointer
ip = process.getInstrPointer()
fp = process.getFramePointer()
depth = 0
while True:
# Hit maximum trace depth?
if max_depth <= depth:
backtrace.truncated = True
break
# Read next frame pointer
try:
nextfp = process.readWord(fp)
except PtraceError:
nextfp = None
# Guess number of function argument
if fp and nextfp:
nargs = ((nextfp - fp) // CPU_WORD_SIZE) - 2
nargs = min(nargs, max_args)
else:
nargs = 0
# Create frame
frame = getBacktraceFrame(process, ip, fp, nargs)
backtrace.append(frame)
# End of the stack?
if not nextfp:
break
# Move to next instruction/frame pointer
ip = process.readWord(fp+CPU_WORD_SIZE)
if ip == CPU_MAX_UINT:
# Linux hack to detect end of the stack
break
fp = nextfp
depth += 1
return backtrace
def getBacktraceFrame(process, ip, fp, nargs):
"""
Get a backtrace frame:
- ip: instruction pointer
- fp: frame pointer
- nargs: number of arguments
Return a BacktraceFrame object.
"""
frame = BacktraceFrame(ip)
address = fp + CPU_WORD_SIZE
try:
for index in xrange(nargs):
address += CPU_WORD_SIZE
word = process.readWord(address)
frame.arguments.append(word)
except PtraceError:
# Ignore argument read error
pass
return frame
|