【问题标题】:Scripting LLDB to obtain a stack trace after a crash编写 LLDB 脚本以在崩溃后获取堆栈跟踪
【发布时间】:2015-01-04 21:10:48
【问题描述】:

我正在尝试添加在我们的一项测试崩溃时自动从 mac 上的核心转储生成堆栈跟踪的功能。

我可以很容易地在 linux 上做到这一点

gdb --batch --quiet -ex "thread apply all bt" -ex "quit" <binary> <core file> 2> /dev/null

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

我最初的方法是使用-s 选项并像这样传入一个脚本文件:

target create -c <core file> <binary>
thread backtrace all
quit

最初我遇到了一些麻烦,我认为这是由于在脚本文件末尾缺少换行符导致 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.

有趣的是,在那之后,我们仍在运行 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)

我在使用这种方法时遇到的问题是 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

这是在加载核心文件时由 LLDB 自动输出的。我不一定需要程序集转储,但我至少需要线程、框架和原因。

我认为我使用的第一种方法,如果它可以工作,将是理想的,但任何一种方法对我来说都可以。不幸的是,我无法控制将要使用的 LLDB 版本,所以我不能只更新到最新版本,看看它是否是已修复的错误。

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

【问题讨论】:

    标签: crash automation lldb


    【解决方案1】:

    来自 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()
    

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

    【讨论】:

    • 要在我的系统上工作 (lldb 8.0.0),我必须将第二行更改为 lldb.process.threads[0].GetStatus(stream)(在 process 之前添加 lldb.)。
    • 我在这个小片段中故意含糊其辞。如果您从 lldb 中的嵌入式脚本解释器(您使用“脚本”命令获得的模式)运行 Python,那么当您进入解释器时,lldb 会设置便利变量lldb.process 指向当前选定的进程。如果您正在编写基于 Python 的 lldb 命令并且您想要访问该进程,则不会定义 lldb.process,您需要从您的命令传递的 SBExecutionContext 中获取该进程。
    【解决方案2】:

    Xcode 7.2 (lldb-340.4.119) 附带的 lldb 版本支持 --batch 命令行参数,并且可能更早。

    the man page 中没有记录,但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.
    

    这些其他命令行选项对于 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.
    

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

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

    这个命令:

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

    我宁愿直接在&lt;binary&gt; 上运行 lldb,这样命令就不会依赖于猜测正确的核心文件。但是 lldb 似乎仍然缺少一种方法来使其以非零退出状态退出——相当于 GDB 的 -return-child-result 选项或 quit 1 命令——所以我无法知道被调试的程序是否成功与否。我filed an issue 请求这样的功能。

    【讨论】:

    • lldb-320.4.124.10 还不支持'--batch' 选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多