标签:
????规则:偏移=( 跳转地址-(指令地址+8) )/4
原因:
指令地址 + 8:因为ARM的流水线使得指令执行到当前指令处时,PC实际的值是A+8。
跳转指令 - 上一步得到地址:得到跳转指令与当前PC处的差值。
÷4:因为ARM的指令是4对齐的,即最低两位为00,于是将这个值右移两位。
?
执行时:
取出偏移,左移两位,加入PC,这时PC的值刚好为目标处的地址值,即目标地址指令进入取值,流水线前两级被清空。
?
实例测试:
.text:0000126C 90 00 9F E5 LDR R0, =0x4D44 .text:00001270 00 70 8F E0 ADD R7, PC, R0 ; _GLOBAL_OFFSET_TABLE_ .text:00001274 07 00 86 E0 ADD R0, R6, R7 .text:00001278 74 10 80 E2 ADD R1, R0, #0x74 .text:0000127C DC 20 80 E2 ADD R2, R0, #0xDC .text:00001280 04 00 A0 E3 MOV R0, #4 .text:00001284 92 FF FF EB BL __android_log_print .text:00001288 00 00 95 E5 LDR R0, [R5] ? ? .plt:000010D4 __android_log_print .plt:000010D4 00 C6 8F E2 ADR R12, 0x10DC |
(0010d4 - (001284 + 8))/4 = 00FFFF92。
对应机器码为 92 ff ff
????(转自 http://bbs.pediy.com/showthread.php?t=199429 ))
1.向后跳转
0012 00F001F8 bl .Lhelo
.Lhelo:
0018 05F0D1F7 pld [r1, r5]
?
计算方式:
取高位 f000, 取后11位 => 000
取低位 f801, 取后11位 => 001
计算: (000 << 12) | (001 << 1) = 2
由于这个最高位符号位为0. 代表向后跳转, 只需要保留该值2即可
?
然后计算得到的目标地址为 : 0x0012 + 4 + 2 = 0x0018
向前跳转
00001164 FF F7 BE FF BL _Z4testv
_Z4testv
000010E4 07 B5 PUSH {R0-R2,LR}
?
计算方式:
取高位 f7ff, 取后11位 => 7ff
取低位 ffbe, 取后11位 => 7be
计算: (7ff << 12) | (7be << 1) = 7fff7c
由于这个最高位符号位为1 代表向前跳转, 需要-1然后取反 得到值为 ff800084。取84即可
?
然后计算得到的目标地址为 : 0x1164 + 4 - 0x84 = 0x10e4
?
逆向过程:
BL?<label>
由BL指令得到机器码算法:
offset = dstAddr - srcAddr; ? offset = (offset -4) & 0x007fffff; ? high = offset >> 12; low = (offset & 0x00000fff) >> 1; ? machineCode = ((0xFF00 | low) << 16) | (0xF000 | high); |
BLX <label>
与BL类似。
offset = dstAddr - srcAddr; ? offset = (offset -4) & 0x007fffff; ? high = offset >> 12; low = (offset & 0x00000fff) >> 1; ? if(low%2 != 0) { low++; } ? machineCode = ((0xEF00 | low) << 16) | (0xF000 | high); |
标签:
原文地址:http://www.cnblogs.com/Reyzal/p/4857948.html