编写LLDB脚本以在崩溃后获取堆栈跟踪

Bwm*_*mat 6 crash automation lldb

我试图在我们的一个测试崩溃时自动添加从mac核心转储生成堆栈跟踪的功能.

我能够在linux上轻松地完成它

gdb --batch --quiet -ex "thread apply all bt" -ex "quit" <binary> <core file> 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

但是我在使用lldb在mac(OSX 10.8)上做同样的事情时遇到了一些麻烦.首先,我使用的lldb版本是lldb-310.2.37.

我最初的方法是使用该-s选项并传入一个脚本文件,如下所示:

target create -c <core file> <binary>
thread backtrace all
quit
Run Code Online (Sandbox Code Playgroud)

最初我遇到了一些麻烦,我认为这是因为在脚本文件末尾错过了一行导致lldb无法退出的新行,但在修复之后,我得到以下内容:执行'lldbSource'中的命令.

(lldb)  target create -c <core file> <binary>
Core file '<core file>' (x86_64) was loaded.
(lldb)  thread backtrace all
error: Aborting reading of commands after command #1: 'thread backtrace all' failed with error: invalid thread
Aborting after_file command execution, command file: 'lldbSource' failed.
Run Code Online (Sandbox Code Playgroud)

有趣的是,在那之后,我们仍在运行lldb,并且手动发出'thread backtrace all'就可以了.

所以,方法#2是创建一个python脚本并使用他们的python API(我试过这个,然后搞清楚我描述的初始阻塞是由于缺少换行).

我的剧本:

import lldb
debugger = lldb.SBDebugger.Create()
target = debugger.CreateTarget('<binary>')
if target:
 process = target.LoadCore('<core file>')
 if process:
  print process.exit_description
  for thread in process:
   print 'Thread %s:' % str(thread.GetThreadID())
   print '\n'.join(str(frame) for frame in thread)
Run Code Online (Sandbox Code Playgroud)

我使用这种方法的问题process.exit_description是返回None(我尝试过的所有其他事情也是如此; LLDB的python API文档几乎完全没用).

我正在寻找来自该调用的输出类似于以下内容:

Process 0 stopped
* thread #1: tid = 0x0000, 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16, stop reason = signal SIGSTOP
    frame #0: 0x00007fff8aca4670 libsystem_c.dylib`strlen + 16
libsystem_c.dylib`strlen + 16:
-> 0x7fff8aca4670:  pcmpeqb (%rdi), %xmm0
   0x7fff8aca4674:  andl   $0xf, %ecx
   0x7fff8aca4677:  shll   %cl, %eax
   0x7fff8aca4679:  pmovmskb %xmm0, %ecx
Run Code Online (Sandbox Code Playgroud)

加载核心文件时,LLDB会自动输出.我不一定需要汇编转储,但我至少想要线程,框架和原因.

我认为我使用的第一种方法,如果它可以使用,将是理想的,但无论哪种方式对我来说都可以.我无法控制将要使用的LLDB版本,所以我不能只更新到最新版本,看看它是否是修复过的错误.

其他获得所需输出的方法也是受欢迎的.对于上下文,这将从perl脚本调用.

Joh*_*ohn 6

--batch命令行参数在LLDB的版本支持附带的Xcode 7.2( lldb-340.4.119),以及可能的前面.

它没有在手册页中记录,但它记录在lldb --help:

   -b 
   --batch 
        Tells the debugger to running the commands from -s, -S, -o & -O,
        and then quit.  However if any run command stopped due to a signal
        or crash, the debugger will return to the interactive prompt at the
        place of the crash.
Run Code Online (Sandbox Code Playgroud)

这些其他命令行选项对lldb自动化很有用:

   -o 
   --one-line 
        Tells the debugger to execute this one-line lldb command after any
        file provided on the command line has been loaded.

   -k 
   --one-line-on-crash 
        When in batch mode, tells the debugger to execute this one-line
        lldb command if the target crashes.
Run Code Online (Sandbox Code Playgroud)

使用这些工具,我拼凑了以下命令:

ulimit -c unlimited && (<binary> || (lldb -c `ls -t /cores/* | head -n1` \
  --batch -o 'thread backtrace all' -o 'quit' && exit 1))
Run Code Online (Sandbox Code Playgroud)

这个命令:

  1. 启用核心转储
  2. 运行可执行文件 <binary>
  3. 如果失败,则在最近创建的核心转储中运行lldb /cores(希望是正确的)
  4. 打印所有线程的回溯
  5. 退出状态为非零,以便此命令可以嵌入其他工作流程(CI脚本,Makefile等)

我宁愿<binary>直接运行lldb ,这样命令就不依赖于猜测正确的核心文件.但lldb似乎仍然没有办法让它以非零退出状态退出 - 相当于GDB的-return-child-result选项或quit 1命令 - 所以我无法知道调试的程序是否成功.我提出了一个问题请求这样的功能.


Jim*_*ham 2

来自 lldb.llvm.org 的 TOT lldb 有一个新的“--batch”模式,其工作方式与 gdb 批处理模式非常相似,并修复了一些使命令行源命令表现更好的错误。如果您可以构建自己的 lldb,那么您现在就可以获得这些修复,否则您将不得不等到下一次 Xcode 更新。

exit_description 是 None 因为你的进程没有退出,它崩溃了。请注意,至少在 OS X 上,当进程崩溃时,多个线程可能会同时出现异常,因此说进程崩溃并没有多大用处。你必须问线程。线程停止时 lldb 打印出的停止状态可通过 GetStatus 方法获得。

stream = lldb.SBStream()
process.threads[0].GetStatus(stream)
print stream.GetData()
Run Code Online (Sandbox Code Playgroud)

这似乎没有非常有用的帮助字符串。