tiny-elf article
This commit is contained in:
parent
0398828c01
commit
f6c52abd83
127
articles/tiny-elf/page.mmd
Normal file
127
articles/tiny-elf/page.mmd
Normal file
@ -0,0 +1,127 @@
|
||||
Title: Slim Summer Elf
|
||||
Brief: Making of minimal x86 (Linux) ELF executable.
|
||||
Date: 1684666702
|
||||
Tags: Programming, Linux, C
|
||||
CSS: /style.css
|
||||
|
||||
Code below was composed for [4mb-jam](https://itch.io/jam/4mb-jam-2023) which I didn't finish.
|
||||
|
||||
It was tested on `Zorin OS 16.2 x86_64`, but should be compatible with any x86/i386
|
||||
operating system using ELF executable format (besides the system call part)
|
||||
|
||||
What's going on:
|
||||
* Amalgamation of shell script and C source, it's possible because of them both having
|
||||
`#if` style directives and similar comment syntax. Also note the usage of shebang starting with `/`.
|
||||
* ELF header is created via `GNU Assembler`.
|
||||
* Custom link script allows for drop of unnecessary data produced by `GNU Linker` by default. There's *a lot* of it it turns out.
|
||||
* One can pass a `DEBUG` argument when compiling so that debug symbols would be generated.
|
||||
|
||||
### Source ###
|
||||
|
||||
```c
|
||||
//bin/sh
|
||||
#if 0
|
||||
set -e
|
||||
cat << ELF_HEADER_SOURCE > ./elf-header.as
|
||||
elfoff = 0x08048000
|
||||
vaddr = 0x08048000
|
||||
.text
|
||||
ehdrstart:
|
||||
.byte 0x7F # e_ident
|
||||
.ascii "ELF"
|
||||
.skip 3, 1
|
||||
.skip 9, 0
|
||||
.word 2 # e_type
|
||||
.word 3 # e_machine
|
||||
.long 1 # e_version
|
||||
.long entry # e_entry
|
||||
.long phdrstart - elfoff # e_phoff
|
||||
.long 0 # e_shoff
|
||||
.long 0 # e_flags
|
||||
.word ehdrsize # e_ehsize
|
||||
.word 32 # e_phentsize
|
||||
.word 1 # e_phnum
|
||||
.skip 6, 0
|
||||
ehdrsize = . - ehdrstart
|
||||
|
||||
phdrstart:
|
||||
#PT_LOAD
|
||||
.long 1 # p_type
|
||||
.long 0 # p_offset
|
||||
.long vaddr # p_vaddr
|
||||
.long 0 # p_paddr
|
||||
.long filesz # p_filesz
|
||||
.long memsz # p_memsz
|
||||
.long 7 # p_flags
|
||||
.long 0x0000 # p_align
|
||||
ELF_HEADER_SOURCE
|
||||
|
||||
cat << LINKER_SCRIPT_SOURCE > ./ld.scr
|
||||
SECTIONS {
|
||||
. = 0x08048000;
|
||||
filestart = .;
|
||||
|
||||
.elf : { ./elf-header.o (.text) }
|
||||
.text ALIGN(0x1) : SUBALIGN(0x1) { *(.text*) *(.rodata*) }
|
||||
.data ALIGN(0x1) : SUBALIGN(0x1) { *(.data*) }
|
||||
|
||||
filesz = . - filestart;
|
||||
.bss : { *(.bss*) }
|
||||
memsz = . - filestart;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note.*)
|
||||
*(.gnu*)
|
||||
*(.gcc*)
|
||||
*(.comment)
|
||||
*(.eh_frame*)
|
||||
}
|
||||
}
|
||||
OUTPUT_FORMAT(binary)
|
||||
LINKER_SCRIPT_SOURCE
|
||||
|
||||
CFLAGS="-x c -std=gnu99 $0 -m32 -nostdlib -fno-pie -DELF -Wall -Wextra -Wpedantic -Werror"
|
||||
LDFLAGS="-m elf_i386"
|
||||
|
||||
if [ ! -z "$1" ] && [ $1 = DEBUG ];
|
||||
then
|
||||
CFLAGS="$CFLAGS -O0 -g3 -ggdb -DDEBUG"
|
||||
LDFLAGS="$LDFLAGS -eentry"
|
||||
else
|
||||
CFLAGS="$CFLAGS -Os"
|
||||
LDFLAGS="$LDFLAGS -T ld.scr -s"
|
||||
fi
|
||||
|
||||
as --32 -o elf-header.o elf-header.as
|
||||
cc -c -o ./elf.o $CFLAGS
|
||||
ld -o elf ./elf-header.o ./elf.o $LDFLAGS
|
||||
./elf
|
||||
exit;
|
||||
#endif
|
||||
|
||||
#ifdef ELF
|
||||
|
||||
/* https://github.com/Jorengarenar/CMObALL/blob/master/cmoball.h */
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/exit.2.html */
|
||||
#define SYS_EXIT(p_return_code) \
|
||||
{ \
|
||||
asm volatile("int $0x80" : : "a"(1), "b"(p_return_code)); \
|
||||
__builtin_unreachable(); \
|
||||
}
|
||||
|
||||
/* https://man7.org/linux/man-pages/man2/write.2.html */
|
||||
#define SYS_WRITE(p_fd, p_msg, p_msg_len) \
|
||||
asm volatile("int $0x80" \
|
||||
: "=a"(sys_result) \
|
||||
: "a"(4), "b"(p_fd), "c"(p_msg), "d"(p_msg_len))
|
||||
|
||||
__attribute((naked)) void entry(void) {
|
||||
static int sys_result;
|
||||
SYS_WRITE(1, "hello world!\n", 13);
|
||||
SYS_EXIT(0);
|
||||
}
|
||||
|
||||
#endif /* #ifdef ELF */
|
||||
|
||||
```
|
Loading…
Reference in New Issue
Block a user