Я пытаюсь понять формат ELF, и прямо сейчас есть некоторые вещи, которые я не получаю о сегментах, определенных в заголовке программы. У меня есть этот небольшой код, который я конвертировать в файл ELF с г ++ (x86_x64 на Linux):Размеры и смещения сегментов заголовка ELF
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
if (argc == 1)
{
cout << "Hello world!" << endl;
}
return 0;
}
С g++ -c -m64 -D ACIS64 main.cpp -o main.o
и g++ -s -O1 -o Main main.o
. Теперь, с readelf Я получаю этот список сегментов:
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000afc 0x0000000000000afc R E 200000
LOAD 0x0000000000000df8 0x0000000000600df8 0x0000000000600df8
0x0000000000000270 0x00000000000003a0 RW 200000
DYNAMIC 0x0000000000000e18 0x0000000000600e18 0x0000000000600e18
0x00000000000001e0 0x00000000000001e0 RW 8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x00000000000009a4 0x00000000004009a4 0x00000000004009a4
0x0000000000000044 0x0000000000000044 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000df8 0x0000000000600df8 0x0000000000600df8
0x0000000000000208 0x0000000000000208 R 1
С Bless Hex Editor Я смотрю на коде и попытаться найти каждую из этих сегментов.
Я нахожу сегмент PHDR сразу после заголовка ELF и имеющий размер всего этого заголовка программы. Он имеет 8 байтов и читается/исполняется. [!] Я не понимаю, почему исполняемый файл.
Я нахожу сегмент, где объявляется переводчик сразу после PHDR. Он имеет размер пути интерпретатора и выравнивание 1 байта. Правильное
Теперь у меня есть сегмент, который является читаемым и исполняемый файл, который [!] Я полагаю, сегмент кода. Я не понимаю, почему он начинается с 0x0000000000000000. Разве это не должно начинаться там, где находится точка входа? Почему он имеет размер 0xafc байт? Разве размер не только размера кода? Какая часть файла является исполняемым? Кроме того, я не понимаю, почему выравнивание составляет 0x200000 байт. Разве это пространство зарезервировано для сегмента LOAD в памяти?. Это где заканчивается этот сегмент и amout 764
0x0
байт следует за ним:
- Следующий (чтение и запись) Я полагаю, это сегмент, где переменные хранятся [!]. Он заканчивается только там, где что-то вроде заголовка разделов может начинаться.
- Теперь следующий заголовок DYNAMIC. Он начинается с 0xe18, который находится внутри одного выше. [!] Я думал, что это сегмент, где хранятся ссылки на внешние функции и переменные, но я не уверен. Он доступен для чтения и записи. Я просто не знаю, что сегмент это и почему это «внутри» сегмент НАГРУЗКИ выше
- ПРИМЕЧАНИЕ сегмент, содержащий некоторую информацию, что я полагаю, не важно прямо сейчас
- GNU конкретные сегменты, один из них имеют любые смещения и размеры, равные
0x0000000000000000
, другие вмешиваются в другие сегменты, которых я тоже не получаю.
Я родом из PE мира, где каждая вещь имеет свои четко определен смещение и размера, и здесь я вижу эти странные адреса и размеры, и я запутался.
Гораздо яснее. Это действительно помогло. Спасибо. – ali