我试图在我们的某个测试崩溃时自动添加从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无法退出,但在修复后,我得到以下内容: 在&lt; lldbSource&#39;中执行命令。
(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,并且发出&#39;线程回溯全部&#39;手动工作得很好。
所以,方法#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脚本调用。
答案 0 :(得分:6)
xcode 7.2(--batch
)附带的lldb版本支持lldb-340.4.119
命令行参数,可能更早。
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))
此命令:
<binary>
/cores
中最近创建的核心转储上运行lldb(希望是正确的)我宁愿直接在<binary>
上运行lldb,这样命令就不依赖猜测正确的核心文件了。但lldb似乎仍然没有办法让它以非零退出状态退出 - 相当于GDB的-return-child-result
选项或quit 1
命令 - 所以我无法知道是否调试的程序是否成功。我filed an issue要求提供此功能。
答案 1 :(得分:1)
来自lldb.llvm.org的TOT lldb有一个新的&#34; - 批次&#34;模式工作非常类似于gdb批处理模式,并修复了一些使命令行源命令行为更好的错误。如果您可以构建自己的lldb,那么现在就可以获得这些修复,否则您将不得不等到下一个Xcode更新。
exit_description为None,因为您的进程没有退出,它崩溃了。请注意,至少在OS X上,当进程崩溃时,几个线程可能同时存在异常,说这个进程崩溃并不是很有用。你必须问线程。使用GetStatus方法可以获得lldb在线程停止时打印出来的停止状态。
stream = lldb.SBStream()
process.threads[0].GetStatus(stream)
print stream.GetData()
这似乎没有一个非常有用的帮助字符串。