Skip to content

Commit b85d655

Browse files
authored
add stubs for dlopen, dlsym, etc. (#443)
* add stubs for dlopen, dlsym, etc. This adds weak exports for the POSIX `dlopen`, `dlsym`, `dlclose`, and `dlerror` functions, allowing code which uses those features to compile. The implementations are stubs which always fail since there is currently no official standard for runtime dynamic linking. Since the symbols are weak, they can be overriden with useful, runtime-specific implementations, e.g. based on host functions or statically-generated tables (see https://github.com/dicej/component-linking-demo for an example of the latter). Signed-off-by: Joel Dice <joel.dice@fermyon.com> * move `dlopen` stubs out of libc and into libdl Per review feedback, it's easier to simply replace libdl.so with a working implementation at runtime than it is to override a handful of symbols in libc. Note that I've both added libdl.so and replaced the empty libdl.a we were previously creating with one that contains the stubs. I'm thinking we might as well be consistent about what symbols the .so and the .a contain. Otherwise, e.g. the CPython build gets confused when the dlfcn.h says `dlopen` etc. exist but libdl.a is empty. Signed-off-by: Joel Dice <joel.dice@fermyon.com> * customize dlfcn.h for WASI For WASI, we use flag values which match MacOS rather than musl. This gives `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. We also avoid declaring `dladdr`, `dlinfo`, and friends on WASI since they are neither supported nor stubbed at this time. Signed-off-by: Joel Dice <joel.dice@fermyon.com> * use musl's RTLD_* flags except for RTLD_LOCAL This minimizes the divergence from upstream while still giving us the flexibility to choose a default value later. Signed-off-by: Joel Dice <joel.dice@fermyon.com> * use `NULL` instead of `0` for null pointers Signed-off-by: Joel Dice <joel.dice@fermyon.com> --------- Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent 0edc7ae commit b85d655

7 files changed

Lines changed: 89 additions & 6 deletions

File tree

Makefile

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ LIBWASI_EMULATED_SIGNAL_SOURCES = \
8080
LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \
8181
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \
8282
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c
83+
LIBDL_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dl.c
8384
LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c)
8485
LIBC_TOP_HALF_DIR = libc-top-half
8586
LIBC_TOP_HALF_MUSL_DIR = $(LIBC_TOP_HALF_DIR)/musl
@@ -379,6 +380,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CL
379380
LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES))
380381
LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES))
381382
LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES))
383+
LIBDL_OBJS = $(call objs,$(LIBDL_SOURCES))
382384
LIBC_BOTTOM_HALF_CRT_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_CRT_SOURCES))
383385

384386
# These variables describe the locations of various files and
@@ -445,7 +447,6 @@ MUSL_OMIT_HEADERS += \
445447
"netdb.h" \
446448
"resolv.h" \
447449
"pty.h" \
448-
"dlfcn.h" \
449450
"setjmp.h" \
450451
"ulimit.h" \
451452
"sys/xattr.h" \
@@ -481,6 +482,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULA
481482
LIBWASI_EMULATED_GETPID_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_GETPID_OBJS))
482483
LIBWASI_EMULATED_SIGNAL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_OBJS))
483484
LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS))
485+
LIBDL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBDL_OBJS))
484486
BULK_MEMORY_SO_OBJS = $(patsubst %.o,%.pic.o,$(BULK_MEMORY_OBJS))
485487
DLMALLOC_SO_OBJS = $(patsubst %.o,%.pic.o,$(DLMALLOC_OBJS))
486488
LIBC_BOTTOM_HALF_ALL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBC_BOTTOM_HALF_ALL_OBJS))
@@ -521,6 +523,8 @@ $(OBJDIR)/libwasi-emulated-getpid.so.a: $(LIBWASI_EMULATED_GETPID_SO_OBJS)
521523

522524
$(OBJDIR)/libwasi-emulated-signal.so.a: $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS)
523525

526+
$(OBJDIR)/libdl.so.a: $(LIBDL_SO_OBJS)
527+
524528
$(SYSROOT_LIB)/libc.a: $(LIBC_OBJS)
525529

526530
$(SYSROOT_LIB)/libc-printscan-long-double.a: $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS)
@@ -535,6 +539,8 @@ $(SYSROOT_LIB)/libwasi-emulated-getpid.a: $(LIBWASI_EMULATED_GETPID_OBJS)
535539

