Skip to content

TibboddiT/dyn-loader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Loading dynamic libraries from non libc static executable - Proof of concept

Warning: prototype quality: lots of bugs, lots of TODOs remaining.

Tested on x86_64-linux-gnu, with libraries compiled agasint glibc 2.41. Seems to also work on libraries compiled agasint musl, with a lightly patched libc.so version for now (cf. Notes).

See this thread for further information.

Usage

const std = @import("std");
const dll = @import("dll");

pub const debug = struct {
    pub const SelfInfo = dll.CustomSelfInfo;
};

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    const allocator = gpa.allocator();
    defer if (gpa.deinit() != .ok) @panic("memory check failed");

    // `dll` is a singleton, it should be initialized early and only once, on the main thread
    try dll.init(.{ .allocator = allocator, .log_level = .warn });
    defer dll.deinit();

    const lib_c = try dll.load("libc.so.6");

    const printf_sym = try lib_c.getSymbol("printf");
    const printf_addr = printf_sym.addr;
    const printf: *const fn ([*:0]const u8, ...) callconv(.c) c_int = @ptrFromInt(printf_addr);

    _ = printf("Hello, %s!\n", "World");
}

Current limitations

  • Libraries that dlopen other libraries might not behave correctly until:
    • all dl public API functions (like dladdr) are implemented
  • Even some dl not so private functions need an implementation, mainly because C++ exception handling (sad) might call them... (for instance _dl_find_object)
  • Loading libraries should be done before having started any thread.
  • Starting threads in zig land and in library land needs to be tested.
  • Some (rare) relocation types are still missing.
  • You should not link any libc (it is part of the goal anyway).

Notes

A custom musl's libc.so is included, which is a patched version of musl 1.25. You should load it first before loading libraries compiled against musl (see the musl printf example). The library is stripped (strip --strip-unneeded lib/libc.so) as it is often the case when it is packaged for linux distros.

The patch is:

diff --git a/original/musl-1.2.5/ldso/dynlink.c b/musl-1.2.5/ldso/dynlink.c
index 324aa85..bfc5140 100644
--- a/original/musl-1.2.5/ldso/dynlink.c
+++ b/musl-1.2.5/ldso/dynlink.c
@@ -1767,6 +1767,14 @@ hidden void __dls2(unsigned char *base, size_t *sp)
        else ((stage3_func)laddr(&ldso, dls2b_def.sym->st_value))(sp, auxv);
 }
 
+extern void __pre_dls2b(size_t *auxv)
+{
+       search_vec(auxv, &__hwcap, AT_HWCAP);
+       libc.auxv = auxv;
+       libc.tls_size = sizeof builtin_tls;
+       libc.tls_align = tls_align;
+}
+
 /* Stage 2b sets up a valid thread pointer, which requires relocations
  * completed in stage 2, and on which stage 3 is permitted to depend.
  * This is done as a separate stage, with symbolic lookup as a barrier,
@@ -1775,13 +1783,11 @@ hidden void __dls2(unsigned char *base, size_t *sp)
 
 void __dls2b(size_t *sp, size_t *auxv)
 {
+       __pre_dls2b(auxv);
+
        /* Setup early thread pointer in builtin_tls for ldso/libc itself to
         * use during dynamic linking. If possible it will also serve as the
         * thread pointer at runtime. */
-       search_vec(auxv, &__hwcap, AT_HWCAP);
-       libc.auxv = auxv;
-       libc.tls_size = sizeof builtin_tls;
-       libc.tls_align = tls_align;
        if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) {
                a_crash();
        }

An unpatched copy of libvulkan.so.1.4.326 from the Alpine repository is also included (renamed libvulkan.so.1).

Both are in the resources/musl directory. It is recommended that you produce those binary artifacts by yourself.

Run examples

zig build run-printf
zig build run-vulkan_version
zig build run-vulkan_version_musl
zig build run-x11_window
  • Both vulkan_advanced versions will currently result in an error, until libc's dl function replacements are implemented.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages