如标题所述,如何计算分支指令的偏移量?
例如我有以下汇编代码,

0x60ECE    B loc_60EE6
;
;
;
0x60EE6    LDR.W R2, #0x123


位置0x60ECE的十六进制代码为0A E0。我想知道它是如何计算的。根据https://stackoverflow.com/questions/6744661/understanding-arm-assembler-branch-offset-calculation,offset应该是04而不是0A

我正在处理android二进制文件。

#1 楼

指令格式为little-endian,因此字节0A E0被解析为机器代码0xE00A或二进制形式的1110000000001010b

根据THUMB指令集的文档,前5位(11100b)解码到无条件分支操作码,最后11位(00000001010b)解码为Offset11:



根据上面的文档,目标地址计算为“相对于PC +/- Offset11 << 1“加上4用于预取操作。

如果我们做数学运算,我们会发现一切都变了:

   0x60ECE + (00000001010b << 1) + 0x4
== 0x60ECE +       10100b        + 0x4
== 0x60ECE +        0x14         + 0x4
== 0x60EE6


#2 楼

您错过了以下事实:您正在THUMB模式下工作,在该模式下,每条指令有两个字节(至少对于大多数指令而言),并且该链接描述了ARM模式,其中每条指令都有4个字节。

(我怎么知道您处于THUMB模式?除了上一个问题,您的0x60ECE B loc_60EE6不是4字节对齐的,因此它必须是THUMB)。

如果添加4个字节根据loc_60ECE上的指令,您将得到0x60ED2。从60EE6减去这个得到14或十进制20。除以2(在THUMB模式下为2字节指令)以获取10十进制或0A十六进制。

由于计算偏移量可能很困难且容易出错,因此我让gnu arm汇编程序为我处理。首先编写一个这样的汇编文件(命名为qs,选择您想要的任何名称):

.thumb
.arch armv7a
.syntax unified
.org 0x60ECE
    B codecave
original:
.org 0x60EE6
codecave:
movw R2, #0x123
B original


,然后对其进行汇编并检查结果:

arm-linux-gnueabi-as q.s
arm-linux-gnueabi-objdump -s a.out | grep -v "00000000 00000000 00000000 00000000"

Contents of section .text:
 60ec0 00000000 00000000 00000000 00000ae0  ................
 60ee0 00000000 000040f2 2312f1e7           ......@.#...    


您在0ae0看到60ece,在40f22312f1e7看到60ee6。您可以直接在IDA中对此进行修补,也可以使用idapatcher插件复制/粘贴十六进制。我发现这比手动制作修补的字节要容易得多。

评论


谢谢您的先生指出这个窍门。这对我来说使一切变得容易得多。终于我能够创建代码凹坑了。

–user2578525
2015年6月9日下午4:31