Заглушки символов Mach-O (IOS) - PullRequest
7 голосов
/ 11 января 2012

Я пытаюсь понять, как работают файлы Mach-o, и добился значительного прогресса с доступными онлайн-ресурсами (В частности, страница Apple здесь: http://developer.apple.com/library/mac/#documentation/developertools/conceptual/MachORuntime/Reference/reference.html),, но я наткнулся на контрольно-пропускной пункт напонимание того, как работают заглушки символов.

Используя "otool -l", я вижу следующий раздел:

Section
  sectname __symbolstub1
   segname __TEXT
      addr 0x00005fc0
      size 0x00000040
    offset 20416
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x80000408

Однако, когда я смотрю на данные из двоичного файла в шестнадцатеричном редакторе, я вижуследующие 4 байта повторяются снова и снова:

00005FC0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88
00005FD0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88
00005FE0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88  
00005FF0  38 F0 9F E5 38 F0 9F E5  38 F0 9F E5 38 F0 9F E5  88

Это выглядит как LDR, который увеличивает ПК на фиксированную величину, но я не понимаю, почему сумма одинакова для каждой записи втаблица символов.

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

Спасибо!

1 Ответ

13 голосов
/ 12 января 2012

Я опишу ситуацию с текущей iOS, она несколько отличается в старых версиях.

Заглушки символов действительно загружают в ПК указатель на функцию.Для стандартного импорта «ленивый» (по требованию) указатель находится в разделе __lazy_symbol и первоначально указывает на вспомогательную процедуру в разделе __stub_helper, например:

__symbolstub1 _AudioServicesAddSystemSoundCompletion
__symbolstub1 LDR  PC, _AudioServicesAddSystemSoundCompletion$lazy_ptr
__symbolstub1 ; End of function _AudioServicesAddSystemSoundCompletion

__lazy_symbol _AudioServicesAddSystemSoundCompletion$lazy_ptr DCD _AudioServicesAddSystemSoundCompletion$stubHelper

__stub_helper _AudioServicesAddSystemSoundCompletion$stubHelper
__stub_helper LDR R12, =nnn ; symbol info offset in the lazy bind table
__stub_helper B   dyld_stub_binding_helper

Функция dyld_stub_binding_helper является первым в разделе __stub_helper и, по сути, является просто батутом к функции dyld_stub_binder в dyld, передавая ей то, что я называю значением "символа информации смещения".Это значение является смещением в потоке информации о отложенном связывании (на который указывает команда загрузки LC_DYLD_INFO или LC_DYLD_INFO_ONLY), которое является своего рода потоком байт-кода с командами для dyld.Типичная последовательность для отложенного импорта выглядит следующим образом:

72: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(M, 0xYYYYY)
19: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(NNNN)
40: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x00, '_AudioServicesAddSystemSoundCompletion')
90: BIND_OPCODE_DO_BIND()

здесь dyld будет делать следующее:

  1. искать функцию с именем '_AudioServicesAddSystemSoundCompletion' из числа Dylib NNNN в спискедилибов, перечисленных в командах загрузки.
  2. поиск номера сегмента исполняемого файла M (скорее всего, __DATA)
  3. запись указателя функции со смещением YYYYY.
  4. переход к адресу поиска, чтобы фактическая функциявыполняет свою работу

Адрес, на который написано, это слот _AudioServicesAddSystemSoundCompletion$lazy_ptr.Таким образом, в следующий раз, когда вызывается _AudioServicesAddSystemSoundCompletion, он сразу перейдет к импортированной функции, не используя dyld.

NB : вы не должны сразу смотреть на смещение 05fc0 в файле.Поле addr - это виртуальный адрес, вам нужно найти команду содержащего сегмента и посмотреть, с какой виртуальной машины она запускается и каково ее смещение файла, а затем выполнить математику.Обычно сегмент __TEXT начинается с 1000.

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

...