在gdbdebugging过程中执行ni命令时遇到这样的错误:
警告:
不能插入断点0。
访问内存地址错误0x3ac706a:input/输出错误。/lib/libc.so.6中的siglongjmp()中的0xf6fa4771
要调查gdb遇到什么问题,我strace gdb并得到这样的输出:
rt_sigprocmask(SIG_BLOCK,NULL,[RT_1],8)= 0
ptrace(PTRACE_PEEKTEXT,651,0xcc4fdf60,[0x1cc4fe470])= 0
ptrace(PTRACE_PEEKTEXT,651,0xcc4fe480,[0x3ac706a4506fa1d])= 0
rt_sigprocmask(SIG_BLOCK,NULL,[RT_1],8)= 0
…
…
rt_sigprocmask(SIG_BLOCK,NULL,[RT_1],8)= 0
rt_sigprocmask(SIG_BLOCK,NULL,[RT_1],8)= 0
ptrace(PTRACE_GETREGS,27781,0,0x7fff8990e8b0)= 0
ptrace(PTRACE_PEEKTEXT,27781,0x3ac7068,[0x28b])= -1 EIO(input/输出错误)
ptrace(PTRACE_PEEKTEXT,27781,0x3ac7068,[0x28b])= -1 EIO(input/输出错误)
这意味着gdb首先在内存地址为0xcc4fe480处获取值为0x3ac706a4506fa1d (实际上是一个8字节的值0x03ac706a4506fa1d )。 后来它从该值的前4个字节得到一个alignment的地址0x3ac7068 ,这是一个无效的地址,并导致gdb无法ptrace。
/ proc / [pid] / maps的内容:
cbce2000-cc353000 r-xp 00000000 08:03 295479 xxx.so
cc353000-cc3f0000 r – p 00670000 08:03 295479 xxx.so
cc3f0000-cc3f6000 rw-p 0070d000 08:03 295479 xxx.so
cc3f6000-cc3fe000 rw-p cc3f6000 00:00 0
cc3fe000-cc3ff000 — p cc3fe000 00:00 0
cc3ff000-cc4ff000 rwxp cc3ff000 00:00 0
cc4ff000-cc500000 — p cc4ff000 00:00 0cc500000-cc600000 rwxp cc500000 00:00 0
cc62d000-cc673000 r-xp 00000000 08:03 295545 yyy.so
cc673000-cc674000 — p 00046000 08:03 295545 yyy.so
cc674000-cc675000 r – p 00046000 08:03 295545 yyy.so
cc675000-cc676000 rw-p 00047000 08:03 295545 yyy.so
它显示地址0xcc4fe480来自上面加粗字体的部分。 本节与任何.so或bin文件无关。
这个问题实际上是相关的另一个问题http://stackoverflow.com/questions/9564417/gdb-cant-insert-internal-breakpoint ,尚未解决。 在上一期的调查中我发现了这些问题。
我有3个问题在这里:
1.在这里看看ptrace的strace输出:
ptrace(PTRACE_PEEKTEXT,651,0xcc4fe480,[0x3ac706a4506fa1d])= 0
为什么用方括号注释的最后一个参数? 这是否意味着它代表了回报价值? 手册页说,ptrace应该返回读PTRACE_PEEKTEXT的单词,但它看起来strace输出不遵循,所以我怀疑它显示在最后一个参数的返回值。
2.在两个.so之间有一个部分(粗体字),但不与任何inode关联。 这部分代表什么?
3. GDB从该部分读取一个单词并将该单词用作地址,但实际上这是一个无效的地址。 这种错误的可能原因是什么?
谢谢!
- 看一下ptrace的strace输出:ptrace(PTRACE_PEEKTEXT,651,0xcc4fe480,[0x3ac706a4506fa1d])= 0为什么最后一个参数用方括号注解? 这是否意味着它代表了回报价值?
正确。
- 在两个.so之间有一段(用粗体字),但不与任何inode关联。 这部分代表什么?
它是用MAP_ANONYMOUNS
标志MAP_ANONYMOUNS
的内存区域(即它不对应于磁盘上的任何文件)。
由于该区域的大小恰好为1MB,并且由于被PROT_NONE
映射的私有区域所包围,所以这个区域代表了一些线程堆栈,并且被堆栈防护区包围。
- GDB从该部分读取一个单词并将该单词用作地址,但实际上这是一个无效的地址。 这种错误的可能原因是什么?
由于某些原因,GDB认为应该在地址0x3ac7068
处有代码,并且希望在那里放置一个内部断点。 GDB使用内部断点来跟踪加载的共享库(等等)。
来自maintenance info break
输出应该显示GDB认为哪些代码位于“坏”地址。
我的猜测是,你的代码是溢出和写在一个有效的地址,gdb正在访问该地区的内存期望地址,但获取垃圾数据。 你正在尝试调试的代码段是什么? 这可能会帮助我们。