From e60072635eca3f3c983d92819aa67c0decc7d4a6 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 18 Apr 2024 21:47:47 +0200 Subject: [PATCH] Add libdl shims from wasi-libc --- lib/libc/include/wasm-wasi-musl/dlfcn.h | 56 +++++++++++++++++++ .../wasi/libc-top-half/musl/src/misc/dl.c | 45 +++++++++++++++ src/Compilation.zig | 1 + src/wasi_libc.zig | 28 ++++++++++ 4 files changed, 130 insertions(+) create mode 100644 lib/libc/include/wasm-wasi-musl/dlfcn.h create mode 100644 lib/libc/wasi/libc-top-half/musl/src/misc/dl.c diff --git a/lib/libc/include/wasm-wasi-musl/dlfcn.h b/lib/libc/include/wasm-wasi-musl/dlfcn.h new file mode 100644 index 0000000000..e802de88f6 --- /dev/null +++ b/lib/libc/include/wasm-wasi-musl/dlfcn.h @@ -0,0 +1,56 @@ +#ifndef _DLFCN_H +#define _DLFCN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_NOLOAD 4 +#define RTLD_NODELETE 4096 +#define RTLD_GLOBAL 256 +#ifdef __wasilibc_unmodified_upstream +#define RTLD_LOCAL 0 +#else +/* For WASI, we give `RTLD_LOCAL` a non-zero value, avoiding ambiguity and + * allowing us to defer the decision of whether `RTLD_LOCAL` or `RTLD_GLOBAL` + * should be the default when neither is specified. + */ +#define RTLD_LOCAL 8 +#endif + +#define RTLD_NEXT ((void *)-1) +#define RTLD_DEFAULT ((void *)0) + +#ifdef __wasilibc_unmodified_upstream +#define RTLD_DI_LINKMAP 2 +#endif + +int dlclose(void *); +char *dlerror(void); +void *dlopen(const char *, int); +void *dlsym(void *__restrict, const char *__restrict); + +#if defined(__wasilibc_unmodified_upstream) && (defined(_GNU_SOURCE) || defined(_BSD_SOURCE)) +typedef struct { + const char *dli_fname; + void *dli_fbase; + const char *dli_sname; + void *dli_saddr; +} Dl_info; +int dladdr(const void *, Dl_info *); +int dlinfo(void *, int, void *); +#endif + +#if _REDIR_TIME64 +__REDIR(dlsym, __dlsym_time64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/libc/wasi/libc-top-half/musl/src/misc/dl.c b/lib/libc/wasi/libc-top-half/musl/src/misc/dl.c new file mode 100644 index 0000000000..266594fd1f --- /dev/null +++ b/lib/libc/wasi/libc-top-half/musl/src/misc/dl.c @@ -0,0 +1,45 @@ +/* This file is used to build libdl.so with stub versions of `dlopen`, `dlsym`, + * etc. The intention is that this stubbed libdl.so can be used to build + * libraries and applications which use `dlopen` without committing to a + * specific runtime implementation. Later, it can be replaced with a real, + * working libdl.so (e.g. at runtime or component composition time). + * + * For example, the `wasm-tools component link` subcommand can be used to create + * a component that bundles any `dlopen`-able libraries in such a way that their + * function exports can be resolved symbolically at runtime using an + * implementation of libdl.so designed for that purpose. In other cases, a + * runtime might provide Emscripten-style dynamic linking via URLs or else a + * more traditional, filesystem-based implementation. Finally, even this + * stubbed version of libdl.so can be used at runtime in cases where dynamic + * library resolution cannot or should not be supported (and the application can + * handle this situation gracefully). */ + +#include +#include + +static const char *error = NULL; + +weak int dlclose(void *library) +{ + error = "dlclose not implemented"; + return -1; +} + +weak char *dlerror(void) +{ + const char *var = error; + error = NULL; + return (char*) var; +} + +weak void *dlopen(const char *name, int flags) +{ + error = "dlopen not implemented"; + return NULL; +} + +weak void *dlsym(void *library, const char *name) +{ + error = "dlsym not implemented"; + return NULL; +} diff --git a/src/Compilation.zig b/src/Compilation.zig index 1362b16cc9..8b12474422 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -806,6 +806,7 @@ pub const MiscTask = enum { @"wasi crt1-reactor.o", @"wasi crt1-command.o", @"wasi libc.a", + @"wasi libdl.a", @"libwasi-emulated-process-clocks.a", @"libwasi-emulated-getpid.a", @"libwasi-emulated-mman.a", diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 97a435c26c..05ae41954a 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -10,6 +10,7 @@ pub const CrtFile = enum { crt1_reactor_o, crt1_command_o, libc_a, + libdl_a, libwasi_emulated_process_clocks_a, libwasi_emulated_getpid_a, libwasi_emulated_mman_a, @@ -17,6 +18,9 @@ pub const CrtFile = enum { }; pub fn getEmulatedLibCrtFile(lib_name: []const u8) ?CrtFile { + if (mem.eql(u8, lib_name, "dl")) { + return .libdl_a; + } if (mem.eql(u8, lib_name, "wasi-emulated-process-clocks")) { return .libwasi_emulated_process_clocks_a; } @@ -34,6 +38,7 @@ pub fn getEmulatedLibCrtFile(lib_name: []const u8) ?CrtFile { pub fn emulatedLibCRFileLibName(crt_file: CrtFile) []const u8 { return switch (crt_file) { + .libdl_a => "libdl.a", .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a", .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a", .libwasi_emulated_mman_a => "libwasi-emulated-mman.a", @@ -154,6 +159,25 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre try comp.build_crt_file("c", .Lib, .@"wasi libc.a", prog_node, libc_sources.items, .{}); }, + + .libdl_a => { + var args = std.ArrayList([]const u8).init(arena); + try addCCArgs(comp, arena, &args, .{ .want_O3 = true }); + try addLibcBottomHalfIncludes(comp, arena, &args); + + var emu_dl_sources = std.ArrayList(Compilation.CSourceFile).init(arena); + for (emulated_dl_src_files) |file_path| { + try emu_dl_sources.append(.{ + .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ + "libc", try sanitize(arena, file_path), + }), + .extra_flags = args.items, + .owner = undefined, + }); + } + try comp.build_crt_file("dl", .Lib, .@"wasi libdl.a", prog_node, emu_dl_sources.items, .{}); + }, + .libwasi_emulated_process_clocks_a => { var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, .{ .want_O3 = true }); @@ -1173,6 +1197,10 @@ const libc_top_half_src_files = [_][]const u8{ const crt1_command_src_file = "wasi/libc-bottom-half/crt/crt1-command.c"; const crt1_reactor_src_file = "wasi/libc-bottom-half/crt/crt1-reactor.c"; +const emulated_dl_src_files = &[_][]const u8{ + "wasi/libc-top-half/musl/src/misc/dl.c", +}; + const emulated_process_clocks_src_files = &[_][]const u8{ "wasi/libc-bottom-half/clocks/clock.c", "wasi/libc-bottom-half/clocks/getrusage.c",