如何将C运行时库与'ld'链接?

时间:2015-12-06 13:27:23

标签: linux gcc assembly nasm ld

我正在学习NASM与大学课程的集会。 我想将 C运行时库ld 相关联,但我似乎无法绕过它。我安装了64 bit Linux Mint机器。

我感到困惑的原因是 - 据我所知 - 而不是链接C运行时,gcc将您需要的东西复制到程序中。我可能错了,所以请不要犹豫,纠正我。

到目前为止,我要做的是使用gcc链接它。这会产生一堆我无法遵循的机器代码,即使对于像rax交换rbx这样的小程序也是如此,这对于学习目的来说并不是那么好。 (请注意该程序有效。)

我不确定它是否相关,但这些是我用来编译和链接的命令:

# 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.o - s相关联的内容,请尝试以下命令:gcc -v -o swap swap.o。请注意,'v'代表'详细'。

另外,you should read this如果您对64位汇编感兴趣。

感谢您 以获得您的答案和有用的见解!演讲结束。

2 个答案:

答案 0 :(得分:6)

以下是使用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

像这样编译和链接:

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

答案 1 :(得分:2)

如果要调用像atoi这样的简单库函数,但仍然避免使用C运行库,则可以这样做。 (即你写_start,而不只是写一个在一堆样板代码运行后被调用的main。)

gcc -o swap -nostartfiles swap.o

正如人们在评论中所说,glibc的某些部分依赖于从标准启动文件运行的构造函数/析构函数。可能是stdio(puts / printf / scanf / getchar)的情况,也许是malloc。很多功能都是纯粹的"但是,这些函数只处理它们给出的输入。 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