【问题标题】:How to import a function from libc6 into an ELF executable?如何将 libc6 中的函数导入 ELF 可执行文件?
【发布时间】:2011-04-19 14:42:37
【问题描述】:

我正在创建需要从 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     $ - $$

我想我需要为导入添加另一个程序头,但我真的不知道 - 我也不熟悉该部分内容的格式。

【问题讨论】:

  • 为什么使用 write 系统调用不是最优的?由于您只是打印一个静态字符串,这似乎是最好的方法。静态包含 printf 可能会创建一个更大的可执行文件,因为 printf 往往非常大。
  • @Michael:这是一个较大项目的一部分,该项目需要 libc6 来实现许多其他功能。

标签: assembly x86 file-format elf


【解决方案1】:

如果你愿意让链接器完成它的工作,这就足够了(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 来拆解你从上面编译得到的可执行映像,并弄清楚它是如何构造的。

【讨论】:

    猜你喜欢
    • 2014-05-24
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    相关资源
    最近更新 更多