536540
$(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS)
537541

542+
$(SYSROOT_LIB)/libdl.a: $(LIBDL_OBJS)
543+
538544
%.a:
539545
@mkdir -p "$(@D)"
540546
# On Windows, the commandline for the ar invocation got too long, so it needs to be split up.
@@ -603,7 +609,7 @@ startup_files $(LIBC_BOTTOM_HALF_ALL_OBJS) $(LIBC_BOTTOM_HALF_ALL_SO_OBJS): CFLA
603609
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \
604610
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal
605611

606-
$(LIBC_TOP_HALF_ALL_OBJS) $(LIBC_TOP_HALF_ALL_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS): CFLAGS += \
612+
$(LIBC_TOP_HALF_ALL_OBJS) $(LIBC_TOP_HALF_ALL_SO_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_OBJS) $(MUSL_PRINTSCAN_LONG_DOUBLE_SO_OBJS) $(MUSL_PRINTSCAN_NO_FLOATING_POINT_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) $(LIBDL_OBJS) $(LIBDL_SO_OBJS): CFLAGS += \
607613
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \
608614
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \
609615
-I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \
@@ -664,7 +670,8 @@ LIBC_SO = \
664670
$(SYSROOT_LIB)/libwasi-emulated-mman.so \
665671
$(SYSROOT_LIB)/libwasi-emulated-process-clocks.so \
666672
$(SYSROOT_LIB)/libwasi-emulated-getpid.so \
667-
$(SYSROOT_LIB)/libwasi-emulated-signal.so
673+
$(SYSROOT_LIB)/libwasi-emulated-signal.so \
674+
$(SYSROOT_LIB)/libdl.so
668675
endif
669676

670677
libc_so: include_dirs $(LIBC_SO)
@@ -676,13 +683,14 @@ libc: include_dirs \
676683
$(SYSROOT_LIB)/libwasi-emulated-mman.a \
677684
$(SYSROOT_LIB)/libwasi-emulated-process-clocks.a \
678685
$(SYSROOT_LIB)/libwasi-emulated-getpid.a \
679-
$(SYSROOT_LIB)/libwasi-emulated-signal.a
686+
$(SYSROOT_LIB)/libwasi-emulated-signal.a \
687+
$(SYSROOT_LIB)/libdl.a
680688

681689
finish: startup_files libc
682690
#
683691
# Create empty placeholder libraries.
684692
#
685-
for name in m rt pthread crypt util xnet resolv dl; do \
693+
for name in m rt pthread crypt util xnet resolv; do \
686694
$(AR) crs "$(SYSROOT_LIB)/lib$${name}.a"; \
687695
done
688696

expected/wasm32-wasi-threads/include-all.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include <crypt.h>
7676
#include <ctype.h>
7777
#include <dirent.h>
78+
#include <dlfcn.h>
7879
#include <endian.h>
7980
#include <err.h>
8081
#include <errno.h>

expected/wasm32-wasi-threads/predefined-macros.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,14 @@
14991499
#define RRFIXEDSZ NS_RRFIXEDSZ
15001500
#define RRQ 01
15011501
#define RS_HIPRI 0x01
1502+
#define RTLD_DEFAULT ((void *)0)
1503+
#define RTLD_GLOBAL 256
1504+
#define RTLD_LAZY 1
1505+
#define RTLD_LOCAL 8
1506+
#define RTLD_NEXT ((void *)-1)
1507+
#define RTLD_NODELETE 4096
1508+
#define RTLD_NOLOAD 4
1509+
#define RTLD_NOW 2
15021510
#define RUSAGE_CHILDREN 2
15031511
#define RUSAGE_SELF 1
15041512
#define R_OK (4)
@@ -2044,6 +2052,7 @@
20442052
#define _Complex_I (0.0f+1.0fi)
20452053
#define _DIRENT_H
20462054
#define _DIRENT_HAVE_D_TYPE
2055+
#define _DLFCN_H
20472056
#define _ENDIAN_H
20482057
#define _ERRNO_H
20492058
#define _ERR_H

expected/wasm32-wasi/include-all.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#include <crypt.h>
7676
#include <ctype.h>
7777
#include <dirent.h>
78+
#include <dlfcn.h>
7879
#include <endian.h>
7980
#include <err.h>
8081
#include <errno.h>

