Как импортировать функцию из libc6 в исполняемый файл ELF? - PullRequest
3 голосов
/ 01 октября 2010

Я создаю исполняемый файл i386 ELF, который должен импортировать функцию из libc6.(Кстати, printf.)

Я создал очень маленький исполняемый файл ELF, который печатает "Hello, world!"на консоль с помощью прерывания ядра Linux 0x80.Это не оптимально, и я хотел бы, чтобы приложение использовало libc вместо этого.

Вот что у меня есть: (кредит этой странице для большей частикод выравнивания структуры.)

BITS 32

            org     0x08048000

ehdr:                                                 ; Elf32_Ehdr
            db      0x7F, "ELF", 1, 1, 1, 0         ;   e_ident
    times 8 db      0
            dw      2                               ;   e_type
            dw      3                               ;   e_machine
            dd      1                               ;   e_version
            dd      _start                          ;   e_entry
            dd      52
            dd      0                               ;   e_shoff
            dd      0                               ;   e_flags
            dw      52
            dw      32
            dw      1                               ;   e_phnum
            dw      0                               ;   e_shentsize
            dw      0                               ;   e_shnum
            dw      0                               ;   e_shstrndx

;   this is the header for the code section

            dd      1                               ;   p_type
            dd      0                               ;   p_offset
            dd      $$                              ;   p_vaddr
            dd      $$                              ;   p_paddr
            dd      filesize                        ;   p_filesz
            dd      filesize                        ;   p_memsz
            dd      5                               ;   p_flags
            dd      0x1000                          ;   p_align

_start:

            ; We want to print the string

    mov eax,4            ; 'write' system call
    mov ebx,1            ; file descriptor 1 = screen
    mov ecx,teststr      ; string to write
    mov edx,14           ; length of string to write
    int 80h              ; call the kernel

    ; Terminate program
    mov eax,1            ; 'exit' system call
    mov ebx,0            ; exit with error code 0
    int 80h              ; call the kernel

_stringtable:

            teststr db "Hello, world!",10,0

filesize      equ     $ - $$

Я думаю, что мне нужно добавить еще один заголовок программы для импорта, но я действительно не знаю - и я не знаком с форматом содержимого этого раздела.

1 Ответ

2 голосов
/ 01 октября 2010

Если вы хотите, чтобы компоновщик выполнял свою работу, этого достаточно (синтаксис GAS; скомпилируйте с gcc hello.s):

        .text
        .globl main
        .type main, @function
main:
        leal    .LC0, %eax
        pushl   %eax
        call    puts
        xorl    %eax, %eax
        ret
        .size main, .-main
.LC0:
        .asciz  "Hello, world!"

(Технически .LC0 следует поместить в .rodata, но я не могу точно вспомнить, как вы это делаете, и я сейчас не на своем компьютере с Linux. Кроме того, это не поддерживает выравнивание указателей стека, что не должно быть проблемой для игрушечной программы, подобной этой, но я не даю никаких обещаний.)

Если вы действительно хотите создать весь исполняемый файл вручную, сначала прочитайте эту книгу: http://www.iecc.com/linker/ Затем вам нужно будет прочитать спецификацию ELF, универсальный ABI System V и дополнение x86-32 psABI. ; все это можно найти здесь: http://refspecs.freestandards.org/. Затем используйте readelf, objdump и / или hexdump, чтобы демонтировать исполняемый образ, полученный при компиляции выше, и выяснить, как он сконструирован.

...