我目前正在尝试调试导致堆栈损坏的 C++ 应用程序崩溃。 经过一番调查后,我非常确定我知道有效的 $rsp 和 $rip 地址,它们对应于堆栈上应该未损坏的非常有用的帧。
当 gdb 具有有效堆栈时,能够使用 gdb 的所有内置功能来处理动态寻址调用将非常有用。 不幸的是,gdb 在调试核心文件时无法直接设置这些寄存器值,并且我发现了一个十年前的功能请求,要求此功能。
有没有办法直接编辑核心文件来设置这些值? 或者 lldb 是否可能允许您在调试核心文件时覆盖这些寄存器值?
有没有办法直接编辑核心文件来设置这些值?
当然——这些值存储在
core
某处;诀窍是找出确切的位置。
寄存器值存储在
PRSTATUS
注释中(第一个这样的注释通常是与崩溃线程对应的注释)。
您可以使用
core
elfutils
检查现有 eu-readelf -Wn core
中的笔记。输出将类似于:
Note segment of 5200 bytes at offset 0x580:
Owner Data size Type
CORE 336 PRSTATUS
info.si_signo: 3, info.si_code: 0, info.si_errno: 0, cursig: 3
sigpend: <>
sighold: <>
pid: 4174783, ppid: 140563, pgrp: 4174783, sid: 140563
utime: 0.000000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
orig_rax: 230, fpvalid: 1
r15: 140725686367064 r14: 1
r13: 140725686367064 r12: 140725686366544
rbp: 0x00007ffd408bf190 rbx: 60
r11: 514 r10: 140725686366608
r9: 0 r8: 0
rax: -516 rcx: 139740173005747
rdx: 140725686366544 rsi: 0
rdi: 0 rip: 0x00007f17cb5f73b3
rflags: 0x0000000000000202 rsp: 0x00007ffd408bf138
fs.base: 0x00007f17cb525740 gs.base: 0x0000000000000000
cs: 0x0033 ss: 0x002b ds: 0x0000 es: 0x0000 fs: 0x0000 gs: 0x0000
在这里您可以看到
Note
位于偏移量 0x580
处,并且 rsp
寄存器位于其中的某个位置。
从这里,您可以使用
offsetof(struct elf_prstatus, pr_reg)
(112
上的x86_64
)和offsetof(struct user_regs_struct, rsp)
(152
)。
如果我的算术正确,
rsp
的值应该是0x580 + 20 + 112 + 152
。让我们检查一下:
xxd -e -s $((0x580+20+112+152)) -g8 core | head -1
0000069c: 00007ffd408bf138 000000000000002b 8..@....+.......
因此,将偏移量
0x69c
处的 8 字节值覆盖到此 core
中应该会产生所需的结果。
附注多余的
20
从哪里来? Elf64_Nhdr
在音符数据开始之前有一些数据项:n_namesz, n_descsz, n_type
(每个 4 字节),后跟音符名称(此处为 CORE\0
),四舍五入到 4 字节边界(因此总共 8 字节)。
您可以使用
$rsp
十六进制搜索 $rip
或 mcview
值(作为小端)并根据需要进行更新。