expected/wasm32-wasi/predefined-macros.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,14 @@
14671467
#define RRFIXEDSZ NS_RRFIXEDSZ
14681468
#define RRQ 01
14691469
#define RS_HIPRI 0x01
1470+
#define RTLD_DEFAULT ((void *)0)
1471+
#define RTLD_GLOBAL 256
1472+
#define RTLD_LAZY 1
1473+
#define RTLD_LOCAL 8
1474+
#define RTLD_NEXT ((void *)-1)
1475+
#define RTLD_NODELETE 4096
1476+
#define RTLD_NOLOAD 4
1477+
#define RTLD_NOW 2
14701478
#define RUSAGE_CHILDREN 2
14711479
#define RUSAGE_SELF 1
14721480
#define R_OK (4)
@@ -2010,6 +2018,7 @@
20102018
#define _Complex_I (0.0f+1.0fi)
20112019
#define _DIRENT_H
20122020
#define _DIRENT_HAVE_D_TYPE
2021+
#define _DLFCN_H
20132022
#define _ENDIAN_H
20142023
#define _ERRNO_H
20152024
#define _ERR_H

libc-top-half/musl/include/dlfcn.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,29 @@ extern "C" {
1212
#define RTLD_NOLOAD 4
1313
#define RTLD_NODELETE 4096
1414
#define RTLD_GLOBAL 256
15+
#ifdef __wasilibc_unmodified_upstream
1516
#define RTLD_LOCAL 0
17+
#else
18+
/* For WASI, we give `RTLD_LOCAL` a non-zero value, avoiding ambiguity and
19+
* allowing us to defer the decision of whether `RTLD_LOCAL` or `RTLD_GLOBAL`
20+
* should be the default when neither is specified.
21+
*/
22+
#define RTLD_LOCAL 8
23+
#endif
1624

1725
#define RTLD_NEXT ((void *)-1)
1826
#define RTLD_DEFAULT ((void *)0)
1927

28+
#ifdef __wasilibc_unmodified_upstream
2029
#define RTLD_DI_LINKMAP 2
30+
#endif
2131

2232
int dlclose(void *);
2333
char *dlerror(void);
2434
void *dlopen(const char *, int);
2535
void *dlsym(void *__restrict, const char *__restrict);
2636

27-
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
37+
#if defined(__wasilibc_unmodified_upstream) && (defined(_GNU_SOURCE) || defined(_BSD_SOURCE))
2838
typedef struct {
2939
const char *dli_fname;
3040
void *dli_fbase;

libc-top-half/musl/src/misc/dl.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* This file is used to build libdl.so with stub versions of `dlopen`, `dlsym`,
2+
* etc. The intention is that this stubbed libdl.so can be used to build
3+
* libraries and applications which use `dlopen` without committing to a
4+
* specific runtime implementation. Later, it can be replaced with a real,
5+
* working libdl.so (e.g. at runtime or component composition time).
6+
*
7+
* For example, the `wasm-tools component link` subcommand can be used to create
8+
* a component that bundles any `dlopen`-able libraries in such a way that their
9+
* function exports can be resolved symbolically at runtime using an
10+
* implementation of libdl.so designed for that purpose. In other cases, a
11+
* runtime might provide Emscripten-style dynamic linking via URLs or else a
12+
* more traditional, filesystem-based implementation. Finally, even this
13+
* stubbed version of libdl.so can be used at runtime in cases where dynamic
14+
* library resolution cannot or should not be supported (and the application can
15+
* handle this situation gracefully). */
16+
17+
#include <stddef.h>
18+
#include <dlfcn.h>
19+
20+
static const char *error = NULL;
21+
22+
weak int dlclose(void *library)
23+
{
24+
error = "dlclose not implemented";
25+
return -1;
26+
}
27+
28+
weak char *dlerror(void)
29+
{
30+
const char *var = error;
31+
error = NULL;
32+
return (char*) var;
33+
}
34+
35+
weak void *dlopen(const char *name, int flags)
36+
{
37+
error = "dlopen not implemented";
38+
return NULL;
39+
}
40+
41+
weak void *dlsym(void *library, const char *name)
42+
{
43+
error = "dlsym not implemented";
44+
return NULL;
45+
}

0 commit comments

Comments
 (0)