├── tfg ├── __init__.py ├── browser │ ├── __init__.py │ ├── palette.py │ └── visualtree.py ├── calltree │ ├── __init__.py │ └── calltree.py ├── stackcollapsers │ ├── __init__.py │ ├── pyspycollapser.py │ ├── dtracecollapser.py │ ├── stackcollapser.py │ └── perfcollapser.py └── main.py ├── a.c ├── tfg.py ├── glibc-compatibility ├── musl │ ├── __math_invalid.c │ ├── __math_invalidf.c │ ├── __math_oflow.c │ ├── __math_oflowf.c │ ├── __math_uflow.c │ ├── __math_uflowf.c │ ├── aarch64 │ │ ├── syscall_arch.h │ │ ├── syscall.s │ │ ├── longjmp.s │ │ └── atomic_arch.h │ ├── __math_divzero.c │ ├── __math_divzerof.c │ ├── __math_xflow.c │ ├── __math_xflowf.c │ ├── signgam.c │ ├── musl_features.h │ ├── secure_getenv.c │ ├── syscall_ret.c │ ├── x86_64 │ │ ├── syscall_arch.h │ │ ├── syscall.s │ │ ├── longjmp.s │ │ └── atomic_arch.h │ ├── README │ ├── sched_cpucount.c │ ├── vasprintf.c │ ├── timespec_get.c │ ├── fallocate.c │ ├── log2f_data.h │ ├── timerfd.c │ ├── logf_data.h │ ├── pwritev.c │ ├── exp2f_data.h │ ├── pow_data.h │ ├── eventfd.c │ ├── sync_file_range.c │ ├── inotify.c │ ├── dup3.c │ ├── getentropy.c │ ├── accept4.c │ ├── exp_data.h │ ├── syscall.h │ ├── log2_data.h │ ├── pipe2.c │ ├── powf_data.h │ ├── log_data.h │ ├── clock_getres.c │ ├── scalbnf.c │ ├── clock_settime.c │ ├── epoll.c │ ├── futimens.c │ ├── clock_nanosleep.c │ ├── utimensat.c │ ├── log2f_data.c │ ├── logf_data.c │ ├── mkstemps.c │ ├── sched_getcpu.c │ ├── exp2f_data.c │ ├── powf_data.c │ ├── exp2f.c │ ├── logf.c │ ├── log2f.c │ ├── fcntl.c │ ├── expf.c │ ├── __polevll.c │ ├── vdso.c │ ├── clock_gettime.c │ ├── posix_spawn.c │ ├── log.c │ ├── strsignal.c │ ├── log2.c │ ├── exp2.c │ ├── exp.c │ ├── powf.c │ ├── glob.c │ ├── COPYRIGHT │ ├── exp_data.c │ ├── atomic.h │ ├── libm.h │ ├── log2_data.c │ ├── getauxval.c │ └── lgamma.c ├── README.md ├── spawn.h └── CMakeLists.txt ├── execute-prefix.sh ├── clangd ├── g++ ├── gcc ├── curl ├── bison ├── package.accept_keywords ├── OpenBLASConfigVersion.cmake ├── clang ├── clang++ ├── disable_ld_preload.c ├── flamegraph ├── OpenBLASConfig.cmake ├── LICENSE ├── portage_bashrc ├── ldb_gperf ├── ldd-recursive.pl ├── setup_toolchain.sh ├── FindThrift.cmake ├── README.md └── Dockerfile /tfg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tfg/browser/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tfg/calltree/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tfg/stackcollapsers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /a.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Compiled with ldb toolchain.\n"); 5 | } 6 | -------------------------------------------------------------------------------- /tfg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from tfg.main import main 4 | 5 | 6 | if __name__ == '__main__': 7 | main() 8 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_invalid.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __math_invalid(double x) 4 | { 5 | return (x - x) / (x - x); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_invalidf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float __math_invalidf(float x) 4 | { 5 | return (x - x) / (x - x); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/README.md: -------------------------------------------------------------------------------- 1 | This folder is forked from [ClickHouse](https://github.com/ClickHouse/ClickHouse/tree/c0b3821d62/base/glibc-compatibility) 2 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_oflow.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __math_oflow(uint32_t sign) 4 | { 5 | return __math_xflow(sign, 0x1p769); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_oflowf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float __math_oflowf(uint32_t sign) 4 | { 5 | return __math_xflowf(sign, 0x1p97f); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_uflow.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __math_uflow(uint32_t sign) 4 | { 5 | return __math_xflow(sign, 0x1p-767); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_uflowf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float __math_uflowf(uint32_t sign) 4 | { 5 | return __math_xflowf(sign, 0x1p-95f); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/aarch64/syscall_arch.h: -------------------------------------------------------------------------------- 1 | #define VDSO_USEFUL 2 | #define VDSO_CGT_SYM "__kernel_clock_gettime" 3 | #define VDSO_CGT_VER "LINUX_2.6.39" 4 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_divzero.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __math_divzero(uint32_t sign) 4 | { 5 | return fp_barrier(sign ? -1.0 : 1.0) / 0.0; 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_divzerof.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float __math_divzerof(uint32_t sign) 4 | { 5 | return fp_barrierf(sign ? -1.0f : 1.0f) / 0.0f; 6 | } 7 | -------------------------------------------------------------------------------- /execute-prefix.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export SHELL=/tmp/gentoo/bin/bash 4 | 5 | RETAIN="HOME=$HOME TERM=$TERM USER=$USER SHELL=$SHELL" 6 | 7 | env -i $RETAIN $SHELL -lc "$*" 8 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_xflow.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | double __math_xflow(uint32_t sign, double y) 4 | { 5 | return eval_as_double(fp_barrier(sign ? -y : y) * y); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/__math_xflowf.c: -------------------------------------------------------------------------------- 1 | #include "libm.h" 2 | 3 | float __math_xflowf(uint32_t sign, float y) 4 | { 5 | return eval_as_float(fp_barrierf(sign ? -y : y) * y); 6 | } 7 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/signgam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "libm.h" 3 | 4 | int __signgam = 0; 5 | 6 | extern __typeof(__signgam) signgam __attribute__((__weak__, alias("__signgam"))); 7 | -------------------------------------------------------------------------------- /clangd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | 8 | exec "$DIR/../tmp/gentoo/llvm/bin/clangd" "$@" 9 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/musl_features.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define weak __attribute__((__weak__)) 4 | #define hidden __attribute__((__visibility__("hidden"))) 5 | #define predict_false(x) __builtin_expect(x, 0) 6 | -------------------------------------------------------------------------------- /g++: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | 8 | exec "$DIR/../tmp/gentoo/bin/g++" -fuse-ld=lld --sysroot "$DIR/.." "$@" 9 | -------------------------------------------------------------------------------- /gcc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | 8 | exec "$DIR/../tmp/gentoo/bin/gcc" -fuse-ld=lld --sysroot "$DIR/.." "$@" 9 | -------------------------------------------------------------------------------- /curl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | export LD_LIBRARY_PATH=$DIR/../lib 8 | 9 | exec "$DIR/ldb-curl" "$@" 10 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/secure_getenv.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | 5 | char * secure_getenv(const char * name) 6 | { 7 | return getauxval(AT_SECURE) ? NULL : getenv(name); 8 | } 9 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/syscall_ret.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "syscall.h" 3 | 4 | long __syscall_ret(unsigned long r) 5 | { 6 | if (r > -4096UL) { 7 | errno = -r; 8 | return -1; 9 | } 10 | return r; 11 | } 12 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/x86_64/syscall_arch.h: -------------------------------------------------------------------------------- 1 | #define VDSO_USEFUL 2 | #define VDSO_CGT_SYM "__vdso_clock_gettime" 3 | #define VDSO_CGT_VER "LINUX_2.6" 4 | #define VDSO_GETCPU_SYM "__vdso_getcpu" 5 | #define VDSO_GETCPU_VER "LINUX_2.6" 6 | -------------------------------------------------------------------------------- /bison: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | export M4="$DIR/m4" 8 | export BISON_PKGDATADIR="$DIR/../share/bison" 9 | 10 | exec "$DIR/bison-3.5.1" "$@" 11 | -------------------------------------------------------------------------------- /package.accept_keywords: -------------------------------------------------------------------------------- 1 | sys-apps/sed ** 2 | sys-devel/binutils-config ** 3 | sys-devel/binutils ** 4 | sys-devel/gcc-config ** 5 | sys-devel/gcc ** 6 | sys-apps/coreutils ** 7 | app-arch/bzip2 ** 8 | sys-apps/portage ** 9 | dev-lang/python ** 10 | app-arch/zstd ** 11 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/README: -------------------------------------------------------------------------------- 1 | Tiny pieces extracted from MUSL library. 2 | 3 | git://git.musl-libc.org/musl 4 | c10bc61508dc52b8315084e628f36a6c3c2dabb1 5 | 6 | NOTE: Files was edited. 7 | 8 | NOTE: Math related files are pulled from commit 6ad514e4e278f0c3b18eb2db1d45638c9af1c07f. 9 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/aarch64/syscall.s: -------------------------------------------------------------------------------- 1 | .global __syscall 2 | .hidden __syscall 3 | .type __syscall,%function 4 | __syscall: 5 | .cfi_startproc 6 | uxtw x8,w0 7 | mov x0,x1 8 | mov x1,x2 9 | mov x2,x3 10 | mov x3,x4 11 | mov x4,x5 12 | mov x5,x6 13 | mov x6,x7 14 | svc 0 15 | ret 16 | .cfi_endproc 17 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/x86_64/syscall.s: -------------------------------------------------------------------------------- 1 | .global __syscall 2 | .hidden __syscall 3 | .type __syscall,@function 4 | __syscall: 5 | .cfi_startproc 6 | movq %rdi,%rax 7 | movq %rsi,%rdi 8 | movq %rdx,%rsi 9 | movq %rcx,%rdx 10 | movq %r8,%r10 11 | movq %r9,%r8 12 | movq 8(%rsp),%r9 13 | syscall 14 | ret 15 | .cfi_endproc 16 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/sched_cpucount.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | 4 | int __sched_cpucount(size_t size, const cpu_set_t *set) 5 | { 6 | size_t i, j, cnt=0; 7 | const unsigned char *p = (const void *)set; 8 | for (i=0; i 3 | #include 4 | #include 5 | 6 | int vasprintf(char **s, const char *fmt, va_list ap) 7 | { 8 | va_list ap2; 9 | va_copy(ap2, ap); 10 | int l = vsnprintf(0, 0, fmt, ap2); 11 | va_end(ap2); 12 | 13 | if (l<0 || !(*s=malloc(l+1U))) return -1; 14 | return vsnprintf(*s, l+1U, fmt, ap); 15 | } 16 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/timespec_get.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int clock_gettime(clockid_t, struct timespec *); 4 | 5 | /* There is no other implemented value than TIME_UTC; all other values 6 | * are considered erroneous. */ 7 | int timespec_get(struct timespec * ts, int base) 8 | { 9 | if (base != TIME_UTC) return 0; 10 | int ret = clock_gettime(CLOCK_REALTIME, ts); 11 | return ret < 0 ? 0 : base; 12 | } 13 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/fallocate.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | 5 | extern long int syscall (long int __sysno, ...) __THROW; 6 | 7 | int fallocate(int fd, int mode, off_t base, off_t len) 8 | { 9 | return syscall(SYS_fallocate, fd, mode, base, len); 10 | } 11 | 12 | int fallocate64(int fd, int mode, off_t base, off_t len) 13 | { 14 | return fallocate(fd, mode, base, len); 15 | } 16 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2f_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _LOG2F_DATA_H 6 | #define _LOG2F_DATA_H 7 | 8 | #include "musl_features.h" 9 | 10 | #define LOG2F_TABLE_BITS 4 11 | #define LOG2F_POLY_ORDER 4 12 | extern hidden const struct log2f_data { 13 | struct { 14 | double invc, logc; 15 | } tab[1 << LOG2F_TABLE_BITS]; 16 | double poly[LOG2F_POLY_ORDER]; 17 | } __log2f_data; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /disable_ld_preload.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | typedef int (*orig_access_f_type)(const char* pathname, int flags); 7 | 8 | int access(const char* path, int amode) { 9 | if (strcmp(path, "/etc/ld.so.preload") == 0) { 10 | errno = ENOENT; 11 | return -1; 12 | } 13 | orig_access_f_type orig_access; 14 | orig_access = (orig_access_f_type)dlsym(RTLD_NEXT, "access"); 15 | return orig_access(path, amode); 16 | } 17 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/timerfd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "syscall.h" 3 | 4 | int timerfd_create(int clockid, int flags) 5 | { 6 | return syscall(SYS_timerfd_create, clockid, flags); 7 | } 8 | 9 | int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old) 10 | { 11 | return syscall(SYS_timerfd_settime, fd, flags, new, old); 12 | } 13 | 14 | int timerfd_gettime(int fd, struct itimerspec *cur) 15 | { 16 | return syscall(SYS_timerfd_gettime, fd, cur); 17 | } 18 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/logf_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _LOGF_DATA_H 6 | #define _LOGF_DATA_H 7 | 8 | #include "musl_features.h" 9 | 10 | #define LOGF_TABLE_BITS 4 11 | #define LOGF_POLY_ORDER 4 12 | extern hidden const struct logf_data { 13 | struct { 14 | double invc, logc; 15 | } tab[1 << LOGF_TABLE_BITS]; 16 | double ln2; 17 | double poly[LOGF_POLY_ORDER - 1]; /* First order coefficient is 1. */ 18 | } __logf_data; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/pwritev.c: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | 7 | ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs) 8 | { 9 | /// There was cancellable syscall (syscall_cp), but I don't care. 10 | return syscall(SYS_pwritev, fd, iov, count, (long)(ofs), (long)(ofs>>32)); 11 | } 12 | 13 | ssize_t pwritev64(int fd, const struct iovec *iov, int count, off_t ofs) 14 | { 15 | return pwritev(fd, iov, count, ofs); 16 | } 17 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/aarch64/longjmp.s: -------------------------------------------------------------------------------- 1 | .global musl_glibc_longjmp 2 | .type musl_glibc_longjmp,@function 3 | musl_glibc_longjmp: 4 | // IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers 5 | ldp x19, x20, [x0,#0] 6 | ldp x21, x22, [x0,#16] 7 | ldp x23, x24, [x0,#32] 8 | ldp x25, x26, [x0,#48] 9 | ldp x27, x28, [x0,#64] 10 | ldp x29, x30, [x0,#80] 11 | ldr x2, [x0,#104] 12 | mov sp, x2 13 | ldp d8 , d9, [x0,#112] 14 | ldp d10, d11, [x0,#128] 15 | ldp d12, d13, [x0,#144] 16 | ldp d14, d15, [x0,#160] 17 | 18 | mov x0, x1 19 | cbnz x1, 1f 20 | mov x0, #1 21 | 1: br x30 22 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp2f_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _EXP2F_DATA_H 6 | #define _EXP2F_DATA_H 7 | 8 | #include "musl_features.h" 9 | #include 10 | 11 | /* Shared between expf, exp2f and powf. */ 12 | #define EXP2F_TABLE_BITS 5 13 | #define EXP2F_POLY_ORDER 3 14 | extern hidden const struct exp2f_data { 15 | uint64_t tab[1 << EXP2F_TABLE_BITS]; 16 | double shift_scaled; 17 | double poly[EXP2F_POLY_ORDER]; 18 | double shift; 19 | double invln2_scaled; 20 | double poly_scaled[EXP2F_POLY_ORDER]; 21 | } __exp2f_data; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /tfg/stackcollapsers/pyspycollapser.py: -------------------------------------------------------------------------------- 1 | from tfg.stackcollapsers.stackcollapser import StackCollapser 2 | 3 | class PySpyCollapser(StackCollapser): 4 | def parse(self): 5 | """parse(self) -> list[(list[str], int)] 6 | """ 7 | result = [] 8 | for i, line in enumerate([x.strip() for x in self._input_file], 1): 9 | if not line: 10 | continue 11 | vals = line.split(";") 12 | parts = vals[-1].split(" ") 13 | vals[-1] = " ".join(parts[:-1]) 14 | count = int(parts[-1]) 15 | result.append((vals, count)) 16 | return result 17 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/pow_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _POW_DATA_H 6 | #define _POW_DATA_H 7 | 8 | #include "musl_features.h" 9 | 10 | #define POW_LOG_TABLE_BITS 7 11 | #define POW_LOG_POLY_ORDER 8 12 | extern hidden const struct pow_log_data { 13 | double ln2hi; 14 | double ln2lo; 15 | double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1. */ 16 | /* Note: the pad field is unused, but allows slightly faster indexing. */ 17 | struct { 18 | double invc, pad, logc, logctail; 19 | } tab[1 << POW_LOG_TABLE_BITS]; 20 | } __pow_log_data; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/eventfd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "syscall.h" 5 | 6 | int eventfd(unsigned int count, int flags) 7 | { 8 | int r = __syscall(SYS_eventfd2, count, flags); 9 | #ifdef SYS_eventfd 10 | if (r==-ENOSYS && !flags) r = __syscall(SYS_eventfd, count); 11 | #endif 12 | return __syscall_ret(r); 13 | } 14 | 15 | int eventfd_read(int fd, eventfd_t *value) 16 | { 17 | return (sizeof(*value) == read(fd, value, sizeof(*value))) ? 0 : -1; 18 | } 19 | 20 | int eventfd_write(int fd, eventfd_t value) 21 | { 22 | return (sizeof(value) == write(fd, &value, sizeof(value))) ? 0 : -1; 23 | } 24 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/sync_file_range.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include "syscall.h" 5 | 6 | // works same in x86_64 && aarch64 7 | #define __SYSCALL_LL_E(x) (x) 8 | #define __SYSCALL_LL_O(x) (x) 9 | 10 | int sync_file_range(int fd, off_t pos, off_t len, unsigned flags) 11 | { 12 | #if defined(SYS_sync_file_range2) 13 | return syscall(SYS_sync_file_range2, fd, flags, 14 | __SYSCALL_LL_E(pos), __SYSCALL_LL_E(len)); 15 | #elif defined(SYS_sync_file_range) 16 | return __syscall(SYS_sync_file_range, fd, 17 | __SYSCALL_LL_O(pos), __SYSCALL_LL_E(len), flags); 18 | #else 19 | return __syscall_ret(-ENOSYS); 20 | #endif 21 | } -------------------------------------------------------------------------------- /glibc-compatibility/musl/inotify.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "syscall.h" 4 | 5 | int inotify_init() 6 | { 7 | return inotify_init1(0); 8 | } 9 | int inotify_init1(int flags) 10 | { 11 | int r = __syscall(SYS_inotify_init1, flags); 12 | #ifdef SYS_inotify_init 13 | if (r==-ENOSYS && !flags) r = __syscall(SYS_inotify_init); 14 | #endif 15 | return __syscall_ret(r); 16 | } 17 | 18 | int inotify_add_watch(int fd, const char *pathname, uint32_t mask) 19 | { 20 | return syscall(SYS_inotify_add_watch, fd, pathname, mask); 21 | } 22 | 23 | int inotify_rm_watch(int fd, int wd) 24 | { 25 | return syscall(SYS_inotify_rm_watch, fd, wd); 26 | } 27 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/dup3.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | 7 | int dup3(int old, int new, int flags) 8 | { 9 | int r; 10 | #ifdef SYS_dup2 11 | if (old==new) return __syscall_ret(-EINVAL); 12 | if (flags & O_CLOEXEC) { 13 | while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); 14 | if (r!=-ENOSYS) return __syscall_ret(r); 15 | } 16 | while ((r=__syscall(SYS_dup2, old, new))==-EBUSY); 17 | if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC); 18 | #else 19 | while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY); 20 | #endif 21 | return __syscall_ret(r); 22 | } 23 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/getentropy.c: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int getentropy(void *buffer, size_t len) 8 | { 9 | int cs, ret = 0; 10 | char *pos = buffer; 11 | 12 | if (len > 256) { 13 | errno = EIO; 14 | return -1; 15 | } 16 | 17 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 18 | 19 | while (len) { 20 | ret = getrandom(pos, len, 0); 21 | if (ret < 0) { 22 | if (errno == EINTR) continue; 23 | else break; 24 | } 25 | pos += ret; 26 | len -= ret; 27 | ret = 0; 28 | } 29 | 30 | pthread_setcancelstate(cs, 0); 31 | 32 | return ret; 33 | } 34 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/accept4.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | 7 | int accept4(int fd, struct sockaddr *restrict addr, socklen_t *restrict len, int flg) 8 | { 9 | if (!flg) return accept(fd, addr, len); 10 | int ret = socketcall_cp(accept4, fd, addr, len, flg, 0, 0); 11 | if (ret>=0 || (errno != ENOSYS && errno != EINVAL)) return ret; 12 | ret = accept(fd, addr, len); 13 | if (ret<0) return ret; 14 | if (flg & SOCK_CLOEXEC) 15 | __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); 16 | if (flg & SOCK_NONBLOCK) 17 | __syscall(SYS_fcntl, ret, F_SETFL, O_NONBLOCK); 18 | return ret; 19 | } 20 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _EXP_DATA_H 6 | #define _EXP_DATA_H 7 | 8 | #include "musl_features.h" 9 | #include 10 | 11 | #define EXP_TABLE_BITS 7 12 | #define EXP_POLY_ORDER 5 13 | #define EXP_USE_TOINT_NARROW 0 14 | #define EXP2_POLY_ORDER 5 15 | extern hidden const struct exp_data { 16 | double invln2N; 17 | double shift; 18 | double negln2hiN; 19 | double negln2loN; 20 | double poly[4]; /* Last four coefficients. */ 21 | double exp2_shift; 22 | double exp2_poly[EXP2_POLY_ORDER]; 23 | uint64_t tab[2*(1 << EXP_TABLE_BITS)]; 24 | } __exp_data; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef long syscall_arg_t; 7 | 8 | __attribute__((visibility("hidden"))) 9 | long __syscall_ret(unsigned long); 10 | 11 | __attribute__((visibility("hidden"))) 12 | long __syscall(syscall_arg_t, ...); 13 | 14 | __attribute__((visibility("hidden"))) 15 | void *__vdsosym(const char *, const char *); 16 | 17 | #define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) 18 | 19 | #define socketcall(...) __syscall_ret(__socketcall(__VA_ARGS__)) 20 | 21 | #define __socketcall(nm,a,b,c,d,e,f) __syscall(SYS_##nm, a, b, c, d, e, f) 22 | 23 | #define socketcall_cp socketcall 24 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _LOG2_DATA_H 6 | #define _LOG2_DATA_H 7 | 8 | #include "musl_features.h" 9 | 10 | #define LOG2_TABLE_BITS 6 11 | #define LOG2_POLY_ORDER 7 12 | #define LOG2_POLY1_ORDER 11 13 | extern hidden const struct log2_data { 14 | double invln2hi; 15 | double invln2lo; 16 | double poly[LOG2_POLY_ORDER - 1]; 17 | double poly1[LOG2_POLY1_ORDER - 1]; 18 | struct { 19 | double invc, logc; 20 | } tab[1 << LOG2_TABLE_BITS]; 21 | #if !__FP_FAST_FMA 22 | struct { 23 | double chi, clo; 24 | } tab2[1 << LOG2_TABLE_BITS]; 25 | #endif 26 | } __log2_data; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/pipe2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | 7 | int pipe2(int fd[2], int flag) 8 | { 9 | if (!flag) return pipe(fd); 10 | int ret = __syscall(SYS_pipe2, fd, flag); 11 | if (ret != -ENOSYS) return __syscall_ret(ret); 12 | ret = pipe(fd); 13 | if (ret) return ret; 14 | if (flag & O_CLOEXEC) { 15 | __syscall(SYS_fcntl, fd[0], F_SETFD, FD_CLOEXEC); 16 | __syscall(SYS_fcntl, fd[1], F_SETFD, FD_CLOEXEC); 17 | } 18 | if (flag & O_NONBLOCK) { 19 | __syscall(SYS_fcntl, fd[0], F_SETFL, O_NONBLOCK); 20 | __syscall(SYS_fcntl, fd[1], F_SETFL, O_NONBLOCK); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/powf_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _POWF_DATA_H 6 | #define _POWF_DATA_H 7 | 8 | #include "libm.h" 9 | #include "exp2f_data.h" 10 | 11 | #define POWF_LOG2_TABLE_BITS 4 12 | #define POWF_LOG2_POLY_ORDER 5 13 | #if TOINT_INTRINSICS 14 | #define POWF_SCALE_BITS EXP2F_TABLE_BITS 15 | #else 16 | #define POWF_SCALE_BITS 0 17 | #endif 18 | #define POWF_SCALE ((double)(1 << POWF_SCALE_BITS)) 19 | extern hidden const struct powf_log2_data { 20 | struct { 21 | double invc, logc; 22 | } tab[1 << POWF_LOG2_TABLE_BITS]; 23 | double poly[POWF_LOG2_POLY_ORDER]; 24 | } __powf_log2_data; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | #ifndef _LOG_DATA_H 6 | #define _LOG_DATA_H 7 | 8 | #include "musl_features.h" 9 | 10 | #define LOG_TABLE_BITS 7 11 | #define LOG_POLY_ORDER 6 12 | #define LOG_POLY1_ORDER 12 13 | extern hidden const struct log_data { 14 | double ln2hi; 15 | double ln2lo; 16 | double poly[LOG_POLY_ORDER - 1]; /* First coefficient is 1. */ 17 | double poly1[LOG_POLY1_ORDER - 1]; 18 | struct { 19 | double invc, logc; 20 | } tab[1 << LOG_TABLE_BITS]; 21 | #if !__FP_FAST_FMA 22 | struct { 23 | double chi, clo; 24 | } tab2[1 << LOG_TABLE_BITS]; 25 | #endif 26 | } __log_data; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/clock_getres.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "syscall.h" 4 | 5 | int clock_getres(clockid_t clk, struct timespec *ts) 6 | { 7 | #ifdef SYS_clock_getres_time64 8 | /* On a 32-bit arch, use the old syscall if it exists. */ 9 | if (SYS_clock_getres != SYS_clock_getres_time64) { 10 | long ts32[2]; 11 | int r = __syscall(SYS_clock_getres, clk, ts32); 12 | if (!r && ts) { 13 | ts->tv_sec = ts32[0]; 14 | ts->tv_nsec = ts32[1]; 15 | } 16 | return __syscall_ret(r); 17 | } 18 | #endif 19 | /* If reaching this point, it's a 64-bit arch or time64-only 20 | * 32-bit arch and we can get result directly into timespec. */ 21 | return syscall(SYS_clock_getres, clk, ts); 22 | } 23 | -------------------------------------------------------------------------------- /glibc-compatibility/spawn.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPAWN_H 2 | #define _SPAWN_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | typedef struct { 11 | int __flags; 12 | pid_t __pgrp; 13 | sigset_t __def, __mask; 14 | int __prio, __pol; 15 | void *__fn; 16 | char __pad[64-sizeof(void *)]; 17 | } posix_spawnattr_t; 18 | 19 | typedef struct { 20 | int __pad0[2]; 21 | void *__actions; 22 | int __pad[16]; 23 | } posix_spawn_file_actions_t; 24 | 25 | int posix_spawn(pid_t *__restrict, const char *__restrict, const posix_spawn_file_actions_t *, 26 | const posix_spawnattr_t *__restrict, char *const *__restrict, char *const *__restrict); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /flamegraph: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | 5 | export PATH="$DIR":$PATH 6 | export LD_PRELOAD= 7 | export LD_LIBRARY_PATH=$DIR/../lib 8 | 9 | http_endpoint=$1 # required 10 | query_id=$2 # required 11 | 12 | if [[ -z $http_endpoint || -z $query_id ]]; then 13 | echo "$(basename "$0") " 14 | exit 1 15 | fi 16 | 17 | ldb-python3 "$DIR"/tfg.py -t pyspy <(ldb-curl -s "$1" -d "SELECT arrayStringConcat(arrayReverse(arrayMap(x -> demangle(addressToSymbol(x)), trace)), ';') || ' ' || toString(count()) FROM system.trace_log WHERE trace_type = 'CPU' and query_id = '$2' and event_date != today() - 10000 GROUP BY trace settings allow_introspection_functions = 1 format TSVRaw") 18 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/scalbnf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float scalbnf(float x, int n) 5 | { 6 | union {float f; uint32_t i;} u; 7 | float_t y = x; 8 | 9 | if (n > 127) { 10 | y *= 0x1p127f; 11 | n -= 127; 12 | if (n > 127) { 13 | y *= 0x1p127f; 14 | n -= 127; 15 | if (n > 127) 16 | n = 127; 17 | } 18 | } else if (n < -126) { 19 | y *= 0x1p-126f; 20 | n += 126; 21 | if (n < -126) { 22 | y *= 0x1p-126f; 23 | n += 126; 24 | if (n < -126) 25 | n = -126; 26 | } 27 | } 28 | u.i = (uint32_t)(0x7f+n)<<23; 29 | x = y * u.f; 30 | return x; 31 | } 32 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/clock_settime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "syscall.h" 4 | 5 | #define IS32BIT(x) !((x)+0x80000000ULL>>32) 6 | 7 | int clock_settime(clockid_t clk, const struct timespec *ts) 8 | { 9 | #ifdef SYS_clock_settime64 10 | time_t s = ts->tv_sec; 11 | long ns = ts->tv_nsec; 12 | int r = -ENOSYS; 13 | if (SYS_clock_settime == SYS_clock_settime64 || !IS32BIT(s)) 14 | r = __syscall(SYS_clock_settime64, clk, 15 | ((long long[]){s, ns})); 16 | if (SYS_clock_settime == SYS_clock_settime64 || r!=-ENOSYS) 17 | return __syscall_ret(r); 18 | if (!IS32BIT(s)) 19 | return __syscall_ret(-ENOTSUP); 20 | return syscall(SYS_clock_settime, clk, ((long[]){s, ns})); 21 | #else 22 | return syscall(SYS_clock_settime, clk, ts); 23 | #endif 24 | } 25 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/x86_64/longjmp.s: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 2 | .global musl_glibc_longjmp 3 | .type musl_glibc_longjmp,@function 4 | musl_glibc_longjmp: 5 | mov 0x30(%rdi),%r8 6 | mov 0x8(%rdi),%r9 7 | mov 0x38(%rdi),%rdx 8 | ror $0x11,%r8 9 | xor %fs:0x30,%r8 /* this ends up being the stack pointer */ 10 | ror $0x11,%r9 11 | xor %fs:0x30,%r9 12 | ror $0x11,%rdx 13 | xor %fs:0x30,%rdx /* this is the instruction pointer */ 14 | mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ 15 | mov 0x10(%rdi),%r12 16 | mov 0x18(%rdi),%r13 17 | mov 0x20(%rdi),%r14 18 | mov 0x28(%rdi),%r15 19 | mov %esi,%eax 20 | mov %r8,%rsp 21 | mov %r9,%rbp 22 | jmpq *%rdx /* goto saved address without altering rsp */ 23 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/epoll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "syscall.h" 5 | 6 | int epoll_create(int size) 7 | { 8 | return epoll_create1(0); 9 | } 10 | 11 | int epoll_create1(int flags) 12 | { 13 | int r = __syscall(SYS_epoll_create1, flags); 14 | #ifdef SYS_epoll_create 15 | if (r==-ENOSYS && !flags) r = __syscall(SYS_epoll_create, 1); 16 | #endif 17 | return __syscall_ret(r); 18 | } 19 | 20 | int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev) 21 | { 22 | return syscall(SYS_epoll_ctl, fd, op, fd2, ev); 23 | } 24 | 25 | int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs) 26 | { 27 | int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8); 28 | #ifdef SYS_epoll_wait 29 | if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to); 30 | #endif 31 | return __syscall_ret(r); 32 | } 33 | 34 | int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to) 35 | { 36 | return epoll_pwait(fd, ev, cnt, to, 0); 37 | } 38 | -------------------------------------------------------------------------------- /OpenBLASConfig.cmake: -------------------------------------------------------------------------------- 1 | # ---- OpenBLAS package configuration ---- 2 | # This file is used by CMake's find_package() to locate and configure OpenBLAS. 3 | 4 | # Package version 5 | set(OpenBLAS_VERSION "0.3.30") 6 | 7 | # Root dir is relative to this file's location 8 | file(REAL_PATH "usr" _OpenBLAS_ROOT_DIR BASE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}") 9 | 10 | # Include + library paths 11 | set(OpenBLAS_INCLUDE_DIR "${_OpenBLAS_ROOT_DIR}/include") 12 | set(OpenBLAS_LIBRARY "${_OpenBLAS_ROOT_DIR}/lib/libopenblas.a") 13 | 14 | if(NOT TARGET OpenBLAS::OpenBLAS) 15 | add_library(OpenBLAS::OpenBLAS UNKNOWN IMPORTED) 16 | set_target_properties(OpenBLAS::OpenBLAS PROPERTIES 17 | IMPORTED_LOCATION "${OpenBLAS_LIBRARY}" 18 | INTERFACE_INCLUDE_DIRECTORIES "${OpenBLAS_INCLUDE_DIR}" 19 | INTERFACE_LINK_LIBRARIES "m" 20 | ) 21 | endif() 22 | 23 | # Backwards-compatible variables 24 | set(OpenBLAS_INCLUDE_DIRS "${OpenBLAS_INCLUDE_DIR}") 25 | set(OpenBLAS_LIBRARIES "${OpenBLAS_LIBRARY};m") 26 | 27 | # Mark variables for find_package_handle_standard_args 28 | set(OpenBLAS_FOUND TRUE) 29 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/futimens.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | #include 7 | 8 | int futimens(int fd, const struct timespec times[2]) 9 | { 10 | int r = __syscall(SYS_utimensat, fd, 0, times, 0); 11 | #ifdef SYS_futimesat 12 | if (r != -ENOSYS) return __syscall_ret(r); 13 | struct timeval *tv = 0, tmp[2]; 14 | if (times) { 15 | int i; 16 | tv = tmp; 17 | for (i=0; i<2; i++) { 18 | if (times[i].tv_nsec >= 1000000000ULL) { 19 | if (times[i].tv_nsec == UTIME_NOW && 20 | times[1-i].tv_nsec == UTIME_NOW) { 21 | tv = 0; 22 | break; 23 | } 24 | if (times[i].tv_nsec == UTIME_OMIT) 25 | return __syscall_ret(-ENOSYS); 26 | return __syscall_ret(-EINVAL); 27 | } 28 | tmp[i].tv_sec = times[i].tv_sec; 29 | tmp[i].tv_usec = times[i].tv_nsec / 1000; 30 | } 31 | } 32 | 33 | r = __syscall(SYS_futimesat, fd, 0, tv); 34 | if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r); 35 | r = __syscall(SYS_utimes, 0, tv); 36 | #endif 37 | return __syscall_ret(r); 38 | } 39 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/clock_nanosleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "syscall.h" 5 | 6 | int clock_nanosleep(clockid_t clk, int flags, const struct timespec * req, struct timespec * rem) 7 | { 8 | if (clk == CLOCK_THREAD_CPUTIME_ID) 9 | return EINVAL; 10 | int old_cancel_type; 11 | int status; 12 | /// We cannot port __syscall_cp because musl has very limited cancellation point implementation. 13 | /// For example, c++ destructors won't get called and exception unwinding isn't implemented. 14 | /// Instead, we use normal __syscall here and turn on the asynchrous cancel mode to allow 15 | /// cancel. This works because nanosleep doesn't contain any resource allocations or 16 | /// deallocations. 17 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_cancel_type); 18 | if (clk == CLOCK_REALTIME && !flags) 19 | status = -__syscall(SYS_nanosleep, req, rem); 20 | else 21 | status = -__syscall(SYS_clock_nanosleep, clk, flags, req, rem); 22 | pthread_setcanceltype(old_cancel_type, NULL); 23 | return status; 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Amos Bird 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/utimensat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "syscall.h" 6 | #include 7 | 8 | int utimensat(int fd, const char *path, const struct timespec times[2], int flags) 9 | { 10 | int r = __syscall(SYS_utimensat, fd, path, times, flags); 11 | #ifdef SYS_futimesat 12 | if (r != -ENOSYS || flags) return __syscall_ret(r); 13 | struct timeval *tv = 0, tmp[2]; 14 | if (times) { 15 | int i; 16 | tv = tmp; 17 | for (i=0; i<2; i++) { 18 | if (times[i].tv_nsec >= 1000000000ULL) { 19 | if (times[i].tv_nsec == UTIME_NOW && 20 | times[1-i].tv_nsec == UTIME_NOW) { 21 | tv = 0; 22 | break; 23 | } 24 | if (times[i].tv_nsec == UTIME_OMIT) 25 | return __syscall_ret(-ENOSYS); 26 | return __syscall_ret(-EINVAL); 27 | } 28 | tmp[i].tv_sec = times[i].tv_sec; 29 | tmp[i].tv_usec = times[i].tv_nsec / 1000; 30 | } 31 | } 32 | 33 | r = __syscall(SYS_futimesat, fd, path, tv); 34 | if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r); 35 | r = __syscall(SYS_utimes, path, tv); 36 | #endif 37 | return __syscall_ret(r); 38 | } 39 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2f_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Data definition for log2f. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "log2f_data.h" 9 | 10 | const struct log2f_data __log2f_data = { 11 | .tab = { 12 | { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 }, 13 | { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 }, 14 | { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 }, 15 | { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 }, 16 | { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 }, 17 | { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 }, 18 | { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 }, 19 | { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 }, 20 | { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 }, 21 | { 0x1p+0, 0x0p+0 }, 22 | { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 }, 23 | { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 }, 24 | { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 }, 25 | { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 }, 26 | { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 }, 27 | { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 }, 28 | }, 29 | .poly = { 30 | -0x1.712b6f70a7e4dp-2, 0x1.ecabf496832ep-2, -0x1.715479ffae3dep-1, 31 | 0x1.715475f35c8b8p0, 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/logf_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Data definition for logf. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "logf_data.h" 9 | 10 | const struct logf_data __logf_data = { 11 | .tab = { 12 | { 0x1.661ec79f8f3bep+0, -0x1.57bf7808caadep-2 }, 13 | { 0x1.571ed4aaf883dp+0, -0x1.2bef0a7c06ddbp-2 }, 14 | { 0x1.49539f0f010bp+0, -0x1.01eae7f513a67p-2 }, 15 | { 0x1.3c995b0b80385p+0, -0x1.b31d8a68224e9p-3 }, 16 | { 0x1.30d190c8864a5p+0, -0x1.6574f0ac07758p-3 }, 17 | { 0x1.25e227b0b8eap+0, -0x1.1aa2bc79c81p-3 }, 18 | { 0x1.1bb4a4a1a343fp+0, -0x1.a4e76ce8c0e5ep-4 }, 19 | { 0x1.12358f08ae5bap+0, -0x1.1973c5a611cccp-4 }, 20 | { 0x1.0953f419900a7p+0, -0x1.252f438e10c1ep-5 }, 21 | { 0x1p+0, 0x0p+0 }, 22 | { 0x1.e608cfd9a47acp-1, 0x1.aa5aa5df25984p-5 }, 23 | { 0x1.ca4b31f026aap-1, 0x1.c5e53aa362eb4p-4 }, 24 | { 0x1.b2036576afce6p-1, 0x1.526e57720db08p-3 }, 25 | { 0x1.9c2d163a1aa2dp-1, 0x1.bc2860d22477p-3 }, 26 | { 0x1.886e6037841edp-1, 0x1.1058bc8a07ee1p-2 }, 27 | { 0x1.767dcf5534862p-1, 0x1.4043057b6ee09p-2 }, 28 | }, 29 | .ln2 = 0x1.62e42fefa39efp-1, 30 | .poly = { 31 | -0x1.00ea348b88334p-2, 0x1.5575b0be00b6ap-2, -0x1.ffffef20a4123p-2, 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /portage_bashrc: -------------------------------------------------------------------------------- 1 | if [[ ${CATEGORY}/${PN} == sys-devel/gcc && ${EBUILD_PHASE} == compile ]]; then 2 | echo "[hook] Disabling atexit_thread.cc usage of __cxa_thread_atexit_impl..." >&2 3 | 4 | sed -i 's/^#define _GLIBCXX_MAY_HAVE___CXA_THREAD_ATEXIT_IMPL 1/\/\/ #undef _GLIBCXX_MAY_HAVE___CXA_THREAD_ATEXIT_IMPL/' ${WORKDIR}/*/libstdc++-v3/config/os/gnu-linux/os_defines.h 5 | 6 | sed -i 's/_GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL/_GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL_DISABLED/g' "${WORKDIR}"/*/libstdc++-v3/libsupc++/atexit_thread.cc 7 | 8 | sed -i 's/_GLIBCXX_MAY_HAVE___CXA_THREAD_ATEXIT_IMPL/_GLIBCXX_MAY_HAVE___CXA_THREAD_ATEXIT_IMPL_DISABLED/g' "${WORKDIR}"/*/libstdc++-v3/libsupc++/atexit_thread.cc 9 | fi 10 | 11 | # Fix gettext m4 macro path for pinentry 12 | if [[ ${CATEGORY}/${PN} == app-crypt/pinentry ]]; then 13 | export AT_SYS_M4DIR="/usr/share/gettext/m4" 14 | fi 15 | 16 | if [[ ${CATEGORY}/${PN} == sys-libs/libunwind && ${EBUILD_PHASE} == compile ]]; then 17 | echo "[hook] Adjusting UNW_TARGET_AARCH64 macro check in _UPT_ptrauth_insn_mask.c ..." >&2 18 | 19 | sed -i 's|#ifdef UNW_TARGET_AARCH64|#if defined(UNW_TARGET_AARCH64) \&\& defined(NT_ARM_PAC_MASK)|' \ 20 | "${WORKDIR}"/*/src/ptrace/_UPT_ptrauth_insn_mask.c 21 | fi 22 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/mkstemps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* This assumes that a check for the 10 | template size has already been made */ 11 | static char * __randname(char * template) 12 | { 13 | int i; 14 | struct timespec ts; 15 | unsigned long r; 16 | 17 | clock_gettime(CLOCK_REALTIME, &ts); 18 | r = (ts.tv_nsec * 65537) ^ ((((intptr_t)(&ts)) / 16) + ((intptr_t)template)); 19 | for (i = 0; i < 6; i++, r >>= 5) 20 | template[i] = 'A' + (r & 15) + (r & 16) * 2; 21 | 22 | return template; 23 | } 24 | 25 | int mkstemps(char * template, int len) 26 | { 27 | size_t l = strlen(template); 28 | if (l < 6 || len > l - 6 || memcmp(template + l - len - 6, "XXXXXX", 6)) 29 | { 30 | errno = EINVAL; 31 | return -1; 32 | } 33 | 34 | int fd, retries = 100; 35 | do 36 | { 37 | __randname(template + l - len - 6); 38 | if ((fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0) 39 | return fd; 40 | } while (--retries && errno == EEXIST); 41 | 42 | memcpy(template + l - len - 6, "XXXXXX", 6); 43 | return -1; 44 | } 45 | -------------------------------------------------------------------------------- /ldb_gperf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | LIBDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/../lib" &> /dev/null && pwd ) 6 | loader="" 7 | 8 | if [ "$(arch)" = "x86_64" ]; then 9 | loader=$LIBDIR/ld-linux-x86-64.so.2 10 | elif [ "$(arch)" = "aarch64" ]; then 11 | loader=$LIBDIR/ld-linux-aarch64.so.1 12 | else 13 | echo "Unknown architecture: $(arch)" 14 | exit 1 15 | fi 16 | 17 | if [ -z "$1" ]; then 18 | echo "Usage: $0 [perf_signal]" 19 | exit 1 20 | fi 21 | 22 | if [ -z "$2" ]; then 23 | echo "Usage: $0 [perf_signal]" 24 | exit 1 25 | fi 26 | 27 | if [ -n "$3" ]; then 28 | num=$3 29 | if [ ! -z "${num##*[!0-9]*}" ] 30 | then 31 | if [ $num -lt 65 ] && [ $num -gt 0 ] 32 | then 33 | SIG="CPUPROFILESIGNAL=$3" 34 | fi 35 | fi 36 | if [ -z $SIG ] 37 | then 38 | echo "Usage: $0 [perf_signal]" 39 | echo "perf_signal should be >= 1 and <= 64" 40 | exit 1 41 | fi 42 | fi 43 | 44 | prog=$(realpath "$1") 45 | 46 | exec env LD_LIBRARY_PATH="$LIBDIR" LD_PRELOAD="$LIBDIR/libunwind.so:$LIBDIR/libprofiler.so" CPUPROFILE="$2" $SIG "$loader" --library-path "$LIBDIR" --inhibit-cache "$prog" 47 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/sched_getcpu.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include "syscall.h" 5 | #include "atomic.h" 6 | 7 | #if defined(__has_feature) 8 | #if __has_feature(memory_sanitizer) 9 | #include 10 | #endif 11 | #endif 12 | 13 | #ifdef VDSO_GETCPU_SYM 14 | 15 | static void *volatile vdso_func; 16 | 17 | typedef long (*getcpu_f)(unsigned *, unsigned *, void *); 18 | 19 | static long getcpu_init(unsigned *cpu, unsigned *node, void *unused) 20 | { 21 | void *p = __vdsosym(VDSO_GETCPU_VER, VDSO_GETCPU_SYM); 22 | getcpu_f f = (getcpu_f)p; 23 | a_cas_p(&vdso_func, (void *)getcpu_init, p); 24 | return f ? f(cpu, node, unused) : -ENOSYS; 25 | } 26 | 27 | static void *volatile vdso_func = (void *)getcpu_init; 28 | 29 | #endif 30 | 31 | int sched_getcpu(void) 32 | { 33 | int r; 34 | unsigned cpu = 0; 35 | 36 | #ifdef VDSO_GETCPU_SYM 37 | getcpu_f f = (getcpu_f)vdso_func; 38 | if (f) { 39 | r = f(&cpu, 0, 0); 40 | if (!r) return cpu; 41 | if (r != -ENOSYS) return __syscall_ret(r); 42 | } 43 | #endif 44 | 45 | r = __syscall(SYS_getcpu, &cpu, 0, 0); 46 | if (!r) { 47 | #if defined(__has_feature) 48 | #if __has_feature(memory_sanitizer) 49 | __msan_unpoison(&cpu, sizeof(cpu)); 50 | #endif 51 | #endif 52 | return cpu; 53 | } 54 | return __syscall_ret(r); 55 | } 56 | -------------------------------------------------------------------------------- /tfg/stackcollapsers/dtracecollapser.py: -------------------------------------------------------------------------------- 1 | """DTrace stack collapser. Used to collapse stacks produced by DTrace tool. 2 | DTrace output example: 3 | 4 | libc.so.7`memcmp+0x16 5 | tcsh`0x4485a3 6 | tcsh`0x40d7dc 7 | tcsh`0x405126 8 | tcsh`0x40395f 9 | ld-elf.so.1`0xc0067b000 10 | 42 11 | 12 | ... 13 | 14 | Read more here: https://github.com/brendangregg/FlameGraph/blob/master/stackcollapse.pl 15 | """ 16 | 17 | from tfg.stackcollapsers.stackcollapser import StackCollapser, StackCollapserException, trim_offset 18 | 19 | 20 | class DtraceCollapser(StackCollapser): 21 | def __init__(self, input_file): 22 | """__init__(self, input_file: file) 23 | """ 24 | super(DtraceCollapser, self).__init__(input_file) 25 | 26 | def parse(self): 27 | """parse(self) -> list[(list[str], int)] 28 | """ 29 | result = [] 30 | stack = [] 31 | for i, line in enumerate([x.strip() for x in self._input_file], 1): 32 | if not line: 33 | continue 34 | try: 35 | count = int(line) 36 | if not stack: 37 | raise StackCollapserException('Found a number at line {} but the stack is empty'.format(i)) 38 | result.append((stack[::-1], count)) 39 | stack = [] 40 | except ValueError: 41 | stack.append(trim_offset(line)) 42 | 43 | return result 44 | -------------------------------------------------------------------------------- /ldd-recursive.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my %uniq; 6 | 7 | foreach my $arg (@ARGV) { 8 | recurseLibs($arg); 9 | delete $uniq{$arg}; 10 | } 11 | print join( "\n", keys(%uniq) ) . "\n"; 12 | 13 | exit 0; 14 | 15 | # Written by Igor Ljubuncic (igor.ljubuncic@intel.com) 16 | # Yuval Nissan (yuval.nissan@intel.com) 17 | # Modified by Amos Bird (amosbird@gmail.com) 18 | sub recurseLibs { 19 | my $filename = shift; 20 | return if $uniq{$filename}; 21 | $uniq{$filename} = 1; 22 | chomp( my @libraries = `/usr/bin/ldd $filename` ); 23 | foreach my $line (@libraries) { 24 | next if not $line; 25 | $line =~ s/^\s+//g; 26 | $line =~ s/\s+$//g; 27 | 28 | if ( ( $line =~ /statically linked/ ) 29 | or ( $line =~ /not a dynamic executable/ ) ) 30 | { 31 | return; 32 | } 33 | elsif (( $line =~ /not found/ ) 34 | or ( $line =~ /linux-vdso.so/ ) ) 35 | { 36 | next; 37 | } 38 | 39 | # Split and recurse on libraries (third value is the lib path): 40 | my @newlibs = split( /\s+/, $line ); 41 | 42 | # Skip if no mapped or directly linked 43 | # Sane output comes with four elements 44 | if ( scalar(@newlibs) < 4 ) { 45 | $uniq{ $newlibs[0] } = 1; 46 | next; 47 | } 48 | 49 | &recurseLibs( $newlibs[2] ); 50 | } 51 | return; 52 | } 53 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp2f_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Shared data between expf, exp2f and powf. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "exp2f_data.h" 9 | 10 | #define N (1 << EXP2F_TABLE_BITS) 11 | 12 | const struct exp2f_data __exp2f_data = { 13 | /* tab[i] = uint(2^(i/N)) - (i << 52-BITS) 14 | used for computing 2^(k/N) for an int |k| < 150 N as 15 | double(tab[k%N] + (k << 52-BITS)) */ 16 | .tab = { 17 | 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, 18 | 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, 19 | 0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, 20 | 0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585, 21 | 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, 22 | 0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, 23 | 0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, 24 | 0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540, 25 | }, 26 | .shift_scaled = 0x1.8p+52 / N, 27 | .poly = { 28 | 0x1.c6af84b912394p-5, 0x1.ebfce50fac4f3p-3, 0x1.62e42ff0c52d6p-1, 29 | }, 30 | .shift = 0x1.8p+52, 31 | .invln2_scaled = 0x1.71547652b82fep+0 * N, 32 | .poly_scaled = { 33 | 0x1.c6af84b912394p-5/N/N/N, 0x1.ebfce50fac4f3p-3/N/N, 0x1.62e42ff0c52d6p-1/N, 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/powf_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Data definition for powf. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "powf_data.h" 9 | 10 | const struct powf_log2_data __powf_log2_data = { 11 | .tab = { 12 | { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 * POWF_SCALE }, 13 | { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 * POWF_SCALE }, 14 | { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 * POWF_SCALE }, 15 | { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 * POWF_SCALE }, 16 | { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 * POWF_SCALE }, 17 | { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 * POWF_SCALE }, 18 | { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 * POWF_SCALE }, 19 | { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 * POWF_SCALE }, 20 | { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 * POWF_SCALE }, 21 | { 0x1p+0, 0x0p+0 * POWF_SCALE }, 22 | { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 * POWF_SCALE }, 23 | { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 * POWF_SCALE }, 24 | { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 * POWF_SCALE }, 25 | { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 * POWF_SCALE }, 26 | { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 * POWF_SCALE }, 27 | { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 * POWF_SCALE }, 28 | }, 29 | .poly = { 30 | 0x1.27616c9496e0bp-2 * POWF_SCALE, -0x1.71969a075c67ap-2 * POWF_SCALE, 31 | 0x1.ec70a6ca7baddp-2 * POWF_SCALE, -0x1.7154748bef6c8p-1 * POWF_SCALE, 32 | 0x1.71547652ab82bp0 * POWF_SCALE, 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp2f.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Single-precision 2^x function. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "exp2f_data.h" 12 | 13 | /* 14 | EXP2F_TABLE_BITS = 5 15 | EXP2F_POLY_ORDER = 3 16 | 17 | ULP error: 0.502 (nearest rounding.) 18 | Relative error: 1.69 * 2^-34 in [-1/64, 1/64] (before rounding.) 19 | Wrong count: 168353 (all nearest rounding wrong results with fma.) 20 | Non-nearest ULP error: 1 (rounded ULP error) 21 | */ 22 | 23 | #define N (1 << EXP2F_TABLE_BITS) 24 | #define T __exp2f_data.tab 25 | #define C __exp2f_data.poly 26 | #define SHIFT __exp2f_data.shift_scaled 27 | 28 | static inline uint32_t top12(float x) 29 | { 30 | return asuint(x) >> 20; 31 | } 32 | 33 | float exp2f(float x) 34 | { 35 | uint32_t abstop; 36 | uint64_t ki, t; 37 | double_t kd, xd, z, r, r2, y, s; 38 | 39 | xd = (double_t)x; 40 | abstop = top12(x) & 0x7ff; 41 | if (predict_false(abstop >= top12(128.0f))) { 42 | /* |x| >= 128 or x is nan. */ 43 | if (asuint(x) == asuint(-INFINITY)) 44 | return 0.0f; 45 | if (abstop >= top12(INFINITY)) 46 | return x + x; 47 | if (x > 0.0f) 48 | return __math_oflowf(0); 49 | if (x <= -150.0f) 50 | return __math_uflowf(0); 51 | } 52 | 53 | /* x = k/N + r with r in [-1/(2N), 1/(2N)] and int k. */ 54 | kd = eval_as_double(xd + SHIFT); 55 | ki = asuint64(kd); 56 | kd -= SHIFT; /* k/N for int k. */ 57 | r = xd - kd; 58 | 59 | /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ 60 | t = T[ki % N]; 61 | t += ki << (52 - EXP2F_TABLE_BITS); 62 | s = asdouble(t); 63 | z = C[0] * r + C[1]; 64 | r2 = r * r; 65 | y = C[2] * r + 1; 66 | y = z * r2 + y; 67 | y = y * s; 68 | return eval_as_float(y); 69 | } 70 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/aarch64/atomic_arch.h: -------------------------------------------------------------------------------- 1 | #define a_ll a_ll 2 | static inline int a_ll(volatile int *p) 3 | { 4 | int v; 5 | __asm__ __volatile__ ("ldaxr %w0,%1" : "=r"(v) : "Q"(*p)); 6 | return v; 7 | } 8 | 9 | #define a_sc a_sc 10 | static inline int a_sc(volatile int *p, int v) 11 | { 12 | int r; 13 | __asm__ __volatile__ ("stlxr %w0,%w2,%1" : "=&r"(r), "=Q"(*p) : "r"(v) : "memory"); 14 | return !r; 15 | } 16 | 17 | #define a_barrier a_barrier 18 | static inline void a_barrier() 19 | { 20 | __asm__ __volatile__ ("dmb ish" : : : "memory"); 21 | } 22 | 23 | #define a_cas a_cas 24 | static inline int a_cas(volatile int *p, int t, int s) 25 | { 26 | int old; 27 | do { 28 | old = a_ll(p); 29 | if (old != t) { 30 | a_barrier(); 31 | break; 32 | } 33 | } while (!a_sc(p, s)); 34 | return old; 35 | } 36 | 37 | #define a_ll_p a_ll_p 38 | static inline void *a_ll_p(volatile void *p) 39 | { 40 | void *v; 41 | __asm__ __volatile__ ("ldaxr %0, %1" : "=r"(v) : "Q"(*(void *volatile *)p)); 42 | return v; 43 | } 44 | 45 | #define a_sc_p a_sc_p 46 | static inline int a_sc_p(volatile int *p, void *v) 47 | { 48 | int r; 49 | __asm__ __volatile__ ("stlxr %w0,%2,%1" : "=&r"(r), "=Q"(*(void *volatile *)p) : "r"(v) : "memory"); 50 | return !r; 51 | } 52 | 53 | #define a_cas_p a_cas_p 54 | static inline void *a_cas_p(volatile void *p, void *t, void *s) 55 | { 56 | void *old; 57 | do { 58 | old = a_ll_p(p); 59 | if (old != t) { 60 | a_barrier(); 61 | break; 62 | } 63 | } while (!a_sc_p(p, s)); 64 | return old; 65 | } 66 | 67 | #define a_ctz_64 a_ctz_64 68 | static inline int a_ctz_64(uint64_t x) 69 | { 70 | __asm__( 71 | " rbit %0, %1\n" 72 | " clz %0, %0\n" 73 | : "=r"(x) : "r"(x)); 74 | return x; 75 | } 76 | 77 | #define a_clz_64 a_clz_64 78 | static inline int a_clz_64(uint64_t x) 79 | { 80 | __asm__("clz %0, %1" : "=r"(x) : "r"(x)); 81 | return x; 82 | } 83 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/logf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Single-precision log function. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "logf_data.h" 12 | 13 | /* 14 | LOGF_TABLE_BITS = 4 15 | LOGF_POLY_ORDER = 4 16 | 17 | ULP error: 0.818 (nearest rounding.) 18 | Relative error: 1.957 * 2^-26 (before rounding.) 19 | */ 20 | 21 | #define T __logf_data.tab 22 | #define A __logf_data.poly 23 | #define Ln2 __logf_data.ln2 24 | #define N (1 << LOGF_TABLE_BITS) 25 | #define OFF 0x3f330000 26 | 27 | float logf(float x) 28 | { 29 | double_t z, r, r2, y, y0, invc, logc; 30 | uint32_t ix, iz, tmp; 31 | int k, i; 32 | 33 | ix = asuint(x); 34 | /* Fix sign of zero with downward rounding when x==1. */ 35 | if (WANT_ROUNDING && predict_false(ix == 0x3f800000)) 36 | return 0; 37 | if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) { 38 | /* x < 0x1p-126 or inf or nan. */ 39 | if (ix * 2 == 0) 40 | return __math_divzerof(1); 41 | if (ix == 0x7f800000) /* log(inf) == inf. */ 42 | return x; 43 | if ((ix & 0x80000000) || ix * 2 >= 0xff000000) 44 | return __math_invalidf(x); 45 | /* x is subnormal, normalize it. */ 46 | ix = asuint(x * 0x1p23f); 47 | ix -= 23 << 23; 48 | } 49 | 50 | /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. 51 | The range is split into N subintervals. 52 | The ith subinterval contains z and c is near its center. */ 53 | tmp = ix - OFF; 54 | i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; 55 | k = (int32_t)tmp >> 23; /* arithmetic shift */ 56 | iz = ix - (tmp & 0xff800000); 57 | invc = T[i].invc; 58 | logc = T[i].logc; 59 | z = (double_t)asfloat(iz); 60 | 61 | /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */ 62 | r = z * invc - 1; 63 | y0 = logc + (double_t)k * Ln2; 64 | 65 | /* Pipelined polynomial evaluation to approximate log1p(r). */ 66 | r2 = r * r; 67 | y = A[1] * r + A[2]; 68 | y = A[0] * r2 + y; 69 | y = y * r2 + (y0 + r); 70 | return eval_as_float(y); 71 | } 72 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2f.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Single-precision log2 function. 3 | * 4 | * Copyright (c) 2017-2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "log2f_data.h" 12 | 13 | /* 14 | LOG2F_TABLE_BITS = 4 15 | LOG2F_POLY_ORDER = 4 16 | 17 | ULP error: 0.752 (nearest rounding.) 18 | Relative error: 1.9 * 2^-26 (before rounding.) 19 | */ 20 | 21 | #define N (1 << LOG2F_TABLE_BITS) 22 | #define T __log2f_data.tab 23 | #define A __log2f_data.poly 24 | #define OFF 0x3f330000 25 | 26 | float log2f(float x) 27 | { 28 | double_t z, r, r2, p, y, y0, invc, logc; 29 | uint32_t ix, iz, top, tmp; 30 | int k, i; 31 | 32 | ix = asuint(x); 33 | /* Fix sign of zero with downward rounding when x==1. */ 34 | if (WANT_ROUNDING && predict_false(ix == 0x3f800000)) 35 | return 0; 36 | if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) { 37 | /* x < 0x1p-126 or inf or nan. */ 38 | if (ix * 2 == 0) 39 | return __math_divzerof(1); 40 | if (ix == 0x7f800000) /* log2(inf) == inf. */ 41 | return x; 42 | if ((ix & 0x80000000) || ix * 2 >= 0xff000000) 43 | return __math_invalidf(x); 44 | /* x is subnormal, normalize it. */ 45 | ix = asuint(x * 0x1p23f); 46 | ix -= 23 << 23; 47 | } 48 | 49 | /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. 50 | The range is split into N subintervals. 51 | The ith subinterval contains z and c is near its center. */ 52 | tmp = ix - OFF; 53 | i = (tmp >> (23 - LOG2F_TABLE_BITS)) % N; 54 | top = tmp & 0xff800000; 55 | iz = ix - top; 56 | k = (int32_t)tmp >> 23; /* arithmetic shift */ 57 | invc = T[i].invc; 58 | logc = T[i].logc; 59 | z = (double_t)asfloat(iz); 60 | 61 | /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */ 62 | r = z * invc - 1; 63 | y0 = logc + (double_t)k; 64 | 65 | /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */ 66 | r2 = r * r; 67 | y = A[1] * r + A[2]; 68 | y = A[0] * r2 + y; 69 | p = A[3] * r + y0; 70 | y = y * r2 + p; 71 | return eval_as_float(y); 72 | } 73 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/fcntl.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "syscall.h" 8 | 9 | #include 10 | #if defined(__GLIBC__) && __GLIBC__ >= 2 11 | # define GLIBC_MINOR __GLIBC_MINOR__ 12 | #elif defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ >= 2 13 | # define GLIBC_MINOR __GNU_LIBRARY_MINOR__ 14 | #endif 15 | 16 | #if defined(GLIBC_MINOR) && GLIBC_MINOR >= 28 17 | 18 | int fcntl64(int fd, int cmd, ...) 19 | { 20 | unsigned long arg; 21 | va_list ap; 22 | va_start(ap, cmd); 23 | arg = va_arg(ap, unsigned long); 24 | va_end(ap); 25 | if (cmd == F_SETFL) arg |= O_LARGEFILE; 26 | if (cmd == F_SETLKW) return syscall(SYS_fcntl, fd, cmd, (void *)arg); 27 | if (cmd == F_GETOWN) { 28 | struct f_owner_ex ex; 29 | int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex); 30 | if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg); 31 | if (ret) return __syscall_ret(ret); 32 | return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid; 33 | } 34 | if (cmd == F_DUPFD_CLOEXEC) { 35 | int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg); 36 | if (ret != -EINVAL) { 37 | if (ret >= 0) 38 | __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); 39 | return __syscall_ret(ret); 40 | } 41 | ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, 0); 42 | if (ret != -EINVAL) { 43 | if (ret >= 0) __syscall(SYS_close, ret); 44 | return __syscall_ret(-EINVAL); 45 | } 46 | ret = __syscall(SYS_fcntl, fd, F_DUPFD, arg); 47 | if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC); 48 | return __syscall_ret(ret); 49 | } 50 | switch (cmd) { 51 | case F_SETLK: 52 | case F_GETLK: 53 | case F_GETOWN_EX: 54 | case F_SETOWN_EX: 55 | return syscall(SYS_fcntl, fd, cmd, (void *)arg); 56 | default: 57 | return syscall(SYS_fcntl, fd, cmd, arg); 58 | } 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /glibc-compatibility/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | 3 | project(glibc-compatibility) 4 | 5 | enable_language(ASM) 6 | 7 | macro(add_glob cur_list) 8 | file(GLOB __tmp RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARGN}) 9 | list(APPEND ${cur_list} ${__tmp}) 10 | endmacro() 11 | 12 | macro(add_headers_and_sources prefix common_path) 13 | add_glob(${prefix}_headers ${CMAKE_CURRENT_SOURCE_DIR} ${common_path}/*.h) 14 | add_glob(${prefix}_sources ${common_path}/*.cpp ${common_path}/*.c ${common_path}/*.h) 15 | endmacro() 16 | 17 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64") 18 | set (ARCH_AMD64 1) 19 | endif () 20 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") 21 | set (ARCH_AARCH64 1) 22 | endif () 23 | if (ARCH_AARCH64 OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm") 24 | set (ARCH_ARM 1) 25 | endif () 26 | if (CMAKE_LIBRARY_ARCHITECTURE MATCHES "i386") 27 | set (ARCH_I386 1) 28 | endif () 29 | if ((ARCH_ARM AND NOT ARCH_AARCH64) OR ARCH_I386) 30 | message (FATAL_ERROR "32bit platforms are not supported") 31 | endif () 32 | 33 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64le.*|PPC64LE.*)") 34 | set (ARCH_PPC64LE 1) 35 | endif () 36 | 37 | add_headers_and_sources(glibc_compatibility .) 38 | add_headers_and_sources(glibc_compatibility musl) 39 | 40 | if (ARCH_ARM) 41 | list (APPEND glibc_compatibility_sources memcpy/memcpy_aarch64.cpp) 42 | list (APPEND glibc_compatibility_sources musl/aarch64/syscall.s musl/aarch64/longjmp.s) 43 | set (musl_arch_include_dir musl/aarch64) 44 | elseif (ARCH_AMD64) 45 | list (APPEND glibc_compatibility_sources memcpy/memcpy_x86_64.cpp) 46 | list (APPEND glibc_compatibility_sources musl/x86_64/syscall.s musl/x86_64/longjmp.s) 47 | set (musl_arch_include_dir musl/x86_64) 48 | else () 49 | message (FATAL_ERROR "glibc_compatibility can only be used on x86_64 or aarch64.") 50 | endif () 51 | 52 | # Need to omit frame pointers to match the performance of glibc 53 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer") 54 | add_library(glibc-compatibility STATIC ${glibc_compatibility_sources}) 55 | target_include_directories(glibc-compatibility PRIVATE ${musl_arch_include_dir}) 56 | target_compile_options(glibc-compatibility PRIVATE -fPIC) 57 | -------------------------------------------------------------------------------- /tfg/stackcollapsers/stackcollapser.py: -------------------------------------------------------------------------------- 1 | """Basic classes and functions for all stack collapsers. 2 | """ 3 | 4 | import re 5 | 6 | 7 | def trim_offset(name): 8 | """_trim_offset(name: str) -> str 9 | Remove address offset from name. 10 | 11 | Example: 12 | some_function+0x42beef -> some_function 13 | """ 14 | return re.sub(r'\+0x[0-9a-fA-F]+$', '', name) 15 | 16 | 17 | class StackCollapserException(Exception): 18 | """Basis stack collapser exception. Used when parse error occured. 19 | """ 20 | pass 21 | 22 | 23 | class StackCollapser(object): 24 | """Basic class for all stack collapsers. 25 | 26 | All derived classes should implement a parse(self) -> list[(list[str], int)] function. 27 | StackCollapser can parse already collapsed stack (see parse()). It's useful when you 28 | already have a file with collapsed stack from previous runs of stackcollapser. 29 | """ 30 | def __init__(self, input_file): 31 | """__init__(self, input_file: file) 32 | """ 33 | self._input_file = input_file 34 | 35 | def parse(self): 36 | """parse(self) -> list[(list[str], int)] 37 | Parse self._input_file. Assume that self._input_file contains already collapsed stack. 38 | 39 | Example input: 40 | kernel`0xffffffff8074d27e;kernel`_sx_xlock 1 41 | kernel`0xffffffff8074d27e;kernel`_sx_xlock_hard 5 42 | kernel`0xffffffff8074d27e;kernel`fork_exit;if_cxgbe.ko`t4_eth_rx 1 43 | 44 | Example output: 45 | [ 46 | (['kernel`0xffffffff8074d27e', 'kernel`_sx_xlock'], 1), 47 | (['kernel`0xffffffff8074d27e', 'kernel`_sx_xlock_hard], 5), 48 | (['kernel`0xffffffff8074d27e', 'kernel`fork_exit', 'if_cxgbe.ko`t4_eth_rx'], 1) 49 | ] 50 | """ 51 | result = list() 52 | for i, line in enumerate([x.strip() for x in self._input_file], 1): 53 | if not line: 54 | continue 55 | # There should be only 2 entries. Example: 56 | # kernel`0xffffffff8074d27e;kernel`_sx_xlock 1 57 | try: 58 | frames, value = line.split() 59 | frames = [trim_offset(n) for n in frames.split(';')] 60 | except ValueError: 61 | raise StackCollapserException('Unable to parse line {}'.format(i)) 62 | result.append((frames, int(value))) 63 | return result 64 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/expf.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */ 2 | /* 3 | * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 4 | */ 5 | /* 6 | * ==================================================== 7 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 8 | * 9 | * Developed at SunPro, a Sun Microsystems, Inc. business. 10 | * Permission to use, copy, modify, and distribute this 11 | * software is freely granted, provided that this notice 12 | * is preserved. 13 | * ==================================================== 14 | */ 15 | 16 | #include "libm.h" 17 | 18 | static const float 19 | half[2] = {0.5,-0.5}, 20 | ln2hi = 6.9314575195e-1f, /* 0x3f317200 */ 21 | ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */ 22 | invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */ 23 | /* 24 | * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: 25 | * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 26 | */ 27 | P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */ 28 | P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */ 29 | 30 | float expf(float x) 31 | { 32 | float_t hi, lo, c, xx, y; 33 | int k, sign; 34 | uint32_t hx; 35 | 36 | GET_FLOAT_WORD(hx, x); 37 | sign = hx >> 31; /* sign bit of x */ 38 | hx &= 0x7fffffff; /* high word of |x| */ 39 | 40 | /* special cases */ 41 | if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */ 42 | if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */ 43 | /* overflow */ 44 | x *= 0x1p127f; 45 | return x; 46 | } 47 | if (sign) { 48 | /* underflow */ 49 | FORCE_EVAL(-0x1p-149f/x); 50 | if (hx >= 0x42cff1b5) /* x <= -103.972084f */ 51 | return 0; 52 | } 53 | } 54 | 55 | /* argument reduction */ 56 | if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ 57 | if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */ 58 | k = invln2*x + half[sign]; 59 | else 60 | k = 1 - sign - sign; 61 | hi = x - k*ln2hi; /* k*ln2hi is exact here */ 62 | lo = k*ln2lo; 63 | x = hi - lo; 64 | } else if (hx > 0x39000000) { /* |x| > 2**-14 */ 65 | k = 0; 66 | hi = x; 67 | lo = 0; 68 | } else { 69 | /* raise inexact */ 70 | FORCE_EVAL(0x1p127f + x); 71 | return 1 + x; 72 | } 73 | 74 | /* x is now in primary range */ 75 | xx = x*x; 76 | c = x - xx*(P1+xx*P2); 77 | y = 1 + (x*c/(2-c) - lo + hi); 78 | if (k == 0) 79 | return y; 80 | return scalbnf(y, k); 81 | } -------------------------------------------------------------------------------- /glibc-compatibility/musl/__polevll.c: -------------------------------------------------------------------------------- 1 | /* origin: OpenBSD /usr/src/lib/libm/src/polevll.c */ 2 | /* 3 | * Copyright (c) 2008 Stephen L. Moshier 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | /* 18 | * Evaluate polynomial 19 | * 20 | * 21 | * SYNOPSIS: 22 | * 23 | * int N; 24 | * long double x, y, coef[N+1], polevl[]; 25 | * 26 | * y = polevll( x, coef, N ); 27 | * 28 | * 29 | * DESCRIPTION: 30 | * 31 | * Evaluates polynomial of degree N: 32 | * 33 | * 2 N 34 | * y = C + C x + C x +...+ C x 35 | * 0 1 2 N 36 | * 37 | * Coefficients are stored in reverse order: 38 | * 39 | * coef[0] = C , ..., coef[N] = C . 40 | * N 0 41 | * 42 | * The function p1evll() assumes that coef[N] = 1.0 and is 43 | * omitted from the array. Its calling arguments are 44 | * otherwise the same as polevll(). 45 | * 46 | * 47 | * SPEED: 48 | * 49 | * In the interest of speed, there are no checks for out 50 | * of bounds arithmetic. This routine is used by most of 51 | * the functions in the library. Depending on available 52 | * equipment features, the user may wish to rewrite the 53 | * program in microcode or assembly language. 54 | * 55 | */ 56 | 57 | #include "libm.h" 58 | 59 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 60 | #else 61 | /* 62 | * Polynomial evaluator: 63 | * P[0] x^n + P[1] x^(n-1) + ... + P[n] 64 | */ 65 | long double __polevll(long double x, const long double *P, int n) 66 | { 67 | long double y; 68 | 69 | y = *P++; 70 | do { 71 | y = y * x + *P++; 72 | } while (--n); 73 | 74 | return y; 75 | } 76 | 77 | /* 78 | * Polynomial evaluator: 79 | * x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] 80 | */ 81 | long double __p1evll(long double x, const long double *P, int n) 82 | { 83 | long double y; 84 | 85 | n -= 1; 86 | y = x + *P++; 87 | do { 88 | y = y * x + *P++; 89 | } while (--n); 90 | 91 | return y; 92 | } 93 | #endif 94 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/vdso.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "syscall.h" 8 | 9 | #ifdef VDSO_USEFUL 10 | 11 | #if ULONG_MAX == 0xffffffff 12 | typedef Elf32_Ehdr Ehdr; 13 | typedef Elf32_Phdr Phdr; 14 | typedef Elf32_Sym Sym; 15 | typedef Elf32_Verdef Verdef; 16 | typedef Elf32_Verdaux Verdaux; 17 | #else 18 | typedef Elf64_Ehdr Ehdr; 19 | typedef Elf64_Phdr Phdr; 20 | typedef Elf64_Sym Sym; 21 | typedef Elf64_Verdef Verdef; 22 | typedef Elf64_Verdaux Verdaux; 23 | #endif 24 | 25 | static int checkver(Verdef *def, int vsym, const char *vername, char *strings) 26 | { 27 | vsym &= 0x7fff; 28 | for (;;) { 29 | if (!(def->vd_flags & VER_FLG_BASE) 30 | && (def->vd_ndx & 0x7fff) == vsym) 31 | break; 32 | if (def->vd_next == 0) 33 | return 0; 34 | def = (Verdef *)((char *)def + def->vd_next); 35 | } 36 | Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux); 37 | return !strcmp(vername, strings + aux->vda_name); 38 | } 39 | 40 | #define OK_TYPES (1<e_phoff); 49 | size_t *dynv=0, base=-1; 50 | for (i=0; ie_phnum; i++, ph=(void *)((char *)ph+eh->e_phentsize)) { 51 | if (ph->p_type == PT_LOAD) 52 | base = (size_t)eh + ph->p_offset - ph->p_vaddr; 53 | else if (ph->p_type == PT_DYNAMIC) 54 | dynv = (void *)((char *)eh + ph->p_offset); 55 | } 56 | if (!dynv || base==(size_t)-1) return 0; 57 | 58 | char *strings = 0; 59 | Sym *syms = 0; 60 | Elf_Symndx *hashtab = 0; 61 | uint16_t *versym = 0; 62 | Verdef *verdef = 0; 63 | 64 | for (i=0; dynv[i]; i+=2) { 65 | void *p = (void *)(base + dynv[i+1]); 66 | switch(dynv[i]) { 67 | case DT_STRTAB: strings = p; break; 68 | case DT_SYMTAB: syms = p; break; 69 | case DT_HASH: hashtab = p; break; 70 | case DT_VERSYM: versym = p; break; 71 | case DT_VERDEF: verdef = p; break; 72 | } 73 | } 74 | 75 | if (!strings || !syms || !hashtab) return 0; 76 | if (!verdef) versym = 0; 77 | 78 | for (i=0; i>4) & OK_BINDS)) continue; 81 | if (!syms[i].st_shndx) continue; 82 | if (strcmp(name, strings+syms[i].st_name)) continue; 83 | if (versym && !checkver(verdef, versym[i], vername, strings)) 84 | continue; 85 | return (void *)(base + syms[i].st_value); 86 | } 87 | 88 | return 0; 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /tfg/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Terminal flame graph. 3 | Parse dtrace, perf, etc. output and display it as a flame graph inside your terminal emulator. 4 | Use arrow keys to navigate around the flame graph. Use 'Enter' key to 'zoom in' to a call frame. 5 | 6 | Python 2 and 3 compatible. 7 | """ 8 | 9 | import argparse 10 | from tfg.calltree.calltree import CallFrameTree 11 | from tfg.stackcollapsers.stackcollapser import StackCollapser 12 | from tfg.stackcollapsers.dtracecollapser import DtraceCollapser 13 | from tfg.stackcollapsers.perfcollapser import PerfCollapser 14 | from tfg.stackcollapsers.pyspycollapser import PySpyCollapser 15 | from tfg.browser.terminal import TerminalBrowser 16 | from tfg.browser.palette import PALETTES 17 | 18 | 19 | COLLAPSERS = { 20 | 'none': StackCollapser, 21 | 'dtrace': DtraceCollapser, 22 | 'perf': PerfCollapser, 23 | 'pyspy': PySpyCollapser, 24 | } 25 | 26 | 27 | def process_args(args): 28 | with open(args.file, 'r') as input_file: 29 | call_tree = CallFrameTree() 30 | collapser = COLLAPSERS[args.file_type](input_file) 31 | stacks = collapser.parse() 32 | for stack in stacks: 33 | call_tree.add_stack(stack[0], stack[1]) 34 | if args.dump: 35 | call_tree.dump() 36 | return 37 | 38 | browser = TerminalBrowser(call_tree, args.ws_filler, PALETTES[args.palette]) 39 | browser.display() 40 | 41 | def main(): 42 | parser = argparse.ArgumentParser(description='Command line flame graph browser') 43 | parser.add_argument('-t', 44 | '--type', 45 | type=str, 46 | dest='file_type', 47 | default='none', 48 | choices=COLLAPSERS.keys(), 49 | help='Input file type') 50 | parser.add_argument('--ws-filler', 51 | type=str, 52 | dest='ws_filler', 53 | default=' ', 54 | help="""Due to a bug (https://bugs.kde.org/show_bug.cgi?id=384620) 55 | some versions of ncurses won't highlight the whitespace properly. 56 | With this whitespace filler option you can specify any other 57 | filler to use (e.g. -)""") 58 | parser.add_argument('-d', '--dump', 59 | dest='dump', 60 | action='store_true', 61 | help='Dump collapsed stacks and quit') 62 | parser.add_argument('-p', 63 | '--palette', 64 | dest='palette', 65 | default='hot', 66 | choices=PALETTES.keys(), 67 | help='Color palette') 68 | parser.add_argument('file', help='Input file to parse') 69 | 70 | process_args(parser.parse_args()) 71 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/clock_gettime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "atomic.h" 5 | #include "syscall.h" 6 | 7 | #ifdef VDSO_CGT_SYM 8 | 9 | static void *volatile vdso_func; 10 | 11 | #ifdef VDSO_CGT32_SYM 12 | static void *volatile vdso_func_32; 13 | static int cgt_time32_wrap(clockid_t clk, struct timespec *ts) 14 | { 15 | long ts32[2]; 16 | int (*f)(clockid_t, long[2]) = 17 | (int (*)(clockid_t, long[2]))vdso_func_32; 18 | int r = f(clk, ts32); 19 | if (!r) { 20 | /* Fallback to syscalls if time32 overflowed. Maybe 21 | * we lucked out and somehow migrated to a kernel with 22 | * time64 syscalls available. */ 23 | if (ts32[0] < 0) { 24 | a_cas_p(&vdso_func, (void *)cgt_time32_wrap, 0); 25 | return -ENOSYS; 26 | } 27 | ts->tv_sec = ts32[0]; 28 | ts->tv_nsec = ts32[1]; 29 | } 30 | return r; 31 | } 32 | #endif 33 | 34 | static int cgt_init(clockid_t clk, struct timespec *ts) 35 | { 36 | void *p = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM); 37 | #ifdef VDSO_CGT32_SYM 38 | if (!p) { 39 | void *q = __vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM); 40 | if (q) { 41 | a_cas_p(&vdso_func_32, 0, q); 42 | p = cgt_time32_wrap; 43 | } 44 | } 45 | #endif 46 | int (*f)(clockid_t, struct timespec *) = 47 | (int (*)(clockid_t, struct timespec *))p; 48 | a_cas_p(&vdso_func, (void *)cgt_init, p); 49 | return f ? f(clk, ts) : -ENOSYS; 50 | } 51 | 52 | static void *volatile vdso_func = (void *)cgt_init; 53 | 54 | #endif 55 | 56 | int clock_gettime(clockid_t clk, struct timespec *ts) 57 | { 58 | int r; 59 | 60 | #ifdef VDSO_CGT_SYM 61 | int (*f)(clockid_t, struct timespec *) = 62 | (int (*)(clockid_t, struct timespec *))vdso_func; 63 | if (f) { 64 | r = f(clk, ts); 65 | if (!r) return r; 66 | if (r == -EINVAL) return __syscall_ret(r); 67 | /* Fall through on errors other than EINVAL. Some buggy 68 | * vdso implementations return ENOSYS for clocks they 69 | * can't handle, rather than making the syscall. This 70 | * also handles the case where cgt_init fails to find 71 | * a vdso function to use. */ 72 | } 73 | #endif 74 | 75 | #ifdef SYS_clock_gettime64 76 | r = -ENOSYS; 77 | if (sizeof(time_t) > 4) 78 | r = __syscall(SYS_clock_gettime64, clk, ts); 79 | if (SYS_clock_gettime == SYS_clock_gettime64 || r!=-ENOSYS) 80 | return __syscall_ret(r); 81 | long ts32[2]; 82 | r = __syscall(SYS_clock_gettime, clk, ts32); 83 | if (r==-ENOSYS && clk==CLOCK_REALTIME) { 84 | r = __syscall(SYS_gettimeofday, ts32, 0); 85 | ts32[1] *= 1000; 86 | } 87 | if (!r) { 88 | ts->tv_sec = ts32[0]; 89 | ts->tv_nsec = ts32[1]; 90 | return r; 91 | } 92 | return __syscall_ret(r); 93 | #else 94 | r = __syscall(SYS_clock_gettime, clk, ts); 95 | if (r == -ENOSYS) { 96 | if (clk == CLOCK_REALTIME) { 97 | __syscall(SYS_gettimeofday, ts, 0); 98 | ts->tv_nsec = (int)ts->tv_nsec * 1000; 99 | return 0; 100 | } 101 | r = -EINVAL; 102 | } 103 | return __syscall_ret(r); 104 | #endif 105 | } 106 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/x86_64/atomic_arch.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define a_cas a_cas 4 | static inline int a_cas(volatile int *p, int t, int s) 5 | { 6 | __asm__ __volatile__ ( 7 | "lock ; cmpxchg %3, %1" 8 | : "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" ); 9 | return t; 10 | } 11 | 12 | #define a_cas_p a_cas_p 13 | static inline void *a_cas_p(volatile void *p, void *t, void *s) 14 | { 15 | __asm__( "lock ; cmpxchg %3, %1" 16 | : "=a"(t), "=m"(*(void *volatile *)p) 17 | : "a"(t), "r"(s) : "memory" ); 18 | return t; 19 | } 20 | 21 | #define a_swap a_swap 22 | static inline int a_swap(volatile int *p, int v) 23 | { 24 | __asm__ __volatile__( 25 | "xchg %0, %1" 26 | : "=r"(v), "=m"(*p) : "0"(v) : "memory" ); 27 | return v; 28 | } 29 | 30 | #define a_fetch_add a_fetch_add 31 | static inline int a_fetch_add(volatile int *p, int v) 32 | { 33 | __asm__ __volatile__( 34 | "lock ; xadd %0, %1" 35 | : "=r"(v), "=m"(*p) : "0"(v) : "memory" ); 36 | return v; 37 | } 38 | 39 | #define a_and a_and 40 | static inline void a_and(volatile int *p, int v) 41 | { 42 | __asm__ __volatile__( 43 | "lock ; and %1, %0" 44 | : "=m"(*p) : "r"(v) : "memory" ); 45 | } 46 | 47 | #define a_or a_or 48 | static inline void a_or(volatile int *p, int v) 49 | { 50 | __asm__ __volatile__( 51 | "lock ; or %1, %0" 52 | : "=m"(*p) : "r"(v) : "memory" ); 53 | } 54 | 55 | #define a_and_64 a_and_64 56 | static inline void a_and_64(volatile uint64_t *p, uint64_t v) 57 | { 58 | __asm__ __volatile( 59 | "lock ; and %1, %0" 60 | : "=m"(*p) : "r"(v) : "memory" ); 61 | } 62 | 63 | #define a_or_64 a_or_64 64 | static inline void a_or_64(volatile uint64_t *p, uint64_t v) 65 | { 66 | __asm__ __volatile__( 67 | "lock ; or %1, %0" 68 | : "=m"(*p) : "r"(v) : "memory" ); 69 | } 70 | 71 | #define a_inc a_inc 72 | static inline void a_inc(volatile int *p) 73 | { 74 | __asm__ __volatile__( 75 | "lock ; incl %0" 76 | : "=m"(*p) : "m"(*p) : "memory" ); 77 | } 78 | 79 | #define a_dec a_dec 80 | static inline void a_dec(volatile int *p) 81 | { 82 | __asm__ __volatile__( 83 | "lock ; decl %0" 84 | : "=m"(*p) : "m"(*p) : "memory" ); 85 | } 86 | 87 | #define a_store a_store 88 | static inline void a_store(volatile int *p, int x) 89 | { 90 | __asm__ __volatile__( 91 | "mov %1, %0 ; lock ; orl $0,(%%rsp)" 92 | : "=m"(*p) : "r"(x) : "memory" ); 93 | } 94 | 95 | #define a_barrier a_barrier 96 | static inline void a_barrier() 97 | { 98 | __asm__ __volatile__( "" : : : "memory" ); 99 | } 100 | 101 | #define a_spin a_spin 102 | static inline void a_spin() 103 | { 104 | __asm__ __volatile__( "pause" : : : "memory" ); 105 | } 106 | 107 | #define a_crash a_crash 108 | static inline void a_crash() 109 | { 110 | __asm__ __volatile__( "hlt" : : : "memory" ); 111 | } 112 | 113 | #define a_ctz_64 a_ctz_64 114 | static inline int a_ctz_64(uint64_t x) 115 | { 116 | __asm__( "bsf %1,%0" : "=r"(x) : "r"(x) ); 117 | return x; 118 | } 119 | 120 | #define a_clz_64 a_clz_64 121 | static inline int a_clz_64(uint64_t x) 122 | { 123 | __asm__( "bsr %1,%0 ; xor $63,%0" : "=r"(x) : "r"(x) ); 124 | return x; 125 | } 126 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/posix_spawn.c: -------------------------------------------------------------------------------- 1 | /// Very limited implementation. Half of code from Musl was cut. 2 | /// This is Ok, because for now, this function is used only from clang driver. 3 | 4 | #define _GNU_SOURCE 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "syscall.h" 17 | 18 | struct args { 19 | int p[2]; 20 | sigset_t oldmask; 21 | const char *path; 22 | int (*exec)(const char *, char *const *, char *const *); 23 | const posix_spawn_file_actions_t *fa; 24 | const posix_spawnattr_t *restrict attr; 25 | char *const *argv, *const *envp; 26 | }; 27 | 28 | void __get_handler_set(sigset_t *); 29 | 30 | static int child(void *args_vp) 31 | { 32 | int ret; 33 | struct args *args = args_vp; 34 | int p = args->p[1]; 35 | const posix_spawnattr_t *restrict attr = args->attr; 36 | 37 | close(args->p[0]); 38 | 39 | /* Close-on-exec flag may have been lost if we moved the pipe 40 | * to a different fd. We don't use F_DUPFD_CLOEXEC above because 41 | * it would fail on older kernels and atomicity is not needed -- 42 | * in this process there are no threads or signal handlers. */ 43 | __syscall(SYS_fcntl, p, F_SETFD, FD_CLOEXEC); 44 | 45 | pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) 46 | ? &attr->__ss : &args->oldmask, 0); 47 | 48 | args->exec(args->path, args->argv, args->envp); 49 | ret = -errno; 50 | 51 | /* Since sizeof errno < PIPE_BUF, the write is atomic. */ 52 | ret = -ret; 53 | if (ret) while (__syscall(SYS_write, p, &ret, sizeof ret) < 0); 54 | _exit(127); 55 | } 56 | 57 | 58 | int __posix_spawnx(pid_t *restrict res, const char *restrict path, 59 | int (*exec)(const char *, char *const *, char *const *), 60 | const posix_spawn_file_actions_t *fa, 61 | const posix_spawnattr_t *restrict attr, 62 | char *const argv[restrict], char *const envp[restrict]) 63 | { 64 | pid_t pid; 65 | char stack[1024]; 66 | int ec=0, cs; 67 | struct args args; 68 | 69 | if (pipe2(args.p, O_CLOEXEC)) 70 | return errno; 71 | 72 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 73 | 74 | args.path = path; 75 | args.exec = exec; 76 | args.fa = fa; 77 | args.attr = attr ? attr : &(const posix_spawnattr_t){0}; 78 | args.argv = argv; 79 | args.envp = envp; 80 | 81 | pid = clone(child, stack+sizeof stack, 82 | CLONE_VM|CLONE_VFORK|SIGCHLD, &args); 83 | close(args.p[1]); 84 | 85 | if (pid > 0) { 86 | if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0; 87 | else waitpid(pid, &(int){0}, 0); 88 | } else { 89 | ec = -pid; 90 | } 91 | 92 | close(args.p[0]); 93 | 94 | if (!ec && res) *res = pid; 95 | 96 | pthread_setcancelstate(cs, 0); 97 | 98 | return ec; 99 | } 100 | 101 | int posix_spawn(pid_t *restrict res, const char *restrict path, 102 | const posix_spawn_file_actions_t *fa, 103 | const posix_spawnattr_t *restrict attr, 104 | char *const argv[restrict], char *const envp[restrict]) 105 | { 106 | return __posix_spawnx(res, path, execve, fa, attr, argv, envp); 107 | } 108 | -------------------------------------------------------------------------------- /tfg/stackcollapsers/perfcollapser.py: -------------------------------------------------------------------------------- 1 | """Perf stack collapser. Used to collapse stacks produced by 'perf script' tool. 2 | Perf script output example: 3 | 4 | init 1 [002] 4042688.470566: 454356 cycles: 5 | 5028bd intel_idle (/usr/lib/debug/lib/modules/2.6.32-696.23.1.el6.x86_64/vmlinux) 6 | 64a99e cpuidle_idle_call (/usr/lib/debug/lib/modules/2.6.32-696.23.1.el6.x86_64/vmlinux) 7 | 209fc9 cpu_idle (/usr/lib/debug/lib/modules/2.6.32-696.23.1.el6.x86_64/vmlinux) 8 | 74c25b start_secondary (/usr/lib/debug/lib/modules/2.6.32-696.23.1.el6.x86_64/vmlinux) 9 | 10 | ... 11 | 12 | Read more here: https://github.com/brendangregg/FlameGraph/blob/master/stackcollapse-perf.pl 13 | """ 14 | 15 | from itertools import takewhile 16 | from tfg.stackcollapsers.stackcollapser import StackCollapser, StackCollapserException, trim_offset 17 | 18 | class PerfCollapser(StackCollapser): 19 | def __init__(self, input_file): 20 | """__init__(self, input_file: file) 21 | """ 22 | super(PerfCollapser, self).__init__(input_file) 23 | 24 | def parse(self): 25 | """parse(self) -> list[(list[str], int)] 26 | """ 27 | result = [] 28 | stack = [] 29 | comm = '' 30 | for i, line in enumerate([x.strip() for x in self._input_file], 1): 31 | if not line: 32 | if comm: # If line is empty and we have a comm name 33 | stack.append(comm) 34 | result.append((stack[::-1], 1)) 35 | stack = [] 36 | comm = '' 37 | continue 38 | 39 | fields = line.split() 40 | if len(fields) > 3: 41 | comm = extract_comm(fields) 42 | if not comm: 43 | raise StackCollapserException('Failed to parse line {}'.format(i)) 44 | else: 45 | try: 46 | stack.append(trim_offset(extract_stack_name(fields))) 47 | except IndexError: 48 | raise StackCollapserException('Failed to parse line {}'.format(i)) 49 | return result 50 | 51 | def extract_comm(fields): 52 | """_extract_comm(self, fields: list[str]) -> str 53 | Extract a command name (commonly used as 'comm') from fields 54 | 55 | Examples: 56 | ['Web', '123', 'cycles:'] -> Web 57 | ['Google', 'Chrome', '321', 'cycles:'] -> Google_Chrome 58 | """ 59 | return '_'.join(takewhile(lambda x: not x.isdigit(), fields)) 60 | 61 | def extract_stack_name(fields): 62 | """_extract_stack_name(self, fields: list[str]) -> str 63 | Extract a stack name from the fields 64 | 65 | Examples: 66 | ffffffff818244f2 [unknown] ([kernel.kallsyms]) -> [kernel.kallsyms] 67 | 1094d __GI___libc_recvmsg (/lib/x86_64-linux-gnu/libpthread-2.23.so) -> __GI__libc_recvmsg 68 | 69 | """ 70 | if fields[1] == '[unknown]': 71 | return to_module_name(fields[2][1:-1]) 72 | return fields[1] 73 | 74 | def to_module_name(field): 75 | """_to_module_name(self, field: str) -> str 76 | Convert module name to match syntax used in https://github.com/brendangregg/FlameGraph 77 | 78 | Examples: 79 | [unknown] -> [unknown]' 80 | /usr/bin/firefox -> [firefox] 81 | """ 82 | if field != '[unknown]': 83 | field = '[{}]'.format(field.split('/')[-1]) 84 | return field 85 | -------------------------------------------------------------------------------- /tfg/browser/palette.py: -------------------------------------------------------------------------------- 1 | """Palette for terminal browser. 2 | 3 | Note: if you're sure that yor terminal emulator supports 256 colors but 4 | flame graph colors seem to be off, you could try set $TERM to "xterm-256color". 5 | """ 6 | 7 | import curses 8 | from itertools import cycle, chain 9 | 10 | 11 | class Palette(object): 12 | """Palette for terminal browser. 13 | Provides gradient generator to infinitely cycle around available colors. 14 | In additional to that, provides lighter and darker colors (compared to 15 | gradient colors). 16 | Supports terminal emulator with [8, 256] colors. 17 | """ 18 | HOT = 0 19 | IO = 1 20 | WAKEUP = 2 21 | CHAIN = 3 22 | 23 | def __init__(self, palette): 24 | self._pairs = None 25 | self._lighter = 0 26 | self._normal = 0 27 | self._darker = 0 28 | if curses.COLORS == 256: 29 | self._init_256(palette) 30 | elif curses.COLORS >= 8: 31 | self._init_8(palette) 32 | else: 33 | raise RuntimeError('Terminal only supports {} colors but at least 8 is required.' 34 | .format(curses.COLOR_PAIRS)) 35 | 36 | def _init_256(self, palette): 37 | """Initialize palette for 256-colors terminals 38 | """ 39 | if palette == Palette.HOT: 40 | self._init_pairs([226, 220, 214, 208, 202], 228, 214, 130) 41 | elif palette == Palette.IO: 42 | self._init_pairs([45, 39, 33, 27, 21], 86, 33, 21) 43 | else: 44 | raise RuntimeError('Unknown color palette {}'.format(palette)) 45 | 46 | def _init_8(self, palette): 47 | """Initialize palette for 8-colors terminals 48 | """ 49 | if palette == Palette.HOT: 50 | self._init_pairs([curses.COLOR_RED, curses.COLOR_YELLOW], 51 | curses.COLOR_GREEN, curses.COLOR_YELLOW, curses.COLOR_BLUE) 52 | elif palette == Palette.IO: 53 | self._init_pairs([curses.COLOR_BLUE, curses.COLOR_CYAN], 54 | curses.COLOR_GREEN, curses.COLOR_BLUE, curses.COLOR_MAGENTA) 55 | else: 56 | raise RuntimeError('Unknown color palette {}'.format(palette)) 57 | 58 | def gradient(self): 59 | """Infinitely colors generator 60 | """ 61 | for i in cycle(chain(self._pairs, self._pairs[1:-1][::-1])): 62 | yield curses.color_pair(i) 63 | 64 | @property 65 | def lighter(self): 66 | return curses.color_pair(self._lighter) 67 | 68 | @property 69 | def normal(self): 70 | return curses.color_pair(self._normal) 71 | 72 | @property 73 | def darker(self): 74 | return curses.color_pair(self._darker) 75 | 76 | def _init_pairs(self, gradient_list, light_color, normal_color, dark_color): 77 | self._pairs = [] 78 | for i, color in enumerate(gradient_list): 79 | curses.init_pair(i + 1, curses.COLOR_BLACK, color) 80 | self._pairs.append(i + 1) 81 | self._lighter = len(self._pairs) + 1 82 | self._normal = self._lighter + 1 83 | self._darker = self._normal + 1 84 | curses.init_pair(self._lighter, curses.COLOR_BLACK, light_color) 85 | curses.init_pair(self._normal, curses.COLOR_BLACK, normal_color) 86 | curses.init_pair(self._darker, curses.COLOR_BLACK, dark_color) 87 | 88 | 89 | PALETTES = { 90 | 'hot': Palette.HOT, 91 | 'io': Palette.IO, 92 | 'wakeup': Palette.WAKEUP, 93 | 'chain': Palette.CHAIN, 94 | } 95 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Double-precision log(x) function. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "log_data.h" 12 | 13 | #define T __log_data.tab 14 | #define T2 __log_data.tab2 15 | #define B __log_data.poly1 16 | #define A __log_data.poly 17 | #define Ln2hi __log_data.ln2hi 18 | #define Ln2lo __log_data.ln2lo 19 | #define N (1 << LOG_TABLE_BITS) 20 | #define OFF 0x3fe6000000000000 21 | 22 | /* Top 16 bits of a double. */ 23 | static inline uint32_t top16(double x) 24 | { 25 | return asuint64(x) >> 48; 26 | } 27 | 28 | double log(double x) 29 | { 30 | double_t w, z, r, r2, r3, y, invc, logc, kd, hi, lo; 31 | uint64_t ix, iz, tmp; 32 | uint32_t top; 33 | int k, i; 34 | 35 | ix = asuint64(x); 36 | top = top16(x); 37 | #define LO asuint64(1.0 - 0x1p-4) 38 | #define HI asuint64(1.0 + 0x1.09p-4) 39 | if (predict_false(ix - LO < HI - LO)) { 40 | /* Handle close to 1.0 inputs separately. */ 41 | /* Fix sign of zero with downward rounding when x==1. */ 42 | if (WANT_ROUNDING && predict_false(ix == asuint64(1.0))) 43 | return 0; 44 | r = x - 1.0; 45 | r2 = r * r; 46 | r3 = r * r2; 47 | y = r3 * 48 | (B[1] + r * B[2] + r2 * B[3] + 49 | r3 * (B[4] + r * B[5] + r2 * B[6] + 50 | r3 * (B[7] + r * B[8] + r2 * B[9] + r3 * B[10]))); 51 | /* Worst-case error is around 0.507 ULP. */ 52 | w = r * 0x1p27; 53 | double_t rhi = r + w - w; 54 | double_t rlo = r - rhi; 55 | w = rhi * rhi * B[0]; /* B[0] == -0.5. */ 56 | hi = r + w; 57 | lo = r - hi + w; 58 | lo += B[0] * rlo * (rhi + r); 59 | y += lo; 60 | y += hi; 61 | return eval_as_double(y); 62 | } 63 | if (predict_false(top - 0x0010 >= 0x7ff0 - 0x0010)) { 64 | /* x < 0x1p-1022 or inf or nan. */ 65 | if (ix * 2 == 0) 66 | return __math_divzero(1); 67 | if (ix == asuint64(INFINITY)) /* log(inf) == inf. */ 68 | return x; 69 | if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0) 70 | return __math_invalid(x); 71 | /* x is subnormal, normalize it. */ 72 | ix = asuint64(x * 0x1p52); 73 | ix -= 52ULL << 52; 74 | } 75 | 76 | /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. 77 | The range is split into N subintervals. 78 | The ith subinterval contains z and c is near its center. */ 79 | tmp = ix - OFF; 80 | i = (tmp >> (52 - LOG_TABLE_BITS)) % N; 81 | k = (int64_t)tmp >> 52; /* arithmetic shift */ 82 | iz = ix - (tmp & 0xfffULL << 52); 83 | invc = T[i].invc; 84 | logc = T[i].logc; 85 | z = asdouble(iz); 86 | 87 | /* log(x) = log1p(z/c-1) + log(c) + k*Ln2. */ 88 | /* r ~= z/c - 1, |r| < 1/(2*N). */ 89 | #if __FP_FAST_FMA 90 | /* rounding error: 0x1p-55/N. */ 91 | r = __builtin_fma(z, invc, -1.0); 92 | #else 93 | /* rounding error: 0x1p-55/N + 0x1p-66. */ 94 | r = (z - T2[i].chi - T2[i].clo) * invc; 95 | #endif 96 | kd = (double_t)k; 97 | 98 | /* hi + lo = r + log(c) + k*Ln2. */ 99 | w = kd * Ln2hi + logc; 100 | hi = w + r; 101 | lo = w - hi + r + kd * Ln2lo; 102 | 103 | /* log(x) = lo + (log1p(r) - r) + hi. */ 104 | r2 = r * r; /* rounding error: 0x1p-54/N^2. */ 105 | /* Worst case error if |y| > 0x1p-5: 106 | 0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma) 107 | Worst case error if |y| > 0x1p-4: 108 | 0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma). */ 109 | y = lo + r2 * A[0] + 110 | r * r2 * (A[1] + r * A[2] + r2 * (A[3] + r * A[4])) + hi; 111 | return eval_as_double(y); 112 | } 113 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/strsignal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if (SIGHUP == 1) && (SIGINT == 2) && (SIGQUIT == 3) && (SIGILL == 4) \ 5 | && (SIGTRAP == 5) && (SIGABRT == 6) && (SIGBUS == 7) && (SIGFPE == 8) \ 6 | && (SIGKILL == 9) && (SIGUSR1 == 10) && (SIGSEGV == 11) && (SIGUSR2 == 12) \ 7 | && (SIGPIPE == 13) && (SIGALRM == 14) && (SIGTERM == 15) && (SIGSTKFLT == 16) \ 8 | && (SIGCHLD == 17) && (SIGCONT == 18) && (SIGSTOP == 19) && (SIGTSTP == 20) \ 9 | && (SIGTTIN == 21) && (SIGTTOU == 22) && (SIGURG == 23) && (SIGXCPU == 24) \ 10 | && (SIGXFSZ == 25) && (SIGVTALRM == 26) && (SIGPROF == 27) && (SIGWINCH == 28) \ 11 | && (SIGPOLL == 29) && (SIGPWR == 30) && (SIGSYS == 31) 12 | 13 | #define sigmap(x) x 14 | 15 | #else 16 | 17 | static const char map[] = { 18 | [SIGHUP] = 1, 19 | [SIGINT] = 2, 20 | [SIGQUIT] = 3, 21 | [SIGILL] = 4, 22 | [SIGTRAP] = 5, 23 | [SIGABRT] = 6, 24 | [SIGBUS] = 7, 25 | [SIGFPE] = 8, 26 | [SIGKILL] = 9, 27 | [SIGUSR1] = 10, 28 | [SIGSEGV] = 11, 29 | [SIGUSR2] = 12, 30 | [SIGPIPE] = 13, 31 | [SIGALRM] = 14, 32 | [SIGTERM] = 15, 33 | #if defined(SIGSTKFLT) 34 | [SIGSTKFLT] = 16, 35 | #elif defined(SIGEMT) 36 | [SIGEMT] = 16, 37 | #endif 38 | [SIGCHLD] = 17, 39 | [SIGCONT] = 18, 40 | [SIGSTOP] = 19, 41 | [SIGTSTP] = 20, 42 | [SIGTTIN] = 21, 43 | [SIGTTOU] = 22, 44 | [SIGURG] = 23, 45 | [SIGXCPU] = 24, 46 | [SIGXFSZ] = 25, 47 | [SIGVTALRM] = 26, 48 | [SIGPROF] = 27, 49 | [SIGWINCH] = 28, 50 | [SIGPOLL] = 29, 51 | [SIGPWR] = 30, 52 | [SIGSYS] = 31 53 | }; 54 | 55 | #define sigmap(x) ((x) >= sizeof map ? (x) : map[(x)]) 56 | 57 | #endif 58 | 59 | static const char strings[] = 60 | "Unknown signal\0" 61 | "Hangup\0" 62 | "Interrupt\0" 63 | "Quit\0" 64 | "Illegal instruction\0" 65 | "Trace/breakpoint trap\0" 66 | "Aborted\0" 67 | "Bus error\0" 68 | "Arithmetic exception\0" 69 | "Killed\0" 70 | "User defined signal 1\0" 71 | "Segmentation fault\0" 72 | "User defined signal 2\0" 73 | "Broken pipe\0" 74 | "Alarm clock\0" 75 | "Terminated\0" 76 | #if defined(SIGSTKFLT) 77 | "Stack fault\0" 78 | #elif defined(SIGEMT) 79 | "Emulator trap\0" 80 | #else 81 | "Unknown signal\0" 82 | #endif 83 | "Child process status\0" 84 | "Continued\0" 85 | "Stopped (signal)\0" 86 | "Stopped\0" 87 | "Stopped (tty input)\0" 88 | "Stopped (tty output)\0" 89 | "Urgent I/O condition\0" 90 | "CPU time limit exceeded\0" 91 | "File size limit exceeded\0" 92 | "Virtual timer expired\0" 93 | "Profiling timer expired\0" 94 | "Window changed\0" 95 | "I/O possible\0" 96 | "Power failure\0" 97 | "Bad system call\0" 98 | "RT32" 99 | "\0RT33\0RT34\0RT35\0RT36\0RT37\0RT38\0RT39\0RT40" 100 | "\0RT41\0RT42\0RT43\0RT44\0RT45\0RT46\0RT47\0RT48" 101 | "\0RT49\0RT50\0RT51\0RT52\0RT53\0RT54\0RT55\0RT56" 102 | "\0RT57\0RT58\0RT59\0RT60\0RT61\0RT62\0RT63\0RT64" 103 | #if _NSIG > 65 104 | "\0RT65\0RT66\0RT67\0RT68\0RT69\0RT70\0RT71\0RT72" 105 | "\0RT73\0RT74\0RT75\0RT76\0RT77\0RT78\0RT79\0RT80" 106 | "\0RT81\0RT82\0RT83\0RT84\0RT85\0RT86\0RT87\0RT88" 107 | "\0RT89\0RT90\0RT91\0RT92\0RT93\0RT94\0RT95\0RT96" 108 | "\0RT97\0RT98\0RT99\0RT100\0RT101\0RT102\0RT103\0RT104" 109 | "\0RT105\0RT106\0RT107\0RT108\0RT109\0RT110\0RT111\0RT112" 110 | "\0RT113\0RT114\0RT115\0RT116\0RT117\0RT118\0RT119\0RT120" 111 | "\0RT121\0RT122\0RT123\0RT124\0RT125\0RT126\0RT127\0RT128" 112 | #endif 113 | ""; 114 | 115 | char *strsignal(int signum) 116 | { 117 | const char *s = strings; 118 | 119 | signum = sigmap(signum); 120 | if (signum - 1U >= _NSIG-1) signum = 0; 121 | 122 | for (; signum--; s++) for (; *s; s++); 123 | 124 | return (char *)s; 125 | } 126 | -------------------------------------------------------------------------------- /tfg/calltree/calltree.py: -------------------------------------------------------------------------------- 1 | """Call frames stack represenation as a tree. 2 | """ 3 | 4 | class CallFrameNode(object): 5 | """Stack frame node. 6 | Represent a single stack frame. 7 | 8 | name - original stack frame name. 9 | frames - children stack frames. 10 | base_count - original sample count for the this node. 11 | count - samle count for all children. Useful to calculate the 'weight' of the node. 12 | """ 13 | 14 | def __init__(self, name, frames=None, base_count=0, count=0, parent=None): 15 | """__init__(self, name: str, frames: list[CallFrameNode], base_count: int, count: int) 16 | """ 17 | self.name = name 18 | if frames is None: 19 | self.frames = [] 20 | else: 21 | self.frames = frames[:] 22 | self.base_count = base_count 23 | self.count = count 24 | self.parent = parent 25 | 26 | def __repr__(self): 27 | return 'CallFrameNode(name={}, base_count={}, count={})'.format( 28 | self.name, self.base_count, self.count) 29 | 30 | 31 | class CallFrameTree(object): 32 | """Tree based representation of call frames. 33 | By default CallFrameTree consist of only one 'all' (head) node. 34 | add_stack() function should be used to add additional frames to the tree. 35 | It will create nodes for all frames (if needed) and will calculate sample 36 | count for each of them. 37 | 38 | Example: 39 | frames1 = ['main', 'foo', 'bar'] 40 | frames2 = ['main', 'foo', 'panic'] 41 | 42 | Calling add_stack(): 43 | add_stack(frames1, 1) 44 | add_stack(frames2, 1) 45 | will result in the following tree structure: 46 | 47 | 'all' -> 'main' -> 'foo' -> 'bar' 48 | | 49 | -----> 'panic' 50 | """ 51 | def __init__(self): 52 | self._head = CallFrameNode('all') 53 | 54 | def add_stack(self, frames, count): 55 | """add_stack(self, frames: list[str], count: int) 56 | Add frames to the tree with sample count. 57 | """ 58 | self._head.count += count 59 | self._insert_frame(self._head, frames, count) 60 | 61 | @property 62 | def head(self): 63 | """Head node. 64 | """ 65 | return self._head 66 | 67 | def dump(self): 68 | """Dump tree to stdout. 69 | This should produce the same output as any stackcollapse*.pl from 70 | https://github.com/brendangregg/FlameGraph. 71 | """ 72 | self._dump(self._head, []) 73 | 74 | def _dump(self, cf, callstack): 75 | # Only original top call frames have base_count > 0 76 | if cf.base_count > 0: 77 | print('{} {}'.format(';'.join(f.name for f in callstack), cf.base_count)) 78 | for child_cf in cf.frames: 79 | callstack.append(child_cf) 80 | self._dump(child_cf, callstack) 81 | callstack.pop() 82 | 83 | def _insert_frame(self, start_frame, frames, count): 84 | if not frames: 85 | return 86 | frame = self._get_or_create_frame(start_frame, frames) 87 | frame.count += count 88 | # Save the original base_count 89 | if len(frames) == 1: 90 | frame.base_count += count 91 | self._insert_frame(frame, frames[1:], count) 92 | 93 | def _get_or_create_frame(self, start_frame, frames): 94 | for frame in start_frame.frames: 95 | if frame.name == frames[0]: 96 | return frame 97 | else: 98 | start_frame.frames.append(CallFrameNode(frames[0], parent=start_frame)) 99 | return start_frame.frames[-1] 100 | -------------------------------------------------------------------------------- /setup_toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | verbose=false 6 | old_abi=false 7 | 8 | help_message="Usage: $0 [OPTIONS] 9 | Options: 10 | -h, --help Display this help message and exit. 11 | -v, --verbose Enable verbose mode. 12 | -o, --old-abi Use old ABI (Application Binary Interface)." 13 | 14 | while getopts ":hvo" opt; do 15 | case $opt in 16 | h) 17 | echo "$help_message" 18 | exit 0 19 | ;; 20 | v) 21 | verbose=true 22 | ;; 23 | o) 24 | old_abi=true 25 | ;; 26 | \?) 27 | echo "Invalid option: -$OPTARG" >&2 28 | exit 1 29 | ;; 30 | esac 31 | done 32 | 33 | shift $((OPTIND -1)) 34 | 35 | if [ -z "$1" ]; then 36 | echo "$help_message" 37 | exit 1 38 | fi 39 | 40 | dir=$1 41 | 42 | if [[ ! "$dir" = "/"* ]]; then 43 | echo "toolchain_dir should be an absolute PATH" 44 | exit 1 45 | fi 46 | 47 | if [[ -e "$dir" ]]; then 48 | echo "$dir already exists" 49 | exit 1 50 | fi 51 | 52 | prefix=$(dirname "$dir") 53 | 54 | tmpdir=$(mktemp -p "$prefix" -d -q -t ".ldb_toolchain_XXXXXX") 55 | 56 | if [ ! $? -eq 0 ]; then 57 | echo "Cannot create directory under $prefix." 58 | exit 1 59 | fi 60 | 61 | trap "rm -rf -- '$tmpdir'" EXIT 62 | 63 | sed '0,/^#EOF#$/d' "$0" | tar zx --strip-components=1 -C "$tmpdir" 64 | 65 | mv "$tmpdir" "$dir" 66 | chmod a+rx "$dir" 67 | 68 | cd "$dir" 69 | interpreter="" 70 | if [ "${ARCH}" == "x86_64" ]; then 71 | interpreter="$dir/lib/ld-linux-x86-64.so.2" 72 | elif [ "${ARCH}" == "aarch64" ]; then 73 | interpreter="$dir/lib/ld-linux-aarch64.so.1" 74 | else 75 | echo "Unknown architecture: ${ARCH}" >&2 76 | exit 1 77 | fi 78 | for f in bin/* 79 | do 80 | bin/patchelf --set-interpreter "$interpreter" --set-rpath '$ORIGIN/../lib' "$f" &> /dev/null || true 81 | done 82 | 83 | for f in tmp/gentoo/bin/* 84 | do 85 | bin/patchelf --set-interpreter "$interpreter" --set-rpath '$ORIGIN/../../../lib' "$f" &> /dev/null || true 86 | done 87 | 88 | for f in tmp/gentoo/llvm/bin/* 89 | do 90 | bin/patchelf --set-interpreter "$interpreter" --set-rpath '$ORIGIN/../../../../lib' "$f" &> /dev/null || true 91 | done 92 | 93 | for f in cc1 cc1plus collect2 g++-mapper-server lto1 lto-wrapper 94 | do 95 | bin/patchelf --set-interpreter "$interpreter" --set-rpath '$ORIGIN/../../../../lib' "libexec/gcc/${TRIPLE}/${GCC_VERSION}/$f" &> /dev/null || true 96 | done 97 | 98 | bin/patchelf --set-rpath '$ORIGIN/../../../../lib' "libexec/gcc/${TRIPLE}/${GCC_VERSION}/liblto_plugin.so" &> /dev/null || true 99 | 100 | for c in clang clang++ gcc g++ 101 | do 102 | if $old_abi; then 103 | sed -i "s//-no-pie -D_GLIBCXX_USE_CXX11_ABI=0/" bin/$c 104 | else 105 | sed -i "s///" bin/$c 106 | fi 107 | done 108 | 109 | if ! bin/gcc test/a.c -o test/a; then 110 | echo "Generated toolchain (gcc) cannot compile a simple program." 111 | echo "Please file an issue at https://github.com/amosbird/ldb_toolchain_gen/issues with current setup information." 112 | exit 1 113 | fi 114 | 115 | if ! bin/clang test/a.c -o test/a; then 116 | echo "Generated toolchain (clang) cannot compile a simple program." 117 | echo "Please file an issue at https://github.com/amosbird/ldb_toolchain_gen/issues with current setup information." 118 | exit 1 119 | fi 120 | 121 | echo "Congratulations! LDB toolchain is setup at $dir. export PATH=\"$dir/bin\":\$PATH to take full advantage." 122 | # JDK and Maven are too large 123 | # echo "NOTE: openjdk and apache-maven are also provided under $dir" 124 | echo "NOTE: LDB toolchain cannot be relocated to other directories manually. Instead, generate it again using $0" 125 | 126 | exit 0 127 | 128 | #EOF# 129 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Double-precision log2(x) function. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "log2_data.h" 12 | 13 | #define T __log2_data.tab 14 | #define T2 __log2_data.tab2 15 | #define B __log2_data.poly1 16 | #define A __log2_data.poly 17 | #define InvLn2hi __log2_data.invln2hi 18 | #define InvLn2lo __log2_data.invln2lo 19 | #define N (1 << LOG2_TABLE_BITS) 20 | #define OFF 0x3fe6000000000000 21 | 22 | /* Top 16 bits of a double. */ 23 | static inline uint32_t top16(double x) 24 | { 25 | return asuint64(x) >> 48; 26 | } 27 | 28 | double log2(double x) 29 | { 30 | double_t z, r, r2, r4, y, invc, logc, kd, hi, lo, t1, t2, t3, p; 31 | uint64_t ix, iz, tmp; 32 | uint32_t top; 33 | int k, i; 34 | 35 | ix = asuint64(x); 36 | top = top16(x); 37 | #define LO asuint64(1.0 - 0x1.5b51p-5) 38 | #define HI asuint64(1.0 + 0x1.6ab2p-5) 39 | if (predict_false(ix - LO < HI - LO)) { 40 | /* Handle close to 1.0 inputs separately. */ 41 | /* Fix sign of zero with downward rounding when x==1. */ 42 | if (WANT_ROUNDING && predict_false(ix == asuint64(1.0))) 43 | return 0; 44 | r = x - 1.0; 45 | #if __FP_FAST_FMA 46 | hi = r * InvLn2hi; 47 | lo = r * InvLn2lo + __builtin_fma(r, InvLn2hi, -hi); 48 | #else 49 | double_t rhi, rlo; 50 | rhi = asdouble(asuint64(r) & -1ULL << 32); 51 | rlo = r - rhi; 52 | hi = rhi * InvLn2hi; 53 | lo = rlo * InvLn2hi + r * InvLn2lo; 54 | #endif 55 | r2 = r * r; /* rounding error: 0x1p-62. */ 56 | r4 = r2 * r2; 57 | /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma). */ 58 | p = r2 * (B[0] + r * B[1]); 59 | y = hi + p; 60 | lo += hi - y + p; 61 | lo += r4 * (B[2] + r * B[3] + r2 * (B[4] + r * B[5]) + 62 | r4 * (B[6] + r * B[7] + r2 * (B[8] + r * B[9]))); 63 | y += lo; 64 | return eval_as_double(y); 65 | } 66 | if (predict_false(top - 0x0010 >= 0x7ff0 - 0x0010)) { 67 | /* x < 0x1p-1022 or inf or nan. */ 68 | if (ix * 2 == 0) 69 | return __math_divzero(1); 70 | if (ix == asuint64(INFINITY)) /* log(inf) == inf. */ 71 | return x; 72 | if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0) 73 | return __math_invalid(x); 74 | /* x is subnormal, normalize it. */ 75 | ix = asuint64(x * 0x1p52); 76 | ix -= 52ULL << 52; 77 | } 78 | 79 | /* x = 2^k z; where z is in range [OFF,2*OFF) and exact. 80 | The range is split into N subintervals. 81 | The ith subinterval contains z and c is near its center. */ 82 | tmp = ix - OFF; 83 | i = (tmp >> (52 - LOG2_TABLE_BITS)) % N; 84 | k = (int64_t)tmp >> 52; /* arithmetic shift */ 85 | iz = ix - (tmp & 0xfffULL << 52); 86 | invc = T[i].invc; 87 | logc = T[i].logc; 88 | z = asdouble(iz); 89 | kd = (double_t)k; 90 | 91 | /* log2(x) = log2(z/c) + log2(c) + k. */ 92 | /* r ~= z/c - 1, |r| < 1/(2*N). */ 93 | #if __FP_FAST_FMA 94 | /* rounding error: 0x1p-55/N. */ 95 | r = __builtin_fma(z, invc, -1.0); 96 | t1 = r * InvLn2hi; 97 | t2 = r * InvLn2lo + __builtin_fma(r, InvLn2hi, -t1); 98 | #else 99 | double_t rhi, rlo; 100 | /* rounding error: 0x1p-55/N + 0x1p-65. */ 101 | r = (z - T2[i].chi - T2[i].clo) * invc; 102 | rhi = asdouble(asuint64(r) & -1ULL << 32); 103 | rlo = r - rhi; 104 | t1 = rhi * InvLn2hi; 105 | t2 = rlo * InvLn2hi + r * InvLn2lo; 106 | #endif 107 | 108 | /* hi + lo = r/ln2 + log2(c) + k. */ 109 | t3 = kd + logc; 110 | hi = t3 + t1; 111 | lo = t3 - hi + t1 + t2; 112 | 113 | /* log2(r+1) = r/ln2 + r^2*poly(r). */ 114 | /* Evaluation is optimized assuming superscalar pipelined execution. */ 115 | r2 = r * r; /* rounding error: 0x1p-54/N^2. */ 116 | r4 = r2 * r2; 117 | /* Worst-case error if |y| > 0x1p-4: 0.547 ULP (0.550 ULP without fma). 118 | ~ 0.5 + 2/N/ln2 + abs-poly-error*0x1p56 ULP (+ 0.003 ULP without fma). */ 119 | p = A[0] + r * A[1] + r2 * (A[2] + r * A[3]) + r4 * (A[4] + r * A[5]); 120 | y = lo + r2 * p + hi; 121 | return eval_as_double(y); 122 | } 123 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Double-precision 2^x function. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "exp_data.h" 12 | 13 | #define N (1 << EXP_TABLE_BITS) 14 | #define Shift __exp_data.exp2_shift 15 | #define T __exp_data.tab 16 | #define C1 __exp_data.exp2_poly[0] 17 | #define C2 __exp_data.exp2_poly[1] 18 | #define C3 __exp_data.exp2_poly[2] 19 | #define C4 __exp_data.exp2_poly[3] 20 | #define C5 __exp_data.exp2_poly[4] 21 | 22 | /* Handle cases that may overflow or underflow when computing the result that 23 | is scale*(1+TMP) without intermediate rounding. The bit representation of 24 | scale is in SBITS, however it has a computed exponent that may have 25 | overflown into the sign bit so that needs to be adjusted before using it as 26 | a double. (int32_t)KI is the k used in the argument reduction and exponent 27 | adjustment of scale, positive k here means the result may overflow and 28 | negative k means the result may underflow. */ 29 | static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) 30 | { 31 | double_t scale, y; 32 | 33 | if ((ki & 0x80000000) == 0) { 34 | /* k > 0, the exponent of scale might have overflowed by 1. */ 35 | sbits -= 1ull << 52; 36 | scale = asdouble(sbits); 37 | y = 2 * (scale + scale * tmp); 38 | return eval_as_double(y); 39 | } 40 | /* k < 0, need special care in the subnormal range. */ 41 | sbits += 1022ull << 52; 42 | scale = asdouble(sbits); 43 | y = scale + scale * tmp; 44 | if (y < 1.0) { 45 | /* Round y to the right precision before scaling it into the subnormal 46 | range to avoid double rounding that can cause 0.5+E/2 ulp error where 47 | E is the worst-case ulp error outside the subnormal range. So this 48 | is only useful if the goal is better than 1 ulp worst-case error. */ 49 | double_t hi, lo; 50 | lo = scale - y + scale * tmp; 51 | hi = 1.0 + y; 52 | lo = 1.0 - hi + y + lo; 53 | y = eval_as_double(hi + lo) - 1.0; 54 | /* Avoid -0.0 with downward rounding. */ 55 | if (WANT_ROUNDING && y == 0.0) 56 | y = 0.0; 57 | /* The underflow exception needs to be signaled explicitly. */ 58 | fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); 59 | } 60 | y = 0x1p-1022 * y; 61 | return eval_as_double(y); 62 | } 63 | 64 | /* Top 12 bits of a double (sign and exponent bits). */ 65 | static inline uint32_t top12(double x) 66 | { 67 | return asuint64(x) >> 52; 68 | } 69 | 70 | double exp2(double x) 71 | { 72 | uint32_t abstop; 73 | uint64_t ki, idx, top, sbits; 74 | double_t kd, r, r2, scale, tail, tmp; 75 | 76 | abstop = top12(x) & 0x7ff; 77 | if (predict_false(abstop - top12(0x1p-54) >= top12(512.0) - top12(0x1p-54))) { 78 | if (abstop - top12(0x1p-54) >= 0x80000000) 79 | /* Avoid spurious underflow for tiny x. */ 80 | /* Note: 0 is common input. */ 81 | return WANT_ROUNDING ? 1.0 + x : 1.0; 82 | if (abstop >= top12(1024.0)) { 83 | if (asuint64(x) == asuint64(-INFINITY)) 84 | return 0.0; 85 | if (abstop >= top12(INFINITY)) 86 | return 1.0 + x; 87 | if (!(asuint64(x) >> 63)) 88 | return __math_oflow(0); 89 | else if (asuint64(x) >= asuint64(-1075.0)) 90 | return __math_uflow(0); 91 | } 92 | if (2 * asuint64(x) > 2 * asuint64(928.0)) 93 | /* Large x is special cased below. */ 94 | abstop = 0; 95 | } 96 | 97 | /* exp2(x) = 2^(k/N) * 2^r, with 2^r in [2^(-1/2N),2^(1/2N)]. */ 98 | /* x = k/N + r, with int k and r in [-1/2N, 1/2N]. */ 99 | kd = eval_as_double(x + Shift); 100 | ki = asuint64(kd); /* k. */ 101 | kd -= Shift; /* k/N for int k. */ 102 | r = x - kd; 103 | /* 2^(k/N) ~= scale * (1 + tail). */ 104 | idx = 2 * (ki % N); 105 | top = ki << (52 - EXP_TABLE_BITS); 106 | tail = asdouble(T[idx]); 107 | /* This is only a valid scale when -1023*N < k < 1024*N. */ 108 | sbits = T[idx + 1] + top; 109 | /* exp2(x) = 2^(k/N) * 2^r ~= scale + scale * (tail + 2^r - 1). */ 110 | /* Evaluation is optimized assuming superscalar pipelined execution. */ 111 | r2 = r * r; 112 | /* Without fma the worst case error is 0.5/N ulp larger. */ 113 | /* Worst case error is less than 0.5+0.86/N+(abs poly error * 2^53) ulp. */ 114 | tmp = tail + r * C1 + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); 115 | if (predict_false(abstop == 0)) 116 | return specialcase(tmp, sbits, ki); 117 | scale = asdouble(sbits); 118 | /* Note: tmp == 0 or |tmp| > 2^-65 and scale > 2^-928, so there 119 | is no spurious underflow here even without fma. */ 120 | return eval_as_double(scale + scale * tmp); 121 | } 122 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Double-precision e^x function. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include 9 | #include 10 | #include "libm.h" 11 | #include "exp_data.h" 12 | 13 | #define N (1 << EXP_TABLE_BITS) 14 | #define InvLn2N __exp_data.invln2N 15 | #define NegLn2hiN __exp_data.negln2hiN 16 | #define NegLn2loN __exp_data.negln2loN 17 | #define Shift __exp_data.shift 18 | #define T __exp_data.tab 19 | #define C2 __exp_data.poly[5 - EXP_POLY_ORDER] 20 | #define C3 __exp_data.poly[6 - EXP_POLY_ORDER] 21 | #define C4 __exp_data.poly[7 - EXP_POLY_ORDER] 22 | #define C5 __exp_data.poly[8 - EXP_POLY_ORDER] 23 | 24 | /* Handle cases that may overflow or underflow when computing the result that 25 | is scale*(1+TMP) without intermediate rounding. The bit representation of 26 | scale is in SBITS, however it has a computed exponent that may have 27 | overflown into the sign bit so that needs to be adjusted before using it as 28 | a double. (int32_t)KI is the k used in the argument reduction and exponent 29 | adjustment of scale, positive k here means the result may overflow and 30 | negative k means the result may underflow. */ 31 | static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki) 32 | { 33 | double_t scale, y; 34 | 35 | if ((ki & 0x80000000) == 0) { 36 | /* k > 0, the exponent of scale might have overflowed by <= 460. */ 37 | sbits -= 1009ull << 52; 38 | scale = asdouble(sbits); 39 | y = 0x1p1009 * (scale + scale * tmp); 40 | return eval_as_double(y); 41 | } 42 | /* k < 0, need special care in the subnormal range. */ 43 | sbits += 1022ull << 52; 44 | scale = asdouble(sbits); 45 | y = scale + scale * tmp; 46 | if (y < 1.0) { 47 | /* Round y to the right precision before scaling it into the subnormal 48 | range to avoid double rounding that can cause 0.5+E/2 ulp error where 49 | E is the worst-case ulp error outside the subnormal range. So this 50 | is only useful if the goal is better than 1 ulp worst-case error. */ 51 | double_t hi, lo; 52 | lo = scale - y + scale * tmp; 53 | hi = 1.0 + y; 54 | lo = 1.0 - hi + y + lo; 55 | y = eval_as_double(hi + lo) - 1.0; 56 | /* Avoid -0.0 with downward rounding. */ 57 | if (WANT_ROUNDING && y == 0.0) 58 | y = 0.0; 59 | /* The underflow exception needs to be signaled explicitly. */ 60 | fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022); 61 | } 62 | y = 0x1p-1022 * y; 63 | return eval_as_double(y); 64 | } 65 | 66 | /* Top 12 bits of a double (sign and exponent bits). */ 67 | static inline uint32_t top12(double x) 68 | { 69 | return asuint64(x) >> 52; 70 | } 71 | 72 | double exp(double x) 73 | { 74 | uint32_t abstop; 75 | uint64_t ki, idx, top, sbits; 76 | double_t kd, z, r, r2, scale, tail, tmp; 77 | 78 | abstop = top12(x) & 0x7ff; 79 | if (predict_false(abstop - top12(0x1p-54) >= top12(512.0) - top12(0x1p-54))) { 80 | if (abstop - top12(0x1p-54) >= 0x80000000) 81 | /* Avoid spurious underflow for tiny x. */ 82 | /* Note: 0 is common input. */ 83 | return WANT_ROUNDING ? 1.0 + x : 1.0; 84 | if (abstop >= top12(1024.0)) { 85 | if (asuint64(x) == asuint64(-INFINITY)) 86 | return 0.0; 87 | if (abstop >= top12(INFINITY)) 88 | return 1.0 + x; 89 | if (asuint64(x) >> 63) 90 | return __math_uflow(0); 91 | else 92 | return __math_oflow(0); 93 | } 94 | /* Large x is special cased below. */ 95 | abstop = 0; 96 | } 97 | 98 | /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ 99 | /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ 100 | z = InvLn2N * x; 101 | #if TOINT_INTRINSICS 102 | kd = roundtoint(z); 103 | ki = converttoint(z); 104 | #elif EXP_USE_TOINT_NARROW 105 | /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes. */ 106 | kd = eval_as_double(z + Shift); 107 | ki = asuint64(kd) >> 16; 108 | kd = (double_t)(int32_t)ki; 109 | #else 110 | /* z - kd is in [-1, 1] in non-nearest rounding modes. */ 111 | kd = eval_as_double(z + Shift); 112 | ki = asuint64(kd); 113 | kd -= Shift; 114 | #endif 115 | r = x + kd * NegLn2hiN + kd * NegLn2loN; 116 | /* 2^(k/N) ~= scale * (1 + tail). */ 117 | idx = 2 * (ki % N); 118 | top = ki << (52 - EXP_TABLE_BITS); 119 | tail = asdouble(T[idx]); 120 | /* This is only a valid scale when -1023*N < k < 1024*N. */ 121 | sbits = T[idx + 1] + top; 122 | /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */ 123 | /* Evaluation is optimized assuming superscalar pipelined execution. */ 124 | r2 = r * r; 125 | /* Without fma the worst case error is 0.25/N ulp larger. */ 126 | /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */ 127 | tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5); 128 | if (predict_false(abstop == 0)) 129 | return specialcase(tmp, sbits, ki); 130 | scale = asdouble(sbits); 131 | /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there 132 | is no spurious underflow here even without fma. */ 133 | return eval_as_double(scale + scale * tmp); 134 | } 135 | -------------------------------------------------------------------------------- /FindThrift.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Cloudera Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # - Find Thrift (a cross platform RPC lib/tool) 16 | # 17 | # Variables used by this module, they can change the default behaviour and need 18 | # to be set before calling find_package: 19 | # 20 | # Thrift_ROOT - When set, this path is inspected instead of standard library 21 | # locations as the root of the Thrift installation. 22 | # The environment variable THRIFT_HOME overrides this variable. 23 | # 24 | # This module defines 25 | # THRIFT_VERSION, version string of ant if found 26 | # THRIFT_INCLUDE_DIR, where to find THRIFT headers 27 | # THRIFT_LIB, THRIFT library 28 | # THRIFT_FOUND, If false, do not try to use ant 29 | 30 | function(EXTRACT_THRIFT_VERSION) 31 | if(THRIFT_INCLUDE_DIR) 32 | file(READ "${THRIFT_INCLUDE_DIR}/thrift/config.h" THRIFT_CONFIG_H_CONTENT) 33 | string(REGEX MATCH "#define PACKAGE_VERSION \"[0-9.]+\"" THRIFT_VERSION_DEFINITION 34 | "${THRIFT_CONFIG_H_CONTENT}") 35 | string(REGEX MATCH "[0-9.]+" THRIFT_VERSION "${THRIFT_VERSION_DEFINITION}") 36 | set(THRIFT_VERSION 37 | "${THRIFT_VERSION}" 38 | PARENT_SCOPE) 39 | set(Thrift_VERSION 40 | "${THRIFT_VERSION}" 41 | PARENT_SCOPE) 42 | else() 43 | set(THRIFT_VERSION 44 | "" 45 | PARENT_SCOPE) 46 | endif() 47 | endfunction(EXTRACT_THRIFT_VERSION) 48 | 49 | if(MSVC_TOOLCHAIN AND NOT DEFINED THRIFT_MSVC_LIB_SUFFIX) 50 | if(NOT ARROW_THRIFT_USE_SHARED) 51 | if(ARROW_USE_STATIC_CRT) 52 | set(THRIFT_MSVC_LIB_SUFFIX "mt") 53 | else() 54 | set(THRIFT_MSVC_LIB_SUFFIX "md") 55 | endif() 56 | endif() 57 | endif() 58 | set(THRIFT_LIB_NAME_BASE "thrift${THRIFT_MSVC_LIB_SUFFIX}") 59 | 60 | if(ARROW_THRIFT_USE_SHARED) 61 | set(THRIFT_LIB_NAMES thrift) 62 | if(CMAKE_IMPORT_LIBRARY_SUFFIX) 63 | list(APPEND 64 | THRIFT_LIB_NAMES 65 | "${CMAKE_IMPORT_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_IMPORT_LIBRARY_SUFFIX}" 66 | ) 67 | endif() 68 | list(APPEND 69 | THRIFT_LIB_NAMES 70 | "${CMAKE_SHARED_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}" 71 | ) 72 | else() 73 | set(THRIFT_LIB_NAMES 74 | "${CMAKE_STATIC_LIBRARY_PREFIX}${THRIFT_LIB_NAME_BASE}${CMAKE_STATIC_LIBRARY_SUFFIX}" 75 | ) 76 | endif() 77 | 78 | if(Thrift_ROOT) 79 | find_library(THRIFT_LIB 80 | NAMES ${THRIFT_LIB_NAMES} 81 | PATHS ${Thrift_ROOT} 82 | PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib") 83 | find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h 84 | PATHS ${Thrift_ROOT} 85 | PATH_SUFFIXES "include") 86 | find_program(THRIFT_COMPILER thrift 87 | PATHS ${Thrift_ROOT} 88 | PATH_SUFFIXES "bin") 89 | extract_thrift_version() 90 | else() 91 | # THRIFT-4760: The pkgconfig files are currently only installed when using autotools. 92 | # Starting with 0.13, they are also installed for the CMake-based installations of Thrift. 93 | find_package(PkgConfig QUIET) 94 | pkg_check_modules(THRIFT_PC thrift) 95 | if(THRIFT_PC_FOUND) 96 | set(THRIFT_INCLUDE_DIR "${THRIFT_PC_INCLUDEDIR}") 97 | 98 | list(APPEND THRIFT_PC_LIBRARY_DIRS "${THRIFT_PC_LIBDIR}") 99 | 100 | find_library(THRIFT_LIB 101 | NAMES ${THRIFT_LIB_NAMES} 102 | PATHS ${THRIFT_PC_LIBRARY_DIRS} 103 | NO_DEFAULT_PATH) 104 | find_program(THRIFT_COMPILER thrift 105 | HINTS ${THRIFT_PC_PREFIX} 106 | NO_DEFAULT_PATH 107 | PATH_SUFFIXES "bin") 108 | set(THRIFT_VERSION ${THRIFT_PC_VERSION}) 109 | else() 110 | find_library(THRIFT_LIB 111 | NAMES ${THRIFT_LIB_NAMES} 112 | PATH_SUFFIXES "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib") 113 | find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h PATH_SUFFIXES "include") 114 | find_program(THRIFT_COMPILER thrift PATH_SUFFIXES "bin") 115 | extract_thrift_version() 116 | endif() 117 | endif() 118 | 119 | if(THRIFT_COMPILER) 120 | set(Thrift_COMPILER_FOUND TRUE) 121 | else() 122 | set(Thrift_COMPILER_FOUND FALSE) 123 | endif() 124 | 125 | find_package_handle_standard_args( 126 | Thrift 127 | REQUIRED_VARS THRIFT_LIB THRIFT_INCLUDE_DIR 128 | VERSION_VAR THRIFT_VERSION 129 | HANDLE_COMPONENTS) 130 | 131 | if(Thrift_FOUND OR THRIFT_FOUND) 132 | set(Thrift_FOUND TRUE) 133 | if(ARROW_THRIFT_USE_SHARED) 134 | add_library(thrift::thrift SHARED IMPORTED) 135 | else() 136 | add_library(thrift::thrift STATIC IMPORTED) 137 | endif() 138 | set_target_properties(thrift::thrift 139 | PROPERTIES IMPORTED_LOCATION "${THRIFT_LIB}" 140 | INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR}") 141 | if(WIN32 AND NOT MSVC_TOOLCHAIN) 142 | # We don't need this for Visual C++ because Thrift uses 143 | # "#pragma comment(lib, "Ws2_32.lib")" in 144 | # thrift/windows/config.h for Visual C++. 145 | set_target_properties(thrift::thrift PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32") 146 | endif() 147 | endif() 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linux Distribution Based Toolchain Generator 2 | 3 | ## TL;DR 4 | 5 | LDB toolchain generator gives you a working gcc-15 and clang-20 environment with cmake 3.29. It helps compiling modern C++ projects like ClickHouse and Doris on almost any Linux distros. The installation file can be found in [Releases](https://github.com/amosbird/ldb_toolchain_gen/releases). 6 | 7 | ByConity is supported as well, but it requires manual adjustments due to its outdated toolchain support. If you just need to make `clangd` happy (e.g., for code completion and navigation), run the following: 8 | 9 | ```bash 10 | rm -rf build && mkdir build && cd build 11 | 12 | CC=clang CXX=clang++ cmake .. 13 | 14 | # Generate the required headers 15 | ninja brpc-static clickhouse_protos_lib 16 | ``` 17 | 18 | ## How to install 19 | 20 | 1. Download `ldb_toolchain_gen.sh` from [Releases](https://github.com/amosbird/ldb_toolchain_gen/releases) 21 | 22 | 2. Execute the following command to generate LDB toolchain 23 | 24 | ``` bash 25 | bash ldb_toolchain_gen.sh /path/to/ldb_toolchain/ 26 | ``` 27 | 28 | `/path/to/ldb_toolchain/` is the directory where the toolchain is installed. The following directory structure will be created. 29 | 30 | ``` sh 31 | ├── bin 32 | ├── include 33 | ├── lib 34 | ├── share 35 | ├── test 36 | └── usr 37 | ``` 38 | 39 | ## FAQ 40 | 41 | 1. Why do I still see version `GLIBC_xxx' not found? 42 | 43 | It might be related to extern libc weak symbol such as [this code](https://github.com/janbar/openssl-cmake/blob/d4634362820f874e1f1461c7f5d766b3ef968c67/crypto/rand/rand_unix.c#L373). The root cause is related to [how the linker processes symbols](https://maskray.me/blog/2021-06-20-linker-symbol-resolution). The ideal solution is removing weak attribute from libc symbol declarations. 44 | 45 | 2. Compiler/Linker doesn't work at all: Symbol not found in xxx.so? 46 | 47 | Make sure `LD_LIBRARY_PATH` is not set. 48 | 49 | --- 50 | 51 | > **Note** 52 | > The following content describes how `ldb_toolchain_gen.sh` is made. There is no need for common users to pay attention. It might lead to unnecessary confusion. 53 | 54 | ## Introduction 55 | 56 | **LDB toolchain generator** helps generate toolchains derived from well-known linux distributions (LDB toolchain). **LDB toolchain** contains binaries from well-known linux distributions, which are heavily tested and optimized. It avoids the docker dependency which usually complicates developing workflows. Projects adopting LDB toolchain will likely generate byte-identical binaries. It benefits testing and debugging due to 100% consistency. It also lowers the bar of contributing code, as large C/C++ projects are usually daunting to build compared to Java, Golang, Rust, etc. 57 | 58 | There are projects like Crosstool-NG and Gentoo-Prefix which aim at bootstraping toolchains from scratch. They are for advanced use cases and take a tremendous amount of time to bootstrap. It's also hard to control the quality of self-compiled toolchains. 59 | 60 | ## Tools used by LDB toolchain generator 61 | 62 | 1. https://github.com/NixOS/patchelf 63 | 64 | There are projects like [Exodus](https://github.com/intoli/exodus) which can generate relocate Linux ELF binaries with wrappers and dependencies. Wrappers are usually good enough for common tools. However, toolchains like GCC and Clang relies heavily on `/proc/self` to re-exec the driver program multiple times, which will not work for `ld-linux` wrappers. As a result, we use [patchelf](https://github.com/NixOS/patchelf) to modify `PT_INTERP` and `RPATH`. Though `RPATH` can be relative to the binary's location, it's not possible to make a relocatable a.out that can tolerate changes to the absolute path of `ld-linux`. Thus, LDB toolchain generator requires user to specify a **toolchain prefix**. 65 | 66 | ## How to generate a LDB toolchain generator 67 | 68 | The main branch illustrates how the generator assembles gcc-15 and clang-20 from ubuntu-18.04. 69 | 70 | To actually generate the toolchain, the following steps can be used: 71 | 72 | ``` 73 | git clone https://github.com/amosbird/ldb_toolchain_gen 74 | 75 | cd ldb_toolchain_gen 76 | 77 | docker build . -t --network host 78 | 79 | # for aarch64 80 | # docker build . -t --network host --build-arg ARCH=aarch64 81 | 82 | docker run --rm -v :/data 83 | 84 | # Concrete Example 85 | 86 | git clone https://github.com/amosbird/ldb_toolchain_gen 87 | 88 | cd ldb_toolchain_gen 89 | 90 | # You may need http proxy to overcome network errors during docker build 91 | docker build . -t amosbird/some_toolchain_gen 92 | # docker build --network host --build-arg http_proxy=http://127.0.0.1:10000 --build-arg https_proxy=http://127.0.0.1:10000 . -t amosbird/some_toolchain_gen 93 | 94 | mkdir /tmp/some_toolchain_gen 95 | 96 | # You may need root privilege 97 | docker run --rm -v /tmp/some_toolchain_gen:/data amosbird/some_toolchain_gen 98 | ``` 99 | 100 | In the end, `/tmp/some_toolchain_gen` will contain a install script: `ldb_toolchain_gen.sh`. 101 | 102 | The main branch is currently used to build [ClickHouse](https://github.com/ClickHouse/ClickHouse) and [Doris](https://github.com/apache/doris). 103 | 104 | If you want to generate a toolchain for the arm platform, you can change `ARCH=x86_64` in the `Dockerfile` to `ARCH=aarch64`. 105 | 106 | ## How to avoid GLIBC incompatibility 107 | 108 | LDB toolchain might use newer libc which in turn will generate binaries that cannot be run on old host, even the same host for compilation. Users will encounter errors like `version GLIBC_2.27 not found`. A practical way of resolving this issue is described in [this wiki](http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc). 109 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/powf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2018, Arm Limited. 3 | * SPDX-License-Identifier: MIT 4 | */ 5 | 6 | #include 7 | #include 8 | #include "libm.h" 9 | #include "exp2f_data.h" 10 | #include "powf_data.h" 11 | 12 | /* 13 | POWF_LOG2_POLY_ORDER = 5 14 | EXP2F_TABLE_BITS = 5 15 | 16 | ULP error: 0.82 (~ 0.5 + relerr*2^24) 17 | relerr: 1.27 * 2^-26 (Relative error ~= 128*Ln2*relerr_log2 + relerr_exp2) 18 | relerr_log2: 1.83 * 2^-33 (Relative error of logx.) 19 | relerr_exp2: 1.69 * 2^-34 (Relative error of exp2(ylogx).) 20 | */ 21 | 22 | #define N (1 << POWF_LOG2_TABLE_BITS) 23 | #define T __powf_log2_data.tab 24 | #define A __powf_log2_data.poly 25 | #define OFF 0x3f330000 26 | 27 | /* Subnormal input is normalized so ix has negative biased exponent. 28 | Output is multiplied by N (POWF_SCALE) if TOINT_INTRINICS is set. */ 29 | static inline double_t log2_inline(uint32_t ix) 30 | { 31 | double_t z, r, r2, r4, p, q, y, y0, invc, logc; 32 | uint32_t iz, top, tmp; 33 | int k, i; 34 | 35 | /* x = 2^k z; where z is in range [OFF,2*OFF] and exact. 36 | The range is split into N subintervals. 37 | The ith subinterval contains z and c is near its center. */ 38 | tmp = ix - OFF; 39 | i = (tmp >> (23 - POWF_LOG2_TABLE_BITS)) % N; 40 | top = tmp & 0xff800000; 41 | iz = ix - top; 42 | k = (int32_t)top >> (23 - POWF_SCALE_BITS); /* arithmetic shift */ 43 | invc = T[i].invc; 44 | logc = T[i].logc; 45 | z = (double_t)asfloat(iz); 46 | 47 | /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */ 48 | r = z * invc - 1; 49 | y0 = logc + (double_t)k; 50 | 51 | /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */ 52 | r2 = r * r; 53 | y = A[0] * r + A[1]; 54 | p = A[2] * r + A[3]; 55 | r4 = r2 * r2; 56 | q = A[4] * r + y0; 57 | q = p * r2 + q; 58 | y = y * r4 + q; 59 | return y; 60 | } 61 | 62 | #undef N 63 | #undef T 64 | #define N (1 << EXP2F_TABLE_BITS) 65 | #define T __exp2f_data.tab 66 | #define SIGN_BIAS (1 << (EXP2F_TABLE_BITS + 11)) 67 | 68 | /* The output of log2 and thus the input of exp2 is either scaled by N 69 | (in case of fast toint intrinsics) or not. The unscaled xd must be 70 | in [-1021,1023], sign_bias sets the sign of the result. */ 71 | static inline float exp2_inline(double_t xd, uint32_t sign_bias) 72 | { 73 | uint64_t ki, ski, t; 74 | double_t kd, z, r, r2, y, s; 75 | 76 | #if TOINT_INTRINSICS 77 | #define C __exp2f_data.poly_scaled 78 | /* N*x = k + r with r in [-1/2, 1/2] */ 79 | kd = roundtoint(xd); /* k */ 80 | ki = converttoint(xd); 81 | #else 82 | #define C __exp2f_data.poly 83 | #define SHIFT __exp2f_data.shift_scaled 84 | /* x = k/N + r with r in [-1/(2N), 1/(2N)] */ 85 | kd = eval_as_double(xd + SHIFT); 86 | ki = asuint64(kd); 87 | kd -= SHIFT; /* k/N */ 88 | #endif 89 | r = xd - kd; 90 | 91 | /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */ 92 | t = T[ki % N]; 93 | ski = ki + sign_bias; 94 | t += ski << (52 - EXP2F_TABLE_BITS); 95 | s = asdouble(t); 96 | z = C[0] * r + C[1]; 97 | r2 = r * r; 98 | y = C[2] * r + 1; 99 | y = z * r2 + y; 100 | y = y * s; 101 | return eval_as_float(y); 102 | } 103 | 104 | /* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is 105 | the bit representation of a non-zero finite floating-point value. */ 106 | static inline int checkint(uint32_t iy) 107 | { 108 | int e = iy >> 23 & 0xff; 109 | if (e < 0x7f) 110 | return 0; 111 | if (e > 0x7f + 23) 112 | return 2; 113 | if (iy & ((1 << (0x7f + 23 - e)) - 1)) 114 | return 0; 115 | if (iy & (1 << (0x7f + 23 - e))) 116 | return 1; 117 | return 2; 118 | } 119 | 120 | static inline int zeroinfnan(uint32_t ix) 121 | { 122 | return 2 * ix - 1 >= 2u * 0x7f800000 - 1; 123 | } 124 | 125 | float powf(float x, float y) 126 | { 127 | uint32_t sign_bias = 0; 128 | uint32_t ix, iy; 129 | 130 | ix = asuint(x); 131 | iy = asuint(y); 132 | if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000 || 133 | zeroinfnan(iy))) { 134 | /* Either (x < 0x1p-126 or inf or nan) or (y is 0 or inf or nan). */ 135 | if (predict_false(zeroinfnan(iy))) { 136 | if (2 * iy == 0) 137 | return issignalingf_inline(x) ? x + y : 1.0f; 138 | if (ix == 0x3f800000) 139 | return issignalingf_inline(y) ? x + y : 1.0f; 140 | if (2 * ix > 2u * 0x7f800000 || 141 | 2 * iy > 2u * 0x7f800000) 142 | return x + y; 143 | if (2 * ix == 2 * 0x3f800000) 144 | return 1.0f; 145 | if ((2 * ix < 2 * 0x3f800000) == !(iy & 0x80000000)) 146 | return 0.0f; /* |x|<1 && y==inf or |x|>1 && y==-inf. */ 147 | return y * y; 148 | } 149 | if (predict_false(zeroinfnan(ix))) { 150 | float_t x2 = x * x; 151 | if (ix & 0x80000000 && checkint(iy) == 1) 152 | x2 = -x2; 153 | /* Without the barrier some versions of clang hoist the 1/x2 and 154 | thus division by zero exception can be signaled spuriously. */ 155 | return iy & 0x80000000 ? fp_barrierf(1 / x2) : x2; 156 | } 157 | /* x and y are non-zero finite. */ 158 | if (ix & 0x80000000) { 159 | /* Finite x < 0. */ 160 | int yint = checkint(iy); 161 | if (yint == 0) 162 | return __math_invalidf(x); 163 | if (yint == 1) 164 | sign_bias = SIGN_BIAS; 165 | ix &= 0x7fffffff; 166 | } 167 | if (ix < 0x00800000) { 168 | /* Normalize subnormal x so exponent becomes negative. */ 169 | ix = asuint(x * 0x1p23f); 170 | ix &= 0x7fffffff; 171 | ix -= 23 << 23; 172 | } 173 | } 174 | double_t logx = log2_inline(ix); 175 | double_t ylogx = y * logx; /* cannot overflow, y is single prec. */ 176 | if (predict_false((asuint64(ylogx) >> 47 & 0xffff) >= 177 | asuint64(126.0 * POWF_SCALE) >> 47)) { 178 | /* |y*log(x)| >= 126. */ 179 | if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE) 180 | return __math_oflowf(sign_bias); 181 | if (ylogx <= -150.0 * POWF_SCALE) 182 | return __math_uflowf(sign_bias); 183 | } 184 | return exp2_inline(ylogx, sign_bias); 185 | } 186 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/glob.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | struct match 12 | { 13 | struct match *next; 14 | char name[1]; 15 | }; 16 | 17 | static int is_literal(const char *p, int useesc) 18 | { 19 | int bracket = 0; 20 | for (; *p; p++) { 21 | switch (*p) { 22 | case '\\': 23 | if (!useesc) break; 24 | case '?': 25 | case '*': 26 | return 0; 27 | case '[': 28 | bracket = 1; 29 | break; 30 | case ']': 31 | if (bracket) return 0; 32 | break; 33 | } 34 | } 35 | return 1; 36 | } 37 | 38 | static int append(struct match **tail, const char *name, size_t len, int mark) 39 | { 40 | struct match *new = malloc(sizeof(struct match) + len + 1); 41 | if (!new) return -1; 42 | (*tail)->next = new; 43 | new->next = NULL; 44 | strcpy(new->name, name); 45 | if (mark) strcat(new->name, "/"); 46 | *tail = new; 47 | return 0; 48 | } 49 | 50 | static int match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail) 51 | { 52 | DIR *dir; 53 | struct dirent *de; 54 | char pat[strlen(p)+1]; 55 | char *p2; 56 | size_t l = strlen(d); 57 | int literal; 58 | int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) 59 | | ((!(flags & GLOB_PERIOD)) ? FNM_PERIOD : 0); 60 | int error; 61 | 62 | if ((p2 = strchr(p, '/'))) { 63 | strcpy(pat, p); 64 | pat[p2-p] = 0; 65 | for (; *p2 == '/'; p2++); 66 | p = pat; 67 | } 68 | literal = is_literal(p, !(flags & GLOB_NOESCAPE)); 69 | if (*d == '/' && !*(d+1)) l = 0; 70 | 71 | /* rely on opendir failing for nondirectory objects */ 72 | dir = opendir(*d ? d : "."); 73 | error = errno; 74 | if (!dir) { 75 | /* this is not an error -- we let opendir call stat for us */ 76 | if (error == ENOTDIR) return 0; 77 | if (error == EACCES && !*p) { 78 | struct stat st; 79 | if (!stat(d, &st) && S_ISDIR(st.st_mode)) { 80 | if (append(tail, d, l, l)) 81 | return GLOB_NOSPACE; 82 | return 0; 83 | } 84 | } 85 | if (errfunc(d, error) || (flags & GLOB_ERR)) 86 | return GLOB_ABORTED; 87 | return 0; 88 | } 89 | if (!*p) { 90 | error = append(tail, d, l, l) ? GLOB_NOSPACE : 0; 91 | closedir(dir); 92 | return error; 93 | } 94 | while ((de = readdir(dir))) { 95 | char namebuf[l+de->d_reclen+2], *name = namebuf; 96 | if (!literal && fnmatch(p, de->d_name, fnm_flags)) 97 | continue; 98 | if (literal && strcmp(p, de->d_name)) 99 | continue; 100 | if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12)) 101 | continue; 102 | /* With GLOB_PERIOD, don't allow matching . or .. unless 103 | * fnmatch would match them with FNM_PERIOD rules in effect. */ 104 | if (p2 && (flags & GLOB_PERIOD) && de->d_name[0]=='.' 105 | && (!de->d_name[1] || (de->d_name[1]=='.' && !de->d_name[2])) 106 | && fnmatch(p, de->d_name, fnm_flags | FNM_PERIOD)) 107 | continue; 108 | if (*d) { 109 | memcpy(name, d, l); 110 | name[l] = '/'; 111 | strcpy(name+l+1, de->d_name); 112 | } else { 113 | name = de->d_name; 114 | } 115 | if (p2) { 116 | if ((error = match_in_dir(name, p2, flags, errfunc, tail))) { 117 | closedir(dir); 118 | return error; 119 | } 120 | } else { 121 | int mark = 0; 122 | if (flags & GLOB_MARK) { 123 | if (de->d_type && !S_ISLNK(de->d_type<<12)) 124 | mark = S_ISDIR(de->d_type<<12); 125 | else { 126 | struct stat st; 127 | stat(name, &st); 128 | mark = S_ISDIR(st.st_mode); 129 | } 130 | } 131 | if (append(tail, name, l+de->d_reclen+1, mark)) { 132 | closedir(dir); 133 | return GLOB_NOSPACE; 134 | } 135 | } 136 | } 137 | closedir(dir); 138 | if (error && (errfunc(d, error) || (flags & GLOB_ERR))) 139 | return GLOB_ABORTED; 140 | return 0; 141 | } 142 | 143 | static int ignore_err(const char *path, int err) 144 | { 145 | return 0; 146 | } 147 | 148 | static void freelist(struct match *head) 149 | { 150 | struct match *match, *next; 151 | for (match=head->next; match; match=next) { 152 | next = match->next; 153 | free(match); 154 | } 155 | } 156 | 157 | static int sort(const void *a, const void *b) 158 | { 159 | return strcmp(*(const char **)a, *(const char **)b); 160 | } 161 | 162 | int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g) 163 | { 164 | const char *p=pat, *d; 165 | struct match head = { .next = NULL }, *tail = &head; 166 | size_t cnt, i; 167 | size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0; 168 | int error = 0; 169 | 170 | if (*p == '/') { 171 | for (; *p == '/'; p++); 172 | d = "/"; 173 | } else { 174 | d = ""; 175 | } 176 | 177 | if (!errfunc) errfunc = ignore_err; 178 | 179 | if (!(flags & GLOB_APPEND)) { 180 | g->gl_offs = offs; 181 | g->gl_pathc = 0; 182 | g->gl_pathv = NULL; 183 | } 184 | 185 | if (strnlen(p, PATH_MAX+1) > PATH_MAX) return GLOB_NOSPACE; 186 | 187 | if (*pat) error = match_in_dir(d, p, flags, errfunc, &tail); 188 | if (error == GLOB_NOSPACE) { 189 | freelist(&head); 190 | return error; 191 | } 192 | 193 | for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++); 194 | if (!cnt) { 195 | if (flags & GLOB_NOCHECK) { 196 | tail = &head; 197 | if (append(&tail, pat, strlen(pat), 0)) 198 | return GLOB_NOSPACE; 199 | cnt++; 200 | } else 201 | return GLOB_NOMATCH; 202 | } 203 | 204 | if (flags & GLOB_APPEND) { 205 | char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *)); 206 | if (!pathv) { 207 | freelist(&head); 208 | return GLOB_NOSPACE; 209 | } 210 | g->gl_pathv = pathv; 211 | offs += g->gl_pathc; 212 | } else { 213 | g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *)); 214 | if (!g->gl_pathv) { 215 | freelist(&head); 216 | return GLOB_NOSPACE; 217 | } 218 | for (i=0; igl_pathv[i] = NULL; 220 | } 221 | for (i=0, tail=head.next; inext, i++) 222 | g->gl_pathv[offs + i] = tail->name; 223 | g->gl_pathv[offs + i] = NULL; 224 | g->gl_pathc += cnt; 225 | 226 | if (!(flags & GLOB_NOSORT)) 227 | qsort(g->gl_pathv+offs, cnt, sizeof(char *), sort); 228 | 229 | return error; 230 | } 231 | 232 | void globfree(glob_t *g) 233 | { 234 | size_t i; 235 | for (i=0; igl_pathc; i++) 236 | free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name)); 237 | free(g->gl_pathv); 238 | g->gl_pathc = 0; 239 | g->gl_pathv = NULL; 240 | } 241 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/COPYRIGHT: -------------------------------------------------------------------------------- 1 | musl as a whole is licensed under the following standard MIT license: 2 | 3 | ---------------------------------------------------------------------- 4 | Copyright © 2005-2014 Rich Felker, et al. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | ---------------------------------------------------------------------- 25 | 26 | Authors/contributors include: 27 | 28 | Alex Dowad 29 | Alexander Monakov 30 | Anthony G. Basile 31 | Arvid Picciani 32 | Bobby Bingham 33 | Boris Brezillon 34 | Brent Cook 35 | Chris Spiegel 36 | Clément Vasseur 37 | Daniel Micay 38 | Denys Vlasenko 39 | Emil Renner Berthing 40 | Felix Fietkau 41 | Felix Janda 42 | Gianluca Anzolin 43 | Hauke Mehrtens 44 | Hiltjo Posthuma 45 | Isaac Dunham 46 | Jaydeep Patil 47 | Jens Gustedt 48 | Jeremy Huntwork 49 | Jo-Philipp Wich 50 | Joakim Sindholt 51 | John Spencer 52 | Josiah Worcester 53 | Justin Cormack 54 | Khem Raj 55 | Kylie McClain 56 | Luca Barbato 57 | Luka Perkov 58 | M Farkas-Dyck (Strake) 59 | Mahesh Bodapati 60 | Michael Forney 61 | Natanael Copa 62 | Nicholas J. Kain 63 | orc 64 | Pascal Cuoq 65 | Petr Hosek 66 | Pierre Carrier 67 | Rich Felker 68 | Richard Pennington 69 | Shiz 70 | sin 71 | Solar Designer 72 | Stefan Kristiansson 73 | Szabolcs Nagy 74 | Timo Teräs 75 | Trutz Behn 76 | Valentin Ochs 77 | William Haddon 78 | 79 | Portions of this software are derived from third-party works licensed 80 | under terms compatible with the above MIT license: 81 | 82 | The TRE regular expression implementation (src/regex/reg* and 83 | src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed 84 | under a 2-clause BSD license (license text in the source files). The 85 | included version has been heavily modified by Rich Felker in 2012, in 86 | the interests of size, simplicity, and namespace cleanliness. 87 | 88 | Much of the math library code (src/math/* and src/complex/*) is 89 | Copyright © 1993,2004 Sun Microsystems or 90 | Copyright © 2003-2011 David Schultz or 91 | Copyright © 2003-2009 Steven G. Kargl or 92 | Copyright © 2003-2009 Bruce D. Evans or 93 | Copyright © 2008 Stephen L. Moshier 94 | and labelled as such in comments in the individual source files. All 95 | have been licensed under extremely permissive terms. 96 | 97 | The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008 98 | The Android Open Source Project and is licensed under a two-clause BSD 99 | license. It was taken from Bionic libc, used on Android. 100 | 101 | The implementation of DES for crypt (src/crypt/crypt_des.c) is 102 | Copyright © 1994 David Burren. It is licensed under a BSD license. 103 | 104 | The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was 105 | originally written by Solar Designer and placed into the public 106 | domain. The code also comes with a fallback permissive license for use 107 | in jurisdictions that may not recognize the public domain. 108 | 109 | The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 110 | Valentin Ochs and is licensed under an MIT-style license. 111 | 112 | The BSD PRNG implementation (src/prng/random.c) and XSI search API 113 | (src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and 114 | licensed under following terms: "Permission to use, copy, modify, 115 | and/or distribute this code for any purpose with or without fee is 116 | hereby granted. There is no warranty." 117 | 118 | The x86_64 port was written by Nicholas J. Kain and is licensed under 119 | the standard MIT terms. 120 | 121 | The mips and microblaze ports were originally written by Richard 122 | Pennington for use in the ellcc project. The original code was adapted 123 | by Rich Felker for build system and code conventions during upstream 124 | integration. It is licensed under the standard MIT terms. 125 | 126 | The mips64 port was contributed by Imagination Technologies and is 127 | licensed under the standard MIT terms. 128 | 129 | The powerpc port was also originally written by Richard Pennington, 130 | and later supplemented and integrated by John Spencer. It is licensed 131 | under the standard MIT terms. 132 | 133 | All other files which have no copyright comments are original works 134 | produced specifically for use as part of this library, written either 135 | by Rich Felker, the main author of the library, or by one or more 136 | contibutors listed above. Details on authorship of individual files 137 | can be found in the git version control history of the project. The 138 | omission of copyright and license comments in each file is in the 139 | interest of source tree size. 140 | 141 | In addition, permission is hereby granted for all public header files 142 | (include/* and arch/*/bits/*) and crt files intended to be linked into 143 | applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit 144 | the copyright notice and permission notice otherwise required by the 145 | license, and to use these files without any requirement of 146 | attribution. These files include substantial contributions from: 147 | 148 | Bobby Bingham 149 | John Spencer 150 | Nicholas J. Kain 151 | Rich Felker 152 | Richard Pennington 153 | Stefan Kristiansson 154 | Szabolcs Nagy 155 | 156 | all of whom have explicitly granted such permission. 157 | 158 | This file previously contained text expressing a belief that most of 159 | the files covered by the above exception were sufficiently trivial not 160 | to be subject to copyright, resulting in confusion over whether it 161 | negated the permissions granted in the license. In the spirit of 162 | permissive licensing, and of not having licensing issues being an 163 | obstacle to adoption, that text has been removed. 164 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/exp_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Shared data between exp, exp2 and pow. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "exp_data.h" 9 | 10 | #define N (1 << EXP_TABLE_BITS) 11 | 12 | const struct exp_data __exp_data = { 13 | // N/ln2 14 | .invln2N = 0x1.71547652b82fep0 * N, 15 | // -ln2/N 16 | .negln2hiN = -0x1.62e42fefa0000p-8, 17 | .negln2loN = -0x1.cf79abc9e3b3ap-47, 18 | // Used for rounding when !TOINT_INTRINSICS 19 | #if EXP_USE_TOINT_NARROW 20 | .shift = 0x1800000000.8p0, 21 | #else 22 | .shift = 0x1.8p52, 23 | #endif 24 | // exp polynomial coefficients. 25 | .poly = { 26 | // abs error: 1.555*2^-66 27 | // ulp error: 0.509 (0.511 without fma) 28 | // if |x| < ln2/256+eps 29 | // abs error if |x| < ln2/256+0x1p-15: 1.09*2^-65 30 | // abs error if |x| < ln2/128: 1.7145*2^-56 31 | 0x1.ffffffffffdbdp-2, 32 | 0x1.555555555543cp-3, 33 | 0x1.55555cf172b91p-5, 34 | 0x1.1111167a4d017p-7, 35 | }, 36 | .exp2_shift = 0x1.8p52 / N, 37 | // exp2 polynomial coefficients. 38 | .exp2_poly = { 39 | // abs error: 1.2195*2^-65 40 | // ulp error: 0.507 (0.511 without fma) 41 | // if |x| < 1/256 42 | // abs error if |x| < 1/128: 1.9941*2^-56 43 | 0x1.62e42fefa39efp-1, 44 | 0x1.ebfbdff82c424p-3, 45 | 0x1.c6b08d70cf4b5p-5, 46 | 0x1.3b2abd24650ccp-7, 47 | 0x1.5d7e09b4e3a84p-10, 48 | }, 49 | // 2^(k/N) ~= H[k]*(1 + T[k]) for int k in [0,N) 50 | // tab[2*k] = asuint64(T[k]) 51 | // tab[2*k+1] = asuint64(H[k]) - (k << 52)/N 52 | .tab = { 53 | 0x0, 0x3ff0000000000000, 54 | 0x3c9b3b4f1a88bf6e, 0x3feff63da9fb3335, 55 | 0xbc7160139cd8dc5d, 0x3fefec9a3e778061, 56 | 0xbc905e7a108766d1, 0x3fefe315e86e7f85, 57 | 0x3c8cd2523567f613, 0x3fefd9b0d3158574, 58 | 0xbc8bce8023f98efa, 0x3fefd06b29ddf6de, 59 | 0x3c60f74e61e6c861, 0x3fefc74518759bc8, 60 | 0x3c90a3e45b33d399, 0x3fefbe3ecac6f383, 61 | 0x3c979aa65d837b6d, 0x3fefb5586cf9890f, 62 | 0x3c8eb51a92fdeffc, 0x3fefac922b7247f7, 63 | 0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2, 64 | 0xbc6a033489906e0b, 0x3fef9b66affed31b, 65 | 0xbc9556522a2fbd0e, 0x3fef9301d0125b51, 66 | 0xbc5080ef8c4eea55, 0x3fef8abdc06c31cc, 67 | 0xbc91c923b9d5f416, 0x3fef829aaea92de0, 68 | 0x3c80d3e3e95c55af, 0x3fef7a98c8a58e51, 69 | 0xbc801b15eaa59348, 0x3fef72b83c7d517b, 70 | 0xbc8f1ff055de323d, 0x3fef6af9388c8dea, 71 | 0x3c8b898c3f1353bf, 0x3fef635beb6fcb75, 72 | 0xbc96d99c7611eb26, 0x3fef5be084045cd4, 73 | 0x3c9aecf73e3a2f60, 0x3fef54873168b9aa, 74 | 0xbc8fe782cb86389d, 0x3fef4d5022fcd91d, 75 | 0x3c8a6f4144a6c38d, 0x3fef463b88628cd6, 76 | 0x3c807a05b0e4047d, 0x3fef3f49917ddc96, 77 | 0x3c968efde3a8a894, 0x3fef387a6e756238, 78 | 0x3c875e18f274487d, 0x3fef31ce4fb2a63f, 79 | 0x3c80472b981fe7f2, 0x3fef2b4565e27cdd, 80 | 0xbc96b87b3f71085e, 0x3fef24dfe1f56381, 81 | 0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1, 82 | 0xbc3d219b1a6fbffa, 0x3fef187fd0dad990, 83 | 0x3c8b3782720c0ab4, 0x3fef1285a6e4030b, 84 | 0x3c6e149289cecb8f, 0x3fef0cafa93e2f56, 85 | 0x3c834d754db0abb6, 0x3fef06fe0a31b715, 86 | 0x3c864201e2ac744c, 0x3fef0170fc4cd831, 87 | 0x3c8fdd395dd3f84a, 0x3feefc08b26416ff, 88 | 0xbc86a3803b8e5b04, 0x3feef6c55f929ff1, 89 | 0xbc924aedcc4b5068, 0x3feef1a7373aa9cb, 90 | 0xbc9907f81b512d8e, 0x3feeecae6d05d866, 91 | 0xbc71d1e83e9436d2, 0x3feee7db34e59ff7, 92 | 0xbc991919b3ce1b15, 0x3feee32dc313a8e5, 93 | 0x3c859f48a72a4c6d, 0x3feedea64c123422, 94 | 0xbc9312607a28698a, 0x3feeda4504ac801c, 95 | 0xbc58a78f4817895b, 0x3feed60a21f72e2a, 96 | 0xbc7c2c9b67499a1b, 0x3feed1f5d950a897, 97 | 0x3c4363ed60c2ac11, 0x3feece086061892d, 98 | 0x3c9666093b0664ef, 0x3feeca41ed1d0057, 99 | 0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0, 100 | 0x3c93ff8e3f0f1230, 0x3feec32af0d7d3de, 101 | 0x3c7690cebb7aafb0, 0x3feebfdad5362a27, 102 | 0x3c931dbdeb54e077, 0x3feebcb299fddd0d, 103 | 0xbc8f94340071a38e, 0x3feeb9b2769d2ca7, 104 | 0xbc87deccdc93a349, 0x3feeb6daa2cf6642, 105 | 0xbc78dec6bd0f385f, 0x3feeb42b569d4f82, 106 | 0xbc861246ec7b5cf6, 0x3feeb1a4ca5d920f, 107 | 0x3c93350518fdd78e, 0x3feeaf4736b527da, 108 | 0x3c7b98b72f8a9b05, 0x3feead12d497c7fd, 109 | 0x3c9063e1e21c5409, 0x3feeab07dd485429, 110 | 0x3c34c7855019c6ea, 0x3feea9268a5946b7, 111 | 0x3c9432e62b64c035, 0x3feea76f15ad2148, 112 | 0xbc8ce44a6199769f, 0x3feea5e1b976dc09, 113 | 0xbc8c33c53bef4da8, 0x3feea47eb03a5585, 114 | 0xbc845378892be9ae, 0x3feea34634ccc320, 115 | 0xbc93cedd78565858, 0x3feea23882552225, 116 | 0x3c5710aa807e1964, 0x3feea155d44ca973, 117 | 0xbc93b3efbf5e2228, 0x3feea09e667f3bcd, 118 | 0xbc6a12ad8734b982, 0x3feea012750bdabf, 119 | 0xbc6367efb86da9ee, 0x3fee9fb23c651a2f, 120 | 0xbc80dc3d54e08851, 0x3fee9f7df9519484, 121 | 0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74, 122 | 0xbc86ee4ac08b7db0, 0x3fee9f9a48a58174, 123 | 0xbc8619321e55e68a, 0x3fee9feb564267c9, 124 | 0x3c909ccb5e09d4d3, 0x3feea0694fde5d3f, 125 | 0xbc7b32dcb94da51d, 0x3feea11473eb0187, 126 | 0x3c94ecfd5467c06b, 0x3feea1ed0130c132, 127 | 0x3c65ebe1abd66c55, 0x3feea2f336cf4e62, 128 | 0xbc88a1c52fb3cf42, 0x3feea427543e1a12, 129 | 0xbc9369b6f13b3734, 0x3feea589994cce13, 130 | 0xbc805e843a19ff1e, 0x3feea71a4623c7ad, 131 | 0xbc94d450d872576e, 0x3feea8d99b4492ed, 132 | 0x3c90ad675b0e8a00, 0x3feeaac7d98a6699, 133 | 0x3c8db72fc1f0eab4, 0x3feeace5422aa0db, 134 | 0xbc65b6609cc5e7ff, 0x3feeaf3216b5448c, 135 | 0x3c7bf68359f35f44, 0x3feeb1ae99157736, 136 | 0xbc93091fa71e3d83, 0x3feeb45b0b91ffc6, 137 | 0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5, 138 | 0xbc6c23f97c90b959, 0x3feeba44cbc8520f, 139 | 0xbc92434322f4f9aa, 0x3feebd829fde4e50, 140 | 0xbc85ca6cd7668e4b, 0x3feec0f170ca07ba, 141 | 0x3c71affc2b91ce27, 0x3feec49182a3f090, 142 | 0x3c6dd235e10a73bb, 0x3feec86319e32323, 143 | 0xbc87c50422622263, 0x3feecc667b5de565, 144 | 0x3c8b1c86e3e231d5, 0x3feed09bec4a2d33, 145 | 0xbc91bbd1d3bcbb15, 0x3feed503b23e255d, 146 | 0x3c90cc319cee31d2, 0x3feed99e1330b358, 147 | 0x3c8469846e735ab3, 0x3feede6b5579fdbf, 148 | 0xbc82dfcd978e9db4, 0x3feee36bbfd3f37a, 149 | 0x3c8c1a7792cb3387, 0x3feee89f995ad3ad, 150 | 0xbc907b8f4ad1d9fa, 0x3feeee07298db666, 151 | 0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb, 152 | 0xbc90a40e3da6f640, 0x3feef9728de5593a, 153 | 0xbc68d6f438ad9334, 0x3feeff76f2fb5e47, 154 | 0xbc91eee26b588a35, 0x3fef05b030a1064a, 155 | 0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2, 156 | 0xbc91bdfbfa9298ac, 0x3fef12c25bd71e09, 157 | 0x3c736eae30af0cb3, 0x3fef199bdd85529c, 158 | 0x3c8ee3325c9ffd94, 0x3fef20ab5fffd07a, 159 | 0x3c84e08fd10959ac, 0x3fef27f12e57d14b, 160 | 0x3c63cdaf384e1a67, 0x3fef2f6d9406e7b5, 161 | 0x3c676b2c6c921968, 0x3fef3720dcef9069, 162 | 0xbc808a1883ccb5d2, 0x3fef3f0b555dc3fa, 163 | 0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c, 164 | 0xbc900dae3875a949, 0x3fef4f87080d89f2, 165 | 0x3c74a385a63d07a7, 0x3fef5818dcfba487, 166 | 0xbc82919e2040220f, 0x3fef60e316c98398, 167 | 0x3c8e5a50d5c192ac, 0x3fef69e603db3285, 168 | 0x3c843a59ac016b4b, 0x3fef7321f301b460, 169 | 0xbc82d52107b43e1f, 0x3fef7c97337b9b5f, 170 | 0xbc892ab93b470dc9, 0x3fef864614f5a129, 171 | 0x3c74b604603a88d3, 0x3fef902ee78b3ff6, 172 | 0x3c83c5ec519d7271, 0x3fef9a51fbc74c83, 173 | 0xbc8ff7128fd391f0, 0x3fefa4afa2a490da, 174 | 0xbc8dae98e223747d, 0x3fefaf482d8e67f1, 175 | 0x3c8ec3bc41aa2008, 0x3fefba1bee615a27, 176 | 0x3c842b94c3a9eb32, 0x3fefc52b376bba97, 177 | 0x3c8a64a931d185ee, 0x3fefd0765b6e4540, 178 | 0xbc8e37bae43be3ed, 0x3fefdbfdad9cbe14, 179 | 0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8, 180 | 0x3c5305c14160cc89, 0x3feff3c22b8f71f1, 181 | }, 182 | }; 183 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef _ATOMIC_H 2 | #define _ATOMIC_H 3 | 4 | #include 5 | 6 | #include "atomic_arch.h" 7 | 8 | #ifdef a_ll 9 | 10 | #ifndef a_pre_llsc 11 | #define a_pre_llsc() 12 | #endif 13 | 14 | #ifndef a_post_llsc 15 | #define a_post_llsc() 16 | #endif 17 | 18 | #ifndef a_cas 19 | #define a_cas a_cas 20 | static inline int a_cas(volatile int *p, int t, int s) 21 | { 22 | int old; 23 | a_pre_llsc(); 24 | do old = a_ll(p); 25 | while (old==t && !a_sc(p, s)); 26 | a_post_llsc(); 27 | return old; 28 | } 29 | #endif 30 | 31 | #ifndef a_swap 32 | #define a_swap a_swap 33 | static inline int a_swap(volatile int *p, int v) 34 | { 35 | int old; 36 | a_pre_llsc(); 37 | do old = a_ll(p); 38 | while (!a_sc(p, v)); 39 | a_post_llsc(); 40 | return old; 41 | } 42 | #endif 43 | 44 | #ifndef a_fetch_add 45 | #define a_fetch_add a_fetch_add 46 | static inline int a_fetch_add(volatile int *p, int v) 47 | { 48 | int old; 49 | a_pre_llsc(); 50 | do old = a_ll(p); 51 | while (!a_sc(p, (unsigned)old + v)); 52 | a_post_llsc(); 53 | return old; 54 | } 55 | #endif 56 | 57 | #ifndef a_fetch_and 58 | #define a_fetch_and a_fetch_and 59 | static inline int a_fetch_and(volatile int *p, int v) 60 | { 61 | int old; 62 | a_pre_llsc(); 63 | do old = a_ll(p); 64 | while (!a_sc(p, old & v)); 65 | a_post_llsc(); 66 | return old; 67 | } 68 | #endif 69 | 70 | #ifndef a_fetch_or 71 | #define a_fetch_or a_fetch_or 72 | static inline int a_fetch_or(volatile int *p, int v) 73 | { 74 | int old; 75 | a_pre_llsc(); 76 | do old = a_ll(p); 77 | while (!a_sc(p, old | v)); 78 | a_post_llsc(); 79 | return old; 80 | } 81 | #endif 82 | 83 | #endif 84 | 85 | #ifdef a_ll_p 86 | 87 | #ifndef a_cas_p 88 | #define a_cas_p a_cas_p 89 | static inline void *a_cas_p(volatile void *p, void *t, void *s) 90 | { 91 | void *old; 92 | a_pre_llsc(); 93 | do old = a_ll_p(p); 94 | while (old==t && !a_sc_p(p, s)); 95 | a_post_llsc(); 96 | return old; 97 | } 98 | #endif 99 | 100 | #endif 101 | 102 | #ifndef a_cas 103 | #error missing definition of a_cas 104 | #endif 105 | 106 | #ifndef a_swap 107 | #define a_swap a_swap 108 | static inline int a_swap(volatile int *p, int v) 109 | { 110 | int old; 111 | do old = *p; 112 | while (a_cas(p, old, v) != old); 113 | return old; 114 | } 115 | #endif 116 | 117 | #ifndef a_fetch_add 118 | #define a_fetch_add a_fetch_add 119 | static inline int a_fetch_add(volatile int *p, int v) 120 | { 121 | int old; 122 | do old = *p; 123 | while (a_cas(p, old, (unsigned)old+v) != old); 124 | return old; 125 | } 126 | #endif 127 | 128 | #ifndef a_fetch_and 129 | #define a_fetch_and a_fetch_and 130 | static inline int a_fetch_and(volatile int *p, int v) 131 | { 132 | int old; 133 | do old = *p; 134 | while (a_cas(p, old, old&v) != old); 135 | return old; 136 | } 137 | #endif 138 | #ifndef a_fetch_or 139 | #define a_fetch_or a_fetch_or 140 | static inline int a_fetch_or(volatile int *p, int v) 141 | { 142 | int old; 143 | do old = *p; 144 | while (a_cas(p, old, old|v) != old); 145 | return old; 146 | } 147 | #endif 148 | 149 | #ifndef a_and 150 | #define a_and a_and 151 | static inline void a_and(volatile int *p, int v) 152 | { 153 | a_fetch_and(p, v); 154 | } 155 | #endif 156 | 157 | #ifndef a_or 158 | #define a_or a_or 159 | static inline void a_or(volatile int *p, int v) 160 | { 161 | a_fetch_or(p, v); 162 | } 163 | #endif 164 | 165 | #ifndef a_inc 166 | #define a_inc a_inc 167 | static inline void a_inc(volatile int *p) 168 | { 169 | a_fetch_add(p, 1); 170 | } 171 | #endif 172 | 173 | #ifndef a_dec 174 | #define a_dec a_dec 175 | static inline void a_dec(volatile int *p) 176 | { 177 | a_fetch_add(p, -1); 178 | } 179 | #endif 180 | 181 | #ifndef a_store 182 | #define a_store a_store 183 | static inline void a_store(volatile int *p, int v) 184 | { 185 | #ifdef a_barrier 186 | a_barrier(); 187 | *p = v; 188 | a_barrier(); 189 | #else 190 | a_swap(p, v); 191 | #endif 192 | } 193 | #endif 194 | 195 | #ifndef a_barrier 196 | #define a_barrier a_barrier 197 | static void a_barrier() 198 | { 199 | volatile int tmp = 0; 200 | a_cas(&tmp, 0, 0); 201 | } 202 | #endif 203 | 204 | #ifndef a_spin 205 | #define a_spin a_barrier 206 | #endif 207 | 208 | #ifndef a_and_64 209 | #define a_and_64 a_and_64 210 | static inline void a_and_64(volatile uint64_t *p, uint64_t v) 211 | { 212 | union { uint64_t v; uint32_t r[2]; } u = { v }; 213 | if (u.r[0]+1) a_and((int *)p, u.r[0]); 214 | if (u.r[1]+1) a_and((int *)p+1, u.r[1]); 215 | } 216 | #endif 217 | 218 | #ifndef a_or_64 219 | #define a_or_64 a_or_64 220 | static inline void a_or_64(volatile uint64_t *p, uint64_t v) 221 | { 222 | union { uint64_t v; uint32_t r[2]; } u = { v }; 223 | if (u.r[0]) a_or((int *)p, u.r[0]); 224 | if (u.r[1]) a_or((int *)p+1, u.r[1]); 225 | } 226 | #endif 227 | 228 | #ifndef a_cas_p 229 | typedef char a_cas_p_undefined_but_pointer_not_32bit[-sizeof(char) == 0xffffffff ? 1 : -1]; 230 | #define a_cas_p a_cas_p 231 | static inline void *a_cas_p(volatile void *p, void *t, void *s) 232 | { 233 | return (void *)a_cas((volatile int *)p, (int)t, (int)s); 234 | } 235 | #endif 236 | 237 | #ifndef a_or_l 238 | #define a_or_l a_or_l 239 | static inline void a_or_l(volatile void *p, long v) 240 | { 241 | if (sizeof(long) == sizeof(int)) a_or(p, v); 242 | else a_or_64(p, v); 243 | } 244 | #endif 245 | 246 | #ifndef a_crash 247 | #define a_crash a_crash 248 | static inline void a_crash() 249 | { 250 | *(volatile char *)0=0; 251 | } 252 | #endif 253 | 254 | #ifndef a_ctz_32 255 | #define a_ctz_32 a_ctz_32 256 | static inline int a_ctz_32(uint32_t x) 257 | { 258 | #ifdef a_clz_32 259 | return 31-a_clz_32(x&-x); 260 | #else 261 | static const char debruijn32[32] = { 262 | 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, 263 | 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14 264 | }; 265 | return debruijn32[(x&-x)*0x076be629 >> 27]; 266 | #endif 267 | } 268 | #endif 269 | 270 | #ifndef a_ctz_64 271 | #define a_ctz_64 a_ctz_64 272 | static inline int a_ctz_64(uint64_t x) 273 | { 274 | static const char debruijn64[64] = { 275 | 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 276 | 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, 277 | 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 278 | 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 279 | }; 280 | if (sizeof(long) < 8) { 281 | uint32_t y = x; 282 | if (!y) { 283 | y = x>>32; 284 | return 32 + a_ctz_32(y); 285 | } 286 | return a_ctz_32(y); 287 | } 288 | return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58]; 289 | } 290 | #endif 291 | 292 | static inline int a_ctz_l(unsigned long x) 293 | { 294 | return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x); 295 | } 296 | 297 | #ifndef a_clz_64 298 | #define a_clz_64 a_clz_64 299 | static inline int a_clz_64(uint64_t x) 300 | { 301 | #ifdef a_clz_32 302 | if (x>>32) 303 | return a_clz_32(x>>32); 304 | return a_clz_32(x) + 32; 305 | #else 306 | uint32_t y; 307 | int r; 308 | if (x>>32) y=x>>32, r=0; else y=x, r=32; 309 | if (y>>16) y>>=16; else r |= 16; 310 | if (y>>8) y>>=8; else r |= 8; 311 | if (y>>4) y>>=4; else r |= 4; 312 | if (y>>2) y>>=2; else r |= 2; 313 | return r | !(y>>1); 314 | #endif 315 | } 316 | #endif 317 | 318 | #endif 319 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 AS generator 2 | 3 | ARG ARCH 4 | ENV ARCH=${ARCH:-x86_64} 5 | 6 | # assert ARCH is either x86_64 or aarch64 7 | RUN if [ "${ARCH}" != "x86_64" ] && [ "${ARCH}" != "aarch64" ]; then echo "Invalid ARCH: ${ARCH}. Must be 'x86_64' or 'aarch64'" >&2; exit 1; fi 8 | 9 | RUN apt-get update 10 | 11 | RUN apt-get install apt-utils sudo -y 12 | 13 | # Create user 14 | RUN useradd --create-home --shell=/bin/bash user 15 | RUN chown -R user /home/user/ 16 | # Add the user to sudoers 17 | RUN chmod -R o-w /etc/sudoers.d/ 18 | RUN usermod -aG sudo user 19 | # Give the user a password 20 | RUN echo user:user | chpasswd 21 | 22 | RUN apt-get install build-essential wget -y 23 | 24 | # some packages like libcrypt and libcxx has a regression which failed to build without -lpthread because newer glibc provides everything in libc.so 25 | RUN sed -i "s=libc_nonshared.a=libc_nonshared.a /lib/${ARCH}-linux-gnu/libpthread.so.0 /usr/lib/${ARCH}-linux-gnu/libpthread_nonshared.a=" /usr/lib/${ARCH}-linux-gnu/libc.so 26 | 27 | WORKDIR /data 28 | USER user 29 | 30 | COPY bootstrap-prefix.sh /data/ 31 | 32 | RUN PREFIX_DISABLE_RAP=yes STOP_BOOTSTRAP_AFTER=stage1 bash bootstrap-prefix.sh /tmp/gentoo noninteractive 33 | 34 | RUN truncate -s 0 /tmp/gentoo/var/db/repos/gentoo/profiles/package.mask 35 | 36 | # Disable __cxa_thread_atexit_impl 37 | COPY portage_bashrc /tmp/gentoo/tmp/etc/portage/bashrc 38 | 39 | COPY package.accept_keywords /tmp/package.accept_keywords 40 | 41 | RUN if [ "${ARCH}" = "aarch64" ]; then ln -s /tmp/gentoo/tmp/usr/lib /tmp/gentoo/tmp/usr/lib64; cp /tmp/package.accept_keywords /tmp/gentoo/tmp/etc/portage/package.accept_keywords; fi 42 | 43 | RUN PREFIX_DISABLE_RAP=yes STOP_BOOTSTRAP_AFTER=stage2 bash bootstrap-prefix.sh /tmp/gentoo noninteractive 44 | 45 | # Disable __cxa_thread_atexit_impl 46 | COPY portage_bashrc /tmp/gentoo/etc/portage/bashrc 47 | 48 | RUN if [ "${ARCH}" = "aarch64" ]; then ln -s /tmp/gentoo/usr/lib /tmp/gentoo/usr/lib64; cp /tmp/package.accept_keywords /tmp/gentoo/etc/portage/package.accept_keywords; echo 'PYTHON_TARGETS="python3_12"' >> /tmp/gentoo/etc/portage/make.conf/0100_bootstrap_prefix_make.conf; fi 49 | 50 | RUN PREFIX_DISABLE_RAP=yes STOP_BOOTSTRAP_AFTER=stage3 bash bootstrap-prefix.sh /tmp/gentoo noninteractive 51 | 52 | RUN PREFIX_DISABLE_RAP=yes bash bootstrap-prefix.sh /tmp/gentoo noninteractive 53 | 54 | USER root 55 | 56 | ENV DEBIAN_FRONTEND=noninteractive 57 | 58 | RUN apt-get install \ 59 | cmake \ 60 | pkg-config \ 61 | tzdata \ 62 | python3-pip \ 63 | python-dev \ 64 | musl-tools \ 65 | binutils-dev \ 66 | libiberty-dev \ 67 | build-essential \ 68 | fakeroot \ 69 | dpkg-dev \ 70 | git \ 71 | flex \ 72 | autoconf \ 73 | google-perftools \ 74 | libssl-dev \ 75 | gettext \ 76 | file \ 77 | quilt \ 78 | gawk \ 79 | debhelper \ 80 | rdfind \ 81 | symlinks \ 82 | netbase \ 83 | gperf \ 84 | bison \ 85 | systemtap-sdt-dev \ 86 | libaudit-dev \ 87 | libcap-dev \ 88 | libselinux-dev \ 89 | zlib1g-dev \ 90 | libtinfo-dev \ 91 | libffi-dev \ 92 | libunwind-dev \ 93 | po-debconf \ 94 | yasm \ 95 | rsync \ 96 | libltdl7 \ 97 | vim \ 98 | --yes --no-install-recommends 99 | 100 | RUN if [ "${ARCH}" = "x86_64" ]; then apt-get install g++-7-multilib --yes --no-install-recommends; fi 101 | 102 | FROM generator AS glibc 103 | 104 | WORKDIR /opt 105 | 106 | RUN wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/glibc/2.27-3ubuntu1.6/glibc_2.27-3ubuntu1.6.dsc 107 | 108 | RUN wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/glibc/2.27-3ubuntu1.6/glibc_2.27.orig.tar.xz 109 | 110 | RUN wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/glibc/2.27-3ubuntu1.6/glibc_2.27-3ubuntu1.6.debian.tar.xz 111 | 112 | RUN dpkg-source -x glibc_2.27-3ubuntu1.6.dsc 113 | 114 | WORKDIR /opt/glibc-2.27 115 | 116 | RUN sed -i "s/if (__glibc_unlikely (__access (preload_file, R_OK) == 0))/if (false)/" elf/rtld.c 117 | 118 | RUN DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -rfakeroot -b 119 | 120 | FROM generator 121 | 122 | COPY --from=glibc /opt/libc6_2.27-3ubuntu1.6_*.deb /opt/ 123 | 124 | RUN dpkg -i /opt/libc6_2.27-3ubuntu1.6_*.deb 125 | 126 | RUN wget https://github.com/Kitware/CMake/releases/download/v3.29.0/cmake-3.29.0-linux-${ARCH}.tar.gz -O /opt/cmake-3.29.0-linux-${ARCH}.tar.gz 127 | 128 | RUN wget https://github.com/NixOS/patchelf/releases/download/0.14.3/patchelf-0.14.3-${ARCH}.tar.gz -O /opt/patchelf-0.14.3-${ARCH}.tar.gz 129 | 130 | RUN if [ "${ARCH}" = "x86_64" ]; then wget https://github.com/apple/foundationdb/releases/download/7.1.59/foundationdb-clients_7.1.59-1_amd64.deb -O /opt/foundationdb-clients_7.1.59-1_amd64.deb && dpkg -i /opt/foundationdb-clients_7.1.59-1_amd64.deb; fi 131 | 132 | RUN pip3 install setuptools 133 | 134 | RUN wget https://mirrors.tuna.tsinghua.edu.cn/gnu/bison/bison-3.5.1.tar.gz -O /opt/bison-3.5.1.tar.gz && \ 135 | cd /opt && \ 136 | tar zxf bison-3.5.1.tar.gz && \ 137 | cd bison-3.5.1 && \ 138 | env M4=m4 ./configure --prefix /usr --enable-relocatable && \ 139 | make && \ 140 | make install && \ 141 | cd .. && \ 142 | rm -rf bison-3.5.1 bison-3.5.1.tar.gz 143 | 144 | COPY execute-prefix.sh /data/ 145 | 146 | RUN mkdir -p /tmp/gentoo/etc/portage/env 147 | 148 | RUN bash -c "echo 'MYCMAKEARGS=\"\${MYCMAKEARGS} -DLIBOMP_ENABLE_SHARED=OFF\"' > /tmp/gentoo/etc/portage/env/openmp-static.conf" 149 | 150 | RUN bash -c 'echo llvm-runtimes/openmp openmp-static.conf > /tmp/gentoo/etc/portage/package.env' 151 | 152 | RUN bash -c 'echo "dev-libs/libaio static-libs" >> /tmp/gentoo/etc/portage/package.use' 153 | 154 | ENV GCC_VERSION=15 LLVM_VERSION=20 155 | 156 | RUN if [ "${ARCH}" = "aarch64" ]; then mkdir -p /tmp/gentoo/usr/lib/llvm/${LLVM_VERSION}/lib; ln -s /tmp/gentoo/usr/lib/llvm/${LLVM_VERSION}/lib /tmp/gentoo/usr/lib/llvm/${LLVM_VERSION}/lib64; echo 'FEATURES="-qa ${FEATURES}"' >> /tmp/gentoo/etc/portage/make.conf/0100_bootstrap_prefix_make.conf; fi 157 | 158 | RUN bash execute-prefix.sh emerge nasm libcxx lldb sys-libs/libunwind llvm-core/clang lld gdb llvm-runtimes/openmp dev-libs/libaio 159 | 160 | RUN bash execute-prefix.sh emerge --sync 161 | 162 | RUN bash execute-prefix.sh emerge --update --deep --changed-use @world 163 | 164 | RUN wget https://github.com/OpenMathLib/OpenBLAS/archive/refs/tags/v0.3.30.tar.gz -O /opt/OpenBLAS-0.3.30.tar.gz && \ 165 | cd /opt && \ 166 | tar zxf OpenBLAS-0.3.30.tar.gz && \ 167 | cd OpenBLAS-0.3.30 && \ 168 | export USE_THREAD=0 USE_LOCKING=1 DYNAMIC_ARCH=1 NO_AFFINITY=1 TARGET=GENERIC BUILD_BFLOAT16=1 NO_SHARED=1 && \ 169 | make && \ 170 | make install && \ 171 | cd .. && \ 172 | rm -rf OpenBLAS-0.3.30 OpenBLAS-0.3.30.tar.gz 173 | 174 | COPY OpenBLASConfig.cmake OpenBLASConfigVersion.cmake / 175 | 176 | RUN wget https://raw.githubusercontent.com/llvm/llvm-project/llvmorg-$(/tmp/gentoo/usr/lib/llvm/${LLVM_VERSION}/bin/clang --version | head -n 1 | awk '{print $3}')/libcxx/utils/gdb/libcxx/printers.py -O /opt/printers.py 177 | 178 | COPY generate_toolchain.sh setup_toolchain.sh disable_ld_preload.c / 179 | 180 | RUN mkdir /wrappers 181 | 182 | COPY tfg.py flamegraph bison ldb_gperf gcc g++ clang clang++ clangd curl /wrappers/ 183 | 184 | ADD tfg /wrappers/tfg 185 | 186 | RUN mkdir /tests 187 | 188 | COPY a.c /tests/ 189 | 190 | COPY FindThrift.cmake / 191 | 192 | ADD glibc-compatibility /glibc-compatibility 193 | 194 | WORKDIR /data 195 | 196 | ENTRYPOINT [ "/generate_toolchain.sh" ] 197 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/libm.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBM_H 2 | #define _LIBM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "musl_features.h" 9 | 10 | #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 11 | #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 12 | union ldshape { 13 | long double f; 14 | struct { 15 | uint64_t m; 16 | uint16_t se; 17 | } i; 18 | }; 19 | #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 20 | /* This is the m68k variant of 80-bit long double, and this definition only works 21 | * on archs where the alignment requirement of uint64_t is <= 4. */ 22 | union ldshape { 23 | long double f; 24 | struct { 25 | uint16_t se; 26 | uint16_t pad; 27 | uint64_t m; 28 | } i; 29 | }; 30 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN 31 | union ldshape { 32 | long double f; 33 | struct { 34 | uint64_t lo; 35 | uint32_t mid; 36 | uint16_t top; 37 | uint16_t se; 38 | } i; 39 | struct { 40 | uint64_t lo; 41 | uint64_t hi; 42 | } i2; 43 | }; 44 | #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN 45 | union ldshape { 46 | long double f; 47 | struct { 48 | uint16_t se; 49 | uint16_t top; 50 | uint32_t mid; 51 | uint64_t lo; 52 | } i; 53 | struct { 54 | uint64_t hi; 55 | uint64_t lo; 56 | } i2; 57 | }; 58 | #else 59 | #error Unsupported long double representation 60 | #endif 61 | 62 | /* Support non-nearest rounding mode. */ 63 | #define WANT_ROUNDING 1 64 | /* Support signaling NaNs. */ 65 | #define WANT_SNAN 0 66 | 67 | #if WANT_SNAN 68 | #error SNaN is unsupported 69 | #else 70 | #define issignalingf_inline(x) 0 71 | #define issignaling_inline(x) 0 72 | #endif 73 | 74 | #ifndef TOINT_INTRINSICS 75 | #define TOINT_INTRINSICS 0 76 | #endif 77 | 78 | #if TOINT_INTRINSICS 79 | /* Round x to nearest int in all rounding modes, ties have to be rounded 80 | consistently with converttoint so the results match. If the result 81 | would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ 82 | static double_t roundtoint(double_t); 83 | 84 | /* Convert x to nearest int in all rounding modes, ties have to be rounded 85 | consistently with roundtoint. If the result is not representible in an 86 | int32_t then the semantics is unspecified. */ 87 | static int32_t converttoint(double_t); 88 | #endif 89 | 90 | /* Helps static branch prediction so hot path can be better optimized. */ 91 | #ifdef __GNUC__ 92 | #define predict_true(x) __builtin_expect(!!(x), 1) 93 | #define predict_false(x) __builtin_expect(x, 0) 94 | #else 95 | #define predict_true(x) (x) 96 | #define predict_false(x) (x) 97 | #endif 98 | 99 | /* Evaluate an expression as the specified type. With standard excess 100 | precision handling a type cast or assignment is enough (with 101 | -ffloat-store an assignment is required, in old compilers argument 102 | passing and return statement may not drop excess precision). */ 103 | 104 | static inline float eval_as_float(float x) 105 | { 106 | float y = x; 107 | return y; 108 | } 109 | 110 | static inline double eval_as_double(double x) 111 | { 112 | double y = x; 113 | return y; 114 | } 115 | 116 | /* fp_barrier returns its input, but limits code transformations 117 | as if it had a side-effect (e.g. observable io) and returned 118 | an arbitrary value. */ 119 | 120 | #ifndef fp_barrierf 121 | #define fp_barrierf fp_barrierf 122 | static inline float fp_barrierf(float x) 123 | { 124 | volatile float y = x; 125 | return y; 126 | } 127 | #endif 128 | 129 | #ifndef fp_barrier 130 | #define fp_barrier fp_barrier 131 | static inline double fp_barrier(double x) 132 | { 133 | volatile double y = x; 134 | return y; 135 | } 136 | #endif 137 | 138 | #ifndef fp_barrierl 139 | #define fp_barrierl fp_barrierl 140 | static inline long double fp_barrierl(long double x) 141 | { 142 | volatile long double y = x; 143 | return y; 144 | } 145 | #endif 146 | 147 | /* fp_force_eval ensures that the input value is computed when that's 148 | otherwise unused. To prevent the constant folding of the input 149 | expression, an additional fp_barrier may be needed or a compilation 150 | mode that does so (e.g. -frounding-math in gcc). Then it can be 151 | used to evaluate an expression for its fenv side-effects only. */ 152 | 153 | #ifndef fp_force_evalf 154 | #define fp_force_evalf fp_force_evalf 155 | static inline void fp_force_evalf(float x) 156 | { 157 | volatile float y; 158 | y = x; 159 | } 160 | #endif 161 | 162 | #ifndef fp_force_eval 163 | #define fp_force_eval fp_force_eval 164 | static inline void fp_force_eval(double x) 165 | { 166 | volatile double y; 167 | y = x; 168 | } 169 | #endif 170 | 171 | #ifndef fp_force_evall 172 | #define fp_force_evall fp_force_evall 173 | static inline void fp_force_evall(long double x) 174 | { 175 | volatile long double y; 176 | y = x; 177 | } 178 | #endif 179 | 180 | #define FORCE_EVAL(x) do { \ 181 | if (sizeof(x) == sizeof(float)) { \ 182 | fp_force_evalf(x); \ 183 | } else if (sizeof(x) == sizeof(double)) { \ 184 | fp_force_eval(x); \ 185 | } else { \ 186 | fp_force_evall(x); \ 187 | } \ 188 | } while(0) 189 | 190 | #define asuint(f) ((union{float _f; uint32_t _i;}){f})._i 191 | #define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f 192 | #define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i 193 | #define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f 194 | 195 | #define EXTRACT_WORDS(hi,lo,d) \ 196 | do { \ 197 | uint64_t __u = asuint64(d); \ 198 | (hi) = __u >> 32; \ 199 | (lo) = (uint32_t)__u; \ 200 | } while (0) 201 | 202 | #define GET_HIGH_WORD(hi,d) \ 203 | do { \ 204 | (hi) = asuint64(d) >> 32; \ 205 | } while (0) 206 | 207 | #define GET_LOW_WORD(lo,d) \ 208 | do { \ 209 | (lo) = (uint32_t)asuint64(d); \ 210 | } while (0) 211 | 212 | #define INSERT_WORDS(d,hi,lo) \ 213 | do { \ 214 | (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ 215 | } while (0) 216 | 217 | #define SET_HIGH_WORD(d,hi) \ 218 | INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) 219 | 220 | #define SET_LOW_WORD(d,lo) \ 221 | INSERT_WORDS(d, asuint64(d)>>32, lo) 222 | 223 | #define GET_FLOAT_WORD(w,d) \ 224 | do { \ 225 | (w) = asuint(d); \ 226 | } while (0) 227 | 228 | #define SET_FLOAT_WORD(d,w) \ 229 | do { \ 230 | (d) = asfloat(w); \ 231 | } while (0) 232 | 233 | extern int __signgam; 234 | hidden double __lgamma_r(double, int *); 235 | hidden float __lgammaf_r(float, int *); 236 | 237 | /* error handling functions */ 238 | hidden float __math_xflowf(uint32_t, float); 239 | hidden float __math_uflowf(uint32_t); 240 | hidden float __math_oflowf(uint32_t); 241 | hidden float __math_divzerof(uint32_t); 242 | hidden float __math_invalidf(float); 243 | hidden double __math_xflow(uint32_t, double); 244 | hidden double __math_uflow(uint32_t); 245 | hidden double __math_oflow(uint32_t); 246 | hidden double __math_divzero(uint32_t); 247 | hidden double __math_invalid(double); 248 | 249 | #endif 250 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/log2_data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Data for log2. 3 | * 4 | * Copyright (c) 2018, Arm Limited. 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | #include "log2_data.h" 9 | 10 | #define N (1 << LOG2_TABLE_BITS) 11 | 12 | const struct log2_data __log2_data = { 13 | // First coefficient: 0x1.71547652b82fe1777d0ffda0d24p0 14 | .invln2hi = 0x1.7154765200000p+0, 15 | .invln2lo = 0x1.705fc2eefa200p-33, 16 | .poly1 = { 17 | // relative error: 0x1.2fad8188p-63 18 | // in -0x1.5b51p-5 0x1.6ab2p-5 19 | -0x1.71547652b82fep-1, 20 | 0x1.ec709dc3a03f7p-2, 21 | -0x1.71547652b7c3fp-2, 22 | 0x1.2776c50f05be4p-2, 23 | -0x1.ec709dd768fe5p-3, 24 | 0x1.a61761ec4e736p-3, 25 | -0x1.7153fbc64a79bp-3, 26 | 0x1.484d154f01b4ap-3, 27 | -0x1.289e4a72c383cp-3, 28 | 0x1.0b32f285aee66p-3, 29 | }, 30 | .poly = { 31 | // relative error: 0x1.a72c2bf8p-58 32 | // abs error: 0x1.67a552c8p-66 33 | // in -0x1.f45p-8 0x1.f45p-8 34 | -0x1.71547652b8339p-1, 35 | 0x1.ec709dc3a04bep-2, 36 | -0x1.7154764702ffbp-2, 37 | 0x1.2776c50034c48p-2, 38 | -0x1.ec7b328ea92bcp-3, 39 | 0x1.a6225e117f92ep-3, 40 | }, 41 | /* Algorithm: 42 | 43 | x = 2^k z 44 | log2(x) = k + log2(c) + log2(z/c) 45 | log2(z/c) = poly(z/c - 1) 46 | 47 | where z is in [1.6p-1; 1.6p0] which is split into N subintervals and z falls 48 | into the ith one, then table entries are computed as 49 | 50 | tab[i].invc = 1/c 51 | tab[i].logc = (double)log2(c) 52 | tab2[i].chi = (double)c 53 | tab2[i].clo = (double)(c - (double)c) 54 | 55 | where c is near the center of the subinterval and is chosen by trying +-2^29 56 | floating point invc candidates around 1/center and selecting one for which 57 | 58 | 1) the rounding error in 0x1.8p10 + logc is 0, 59 | 2) the rounding error in z - chi - clo is < 0x1p-64 and 60 | 3) the rounding error in (double)log2(c) is minimized (< 0x1p-68). 61 | 62 | Note: 1) ensures that k + logc can be computed without rounding error, 2) 63 | ensures that z/c - 1 can be computed as (z - chi - clo)*invc with close to a 64 | single rounding error when there is no fast fma for z*invc - 1, 3) ensures 65 | that logc + poly(z/c - 1) has small error, however near x == 1 when 66 | |log2(x)| < 0x1p-4, this is not enough so that is special cased. */ 67 | .tab = { 68 | {0x1.724286bb1acf8p+0, -0x1.1095feecdb000p-1}, 69 | {0x1.6e1f766d2cca1p+0, -0x1.08494bd76d000p-1}, 70 | {0x1.6a13d0e30d48ap+0, -0x1.00143aee8f800p-1}, 71 | {0x1.661ec32d06c85p+0, -0x1.efec5360b4000p-2}, 72 | {0x1.623fa951198f8p+0, -0x1.dfdd91ab7e000p-2}, 73 | {0x1.5e75ba4cf026cp+0, -0x1.cffae0cc79000p-2}, 74 | {0x1.5ac055a214fb8p+0, -0x1.c043811fda000p-2}, 75 | {0x1.571ed0f166e1ep+0, -0x1.b0b67323ae000p-2}, 76 | {0x1.53909590bf835p+0, -0x1.a152f5a2db000p-2}, 77 | {0x1.5014fed61adddp+0, -0x1.9217f5af86000p-2}, 78 | {0x1.4cab88e487bd0p+0, -0x1.8304db0719000p-2}, 79 | {0x1.49539b4334feep+0, -0x1.74189f9a9e000p-2}, 80 | {0x1.460cbdfafd569p+0, -0x1.6552bb5199000p-2}, 81 | {0x1.42d664ee4b953p+0, -0x1.56b23a29b1000p-2}, 82 | {0x1.3fb01111dd8a6p+0, -0x1.483650f5fa000p-2}, 83 | {0x1.3c995b70c5836p+0, -0x1.39de937f6a000p-2}, 84 | {0x1.3991c4ab6fd4ap+0, -0x1.2baa1538d6000p-2}, 85 | {0x1.3698e0ce099b5p+0, -0x1.1d98340ca4000p-2}, 86 | {0x1.33ae48213e7b2p+0, -0x1.0fa853a40e000p-2}, 87 | {0x1.30d191985bdb1p+0, -0x1.01d9c32e73000p-2}, 88 | {0x1.2e025cab271d7p+0, -0x1.e857da2fa6000p-3}, 89 | {0x1.2b404cf13cd82p+0, -0x1.cd3c8633d8000p-3}, 90 | {0x1.288b02c7ccb50p+0, -0x1.b26034c14a000p-3}, 91 | {0x1.25e2263944de5p+0, -0x1.97c1c2f4fe000p-3}, 92 | {0x1.234563d8615b1p+0, -0x1.7d6023f800000p-3}, 93 | {0x1.20b46e33eaf38p+0, -0x1.633a71a05e000p-3}, 94 | {0x1.1e2eefdcda3ddp+0, -0x1.494f5e9570000p-3}, 95 | {0x1.1bb4a580b3930p+0, -0x1.2f9e424e0a000p-3}, 96 | {0x1.19453847f2200p+0, -0x1.162595afdc000p-3}, 97 | {0x1.16e06c0d5d73cp+0, -0x1.f9c9a75bd8000p-4}, 98 | {0x1.1485f47b7e4c2p+0, -0x1.c7b575bf9c000p-4}, 99 | {0x1.12358ad0085d1p+0, -0x1.960c60ff48000p-4}, 100 | {0x1.0fef00f532227p+0, -0x1.64ce247b60000p-4}, 101 | {0x1.0db2077d03a8fp+0, -0x1.33f78b2014000p-4}, 102 | {0x1.0b7e6d65980d9p+0, -0x1.0387d1a42c000p-4}, 103 | {0x1.0953efe7b408dp+0, -0x1.a6f9208b50000p-5}, 104 | {0x1.07325cac53b83p+0, -0x1.47a954f770000p-5}, 105 | {0x1.05197e40d1b5cp+0, -0x1.d23a8c50c0000p-6}, 106 | {0x1.03091c1208ea2p+0, -0x1.16a2629780000p-6}, 107 | {0x1.0101025b37e21p+0, -0x1.720f8d8e80000p-8}, 108 | {0x1.fc07ef9caa76bp-1, 0x1.6fe53b1500000p-7}, 109 | {0x1.f4465d3f6f184p-1, 0x1.11ccce10f8000p-5}, 110 | {0x1.ecc079f84107fp-1, 0x1.c4dfc8c8b8000p-5}, 111 | {0x1.e573a99975ae8p-1, 0x1.3aa321e574000p-4}, 112 | {0x1.de5d6f0bd3de6p-1, 0x1.918a0d08b8000p-4}, 113 | {0x1.d77b681ff38b3p-1, 0x1.e72e9da044000p-4}, 114 | {0x1.d0cb5724de943p-1, 0x1.1dcd2507f6000p-3}, 115 | {0x1.ca4b2dc0e7563p-1, 0x1.476ab03dea000p-3}, 116 | {0x1.c3f8ee8d6cb51p-1, 0x1.7074377e22000p-3}, 117 | {0x1.bdd2b4f020c4cp-1, 0x1.98ede8ba94000p-3}, 118 | {0x1.b7d6c006015cap-1, 0x1.c0db86ad2e000p-3}, 119 | {0x1.b20366e2e338fp-1, 0x1.e840aafcee000p-3}, 120 | {0x1.ac57026295039p-1, 0x1.0790ab4678000p-2}, 121 | {0x1.a6d01bc2731ddp-1, 0x1.1ac056801c000p-2}, 122 | {0x1.a16d3bc3ff18bp-1, 0x1.2db11d4fee000p-2}, 123 | {0x1.9c2d14967feadp-1, 0x1.406464ec58000p-2}, 124 | {0x1.970e4f47c9902p-1, 0x1.52dbe093af000p-2}, 125 | {0x1.920fb3982bcf2p-1, 0x1.651902050d000p-2}, 126 | {0x1.8d30187f759f1p-1, 0x1.771d2cdeaf000p-2}, 127 | {0x1.886e5ebb9f66dp-1, 0x1.88e9c857d9000p-2}, 128 | {0x1.83c97b658b994p-1, 0x1.9a80155e16000p-2}, 129 | {0x1.7f405ffc61022p-1, 0x1.abe186ed3d000p-2}, 130 | {0x1.7ad22181415cap-1, 0x1.bd0f2aea0e000p-2}, 131 | {0x1.767dcf99eff8cp-1, 0x1.ce0a43dbf4000p-2}, 132 | }, 133 | #if !__FP_FAST_FMA 134 | .tab2 = { 135 | {0x1.6200012b90a8ep-1, 0x1.904ab0644b605p-55}, 136 | {0x1.66000045734a6p-1, 0x1.1ff9bea62f7a9p-57}, 137 | {0x1.69fffc325f2c5p-1, 0x1.27ecfcb3c90bap-55}, 138 | {0x1.6e00038b95a04p-1, 0x1.8ff8856739326p-55}, 139 | {0x1.71fffe09994e3p-1, 0x1.afd40275f82b1p-55}, 140 | {0x1.7600015590e1p-1, -0x1.2fd75b4238341p-56}, 141 | {0x1.7a00012655bd5p-1, 0x1.808e67c242b76p-56}, 142 | {0x1.7e0003259e9a6p-1, -0x1.208e426f622b7p-57}, 143 | {0x1.81fffedb4b2d2p-1, -0x1.402461ea5c92fp-55}, 144 | {0x1.860002dfafcc3p-1, 0x1.df7f4a2f29a1fp-57}, 145 | {0x1.89ffff78c6b5p-1, -0x1.e0453094995fdp-55}, 146 | {0x1.8e00039671566p-1, -0x1.a04f3bec77b45p-55}, 147 | {0x1.91fffe2bf1745p-1, -0x1.7fa34400e203cp-56}, 148 | {0x1.95fffcc5c9fd1p-1, -0x1.6ff8005a0695dp-56}, 149 | {0x1.9a0003bba4767p-1, 0x1.0f8c4c4ec7e03p-56}, 150 | {0x1.9dfffe7b92da5p-1, 0x1.e7fd9478c4602p-55}, 151 | {0x1.a1fffd72efdafp-1, -0x1.a0c554dcdae7ep-57}, 152 | {0x1.a5fffde04ff95p-1, 0x1.67da98ce9b26bp-55}, 153 | {0x1.a9fffca5e8d2bp-1, -0x1.284c9b54c13dep-55}, 154 | {0x1.adfffddad03eap-1, 0x1.812c8ea602e3cp-58}, 155 | {0x1.b1ffff10d3d4dp-1, -0x1.efaddad27789cp-55}, 156 | {0x1.b5fffce21165ap-1, 0x1.3cb1719c61237p-58}, 157 | {0x1.b9fffd950e674p-1, 0x1.3f7d94194cep-56}, 158 | {0x1.be000139ca8afp-1, 0x1.50ac4215d9bcp-56}, 159 | {0x1.c20005b46df99p-1, 0x1.beea653e9c1c9p-57}, 160 | {0x1.c600040b9f7aep-1, -0x1.c079f274a70d6p-56}, 161 | {0x1.ca0006255fd8ap-1, -0x1.a0b4076e84c1fp-56}, 162 | {0x1.cdfffd94c095dp-1, 0x1.8f933f99ab5d7p-55}, 163 | {0x1.d1ffff975d6cfp-1, -0x1.82c08665fe1bep-58}, 164 | {0x1.d5fffa2561c93p-1, -0x1.b04289bd295f3p-56}, 165 | {0x1.d9fff9d228b0cp-1, 0x1.70251340fa236p-55}, 166 | {0x1.de00065bc7e16p-1, -0x1.5011e16a4d80cp-56}, 167 | {0x1.e200002f64791p-1, 0x1.9802f09ef62ep-55}, 168 | {0x1.e600057d7a6d8p-1, -0x1.e0b75580cf7fap-56}, 169 | {0x1.ea00027edc00cp-1, -0x1.c848309459811p-55}, 170 | {0x1.ee0006cf5cb7cp-1, -0x1.f8027951576f4p-55}, 171 | {0x1.f2000782b7dccp-1, -0x1.f81d97274538fp-55}, 172 | {0x1.f6000260c450ap-1, -0x1.071002727ffdcp-59}, 173 | {0x1.f9fffe88cd533p-1, -0x1.81bdce1fda8bp-58}, 174 | {0x1.fdfffd50f8689p-1, 0x1.7f91acb918e6ep-55}, 175 | {0x1.0200004292367p+0, 0x1.b7ff365324681p-54}, 176 | {0x1.05fffe3e3d668p+0, 0x1.6fa08ddae957bp-55}, 177 | {0x1.0a0000a85a757p+0, -0x1.7e2de80d3fb91p-58}, 178 | {0x1.0e0001a5f3fccp+0, -0x1.1823305c5f014p-54}, 179 | {0x1.11ffff8afbaf5p+0, -0x1.bfabb6680bac2p-55}, 180 | {0x1.15fffe54d91adp+0, -0x1.d7f121737e7efp-54}, 181 | {0x1.1a00011ac36e1p+0, 0x1.c000a0516f5ffp-54}, 182 | {0x1.1e00019c84248p+0, -0x1.082fbe4da5dap-54}, 183 | {0x1.220000ffe5e6ep+0, -0x1.8fdd04c9cfb43p-55}, 184 | {0x1.26000269fd891p+0, 0x1.cfe2a7994d182p-55}, 185 | {0x1.2a00029a6e6dap+0, -0x1.00273715e8bc5p-56}, 186 | {0x1.2dfffe0293e39p+0, 0x1.b7c39dab2a6f9p-54}, 187 | {0x1.31ffff7dcf082p+0, 0x1.df1336edc5254p-56}, 188 | {0x1.35ffff05a8b6p+0, -0x1.e03564ccd31ebp-54}, 189 | {0x1.3a0002e0eaeccp+0, 0x1.5f0e74bd3a477p-56}, 190 | {0x1.3e000043bb236p+0, 0x1.c7dcb149d8833p-54}, 191 | {0x1.4200002d187ffp+0, 0x1.e08afcf2d3d28p-56}, 192 | {0x1.460000d387cb1p+0, 0x1.20837856599a6p-55}, 193 | {0x1.4a00004569f89p+0, -0x1.9fa5c904fbcd2p-55}, 194 | {0x1.4e000043543f3p+0, -0x1.81125ed175329p-56}, 195 | {0x1.51fffcc027f0fp+0, 0x1.883d8847754dcp-54}, 196 | {0x1.55ffffd87b36fp+0, -0x1.709e731d02807p-55}, 197 | {0x1.59ffff21df7bap+0, 0x1.7f79f68727b02p-55}, 198 | {0x1.5dfffebfc3481p+0, -0x1.180902e30e93ep-54}, 199 | }, 200 | #endif 201 | }; 202 | -------------------------------------------------------------------------------- /tfg/browser/visualtree.py: -------------------------------------------------------------------------------- 1 | """Call frames stack representation as a visual tree. 2 | Visual tree is a tree where each node contains an enough information to draw it on screen. 3 | """ 4 | from itertools import tee 5 | from functools import partial 6 | 7 | 8 | def pairwise(iterable): 9 | """Return an iterator to a pair 10 | s[] -> (s[0], s[1]), (s[2], s[3]), (s[4], s[5]), ... 11 | """ 12 | a, b = tee(iterable) 13 | next(b, None) 14 | return zip(a, b) 15 | 16 | 17 | def fit_string(text, width, ws_filler): 18 | """fit_string(text: str, width: int, ws_filler: str) 19 | Fit a 'text' string inside [0, width) range. Use ws_filler as a white space filler. 20 | """ 21 | if len(text) < width: 22 | return ''.join([text[:width], ws_filler * (width - len(text))]) 23 | return text[:width] 24 | 25 | 26 | def calculate_width(count, parent_count, parent_width): 27 | """calculate_width(count: int, parent_count: int, parent_width: int) 28 | Calculate string width based on parent width and sample count. 29 | """ 30 | return int(count * parent_width // parent_count) if parent_count != 0 else 0 31 | 32 | 33 | class VisualFrameNode(object): 34 | """Visual stack frame node. 35 | Store all necessary information to draw a stack frame node. 36 | 37 | Sometimes the number of samples for a stack frame can be so small that the calculated 38 | visual frame width is equal to 0. In that case, we will collect all those 'small' frames 39 | and create a single 'combined frame'. The user later, could select this frame and choose 40 | which 'small' frame he would like to examine. 41 | 42 | x - x coordinate on screen. 43 | y - y coordinate on screem. 44 | count - sample count (see CallFrameNode). 45 | width - width of the frame. 46 | text - text to display (always len(text) == width). To get the full text use 'cf'. 47 | Note: all those neighbor visual frames are used to easily navigate around a flame graph. 48 | parent_vf - parent VisualFrameNode. 49 | left_vf - left VisualFrameNode. 50 | right_vf - right VisualFrameNode. 51 | frames - child frames 52 | cf - original CallFrameNode. Equal to None in case of combined frames. 53 | zoomed - True if we're zooming in this frame. 54 | combined_frames - A list of combined frames. [CallFrameNode]. 55 | """ 56 | 57 | def __init__(self, x, y, count, width, text, pvf=None, lvf=None, rvf=None, cf=None): 58 | self.x = x 59 | self.y = y 60 | self.count = count 61 | self.width = width 62 | self.text = text 63 | self.parent_vf = pvf 64 | self.left_vf = lvf 65 | self.right_vf = rvf 66 | self.frames = [] 67 | self.cf = cf 68 | self.zoomed = False 69 | self.combined_frames = [] 70 | 71 | 72 | class VisualFrameTree(object): 73 | def __init__(self, call_tree, x, y, width, height, ws_filler=' ', with_combined_frames=True): 74 | """__init__(self, call_tree: CallFrameTree, x: int, y: int, width: int, height: int, 75 | ws_filler:str, with_combined_frames: bool) 76 | (x, y) - top left corner of the area to draw on. 77 | (width, height) - size of the area to draw on. 78 | """ 79 | self._call_tree = call_tree 80 | self._x = x 81 | self._y = y 82 | self._width = width 83 | self._height = height 84 | self._ws_filler = ws_filler 85 | self._start_vf = None 86 | self._with_combined_frames = with_combined_frames 87 | self.rebuild_tree() 88 | self.link_frames() 89 | 90 | def rebuild_tree(self, start_vf=None): 91 | """Rebuild the whole tree. Use start_vf as a zoomed frame. 92 | """ 93 | text = fit_string(self._call_tree.head.name, self._width, self._ws_filler) 94 | self._head = VisualFrameNode(self._x, 0, self._call_tree.head.count, self._width, text) 95 | self._head.cf = self._call_tree.head 96 | self._head.zoomed = True 97 | start_vf = self._create_start_vf(start_vf, self._width) 98 | self._create_vf_children(start_vf, start_vf.cf) 99 | return start_vf 100 | 101 | def link_frames(self): 102 | """Link left and right frames. 103 | """ 104 | for lvf, rvf in pairwise(self.bfs_traversal()): 105 | lvf.left_vf = rvf 106 | rvf.right_vf = lvf 107 | 108 | def dfs_traversal(self): 109 | """Return depth-first search traversal iterator. 110 | """ 111 | def dfs_iterator(vf): 112 | yield vf 113 | for child_vf in vf.frames: 114 | for vf_yield in dfs_iterator(child_vf): 115 | yield vf_yield 116 | return partial(dfs_iterator, self._head)() 117 | 118 | def bfs_traversal(self): 119 | """Return breadth-first search traversal iterator. 120 | """ 121 | def bfs_iterator(vf): 122 | queue = [vf] 123 | while queue: 124 | vf = queue.pop(0) 125 | yield vf 126 | queue.extend(vf.frames) 127 | return partial(bfs_iterator, self._head)() 128 | 129 | def level_traversal(self): 130 | """Return level traversal iterator. 131 | """ 132 | def level_iterator(vf): 133 | bfs = self.bfs_traversal() 134 | vfs = [next(bfs)] 135 | for vf in bfs: 136 | if vfs[0].y == vf.y: 137 | vfs.append(vf) 138 | else: 139 | yield vfs 140 | vfs = [vf] 141 | if vfs: 142 | yield vfs 143 | return partial(level_iterator, self._head)() 144 | 145 | @property 146 | def with_combined_frames(self): 147 | return self._with_combined_frames 148 | 149 | @with_combined_frames.setter 150 | def with_combined_frames(self, value): 151 | self._with_combined_frames = value 152 | 153 | @property 154 | def head(self): 155 | return self._head 156 | 157 | @property 158 | def start_vf(self): 159 | return self._start_vf 160 | 161 | def _create_start_vf(self, start_vf, width): 162 | """Create start visual frame. 163 | """ 164 | if start_vf is not None and start_vf != self._head: 165 | start_vf_parents = [] 166 | start_vf_parent = start_vf 167 | while start_vf_parent is not None: 168 | start_vf_parents.append(start_vf_parent) 169 | start_vf_parent = start_vf_parent.parent_vf 170 | 171 | self._start_vf = self._head 172 | for parent in start_vf_parents[:-1][::-1]: 173 | text = fit_string(parent.cf.name, width, self._ws_filler) 174 | vf = VisualFrameNode(self._x, parent.y, parent.count, width, text, self._start_vf) 175 | vf.cf = parent.cf 176 | self._start_vf.frames.append(vf) 177 | self._start_vf = self._start_vf.frames[-1] 178 | self._start_vf.zoomed = True 179 | else: 180 | self._start_vf = self._head 181 | return self._start_vf 182 | 183 | def _create_vf_children(self, vf, cf): 184 | """Create children for 'vf' from 'cf.frames'. 185 | """ 186 | if not cf.frames: 187 | return 188 | 189 | x = vf.x + vf.width 190 | # All calculated widths 191 | vf_widths = [calculate_width(c.count, vf.count, vf.width) for c in cf.frames] 192 | # If at least one children has width == 0 193 | has_zero_vf = min(vf_widths) == 0 194 | vf_total_width = sum(vf_widths) 195 | has_combined = self._with_combined_frames and has_zero_vf 196 | 197 | combined_vfs = [] 198 | for child_cf in sorted(cf.frames, key=lambda c: c.name, reverse=True): 199 | child_vf = self._create_vf(x, 200 | vf.y + 1, 201 | vf, 202 | child_cf, 203 | has_combined and vf_total_width == vf.width) 204 | x -= child_vf.width 205 | # We will combine all vfs with width == 0 in one vf 206 | if child_vf.width > 0: 207 | self._create_vf_children(child_vf, child_cf) 208 | vf.frames.append(child_vf) 209 | else: 210 | combined_vfs.append(child_vf) 211 | 212 | # Push combined frame to 'vf' 213 | if has_combined: 214 | combined_vfs_total_count = sum(c.count for c in combined_vfs) 215 | vf_child = VisualFrameNode(x - 1, vf.y + 1, combined_vfs_total_count, 1, '+', vf) 216 | vf_child.combined_frames = combined_vfs 217 | vf.frames.append(vf_child) 218 | 219 | def _create_vf(self, x, y, parent_vf, cf, has_combined): 220 | """Create a visual frame. 221 | """ 222 | width = parent_vf.width 223 | if has_combined: 224 | width -= 1 225 | width = calculate_width(cf.count, parent_vf.count, width) 226 | text = fit_string(cf.name, width, self._ws_filler) 227 | return VisualFrameNode(x - width, y, cf.count, width, text, parent_vf, cf=cf) 228 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/getauxval.c: -------------------------------------------------------------------------------- 1 | #include "atomic.h" 2 | #include 3 | #include // open 4 | #include // O_RDONLY 5 | #include // read, close 6 | #include // ssize_t 7 | #include // perror, fprintf 8 | #include // ElfW 9 | #include 10 | 11 | #include "syscall.h" 12 | 13 | #if defined(__has_feature) 14 | #if __has_feature(memory_sanitizer) 15 | #include 16 | #endif 17 | #endif 18 | 19 | #define ARRAY_SIZE(a) sizeof((a))/sizeof((a[0])) 20 | 21 | /// Suppress TSan since it is possible for this code to be called from multiple threads, 22 | /// and initialization is safe to be done multiple times from multiple threads. 23 | #define NO_SANITIZE_THREAD __attribute__((__no_sanitize__("thread"))) 24 | 25 | // We don't have libc struct available here. 26 | // Compute aux vector manually (from /proc/self/auxv). 27 | // 28 | // Right now there are 51 AT_* constants. Custom kernels have been encountered 29 | // making use of up to 71. 128 should be enough until this implementation is 30 | // replaced with musl. 31 | static unsigned long __auxv_procfs[128]; 32 | static unsigned long __auxv_secure = 0; 33 | // Common 34 | static unsigned long * __auxv_environ = NULL; 35 | 36 | static void * volatile getauxval_func; 37 | 38 | static unsigned long __auxv_init_environ(unsigned long type); 39 | 40 | // 41 | // auxv from procfs interface 42 | // 43 | ssize_t __retry_read(int fd, void * buf, size_t count) 44 | { 45 | for (;;) 46 | { 47 | // We cannot use the read syscall as it will be intercept by sanitizers, which aren't 48 | // initialized yet. Emit syscall directly. 49 | ssize_t ret = __syscall_ret(__syscall(SYS_read, fd, buf, count)); 50 | if (ret == -1) 51 | { 52 | if (errno == EINTR) 53 | { 54 | continue; 55 | } 56 | perror("Cannot read /proc/self/auxv"); 57 | abort(); 58 | } 59 | return ret; 60 | } 61 | } 62 | unsigned long NO_SANITIZE_THREAD __getauxval_procfs(unsigned long type) 63 | { 64 | if (type == AT_SECURE) 65 | { 66 | return __auxv_secure; 67 | } 68 | 69 | if (type >= ARRAY_SIZE(__auxv_procfs)) 70 | { 71 | errno = ENOENT; 72 | return 0; 73 | } 74 | 75 | return __auxv_procfs[type]; 76 | } 77 | static unsigned long NO_SANITIZE_THREAD __auxv_init_procfs(unsigned long type) 78 | { 79 | #if defined(__x86_64__) && defined(__has_feature) 80 | # if __has_feature(memory_sanitizer) || __has_feature(thread_sanitizer) 81 | /// Sanitizers are not compatible with high ASLR entropy, which is the default on modern Linux distributions, and 82 | /// to workaround this limitation, TSAN and MSAN (couldn't see other sanitizers doing the same), re-exec the binary 83 | /// without ASLR (see https://github.com/llvm/llvm-project/commit/0784b1eefa36d4acbb0dacd2d18796e26313b6c5) 84 | 85 | /// The problem we face is that, in order to re-exec, the sanitizer wants to use the original pathname in the call 86 | /// and to get its value it uses getauxval (https://github.com/llvm/llvm-project/blob/20eff684203287828d6722fc860b9d3621429542/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp#L985-L988). 87 | /// Since we provide getauxval ourselves (to minimize the version dependency on runtime glibc), we are the ones 88 | // being called and we fail horribly: 89 | /// 90 | /// ==301455==ERROR: MemorySanitizer: SEGV on unknown address 0x2ffc6d721550 (pc 0x5622c1cc0073 bp 0x000000000003 sp 0x7ffc6d721530 T301455) 91 | /// ==301455==The signal is caused by a WRITE memory access. 92 | /// #0 0x5622c1cc0073 in __auxv_init_procfs ./ClickHouse/base/glibc-compatibility/musl/getauxval.c:129:5 93 | /// #1 0x5622c1cbffe9 in getauxval ./ClickHouse/base/glibc-compatibility/musl/getauxval.c:240:12 94 | /// #2 0x5622c0d7bfb4 in __sanitizer::ReExec() crtstuff.c 95 | /// #3 0x5622c0df7bfc in __msan::InitShadowWithReExec(bool) crtstuff.c 96 | /// #4 0x5622c0d95356 in __msan_init (./ClickHouse/build_msan/contrib/google-protobuf-cmake/protoc+0x256356) (BuildId: 6411d3c88b898ba3f7d49760555977d3e61f0741) 97 | /// #5 0x5622c0dfe878 in msan.module_ctor main.cc 98 | /// #6 0x5622c1cc156c in __libc_csu_init (./ClickHouse/build_msan/contrib/google-protobuf-cmake/protoc+0x118256c) (BuildId: 6411d3c88b898ba3f7d49760555977d3e61f0741) 99 | /// #7 0x73dc05dd7ea3 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:343:6 100 | /// #8 0x5622c0d6b7cd in _start (./ClickHouse/build_msan/contrib/google-protobuf-cmake/protoc+0x22c7cd) (BuildId: 6411d3c88b898ba3f7d49760555977d3e61f0741) 101 | 102 | /// The source of the issue above is that, at this point in time during __msan_init, we can't really do much as 103 | /// most global variables aren't initialized or available yet, so we can't initiate the auxiliary vector. 104 | /// Normal glibc / musl getauxval doesn't have this problem since they initiate their auxval vector at the very 105 | /// start of __libc_start_main (just keeping track of argv+argc+1), but we don't have such option (otherwise 106 | /// this complexity of reading "/proc/self/auxv" or using __environ would not be necessary). 107 | 108 | /// To avoid this crashes on the re-exec call (see above how it would fail when creating `aux`, and if we used 109 | /// __auxv_init_environ then it would SIGSEV on READing `__environ`) we capture this call for `AT_EXECFN` and 110 | /// unconditionally return "/proc/self/exe" without any preparation. Theoretically this should be fine in 111 | /// our case, as we don't load any libraries. That's the theory at least. 112 | if (type == AT_EXECFN) 113 | return (unsigned long)"/proc/self/exe"; 114 | # endif 115 | #endif 116 | 117 | // For debugging: 118 | // - od -t dL /proc/self/auxv 119 | // - LD_SHOW_AUX= ls 120 | int fd = open("/proc/self/auxv", O_RDONLY); 121 | // It is possible in case of: 122 | // - no procfs mounted 123 | // - on android you are not able to read it unless running from shell or debugging 124 | // - some other issues 125 | if (fd == -1) 126 | { 127 | // Fallback to environ. 128 | a_cas_p(&getauxval_func, (void *)__auxv_init_procfs, (void *)__auxv_init_environ); 129 | return __auxv_init_environ(type); 130 | } 131 | 132 | ElfW(auxv_t) aux; 133 | 134 | /// NOTE: sizeof(aux) is very small (less then PAGE_SIZE), so partial read should not be possible. 135 | _Static_assert(sizeof(aux) < 4096, "Unexpected sizeof(aux)"); 136 | while (__retry_read(fd, &aux, sizeof(aux)) == sizeof(aux)) 137 | { 138 | #if defined(__has_feature) 139 | #if __has_feature(memory_sanitizer) 140 | __msan_unpoison(&aux, sizeof(aux)); 141 | #endif 142 | #endif 143 | if (aux.a_type == AT_NULL) 144 | { 145 | break; 146 | } 147 | if (aux.a_type == AT_IGNORE || aux.a_type == AT_IGNOREPPC) 148 | { 149 | continue; 150 | } 151 | 152 | if (aux.a_type >= ARRAY_SIZE(__auxv_procfs)) 153 | { 154 | fprintf(stderr, "AT_* is out of range: %li (maximum allowed is %zu)\n", aux.a_type, ARRAY_SIZE(__auxv_procfs)); 155 | abort(); 156 | } 157 | if (__auxv_procfs[aux.a_type]) 158 | { 159 | /// It is possible due to race on initialization. 160 | } 161 | __auxv_procfs[aux.a_type] = aux.a_un.a_val; 162 | } 163 | close(fd); 164 | 165 | __auxv_secure = __getauxval_procfs(AT_SECURE); 166 | 167 | // Now we've initialized __auxv_procfs, next time getauxval() will only call __get_auxval(). 168 | a_cas_p(&getauxval_func, (void *)__auxv_init_procfs, (void *)__getauxval_procfs); 169 | 170 | return __getauxval_procfs(type); 171 | } 172 | 173 | // 174 | // auxv from environ interface 175 | // 176 | // NOTE: environ available only after static initializers, 177 | // so you cannot rely on this if you need getauxval() before. 178 | // 179 | // Good example of such user is sanitizers, for example 180 | // LSan will not work with __auxv_init_environ(), 181 | // since it needs getauxval() before. 182 | // 183 | static size_t NO_SANITIZE_THREAD __find_auxv(unsigned long type) 184 | { 185 | size_t i; 186 | for (i = 0; __auxv_environ[i]; i += 2) 187 | { 188 | if (__auxv_environ[i] == type) 189 | { 190 | return i + 1; 191 | } 192 | } 193 | return (size_t) -1; 194 | } 195 | unsigned long NO_SANITIZE_THREAD __getauxval_environ(unsigned long type) 196 | { 197 | if (type == AT_SECURE) 198 | return __auxv_secure; 199 | 200 | if (__auxv_environ) 201 | { 202 | size_t index = __find_auxv(type); 203 | if (index != ((size_t) -1)) 204 | return __auxv_environ[index]; 205 | } 206 | 207 | errno = ENOENT; 208 | return 0; 209 | } 210 | static unsigned long NO_SANITIZE_THREAD __auxv_init_environ(unsigned long type) 211 | { 212 | if (!__environ) 213 | { 214 | // __environ is not initialized yet so we can't initialize __auxv_environ right now. 215 | // That's normally occurred only when getauxval() is called from some sanitizer's internal code. 216 | errno = ENOENT; 217 | return 0; 218 | } 219 | 220 | // Initialize __auxv_environ and __auxv_secure. 221 | size_t i; 222 | for (i = 0; __environ[i]; i++); 223 | __auxv_environ = (unsigned long *) (__environ + i + 1); 224 | 225 | size_t secure_idx = __find_auxv(AT_SECURE); 226 | if (secure_idx != ((size_t) -1)) 227 | __auxv_secure = __auxv_environ[secure_idx]; 228 | 229 | // Now we need to switch to __getauxval_environ for all later calls, since 230 | // everything is initialized. 231 | a_cas_p(&getauxval_func, (void *)__auxv_init_environ, (void *)__getauxval_environ); 232 | 233 | return __getauxval_environ(type); 234 | } 235 | 236 | // Callchain: 237 | // - __auxv_init_procfs -> __getauxval_environ 238 | // - __auxv_init_procfs -> __auxv_init_environ -> __getauxval_environ 239 | static void * volatile getauxval_func = (void *)__auxv_init_procfs; 240 | 241 | unsigned long NO_SANITIZE_THREAD getauxval(unsigned long type) 242 | { 243 | return ((unsigned long (*)(unsigned long))getauxval_func)(type); 244 | } 245 | -------------------------------------------------------------------------------- /glibc-compatibility/musl/lgamma.c: -------------------------------------------------------------------------------- 1 | /* origin: FreeBSD /usr/src/lib/msun/src/e_lgamma_r.c */ 2 | /* 3 | * ==================================================== 4 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 5 | * 6 | * Developed at SunSoft, a Sun Microsystems, Inc. business. 7 | * Permission to use, copy, modify, and distribute this 8 | * software is freely granted, provided that this notice 9 | * is preserved. 10 | * ==================================================== 11 | * 12 | */ 13 | /* lgamma_r(x, signgamp) 14 | * Reentrant version of the logarithm of the Gamma function 15 | * with user provide pointer for the sign of Gamma(x). 16 | * 17 | * Method: 18 | * 1. Argument Reduction for 0 < x <= 8 19 | * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may 20 | * reduce x to a number in [1.5,2.5] by 21 | * lgamma(1+s) = log(s) + lgamma(s) 22 | * for example, 23 | * lgamma(7.3) = log(6.3) + lgamma(6.3) 24 | * = log(6.3*5.3) + lgamma(5.3) 25 | * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) 26 | * 2. Polynomial approximation of lgamma around its 27 | * minimum ymin=1.461632144968362245 to maintain monotonicity. 28 | * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use 29 | * Let z = x-ymin; 30 | * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) 31 | * where 32 | * poly(z) is a 14 degree polynomial. 33 | * 2. Rational approximation in the primary interval [2,3] 34 | * We use the following approximation: 35 | * s = x-2.0; 36 | * lgamma(x) = 0.5*s + s*P(s)/Q(s) 37 | * with accuracy 38 | * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 39 | * Our algorithms are based on the following observation 40 | * 41 | * zeta(2)-1 2 zeta(3)-1 3 42 | * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... 43 | * 2 3 44 | * 45 | * where Euler = 0.5771... is the Euler constant, which is very 46 | * close to 0.5. 47 | * 48 | * 3. For x>=8, we have 49 | * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... 50 | * (better formula: 51 | * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) 52 | * Let z = 1/x, then we approximation 53 | * f(z) = lgamma(x) - (x-0.5)(log(x)-1) 54 | * by 55 | * 3 5 11 56 | * w = w0 + w1*z + w2*z + w3*z + ... + w6*z 57 | * where 58 | * |w - f(z)| < 2**-58.74 59 | * 60 | * 4. For negative x, since (G is gamma function) 61 | * -x*G(-x)*G(x) = pi/sin(pi*x), 62 | * we have 63 | * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) 64 | * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 65 | * Hence, for x<0, signgam = sign(sin(pi*x)) and 66 | * lgamma(x) = log(|Gamma(x)|) 67 | * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); 68 | * Note: one should avoid compute pi*(-x) directly in the 69 | * computation of sin(pi*(-x)). 70 | * 71 | * 5. Special Cases 72 | * lgamma(2+s) ~ s*(1-Euler) for tiny s 73 | * lgamma(1) = lgamma(2) = 0 74 | * lgamma(x) ~ -log(|x|) for tiny x 75 | * lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero 76 | * lgamma(inf) = inf 77 | * lgamma(-inf) = inf (bug for bug compatible with C99!?) 78 | * 79 | */ 80 | 81 | static const double 82 | pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ 83 | a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ 84 | a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ 85 | a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ 86 | a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ 87 | a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ 88 | a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ 89 | a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ 90 | a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ 91 | a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ 92 | a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ 93 | a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ 94 | a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ 95 | tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ 96 | tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ 97 | /* tt = -(tail of tf) */ 98 | tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ 99 | t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ 100 | t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ 101 | t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ 102 | t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ 103 | t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ 104 | t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ 105 | t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ 106 | t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ 107 | t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ 108 | t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ 109 | t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ 110 | t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ 111 | t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ 112 | t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ 113 | t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ 114 | u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ 115 | u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ 116 | u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ 117 | u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ 118 | u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ 119 | u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ 120 | v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ 121 | v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ 122 | v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ 123 | v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ 124 | v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ 125 | s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ 126 | s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ 127 | s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ 128 | s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ 129 | s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ 130 | s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ 131 | s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ 132 | r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ 133 | r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ 134 | r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ 135 | r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ 136 | r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ 137 | r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ 138 | w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ 139 | w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ 140 | w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ 141 | w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ 142 | w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ 143 | w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ 144 | w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ 145 | 146 | #include 147 | #include 148 | 149 | double lgamma_r(double x, int *signgamp) 150 | { 151 | union {double f; uint64_t i;} u = {x}; 152 | double_t t,y,z,nadj=0,p,p1,p2,p3,q,r,w; 153 | uint32_t ix; 154 | int sign,i; 155 | 156 | /* purge off +-inf, NaN, +-0, tiny and negative arguments */ 157 | *signgamp = 1; 158 | sign = u.i>>63; 159 | ix = u.i>>32 & 0x7fffffff; 160 | if (ix >= 0x7ff00000) 161 | return x*x; 162 | if (ix < (0x3ff-70)<<20) { /* |x|<2**-70, return -log(|x|) */ 163 | if(sign) { 164 | x = -x; 165 | *signgamp = -1; 166 | } 167 | return -log(x); 168 | } 169 | if (sign) { 170 | x = -x; 171 | t = sin(pi * x); 172 | if (t == 0.0) /* -integer */ 173 | return 1.0/(x-x); 174 | if (t > 0.0) 175 | *signgamp = -1; 176 | else 177 | t = -t; 178 | nadj = log(pi/(t*x)); 179 | } 180 | 181 | /* purge off 1 and 2 */ 182 | if ((ix == 0x3ff00000 || ix == 0x40000000) && (uint32_t)u.i == 0) 183 | r = 0; 184 | /* for x < 2.0 */ 185 | else if (ix < 0x40000000) { 186 | if (ix <= 0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */ 187 | r = -log(x); 188 | if (ix >= 0x3FE76944) { 189 | y = 1.0 - x; 190 | i = 0; 191 | } else if (ix >= 0x3FCDA661) { 192 | y = x - (tc-1.0); 193 | i = 1; 194 | } else { 195 | y = x; 196 | i = 2; 197 | } 198 | } else { 199 | r = 0.0; 200 | if (ix >= 0x3FFBB4C3) { /* [1.7316,2] */ 201 | y = 2.0 - x; 202 | i = 0; 203 | } else if(ix >= 0x3FF3B4C4) { /* [1.23,1.73] */ 204 | y = x - tc; 205 | i = 1; 206 | } else { 207 | y = x - 1.0; 208 | i = 2; 209 | } 210 | } 211 | switch (i) { 212 | case 0: 213 | z = y*y; 214 | p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); 215 | p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); 216 | p = y*p1+p2; 217 | r += (p-0.5*y); 218 | break; 219 | case 1: 220 | z = y*y; 221 | w = z*y; 222 | p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ 223 | p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); 224 | p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); 225 | p = z*p1-(tt-w*(p2+y*p3)); 226 | r += tf + p; 227 | break; 228 | case 2: 229 | p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); 230 | p2 = 1.0+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); 231 | r += -0.5*y + p1/p2; 232 | } 233 | } else if (ix < 0x40200000) { /* x < 8.0 */ 234 | i = (int)x; 235 | y = x - (double)i; 236 | p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); 237 | q = 1.0+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); 238 | r = 0.5*y+p/q; 239 | z = 1.0; /* lgamma(1+s) = log(s) + lgamma(s) */ 240 | switch (i) { 241 | case 7: z *= y + 6.0; /* FALLTHRU */ 242 | case 6: z *= y + 5.0; /* FALLTHRU */ 243 | case 5: z *= y + 4.0; /* FALLTHRU */ 244 | case 4: z *= y + 3.0; /* FALLTHRU */ 245 | case 3: z *= y + 2.0; /* FALLTHRU */ 246 | r += log(z); 247 | break; 248 | } 249 | } else if (ix < 0x43900000) { /* 8.0 <= x < 2**58 */ 250 | t = log(x); 251 | z = 1.0/x; 252 | y = z*z; 253 | w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); 254 | r = (x-0.5)*(t-1.0)+w; 255 | } else /* 2**58 <= x <= inf */ 256 | r = x*(log(x)-1.0); 257 | if (sign) 258 | r = nadj - r; 259 | return r; 260 | } 261 | --------------------------------------------------------------------------------