Skip to content

Commit

Permalink
Tweak how we do symbol versioning for glibc (#14272)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner authored Oct 3, 2024
1 parent 9446fd6 commit eda608d
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 111 deletions.
29 changes: 18 additions & 11 deletions cmake/targets/BuildBun.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -883,26 +883,33 @@ else()
-Wl,--as-needed
-Wl,--gc-sections
-Wl,-z,stack-size=12800000
-Wl,--wrap=fcntl
-Wl,--wrap=fcntl64
-Wl,--wrap=stat64
-Wl,--wrap=pow
-Wl,--wrap=cosf
-Wl,--wrap=exp
-Wl,--wrap=expf
-Wl,--wrap=fcntl
-Wl,--wrap=fcntl64
-Wl,--wrap=fmod
-Wl,--wrap=fmodf
-Wl,--wrap=fstat
-Wl,--wrap=fstat64
-Wl,--wrap=fstatat
-Wl,--wrap=fstatat64
-Wl,--wrap=log
-Wl,--wrap=log10f
-Wl,--wrap=log2
-Wl,--wrap=log2f
-Wl,--wrap=logf
-Wl,--wrap=lstat
-Wl,--wrap=stat64
-Wl,--wrap=stat
-Wl,--wrap=fstat
-Wl,--wrap=fstatat
-Wl,--wrap=lstat64
-Wl,--wrap=fstat64
-Wl,--wrap=fstatat64
-Wl,--wrap=mknod
-Wl,--wrap=mknodat
-Wl,--wrap=pow
-Wl,--wrap=sincosf
-Wl,--wrap=sinf
-Wl,--wrap=stat
-Wl,--wrap=stat64
-Wl,--wrap=statx
-Wl,--wrap=fmod
-Wl,--wrap=tanf
-Wl,--compress-debug-sections=zlib
-Wl,-z,lazy
-Wl,-z,norelro
Expand Down
260 changes: 160 additions & 100 deletions src/bun.js/bindings/workaround-missing-symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ extern "C" int kill(int pid, int sig)
// if linux
#if defined(__linux__)

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <fcntl.h>
// #include <sys/stat.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include <dlfcn.h>
#include <math.h>

#ifndef _STAT_VER
#if defined(__aarch64__)
Expand All @@ -72,132 +75,189 @@ extern "C" int kill(int pid, int sig)
#endif

#if defined(__x86_64__)
// Force older versions of symbols
__asm__(".symver pow,pow@GLIBC_2.2.5");
__asm__(".symver cosf,cosf@GLIBC_2.2.5");
__asm__(".symver exp,exp@GLIBC_2.2.5");
__asm__(".symver expf,expf@GLIBC_2.2.5");
__asm__(".symver fcntl,fcntl@GLIBC_2.2.5");
__asm__(".symver fmod,fmod@GLIBC_2.2.5");
__asm__(".symver fmodf,fmodf@GLIBC_2.2.5");
__asm__(".symver log,log@GLIBC_2.2.5");
__asm__(".symver log10f,log10f@GLIBC_2.2.5");
__asm__(".symver log2,log2@GLIBC_2.2.5");
__asm__(".symver log2f,log2f@GLIBC_2.2.5");
__asm__(".symver logf,logf@GLIBC_2.2.5");
__asm__(".symver pow,pow@GLIBC_2.2.5");
__asm__(".symver sincosf,sincosf@GLIBC_2.2.5");
__asm__(".symver sinf,sinf@GLIBC_2.2.5");
__asm__(".symver tanf,tanf@GLIBC_2.2.5");
#elif defined(__aarch64__)
__asm__(".symver cosf,cosf@GLIBC_2.17");
__asm__(".symver exp,exp@GLIBC_2.17");
__asm__(".symver expf,expf@GLIBC_2.17");
__asm__(".symver fcntl,fcntl@GLIBC_2.17");
__asm__(".symver fmod,fmod@GLIBC_2.17");
__asm__(".symver fmodf,fmodf@GLIBC_2.17");
__asm__(".symver log,log@GLIBC_2.17");
__asm__(".symver log10f,log10f@GLIBC_2.17");
__asm__(".symver log2,log2@GLIBC_2.17");
__asm__(".symver log2f,log2f@GLIBC_2.17");
__asm__(".symver logf,logf@GLIBC_2.17");
__asm__(".symver pow,pow@GLIBC_2.17");
__asm__(".symver sincosf,sincosf@GLIBC_2.17");
__asm__(".symver sinf,sinf@GLIBC_2.17");
__asm__(".symver tanf,tanf@GLIBC_2.17");
#endif

// ban statx, for now
extern "C" int __wrap_statx(int fd, const char* path, int flags,
unsigned int mask, struct statx* buf)
{
errno = ENOSYS;
#ifdef BUN_DEBUG
abort();
#if defined(__x86_64__) || defined(__aarch64__)
#define BUN_WRAP_GLIBC_SYMBOL(symbol) __wrap_##symbol
#else
#define BUN_WRAP_GLIBC_SYMBOL(symbol) symbol
#endif
return -1;
}

extern "C" int __real_fcntl(int fd, int cmd, ...);
typedef double (*MathFunction)(double);
typedef double (*MathFunction2)(double, double);

static inline double __real_exp(double x)
{
static MathFunction function = nullptr;
if (UNLIKELY(function == nullptr)) {
function = reinterpret_cast<MathFunction>(dlsym(nullptr, "exp"));
if (UNLIKELY(function == nullptr))
abort();
}

return function(x);
extern "C" {
double BUN_WRAP_GLIBC_SYMBOL(exp)(double);
double BUN_WRAP_GLIBC_SYMBOL(fmod)(double, double);
double BUN_WRAP_GLIBC_SYMBOL(log)(double);
double BUN_WRAP_GLIBC_SYMBOL(log2)(double);
double BUN_WRAP_GLIBC_SYMBOL(pow)(double, double);
float BUN_WRAP_GLIBC_SYMBOL(cosf)(float);
float BUN_WRAP_GLIBC_SYMBOL(expf)(float);
float BUN_WRAP_GLIBC_SYMBOL(fmodf)(float, float);
float BUN_WRAP_GLIBC_SYMBOL(log10f)(float);
float BUN_WRAP_GLIBC_SYMBOL(log2f)(float);
float BUN_WRAP_GLIBC_SYMBOL(logf)(float);
float BUN_WRAP_GLIBC_SYMBOL(sinf)(float);
float BUN_WRAP_GLIBC_SYMBOL(tanf)(float);
int BUN_WRAP_GLIBC_SYMBOL(fcntl)(int, int, ...);
int BUN_WRAP_GLIBC_SYMBOL(fcntl64)(int, int, ...);
void BUN_WRAP_GLIBC_SYMBOL(sincosf)(float, float*, float*);
}
static inline double __real_log(double x)
{
static MathFunction function = nullptr;
if (UNLIKELY(function == nullptr)) {
function = reinterpret_cast<MathFunction>(dlsym(nullptr, "log"));
if (UNLIKELY(function == nullptr))
abort();
}

return function(x);
}
static inline double __real_log2(double x)
extern "C" {
int __wrap_fcntl(int fd, int cmd, ...)
{
static MathFunction function = nullptr;
if (UNLIKELY(function == nullptr)) {
function = reinterpret_cast<MathFunction>(dlsym(nullptr, "log2"));
if (UNLIKELY(function == nullptr))
abort();
}

return function(x);
va_list args;
va_start(args, cmd);
void* arg = va_arg(args, void*);
va_end(args);
return fcntl(fd, cmd, arg);
}
static inline double __real_fmod(double x, double y)
{
static MathFunction2 function = nullptr;
if (UNLIKELY(function == nullptr)) {
function = reinterpret_cast<MathFunction2>(dlsym(nullptr, "fmod"));
if (UNLIKELY(function == nullptr))
abort();
}

return function(x, y);
}
typedef int (*fcntl64_func)(int fd, int cmd, ...);
static fcntl64_func real_fcntl64 = NULL;

extern "C" int __wrap_fcntl(int fd, int cmd, ...)
static void init_real_fcntl64()
{
va_list va;
va_start(va, cmd);
int ret = __real_fcntl(fd, cmd, va_arg(va, void*));
va_end(va);
return ret;
if (!real_fcntl64) {
real_fcntl64 = (fcntl64_func)dlsym(RTLD_NEXT, "fcntl64");
}
}

extern "C" int __wrap_fcntl64(int fd, int cmd, ...)
{
va_list va;
va_start(va, cmd);
int ret = __real_fcntl(fd, cmd, va_arg(va, void*));
va_end(va);
return ret;
}
enum arg_type {
NO_ARG,
INT_ARG,
PTR_ARG
};

extern "C" double __wrap_pow(double x, double y)
static enum arg_type get_arg_type(int cmd)
{
static void* pow_ptr = nullptr;
if (UNLIKELY(pow_ptr == nullptr)) {
pow_ptr = dlsym(RTLD_DEFAULT, "pow");
switch (cmd) {
// Commands that take no argument
case F_GETFD:
case F_GETFL:
case F_GETOWN:
case F_GETSIG:
case F_GETLEASE:
case F_GETPIPE_SZ:
#ifdef F_GET_SEALS
case F_GET_SEALS:
#endif
return NO_ARG;

// Commands that take an integer argument
case F_DUPFD:
case F_DUPFD_CLOEXEC:
case F_SETFD:
case F_SETFL:
case F_SETOWN:
case F_SETSIG:
case F_SETLEASE:
case F_NOTIFY:
case F_SETPIPE_SZ:
#ifdef F_ADD_SEALS
case F_ADD_SEALS:
#endif
return INT_ARG;

// Commands that take a pointer argument
case F_GETLK:
case F_SETLK:
case F_SETLKW:
case F_GETOWN_EX:
case F_SETOWN_EX:
return PTR_ARG;

default:
return PTR_ARG; // Default to pointer for unknown commands
}

return ((double (*)(double, double))pow_ptr)(x, y);
}

extern "C" double __wrap_exp(double x)
extern "C" int __wrap_fcntl64(int fd, int cmd, ...)
{
return __real_exp(x);
}
va_list ap;
enum arg_type type = get_arg_type(cmd);

extern "C" double __wrap_log(double x)
{
return __real_log(x);
}
init_real_fcntl64();

extern "C" double __wrap_log2(double x)
{
return __real_log2(x);
}
switch (type) {
case NO_ARG:
return real_fcntl64(fd, cmd);

extern "C" double __wrap_fmod(double x, double y)
{
return __real_fmod(x, y);
}
case INT_ARG: {
va_start(ap, cmd);
int arg = va_arg(ap, int);
va_end(ap);
return real_fcntl64(fd, cmd, arg);
}

static inline float __real_expf(float arg)
{
static void* ptr = nullptr;
if (UNLIKELY(ptr == nullptr)) {
ptr = dlsym(RTLD_DEFAULT, "expf");
case PTR_ARG: {
va_start(ap, cmd);
void* arg = va_arg(ap, void*);
va_end(ap);
return real_fcntl64(fd, cmd, arg);
}

return ((float (*)(float))ptr)(arg);
default:
va_end(ap);
errno = EINVAL;
return -1;
}
}
double __wrap_exp(double x) { return exp(x); }
double __wrap_fmod(double x, double y) { return fmod(x, y); }
double __wrap_log(double x) { return log(x); }
double __wrap_log2(double x) { return log2(x); }
double __wrap_pow(double x, double y) { return pow(x, y); }
float __wrap_cosf(float x) { return cosf(x); }
float __wrap_expf(float x) { return expf(x); }
float __wrap_fmodf(float x, float y) { return fmodf(x, y); }
float __wrap_log10f(float x) { return log10f(x); }
float __wrap_log2f(float x) { return log2f(x); }
float __wrap_logf(float x) { return logf(x); }
float __wrap_sinf(float x) { return sinf(x); }
float __wrap_tanf(float x) { return tanf(x); }
void __wrap_sincosf(float x, float* sin_x, float* cos_x) { sincosf(x, sin_x, cos_x); }
}

extern "C" float __wrap_expf(float arg)
// ban statx, for now
extern "C" int __wrap_statx(int fd, const char* path, int flags,
unsigned int mask, struct statx* buf)
{
return __real_expf(arg);
errno = ENOSYS;
#ifdef BUN_DEBUG
abort();
#endif
return -1;
}

#ifndef _MKNOD_VER
Expand Down

0 comments on commit eda608d

Please sign in to comment.