Pokud chcete volat jednoduché funkce knihovny jako atoi
, ale přesto se vyhněte použití C runtime, můžete to udělat. (tj. napíšete _start
, místo pouhého psaní main
který je volán po spuštění hromady kotelního kódu.)
gcc -o swap -nostartfiles swap.o
Jak lidé říkají v komentářích, některé části glibc závisí na konstruktorech/destruktorech spouštěných ze standardních spouštěcích souborů. Pravděpodobně je to případ stdio (puts/printf/scanf/getchar) a možná malloc. Mnoho funkcí jsou však „čisté“ funkce, které pouze zpracovávají zadaný vstup. sprintf/sscanf
může být v pořádku použít.
Například:
$ cat >exit64.asm <<EOF
section .text
extern exit
global _start
_start:
xor edi, edi
jmp exit ; doesn't return, so optimize like a tail-call
;; or make the syscall directly, if the jmp is commented
mov eax, 231 ; exit(0)
syscall
; movl eax, 1 ; 32bit call
; int 0x80
EOF
$ yasm -felf64 exit64.asm && gcc -nostartfiles exit64.o -o exit64-dynamic
$ nm exit64-dynamic
0000000000601020 D __bss_start
0000000000600ec0 d _DYNAMIC
0000000000601020 D _edata
0000000000601020 D _end
U [email protected]@GLIBC_2.2.5
0000000000601000 d _GLOBAL_OFFSET_TABLE_
00000000004002d0 T _start
$ ltrace ./exit64-dynamic
enable_breakpoint pid=11334, addr=0x1, symbol=(null): Input/output error
exit(0 <no return ...>
+++ exited (status 0) +++
$ strace ... # shows the usual system calls by the runtime dynamic linker
Zde je příklad, který používá libc
bez použití GCC.
extern printf
extern _exit
section .data
hello: db 'Hello world!',10
section .text
global _start
_start:
xor eax, eax
mov edi, hello
call printf
mov rax, 0
jmp _exit
Zkompilujte a propojte takto:
nasm -f elf64 hello.asm
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -m elf_x86_64
To mi zatím fungovalo dobře, ale pro statické propojení je to komplikované.
Použijte knihovnu C ve Swift na Linuxu
Spuštěný docker na Ubuntu:připojený svazek hostitele nelze zapisovat z kontejneru