Python源码示例:gdb.Value()
示例1
def __init__(self, base_addr, size):
Thread.__init__(self)
self.base_addr = base_addr # the vector we are monitoring
self.size = size # its size
self.messages = Queue() # cross-thread communication
# store contents of vec
self.values = []
int_t = gdb.lookup_type('int')
for idx in range(0, size):
self.values.append(int((base_addr + idx).dereference().cast(int_t)))
self.animations = []
# Front end code
# These methods run in the gdb thread in response to breakpoints,
# and accept gdb.Value objects
# Updates for instrumented actions
示例2
def __stackmap(self, frame_items):
symbolmap = defaultdict(list)
if not frame_items:
return symbolmap
for i in frame_items:
name = i.symbol().name
addr = self._frame.read_var(name).address
if not addr == None:
# gdb.Value is not "hashable"; keys must be something else
# so here we use addr converted to int
sz = i.symbol().type.sizeof
# mark all dwords in the stack with this symbol
addr = addr.cast(gdb.lookup_type("void").pointer()) # cast to void*
# handle sub-dword quantities by just listing everything that overlaps
for saddr in range(addr, addr+sz, 0x8):
symbolmap[int(saddr)].append(i.symbol())
return symbolmap
# Now create a gdb command that prints the current stack:
示例3
def _BacktraceFromFramePtr(self, frame_ptr):
"""Assembles and returns what looks exactly like python's backtraces."""
# expects frame_ptr to be a gdb.Value
frame_objs = [PyFrameObjectPtr(frame) for frame
in self._IterateChainedList(frame_ptr, 'f_back')]
# We want to output tracebacks in the same format python uses, so we have to
# reverse the stack
frame_objs.reverse()
tb_strings = ['Traceback (most recent call last):']
for frame in frame_objs:
line_string = (' File "%s", line %s, in %s' %
(frame.filename(),
str(frame.current_line_num()),
frame.co_name.proxyval(set())))
tb_strings.append(line_string)
line_string = ' %s' % frame.current_line().strip()
tb_strings.append(line_string)
return '\n'.join(tb_strings)
示例4
def Assign(self, listObj):
try:
if ( listObj.type == ListInspector.ListType ):
self._list = listObj
return
else:
raise TypeError("Invalid List Object Type!")
except Exception as exc:
#print(" Failed to assign from List object: %s" % str(exc))
pass
symbol, methodObj = gdb.lookup_symbol(listObj)
if ( symbol != None ):
self._list = symbol.value()
else:
addrInt = int(listObj, 0)
listObjPtr = gdb.Value(addrInt).cast(ListInspector.ListType.pointer())
self._list = listObjPtr.dereference()
示例5
def show_swap(self, a, b):
# sending gdb.Value objects over the queue doesn't seem to work
# at least, their addresses are no longer accessible in the other thread
# So we'll do the calculations here
a_idx = a.address - self.base_addr
b_idx = b.address - self.base_addr
self._send_message('swap', int(a_idx), int(b_idx))
示例6
def show_move(self, a, b): # a moved into from b
# a is always an address and b is an rvalue reference
# so we use "a" and "b.address"
# detect whether a or b is a temporary
a_in_vec = (a >= self.base_addr) and (a < (self.base_addr + self.size))
b_in_vec = (b.address >= self.base_addr) and (b.address < (self.base_addr + self.size))
# we will supply temporaries as their address in string form,
# and in-vector quantities as their offset (a Python int)
# this way gdb.Value objects don't outlive their frame
if a_in_vec and b_in_vec:
a_idx = a - self.base_addr
b_idx = b.address - self.base_addr
self._send_message('move', int(b_idx), int(a_idx))
elif a_in_vec:
# source is a temporary; stringify its address to use as a token representing it
a_idx = a - self.base_addr
self._send_message('move_from_temp', str(b.address), int(a_idx))
elif b_in_vec:
# dest is a temporary
b_idx = b.address - self.base_addr
self._send_message('move_to_temp', int(b_idx), str(a))
else:
# I've never seen a move from temporary to temporary
raise RuntimeError('saw an unexpected move from temporary to temporary')
示例7
def _UnpackGdbVal(self, gdb_value):
"""Unpacks gdb.Value objects and returns the best-matched python object."""
val_type = gdb_value.type.code
if val_type == gdb.TYPE_CODE_INT or val_type == gdb.TYPE_CODE_ENUM:
return int(gdb_value)
if val_type == gdb.TYPE_CODE_VOID:
return None
if val_type == gdb.TYPE_CODE_PTR:
return long(gdb_value)
if val_type == gdb.TYPE_CODE_ARRAY:
# This is probably a string
return str(gdb_value)
# I'm out of ideas, let's return it as a string
return str(gdb_value)
示例8
def field(self, name):
'''
Get the gdb.Value for the given field within the PyObject, coping with
some python 2 versus python 3 differences.
Various libpython types are defined using the "PyObject_HEAD" and
"PyObject_VAR_HEAD" macros.
In Python 2, this these are defined so that "ob_type" and (for a var
object) "ob_size" are fields of the type in question.
In Python 3, this is defined as an embedded PyVarObject type thus:
PyVarObject ob_base;
so that the "ob_size" field is located insize the "ob_base" field, and
the "ob_type" is most easily accessed by casting back to a (PyObject*).
'''
if self.is_null():
raise NullPyObjectPtr(self)
if name == 'ob_type':
pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
return pyo_ptr.dereference()[name]
if name == 'ob_size':
try:
# Python 2:
return self._gdbval.dereference()[name]
except RuntimeError:
# Python 3:
return self._gdbval.dereference()['ob_base'][name]
# General case: look it up inside the object:
return self._gdbval.dereference()[name]
示例9
def proxyval(self, visited):
'''
Scrape a value from the inferior process, and try to represent it
within the gdb process, whilst (hopefully) avoiding crashes when
the remote data is corrupt.
Derived classes will override this.
For example, a PyIntObject* with ob_ival 42 in the inferior process
should result in an int(42) in this process.
visited: a set of all gdb.Value pyobject pointers already visited
whilst generating this value (to guard against infinite recursion when
visiting object graphs with loops). Analogous to Py_ReprEnter and
Py_ReprLeave
'''
class FakeRepr(object):
"""
Class representing a non-descript PyObject* value in the inferior
process for when we don't have a custom scraper, intended to have
a sane repr().
"""
def __init__(self, tp_name, address):
self.tp_name = tp_name
self.address = address
def __repr__(self):
# For the NULL pointer, we have no way of knowing a type, so
# special-case it as per
# http://bugs.python.org/issue8032#msg100882
if self.address == 0:
return '0x0'
return '<%s at remote 0x%x>' % (self.tp_name, self.address)
return FakeRepr(self.safe_tp_name(),
long(self._gdbval))
示例10
def __getitem__(self, i):
# Get the gdb.Value for the (PyObject*) with the given index:
field_ob_item = self.field('ob_item')
return field_ob_item[i]
示例11
def field(self, name):
'''
Get the gdb.Value for the given field within the PyObject, coping with
some python 2 versus python 3 differences.
Various libpython types are defined using the "PyObject_HEAD" and
"PyObject_VAR_HEAD" macros.
In Python 2, this these are defined so that "ob_type" and (for a var
object) "ob_size" are fields of the type in question.
In Python 3, this is defined as an embedded PyVarObject type thus:
PyVarObject ob_base;
so that the "ob_size" field is located insize the "ob_base" field, and
the "ob_type" is most easily accessed by casting back to a (PyObject*).
'''
if self.is_null():
raise NullPyObjectPtr(self)
if name == 'ob_type':
pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
return pyo_ptr.dereference()[name]
if name == 'ob_size':
try:
# Python 2:
return self._gdbval.dereference()[name]
except RuntimeError:
# Python 3:
return self._gdbval.dereference()['ob_base'][name]
# General case: look it up inside the object:
return self._gdbval.dereference()[name]
示例12
def proxyval(self, visited):
'''
Scrape a value from the inferior process, and try to represent it
within the gdb process, whilst (hopefully) avoiding crashes when
the remote data is corrupt.
Derived classes will override this.
For example, a PyIntObject* with ob_ival 42 in the inferior process
should result in an int(42) in this process.
visited: a set of all gdb.Value pyobject pointers already visited
whilst generating this value (to guard against infinite recursion when
visiting object graphs with loops). Analogous to Py_ReprEnter and
Py_ReprLeave
'''
class FakeRepr(object):
"""
Class representing a non-descript PyObject* value in the inferior
process for when we don't have a custom scraper, intended to have
a sane repr().
"""
def __init__(self, tp_name, address):
self.tp_name = tp_name
self.address = address
def __repr__(self):
# For the NULL pointer, we have no way of knowing a type, so
# special-case it as per
# http://bugs.python.org/issue8032#msg100882
if self.address == 0:
return '0x0'
return '<%s at remote 0x%x>' % (self.tp_name, self.address)
return FakeRepr(self.safe_tp_name(),
long(self._gdbval))
示例13
def __getitem__(self, i):
# Get the gdb.Value for the (PyObject*) with the given index:
field_ob_item = self.field('ob_item')
return field_ob_item[i]
示例14
def __getitem__(self, i):
# Get the gdb.Value for the (PyObject*) with the given index:
field_ob_item = self.field('ob_item')
return field_ob_item[i]
示例15
def field(self, name):
'''
Get the gdb.Value for the given field within the PyObject, coping with
some python 2 versus python 3 differences.
Various libpython types are defined using the "PyObject_HEAD" and
"PyObject_VAR_HEAD" macros.
In Python 2, this these are defined so that "ob_type" and (for a var
object) "ob_size" are fields of the type in question.
In Python 3, this is defined as an embedded PyVarObject type thus:
PyVarObject ob_base;
so that the "ob_size" field is located insize the "ob_base" field, and
the "ob_type" is most easily accessed by casting back to a (PyObject*).
'''
if self.is_null():
raise NullPyObjectPtr(self)
if name == 'ob_type':
pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
return pyo_ptr.dereference()[name]
if name == 'ob_size':
pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
return pyo_ptr.dereference()[name]
# General case: look it up inside the object:
return self._gdbval.dereference()[name]
示例16
def __getitem__(self, i):
# Get the gdb.Value for the (PyObject*) with the given index:
field_ob_item = self.field('ob_item')
return field_ob_item[i]
示例17
def __getitem__(self, i):
# Get the gdb.Value for the (PyObject*) with the given index:
field_ob_item = self.field('ob_item')
return field_ob_item[i]
示例18
def __init__(self, handle):
self._tcb = None
#print("Task: Pass Handle: %s" % str(handle))
try:
if ( handle.type == TaskInspector.TCBType ):
self._tcb = handle
return
else:
print("Handle Type: %s" % str(handle.type))
except AttributeError as aexc:
print("Attribute Error: %s" % str(aexc))
pass
except Exception as exc:
print("Error Initializing Task Inspector: %s" % str(exc))
raise
try:
tcbPtr = gdb.Value(handle).cast(TaskInspector.TCBType.pointer())
self._tcb = tcbPtr.dereference()
return
except Exception as exc:
print("Failed to convert Handle Pointer: %s" % str(handle))
self._tcb = handle
示例19
def __init__(self, handle):
"""
"""
self._evtgrp = gdb.Value(handle).cast(EventGroupInspector.EvtGrpType)
示例20
def GetEventBits(self):
""" Get the Event Flag Bits
@return L{gdb.Value} of EventBits_t
"""
return(self._evtgrp['uxEventBits'])
示例21
def __init__(self, handle):
"""
"""
# print("Queue: Handle: %s" % handle)
self.name = None
queueObjPtr = None
if ( type(handle) == gdb.Value ):
queueObjPtr = handle.cast(QueueInspector.QueueType.pointer())
self._queue = queueObjPtr.dereference()
else:
queueObjPtr = gdb.Value(handle).cast(QueueInspector.QueueType.pointer())
self._queue = queueObjPtr.dereference()
示例22
def GetTasksWaitingToSend(self):
""" Retrieve a list of gdb.Value objects of type
TCB that are the tasks that are currently waiting to
send data on this queue object.
"""
sendList = ListInspector(self._queue['xTasksWaitingToSend'])
return( sendList.GetElements( TaskInspector.TCBType ))
示例23
def GetQueueMessagesWaiting(self):
""" Return the number of messages waiting as a
L{gdb.Value} object
"""
return( self._queue['uxMessagesWaiting'] )
示例24
def get_next_cache(c1):
"""
given a certain kmem cache, retrieve the memory area relative to the next one
the code nagivates the struct, computes the address of 'next', then casts it to the correct type
"""
nxt = c1['list']['next']
c2 = gdb.Value(int(nxt)-list_offset//8).cast(gdb.lookup_type('struct kmem_cache').pointer())
return c2
示例25
def walk_caches():
"""
walk through all the active kmem caches and collect information about them
this function fills a data structure, used later by the other walk_* functions
"""
global salt_caches
salt_caches = []
slab_caches = gdb.lookup_global_symbol('slab_caches').value().address
salt_caches.append(dict())
salt_caches[-1]['name'] = 'slab_caches'
start = gdb.Value(int(slab_caches)-list_offset//8).cast(gdb.lookup_type('struct kmem_cache').pointer())
nxt = get_next_cache(start)
salt_caches[-1]['next'] = tohex(int(nxt), 64)
salt_caches.append(dict())
while True:
objsize = int(nxt['object_size'])
salt_caches[-1]['objsize'] = objsize
offset = int(nxt['offset'])
salt_caches[-1]['offset'] = offset
salt_caches[-1]['name'] = nxt['name'].string()
cpu_slab_offset = int(nxt['cpu_slab'])
cpu_slab_ptr = gdb.Value(cpu_slab_offset+cpu0_offset).cast(gdb.lookup_type('struct kmem_cache_cpu').pointer())
cpu_slab = cpu_slab_ptr.dereference()
free = int(cpu_slab['freelist'])
salt_caches[-1]['first_free'] = tohex(free, 64)
salt_caches[-1]['freelist'] = []
while free:
free = gdb.Value(free+offset).cast(gdb.lookup_type('uint64_t').pointer()).dereference()
salt_caches[-1]['freelist'].append(tohex(int(free), 64))
nxt = get_next_cache(nxt)
salt_caches[-1]['next'] = tohex(int(nxt), 64)
if start == nxt:
break
else:
salt_caches.append(dict())
示例26
def GetElements(self, CastTypeStr = None, startElem = 1 ):
""" Get the Elements of the list as an array of
gdb.Value type objects.
@param CastTypeStr string name of the type of object that
we will cast the void *pvOwner elements of the list to.
User can also pass a L{gdb.Type} object as the type
If None, we will simply cast to uint32_t and print these
as hex values.
@param startElem This is a flag to indicate whether
we will start getting elements starting at 0 or 1. Note
that this is to deal with some non-consistent behavior
of some of the TCB Task lists.
"""
if ( self._list != None ):
CastType = None
if ( CastTypeStr != None):
if( type(CastTypeStr) == str ):
try:
CastType = gdb.lookup_type(CastTypeStr).pointer()
except:
print("Failed to find type: %s" % CastTypeStr)
elif ( type(CastTypeStr) == gdb.Type):
CastType = CastTypeStr.pointer()
resp = []
numElems = self._list['uxNumberOfItems']
#print("List Elements: %d" % numElems)
index = self._list['pxIndex']
if ( numElems > 0 and numElems < 200 ):
if ( startElem == 0 ):
curr = index
else:
curr = index['pxPrevious']
for i in range(0, numElems):
owner = curr['pvOwner']
ownerObj = None
if ( CastType != None ):
castObjPtr = owner.cast(CastType)
castObj = castObjPtr.dereference()
ownerObj = castObj
else:
ownerUInt = owner.cast(StdTypes.uint32_t)
ownerObj = ownerUInt
itemVal = curr['xItemValue']
resp.append( (ownerObj, itemVal.cast(StdTypes.uint32_t)) )
curr = curr['pxPrevious']
return(resp)
else:
raise ValueError("Invalid List Object - Possibly Failed to Initialize!")