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

で使用できるようになったことはわかっていますb *0x0000000100000e50gdb、GDB のシンボル テーブルを変更して を受け入れるようにする方法はありb +[TestClass randomNum]ますか?

編集: GDB v6はAppleのパッチを適用した最新バージョンであるため、GDB v7だけでなくGDB v6でも動作することが望ましいでしょう。

4

3 に答える 3

38

コマンドを使用して gdb にシンボル ファイルを読み込むことができますadd-symbol-file。最も困難な部分は、このシンボル ファイルを作成することです。

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と を一緒に使用するのSymTabCreatorは簡単です。

$ 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 スクリプトを使用してこれを自動化できます。

以下のスクリプトを に追加し、ストリップされた実行可能ファイルをターゲットにして、gdb.gdbinitでコマンドを実行します。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
于 2013-07-25T12:55:50.650 に答える