如何使用 'ld' link C 运行时库?
How to link the C Runtime Library with 'ld'?
我正在 NASM
学习汇编,以 class 我在大学里。 我想 link C 运行时库 和 ld
,但我似乎无法包装我的绕过它。我有一台安装了 Linux Mint
的 64 bit
机器。
我感到困惑的原因是——据我所知——不是 linkC 运行时,gcc
将你需要的东西复制到你的程序中。虽然我可能是错的,所以请不要犹豫纠正我。
到目前为止我所做的是 link 它使用 gcc
。这会产生一堆我无法理解的机器代码,即使是像交换 rax
和 rbx
这样的小程序,这对学习目的来说也不是很好。 (请注意该程序有效。)
我不确定它是否相关,但这些是我用来编译的命令 link:
# compilation
nasm -f elf64 swap.asm
# gcc
gcc -o swap swap.o
# ld, no c runtime
ld -s -o swap swap.o
提前致谢!
结论:
既然我对这个问题有了正确的回答,这里有几件事我想提一下。动态链接 glibc
可以像 Z boson 的回答(对于 64 位系统)那样完成。如果您想静态地进行,do follow this link(我从 Z boson 的回答中重新发布)。
这是 Jester 发表的一篇文章,关于 how programs start in linux。
要查看 gcc
对 link 你的 .o
-s 做了什么,试试这个命令:gcc -v -o swap swap.o
。请注意 'v' 代表 'verbose'.
此外,you should read this 如果您对 64 位汇编感兴趣。
感谢您的回答和有用的见解!演讲结束。
如果你想调用像atoi
这样的简单库函数,但仍然避免使用C 运行时间,你可以这样做。 (即你写 _start
,而不是只写一个 main
在一堆样板代码 运行 之后被调用。)
gcc -o swap -nostartfiles swap.o
正如人们在评论中所说,glibc 的某些部分依赖于标准启动文件中的 constructors/destructors 运行。 stdio (puts/printf/scanf/getchar) 和 malloc 可能就是这种情况。不过,很多函数都是 "pure" 函数,它们只处理给定的输入。 sprintf/sscanf
可能还可以使用。
例如:
$ 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 exit@@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
这是一个使用 libc
而不使用 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
像这样编译和link:
nasm -f elf64 hello.asm
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -m elf_x86_64
到目前为止,这对我来说效果很好,但 static linkage it's complicated。
我正在 NASM
学习汇编,以 class 我在大学里。 我想 link C 运行时库 和 ld
,但我似乎无法包装我的绕过它。我有一台安装了 Linux Mint
的 64 bit
机器。
我感到困惑的原因是——据我所知——不是 linkC 运行时,gcc
将你需要的东西复制到你的程序中。虽然我可能是错的,所以请不要犹豫纠正我。
到目前为止我所做的是 link 它使用 gcc
。这会产生一堆我无法理解的机器代码,即使是像交换 rax
和 rbx
这样的小程序,这对学习目的来说也不是很好。 (请注意该程序有效。)
我不确定它是否相关,但这些是我用来编译的命令 link:
# compilation
nasm -f elf64 swap.asm
# gcc
gcc -o swap swap.o
# ld, no c runtime
ld -s -o swap swap.o
提前致谢!
结论:
既然我对这个问题有了正确的回答,这里有几件事我想提一下。动态链接 glibc
可以像 Z boson 的回答(对于 64 位系统)那样完成。如果您想静态地进行,do follow this link(我从 Z boson 的回答中重新发布)。
这是 Jester 发表的一篇文章,关于 how programs start in linux。
要查看 gcc
对 link 你的 .o
-s 做了什么,试试这个命令:gcc -v -o swap swap.o
。请注意 'v' 代表 'verbose'.
此外,you should read this 如果您对 64 位汇编感兴趣。
感谢您的回答和有用的见解!演讲结束。
如果你想调用像atoi
这样的简单库函数,但仍然避免使用C 运行时间,你可以这样做。 (即你写 _start
,而不是只写一个 main
在一堆样板代码 运行 之后被调用。)
gcc -o swap -nostartfiles swap.o
正如人们在评论中所说,glibc 的某些部分依赖于标准启动文件中的 constructors/destructors 运行。 stdio (puts/printf/scanf/getchar) 和 malloc 可能就是这种情况。不过,很多函数都是 "pure" 函数,它们只处理给定的输入。 sprintf/sscanf
可能还可以使用。
例如:
$ 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 exit@@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
这是一个使用 libc
而不使用 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
像这样编译和link:
nasm -f elf64 hello.asm
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -m elf_x86_64
到目前为止,这对我来说效果很好,但 static linkage it's complicated。