我正在创建一个需要从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 $ - $$
我想我需要为导入添加另一个程序头,但我真的不知道 - 我也不熟悉该部分内容的格式。
答案 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/。然后,使用readelf
,objdump
和/或hexdump
来拆除从编译上述内容中获得的可执行映像,并弄清楚它是如何构建的。