首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LLDB:在同一会话中重新启动应用程序(并保留所有内存/上下文)?

LLDB:在同一会话中重新启动应用程序(并保留所有内存/上下文)?
EN

Stack Overflow用户
提问于 2021-02-18 06:04:34
回答 1查看 261关注 0票数 0

假设我正处于一个函数的中间,LLDB在一个分段错误(内存访问错误)上停止。

是否有可能清除信号,并返回到main,并重新执行一切?(如果代码进行了任何有状态的更改,我希望保留这些更改)。我不是要求在新的会话中终止和重新启动进程。

(不确定这是否有助于澄清问题,但对于那些熟悉Java调试器的人来说,有一个“拖到帧”的概念,它基本上会弹出顶部的x帧,然后重新启动执行)

更新:使用thread return后的详细信息,如下所示。

使用thread return和调整pc确实让我回到了以前的执行点,但是信号没有被清除,所以lldb拒绝继续。

代码语言:javascript
复制
(lldb) target create "test.out"
Current executable set to '/Users/user/test.out' (x86_64).
(lldb) run
Process 89918 launched: '/Users/user/test.out' (x86_64)
before npe
i=0
i=1
i=2
i=3
i=4
Process 89918 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x5)
    frame #0: 0x0000000100003ee1 test.out`cause_npe(n=5) at test.c:17:11
   14       printf("i=%d\n", i);
   15     
   16     // cause bad mem access here
-> 17      return *(int*)(n);
   18   }
   19   
   20   int main ()
Target 0: (test.out) stopped.
(lldb) thread return
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x5)
    frame #0: 0x0000000100003f1a test.out`main at test.c:25:3
   22     //    signal (SIGSEGV, my_handler);    
   23     printf( "before npe\n");
   24     cause_npe(5);
-> 25     printf("recovered after signal\n");
   26     return 0;
   27   }
(lldb) register write pc `$pc-8`
(lldb) register write pc `$pc-8`
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x5)
  * frame #0: 0x0000000100003f0a test.out`main at test.c:23:3
    frame #1: 0x00007fff6efa3cc9 libdyld.dylib`start + 1
(lldb) n
Process 89918 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x5)
    frame #0: 0x0000000100003f0a test.out`main at test.c:23:3
   20   int main ()
   21   {
   22     //    signal (SIGSEGV, my_handler);    
-> 23     printf( "before npe\n");
   24     cause_npe(5);
   25     printf("recovered after signal\n");
   26     return 0;
Target 0: (test.out) stopped.

test.c代码:

代码语言:javascript
复制
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int cause_npe(int n) {
  // prints a few lines before the bad mem access
  for (int i = 0; i < n; ++i)
    printf("i=%d\n", i);
  
  // cause bad mem access here
  return *(int*)(n);
}

int main () {
  printf( "before npe\n");
  cause_npe(5);
  printf("recovered after signal\n");
  return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-18 18:52:07

lldb有一个thread return命令,它从堆栈中弹出帧。这将回到一个点后,调用是活跃的堆栈帧,你返回,所以你必须使用thread jump,使pc回到调用站点。

这样做将使内存状态保持不变,因此从全局变量或静态变量访问的任何内容都将保留其状态。thread return是相当残忍的力量,然而,它盲目地展开堆栈,它不试图模仿异常抛出的所有清理。因此,任何堆栈分配的对象都将被搁浅,而不是被销毁,如果您返回到版本之后,您可能会得到过多保留的对象。

此外,如果程序是多线程的,则必须注意其他线程尚未从正在展开的线程中传递堆栈分配对象。当您重新执行时,这些线程将被重新分配,因此这两个线程将有不同的副本。

无论如何,尽管可能,这不是一个通用的技术,如果你使用它,你想要怀疑你看到了什么,或者你很可能花时间去寻找展开过程中的工件,而不是学习任何有用的东西。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66254480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档