Z b*_*son 3 assembly gcc glibc nasm
我创建使用NASM它调用一个简单的Hello World printf,并_exit从libc的,但不使用main.
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
Run Code Online (Sandbox Code Playgroud)
我像这样创建对象文件
nasm -felf64 hello.asm
Run Code Online (Sandbox Code Playgroud)
然后我可以使用动态链接与glibc这样链接它
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64
Run Code Online (Sandbox Code Playgroud)
这运行正确,没有错误.但现在我想静静地做.我做
ln -s `gcc -print-file-name=libc.a`
ln -s `gcc -print-file-name=libgcc_eh.a`
ld hello.o -static libc.a libgcc_eh.a libc.a -melf_x86_64
Run Code Online (Sandbox Code Playgroud)
这链接,但当我运行代码时,我得到一个分段错误.使用gdb我看到它给出
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401004 in vfprintf ()
Run Code Online (Sandbox Code Playgroud)
如果我在C中编写一个简单的hello世界并在运行中使用static编译,那么显然可以在我的系统上静态链接到glibc.如何使用glibc与汇编代码进行静态链接?
如果我链接到glibc的替代品,如musl-libc,它可以正常工作
ld hello.o -static /usr/local/musl/lib/libc.a -melf_x86_64
Run Code Online (Sandbox Code Playgroud)
我使用的是Ubuntu 14.04,eglibc 2.19和GCC 4.9.1
Glibc有一个巨大的初始化序列,因为它有很强的意图在多线程系统中工作.此外,GLIBC正确处理一些GNU扩展,如构造函数属性.在启动时,它在TLS中缓存很多,包括区域设置信息,初始化同步对象等等.
vprintf的确切问题是未初始化的语言环境访问.
当您动态链接到它时,所有这些工作都是在加载时完成的,一切正常.
需要__libc_init_first调用静态链接的glibc 来初始化它所需要的一切.在此调用之前,您需要__dl_tls_setup正确设置TLS,在此调用之后,您需要__libc_csu_init正确调用所有全局构造函数.
所有这些东西都是高度依赖版本的,几乎没有文档记录.严格地说,没有安全的方法可以静态链接到glibc,跳过或修改它的正常_start序列.
另一方面,像musl或newlib这样的嵌入式库对初始化,多线程和语言环境没有那么严格的限制.
| 归档时间: |
|
| 查看次数: |
646 次 |
| 最近记录: |