将类转储信息导入LLDB

时间:2014-06-15 14:17:52

标签: objective-c lldb debug-symbols

这个问题基本上是Import class-dump info into GDB的克隆,但是使用LLDB而不是GDB。


使用上述问题答案中描述的方法,我可以创建包含名为test.stabs的符号的符号文件。

要在LLDB中导入和使用此信息,我尝试执行以下操作:

$ lldb test
(lldb) target module add test.stabs
(lldb) b +[TestClass randomNum]
Breakpoint 1: where = test.stabs`+[TestClass randomNum]:F(0,1), address = 0x0000000100000ed0

正如您所见,LLDB可以加载地址,但在实际运行目标时,LLDB不会中断:

(lldb) r
Process 40430 launched: '/Users/Tyilo/test' (x86_64)
num: 4
Process 40430 exited with status = 0 (0x00000000)

您当然可以直接指定断点的地址:

(lldb) b -a 0x0000000100000ed0

它会起作用。

有没有办法让LLDB中的b +[TestClass randomNum]工作得到断点?

2 个答案:

答案 0 :(得分:4)

我已经创建了一个可以用来实现我想要的python函数,但它只在程序运行时才有效。将下面的代码保存为break_message.py,然后运行command script import break_message.py将其导入lldb。现在你可以像这样使用它:

$ lldb -p $(pgrep Finder)
(lldb) command script import break_message.py
(lldb) break_message -[TApplicationController cmdEmptyTrash:]
(lldb) continue

现在在Finder中打开废纸篓并清空它(如果它已经是空的,则放入一些东西)。断点将在lldb中命中。


import lldb
import re

def lldb_run(command):
    res = lldb.SBCommandReturnObject()
    lldb.debugger.GetCommandInterpreter().HandleCommand(command, res)
    return res

def lldb_call(command):
    res = lldb_run('call ' + command)
    out = res.GetOutput()
    r = re.compile(r'^[^=]*= (.*)\n$')
    m = r.search(out)
    return m.groups()[0]

def __lldb_init_module(debugger, internal_dict):
    lldb_run('command script add -f break_message.{0} {0}'.format('break_message'))

def break_message(debugger, command, result, internal_dict):
    r = re.compile(r'([+-])\s*\[\s*(\S+)\s+([^\]]+)\]')
    m = r.search(command)
    if not m:
        print 'Error in message format!'
        return

    typ, cls, sel = m.groups()
    sel = re.sub(r'\s+', '', sel)

    meta = typ == '+'

    clsptr = lldb_call('(id)objc_getClass("{}")'.format(cls))
    if clsptr == 'nil':
        print "Couldn't find class: " + cls
        return

    selptr = lldb_call('(id)sel_registerName("{}")'.format(sel))
    if selptr == 'nil':
        print "Couldn't register selector: " + sel
        return

    func = 'class_getClassMethod' if meta else 'class_getInstanceMethod'
    method = lldb_call('(id){}({}, {})'.format(func, clsptr, selptr))
    if method == 'nil':
        print "Couldn't find method for: " + sel
        return

    imp = lldb_call('(id)method_getImplementation({})'.format(method))

    lldb_run('breakpoint set -a {}'.format(imp))

答案 1 :(得分:1)

lldb认为您的方法名称是+[TestClass randomNum]:F(0,1)?你的文件名test.stabs让我觉得它是用stabs调试信息构建的 - 看起来像刺。

lldb对stabs调试格式一无所知 - 你甚至无法用clang生成它 - 我们在Mac OS X和iOS上使用DWARF。您可能会更成功地从您的二进制文件中删除stabs调试信息(请参阅strip(1))命令 - 然后lldb不会分心。