记录gdb开源python扩展libheap的实际使用
copy需告知说明,转载需注明出处。
libheap使用的是python3开发的,但是我的gdb自带的使用的是python2,这种情况需要重新源码编译gdb 携带--with-python选项,./configure --with-python="/usr/bin/python3",但是因为某些原因,我这样操作很麻烦,所以我尝试用python2来进行调试。
可以看到,我已经可以使用libheap的部分功能
(gdb) heapls getting heap base from proc ADDR SIZE STATUS sbrk_base 0x104f000 chunk 0x104f000 0x20 (inuse) chunk 0x104f020 0x240 (inuse) chunk 0x104f260 0x240 (inuse) chunk 0x104f4a0 0x20b60 [!] Could not read address 0x1070000 (F) FD 0x0 BK 0x0 [!] Could not read address 0x1070000 (LC) [!] Could not read address 0x1070000 chunk 0x1070000 0x0 [!] Could not read address 0x1070000 [!] Could not read address 0x1070000 Python Exception <type 'exceptions.TypeError'> int() argument must be a string or a number, not 'NoneType': (F) FD Error occurred in Python command: int() argument must be a string or a number, not 'NoneType'
现在调用基础的heap命令
(gdb) heap [!] No arenas could be found at 0x7fae7992f780
这段打印由heap.py控制
# XXX: add arena address passing via arg (-a) if (len(arg) == 0) and (ar_ptr.next == 0): # struct malloc_state may be invalid size (wrong glibc version) print_error("No arenas could be found at {:#x}".format( ar_ptr.address)) return
我加了一些print进行调试
(gdb) heap ar_ptr.address=140387340711808 # 我加的调试信息 main_arena.address=0x7fae7992f780 <main_arena> # 我加的调试信息 arena_address=140387340711808 # 我加的调试信息 type(self.dbg)=<type 'instance'> # 我加的调试信息 self.dbg=<libheap.pydbg.debugger.pydbg instance at 0x7f6e09a6bdd0># 我加的调试信息 [!] No arenas could be found at 0x7fae7992f780 (gdb) p &main_arena $1 = (struct malloc_state *) 0x7fae7992f780 <main_arena>
明明是有arena的,但是却打印不出来,只能说明malloc_state这个类有问题
代码里经常有self.debugger这个属性,经调试,原型是gdb.frame
(gdb) python print(gdb.selected_frame().read_var("main_arena")) struct malloc_state { mutex = 0x0 flags = 0x0 fastbinsY = {...} top = 0x104f4a0 last_remainder = 0x0 bins = {...} binmap = {...} next = 0x7fae6c000020 next_free = 0x0 attached_threads = 0x1 system_mem = 0x21000 max_system_mem = 0x21000 (gdb) p main_arena $1 = struct malloc_state { mutex = 0x0 flags = 0x0 fastbinsY = {...} top = 0x104f4a0 last_remainder = 0x0 bins = {...} binmap = {...} next = 0x7fae6c000020 next_free = 0x0 attached_threads = 0x1 system_mem = 0x21000 max_system_mem = 0x21000
(gdb) python print(gdb.selected_frame().read_var("main_arena").next) Traceback (most recent call last): File "<string>", line 1, in <module> AttributeError: 'gdb.Value' object has no attribute 'next' Error while executing Python code. (gdb) p 0x7fae6c000020 $2 = 140387112976416
随便试试
(gdb) set $a= (struct malloc_state*) 0x7fae6c000020 (gdb) p $a $9 = (struct malloc_state *) 0x7fae6c000020 (gdb) p *$a $10 = struct malloc_state { mutex = 0x0 flags = 0x2 fastbinsY = {...} top = 0x7fae6c0008d0 last_remainder = 0x0 bins = {...} binmap = {...} next = 0x7fae74000020 next_free = 0x0 attached_threads = 0x1 system_mem = 0x21000 max_system_mem = 0x21000 (gdb) set $b = (struct malloc_state*)0x7fae74000020 (gdb) p *$b $11 = struct malloc_state { mutex = 0x0 flags = 0x2 fastbinsY = {...} top = 0x7fae740008d0 last_remainder = 0x0 bins = {...} binmap = {...} next = 0x7fae7992f780 # 这个值已经是一开始的main_arena的地址了 next_free = 0x0 attached_threads = 0x1 system_mem = 0x21000 max_system_mem = 0x21000
小结:
1、next所指向的地址,一共有0x7fae7992f780,0x7fae6c000020,0x7fae74000020三个,正好是我代码中malloc的个数。
2、0x21000转换成10进制为135168
(gdb) heap self.size=2200 # 我在malloc_state.py添加的打印 self.version=2.27 # 我在malloc_state.py添加的打印 [!] No arenas could be found at 0x7fae7992f780
上面就看出问题了,版本是2.27,但是我的实际glibc版本是2.17,所以没有进行配置,修改libheap.cfg改为2.17,重新执行
(gdb) heap Arena(s) found: arena @ 0x7fae7992f780 self.size=2184 self.version=2.17 arena @ 0x7fae6c000020 self.size=2184 self.version=2.17 arena @ 0x7fae74000020 self.size=2184 self.version=2.17
哇咔咔,终于有阶段性进展了
(gdb) mstats Malloc Stats self.size=2184 self.version=2.17 Arena 0: system bytes = 135168 in use bytes = 1152 self.size=2184 self.version=2.17 Arena 1: system bytes = 135168 in use bytes = 2256 self.size=2184 self.version=2.17 Arena 2: system bytes = 135168 in use bytes = 2256 Total (including mmap): system bytes = 405504 in use bytes = 5664 max system bytes = 0 max mmap regions = 0 max mmap bytes = 0
在heapls.py里发现也读取了thread_arena的内容,尝试在gdb中打印thread_arena
(gdb) p &thread_arena No symbol "thread_arena" in current context. (gdb) info threads Id Target Id Frame 3 Thread 0x7fae79567700 (LWP 46) "lynalee" __lll_lock_wait_private () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95 2 Thread 0x7fae78d66700 (LWP 47) "lynalee" 0x00007fae796578dd in write () at ../sysdeps/unix/syscall-template.S:81 * 1 Thread 0x7fae79d6f740 (LWP 45) "lynalee" 0x00007fae7965787d in read () at ../sysdeps/unix/syscall-template.S:81
发现没有这个symbol;所以考虑是不是没有调试线程的原因
(gdb) thread 2 [Switching to thread 2 (Thread 0x7fae78d66700 (LWP 47))] #0 0x00007fae796578dd in write () at ../sysdeps/unix/syscall-template.S:81 81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) (gdb) p &thread_arena No symbol "thread_arena" in current context.
依然没有thread_arena符号
参考:https://sourceware.org/gdb/onlinedocs/gdb/Python-API.html # gdb的python扩展api文档
lynalee
调试信息