diff --git a/CMakeLists.txt b/CMakeLists.txt index fa5f9b5a899..c1f4c82a5a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,6 +187,18 @@ if (APPLE) set(OLDEST_OSX_SUPPPORTED "11.7") elseif (UNIX) set(LINUX 1) + find_program(LDD ldd DOC "util for examing shared object dependency") + if (NOT LDD) + message(STATUS "Unable to find ldd: assume glibc") + else () + execute_process(COMMAND ${LDD} + RESULT_VARIABLE ldd_result + ERROR_VARIABLE ldd_err + OUTPUT_VARIABLE ldd_out) + if (ldd_err MATCHES "^musl libc") + set(MUSL 1) + endif () + endif () endif (APPLE) if (WIN32) set(WINDOWS 1) diff --git a/core/unix/include/siginfo.h b/core/unix/include/siginfo.h index 28abb62ebed..68be32146cd 100644 --- a/core/unix/include/siginfo.h +++ b/core/unix/include/siginfo.h @@ -17,6 +17,7 @@ * undef them here. */ #include +#include #ifdef MACOS /* For now we just use the system header. */ @@ -33,6 +34,11 @@ typedef clock_t __clock_t; # ifndef __WORDSIZE # define __WORDSIZE 32 # endif +# elif !defined(__GLIBC__) +# define __WORDSIZE LONG_BIT +typedef uid_t __uid_t; +typedef pid_t __pid_t; +typedef clock_t __clock_t; # else # include # endif diff --git a/core/unix/os.c b/core/unix/os.c index 9d9becdb14f..e2487c18fe3 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -6418,7 +6418,6 @@ set_stdfile_fileno(stdfile_t **stdfile, file_t old_fd, file_t file_no) (*stdfile)->STDFILE_FILENO = file_no; # endif #else -# warning stdfile_t is opaque; DynamoRIO will not set fds of libc FILEs. /* i#1973: musl libc support (and potentially other non-glibcs) */ /* only called by handle_close_pre(), so warning is specific to that. */ SYSLOG_INTERNAL_WARNING_ONCE( diff --git a/ext/drsyms/CMakeLists.txt b/ext/drsyms/CMakeLists.txt index 8a40bdb8aae..14aa751c83c 100644 --- a/ext/drsyms/CMakeLists.txt +++ b/ext/drsyms/CMakeLists.txt @@ -232,6 +232,10 @@ elseif (UNIX) # libdw uses pthread_rwlock_* routines. link_with_pthread(dw_pic) + if (MUSL) + target_sources(elf_pic PRIVATE "${elfutils_dir}/lib/error.c") + endif () + include_directories("${elfutils_dir}/libelf") include_directories("${elfutils_dir}/libdw") set(srcs ${srcs} drsyms_dw.c drsyms_elf.c) diff --git a/ext/drsyms/elfutils/config.h b/ext/drsyms/elfutils/config.h index bc684b2d518..e75ef5f74c3 100644 --- a/ext/drsyms/elfutils/config.h +++ b/ext/drsyms/elfutils/config.h @@ -33,7 +33,9 @@ /* Define if the GNU dcgettext() function is already present or preinstalled. */ -#define HAVE_DCGETTEXT 1 +#if !defined(__linux__) || defined(__GLIBC__) +# define HAVE_DCGETTEXT 1 +#endif /* Define to 1 if you have the declaration of `mempcpy', and to 0 if you don't. */ @@ -49,7 +51,9 @@ /* Define to 1 if you have the declaration of `rawmemchr', and to 0 if you don't. */ -#define HAVE_DECL_RAWMEMCHR 1 +#if !defined(__linux__) || defined(__GLIBC__) +# define HAVE_DECL_RAWMEMCHR 1 +#endif /* Define to 1 if you have the declaration of `reallocarray', and to 0 if you don't. */ @@ -60,7 +64,9 @@ #define HAVE_DECL_STRERROR_R 1 /* Define to 1 if you have the header file. */ -#define HAVE_ERROR_H 1 +#if !defined(__linux__) || defined(__GLIBC__) +# define HAVE_ERROR_H 1 +#endif /* Define to 1 if you have the header file. */ #define HAVE_ERR_H 1 diff --git a/make/configure.cmake.h b/make/configure.cmake.h index 5af65a6c5f4..879519475d5 100644 --- a/make/configure.cmake.h +++ b/make/configure.cmake.h @@ -65,6 +65,7 @@ /* Used a lot due to the different TLS. We thus provide a convenience define. */ # define MACOS64 #endif +#cmakedefine MUSL /* host, when different */ #cmakedefine DR_HOST_X86 diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 6ba6d409f91..c550d09d373 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -425,6 +425,11 @@ function (set_cflags source) else () set(cflags "${ORIG_CMAKE_C_FLAGS}") endif () + # Alpine Linux enables "-Wtrampolines" by default, breaking + # security-linux/trampoline.c + if (MUSL) + set(cflags "${cflags} -Wno-trampolines") + endif () if ("${source}" MATCHES ".cpp$") # Our C files need -std=gnu99, but that's an invalid flag for C++. # configure_DynamoRIO_global removes unfavorable options for clients, @@ -2737,7 +2742,9 @@ else (UNIX) tobuild_ci(client.winxfer client-interface/winxfer.c "" "" "") endif (UNIX) -if (NOT APPLE OR NOT AARCH64) # TODO i#5383: Port to Mac M1. +# TODO i#5383: Port to Mac M1. +# TODO i#1973: Port to musl libc +if (NOT APPLE OR NOT AARCH64 AND NOT MUSL) tobuild_ci(client.file_io client-interface/file_io.c "${CMAKE_CURRENT_SOURCE_DIR}/client-interface/file_io_data.txt" "" "") endif () diff --git a/suite/tests/linux/signal-base.h b/suite/tests/linux/signal-base.h index 0cef7de7b5d..33bf99ea5bf 100644 --- a/suite/tests/linux/signal-base.h +++ b/suite/tests/linux/signal-base.h @@ -77,6 +77,11 @@ static sigjmp_buf env; # define ITERS 500000 #endif +/* i#1973: __SIGRTMAX isn't available on musl libc */ +#ifdef MUSL +# define __SIGRTMAX SIGRTMAX +#endif + #ifdef AARCHXX /* i#4719: Work around QEMU bugs where QEMU can't handle signals 63 or 64. */ # undef SIGRTMAX @@ -151,25 +156,6 @@ static void break; } -#ifdef LINUX - case __SIGRTMAX: { - sigcontext_t *sc = SIGCXT_FROM_UCXT(ucxt); - void *pc = (void *)sc->SC_XIP; - /* SIGRTMAX has been 64 on Linux since kernel 2.1, from looking at glibc - * sources. */ -# ifndef AARCHXX /* i#4719: Work around QEMU bugs handling signals 63,64. */ - assert(__SIGRTMAX == 64); -# endif - assert(__SIGRTMAX == SIGRTMAX); -# if VERBOSE - print("Got SIGRTMAX @ 0x%08x\n", pc); -# else - print("Got SIGRTMAX\n"); -# endif - break; - } -#endif - #if USE_TIMER case SIGVTALRM: { sigcontext_t *sc = SIGCXT_FROM_UCXT(ucxt); @@ -182,7 +168,28 @@ static void } #endif - default: assert(0); + default: + /* i#1973: SIGRTMAX is a macro over function call, rather a constant on + musl libc. We use an if branch in default block to handle this */ +#ifdef LINUX + if (sig == __SIGRTMAX) { + sigcontext_t *sc = SIGCXT_FROM_UCXT(ucxt); + void *pc = (void *)sc->SC_XIP; + /* SIGRTMAX has been 64 on Linux since kernel 2.1, from looking at glibc + * sources. */ +# ifndef AARCHXX /* i#4719: Work around QEMU bugs handling signals 63,64. */ + assert(__SIGRTMAX == 64); +# endif + assert(__SIGRTMAX == SIGRTMAX); +# if VERBOSE + print("Got SIGRTMAX @ 0x%08x\n", pc); +# else + print("Got SIGRTMAX\n"); +# endif + break; + } +#endif + assert(0); } } diff --git a/suite/tests/tools.c b/suite/tests/tools.c index 44560c533f0..87feabf4cba 100644 --- a/suite/tests/tools.c +++ b/suite/tests/tools.c @@ -381,6 +381,9 @@ nolibc_print(const char *str) 3, # if defined(MACOS) || defined(ANDROID) stderr->_file, + /* TODO i#1973: handle opaque FILE * on musl libc */ +# elif defined(MUSL) + STDERR_FILENO, # else stderr->_fileno, # endif diff --git a/suite/tests/tools.h b/suite/tests/tools.h index 442fbeda987..f4eccbdd19f 100644 --- a/suite/tests/tools.h +++ b/suite/tests/tools.h @@ -53,7 +53,62 @@ # include # include /* abort */ # include +# ifdef MUSL +# pragma push_macro("REG_R8") +# pragma push_macro("REG_R9") +# pragma push_macro("REG_R10") +# pragma push_macro("REG_R11") +# pragma push_macro("REG_R12") +# pragma push_macro("REG_R13") +# pragma push_macro("REG_R14") +# pragma push_macro("REG_R15") +# pragma push_macro("REG_RDI") +# pragma push_macro("REG_RSI") +# pragma push_macro("REG_RBP") +# pragma push_macro("REG_RBX") +# pragma push_macro("REG_RDX") +# pragma push_macro("REG_RAX") +# pragma push_macro("REG_RCX") +# pragma push_macro("REG_RSP") +# pragma push_macro("REG_CR2") +# undef REG_R8 +# undef REG_R9 +# undef REG_R10 +# undef REG_R11 +# undef REG_R12 +# undef REG_R13 +# undef REG_R14 +# undef REG_R15 +# undef REG_RDI +# undef REG_RSI +# undef REG_RBP +# undef REG_RBX +# undef REG_RDX +# undef REG_RAX +# undef REG_RCX +# undef REG_RSP +# undef REG_CR2 +# endif # include +# ifdef MUSL +# pragma pop_macro("REG_R8") +# pragma pop_macro("REG_R9") +# pragma pop_macro("REG_R10") +# pragma pop_macro("REG_R11") +# pragma pop_macro("REG_R12") +# pragma pop_macro("REG_R13") +# pragma pop_macro("REG_R14") +# pragma pop_macro("REG_R15") +# pragma pop_macro("REG_RDI") +# pragma pop_macro("REG_RSI") +# pragma pop_macro("REG_RBP") +# pragma pop_macro("REG_RBX") +# pragma pop_macro("REG_RDX") +# pragma pop_macro("REG_RAX") +# pragma pop_macro("REG_RCX") +# pragma pop_macro("REG_RSP") +# pragma pop_macro("REG_CR2") +# endif # ifdef MACOS # define _XOPEN_SOURCE \ 700 /* required to get POSIX, etc. defines out of ucontext.h */