2012-01-23 8 views
5

Estoy tratando de comprender cómo se implementan las llamadas al mensaje objetivo C de IOS en el lenguaje ensamblador ARM. En cuanto a la salida de desensamblaje de IDA, puedo ver las referencias de clase y selector insertadas en los registros antes de que se llame a __obj_msgsend. Esto tiene mucho sentido, pero lo extraño es que hay una compensación extraña para estos valores.Compensación para el objetivo C selectores en el ensamblaje ARM (IOS)

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

El valor 0x29BC en el árbitro de clase parece estar apuntando a la instrucción después de la __obj_msgsend que tiene una cierta lógica, pero el selector de ref 0x29B0 está apuntando a una instrucción MOVT azar. Y para empeorar las cosas, esta compensación parece ser diferente para cada invocación de selector.

¿Alguien sabe de dónde vienen estas compensaciones? ¿Por qué no se refieren solo a la dirección de la instrucción + 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 

Actualización: Aquí es otro caso:

__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 

Gracias a la explicación de Igor, entiendo que el 0x2758 vino, pero las matemáticas no funcionan aquí: selRef_view - 0x2758 = 0x49A8 - 0x2758 = 0x2250. Pero los datos en la primera instrucción son 50 12, lo que se traduce en 0x1250, 0x1000 menos de lo que cabría esperar. ¿¿¿Algunas ideas???

+0

Dijiste offset, pero la lista de desmontaje es de la dirección absoluta. – arul

Respuesta

8

En ARM, el valor de PC señala dos ranuras de instrucción adelante, es decir. + 8 en modo ARM y. + 4 en modo Thumb. De ahí provienen los valores "aleatorios". Por ejemplo:

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

Ya que estamos en el modo de ARM, el valor PC es 029A8 + 8 = 029B0. Por lo tanto, este código es equivalente a r1 = *(int*)(r1+0x29B0). IDA nos da una pista de que R1 está cargado con el valor (selRef_arrayWithObject_ - 0x29B0), por lo que después de la simplificación obtenemos r1 = *(int*)(selRef_arrayWithObject_), que presumiblemente se resuelve en la dirección de la cadena (selector) "arrayWithObject:".

+0

Es decir leer el ensamblaje de ARM es un dolor en el trasero. :) – bbum

+0

A menos que use IDA;) –

+0

veo. Sabía de PC + 8 pero estaba usando la PC incorrecta (: ¡Gracias! – Locksleyu