请参阅以下示例。我有一个C ++代码,我想在powerpc
下编译并生成二进制代码。
#include <stdio.h>
int function(int x);
int myfunction(int x);
int main()
{
int x = function(2);
int y = myfunction(2);
return x + y;
}
int function(int x)
{
return x * myfunction(x);
}
int myfunction(int x)
{
return x;
}
我有两个函数调用:call function(2)
和call myfunction(2)
。我在powerpc
下编译这个C ++代码。所以,现在我使用objdump
来获取目标文件后面的程序集,如下所示:
00000000 <main>:
0: 94 21 ff e0 stwu r1,-32(r1)
4: 7c 08 02 a6 mflr r0
8: 93 e1 00 1c stw r31,28(r1)
c: 90 01 00 24 stw r0,36(r1)
10: 7c 3f 0b 78 mr r31,r1
14: 38 60 00 02 li r3,2
18: 48 00 00 01 bl 18 <main+0x18>
1c: 7c 60 1b 78 mr r0,r3
20: 90 1f 00 08 stw r0,8(r31)
24: 38 60 00 02 li r3,2
28: 48 00 00 01 bl 28 <main+0x28>
2c: 7c 60 1b 78 mr r0,r3
30: 90 1f 00 0c stw r0,12(r31)
34: 80 1f 00 08 lwz r0,8(r31)
38: 81 3f 00 0c lwz r9,12(r31)
3c: 7c 00 4a 14 add r0,r0,r9
40: 7c 03 03 78 mr r3,r0
44: 48 00 00 0c b 50 <main+0x50>
48: 38 60 00 00 li r3,0
4c: 48 00 00 04 b 50 <main+0x50>
50: 81 61 00 00 lwz r11,0(r1)
54: 80 0b 00 04 lwz r0,4(r11)
58: 7c 08 03 a6 mtlr r0
5c: 83 eb ff fc lwz r31,-4(r11)
60: 7d 61 5b 78 mr r1,r11
64: 4e 80 00 20 blr
00000068 <function__Fi>:
68: 94 21 ff e0 stwu r1,-32(r1)
6c: 7c 08 02 a6 mflr r0
70: 93 e1 00 1c stw r31,28(r1)
74: 90 01 00 24 stw r0,36(r1)
78: 7c 3f 0b 78 mr r31,r1
7c: 90 7f 00 08 stw r3,8(r31)
80: 80 7f 00 08 lwz r3,8(r31)
84: 48 00 00 01 bl 84 <function__Fi+0x1c>
88: 7c 60 1b 78 mr r0,r3
8c: 81 3f 00 08 lwz r9,8(r31)
90: 7c 00 49 d6 mullw r0,r0,r9
94: 7c 03 03 78 mr r3,r0
98: 48 00 00 0c b a4 <function__Fi+0x3c>
9c: 48 00 00 08 b a4 <function__Fi+0x3c>
a0: 48 00 00 04 b a4 <function__Fi+0x3c>
a4: 81 61 00 00 lwz r11,0(r1)
a8: 80 0b 00 04 lwz r0,4(r11)
ac: 7c 08 03 a6 mtlr r0
b0: 83 eb ff fc lwz r31,-4(r11)
b4: 7d 61 5b 78 mr r1,r11
b8: 4e 80 00 20 blr
000000bc <myfunction__Fi>:
bc: 94 21 ff e0 stwu r1,-32(r1)
c0: 93 e1 00 1c stw r31,28(r1)
c4: 7c 3f 0b 78 mr r31,r1
c8: 90 7f 00 08 stw r3,8(r31)
cc: 80 1f 00 08 lwz r0,8(r31)
d0: 7c 03 03 78 mr r3,r0
d4: 48 00 00 04 b d8 <myfunction__Fi+0x1c>
d8: 81 61 00 00 lwz r11,0(r1)
dc: 83 eb ff fc lwz r31,-4(r11)
e0: 7d 61 5b 78 mr r1,r11
e4: 4e 80 00 20 blr
让我感到疑惑的有趣的事情是执行函数调用的行:
18: 48 00 00 01 bl 18 <main+0x18>
...
28: 48 00 00 01 bl 28 <main+0x28>
如您所见,两者都是二进制代码&#34; 48 00 00 01&#34;,但一个调用function
,另一个调用myfunction
。问题是我们如何找到call target
。正如我发现的那样,呼叫目标写在RELOCATION ENTRIES
上。哦,一切都很好,我使用下面的命令生成重定位条目,如下所示:
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000018 R_PPC_REL24 function__Fi
00000028 R_PPC_REL24 myfunction__Fi
00000084 R_PPC_REL24 myfunction__Fi
此条目对于查找呼叫目标很有用。现在,我使用objcopy -O binary
命令生成原始二进制文件(平面二进制文件)。
objcopy -O binary object-file
我的object-file
是elf32-powerpc
。输出二进制文件显示在以下块中:
2564 0000 2564 0a00 93e1 001c 9001 0024
7c3f 0b78 3860 0002 4800 0001 7c60 1b78
901f 0008 3860 0002 4800 0001 7c60 1b78
901f 000c 801f 0008 2c00 0002 4182 003c
2c00 0002 4181 0010 2c00 0001 4182 0014
4800 0058 2c00 0003 4182 0038 4800 004c
3d20 0000 3869 0000 389f 0008 4cc6 3182
4800 0001 4800 004c 3d20 0000 3869 0004
3880 0014 4cc6 3182 4800 0001 4800 0034
3d20 0000 3869 0004 3880 001e 4cc6 3182
4800 0001 4800 001c 3d20 0000 3869 0004
3880 0028 4cc6 3182 4800 0001 4800 0004
3860 0000 4800 0004 8161 0000 800b 0004
7c08 03a6 83eb fffc 7d61 5b78 4e80 0020
9421 ffe0 7c08 02a6 93e1 001c 9001 0024
7c3f 0b78 907f 0008 807f 0008 4800 0001
7c60 1b78 813f 0008 7c00 49d6 7c03 0378
4800 000c 4800 0008 4800 0004 8161 0000
800b 0004 7c08 03a6 83eb fffc 7d61 5b78
4e80 0020 9421 ffe0 93e1 001c 7c3f 0b78
907f 0008 801f 0008 7c03 0378 4800 0004
8161 0000 83eb fffc 7d61 5b78 4e80 0020
我们可以找到4800 0001
。但是没有relocation entries
。可以请任何人告诉我如何找到relocation entries
?
先谢谢。
答案 0 :(得分:1)
执行objcopy时,您的重定位条目将被丢弃。从手册:
objcopy可用于通过使用输出生成原始二进制文件 二进制的目标(例如,使用-O二进制)。当objcopy生成原始数据时 二进制文件,它基本上会产生内容的内存转储 输入对象文件。 所有符号和重定位信息都将 被丢弃。内存转储将从加载地址开始 最低部分复制到输出文件中。
为了使您的原始二进制文件有用,您可以在此处选择一些选项:
您可以在构建过程中执行重定位,以便您的原始二进制文件可以运行。但是,这意味着二进制文件需要在内存中的固定地址运行。
或者,您可以生成不需要重定位的目标文件 - 所有地址引用都需要是相对的。查找&#34;与位置无关的代码&#34;了解更多详情。
最后,您还可以使用其他方式生成原始二进制文件(而不是objcopy
阶段),其中包括输出文件中的重定位表,然后使用您的代码在运行时手动处理这些重定位。
此处的选择将取决于您尝试做什么,以及您的运行时环境有哪些限制。