Dear list, While porting a smalltalk VM to OpenBSD I came across this peculiar quirk and I don't quite understand what's going on.
This VM does its FFI calls through dlopen'ing and dlsym'ing the symbols in question. This seems to work fine for all kinds of functions. However it fails with libc's "environ" symbol. What happens in the VM boils down to this snippet: -------------------------------------------------- #include <dlfcn.h> #include <stdio.h> int main (int argc, char** argv){ void* handle; void *fn; char **e; handle = dlopen("libc.so", RTLD_NOW|RTLD_GLOBAL); printf("Handle %p\n", handle); if (handle == NULL) return -1; fn = dlsym(handle, "environ"); if (fn == NULL) return -1; printf("Fn %p\n", fn); for (e=(char**)*((char **)fn); *e; e++) printf("%s\n", *e); return 0; } -------------------------------------------------- Surprisingly this works on linux. (Substitute libc.so with /usr/x86_64-linux-gnu/libc.so.6 madness for linux) On OpenBSD-current I get a handle for the symbol but it does not seem to point to a sane place resulting in a segfault. When running this with LD_DEBUG=1 I see that the loader does resolve environ: -------------------------------------------------- LD_DEBUG=1 ./a.out rtld loading: 'a.out' exe load offset: 0xc796800000 flags ./a.out = 0x0 head ./a.out obj ./a.out has ./a.out as head examining: './a.out' loading: libc.so.92.0 required by ./a.out flags /usr/lib/libc.so.92.0 = 0x0 obj /usr/lib/libc.so.92.0 has ./a.out as head linking dep /usr/lib/libc.so.92.0 as child of ./a.out examining: '/usr/lib/libc.so.92.0' flags /usr/libexec/ld.so = 0x0 obj /usr/libexec/ld.so has ./a.out as head protect start RELRO = 0xc9f48f4f80 in /usr/lib/libc.so.92.0 protect end RELRO = 0xc9f48f7000 in /usr/lib/libc.so.92.0 protect start RELRO = 0xc796a00e28 in ./a.out protect end RELRO = 0xc796a01000 in ./a.out Start End Type Open Ref GrpRef Name 000000c796800000 000000c796a02000 exe 1 0 0 ./a.out 000000c9f462b000 000000c9f490b000 rlib 0 1 0 /usr/lib/libc.so.92.0 000000ca09b00000 000000ca09b00000 rtld 0 1 0 /usr/libexec/ld.so symcache lookups 37 hits 0 ratio 0% hits dynamic loading done, success. tib new=0xca56f75f80 setting environ 0xca09d14640@/usr/libexec/ld.so[0xca7476d000] from 0xca09d14640 setting __progname 0xca09d14648@/usr/libexec/ld.so[0xca7476d000] from 0xca09d14648 entry point: 0xc7968003f0 dlopen: loading: libc.so linking /usr/lib/libc.so.92.0 as dlopen()ed dlopen: libc.so: done (success). Handle 0xca1f595800 dlsym: environ in /usr/lib/libc.so.92.0: 0xc9f4902720 Fn 0xc9f4902720 Segmentation fault (core dumped) -------------------------------------------------- Where does the semantic of dlsym differ from OpenBSD and Linux? Or is it the loader? What exactly am I getting back from dlsym here? Can someone enlighten me? Thanks for reading. Kind regards, Christian.