Смещение для объективных селекторов C в сборке ARM (IOS)

Я пытаюсь понять, как вызовы сообщений IOS Objective-C реализованы на языке ассемблера ARM. Глядя на результат дизассемблирования IDA, я вижу, что ссылки на классы и селекторы помещаются в регистры до вызова __obj_msgsend. Это имеет смысл, но странно то, что эти значения имеют странное смещение.

selector ref = (selRef_arrayWithObject_ - 0x29B0) 
class ref = (classRef_NSArray - 0x29BC)

Значение 0x29BC в ссылке класса указывает на инструкцию после __obj_msgsend, которая имеет определенную логику, но ссылка селектора 0x29B0 указывает на случайную инструкцию MOVT. И что еще хуже, это смещение кажется разным для каждого вызова селектора.

Кто-нибудь знает, откуда берутся эти смещения? Почему они просто не ссылаются на адрес инструкции + 8?

__text:00002998 E8 1F 01 E3                 MOV             R1, #(selRef_arrayWithObject_ - 0x29B0) ; selRef_arrayWithObject_
__text:0000299C 05 20 A0 E1                 MOV             R2, R5
__text:000029A0 00 10 40 E3                 MOVT            R1, #0
__text:000029A4 01 50 A0 E3                 MOV             R5, #1
__text:000029A8 01 10 9F E7                 LDR             R1, [PC,R1] ; selRef_arrayWithObject_ ; "arrayWithObject:"
__text:000029AC 74 00 02 E3                 MOV             R0, #(classRef_NSArray - 0x29BC) ; classRef_NSArray
__text:000029B0 00 00 40 E3                 MOVT            R0, #0
__text:000029B4 00 00 9F E7                 LDR             R0, [PC,R0] ;     _OBJC_CLASS_$_NSArray
__text:000029B8 8C 05 00 EB                 BL              _objc_msgSend

Обновление: вот еще один случай:

__text:00002744 50 12 02 E3                 MOV             R1, #(selRef_view - 0x2758) ;    selRef_view
__text:00002748 00 10 40 E3                 MOVT            R1, #0
__text:0000274C 00 50 A0 E1                 MOV             R5, R0
__text:00002750 01 10 9F E7                 LDR             R1, [PC,R1] ; selRef_view ; "view"


__objc_selrefs:000049A8 1A 39 00 00 selRef_view     DCD sel_view            ; DATA XREF:     __text:000025F8o

Благодаря объяснению Игоря я понял откуда взялся 0x2758, но тут не получается математика: selRef_view - 0x2758 = 0x49A8 - 0x2758 = 0x2250. Но данные в первой инструкции — 50 12, что соответствует 0x1250, на 0x1000 меньше, чем я ожидал. Любые идеи???


person Locksleyu    schedule 23.01.2012    source источник
comment
Вы сказали смещение, но листинг разборки дан по абсолютному адресу.   -  person arul    schedule 23.01.2012


Ответы (1)


В ARM значение PC указывает на два слота инструкций вперед, т.е. + 8 в режиме ARM и . + 4 в режиме большого пальца. Вот откуда берутся «случайные» значения. Например:

__text:000029A8 LDR R1, [PC,R1]

Поскольку мы находимся в режиме ARM, значение ПК равно 029A8 + 8 = 029B0. Итак, этот код эквивалентен r1 = *(int*)(r1+0x29B0). IDA подсказывает нам, что R1 загружается со значением (selRef_arrayWithObject_ — 0x29B0), поэтому после упрощения мы получаем r1 = *(int*)(selRef_arrayWithObject_), который предположительно разрешается в адрес строки (селектора) "arrayWithObject:".

person Igor Skochinsky    schedule 23.01.2012
comment
Я понимаю. Я знал о ПК + 8, но использовал не тот ПК (: Спасибо! - person Locksleyu; 23.01.2012
comment
Игорь, не мог бы ты посмотреть на обновление моего исходного поста? У меня есть случай, когда математика не работает. - person Locksleyu; 23.01.2012
comment
Непосредственное значение инструкции MOV (на самом деле здесь MOVW) разделено на несколько полей, вы не должны смотреть только на байты. - person Igor Skochinsky; 24.01.2012
comment
Что это за ИДА, о которой вы говорите, и где я могу ее получить? - person bbum; 24.01.2012
comment
Игорь, спасибо за предложение. Я прочитал большую часть справочного руководства по ARMv7, но не могу найти формат инструкции, точно соответствующий части «E3 02». В документации есть 11110 для начала MOVW, но «E3 02» начинается с 11100. Не могли бы вы предоставить ссылку на ссылку, в которой указана эта инструкция? - person Locksleyu; 26.01.2012
comment
@Locksleyu см. Кодирование A2 для MOV (немедленно). - person Igor Skochinsky; 26.01.2012