【问题标题】:Import class-dump info into GDB将类转储信息导入 GDB
【发布时间】:2013-07-09 17:02:28
【问题描述】:

有没有办法将class-dump 的输出导入到 GDB 中?

示例代码:

$ cat > test.m
#include <stdio.h>
#import <Foundation/Foundation.h>

@interface TestClass : NSObject

+ (int)randomNum;

@end

@implementation TestClass

+ (int)randomNum {
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

@end

int main(void) {
    printf("num: %d\n", [TestClass randomNum]);
    return 0;
}
^D

$ gcc test.m -lobjc -o test
$ ./test
num: 4
$ gdb test
...
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000e5c
(gdb) ^D
$ strip test
$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) ^D

$ class-dump -A test
...
@interface TestClass : NSObject
{
}

+ (int)randomNum;   // IMP=0x0000000100000e50

@end

我知道我现在可以在gdb 中使用b *0x0000000100000e50,但是有没有办法修改GDB 的符号表以使其接受b +[TestClass randomNum]

编辑:如果它可以与 GDB v6 而不仅仅是 GDB v7 一起使用会更好,因为 GDB v6 是带有 Apple 补丁的最新版本。

【问题讨论】:

  • 可能是我在 Stack Overflow 上读过的最好的问题之一。 (+1)

标签: objective-c gdb debug-symbols


【解决方案1】:

可以使用add-symbol-file 命令在 gdb 中加载符号文件。最难的部分是生成这个符号文件。

在 libMachObjC(class-dump 的一部分)的帮助下,很容易转储所有地址及其对应的 Objective-C 方法。我写了一个小工具,objc-symbols 正是这样做的。

我们以 Calendar.app 为例。如果您尝试使用nm 工具列出符号,您会注意到日历应用已被剥离:

$ nm -U /Applications/Calendar.app/Contents/MacOS/Calendar 
0000000100000000 T __mh_execute_header
0000000005614542 - 00 0000   OPT radr://5614542

但是使用objc-symbols,您可以轻松检索所有缺少的 Objective-C 方法的地址:

$ objc-symbols /Applications/Calendar.app
00000001000c774c +[CALCanvasAttributedText textWithPosition:size:text:]
00000001000c8936 -[CALCanvasAttributedText createTextureIfNeeded]
00000001000c8886 -[CALCanvasAttributedText bounds]
00000001000c883b -[CALCanvasAttributedText updateBezierRepresentation]
...
00000001000309eb -[CALApplication applicationDidFinishLaunching:]
...

然后,使用SymTabCreator,您可以创建一个符号文件,它实际上只是一个包含所有符号的空 dylib。

同时使用objc-symbolsSymTabCreator 很简单:

$ objc-symbols /Applications/Calendar.app | SymTabCreator -o Calendar.stabs

您可以检查Calendar.stabs 是否包含所有符号:

$ nm Calendar.stabs 
000000010014a58b T +[APLCALSource printingCachedTextSize]
000000010013e7c5 T +[APLColorSource alternateGenerator]
000000010013e780 T +[APLColorSource defaultColorSource]
000000010013e7bd T +[APLColorSource defaultGenerator]
000000010011eb12 T +[APLConstraint constraintOfClass:withProperties:]
...
00000001000309eb T -[CALApplication applicationDidFinishLaunching:]
...

现在让我们看看 gdb 中发生了什么:

$ gdb --silent /Applications/Calendar.app
Reading symbols for shared libraries ................................. done

没有符号文件:

(gdb) b -[CALApplication applicationDidFinishLaunching:]
Function "-[CALApplication applicationDidFinishLaunching:]" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n

加载符号文件后:

(gdb) add-symbol-file Calendar.stabs 
add symbol table from file "Calendar.stabs"? (y or n) y
Reading symbols from /Users/0xced/Calendar.stabs...done.
(gdb) b -[CALApplication applicationDidFinishLaunching:]
Breakpoint 1 at 0x1000309f2

你会注意到断点地址与符号地址不完全匹配(0x1000309f2 vs 0x1000309eb,相差7个字节),这是因为gdb会自动识别函数序言并在其后设置断点。


GDB 脚本

假设剥离的可执行文件是当前目标,您可以使用此 GDB 脚本自动执行此操作。

将下面的脚本添加到您的.gdbinit,定位剥离的可执行文件并在gdb中运行命令objc_symbols

$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) objc_symbols
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000ee1
(gdb) ^D

define objc_symbols
    shell rm -f /tmp/gdb-objc_symbols

    set logging redirect on
    set logging file /tmp/gdb-objc_symbols
    set logging on

    info target

    set logging off

    shell target="$(head -1 /tmp/gdb-objc_symbols | head -1 | awk -F '"' '{ print $2 }')"; objc-symbols "$target" | SymTabCreator -o /tmp/gdb-symtab

    set logging on
    add-symbol-file /tmp/gdb-symtab
    set logging off
end

【讨论】:

  • 我无法编译 SymTabCreator,我收到错误 /Users/Tyilo/Downloads/SymTabCreator-master/SymTabCreator.m:80:54: Operand of type 'NSArray' where arithmetic or pointer type is required
  • @Tyilo:你需要升级你的开发者工具。 Xcode 从 4.4 开始支持对象下标。 developer.apple.com/library/mac/releasenotes/ObjectiveC/…
  • @PeterHosey 我使用的是 Xcode 4.6,所以一定有一些构建设置阻止我使用 objc 下标。
  • @PeterHosey 在构建 Debug 版本时它工作正常,但它只发生在 Release 版本中。
  • 嘿!非常好的代码:) 非常喜欢。我创建了一个脚本,将所有这些简化为一行。见gist.github.com/nickskull/6083359
【解决方案2】:

没有直接的方法可以做到这一点(据我所知),但这似乎是个好主意。

现在有一种方法可以做到...不错的答案,0xced!

DWARF 文件格式是 well documented,IIRC,并且由于 lldb source 可用,您有一个解析器的工作示例。

由于source to class-dump 也是可用的,因此修改它以产生随后可以加载到调试器中的 DWARF 输出应该不会太难。

显然,您无法完全保真地转储符号,但这可能非常有用。

【讨论】:

  • 只是为了清楚......原来的提问者是在询问 gdb,但原来的提问者是否应该对 lldb 更感兴趣,因为这是当前的,或者原来的提问者真的想要 gdb,大部分是说这里仍然存在……如果确实需要的话,可以从 gnu.org/software/gdb/current 检索 gdb 的源代码。
  • @john.k.doe 是的——好点。此外,gdb 似乎也可以加载 DWARF。
【解决方案3】:

您可以使用DSYMCreator

  1. 使用 DSYMCreator,您可以从 iOS 可执行二进制文件创建符号文件。

    它是一个工具链,所以你可以这样使用它。

    $ ./main.py --only-objc /path/to/binary/xxx

    然后会创建一个文件/path/to/binary/xxx.symbol,这是一个DWARF格式的符号。你可以自己导入到lldb

  2. 除此之外,DSYMCreator 还支持从 IDA Pro 导出符号,你可以这样使用。

    $ ./main.py /path/to/binary/xxx

    是的,只需忽略 --only-objc 标志。然后IDA Pro会自动运行,然后会创建一个文件/path/to/binary/xxx.symbol,就是符号文件。

感谢 0xced 创建 objc-symbols,它是 DSYMCreator 工具链的一部分。

顺便说一句,https://github.com/tobefuturer/restore-symbol 是另一种选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多