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-symbols
andSymTabCreator
很简单:
$ 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 与 0x1000309eb,相差 7 个字节),这是因为 gdb 会自动识别函数序言并在其后设置断点。
GDB 脚本
假设剥离的可执行文件是当前目标,您可以使用此 GDB 脚本自动执行此操作。
将下面的脚本添加到您的.gdbinit
,以剥离的可执行文件为目标并objc_symbols
在 gdb 中运行命令:
$ 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