Почему файл Elf с одним небольшим сегментом выдает ошибку?Linux

Ответить
Anonymous
 Почему файл Elf с одним небольшим сегментом выдает ошибку?

Сообщение Anonymous »

Я создаю исполняемый файл Elf. Я столкнулся с проблемой, которую не понимаю. Мне удалось воспроизвести проблему с помощью небольшого файла nasm:

Код: Выделить всё

bits 64

va equ 0x1000

elf_header:
db  0x7F, "ELF", 2, 1, 1, 0 ; e_ident
times 8 db 0                ; unused padding
dw  2                       ; e_type
dw  62                      ; e_machine
dd  1                       ; e_version
dq  va + 0x40 + 0x38        ; e_entry
dq  0x40                    ; e_phoff
dq  0                       ; e_shoff
dd  0                       ; e_flags
dw  0x40                    ; e_ehsize
dw  0x38                    ; e_phentsize
dw  1                       ; e_phnum
dw  0x40                    ; e_shentsize
dw  0                       ; e_shnum
dw  0                       ; e_shstrndx

program_header:
dd  1                       ; p_type
dd  7                       ; p_flags
dq  _start                  ; p_offset
dq  va + _start             ; p_vaddr
dq  va + _start             ; p_paddr
dq  _start_end - _start     ; p_filesz
dq  _start_end - _start     ; p_memsz
dq  0x1000                  ; p_align

_start:
mov edi, 42
mov eax, 60
syscall

_start_end:
Как видите, существует один заголовок программы, указывающий на один крошечный сегмент _start. Читая этот файл, кажется, все в порядке:

Код: Выделить всё

$ nasm -f bin -o test test.asm
$ objdump --all-headers test

debug:  file format elf64-x86-64
architecture: x86_64
start address: 0x0000000000001078

Program Header:
LOAD off    0x0000000000000078 vaddr 0x0000000000001078 paddr 0x0000000000001078 align 2**12
filesz 0x000000000000000c memsz 0x000000000000000c flags rwx

Dynamic Section:

Sections:
Idx Name          Size     VMA              Type
0 PT_LOAD#0     0000000c 0000000000001078 TEXT

SYMBOL TABLE:
Насколько я понимаю, правило offset % выравнивания == vaddr % выравнивания соблюдается.
Однако, когда я пытаюсь чтобы запустить эту программу, я получаю следующую ошибку:

Код: Выделить всё

$ ./test
assertion failed [segment_file_size >= size_of_elf_and_program_headers]: first load segment does not span the elf header size
Во многих местах в Интернете я вижу, что НЕ обязательно, чтобы первый сегмент загрузки включал заголовок elf вместе с заголовком программы, но это ошибочное утверждение, похоже, говорит об обратном.
Однако я могу обмануть это, изменив _start, чтобы добавить пустые инструкции (), чтобы увеличить размер сегмента:

Код: Выделить всё

_start:
times 150 nop
mov edi, 42
mov eax, 60
syscall

_start_end:
На этот раз все работает хорошо:

Код: Выделить всё

$ nasm -f bin -o test test.asm
$ objdump --all-headers test

debug:  file format elf64-x86-64
architecture: x86_64
start address: 0x0000000000001078

Program Header:
LOAD off    0x0000000000000078 vaddr 0x0000000000001078 paddr 0x0000000000001078 align 2**12
filesz 0x00000000000000a2 memsz 0x00000000000000a2 flags rwx

Dynamic Section:

Sections:
Idx Name          Size     VMA              Type
0 PT_LOAD#0     000000a2 0000000000001078 TEXT

SYMBOL TABLE:

$ ./test
$ echo $?
42
Другая альтернатива могла бы эффективно использовать set offset = 0 и переместить смещение на vaddr, вот так (разница на основе первой версии с начальным _start ):

Код: Выделить всё

--- test.asm    2024-11-12 10:03:40
+++ offset_eq_0.asm 2024-11-12 10:03:48
@@ -22,11 +22,11 @@
program_header:
dd  1                       ; p_type
dd  7                       ; p_flags
-    dq  _start                  ; p_offset
-    dq  va + _start             ; p_vaddr
-    dq  va + _start             ; p_paddr
-    dq  _start_end - _start     ; p_filesz
-    dq  _start_end - _start     ; p_memsz
+    dq  0                       ; p_offset
+    dq  va                      ; p_vaddr
+    dq  va                      ; p_paddr
+    dq  _start_end - _start + 0x40 + 0x38 ; p_filesz
+    dq  _start_end - _start + 0x40 + 0x38 ; p_memsz
dq  0x1000                  ; p_align

_start:
Точка входа по-прежнему установлена ​​на va + 0x40 + 0x38, что является допустимым. И на этот раз это работает:

Код: Выделить всё

$ ./offset_eq_0
$ echo $?
42
В этой версии p_filesz и p_memsz также больше размера заголовка Elf.
Я Я создаю этот файл из aarch64 macOS, но работаю на машине Debian x86_64 (

Код: Выделить всё

Linux debian 6.11.5-orbstack-00280-g96d99c92a42b #51 SMP Sun Nov  3 08:07:37 UTC 2024 x86_64 GNU/Linux
) через OrbStack.
Нигде в Интернете я не могу найти эту ошибку, любые репозитории исходного кода, архивы, ничего, нигде.

Подробнее здесь: https://stackoverflow.com/questions/791 ... s-an-error
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Linux»