Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Static dynamic

The one header library to allow statically linked binaries to get access to the dynamic loading functionality.

The trick for doing this is to make the application do part of the kernel job and load the dynamic linker manually. This has the additional benefit of making the application libc version independent. The path to the linker is found using an assumption that on each Linux machine there is a dynamically linked /bin/sh binary from which the system's linker path can be obtained. Assuming this holds on all distributions, this also makes the application linker independent.

Since the system libc is loaded separately, this means the applications can still use statically linked libc such as musl without issues.

For doing all of the preparatory work, the library needs some space to store data required for the dynamic linker to launch properly. Trying to take as little space as possible and be non-intrusive as possible, the library allocates all of the permanent data on the stack in a tightly packed manner. This uses ~2K (depends on the number of args and env vars present) of the stack space which is just a small percentage of the usual stack on linux.

Note

Currently only x86_64 and aarch64 are supported

Usage

Just include the header to your application and ensure the main function signature is

int main(int argc, char** argv)

The access to the dlopen and other functions just access the sd_got global. There is also a SD_RTLD_NOW macro already defined to avoid including additional headers.

void* libc = sd_got.dlopen("libc.so.6", SD_RTLD_NOW);

The sd_got itself contains 4 function pointers: dlopen, dlsym, dlclose, dlerror:

typedef struct {
  sd_dlopen_fn  dlopen;
  sd_dlsym_fn   dlsym;
  sd_dlclose_fn dlclose;
  sd_dlerror_fn dlerror;
} sd_got_t;

Compilation flags

The loading of the dynamic linker happens before the main is called. For this reason the library defines its own _start symbol from which the program execution should start. For this to work, build must include compilation flags: -nostartfiles -fno-stack-protector.

Example

There is an example static_dynamic_test.c with build.sh that shows all of this and builds a simple raylib demo with this functionality

Acknowledgements

  • Detour - provided the base idea of how this whole machinery should work

About

[mirror] Dynamically load dynamic linker from a static binary

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages