如何将函数从libc6导入ELF可执行文件?

时间:2010-09-30 22:23:53

标签: assembly x86 file-format elf

我正在创建一个需要从libc6导入函数的i386 ELF可执行文件。 (顺便说一下,这是printf。)

我创建了一个非常小的ELF可执行文件,可以打印“Hello,world!”通过使用Linux内核中断0x80到控制台。这不是最优的,我想让应用程序使用libc代替。

以下是我到目前为止的内容:(大多数结构对齐代码都归功于this页面。)

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 个答案:

答案 0 :(得分:2)

如果你愿意让链接器完成它的工作,这就足够了(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规范,System V通用ABI和x86-32 psABI补充;这些都可以在这里找到:http://refspecs.freestandards.org/。然后,使用readelfobjdump和/或hexdump来拆除从编译上述内容中获得的可执行映像,并弄清楚它是如何构建的。