A power tool to understand memory layout |
Core analyzer |
Core Analyzer may also be invoked through Python script. This is currently available for gdb debugger. Support for other environment may be added in the future. All Python commands and types are added to gdb module, which is imported automatically by the debugger. Extended Python Commands gdb.ref (address, size, scope) Return a list of gdb.Object_ref objects which are references to the input object. The first input argument is the address of the searched target; the second argument specifies target size, which is optional and its default value is 1; the third argument is the search scope, which is one of the constant values of storage type listed below in the constants section, or any combination of them through “or” operation. The argument is also optional and defaults to all scopes, i.e. gdb.ENUM_UNKNOWN. If no references are found, Py_None is returned. gdb.share(args) Return a list of gdb.Object_ref objects which are data objects shared by more than one thread. Input argument is an arbitrary list of thread id (integer), which limit the search to the objects referenced by these threads only. If no objects are found, Py_None is returned. gdb.cpp_object(type) Return a list of gdb.Object_ref objects which are of the type specified. The sole argument should be a string that can be evaluated to a C++ class with vtable. If no objects are found, Py_None is returned. gdb.big_block(n) Return a list of gdb.Heap_block objects of biggest heap memory blocks. The single argument specifies number of blocks to return. gdb.heap_walk(block) Return a gdb.Heap_block object represents the next heap memory block in address after the input value. The input argument is optional (default is zero), which is either an address (integer) or a gdb.Heap_block object. If no heap memory block is after the input address, Py_None is returned. Extended Python Types gdb.Heap_block Represent a heap memory block. It has three read-only attributes: address, size and inuse. Heap_block.address is the starting address of the memory block. Heap_block.size is the block size. Heap_block.inuse is a flag indicating whether the memory block is in-use or not. gdb.Object_ref Represent a reference to a target object. It supports the following attributes: Object_ref.storage_type indicates the place of the reference, which is one of the constant values listed below. Object_ref.address is the reference address. Object_ref.target is the value referenced. Object_ref.tid is the thread id if the reference belongs to a stack, for example, a local variable. Object_ref.register_name is the name of the register that hold the target value. Object_ref.frame is the frame number if the reference is of stack type. Object_ref.module_name is the name of the module where the reference is located, for example, a global variable. Object_ref.symbol returns a gdb.Symbol object of the reference. It is Py_None if no symbol is available. Object_ref.type returns a gdb.Type object if the reference’s type is known, otherwise Py_None is returned. Object_ref.heap_addr is the address of the memory block if the reference is on heap. Object_ref.heap_size is the size of the memory block if the reference is on heap. Object_ref.heap_inuse is the inuse flag of the memory block if the reference is on heap. Constants The following constants specify the storage type of an object. gdb.ENUM_REGISTER = 0x01, gdb.ENUM_STACK = 0x02, gdb.ENUM_MODULE_TEXT = 0x04, gdb.ENUM_MODULE_DATA = 0x08, gdb.ENUM_HEAP = 0x10, gdb.ENUM_UNKNOWN = 0xffffffff
Example The following python script illustrates how the extension commands may be used. def print_ref(ref): if ref.storage_type==gdb.ENUM_REGISTER: print "[register] %s=0x%lx" % (ref.register_name, ref.target) elif ref.storage_type==gdb.ENUM_STACK: print "[stack] thread %d frame %d" % (ref.tid, ref.frame), sym = ref.symbol if sym: print sym, elif ref.storage_type==gdb.ENUM_MODULE_TEXT or ref.storage_type==gdb.ENUM_MODULE_DATA: print "[module] %s" % ref.module_name, sym = ref.symbol if sym: print sym, elif ref.storage_type==gdb.ENUM_HEAP: print "[heap block] addr=0x%lx size=%ld inuse=%d" % (ref.heap_addr, ref.heap_size, ref.heap_inuse), type = ref.type if type: print type, else: print "[unknown]", if ref.storage_type!=gdb.ENUM_REGISTER: print " 0x%lx: 0x%lx" % (ref.address, ref.target)
def heapwalk(addr,n=0xffffffff): total=0 total_inuse=0 total_free=0 total_inuse_bytes=0 total_free_bytes=0 blk=gdb.heap_walk(addr) while blk: total=total+1 if blk.inuse: total_inuse=total_inuse+1 total_inuse_bytes=total_inuse_bytes+blk.size else: total_free=total_free+1 total_free_bytes=total_free_bytes+blk.size print "[", total, "] ", blk if n!=0 and total>=n: break blk=gdb.heap_walk(blk) print "Total ", total_inuse, " inuse blocks of ", total_inuse_bytes, " bytes" print "Total ", total_free, " free blocks of ", total_free_bytes, " bytes"
def top(n): blks=gdb.big_block(n) count=0 for blk in blks: count=count+1 print "[", count, "] ", print blk
def obj(type_name): objects=gdb.cpp_object(type_name) if objects: for obj in objects: print_ref(obj)
def share(*args): count=0 objects=gdb.shared_object(*args) if objects: for obj in objects: count=count+1 print "[", count, "] ", print obj
def ref(addr,*args): refs=gdb.ref(addr,*args) if refs: count=0 for ref in refs: count=count+1 print "[", count, "] ", print_ref(ref) |
Python Extension |