Static linkage with glibc without calling main

对着背影说爱祢 提交于 2019-12-17 20:52:41

问题


I have created a simple hello world using NASM which calls printf and _exit from libc but does not use 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

I create the object file like this

nasm -felf64 hello.asm

Then I can link it using dynamic linkage with glibc like this

ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64

This runs correctly with no errors. But now I want to do it statically. I do

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

This links but when I run the code I get a segmentation fault. Using gdb I see it gives

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401004 in vfprintf ()

If I write a simple hello world in C and compile with static in runs fine so apparently it's possible to link statically to glibc on my system. How can I use static linkage with glibc with my assembly code?

If I link to an alternative to glibc such as musl-libc it works fine

ld hello.o -static /usr/local/musl/lib/libc.a -melf_x86_64

I'm using Ubuntu 14.04, eglibc 2.19, and GCC 4.9.1


回答1:


Glibc have a huge initialization sequence, because it is done with strong intention to work in multithreading systems. Also GLIBC properly handles some GNU extensions like constructor attributes. On startup, it caching a lot inside TLS, including locale information, it initializes synchronization objects and so on.

Exact problem with your vprintf is uninitialized locale access.

When you are linking to it dynamically, all this work is done on loading and everything works.

Statically linked glibc requires __libc_init_first to be called to initialize all it need. Before this call you need __dl_tls_setup to properly setup TLS and after this call you will need __libc_csu_init to properly call all global constructors.

All this stuff is highly version-dependent and practically undocumented. Strictly saying, there is no safe way to link statically to glibc, skipping or modifying its normal _start sequence.

On the other hand, embedded-oriented libraries like musl or newlib are not so restrictive about initialization and multithreading and locales.



来源:https://stackoverflow.com/questions/26358119/static-linkage-with-glibc-without-calling-main

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!