Commit e60072635e

Frank Denis <github@pureftpd.org>
2024-04-18 21:47:47
Add libdl shims from wasi-libc
1 parent 8a8da49
Changed files (4)
lib
libc
include
wasm-wasi-musl
wasi
libc-top-half
musl
src
misc
src
lib/libc/include/wasm-wasi-musl/dlfcn.h
@@ -0,0 +1,56 @@
+#ifndef	_DLFCN_H
+#define	_DLFCN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+
+#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
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 <stddef.h>
+#include <dlfcn.h>
+
+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;
+}
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",
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",