Подтвердить что ты не робот

Импортировать информацию о дампе класса в GDB

Есть ли способ импортировать вывод из 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 *0x0000000100000e50 в gdb, но есть ли способ изменить таблицу символов GDB, чтобы он принял b +[TestClass randomNum]?

Изменить: Было бы желательно, если бы он работал с GDB v6, а не только с GDB v7, так как GDB v6 - это последняя версия с патчами Apple.

4b9b3361

Ответ 1

Его можно загрузить файл символов в 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 vs 0x1000309eb, 7 байтов разницы), это связано с тем, что gdb автоматически распознает пролог функции и сразу устанавливает точку останова.


GDB script

Вы можете использовать этот GDB script, чтобы автоматизировать это, учитывая, что лишенный исполняемый файл является текущей целью.

Добавьте script снизу к вашему .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

Ответ 2

Нет прямого способа сделать это (что я знаю), но это кажется отличной идеей.

И теперь есть способ сделать это... хороший ответ, 0xced!

Формат файла DWARF хорошо документирован, IIRC, а в качестве lldb source, у вас есть рабочий пример синтаксического анализатора.

Так как источник для класса-дампа доступен, его не должно быть слишком сложно изменить, чтобы вывести вывод DWARF, который мог бы затем загружаться в отладчик.

Очевидно, что вы не сможете сбрасывать символы с полной точностью, но это, вероятно, будет весьма полезно.

Ответ 3

Вы можете использовать DSYMCreator.

  • С помощью DSYMCreator вы можете создать файл символов из исполняемого двоичного файла iOS.

    Это инструментальная цепочка, поэтому вы можете использовать ее так.

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

    Затем будет создан файл /path/to/binary/xxx.symbol, который является символом формата DWARF. вы можете импортировать его в lldb самостоятельно.

  • Кроме того, DSYMCreator также поддерживает экспорт символов из IDA Pro, вы можете использовать его следующим образом.

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

    ДА, просто игнорируйте флаг --only-objc. Затем IDA Pro будет запускаться автоматически, а затем будет создан файл /path/to/binary/xxx.symbol, который является символьным файлом.

Спасибо 0xced за создание objc-symbols, который является частью инструментальной привязки DSYMCreator.

BTW, https://github.com/tobefuturer/restore-symbol - еще один выбор.