我在gdb调试期间执行ni命令时遇到了这样的错误:
警告:
无法插入断点 0。
访问内存地址 0x3ac706a 时出错:输入/输出错误。
/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_sigproc1(SIG ], 8) = 0
...<br> ...
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 (输入/输出错误)
ptrace(PTRACE_PEEKTEXT, 27781, 0x3ac7068, [0x28b]) = -1 EIO (输入/输出错误)
这意味着 gdb 首先 ptrace 在内存地址0xcc4fe480并获取值0x3ac706a4506fa1d(实际上是一个 8 字节值0x03ac706a4506fa1d)。稍后它从该值的前 4 个字节中获取对齐的地址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 0
cc500000-cc600000 rwxp cc500000 00:00 0
cc62d000-cc673000ř -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。
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 之间有一个节(who 用粗体字),但不与任何inode 关联。这样的部分代表什么?
3. Gdb 从该部分读取一个字并将该字用作地址,但实际上这是一个无效地址。这种错误的可能原因是什么?
谢谢!