Пожалуйста, обратите внимание на следующий пример. У меня есть код 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)
, Я компилирую этот код C ++ под powerpc
, Итак, теперь я использую 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>
Как видите, оба являются двоичным кодом «48 00 00 01», но один вызывает 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
?
Заранее спасибо.
Ваши записи о перемещении удаляются, когда вы делаете objcopy. Из руководства:
objcopy можно использовать для генерации необработанного двоичного файла с помощью вывода
целевой двоичный файл (например, используйте -O двоичный). Когда objcopy генерирует сырой
бинарный файл, он по существу произведет дамп памяти содержимого
входного объектного файла. Все символы и информация о перемещении будут
быть отброшенным Дамп памяти начнется с адреса загрузки
нижний раздел скопирован в выходной файл.
Чтобы ваш двоичный файл был полезен, у вас есть несколько вариантов:
Вы можете выполнить перемещения во время процесса сборки, чтобы ваш сырой двоичный файл был готов к запуску. Однако это означает, что двоичный файл должен быть запущен по фиксированному адресу в памяти.
Кроме того, вы можете создать объектный файл, который не требует перемещения — все адреса адресов должны быть относительными. Найдите «позиционно-независимый код» для более подробной информации.
Наконец, вы можете также использовать какой-то другой способ генерации необработанного двоичного файла (вместо или в дополнение к objcopy
stage), которая включает таблицу перемещений в выходной файл, а затем ваш код вручную обрабатывает эти перемещения во время выполнения.
Выбор здесь будет зависеть от того, что вы пытаетесь сделать, и от того, какие ограничения имеет ваша среда выполнения.