2012-01-23 19 views
5

Próbuję zrozumieć, w jaki sposób wywołania komunikatów IOS obiektu C są zaimplementowane w języku asemblerowym ARM. Patrząc na dane wyjściowe demontażu IDA, widzę odwołanie do klasy i selektora, które są przesyłane do rejestrów przed wywołaniem __obj_msgsend. To ma sens, ale dziwne jest to, że te wartości są dziwne.Przesunięcie dla obiektywnych selektorów języka C w zespole ARM (IOS)

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

Wartość 0x29BC w odnośniku klasy wydaje się być skierowany do instrukcji po __obj_msgsend która ma pewną logikę do niego, ale selektor ref 0x29B0 jest skierowany do losowej instrukcji MOVT. I na domiar złego to przesunięcie wydaje się być różne dla każdego wywołania selektora.

Czy ktoś wie, skąd pochodzą te przesunięcia? Dlaczego nie odwołują się do adresu instrukcji + 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 

Aktualizacja: Oto kolejny przypadek:

__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 

Dzięki wyjaśnienia Igora, rozumiem gdzie 0x2758 pochodzi, ale matematyka nie działa tutaj: selRef_view - 0x2758 = 0x49A8 - 0x2758 = 0x2250. Ale dane w pierwszej instrukcji to 50 12, co przekłada się na 0x1250, 0x1000 mniej, niż oczekiwałbym. Jakieś pomysły???

+0

Powiedziałeś przesunięcie, ale lista demontażu pochodzi z adresu bezwzględnego. – arul

Odpowiedz

8

W ARM wartość PC wskazuje dwa przednie kieszenie na instrukcje, tj. + 8 w trybie ARM i. + 4 w trybie Kciuk. Stąd pochodzą "losowe" wartości. Na przykład:

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

Ponieważ jesteśmy w trybie ARM, wartość PC wynosi 029A8 + 8 = 029B0. Kod ten jest więc równoważny z r1 = *(int*)(r1+0x29B0). IDA daje nam wskazówkę, że R1 jest załadowany wartością (selRef_arrayWithObject_ - 0x29B0), więc po uproszczeniu otrzymujemy r1 = *(int*)(selRef_arrayWithObject_), co prawdopodobnie rozstrzyga adres ciągu (selektora) "arrayWithObject:".

+0

tj. czytanie zespołu ARM to ból w tyłku. :) – bbum

+0

O ile nie używasz IDA;) –

+0

Rozumiem. Wiedziałem o PC + 8, ale korzystałem z niewłaściwego komputera (: Dzięki! – Locksleyu