1

I'm using -nostartfiles flag (GCC) so my main function is :

void _start() {}

Now I want to use dlopen() function to open a .so lib ... So I decide to link the libdl.so too (to access dlopen() and ...) ... In fact, my CMake is like this:

cmake_minimum_required(VERSION 3.0)
project(myproject C)
set(CMAKE_C_STANDARD 11)
add_executable(myproject start.c)
set(CMAKE_C_FLAGS "-O3 -mavx2 -nostartfiles")
target_link_libraries(myproject 
        "libdl.so"
        "libc.so")

and this is my start.c

void * dlopen(const char * filename, int flag);

void _start() {
   
  void * lib = dlopen("mylib.so", RTLD_LAZY);
  if(!lib) {}

  // sys_exit(0)
  asm volatile("syscall" :: "a" (60), "D" (0) : "rcx", "r11");
}

As you see, I just used dlopen() function and when I run this program, I get 139 as exit-code and there is a problem with dlopen() function … There is a problem inside _dl_relocate_object function on movaps %xmm0,-0x70(%rbp) ... segmentation fault

But when I remove -nostartfiles and I change void _start() {} to int main() {}, everything is just fine ... How to fix this problem with -nostartfiles ? What is the problem !!?

Attention, the "mylib.so" library MUST exist otherwise you get no error on void _start() {}

UPDATE I test it in Assembly (FASM) and worked successfully without requiring any initialization !!!!!

format ELF64 EXECUTABLE 3
entry start

include 'import64.inc'

interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libdl.so'
import dlopen,dlsym

segment readable executable

start:
        mov     rdi, dl_filename
        mov     esi, 1
        call    [dlopen]

        mov     rdi, rax
        mov     rsi, dl_function_name
        call    [dlsym]

        call    rax

        mov     eax, 60
        xor     edi, edi
        syscall
        hlt

segment readable
dl_filename db 'libuntitled.so', 0x00
dl_function_name db 'hello', 0x00    
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
HelloMachine
  • 355
  • 2
  • 8
  • What is the problem? - you can check an error code. – user14063792468 May 15 '22 at 16:51
  • @user14063792468 well i said what is the problem ... i get segmentation fault in `_dl_relocate_object` function ! – HelloMachine May 15 '22 at 16:54
  • Really missed that. You can help by specifying your OS. – user14063792468 May 15 '22 at 17:02
  • 3
    If you want to bypass all the C runtime initialization code ("-nostartfiles")... then you need to know what you're doing. It sounds like you're trying to load a shared library ... using dlopen(), which is *ITSELF* part of a shared library ... without completely initialiizing the shared library runtime code first. Whoops! – paulsm4 May 15 '22 at 17:02
  • 1
    SUGGESTIONS: Q: Do you absolutely *NEED* to use "-nostartfiles"? What exactly do you gain without it? Q: Do you have a static version of libdl.a you can link instead? Q: Have you tried observing the default startup (e.g. with [strace](https://linux.die.net/man/1/strace) or equivalent) to see exactly what "initialization" you'll need to do "manually"? – paulsm4 May 15 '22 at 17:04
  • 1
    Why exactly do you want to use `-nostartfiles`? – Joseph Sible-Reinstate Monica May 15 '22 at 17:05
  • I must use `-nostartfiles` since i want to write Assembly project too without any C functions except (dlopen) ... – HelloMachine May 15 '22 at 17:09
  • 2
    `gcc` on `Linux`, as is on every other system, uses some runtime initialization. That is, it links with some files, like `crt0.o`, `crt1.o`, that "tune up" the C runtime. You explicitly have that initialization off. Also you still link with the `libc`. And `libc` suggests that it will be some initialization. You will have to supply some initialization by yourself _before_ you can use `libc`. – user14063792468 May 15 '22 at 17:11
  • 2
    `libdl` may also imply that you had done some initialization by yourself. I can not reproduce the program, I do not have `Linux` at hand. Seeing the `crt0`, or whatever startup it is, is a good start for you to understand what is what. – user14063792468 May 15 '22 at 17:15
  • 1
    This looks like you have a Stack misalignment problem. Make sure your Stack is aligned to 16 bytes whenever you call a function. – fuz May 15 '22 at 20:40
  • @paulsm4: A static library is the opposite of what you want. You need to let Linux's dynamic linking infrastructure run init hooks in shared libraries (including libc) if you're replacing `_start` with your own code that doesn't directly call init functions. The only way this program can work with most libc functions is by being dynamically linked (to libc at least). – Peter Cordes May 15 '22 at 22:33
  • 2
    The problem is that `_start` isn't a function, and is entered with RSP%16 == 0, not RSP%16 == 8 like functions are. So you need to declare it appropriately with GNU C `__attribute__((force_align_arg_pointer)) `, or write it in asm. Or compile with `-mincoming-stack-boundary=2` to make code that realigns the stack in every function. [How Get arguments value using inline assembly in C without Glibc?](https://stackoverflow.com/q/50260855) shows that. – Peter Cordes May 15 '22 at 22:35
  • @PeterCordes your answer `__attribute__((force_align_arg_pointer))` was amazing and solved my problem ... yes i thought about stack alignment since the problem was from `movaps` ... Thank you ... but this question is unique since it's talk about `dlopen` not segmention fault problem anyway – HelloMachine May 16 '22 at 04:44
  • The actual problem is writing a `_start` (in C or asm) that makes it safe to call other functions, including `dlopen` from `libdl`, or `printf` from `libc`. As you said yourself, `__attribute__((force_align_arg_pointer))` is the key part of the answer, so it's a duplicate of Q&As that explain stack alignment and how to get it in this case (a `_start` written in C instead of asm). What do you mean "*it's talk about `dlopen` not segmention fault problem anyway*" - the crash problem you describe in this question is a segmentation fault. Stack alignment is how you broke `dlopen`. – Peter Cordes May 16 '22 at 04:56

0 Answers0