【问题标题】:How to tell LLDB to continue after a segmentation fault?如何在分段错误后告诉 LLDB 继续?
【发布时间】:2012-11-10 15:45:48
【问题描述】:

上下文:我正在为另一个平台编写解释器,这意味着我的程序通常会从任意整数数据中加载指针。当涉及到分支时,我尝试取消引用以立即读取下一条指令的地址,这样如果地址无效,我就会在分支指令的方法中得到分段错误,而不是稍后。这应该会使调试更容易。

但是,这并没有我希望的那么有用。当那里发生段错误时,它应该是完全可恢复的,因为它是由虚拟读取触发的,所以我希望能够将程序的指令指针移回方法的开头并重置段错误。

我可以告诉 LLDB 忽略已经进入我的程序的SIGSEGV 吗?我知道我可以使用process handle ... 来决定哪些信号进入我的程序,但这不适用于进程当前正在处理(或者说不处理)的信号。

(如果不可能,我想我仍然可以要求 lldb 停止段错误而不将它们传递给程序,但我至少想知道是否可能.)

【问题讨论】:

  • 等等,你不能使用sigaction函数(man 2)吗?使用它,可以为这个信号设置信号处理程序并制作longjmp函数(man3),返回你想要的地方
  • @gekannt,是的,我可以使用sigactionSIGSEGV 定义一个自定义处理程序,但只要不附加调试器,它就会有害。这就是我想从调试器中执行此操作的原因。

标签: debugging signals lldb


【解决方案1】:

我认为您正在尝试解决EXC_BAD_ACCESS 以正确放置它。例如,听起来您在这个示例程序中描述了 dataptr

#include <stdio.h>
int main ()
{
  void (*funcptr)(void) = 0;
  int *dataptr = 0;
  puts ("about to deref dataptr");
  printf ("%d\n", *dataptr);
  puts ("about to call through f ptr");
  funcptr();
  puts ("done");
  return 0;
}

您将在printf 调用中点击dataptr 取消引用的第一个EXC_BAD_ACCESS。您可以将变量更改为有效值以继续执行。这里的一个技巧是变量dataptr 在我的-O0 编译示例中位于堆栈中,因此您需要设置此时正在读取的寄存器 以通过它。这里我只是以main()的起始地址作为本程序中的有效地址作为一个简单的例子。

* thread #1: tid = 0x1f03, 0x0000000100000eb6 a.out`main + 54 at a.c:7, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
-> 7      printf ("%d\n", *dataptr);

(lldb) disass -c 1 --pc
a.out`main + 54 at a.c:7:
-> 0x100000eb6:  movl   (%rcx), %esi
(lldb) reg read rcx
     rcx = 0x0000000000000000
(lldb) p dataptr
(int *) $0 = 0x0000000000000000

(lldb) p dataptr = (int*) main
(int *) $1 = 0x0000000100000e80
(lldb) reg write rcx `$1`

(lldb) c
Process 77491 resuming
-443987883
about to call through f ptr
* thread #1: tid = 0x1f03, 0x0000000000000000, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    #0: 0x0000000000000000

现在我停止了,因为我通过 NULL 函数指针调用。展开这需要一点额外的 x86_64 ABI 知识,但这并不难——将 pc 设置为调用者的返回地址,将堆栈弹出一个单词,然后你就回来了。

(lldb) reg write pc `*(unsigned long long *)$sp`
(lldb) reg write sp `$sp + 8`
(lldb) c
Process 77522 resuming
done
Process 77522 exited with status = 0 (0x00000000) 

当然,这是非常手动的调整 - 自动化并不容易。您可以使用 python 函数表达空函数指针 deref 并添加一个 lldb 命令来轻松完成,但是空数据指针 deref 要求您知道正在访问哪个寄存器 - 也许反汇编指令的一些巧妙的模式匹配可以做到与一些常见情况下的python扩展相同。

希望对您有所帮助。

【讨论】:

  • 我以为我做了类似的事情。好吧,这行得通,非常感谢您的精彩和描述性回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多