Skip to content

Commit f7cfe03

Browse files
committed
Fix dlopen() for FreeBSD and NetBSD
1 parent 2c1efd3 commit f7cfe03

File tree

3 files changed

+22
-11
lines changed

3 files changed

+22
-11
lines changed

examples/dlopen.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* - x86-64 Linux w/ Musl Libc
2323
* - x86-64 FreeBSD
2424
* - x86-64 Windows
25+
* - x86-64 NetBSD
2526
* - aarch64 Linux w/ Glibc
2627
* - aarch64 Linux w/ Musl Libc
2728
* - aarch64 MacOS

libc/dlopen/dlopen.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "libc/fmt/itoa.h"
3838
#include "libc/intrin/atomic.h"
3939
#include "libc/intrin/bits.h"
40+
#include "libc/intrin/kprintf.h"
4041
#include "libc/intrin/strace.internal.h"
4142
#include "libc/limits.h"
4243
#include "libc/nt/dll.h"
@@ -147,7 +148,7 @@ static int is_file_newer_than(const char *path, const char *other) {
147148
}
148149
if (stat(other, &st2)) {
149150
if (errno == ENOENT) {
150-
return true;
151+
return 2;
151152
} else {
152153
return -1;
153154
}
@@ -347,6 +348,7 @@ static dontinline void elf_exec(const char *file, char **envp) {
347348
size_t argsize = (1 + 2 + 1 + envc + 1 + auxc * 2 + 1 + 3) * 8;
348349
size_t mapsize = (stksize + argsize + (pagesz - 1)) & -pagesz;
349350
size_t skew = (mapsize - argsize) & (stkalign - 1);
351+
if (IsFreebsd()) skew += 8; // FreeBSD calls _start() like a C function
350352
map = __sys_mmap(0, mapsize, PROT_READ | PROT_WRITE,
351353
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, 0);
352354
if (map == MAP_FAILED) return;
@@ -569,12 +571,17 @@ static dontinline bool foreign_compile(char exe[hasatleast PATH_MAX]) {
569571
strlcat(exe, "dlopen-helper", PATH_MAX);
570572

571573
// skip build if helper exists and this program is older
574+
bool helper_exe_exists;
572575
switch (is_file_newer_than(GetProgramExecutableName(), exe)) {
573576
case -1:
574577
return false;
575-
case false:
578+
case 0:
576579
return true;
577-
case true:
580+
case 1:
581+
helper_exe_exists = true;
582+
break;
583+
case 2:
584+
helper_exe_exists = false;
578585
break;
579586
default:
580587
__builtin_unreachable();
@@ -586,12 +593,14 @@ static dontinline bool foreign_compile(char exe[hasatleast PATH_MAX]) {
586593
char sauce[sizeof(HELPER)];
587594
strlcpy(src, exe, PATH_MAX);
588595
strlcat(src, ".c", PATH_MAX);
589-
if ((fd = open(src, O_RDONLY | O_CLOEXEC)) != -1) {
590-
ssize_t got = pread(fd, sauce, sizeof(HELPER), 0);
591-
close(fd);
592-
if (got == sizeof(HELPER) - 1 &&
593-
!memcmp(sauce, HELPER, sizeof(HELPER) - 1)) {
594-
return true;
596+
if (helper_exe_exists) {
597+
if ((fd = open(src, O_RDONLY | O_CLOEXEC)) != -1) {
598+
ssize_t got = pread(fd, sauce, sizeof(HELPER), 0);
599+
close(fd);
600+
if (got == sizeof(HELPER) - 1 &&
601+
!memcmp(sauce, HELPER, sizeof(HELPER) - 1)) {
602+
return true;
603+
}
595604
}
596605
}
597606

@@ -623,7 +632,7 @@ static dontinline bool foreign_compile(char exe[hasatleast PATH_MAX]) {
623632
return false;
624633
}
625634
int pid, ws;
626-
char *args[] = {"cc", "-pie", "-fPIC", src, "-o", tmp, "-ldl", 0};
635+
char *args[] = {"cc", "-pie", "-fPIC", src, "-o", tmp, 0};
627636
errno_t err = posix_spawnp(&pid, args[0], NULL, NULL, args, environ);
628637
if (err) {
629638
unlink(tmp);

libc/dlopen/dlopen.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ LIBC_DLOPEN_A_DIRECTDEPS = \
3333
LIBC_RUNTIME \
3434
LIBC_SYSV \
3535
LIBC_SYSV_CALLS \
36-
LIBC_STR
36+
LIBC_STR \
37+
THIRD_PARTY_COMPILER_RT
3738

3839
LIBC_DLOPEN_A_DEPS := \
3940
$(call uniq,$(foreach x,$(LIBC_DLOPEN_A_DIRECTDEPS),$($(x))))

0 commit comments

Comments
 (0)