Cyr*_*yro 13 assembly gnu-assembler ld binutils
作为一个练习来更准确地学习c程序如何工作以及程序能够使用libc必须存在的最低内容级别,我自己尝试使用gas和ld主要在x86程序集中进行编程.
作为一个有趣的小挑战,我已成功组装并链接了几个链接到不同自制动态库的程序,但是我无法从头开始编写程序以使用libc函数调用而无需直接使用gcc.
我了解单个c库函数的调用约定,并通过使用objdump和readelf彻底检查了gcc编译的程序,但是在气体汇编文件中包含哪些信息以及要调用的参数方面没有任何进展在ld中成功链接到libc.有人对此有任何见解吗?
我在x86机器上运行Linux.
Mat*_*ery 20
要成功将libc与动态链接一起使用,至少需要做三件事:
/usr/lib/crt1.o包含的链接,_start它将是ELF二进制文件的入口点;/usr/lib/crti.o(在libc之前)和/usr/lib/crtn.o(之后),它们提供一些初始化和最终化代码;/lib/ld-linux.so.例如:
$ cat hello.s
.text
.globl main
main:
push %ebp
mov %esp, %ebp
pushl $hw_str
call puts
add $4, %esp
xor %eax, %eax
leave
ret
.data
hw_str:
.asciz "Hello world!"
$ as -o hello.o hello.s
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc hello.o /usr/lib/crtn.o
$ ./hello
Hello world!
$
Run Code Online (Sandbox Code Playgroud)
如果main在程序集中定义
马修的回答很好地告诉您最低要求。
让我向您展示如何在您的系统中找到这些路径。跑:
gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n'
Run Code Online (Sandbox Code Playgroud)
然后拿起马修提到的文件。
gcc -v 为您提供 GCC 使用的确切链接器命令。
collect2是 GCC 用作链接器前端的内部可执行文件,它与ld.
在 Ubuntu 14.04 64 位(GCC 4.8)中,我得到了:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
/usr/lib/x86_64-linux-gnu/crt1.o \
/usr/lib/x86_64-linux-gnu/crti.o \
-lc hello_world.o \
/usr/lib/x86_64-linux-gnu/crtn.o
Run Code Online (Sandbox Code Playgroud)
您可能还需要-lgcc和-lgcc_s。另请参阅:我真的需要 libgcc 吗?
如果_start在程序集中定义
如果我定义了_start,那么来自 glibc 的 hello world 仅适用于:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc hello_world.o
Run Code Online (Sandbox Code Playgroud)
我不确定这是否可靠,即是否crt可以安全地跳过初始化以调用 glibc 函数。另请参阅:为什么汇编程序仅在与 crt1.o crti.o 和 crtn.o 链接时才起作用?
| 归档时间: |
|
| 查看次数: |
8854 次 |
| 最近记录: |