24 Commits
Author SHA1 Message Date
sisungo d65988fcf0 feat: adapt semios filesystem layout
Signed-off-by: sisungo <[email protected]>
2026-07-18 21:20:39 +08:00
sisungo 4360d2fd2e feat: add accountd support
Signed-off-by: sisungo <[email protected]>
2026-07-18 18:32:16 +08:00
sisungo da11edfa02 fix: malloc initialized before tls
Signed-off-by: sisungo <[email protected]>
2026-07-04 22:19:10 +08:00
sisungo 1c8ee1fa29 feat: update upstream musl libc to v1.2.6 2026-06-27 13:16:53 +08:00
Rich Felker 9fa28ece75 release 1.2.6 2026-03-20 11:40:00 -04:00
Tomáš HulataandRich Felker 1347154cdc vdso: add support for GNU hash tables
on some kernel builds, the vdso exports symbols with DT_GNU_HASH but
omits DT_HASH, causing the vdso not to get used and for clock_gettime
to fall back to using a syscall.

our vdso resolver does not use the hash table anyway, but does need
the symbol count from the standard sysv hash table. if it's missing,
use the GNU hashtable to calculate the number of symbols.
2026-03-19 09:57:35 -04:00
Rich Felker 149d872970 getgr*: validate group member lists from nscd backend
this corrects missing validation when using alternate group database
backends via nscd, as reported by 0rbitingZer0, which could result in
a heap-based buffer overflow.

while the source of truth for user (passwd) and group definitions is
generally an equal or higher-privilege domain than the application,
and compromise of nscd could inherently lead to bypass of some access
controls, it is still worthwhile to harden against direct attacks from
a compromised nscd.

this patch adds validation in the least invasive way possible,
erroring out at the point where a write past the end of the buffer
would previously have occurred.

a check is also added for member counts that would cause arithmetic
overflow in the existing buffer size computations, including negative
counts. this could be handled better by making adjustments where the
arithmetic is performed, but the way it's done here avoids making any
changes except for the actual bounds check.
2026-03-19 09:57:35 -04:00
Michal BiesekandRich Felker 19f9aeaaba sys/mman.h: add MADV_COLLAPSE from linux v6.1
Add madvise flag which performs a best-effort synchronous
collapse of the native pages mapped by the memory range
into Transparent Huge Pages (THPs)
see
  linux commit 7d8faaf155454f8798ec56404faca29a82689c77
  mm/madvise: introduce MADV_COLLAPSE sync hugepage collapse
2026-03-19 09:57:30 -04:00
Rich Felker 56df2e1fc1 sys/mman.h: add MADV_DONTNEED_LOCKED from linux v6.0
this flag works like MADV_DONTNEED but also applies to locked memory
ranges.

see
  linux commit 9457056ac426e5ed0671356509c8dcce69f8dee0
  mm: madvise: MADV_DONTNEED_LOCKED
2026-03-19 09:56:42 -04:00
Michal BiesekandRich Felker bb5693fa5e sys/mman.h: add MADV_POPULATE_(READ|WRITE) from linux v5.14
Add madvise flags to populate(prefault) page tables
see
  linux commit 4ca9b3859dac14bbef0c27d00667bb5b10917adb
  mm/madvise: introduce MADV_POPULATE_(READ|WRITE) to prefault page tables
2026-03-15 16:23:20 -04:00
Xing LiandRich Felker 9355c44311 loongarch64: add lsx and lasx regset definition 2026-03-12 21:21:50 -04:00
JianTao ShanandRich Felker b5146b83ab loongarch64: add fpu and simd context to signal.h
The signal stack extension field of loongarch64 is mutable, and the
types are distinguished according to some magic.
2026-03-12 20:39:22 -04:00
Jingyun HuaandRich Felker 38b00812ef loongarch64: add new reloc types and NT_LOONGARCH_HW_* into elf.h
These new LoongArch reloc types(101 to 126) have been added in
LoongArch psABI v2.30 and NT_LOONGARCH_HW_BREAK/NT_LOONGARCH_HW_WATCH
sync with Linux 6.12 elf.h.
2026-03-10 23:37:14 -04:00
Alex Rønne PetersenandRich Felker b37d241dfe fenv: add missing C dummy functions for loongarch64 soft float
analogous to fenv-sf.c for all other archs with softfloat variants.
2026-03-10 23:36:59 -04:00
Szabolcs NagyandRich Felker 5c901bb360 update syscalls up to linux 6.19
Add two missing syscalls from v5.14 and new syscalls from v6.4 .. v6.19

add __NR_quotactl_fd from linux v5.14 see

  linux commit 9dfa23c8de925041b7b45637a1a80a98a22f19dd
  quota: Add mountpath based quota support

  linux commit fa8b90070a80bb1a3042b4b25af4b3ee2c4c27e1
  quota: wire up quotactl_path

  linux commit 64c2c2c62f92339b176ea24403d8db16db36f9e6
  quota: Change quotactl_path() systcall to an fd-based one

add __NR_memfd_secret from linux v5.14 see

  linux commit 7bb7f2ac24a028b20fca466b9633847b289b156a
  arch, mm: wire up memfd_secret system call where relevant

  linux commit 1507f51255c9ff07d75909a84e7c0d7f3c4b2f49
  mm: introduce memfd_secret system call to create "secret" memory areas

note: was already added on x86 and s390, now on aarch64 and riscv*.

add riscv __NR_riscv_hwprobe from linux v6.4 see

  linux commit ea3de9ce8aa280c5175c835bd3e94a3a9b814b74
  RISC-V: Add a syscall for HW probing

add x86_64 only map_shadow_stack syscall from linux v6.6 see

  linux commit c35559f94ebc3e3bc82e56e07161bb5986cd9761
  x86/shstk: Introduce map_shadow_stack syscall

add map_shadow_stack syscall from linux v6.7 see

  linux commit 2fd0ebad27bcd4c8fc61c61a98d4283c47054bcf
  arch: Reserve map_shadow_stack() syscall number for all architectures

add futex_* syscalls from linux v6.7 see

  linux commit 9f6c532f59b20580acf8ede9409c9b8dce6e74e1
  futex: Add sys_futex_wake()

  linux commit cb8c4312afca1b2dc64107e7e7cea81911055612
  futex: Add sys_futex_wait()

  linux commit 0f4b5f972216782a4acb1ae00dcb55173847c2ff
  futex: Add sys_futex_requeue()

add statmount, listmount syscalls from linux v6.8 see

  linux commit d8b0f5465012538cc4bb10ddc4affadbab73465b
  wire up syscalls for statmount/listmount

  linux commit b4c2bea8ceaa50cd42a8f73667389d801a3ecf2d
  add listmount(2) syscall

  linux commit 46eae99ef73302f9fb3dddcd67c374b3dffe8fd6
  add statmount(2) syscall

add lsm_* syscalls from linux v6.8 see

  linux commit 5f42375904b08890f2e8e7cd955c5bf0c2c0d05a
  LSM: wireup Linux Security Module syscalls

  linux commit ad4aff9ec25f400608283c10d634cc4eeda83a02
  LSM: Create lsm_list_modules system call

  linux commit a04a1198088a1378d0389c250cc684f649bcc91e
  LSM: syscalls for current process attributes

add mseal syscall from linux v6.10 see

  linux commit ff388fe5c481d39cc0a5940d1ad46f7920f1d646
  mseal: wire up mseal syscall

on sh add sync_file_range2 from linux v6.10 see

  linux commit 30766f1105d6d2459c3b9fe34a3e52b637a72950
  sh: rework sync_file_range ABI

on x86 add uretprobe from linux v6.11 see

  linux commit 54233a4254036efca91b9bffbd398ecf39e90555
  uretprobe: change syscall number, again

add *xattrat syscalls from linux v6.13 see

  linux commit 6140be90ec70c39fa844741ca3cc807dd0866394
  fs/xattr: add *at family syscalls

add open_tree_attr from linux v6.15 see

  linux commit c4a16820d90199409c9bf01c4f794e1e9e8d8fd8
  fs: add open_tree_attr()

add file_{get,set}attr from linux v6.17 see

  linux commit be7efb2d20d67f334a7de2aef77ae6c69367e646
  fs: introduce file_getattr and file_setattr syscalls

on x86 add uprobe from linux v6.18 see

  linux commit 56101b69c9190667f473b9f93f8b6d8209aaa816
  uprobes/x86: Add uprobe syscall to speed up uprobe

add listns from linux v6.19 see

  linux commit b36d4b6aa88ef039647228b98c59a875e92f8c8e
  arch: hookup listns() system call
2026-03-10 23:06:02 -04:00
RocketDevandRich Felker 4268281ab4 getifaddr: fix typo ssl to sll
sll_addr is a member of sockaddr_ll, but it is misspelled as
ssl_addr in comment.

Please cc me back when reply.

Signed-off-by: RocketDev <[email protected]>
2026-03-10 22:49:31 -04:00
Michael ForneyandRich Felker 5c26c890ed mallocng: prevent stray ';' at top-level
The LOCK_OBJ_DEF macro is used with a trailing semicolon. However,
since the macro definition ends with the closing brace of a function
definition, the ISO C grammar does not allow an extra semicolon.

To fix this, swap the order of the two definitions, and drop the
semicolon from the __malloc_lock declaration.
2026-03-10 22:48:21 -04:00
sisungo 475334f2db feat: add rpmalloc 2026-02-23 13:16:42 +08:00
sisungo 9ed6813222 fix: stdatomic.h compatibility with gcc -std=c11/c17/...
Newer versions of gcc has __has_feature(x) macro, too, and returns
true on c_atomic, though it does not support Clang-flavored atomic
builtins.
2026-02-22 15:52:46 +08:00
sisungo 58c7494c47 feat: add malloc initialization 2026-02-22 14:56:49 +08:00
sisungo ccca821d4e fix: remove stdckdint.h cplusplus code to reduce size 2026-02-22 14:19:26 +08:00
sisungo 1d717f1afd feat: add C23 stdckdint.h 2026-02-22 14:05:01 +08:00
sisungo 8043aba13f feat: rename weak in features.h to __weak
The internal `features.h` defines macro `weak`, and it prevents us porting
third-party code including the identifier.
2026-02-22 13:42:41 +08:00
sisungo e7e10be26a feat: support C11 atomics 2026-02-22 13:01:19 +08:00
67 changed files with 9397 additions and 802 deletions
+2 -3
View File
@@ -17,7 +17,7 @@ includedir = $(prefix)/include
libdir = $(prefix)/lib
syslibdir = /lib
MALLOC_DIR = mallocng
MALLOC_DIR = rpmalloc
SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS))
BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
@@ -44,9 +44,8 @@ LIBCC = -lgcc
CPPFLAGS =
CFLAGS =
CFLAGS_AUTO = -Os -pipe
CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
CFLAGS_ALL = $(CFLAGS_C99FSE)
CFLAGS_ALL = -std=c17 -ffreestanding -nostdinc
CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
+1 -1
View File
@@ -1 +1 @@
1.2.5
1.2.6
+53
View File
@@ -2438,3 +2438,56 @@ arch-specific bugs fixed:
- riscv64 icache flush operation was non-functional
- sh sigsetjmp failed to properly restore call-saved register r8 on return
- sh dlsym RTLD_NEXT did not identify calling module correctly
1.2.6 release notes
new features:
- posix_getdents interface (new in POSIX-2024)
- renameat2 interface (linux extension)
- iconv support for CP858
- vdso clock_gettime for riscv{32,64}, powerpc{,64}, and s390x
- loongarch64 TLSDESC support
- exposed __getauxval for compiler runtime use detecting cpu features
compatibility:
- initgroups no longer artificially limits number of supplementary groups
- getusershell now skips blank lines and comments
- exit is now explicitly thread-safe (possible future requirement)
- atexit now fails rather than deadlocking if called from late dtor
- strerror now has error strings for EUCLEAN and ENAVAIL
- isatty no longer collapses errors to ENOTTY
- sched.h namespace pollution with _GNU_SOURCE is reduced
- hasmntopt now matches only whole options, not arbitrary substrings
- shadow.h no longer declares an unimplemented sgetspent interface
- vdso with missing sysv hash table (only gnu hash) is now supported
conformance:
- pwrite now handles O_APPEND correctly, reports error if it can't
- mbnrtowcs now conforms to new POSIX-2024 requirement for partial character
- iconv GBK now properly includes euro symbol
- strptime now accepts conversion specifiers added in POSIX-2024
- inet_ntop IPv6 "zero compression" now conforms to RFC 5952
bugs fixed:
- iconv euc-kr decoder could do oob writes on invalid inputs (CVE-2025-26519)
- iconv shift_jis decoder could produce wrong outputs for some invalid inputs
- printf did not honor hex float precision correctly in some cases
- lost or delayed wakes in sem_post under race condition
- termios input speed handling was wrong
- strcasestr failed to match zero-length needle
- fma handled corner case with negative zero wrongly
- syslog LOG_MAKEPRI macro was incorrect
- timer_create is no longer affected by known pthread_barrier bugs
- sysconf(_SC_MINSIGSTKSZ) computed min size incorrectly
- statx emulation left some fields uninitialized
- mntent wrongly included final newline in parsed field output
- SIGEV_THREAD timers could abort process if SIGTIMER became unblocked
- bind_textdomain_codeset returned wrong value
arch-specific bugs fixed:
- early dynamic linker handled page size wrong on dynamic pagesize archs
- arm and aarch64 crti/n files had wrong alignment
- m68k POLLWRNORM and POLLWRBAND values were incorrect
- x32 mq ABI was mismatched
+20
View File
@@ -296,12 +296,32 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#define __NR_memfd_secret 447
#define __NR_process_mrelease 448
#define __NR_futex_waitv 449
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+19
View File
@@ -396,6 +396,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -404,6 +405,24 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
#define __ARM_NR_breakpoint 0x0f0001
#define __ARM_NR_cacheflush 0x0f0002
+19
View File
@@ -433,6 +433,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -442,4 +443,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+43
View File
@@ -18,6 +18,10 @@
#endif
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
#define SC_USED_FP (1U << 0)
#define SC_ADDRERR_RD (1U << 30)
#define SC_ADDRERR_WR (1U << 31)
typedef unsigned long greg_t, gregset_t[32];
struct sigcontext {
@@ -26,6 +30,45 @@ struct sigcontext {
unsigned sc_flags;
unsigned long sc_extcontext[] __attribute__((__aligned__(16)));
};
#define CONTEXT_INFO_ALIGN 16
struct sctx_info {
unsigned magic;
unsigned size;
unsigned long padding;
};
#define FPU_CTX_MAGIC 0x46505501
#define FPU_CTX_ALIGN 8
struct fpu_context {
unsigned long regs[32];
unsigned long fcc;
unsigned fcsr;
};
#define LSX_CTX_MAGIC 0x53580001
#define LSX_CTX_ALIGN 16
struct lsx_context {
unsigned long regs[2*32];
unsigned long fcc;
unsigned fcsr;
};
#define LASX_CTX_MAGIC 0x41535801
#define LASX_CTX_ALIGN 32
struct lasx_context {
unsigned long regs[4*32];
unsigned long fcc;
unsigned fcsr;
};
#define LBT_CTX_MAGIC 0x42540001
#define LBT_CTX_ALIGN 8
struct lbt_context {
unsigned long regs[4];
unsigned eflags;
unsigned ftop;
};
#endif
typedef struct {
+14
View File
@@ -305,6 +305,20 @@
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
#define __NR_fcntl __NR3264_fcntl
#define __NR_statfs __NR3264_statfs
#define __NR_fstatfs __NR3264_fstatfs
+14
View File
@@ -22,3 +22,17 @@ typedef union {
float f;
} elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
typedef union
{
__attribute__((__aligned__(16)))
double d[2];
float f[4];
} elf_lsxregset_t[32];
typedef union
{
__attribute__((__aligned__(32)))
double d[4];
float f[8];
} elf_lasxregset_t[32];
+19
View File
@@ -413,6 +413,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -421,3 +422,21 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+19
View File
@@ -434,6 +434,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -442,4 +443,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+19
View File
@@ -415,6 +415,7 @@
#define __NR_process_madvise 4440
#define __NR_epoll_pwait2 4441
#define __NR_mount_setattr 4442
#define __NR_quotactl_fd 4443
#define __NR_landlock_create_ruleset 4444
#define __NR_landlock_add_rule 4445
#define __NR_landlock_restrict_self 4446
@@ -423,4 +424,22 @@
#define __NR_set_mempolicy_home_node 4450
#define __NR_cachestat 4451
#define __NR_fchmodat2 4452
#define __NR_map_shadow_stack 4453
#define __NR_futex_wake 4454
#define __NR_futex_wait 4455
#define __NR_futex_requeue 4456
#define __NR_statmount 4457
#define __NR_listmount 4458
#define __NR_lsm_get_self_attr 4459
#define __NR_lsm_set_self_attr 4460
#define __NR_lsm_list_modules 4461
#define __NR_mseal 4462
#define __NR_setxattrat 4463
#define __NR_getxattrat 4464
#define __NR_listxattrat 4465
#define __NR_removexattrat 4466
#define __NR_open_tree_attr 4467
#define __NR_file_getattr 4468
#define __NR_file_setattr 4469
#define __NR_listns 4470
+19
View File
@@ -345,6 +345,7 @@
#define __NR_process_madvise 5440
#define __NR_epoll_pwait2 5441
#define __NR_mount_setattr 5442
#define __NR_quotactl_fd 5443
#define __NR_landlock_create_ruleset 5444
#define __NR_landlock_add_rule 5445
#define __NR_landlock_restrict_self 5446
@@ -353,4 +354,22 @@
#define __NR_set_mempolicy_home_node 5450
#define __NR_cachestat 5451
#define __NR_fchmodat2 5452
#define __NR_map_shadow_stack 5453
#define __NR_futex_wake 5454
#define __NR_futex_wait 5455
#define __NR_futex_requeue 5456
#define __NR_statmount 5457
#define __NR_listmount 5458
#define __NR_lsm_get_self_attr 5459
#define __NR_lsm_set_self_attr 5460
#define __NR_lsm_list_modules 5461
#define __NR_mseal 5462
#define __NR_setxattrat 5463
#define __NR_getxattrat 5464
#define __NR_listxattrat 5465
#define __NR_removexattrat 5466
#define __NR_open_tree_attr 5467
#define __NR_file_getattr 5468
#define __NR_file_setattr 5469
#define __NR_listns 5470
+19
View File
@@ -369,6 +369,7 @@
#define __NR_process_madvise 6440
#define __NR_epoll_pwait2 6441
#define __NR_mount_setattr 6442
#define __NR_quotactl_fd 6443
#define __NR_landlock_create_ruleset 6444
#define __NR_landlock_add_rule 6445
#define __NR_landlock_restrict_self 6446
@@ -377,4 +378,22 @@
#define __NR_set_mempolicy_home_node 6450
#define __NR_cachestat 6451
#define __NR_fchmodat2 6452
#define __NR_map_shadow_stack 6453
#define __NR_futex_wake 6454
#define __NR_futex_wait 6455
#define __NR_futex_requeue 6456
#define __NR_statmount 6457
#define __NR_listmount 6458
#define __NR_lsm_get_self_attr 6459
#define __NR_lsm_set_self_attr 6460
#define __NR_lsm_list_modules 6461
#define __NR_mseal 6462
#define __NR_setxattrat 6463
#define __NR_getxattrat 6464
#define __NR_listxattrat 6465
#define __NR_removexattrat 6466
#define __NR_open_tree_attr 6467
#define __NR_file_getattr 6468
#define __NR_file_setattr 6469
#define __NR_listns 6470
+19
View File
@@ -318,6 +318,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -326,4 +327,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+19
View File
@@ -422,6 +422,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -430,4 +431,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+19
View File
@@ -394,6 +394,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -402,4 +403,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+20
View File
@@ -289,12 +289,32 @@
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#define __NR_memfd_secret 447
#define __NR_process_mrelease 448
#define __NR_futex_waitv 449
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex __NR_futex_time64
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
#define __NR_riscv_hwprobe (__NR_sysriscv + 14)
+21
View File
@@ -296,14 +296,35 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
#define __NR_memfd_secret 447
#define __NR_process_mrelease 448
#define __NR_futex_waitv 449
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
#define __NR_sysriscv __NR_arch_specific_syscall
#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
#define __NR_riscv_hwprobe (__NR_sysriscv + 14)
+19
View File
@@ -359,6 +359,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -368,4 +369,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+20
View File
@@ -357,6 +357,7 @@
#define __NR_pkey_alloc 385
#define __NR_pkey_free 386
#define __NR_rseq 387
#define __NR_sync_file_range2 388
#define __NR_semget 393
#define __NR_semctl 394
#define __NR_shmget 395
@@ -406,6 +407,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -414,4 +416,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
+21
View File
@@ -286,6 +286,8 @@
#define __NR_statx (0x40000000 + 332)
#define __NR_io_pgetevents (0x40000000 + 333)
#define __NR_rseq (0x40000000 + 334)
#define __NR_uretprobe (0x40000000 + 335)
#define __NR_uprobe (0x40000000 + 336)
#define __NR_pidfd_send_signal (0x40000000 + 424)
#define __NR_io_uring_setup (0x40000000 + 425)
#define __NR_io_uring_enter (0x40000000 + 426)
@@ -305,6 +307,7 @@
#define __NR_process_madvise (0x40000000 + 440)
#define __NR_epoll_pwait2 (0x40000000 + 441)
#define __NR_mount_setattr (0x40000000 + 442)
#define __NR_quotactl_fd (0x40000000 + 443)
#define __NR_landlock_create_ruleset (0x40000000 + 444)
#define __NR_landlock_add_rule (0x40000000 + 445)
#define __NR_landlock_restrict_self (0x40000000 + 446)
@@ -314,6 +317,24 @@
#define __NR_set_mempolicy_home_node (0x40000000 + 450)
#define __NR_cachestat (0x40000000 + 451)
#define __NR_fchmodat2 (0x40000000 + 452)
#define __NR_map_shadow_stack (0x40000000 + 453)
#define __NR_futex_wake (0x40000000 + 454)
#define __NR_futex_wait (0x40000000 + 455)
#define __NR_futex_requeue (0x40000000 + 456)
#define __NR_statmount (0x40000000 + 457)
#define __NR_listmount (0x40000000 + 458)
#define __NR_lsm_get_self_attr (0x40000000 + 459)
#define __NR_lsm_set_self_attr (0x40000000 + 460)
#define __NR_lsm_list_modules (0x40000000 + 461)
#define __NR_mseal (0x40000000 + 462)
#define __NR_setxattrat (0x40000000 + 463)
#define __NR_getxattrat (0x40000000 + 464)
#define __NR_listxattrat (0x40000000 + 465)
#define __NR_removexattrat (0x40000000 + 466)
#define __NR_open_tree_attr (0x40000000 + 467)
#define __NR_file_getattr (0x40000000 + 468)
#define __NR_file_setattr (0x40000000 + 469)
#define __NR_listns (0x40000000 + 470)
#define __NR_rt_sigaction (0x40000000 + 512)
+21
View File
@@ -333,6 +333,8 @@
#define __NR_statx 332
#define __NR_io_pgetevents 333
#define __NR_rseq 334
#define __NR_uretprobe 335
#define __NR_uprobe 336
#define __NR_pidfd_send_signal 424
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
@@ -352,6 +354,7 @@
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_quotactl_fd 443
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
@@ -361,4 +364,22 @@
#define __NR_set_mempolicy_home_node 450
#define __NR_cachestat 451
#define __NR_fchmodat2 452
#define __NR_map_shadow_stack 453
#define __NR_futex_wake 454
#define __NR_futex_wait 455
#define __NR_futex_requeue 456
#define __NR_statmount 457
#define __NR_listmount 458
#define __NR_lsm_get_self_attr 459
#define __NR_lsm_set_self_attr 460
#define __NR_lsm_list_modules 461
#define __NR_mseal 462
#define __NR_setxattrat 463
#define __NR_getxattrat 464
#define __NR_listxattrat 465
#define __NR_removexattrat 466
#define __NR_open_tree_attr 467
#define __NR_file_getattr 468
#define __NR_file_setattr 469
#define __NR_listns 470
Vendored
+2 -2
View File
@@ -36,7 +36,7 @@ Optional features:
--disable-static inhibit building static library [enabled]
Optional packages:
--with-malloc=... choose malloc implementation [mallocng]
--with-malloc=... choose malloc implementation [rpmalloc]
Some influential environment variables:
CC C compiler command [detected]
@@ -142,7 +142,7 @@ static=yes
wrapper=auto
gcc_wrapper=no
clang_wrapper=no
malloc_dir=mallocng
malloc_dir=rpmalloc
for arg ; do
case "$arg" in
+2 -2
View File
@@ -6,8 +6,8 @@
#include "crt_arch.h"
int main();
weak void _init();
weak void _fini();
__weak void _init();
__weak void _fini();
int __libc_start_main(int (*)(), int, char **,
void (*)(), void(*)(), void(*)());
+2 -2
View File
@@ -3,8 +3,8 @@
#include "../ldso/dlstart.c"
int main();
weak void _init();
weak void _fini();
__weak void _init();
__weak void _fini();
int __libc_start_main(int (*)(), int, char **,
void (*)(), void(*)(), void(*)());
+28
View File
@@ -712,6 +712,8 @@ typedef struct {
#define NT_LOONGARCH_LSX 0xa02
#define NT_LOONGARCH_LASX 0xa03
#define NT_LOONGARCH_LBT 0xa04
#define NT_LOONGARCH_HW_BREAK 0xa05
#define NT_LOONGARCH_HW_WATCH 0xa06
@@ -3408,6 +3410,32 @@ enum
#define R_LARCH_TLS_GD_HI20 98
#define R_LARCH_32_PCREL 99
#define R_LARCH_RELAX 100
#define R_LARCH_DELETE 101
#define R_LARCH_ALIGN 102
#define R_LARCH_PCREL20_S2 103
#define R_LARCH_CFA 104
#define R_LARCH_ADD6 105
#define R_LARCH_SUB6 106
#define R_LARCH_ADD_ULEB128 107
#define R_LARCH_SUB_ULEB128 108
#define R_LARCH_64_PCREL 109
#define R_LARCH_CALL36 110
#define R_LARCH_TLS_DESC_PC_HI20 111
#define R_LARCH_TLS_DESC_PC_LO12 112
#define R_LARCH_TLS_DESC64_PC_LO20 113
#define R_LARCH_TLS_DESC64_PC_HI12 114
#define R_LARCH_TLS_DESC_HI20 115
#define R_LARCH_TLS_DESC_LO12 116
#define R_LARCH_TLS_DESC64_LO20 117
#define R_LARCH_TLS_DESC64_HI12 118
#define R_LARCH_TLS_DESC_LD 119
#define R_LARCH_TLS_DESC_CALL 120
#define R_LARCH_TLS_LE_HI20_R 121
#define R_LARCH_TLS_LE_ADD_R 122
#define R_LARCH_TLS_LE_LO12_R 123
#define R_LARCH_TLS_LD_PCREL20_S2 124
#define R_LARCH_TLS_GD_PCREL20_S2 125
#define R_LARCH_TLS_DESC_PCREL20_S2 126
#ifdef __cplusplus
}
+1 -1
View File
@@ -64,7 +64,7 @@ typedef struct __res_state {
#define __RES 19960801
#ifndef _PATH_RESCONF
#define _PATH_RESCONF "/etc/resolv.conf"
#define _PATH_RESCONF "/var/config/network/resolv.conf"
#endif
struct res_sym {
+346
View File
@@ -0,0 +1,346 @@
/*-
* Copyright (c) 2011 Ed Schouten <[email protected]>
* David Chisnall <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/include/stdatomic.h,v 1.10.2.2 2012/05/30 19:21:54 theraven Exp $
*/
#ifndef _STDATOMIC_H_
#define _STDATOMIC_H_
#include <stddef.h>
#include <stdint.h>
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif
#if !defined(__has_builtin)
#define __has_builtin(x) 0
#endif
#if !defined(__GNUC_PREREQ__)
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
#define __GNUC_PREREQ__(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
#define __GNUC_PREREQ__(maj, min) 0
#endif
#endif
#if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS)
#if __GNUC_PREREQ__(4, 7)
#define __GNUC_ATOMICS
#elif __has_feature(c_atomic)
#define __CLANG_ATOMICS
#elif !defined(__GNUC__)
#error "stdatomic.h does not support your compiler"
#endif
#endif
/*
* 7.17.2 Initialization.
*/
#if defined(__CLANG_ATOMICS)
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
#else
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) do { \
*(obj) = (value); \
} while (0)
#endif
/*
* Clang and recent GCC both provide predefined macros for the memory
* orderings. If we are using a compiler that doesn't define them, use the
* clang values - these will be ignored in the fallback path.
*/
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#endif
#ifndef __ATOMIC_CONSUME
#define __ATOMIC_CONSUME 1
#endif
#ifndef __ATOMIC_ACQUIRE
#define __ATOMIC_ACQUIRE 2
#endif
#ifndef __ATOMIC_RELEASE
#define __ATOMIC_RELEASE 3
#endif
#ifndef __ATOMIC_ACQ_REL
#define __ATOMIC_ACQ_REL 4
#endif
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST 5
#endif
/*
* 7.17.3 Order and consistency.
*
* The memory_order_* constants that denote the barrier behaviour of the
* atomic operations.
*/
enum memory_order {
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
};
typedef enum memory_order memory_order;
/*
* 7.17.4 Fences.
*/
#ifdef __CLANG_ATOMICS
#define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
#define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
#elif defined(__GNUC_ATOMICS)
#define atomic_thread_fence(order) __atomic_thread_fence(order)
#define atomic_signal_fence(order) __atomic_signal_fence(order)
#else
#define atomic_thread_fence(order) __sync_synchronize()
#define atomic_signal_fence(order) __asm volatile ("" : : : "memory")
#endif
/*
* 7.17.5 Lock-free property.
*/
#if defined(__CLANG_ATOMICS)
#define atomic_is_lock_free(obj) \
__c11_atomic_is_lock_free(sizeof(obj))
#elif defined(__GNUC_ATOMICS)
#define atomic_is_lock_free(obj) \
__atomic_is_lock_free(sizeof((obj)->__val))
#else
#define atomic_is_lock_free(obj) \
(sizeof((obj)->__val) <= sizeof(void *))
#endif
/*
* 7.17.6 Atomic integer types.
*/
typedef _Atomic(_Bool) atomic_bool;
typedef _Atomic(char) atomic_char;
typedef _Atomic(signed char) atomic_schar;
typedef _Atomic(unsigned char) atomic_uchar;
typedef _Atomic(short) atomic_short;
typedef _Atomic(unsigned short) atomic_ushort;
typedef _Atomic(int) atomic_int;
typedef _Atomic(unsigned int) atomic_uint;
typedef _Atomic(long) atomic_long;
typedef _Atomic(unsigned long) atomic_ulong;
typedef _Atomic(long long) atomic_llong;
typedef _Atomic(unsigned long long) atomic_ullong;
#if 0
typedef _Atomic(char16_t) atomic_char16_t;
typedef _Atomic(char32_t) atomic_char32_t;
#endif
typedef _Atomic(wchar_t) atomic_wchar_t;
typedef _Atomic(int_least8_t) atomic_int_least8_t;
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
typedef _Atomic(int_least16_t) atomic_int_least16_t;
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
typedef _Atomic(int_least32_t) atomic_int_least32_t;
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
typedef _Atomic(int_least64_t) atomic_int_least64_t;
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
typedef _Atomic(intptr_t) atomic_intptr_t;
typedef _Atomic(uintptr_t) atomic_uintptr_t;
typedef _Atomic(size_t) atomic_size_t;
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
typedef _Atomic(intmax_t) atomic_intmax_t;
typedef _Atomic(uintmax_t) atomic_uintmax_t;
/*
* 7.17.7 Operations on atomic types.
*/
/*
* Compiler-specific operations.
*/
#if defined(__CLANG_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__c11_atomic_compare_exchange_strong(object, expected, desired, \
success, failure)
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
__c11_atomic_compare_exchange_weak(object, expected, desired, \
success, failure)
#define atomic_exchange_explicit(object, desired, order) \
__c11_atomic_exchange(object, desired, order)
#define atomic_fetch_add_explicit(object, operand, order) \
__c11_atomic_fetch_add(object, operand, order)
#define atomic_fetch_and_explicit(object, operand, order) \
__c11_atomic_fetch_and(object, operand, order)
#define atomic_fetch_or_explicit(object, operand, order) \
__c11_atomic_fetch_or(object, operand, order)
#define atomic_fetch_sub_explicit(object, operand, order) \
__c11_atomic_fetch_sub(object, operand, order)
#define atomic_fetch_xor_explicit(object, operand, order) \
__c11_atomic_fetch_xor(object, operand, order)
#define atomic_load_explicit(object, order) \
__c11_atomic_load(object, order)
#define atomic_store_explicit(object, desired, order) \
__c11_atomic_store(object, desired, order)
#elif defined(__GNUC_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(object, expected, \
desired, 0, success, failure)
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(object, expected, \
desired, 1, success, failure)
#define atomic_exchange_explicit(object, desired, order) \
__atomic_exchange_n(object, desired, order)
#define atomic_fetch_add_explicit(object, operand, order) \
__atomic_fetch_add(object, operand, order)
#define atomic_fetch_and_explicit(object, operand, order) \
__atomic_fetch_and(object, operand, order)
#define atomic_fetch_or_explicit(object, operand, order) \
__atomic_fetch_or(object, operand, order)
#define atomic_fetch_sub_explicit(object, operand, order) \
__atomic_fetch_sub(object, operand, order)
#define atomic_fetch_xor_explicit(object, operand, order) \
__atomic_fetch_xor(object, operand, order)
#define atomic_load_explicit(object, order) \
__atomic_load_n(object, order)
#define atomic_store_explicit(object, desired, order) \
__atomic_store_n(object, desired, order)
#else
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) ({ \
__typeof__(*(object)) __v; \
_Bool __r; \
__v = __sync_val_compare_and_swap(object, \
*(expected), desired); \
__r = *(expected) == __v; \
*(expected) = __v; \
__r; \
})
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure)
#if __has_builtin(__sync_swap)
/* Clang provides a full-barrier atomic exchange - use it if available. */
#define atomic_exchange_explicit(object, desired, order) \
__sync_swap(object, desired)
#else
/*
* __sync_lock_test_and_set() is only an acquire barrier in theory (although in
* practice it is usually a full barrier) so we need an explicit barrier after
* it.
*/
#define atomic_exchange_explicit(object, desired, order) ({ \
__typeof__(*(object)) __v; \
__v = __sync_lock_test_and_set(object, desired); \
__sync_synchronize(); \
__v; \
})
#endif
#define atomic_fetch_add_explicit(object, operand, order) \
__sync_fetch_and_add(object, operand)
#define atomic_fetch_and_explicit(object, operand, order) \
__sync_fetch_and_and(object, operand)
#define atomic_fetch_or_explicit(object, operand, order) \
__sync_fetch_and_or(object, operand)
#define atomic_fetch_sub_explicit(object, operand, order) \
__sync_fetch_and_sub(object, operand)
#define atomic_fetch_xor_explicit(object, operand, order) \
__sync_fetch_and_xor(object, operand)
#define atomic_load_explicit(object, order) \
__sync_fetch_and_add(object, 0)
#define atomic_store_explicit(object, desired, order) do { \
__sync_synchronize(); \
*(object) = (desired); \
__sync_synchronize(); \
} while (0)
#endif
/*
* Convenience functions.
*/
#define atomic_compare_exchange_strong(object, expected, desired) \
atomic_compare_exchange_strong_explicit(object, expected, \
desired, memory_order_seq_cst, memory_order_seq_cst)
#define atomic_compare_exchange_weak(object, expected, desired) \
atomic_compare_exchange_weak_explicit(object, expected, \
desired, memory_order_seq_cst, memory_order_seq_cst)
#define atomic_exchange(object, desired) \
atomic_exchange_explicit(object, desired, memory_order_seq_cst)
#define atomic_fetch_add(object, operand) \
atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_and(object, operand) \
atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_or(object, operand) \
atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_sub(object, operand) \
atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_xor(object, operand) \
atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
#define atomic_load(object) \
atomic_load_explicit(object, memory_order_seq_cst)
#define atomic_store(object, desired) \
atomic_store_explicit(object, desired, memory_order_seq_cst)
/*
* 7.17.8 Atomic flag type and operations.
*/
typedef atomic_bool atomic_flag;
#define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0)
#define atomic_flag_clear_explicit(object, order) \
atomic_store_explicit(object, 0, order)
#define atomic_flag_test_and_set_explicit(object, order) \
atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
#define atomic_flag_clear(object) \
atomic_flag_clear_explicit(object, memory_order_seq_cst)
#define atomic_flag_test_and_set(object) \
atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
#endif /* !_STDATOMIC_H_ */
+379
View File
@@ -0,0 +1,379 @@
/*
* Copyright 2023 Justine Alexandra Roberts Tunney
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* @fileoverview C23 Checked Arithmetic
*
* This header defines three type generic functions:
*
* - `bool ckd_add(res, a, b)`
* - `bool ckd_sub(res, a, b)`
* - `bool ckd_mul(res, a, b)`
*
* Which allow integer arithmetic errors to be detected. There are many
* kinds of integer errors, e.g. overflow, truncation, etc. These funcs
* catch them all. Here's an example of how it works:
*
* uint32_t c;
* int32_t a = 0x7fffffff;
* int32_t b = 2;
* assert(!ckd_add(&c, a, b));
* assert(c == 0x80000001u);
*
* Experienced C / C++ users should find this example counter-intuitive
* because the expression `0x7fffffff + 2` not only overflows it's also
* undefined behavior. However here we see it's specified, and does not
* result in an error. That's because C23 checked arithmetic is not the
* arithmetic you're used to. The new standard changes the mathematics.
*
* C23 checked arithmetic is defined as performing the arithmetic using
* infinite precision and then checking if the resulting value will fit
* in the output type. Our example above did not result in an error due
* to `0x80000001` being a legal value for `uint32_t`.
*
* This implementation will use the GNU compiler builtins, when they're
* available, only if you don't use build flags like `-std=c11` because
* they define `__STRICT_ANSI__` and GCC extensions aren't really ANSI.
* Instead, you'll get a pretty good pure C11 and C++11 implementation.
*
* @see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf
* @version 1.0 (2024-12-07)
*/
#ifndef STDCKDINT_H_
#define STDCKDINT_H_
#define __STDC_VERSION_STDCKDINT_H__ 202311L
#if (!defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__))
#define __ckd_have_int128
#define __ckd_intmax __int128
#elif ((defined(__cplusplus) && __cplusplus >= 201103L) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L))
#define __ckd_intmax long long
#else
#define __ckd_intmax long
#endif
typedef signed __ckd_intmax __ckd_intmax_t;
typedef unsigned __ckd_intmax __ckd_uintmax_t;
#ifdef __has_builtin
#define __ckd_has_builtin(x) __has_builtin(x)
#else
#define __ckd_has_builtin(x) 0
#endif
#if (!defined(__STRICT_ANSI__) && \
((defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)) || \
(__ckd_has_builtin(__builtin_add_overflow) && \
__ckd_has_builtin(__builtin_sub_overflow) && \
__ckd_has_builtin(__builtin_mul_overflow))))
#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))
#else
#define ckd_add(res, a, b) __ckd_expr(add, (res), (a), (b))
#define ckd_sub(res, a, b) __ckd_expr(sub, (res), (a), (b))
#define ckd_mul(res, a, b) __ckd_expr(mul, (res), (a), (b))
#if defined(__GNUC__) || defined(__llvm__)
#define __ckd_inline \
extern __inline __attribute__((__gnu_inline__, \
__always_inline__, \
__artificial__))
#else
#define __ckd_inline static inline
#endif
#ifdef __ckd_have_int128
#define __ckd_generic_int128(x, y) , signed __int128: x, unsigned __int128: y
#else
#define __ckd_generic_int128(x, y)
#endif
#define __ckd_sign(T) \
((T)1 << (sizeof(T) * 8 - 1))
#define __ckd_is_signed(x) \
_Generic(x, \
signed char: 1, \
unsigned char: 0, \
signed short: 1, \
unsigned short: 0, \
signed int: 1, \
unsigned int: 0, \
signed long: 1, \
unsigned long: 0, \
signed long long: 1, \
unsigned long long: 0 \
__ckd_generic_int128(1, 0))
#define __ckd_expr(op, res, a, b) \
(_Generic(*res, \
signed char: __ckd_##op##_schar, \
unsigned char: __ckd_##op##_uchar, \
signed short: __ckd_##op##_sshort, \
unsigned short: __ckd_##op##_ushort, \
signed int: __ckd_##op##_sint, \
unsigned int: __ckd_##op##_uint, \
signed long: __ckd_##op##_slong, \
unsigned long: __ckd_##op##_ulong, \
signed long long: __ckd_##op##_slonger, \
unsigned long long: __ckd_##op##_ulonger \
__ckd_generic_int128( \
__ckd_##op##_sint128, \
__ckd_##op##_uint128))( \
res, a, b, \
__ckd_is_signed(a), \
__ckd_is_signed(b)))
#define __ckd_declare_add(S, T) \
__ckd_inline char S(void *__res, \
__ckd_uintmax_t __x, \
__ckd_uintmax_t __y, \
char __a_signed, \
char __b_signed) { \
__ckd_uintmax_t __z = __x + __y; \
*(T *)__res = (T)__z; \
char __truncated = 0; \
if (sizeof(T) < sizeof(__ckd_intmax_t)) { \
__truncated = __z != (__ckd_uintmax_t)(T)__z; \
} \
switch (__ckd_is_signed((T)0) << 2 | \
__a_signed << 1 | __b_signed) { \
case 0: /* u = u + u */ \
return __truncated | (__z < __x); \
case 1: /* u = u + s */ \
__y ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | \
((__ckd_intmax_t)((__z ^ __x) & \
(__z ^ __y)) < 0); \
case 2: /* u = s + u */ \
__x ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | \
((__ckd_intmax_t)((__z ^ __x) & \
(__z ^ __y)) < 0); \
case 3: /* u = s + s */ \
return __truncated | \
((__ckd_intmax_t)(((__z | __x) & __y) | \
((__z & __x) & ~__y)) < 0); \
case 4: /* s = u + u */ \
return __truncated | (__z < __x) | ((__ckd_intmax_t)__z < 0); \
case 5: /* s = u + s */ \
__y ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | (__x + __y < __y); \
case 6: /* s = s + u */ \
__x ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | (__x + __y < __x); \
case 7: /* s = s + s */ \
return __truncated | \
((__ckd_intmax_t)((__z ^ __x) & \
(__z ^ __y)) < 0); \
default: \
for (;;) (void)0; \
} \
}
__ckd_declare_add(__ckd_add_schar, signed char)
__ckd_declare_add(__ckd_add_uchar, unsigned char)
__ckd_declare_add(__ckd_add_sshort, signed short)
__ckd_declare_add(__ckd_add_ushort, unsigned short)
__ckd_declare_add(__ckd_add_sint, signed int)
__ckd_declare_add(__ckd_add_uint, unsigned int)
__ckd_declare_add(__ckd_add_slong, signed long)
__ckd_declare_add(__ckd_add_ulong, unsigned long)
__ckd_declare_add(__ckd_add_slonger, signed long long)
__ckd_declare_add(__ckd_add_ulonger, unsigned long long)
#ifdef __ckd_have_int128
__ckd_declare_add(__ckd_add_sint128, signed __int128)
__ckd_declare_add(__ckd_add_uint128, unsigned __int128)
#endif
#define __ckd_declare_sub(S, T) \
__ckd_inline char S(void *__res, \
__ckd_uintmax_t __x, \
__ckd_uintmax_t __y, \
char __a_signed, \
char __b_signed) { \
__ckd_uintmax_t __z = __x - __y; \
*(T *)__res = (T)__z; \
char __truncated = 0; \
if (sizeof(T) < sizeof(__ckd_intmax_t)) { \
__truncated = __z != (__ckd_uintmax_t)(T)__z; \
} \
switch (__ckd_is_signed((T)0) << 2 | \
__a_signed << 1 | __b_signed) { \
case 0: /* u = u - u */ \
return __truncated | (__x < __y); \
case 1: /* u = u - s */ \
__y ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | \
((__ckd_intmax_t)((__x ^ __y) & \
(__z ^ __x)) < 0); \
case 2: /* u = s - u */ \
return __truncated | (__y > __x) | ((__ckd_intmax_t)__x < 0); \
case 3: /* u = s - s */ \
return __truncated | \
((__ckd_intmax_t)(((__z & __x) & __y) | \
((__z | __x) & ~__y)) < 0); \
case 4: /* s = u - u */ \
return __truncated | ((__x < __y) ^ ((__ckd_intmax_t)__z < 0)); \
case 5: /* s = u - s */ \
__y ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | (__x >= __y); \
case 6: /* s = s - u */ \
__x ^= __ckd_sign(__ckd_uintmax_t); \
return __truncated | (__x < __y); \
case 7: /* s = s - s */ \
return __truncated | \
((__ckd_intmax_t)((__x ^ __y) & \
(__z ^ __x)) < 0); \
default: \
for (;;) (void)0; \
} \
}
__ckd_declare_sub(__ckd_sub_schar, signed char)
__ckd_declare_sub(__ckd_sub_uchar, unsigned char)
__ckd_declare_sub(__ckd_sub_sshort, signed short)
__ckd_declare_sub(__ckd_sub_ushort, unsigned short)
__ckd_declare_sub(__ckd_sub_sint, signed int)
__ckd_declare_sub(__ckd_sub_uint, unsigned int)
__ckd_declare_sub(__ckd_sub_slong, signed long)
__ckd_declare_sub(__ckd_sub_ulong, unsigned long)
__ckd_declare_sub(__ckd_sub_slonger, signed long long)
__ckd_declare_sub(__ckd_sub_ulonger, unsigned long long)
#ifdef __ckd_have_int128
__ckd_declare_sub(__ckd_sub_sint128, signed __int128)
__ckd_declare_sub(__ckd_sub_uint128, unsigned __int128)
#endif
#define __ckd_declare_mul(S, T) \
__ckd_inline char S(void *__res, \
__ckd_uintmax_t __x, \
__ckd_uintmax_t __y, \
char __a_signed, \
char __b_signed) { \
switch (__ckd_is_signed((T)0) << 2 | \
__a_signed << 1 | __b_signed) { \
case 0: { /* u = u * u */ \
__ckd_uintmax_t __z = __x * __y; \
int __o = __x && __z / __x != __y; \
*(T *)__res = (T)__z; \
return __o | (sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res); \
} \
case 1: { /* u = u * s */ \
__ckd_uintmax_t __z = __x * __y; \
int __o = __x && __z / __x != __y; \
*(T *)__res = (T)__z; \
return (__o | (((__ckd_intmax_t)__y < 0) & !!__x) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 2: { /* u = s * u */ \
__ckd_uintmax_t __z = __x * __y; \
int __o = __x && __z / __x != __y; \
*(T *)__res = (T)__z; \
return (__o | (((__ckd_intmax_t)__x < 0) & !!__y) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 3: { /* u = s * s */ \
int __o = 0; \
if ((__ckd_intmax_t)(__x & __y) < 0) { \
__x = 0 - __x; \
__y = 0 - __y; \
} else if ((__ckd_intmax_t)(__x ^ __y) < 0) { \
__o = __x && __y; \
} \
__ckd_uintmax_t __z = __x * __y; \
__o |= __x && __z / __x != __y; \
*(T *)__res = (T)__z; \
return __o | (sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res); \
} \
case 4: { /* s = u * u */ \
__ckd_uintmax_t __z = __x * __y; \
int __o = __x && __z / __x != __y; \
*(T *)__res = (T)__z; \
return (__o | ((__ckd_intmax_t)(__z) < 0) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 5: { /* s = u * s */ \
__ckd_uintmax_t __t = 0 - __y; \
__t = (__ckd_intmax_t)(__t) < 0 ? __y : __t; \
__ckd_uintmax_t __p = __t * __x; \
int __o = __t && __p / __t != __x; \
int __n = (__ckd_intmax_t)__y < 0; \
__ckd_uintmax_t __z = __n ? 0 - __p : __p; \
*(T *)__res = (T)__z; \
__ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \
return (__o | (__p > __m + __n) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 6: { /* s = s * u */ \
__ckd_uintmax_t __t = 0 - __x; \
__t = (__ckd_intmax_t)(__t) < 0 ? __x : __t; \
__ckd_uintmax_t __p = __t * __y; \
int __o = __t && __p / __t != __y; \
int __n = (__ckd_intmax_t)__x < 0; \
__ckd_uintmax_t __z = __n ? 0 - __p : __p; \
*(T *)__res = (T)__z; \
__ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \
return (__o | (__p > __m + __n) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
case 7: { /* s = s * s */ \
__ckd_uintmax_t __z = __x * __y; \
*(T *)__res = (T)__z; \
return (((((__ckd_intmax_t)__y < 0) && \
(__x == __ckd_sign(__ckd_uintmax_t))) || \
(__y && (((__ckd_intmax_t)__z / \
(__ckd_intmax_t)__y) != \
(__ckd_intmax_t)__x))) | \
(sizeof(T) < sizeof(__z) && \
__z != (__ckd_uintmax_t)*(T *)__res)); \
} \
default: \
for (;;) (void)0; \
} \
}
__ckd_declare_mul(__ckd_mul_schar, signed char)
__ckd_declare_mul(__ckd_mul_uchar, unsigned char)
__ckd_declare_mul(__ckd_mul_sshort, signed short)
__ckd_declare_mul(__ckd_mul_ushort, unsigned short)
__ckd_declare_mul(__ckd_mul_sint, signed int)
__ckd_declare_mul(__ckd_mul_uint, unsigned int)
__ckd_declare_mul(__ckd_mul_slong, signed long)
__ckd_declare_mul(__ckd_mul_ulong, unsigned long)
__ckd_declare_mul(__ckd_mul_slonger, signed long long)
__ckd_declare_mul(__ckd_mul_ulonger, unsigned long long)
#ifdef __ckd_have_int128
__ckd_declare_mul(__ckd_mul_sint128, signed __int128)
__ckd_declare_mul(__ckd_mul_uint128, unsigned __int128)
#endif
#endif /* GNU */
#endif /* STDCKDINT_H_ */
+4
View File
@@ -95,6 +95,10 @@ extern "C" {
#define MADV_KEEPONFORK 19
#define MADV_COLD 20
#define MADV_PAGEOUT 21
#define MADV_POPULATE_READ 22
#define MADV_POPULATE_WRITE 23
#define MADV_DONTNEED_LOCKED 24
#define MADV_COLLAPSE 25
#define MADV_HWPOISON 100
#define MADV_SOFT_OFFLINE 101
#endif
+3 -1
View File
@@ -159,7 +159,7 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap;
struct debug *_dl_debug_addr = &debug;
extern weak hidden char __ehdr_start[];
extern __weak hidden char __ehdr_start[];
extern hidden int __malloc_replaced;
@@ -1782,6 +1782,8 @@ void __dls3(size_t *sp, size_t *auxv)
libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
|| aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]);
__malloc_process_init();
/* Only trust user/env if kernel says we're not suid/sgid */
if (!libc.secure) {
env_path = getenv("LD_LIBRARY_PATH");
+1 -1
View File
@@ -77,7 +77,7 @@ typedef Elf32_Phdr Phdr;
typedef Elf64_Phdr Phdr;
#endif
extern weak hidden const size_t _DYNAMIC[];
extern __weak hidden const size_t _DYNAMIC[];
static void static_init_tls(size_t *aux)
{
+3 -1
View File
@@ -10,7 +10,7 @@
static void dummy(void) {}
weak_alias(dummy, _init);
extern weak hidden void (*const __init_array_start)(void), (*const __init_array_end)(void);
extern __weak hidden void (*const __init_array_start)(void), (*const __init_array_end)(void);
static void dummy1(void *p) {}
weak_alias(dummy1, __init_ssp);
@@ -39,6 +39,8 @@ void __init_libc(char **envp, char *pn)
__init_tls(aux);
__init_ssp((void *)aux[AT_RANDOM]);
__malloc_process_init();
if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
&& !aux[AT_SECURE]) return;
+1 -1
View File
@@ -15,7 +15,7 @@ weak_alias(dummy, __funcs_on_exit);
weak_alias(dummy, __stdio_exit);
weak_alias(dummy, _fini);
extern weak hidden void (*const __fini_array_start)(void), (*const __fini_array_end)(void);
extern __weak hidden void (*const __fini_array_start)(void), (*const __fini_array_end)(void);
static void libc_exit_fini(void)
{
+3
View File
@@ -0,0 +1,3 @@
#ifdef __loongarch_soft_float
#include "../fenv.c"
#endif
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../../include/features.h"
#define weak __attribute__((__weak__))
#define __weak __attribute__((__weak__))
#define hidden __attribute__((__visibility__("hidden")))
#define weak_alias(old, new) \
extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))
+3
View File
@@ -15,5 +15,8 @@ hidden void *__libc_malloc_impl(size_t);
hidden void *__libc_calloc(size_t, size_t);
hidden void *__libc_realloc(void *, size_t);
hidden void __libc_free(void *);
hidden void __malloc_process_init();
hidden void __malloc_thread_init();
hidden void __malloc_thread_done();
#endif
+1
View File
@@ -32,6 +32,7 @@ struct pthread {
#endif
/* Part 2 -- implementation details, non-ABI. */
void *theap;
int tid;
int errno_val;
volatile int detach_state;
+26 -2
View File
@@ -40,6 +40,24 @@ static int checkver(Verdef *def, int vsym, const char *vername, char *strings)
#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON)
#define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
static size_t count_syms_gnu(uint32_t *gh)
{
size_t nsym, i;
uint32_t *buckets = gh + 4 + (gh[2]*sizeof(size_t)/4);
uint32_t *hashval;
for (i = nsym = 0; i < gh[0]; i++) {
if (buckets[i] > nsym)
nsym = buckets[i];
}
if (nsym) {
hashval = buckets + gh[0] + (nsym - gh[1]);
do nsym++;
while (!(*hashval++ & 1));
}
return nsym;
}
void *__vdsosym(const char *vername, const char *name)
{
size_t i;
@@ -60,6 +78,7 @@ void *__vdsosym(const char *vername, const char *name)
char *strings = 0;
Sym *syms = 0;
Elf_Symndx *hashtab = 0;
uint32_t *ghashtab = 0;
uint16_t *versym = 0;
Verdef *verdef = 0;
@@ -69,15 +88,20 @@ void *__vdsosym(const char *vername, const char *name)
case DT_STRTAB: strings = p; break;
case DT_SYMTAB: syms = p; break;
case DT_HASH: hashtab = p; break;
case DT_GNU_HASH: ghashtab = p; break;
case DT_VERSYM: versym = p; break;
case DT_VERDEF: verdef = p; break;
}
}
if (!strings || !syms || !hashtab) return 0;
if (!strings || !syms) return 0;
if (!verdef) versym = 0;
size_t nsym = 0;
for (i=0; i<hashtab[1]; i++) {
if (hashtab) nsym = hashtab[1];
else if (ghashtab) nsym = count_syms_gnu(ghashtab);
for (i=0; i<nsym; i++) {
if (!(1<<(syms[i].st_info&0xf) & OK_TYPES)) continue;
if (!(1<<(syms[i].st_info>>4) & OK_BINDS)) continue;
if (!syms[i].st_shndx) continue;
+1 -1
View File
@@ -5,7 +5,7 @@
#define AUX_CNT 38
extern weak hidden const size_t _DYNAMIC[];
extern __weak hidden const size_t _DYNAMIC[];
static int static_dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
{
+1 -1
View File
@@ -69,7 +69,7 @@
#define ICONV_ERR_ILLEGAL_OPCODE -4
#define ICONV_ERR_MEMORY_OVERFLOW -5
#define ICONV_CHARSET_PATH_PREFIX "/etc/iconv/"
#define ICONV_CHARSET_PATH_PREFIX "/share/iconv/"
static const uint8_t vm_binary_magic[4] = { 'S', 'I', 'C', 'V' };
+5
View File
@@ -116,3 +116,8 @@ static void *default_malloc(size_t n)
}
weak_alias(default_malloc, malloc);
static void dummy(void) {}
weak_alias(dummy, __malloc_process_init);
weak_alias(dummy, __malloc_thread_init);
weak_alias(dummy, __malloc_thread_done);
+2 -2
View File
@@ -62,8 +62,8 @@ __attribute__((__visibility__("hidden")))
extern int __malloc_lock[1];
#define LOCK_OBJ_DEF \
int __malloc_lock[1]; \
void __malloc_atfork(int who) { malloc_atfork(who); }
void __malloc_atfork(int who) { malloc_atfork(who); } \
int __malloc_lock[1]
static inline void rdlock()
{
+13
View File
@@ -0,0 +1,13 @@
#include <stdlib.h>
void __malloc_process_init()
{
}
void __malloc_thread_init()
{
}
void __malloc_thread_done()
{
}
-53
View File
@@ -1,53 +0,0 @@
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include "malloc_impl.h"
void *aligned_alloc(size_t align, size_t len)
{
unsigned char *mem, *new;
if ((align & -align) != align) {
errno = EINVAL;
return 0;
}
if (len > SIZE_MAX - align ||
(__malloc_replaced && !__aligned_alloc_replaced)) {
errno = ENOMEM;
return 0;
}
if (align <= SIZE_ALIGN)
return malloc(len);
if (!(mem = malloc(len + align-1)))
return 0;
new = (void *)((uintptr_t)mem + align-1 & -align);
if (new == mem) return mem;
struct chunk *c = MEM_TO_CHUNK(mem);
struct chunk *n = MEM_TO_CHUNK(new);
if (IS_MMAPPED(c)) {
/* Apply difference between aligned and original
* address to the "extra" field of mmapped chunk. */
n->psize = c->psize + (new-mem);
n->csize = c->csize - (new-mem);
return new;
}
struct chunk *t = NEXT_CHUNK(c);
/* Split the allocated chunk into two chunks. The aligned part
* that will be used has the size in its footer reduced by the
* difference between the aligned and original addresses, and
* the resulting size copied to its header. A new header and
* footer are written for the split-off part to be freed. */
n->psize = c->csize = C_INUSE | (new-mem);
n->csize = t->psize -= new-mem;
__bin_chunk(c);
return new;
}
-556
View File
@@ -1,556 +0,0 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include "libc.h"
#include "atomic.h"
#include "pthread_impl.h"
#include "malloc_impl.h"
#include "fork_impl.h"
#define malloc __libc_malloc_impl
#define realloc __libc_realloc
#define free __libc_free
#if defined(__GNUC__) && defined(__PIC__)
#define inline inline __attribute__((always_inline))
#endif
static struct {
volatile uint64_t binmap;
struct bin bins[64];
volatile int split_merge_lock[2];
} mal;
/* Synchronization tools */
static inline void lock(volatile int *lk)
{
int need_locks = libc.need_locks;
if (need_locks) {
while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
if (need_locks < 0) libc.need_locks = 0;
}
}
static inline void unlock(volatile int *lk)
{
if (lk[0]) {
a_store(lk, 0);
if (lk[1]) __wake(lk, 1, 1);
}
}
static inline void lock_bin(int i)
{
lock(mal.bins[i].lock);
if (!mal.bins[i].head)
mal.bins[i].head = mal.bins[i].tail = BIN_TO_CHUNK(i);
}
static inline void unlock_bin(int i)
{
unlock(mal.bins[i].lock);
}
static int first_set(uint64_t x)
{
#if 1
return a_ctz_64(x);
#else
static const char debruijn64[64] = {
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
};
static const char debruijn32[32] = {
0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
};
if (sizeof(long) < 8) {
uint32_t y = x;
if (!y) {
y = x>>32;
return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
}
return debruijn32[(y&-y)*0x076be629 >> 27];
}
return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
#endif
}
static const unsigned char bin_tab[60] = {
32,33,34,35,36,36,37,37,38,38,39,39,
40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,
44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,45,
46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,
};
static int bin_index(size_t x)
{
x = x / SIZE_ALIGN - 1;
if (x <= 32) return x;
if (x < 512) return bin_tab[x/8-4];
if (x > 0x1c00) return 63;
return bin_tab[x/128-4] + 16;
}
static int bin_index_up(size_t x)
{
x = x / SIZE_ALIGN - 1;
if (x <= 32) return x;
x--;
if (x < 512) return bin_tab[x/8-4] + 1;
return bin_tab[x/128-4] + 17;
}
#if 0
void __dump_heap(int x)
{
struct chunk *c;
int i;
for (c = (void *)mal.heap; CHUNK_SIZE(c); c = NEXT_CHUNK(c))
fprintf(stderr, "base %p size %zu (%d) flags %d/%d\n",
c, CHUNK_SIZE(c), bin_index(CHUNK_SIZE(c)),
c->csize & 15,
NEXT_CHUNK(c)->psize & 15);
for (i=0; i<64; i++) {
if (mal.bins[i].head != BIN_TO_CHUNK(i) && mal.bins[i].head) {
fprintf(stderr, "bin %d: %p\n", i, mal.bins[i].head);
if (!(mal.binmap & 1ULL<<i))
fprintf(stderr, "missing from binmap!\n");
} else if (mal.binmap & 1ULL<<i)
fprintf(stderr, "binmap wrongly contains %d!\n", i);
}
}
#endif
/* This function returns true if the interval [old,new]
* intersects the 'len'-sized interval below &libc.auxv
* (interpreted as the main-thread stack) or below &b
* (the current stack). It is used to defend against
* buggy brk implementations that can cross the stack. */
static int traverses_stack_p(uintptr_t old, uintptr_t new)
{
const uintptr_t len = 8<<20;
uintptr_t a, b;
b = (uintptr_t)libc.auxv;
a = b > len ? b-len : 0;
if (new>a && old<b) return 1;
b = (uintptr_t)&b;
a = b > len ? b-len : 0;
if (new>a && old<b) return 1;
return 0;
}
/* Expand the heap in-place if brk can be used, or otherwise via mmap,
* using an exponential lower bound on growth by mmap to make
* fragmentation asymptotically irrelevant. The size argument is both
* an input and an output, since the caller needs to know the size
* allocated, which will be larger than requested due to page alignment
* and mmap minimum size rules. The caller is responsible for locking
* to prevent concurrent calls. */
static void *__expand_heap(size_t *pn)
{
static uintptr_t brk;
static unsigned mmap_step;
size_t n = *pn;
if (n > SIZE_MAX/2 - PAGE_SIZE) {
errno = ENOMEM;
return 0;
}
n += -n & PAGE_SIZE-1;
if (!brk) {
brk = __syscall(SYS_brk, 0);
brk += -brk & PAGE_SIZE-1;
}
if (n < SIZE_MAX-brk && !traverses_stack_p(brk, brk+n)
&& __syscall(SYS_brk, brk+n)==brk+n) {
*pn = n;
brk += n;
return (void *)(brk-n);
}
size_t min = (size_t)PAGE_SIZE << mmap_step/2;
if (n < min) n = min;
void *area = __mmap(0, n, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (area == MAP_FAILED) return 0;
*pn = n;
mmap_step++;
return area;
}
static struct chunk *expand_heap(size_t n)
{
static void *end;
void *p;
struct chunk *w;
/* The argument n already accounts for the caller's chunk
* overhead needs, but if the heap can't be extended in-place,
* we need room for an extra zero-sized sentinel chunk. */
n += SIZE_ALIGN;
p = __expand_heap(&n);
if (!p) return 0;
/* If not just expanding existing space, we need to make a
* new sentinel chunk below the allocated space. */
if (p != end) {
/* Valid/safe because of the prologue increment. */
n -= SIZE_ALIGN;
p = (char *)p + SIZE_ALIGN;
w = MEM_TO_CHUNK(p);
w->psize = 0 | C_INUSE;
}
/* Record new heap end and fill in footer. */
end = (char *)p + n;
w = MEM_TO_CHUNK(end);
w->psize = n | C_INUSE;
w->csize = 0 | C_INUSE;
/* Fill in header, which may be new or may be replacing a
* zero-size sentinel header at the old end-of-heap. */
w = MEM_TO_CHUNK(p);
w->csize = n | C_INUSE;
return w;
}
static int adjust_size(size_t *n)
{
/* Result of pointer difference must fit in ptrdiff_t. */
if (*n-1 > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE) {
if (*n) {
errno = ENOMEM;
return -1;
} else {
*n = SIZE_ALIGN;
return 0;
}
}
*n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
return 0;
}
static void unbin(struct chunk *c, int i)
{
if (c->prev == c->next)
a_and_64(&mal.binmap, ~(1ULL<<i));
c->prev->next = c->next;
c->next->prev = c->prev;
c->csize |= C_INUSE;
NEXT_CHUNK(c)->psize |= C_INUSE;
}
static void bin_chunk(struct chunk *self, int i)
{
self->next = BIN_TO_CHUNK(i);
self->prev = mal.bins[i].tail;
self->next->prev = self;
self->prev->next = self;
if (self->prev == BIN_TO_CHUNK(i))
a_or_64(&mal.binmap, 1ULL<<i);
}
static void trim(struct chunk *self, size_t n)
{
size_t n1 = CHUNK_SIZE(self);
struct chunk *next, *split;
if (n >= n1 - DONTCARE) return;
next = NEXT_CHUNK(self);
split = (void *)((char *)self + n);
split->psize = n | C_INUSE;
split->csize = n1-n;
next->psize = n1-n;
self->csize = n | C_INUSE;
int i = bin_index(n1-n);
lock_bin(i);
bin_chunk(split, i);
unlock_bin(i);
}
void *malloc(size_t n)
{
struct chunk *c;
int i, j;
uint64_t mask;
if (adjust_size(&n) < 0) return 0;
if (n > MMAP_THRESHOLD) {
size_t len = n + OVERHEAD + PAGE_SIZE - 1 & -PAGE_SIZE;
char *base = __mmap(0, len, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (base == (void *)-1) return 0;
c = (void *)(base + SIZE_ALIGN - OVERHEAD);
c->csize = len - (SIZE_ALIGN - OVERHEAD);
c->psize = SIZE_ALIGN - OVERHEAD;
return CHUNK_TO_MEM(c);
}
i = bin_index_up(n);
if (i<63 && (mal.binmap & (1ULL<<i))) {
lock_bin(i);
c = mal.bins[i].head;
if (c != BIN_TO_CHUNK(i) && CHUNK_SIZE(c)-n <= DONTCARE) {
unbin(c, i);
unlock_bin(i);
return CHUNK_TO_MEM(c);
}
unlock_bin(i);
}
lock(mal.split_merge_lock);
for (mask = mal.binmap & -(1ULL<<i); mask; mask -= (mask&-mask)) {
j = first_set(mask);
lock_bin(j);
c = mal.bins[j].head;
if (c != BIN_TO_CHUNK(j)) {
unbin(c, j);
unlock_bin(j);
break;
}
unlock_bin(j);
}
if (!mask) {
c = expand_heap(n);
if (!c) {
unlock(mal.split_merge_lock);
return 0;
}
}
trim(c, n);
unlock(mal.split_merge_lock);
return CHUNK_TO_MEM(c);
}
int __malloc_allzerop(void *p)
{
return IS_MMAPPED(MEM_TO_CHUNK(p));
}
void *realloc(void *p, size_t n)
{
struct chunk *self, *next;
size_t n0, n1;
void *new;
if (!p) return malloc(n);
if (adjust_size(&n) < 0) return 0;
self = MEM_TO_CHUNK(p);
n1 = n0 = CHUNK_SIZE(self);
if (n<=n0 && n0-n<=DONTCARE) return p;
if (IS_MMAPPED(self)) {
size_t extra = self->psize;
char *base = (char *)self - extra;
size_t oldlen = n0 + extra;
size_t newlen = n + extra;
/* Crash on realloc of freed chunk */
if (extra & 1) a_crash();
if (newlen < PAGE_SIZE && (new = malloc(n-OVERHEAD))) {
n0 = n;
goto copy_free_ret;
}
newlen = (newlen + PAGE_SIZE-1) & -PAGE_SIZE;
if (oldlen == newlen) return p;
base = __mremap(base, oldlen, newlen, MREMAP_MAYMOVE);
if (base == (void *)-1)
goto copy_realloc;
self = (void *)(base + extra);
self->csize = newlen - extra;
return CHUNK_TO_MEM(self);
}
next = NEXT_CHUNK(self);
/* Crash on corrupted footer (likely from buffer overflow) */
if (next->psize != self->csize) a_crash();
if (n < n0) {
int i = bin_index_up(n);
int j = bin_index(n0);
if (i<j && (mal.binmap & (1ULL << i)))
goto copy_realloc;
struct chunk *split = (void *)((char *)self + n);
self->csize = split->psize = n | C_INUSE;
split->csize = next->psize = n0-n | C_INUSE;
__bin_chunk(split);
return CHUNK_TO_MEM(self);
}
lock(mal.split_merge_lock);
size_t nsize = next->csize & C_INUSE ? 0 : CHUNK_SIZE(next);
if (n0+nsize >= n) {
int i = bin_index(nsize);
lock_bin(i);
if (!(next->csize & C_INUSE)) {
unbin(next, i);
unlock_bin(i);
next = NEXT_CHUNK(next);
self->csize = next->psize = n0+nsize | C_INUSE;
trim(self, n);
unlock(mal.split_merge_lock);
return CHUNK_TO_MEM(self);
}
unlock_bin(i);
}
unlock(mal.split_merge_lock);
copy_realloc:
/* As a last resort, allocate a new chunk and copy to it. */
new = malloc(n-OVERHEAD);
if (!new) return 0;
copy_free_ret:
memcpy(new, p, (n<n0 ? n : n0) - OVERHEAD);
free(CHUNK_TO_MEM(self));
return new;
}
void __bin_chunk(struct chunk *self)
{
struct chunk *next = NEXT_CHUNK(self);
/* Crash on corrupted footer (likely from buffer overflow) */
if (next->psize != self->csize) a_crash();
lock(mal.split_merge_lock);
size_t osize = CHUNK_SIZE(self), size = osize;
/* Since we hold split_merge_lock, only transition from free to
* in-use can race; in-use to free is impossible */
size_t psize = self->psize & C_INUSE ? 0 : CHUNK_PSIZE(self);
size_t nsize = next->csize & C_INUSE ? 0 : CHUNK_SIZE(next);
if (psize) {
int i = bin_index(psize);
lock_bin(i);
if (!(self->psize & C_INUSE)) {
struct chunk *prev = PREV_CHUNK(self);
unbin(prev, i);
self = prev;
size += psize;
}
unlock_bin(i);
}
if (nsize) {
int i = bin_index(nsize);
lock_bin(i);
if (!(next->csize & C_INUSE)) {
unbin(next, i);
next = NEXT_CHUNK(next);
size += nsize;
}
unlock_bin(i);
}
int i = bin_index(size);
lock_bin(i);
self->csize = size;
next->psize = size;
bin_chunk(self, i);
unlock(mal.split_merge_lock);
/* Replace middle of large chunks with fresh zero pages */
if (size > RECLAIM && (size^(size-osize)) > size-osize) {
uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
int e = errno;
#if 1
__madvise((void *)a, b-a, MADV_DONTNEED);
#else
__mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
#endif
errno = e;
}
unlock_bin(i);
}
static void unmap_chunk(struct chunk *self)
{
size_t extra = self->psize;
char *base = (char *)self - extra;
size_t len = CHUNK_SIZE(self) + extra;
/* Crash on double free */
if (extra & 1) a_crash();
int e = errno;
__munmap(base, len);
errno = e;
}
void free(void *p)
{
if (!p) return;
struct chunk *self = MEM_TO_CHUNK(p);
if (IS_MMAPPED(self))
unmap_chunk(self);
else
__bin_chunk(self);
}
void __malloc_donate(char *start, char *end)
{
size_t align_start_up = (SIZE_ALIGN-1) & (-(uintptr_t)start - OVERHEAD);
size_t align_end_down = (SIZE_ALIGN-1) & (uintptr_t)end;
/* Getting past this condition ensures that the padding for alignment
* and header overhead will not overflow and will leave a nonzero
* multiple of SIZE_ALIGN bytes between start and end. */
if (end - start <= OVERHEAD + align_start_up + align_end_down)
return;
start += align_start_up + OVERHEAD;
end -= align_end_down;
struct chunk *c = MEM_TO_CHUNK(start), *n = MEM_TO_CHUNK(end);
c->psize = n->csize = C_INUSE;
c->csize = n->psize = C_INUSE | (end-start);
__bin_chunk(c);
}
void __malloc_atfork(int who)
{
if (who<0) {
lock(mal.split_merge_lock);
for (int i=0; i<64; i++)
lock(mal.bins[i].lock);
} else if (!who) {
for (int i=0; i<64; i++)
unlock(mal.bins[i].lock);
unlock(mal.split_merge_lock);
} else {
for (int i=0; i<64; i++)
mal.bins[i].lock[0] = mal.bins[i].lock[1] = 0;
mal.split_merge_lock[1] = 0;
mal.split_merge_lock[0] = 0;
}
}
-39
View File
@@ -1,39 +0,0 @@
#ifndef MALLOC_IMPL_H
#define MALLOC_IMPL_H
#include <sys/mman.h>
#include "dynlink.h"
struct chunk {
size_t psize, csize;
struct chunk *next, *prev;
};
struct bin {
volatile int lock[2];
struct chunk *head;
struct chunk *tail;
};
#define SIZE_ALIGN (4*sizeof(size_t))
#define SIZE_MASK (-SIZE_ALIGN)
#define OVERHEAD (2*sizeof(size_t))
#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
#define DONTCARE 16
#define RECLAIM 163840
#define CHUNK_SIZE(c) ((c)->csize & -2)
#define CHUNK_PSIZE(c) ((c)->psize & -2)
#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD)
#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD)
#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
#define C_INUSE ((size_t)1)
#define IS_MMAPPED(c) !((c)->csize & (C_INUSE))
hidden void __bin_chunk(struct chunk *);
#endif
@@ -1,9 +0,0 @@
#include <malloc.h>
#include "malloc_impl.h"
hidden void *(*const __realloc_dep)(void *, size_t) = realloc;
size_t malloc_usable_size(void *p)
{
return p ? CHUNK_SIZE(MEM_TO_CHUNK(p)) - OVERHEAD : 0;
}
+47
View File
@@ -0,0 +1,47 @@
#include "rpmalloc.h"
#if (defined(__GNUC__) && __GNUC__ >= 9)
#pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward
#define hidden_alias(fun) __attribute__((alias(#fun), used, visibility("hidden"), copy(fun)));
#define public_alias(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun)));
#else
#define hidden_alias(fun) __attribute__((alias(#fun), used, visibility("hidden")));
#define public_alias(fun) __attribute__((alias(#fun), used, visibility("default"), copy(fun)));
#endif
void* __libc_malloc_impl(size_t) hidden_alias(rpmalloc)
void* __libc_realloc(void*, size_t) hidden_alias(rprealloc)
void __libc_free(void*) hidden_alias(rpfree)
void *aligned_alloc(size_t align, size_t size) public_alias(rpaligned_alloc)
size_t malloc_usable_size(void * p) public_alias(rpmalloc_usable_size)
hidden void __malloc_atfork(int who) {}
hidden void __malloc_donate(char *start, char *end) {}
hidden void __malloc_process_init() {
rpmalloc_set_main_thread();
if (rpmalloc_initialize() < 0) {
abort();
}
}
hidden void __malloc_thread_init() {
rpmalloc_thread_initialize();
}
hidden void __malloc_thread_finalize() {
rpmalloc_thread_finalize(1);
}
#include "pthread_impl.h"
static inline heap_t* get_thread_heap_raw(void) {
pthread_t self = __pthread_self();
return (heap_t *) self->theap;
}
static inline uintptr_t get_thread_id(void) {
return (uintptr_t)__pthread_self()->self;
}
static void set_thread_heap(heap_t* heap) {
__pthread_self()->theap = (void *)heap;
if (heap) heap->owner_thread = get_thread_id();
}
File diff suppressed because it is too large Load Diff
+362
View File
@@ -0,0 +1,362 @@
/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson
*
* This library provides a cross-platform lock free thread caching malloc implementation in C11.
* The latest source code is always available at
*
* https://github.com/mjansson/rpmalloc
*
* This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
*
*/
#pragma once
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__clang__) || defined(__GNUC__)
# define RPMALLOC_EXPORT static
# define RPMALLOC_ALLOCATOR
# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
# else
# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))
# endif
# define RPMALLOC_CDECL
#elif defined(_MSC_VER)
# define RPMALLOC_EXPORT
# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)
# define RPMALLOC_CDECL __cdecl
#else
# define RPMALLOC_EXPORT
# define RPMALLOC_ALLOCATOR
# define RPMALLOC_ATTRIB_MALLOC
# define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size)
# define RPMALLOC_CDECL
#endif
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
// a very small overhead due to some size calculations not being compile time constants
#ifndef RPMALLOC_CONFIGURABLE
#define RPMALLOC_CONFIGURABLE 0
#endif
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions).
// Will introduce a very small overhead to track fully allocated spans in heaps
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
#define RPMALLOC_FIRST_CLASS_HEAPS 0
#endif
//! Flag to rpaligned_realloc to not preserve content in reallocation
#define RPMALLOC_NO_PRESERVE 1
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place,
// in which case the original pointer is still valid (just like a call to realloc which failes to allocate
// a new block).
#define RPMALLOC_GROW_OR_FAIL 2
typedef struct rpmalloc_global_statistics_t {
//! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
size_t mapped;
//! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
size_t mapped_peak;
//! Current amount of memory in global caches for small and medium sizes (<32KiB)
size_t cached;
//! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
size_t huge_alloc;
//! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
size_t huge_alloc_peak;
//! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1)
size_t mapped_total;
//! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1)
size_t unmapped_total;
} rpmalloc_global_statistics_t;
typedef struct rpmalloc_thread_statistics_t {
//! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB)
size_t sizecache;
//! Current number of bytes available in thread span caches for small and medium sizes (<32KiB)
size_t spancache;
//! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1)
size_t thread_to_global;
//! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1)
size_t global_to_thread;
//! Per span count statistics (only if ENABLE_STATISTICS=1)
struct {
//! Currently used number of spans
size_t current;
//! High water mark of spans used
size_t peak;
//! Number of spans transitioned to global cache
size_t to_global;
//! Number of spans transitioned from global cache
size_t from_global;
//! Number of spans transitioned to thread cache
size_t to_cache;
//! Number of spans transitioned from thread cache
size_t from_cache;
//! Number of spans transitioned to reserved state
size_t to_reserved;
//! Number of spans transitioned from reserved state
size_t from_reserved;
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
size_t map_calls;
} span_use[64];
//! Per size class statistics (only if ENABLE_STATISTICS=1)
struct {
//! Current number of allocations
size_t alloc_current;
//! Peak number of allocations
size_t alloc_peak;
//! Total number of allocations
size_t alloc_total;
//! Total number of frees
size_t free_total;
//! Number of spans transitioned to cache
size_t spans_to_cache;
//! Number of spans transitioned from cache
size_t spans_from_cache;
//! Number of spans transitioned from reserved state
size_t spans_from_reserved;
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
size_t map_calls;
} size_use[128];
} rpmalloc_thread_statistics_t;
typedef struct rpmalloc_config_t {
//! Map memory pages for the given number of bytes. The returned address MUST be
// aligned to the rpmalloc span size, which will always be a power of two.
// Optionally the function can store an alignment offset in the offset variable
// in case it performs alignment and the returned pointer is offset from the
// actual start of the memory region due to this alignment. The alignment offset
// will be passed to the memory unmap function. The alignment offset MUST NOT be
// larger than 65535 (storable in an uint16_t), if it is you must use natural
// alignment to shift it into 16 bits. If you set a memory_map function, you
// must also set a memory_unmap function or else the default implementation will
// be used for both. This function must be thread safe, it can be called by
// multiple threads simultaneously.
void* (*memory_map)(size_t size, size_t* offset);
//! Unmap the memory pages starting at address and spanning the given number of bytes.
// If release is set to non-zero, the unmap is for an entire span range as returned by
// a previous call to memory_map and that the entire range should be released. The
// release argument holds the size of the entire span range. If release is set to 0,
// the unmap is a partial decommit of a subset of the mapped memory range.
// If you set a memory_unmap function, you must also set a memory_map function or
// else the default implementation will be used for both. This function must be thread
// safe, it can be called by multiple threads simultaneously.
void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release);
//! Called when an assert fails, if asserts are enabled. Will use the standard assert()
// if this is not set.
void (*error_callback)(const char* message);
//! Called when a call to map memory pages fails (out of memory). If this callback is
// not set or returns zero the library will return a null pointer in the allocation
// call. If this callback returns non-zero the map call will be retried. The argument
// passed is the number of bytes that was requested in the map call. Only used if
// the default system memory map function is used (memory_map callback is not set).
int (*map_fail_callback)(size_t size);
//! Size of memory pages. The page size MUST be a power of two. All memory mapping
// requests to memory_map will be made with size set to a multiple of the page size.
// Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.
size_t page_size;
//! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144]
// range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE
// is defined to 1.
size_t span_size;
//! Number of spans to map at each request to map new virtual memory blocks. This can
// be used to minimize the system call overhead at the cost of virtual memory address
// space. The extra mapped pages will not be written until actually used, so physical
// committed memory should not be affected in the default implementation. Will be
// aligned to a multiple of spans that match memory page size in case of huge pages.
size_t span_map_count;
//! Enable use of large/huge pages. If this flag is set to non-zero and page size is
// zero, the allocator will try to enable huge pages and auto detect the configuration.
// If this is set to non-zero and page_size is also non-zero, the allocator will
// assume huge pages have been configured and enabled prior to initializing the
// allocator.
// For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
int enable_huge_pages;
int unused;
} rpmalloc_config_t;
//! Initialize allocator with default configuration
RPMALLOC_EXPORT int
rpmalloc_initialize(void);
//! Initialize allocator with given configuration
RPMALLOC_EXPORT int
rpmalloc_initialize_config(const rpmalloc_config_t* config);
//! Get allocator configuration
RPMALLOC_EXPORT const rpmalloc_config_t*
rpmalloc_config(void);
//! Finalize allocator
RPMALLOC_EXPORT void
rpmalloc_finalize(void);
//! Initialize allocator for calling thread
RPMALLOC_EXPORT void
rpmalloc_thread_initialize(void);
//! Finalize allocator for calling thread
RPMALLOC_EXPORT void
rpmalloc_thread_finalize(int release_caches);
//! Perform deferred deallocations pending for the calling thread heap
RPMALLOC_EXPORT void
rpmalloc_thread_collect(void);
//! Query if allocator is initialized for calling thread
RPMALLOC_EXPORT int
rpmalloc_is_thread_initialized(void);
//! Get per-thread statistics
RPMALLOC_EXPORT void
rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats);
//! Get global statistics
RPMALLOC_EXPORT void
rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats);
//! Dump all statistics in human readable format to file (should be a FILE*)
RPMALLOC_EXPORT void
rpmalloc_dump_statistics(void* file);
//! Allocate a memory block of at least the given size
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);
//! Free the given memory block
RPMALLOC_EXPORT void
rpfree(void* ptr);
//! Allocate a memory block of at least the given size and zero initialize it
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
//! Reallocate the given block to at least the given size
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Reallocate the given block to at least the given size and alignment,
// with optional control flags (see RPMALLOC_NO_PRESERVE).
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size and alignment, and zero initialize it.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size and alignment.
// Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB)
RPMALLOC_EXPORT int
rpposix_memalign(void** memptr, size_t alignment, size_t size);
//! Query the usable size of the given memory block (from given pointer to the end of block)
RPMALLOC_EXPORT size_t
rpmalloc_usable_size(void* ptr);
#if RPMALLOC_FIRST_CLASS_HEAPS
//! Heap type
typedef struct heap_t rpmalloc_heap_t;
//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap
// if none available. Heap API is implemented with the strict assumption that only one single
// thread will call heap functions for a given heap at any given time, no functions are thread safe.
RPMALLOC_EXPORT rpmalloc_heap_t*
rpmalloc_heap_acquire(void);
//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap).
// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer.
RPMALLOC_EXPORT void
rpmalloc_heap_release(rpmalloc_heap_t* heap);
//! Allocate a memory block of at least the given size using the given heap.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
//! Allocate a memory block of at least the given size using the given heap. The returned
// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Allocate a memory block of at least the given size using the given heap and zero initialize it.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned
// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*),
// and should ideally be less than memory page size. A caveat of rpmalloc
// internals is that this must also be strictly less than the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
// by the same heap given to this function.
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
// by the same heap given to this function. The returned block will have the requested alignment.
// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be
// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than
// the span size (default 64KiB).
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void*
rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
//! Free the given memory block from the given heap. The memory block MUST be allocated
// by the same heap given to this function.
RPMALLOC_EXPORT void
rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr);
//! Free all memory allocated by the heap
RPMALLOC_EXPORT void
rpmalloc_heap_free_all(rpmalloc_heap_t* heap);
//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap
// for a single thread, a heap can never be shared between multiple threads. The previous
// current heap for the calling thread is released to be reused by other threads.
RPMALLOC_EXPORT void
rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap);
#endif
#ifdef __cplusplus
}
#endif
+2 -2
View File
@@ -13,8 +13,8 @@
/* getifaddrs() reports hardware addresses with PF_PACKET that implies
* struct sockaddr_ll. But e.g. Infiniband socket address length is
* longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct
* to extend ssl_addr - callers should be able to still use it. */
* longer than sockaddr_ll.sll_addr[8] can hold. Use this hack struct
* to extend sll_addr - callers should be able to still use it. */
struct sockaddr_ll_hack {
unsigned short sll_family, sll_protocol;
int sll_ifindex;
+3 -3
View File
@@ -47,7 +47,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i
char line[512], *p, *z;
unsigned char _buf[1032], atmp[16];
struct address iplit;
FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
FILE _f, *f = __fopen_rb_ca("/var/config/network/hosts", &_f, _buf, sizeof _buf);
if (!f) return;
if (family == AF_INET) {
memcpy(atmp+12, a, 4);
@@ -71,7 +71,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i
if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid)
continue;
for (; *p && isspace(*p); p++);
for (z=p; *z && !isspace(*z); z++);
*z = 0;
@@ -116,7 +116,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const
data, c, 256) <= 0)
*(char *)c = 0;
return 0;
}
int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
+1 -1
View File
@@ -52,7 +52,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
size_t l = strlen(name);
int cnt = 0, badfam = 0, have_canon = 0;
unsigned char _buf[1032];
FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
FILE _f, *f = __fopen_rb_ca("/var/config/network/hosts", &_f, _buf, sizeof _buf);
if (!f) switch (errno) {
case ENOENT:
case ENOTDIR:
+1 -1
View File
@@ -18,7 +18,7 @@ int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz)
conf->attempts = 2;
if (search) *search = 0;
f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
f = __fopen_rb_ca("/var/config/network/resolv.conf", &_f, _buf, sizeof _buf);
if (!f) switch (errno) {
case ENOENT:
case ENOTDIR:
+404
View File
@@ -0,0 +1,404 @@
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include "spp.h"
#include "json.h"
#ifndef _ACCOUNT_CLIENT
#define _ACCOUNT_CLIENT
#define REQ2(condition, err) if (!(condition)) { errno = err; return -1; }
#define REQ(condition) REQ2(condition, EPERM)
#define REQP2(condition, err) if (!(condition)) { errno = err; return NULL; }
#define REQP(condition) REQP2(condition, EPERM)
#define ITEROBJ(obj, it) for (struct json_object_element_s *it = obj->start; it != NULL; it = it->next)
#define DECLPOOL(pool, buf, size) struct account_memory_pool pool = { .ptr = buf, .len = size, .cursor = 0 }
#ifdef __linux__
static inline int account_connect() {
return spp_connect_linux("verified:org.semilabs.os/accountd");
}
#else
static inline int account_connect() {
return spp_connect_unix("/var/run/accountd.sock");
}
#endif /* __linux__ */
struct account_memory_pool {
void *ptr;
size_t cursor;
size_t len;
};
static inline void *account_allocate_pool(struct account_memory_pool *pool, size_t size) {
if (!pool || !pool->ptr || size == 0) {
return NULL;
}
if (pool->cursor + size > pool->len) {
return NULL;
}
void *result = (char *)pool->ptr + pool->cursor;
pool->cursor += size;
return result;
}
static inline int account_recordpw(
struct json_value_s *root,
struct passwd *passwd,
struct account_memory_pool *pool
) {
passwd->pw_passwd = account_allocate_pool(pool, 2);
REQ2(passwd->pw_passwd, ERANGE);
strcpy(passwd->pw_passwd, "x");
passwd->pw_gecos = account_allocate_pool(pool, 1);
REQ2(passwd->pw_gecos, ERANGE);
strcpy(passwd->pw_gecos, "");
struct json_object_s *object = json_value_as_object(root);
REQ(object);
ITEROBJ(object, it) {
const char *name = it->name->string;
struct json_value_s *value = it->value;
if (strcmp(name, "username") == 0) {
struct json_string_s *username = json_value_as_string(value);
REQ(username);
passwd->pw_name = account_allocate_pool(pool, username->string_size + 1);
REQ2(passwd->pw_name, ERANGE);
strcpy(passwd->pw_name, username->string);
continue;
}
if (strcmp(name, "home_directory") == 0) {
struct json_string_s *homedir = json_value_as_string(value);
REQ(homedir);
passwd->pw_dir = account_allocate_pool(pool, homedir->string_size + 1);
REQ2(passwd->pw_dir, ERANGE);
strcpy(passwd->pw_dir, homedir->string);
continue;
}
if (strcmp(name, "defaults") == 0) {
struct json_object_s *defaults = json_value_as_object(value);
REQ(defaults);
ITEROBJ(defaults, def) {
name = def->name->string;
value = def->value;
if (strcmp(name, "CliLoginShell") == 0) {
struct json_string_s *shell = json_value_as_string(value);
REQ(shell);
passwd->pw_shell = account_allocate_pool(pool, shell->string_size + 1);
REQ2(passwd->pw_shell, ERANGE);
strcpy(passwd->pw_shell, shell->string);
continue;
}
}
continue;
}
if (strcmp(name, "host_uid") == 0) {
struct json_number_s *uid = json_value_as_number(value);
REQ(uid);
passwd->pw_uid = atoi(uid->number);
continue;
}
}
return 0;
}
static inline int account_recordgr(
struct json_value_s *root,
struct group *group,
struct account_memory_pool *pool
) {
group->gr_passwd = account_allocate_pool(pool, 2);
REQ2(group->gr_passwd, ERANGE);
strcpy(group->gr_passwd, "x");
struct json_object_s *object = json_value_as_object(root);
REQ(object);
ITEROBJ(object, it) {
const char *name = it->name->string;
struct json_value_s *value = it->value;
if (strcmp(name, "groupname") == 0) {
struct json_string_s *groupname = json_value_as_string(value);
REQ(groupname);
group->gr_name = account_allocate_pool(pool, groupname->string_size + 1);
REQ2(group->gr_name, ERANGE);
strcpy(group->gr_name, groupname->string);
continue;
}
if (strcmp(name, "host_gid") == 0) {
struct json_number_s *gid = json_value_as_number(value);
REQ(gid);
group->gr_gid = atoi(gid->number);
continue;
}
}
return 0;
}
typedef int (*pwgr_parser_t)(struct json_value_s*, void*, struct account_memory_pool*);
static inline int account_getpwgrkey(
int fd,
const char *method,
const char *key,
const char *valueborder,
const char *name,
pwgr_parser_t parser,
void *pwgr,
struct account_memory_pool *pool
) {
int status;
const char *request_template = "{\"method\": \"%s\", \"params\": {\"%s\": %s%s%s}}";
int request_need = snprintf(NULL, 0, request_template, method, key, valueborder, name, valueborder);
REQ(request_need > 0);
char *request_json = malloc(request_need + 1);
REQ2(request_json, ENOMEM);
snprintf(request_json, request_need + 1, request_template, method, key, valueborder, name, valueborder);
status = spp_send(fd, request_json);
free(request_json);
REQ(status == 0);
const char *reply_str = spp_recv(fd);
REQ(reply_str);
struct json_value_s *reply = json_parse(reply_str, strlen(reply_str));
spp_free((void*)reply_str);
REQ(reply);
struct json_object_s *reply_object = json_value_as_object(reply);
if (!reply_object) goto format_error;
ITEROBJ(reply_object, it) {
if (strcmp(it->name->string, "success") == 0) {
if (json_value_is_false(it->value)) goto not_found;
continue;
}
if (strcmp(it->name->string, "value") == 0) {
status = parser(it->value, pwgr, pool);
if (status != 0) goto not_found;
continue;
}
}
free(reply);
return 0;
format_error:
errno = EPERM;
not_found:
free(reply);
return -1;
}
static inline char *account_list_uuid_next(
int fd,
const char *method,
unsigned int no
) {
int status;
const char *request_template = "{\"method\": \"%s\", \"params\": {\"start\": %u, \"len\": 1}}";
int request_need = snprintf(NULL, 0, request_template, method, no);
REQP(request_need > 0);
char *request_json = malloc(request_need + 1);
REQP2(request_json, ENOMEM);
snprintf(request_json, request_need + 1, request_template, method, no);
status = spp_send(fd, request_json);
free(request_json);
REQP(status == 0);
const char *reply_str = spp_recv(fd);
REQP(reply_str);
struct json_value_s *reply = json_parse(reply_str, strlen(reply_str));
spp_free((void*)reply_str);
REQP(reply);
struct json_object_s *reply_object = json_value_as_object(reply);
if (!reply_object) goto format_error;
ITEROBJ(reply_object, it) {
if (strcmp(it->name->string, "success") == 0) {
if (json_value_is_false(it->value)) goto not_found;
continue;
}
if (strcmp(it->name->string, "value") == 0) {
struct json_array_s *list = json_value_as_array(it->value);
if (!list) goto not_found;
struct json_array_element_s *first = list->start;
if (!first) goto not_found;
struct json_string_s *item = json_value_as_string(first->value);
if (!item) goto format_error;
return strdup(item->string);
}
}
free(reply);
return NULL;
format_error:
errno = EPERM;
not_found:
free(reply);
return NULL;
}
static inline int account_getpwuid(
int fd,
uid_t uid,
struct passwd *passwd,
struct account_memory_pool *pool
) {
char uid_str[32];
int len = snprintf(uid_str, sizeof(uid_str), "%u", (unsigned int)uid);
REQ(len > 0 && (size_t)len < sizeof(uid_str));
return account_getpwgrkey(
fd,
"GetUserInfo",
"host_uid",
"",
uid_str,
(pwgr_parser_t)account_recordpw,
passwd,
pool
);
}
static inline int account_getpwnam(
int fd,
const char *name,
struct passwd *passwd,
struct account_memory_pool *pool
) {
return account_getpwgrkey(
fd,
"GetUserInfo",
"username",
"\"",
name,
(pwgr_parser_t)account_recordpw,
passwd,
pool
);
}
static inline int account_getpwuuid(
int fd,
const char *uuid,
struct passwd *passwd,
struct account_memory_pool *pool
) {
return account_getpwgrkey(
fd,
"GetUserInfo",
"uuid",
"\"",
uuid,
(pwgr_parser_t)account_recordpw,
passwd,
pool
);
}
static inline int account_getgrgid(
int fd,
gid_t gid,
struct group *group,
struct account_memory_pool *pool
) {
char gid_str[32];
int len = snprintf(gid_str, sizeof(gid_str), "%u", (unsigned int)gid);
REQ(len > 0 && (size_t)len < sizeof(gid_str));
return account_getpwgrkey(
fd,
"GetGroupInfo",
"host_gid",
"",
gid_str,
(pwgr_parser_t)account_recordgr,
group,
pool
);
}
static inline int account_getgrnam(
int fd,
const char *name,
struct group *group,
struct account_memory_pool *pool
) {
return account_getpwgrkey(
fd,
"GetGroupInfo",
"groupname",
"\"",
name,
(pwgr_parser_t)account_recordgr,
group,
pool
);
}
static inline int account_getgruuid(
int fd,
const char *uuid,
struct group *group,
struct account_memory_pool *pool
) {
return account_getpwgrkey(
fd,
"GetGroupInfo",
"uuid",
"\"",
uuid,
(pwgr_parser_t)account_recordgr,
group,
pool
);
}
static inline int account_getpwent(
int fd,
unsigned int *no,
struct passwd *passwd,
struct account_memory_pool *pool
) {
int status;
char *next_uuid = account_list_uuid_next(fd, "ListUser", *no);
REQ2(next_uuid, errno);
status = account_getpwuuid(fd, next_uuid, passwd, pool);
free(next_uuid);
REQ(status == 0);
*no += 1;
return 0;
}
static inline int account_getgrent(
int fd,
unsigned int *no,
struct group *group,
struct account_memory_pool *pool
) {
int status;
char *next_uuid = account_list_uuid_next(fd, "ListGroup", *no);
REQ2(next_uuid, errno);
status = account_getgruuid(fd, next_uuid, group, pool);
free(next_uuid);
REQ(status == 0);
*no += 1;
return 0;
}
#endif /* _ACCOUNT_CLIENT */
+11 -1
View File
@@ -71,6 +71,10 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t
goto cleanup_f;
}
if (groupbuf[GRMEMCNT] > (size_t)(INT32_MAX-1)) {
rv = ENOMEM;
goto cleanup_f;
}
if (groupbuf[GRNAMELEN] > SIZE_MAX - groupbuf[GRPASSWDLEN]) {
rv = ENOMEM;
goto cleanup_f;
@@ -127,7 +131,13 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t
if (groupbuf[GRMEMCNT]) {
mem[0][0] = *buf + groupbuf[GRNAMELEN] + groupbuf[GRPASSWDLEN];
for (ptr = mem[0][0], i = 0; ptr != mem[0][0]+grlist_len; ptr++)
if (!*ptr) mem[0][++i] = ptr+1;
if (!*ptr)
if (i<groupbuf[GRMEMCNT]) {
mem[0][++i] = ptr+1;
} else {
rv = EIO;
goto cleanup_f;
}
mem[0][i] = 0;
if (i != groupbuf[GRMEMCNT]) {
+53 -40
View File
@@ -1,49 +1,62 @@
#include "pwf.h"
#include <pthread.h>
#include "account_client.h"
#include <grp.h>
#include <string.h>
#include <errno.h>
#define FIX(x) (gr->gr_##x = gr->gr_##x-line+buf)
static int getgr_r(const char *name, gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
{
char *line = 0;
size_t len = 0;
char **mem = 0;
size_t nmem = 0;
int rv = 0;
size_t i;
int cs;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
rv = __getgr_a(name, gid, gr, &line, &len, &mem, &nmem, res);
if (*res && size < len + (nmem+1)*sizeof(char *) + 32) {
*res = 0;
rv = ERANGE;
}
if (*res) {
buf += (16-(uintptr_t)buf)%16;
gr->gr_mem = (void *)buf;
buf += (nmem+1)*sizeof(char *);
memcpy(buf, line, len);
FIX(name);
FIX(passwd);
for (i=0; mem[i]; i++)
gr->gr_mem[i] = mem[i]-line+buf;
gr->gr_mem[i] = 0;
}
free(mem);
free(line);
pthread_setcancelstate(cs, 0);
if (rv) errno = rv;
return rv;
}
#define VERIFYPOOL(pool) if (!pool.ptr || pool.len == 0) { if (res) *res = NULL; return EINVAL; }
int getgrnam_r(const char *name, struct group *gr, char *buf, size_t size, struct group **res)
{
return getgr_r(name, 0, gr, buf, size, res);
int ret;
int saved_errno;
DECLPOOL(pool, buf, size);
VERIFYPOOL(pool);
int fd = account_connect();
if (fd < 0) {
saved_errno = errno;
*res = NULL;
return saved_errno != 0 ? saved_errno : EIO;
}
ret = account_getgrnam(fd, name, gr, &pool);
saved_errno = errno;
spp_close(fd);
if (ret != 0) {
*res = NULL;
return 0;
}
*res = gr;
return 0;
}
int getgrgid_r(gid_t gid, struct group *gr, char *buf, size_t size, struct group **res)
{
return getgr_r(0, gid, gr, buf, size, res);
int ret;
int saved_errno;
DECLPOOL(pool, buf, size);
VERIFYPOOL(pool);
int fd = account_connect();
if (fd < 0) {
saved_errno = errno;
*res = NULL;
return saved_errno != 0 ? saved_errno : EIO;
}
ret = account_getgrgid(fd, gid, gr, &pool);
saved_errno = errno;
spp_close(fd);
if (ret != 0) {
*res = NULL;
return 0;
}
*res = gr;
return 0;
}
+50 -19
View File
@@ -1,39 +1,70 @@
#include "pwf.h"
#include <grp.h>
#include <string.h>
#include <errno.h>
#include "account_client.h"
static FILE *f;
static char *line, **mem;
static struct group gr;
static char grs_buf[16384];
unsigned int igrent = 0;
void setgrent()
{
if (f) fclose(f);
f = 0;
igrent = 0;
}
weak_alias(setgrent, endgrent);
struct group *getgrent()
{
struct group *res;
size_t size=0, nmem=0;
if (!f) f = fopen("/etc/group", "rbe");
if (!f) return 0;
__getgrent_a(f, &gr, &line, &size, &mem, &nmem, &res);
return res;
memset(&gr, 0, sizeof(gr));
memset(grs_buf, 0, sizeof(grs_buf));
DECLPOOL(pool, grs_buf, sizeof(grs_buf));
int fd = account_connect();
int status = account_getgrent(fd, &igrent, &gr, &pool);
spp_close(fd);
if (status != 0) return NULL;
return &gr;
}
struct group *getgrgid(gid_t gid)
{
struct group *res;
size_t size=0, nmem=0;
__getgr_a(0, gid, &gr, &line, &size, &mem, &nmem, &res);
return res;
struct group *result;
int ret;
memset(&gr, 0, sizeof(gr));
memset(grs_buf, 0, sizeof(grs_buf));
ret = getgrgid_r(gid, &gr, grs_buf, sizeof(grs_buf), &result);
if (ret != 0) {
errno = ret;
return NULL;
}
if (result == NULL) {
errno = 0;
return NULL;
}
return &gr;
}
struct group *getgrnam(const char *name)
{
struct group *res;
size_t size=0, nmem=0;
__getgr_a(name, 0, &gr, &line, &size, &mem, &nmem, &res);
return res;
struct group *result;
int ret;
memset(&gr, 0, sizeof(gr));
memset(grs_buf, 0, sizeof(grs_buf));
ret = getgrnam_r(name, &gr, grs_buf, sizeof(grs_buf), &result);
if (ret != 0) {
errno = ret;
return NULL;
}
if (result == NULL) {
errno = 0;
return NULL;
}
return &gr;
}
+53 -33
View File
@@ -1,42 +1,62 @@
#include "pwf.h"
#include <pthread.h>
#include "account_client.h"
#include <pwd.h>
#include <string.h>
#include <errno.h>
#define FIX(x) (pw->pw_##x = pw->pw_##x-line+buf)
static int getpw_r(const char *name, uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
{
char *line = 0;
size_t len = 0;
int rv = 0;
int cs;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
rv = __getpw_a(name, uid, pw, &line, &len, res);
if (*res && size < len) {
*res = 0;
rv = ERANGE;
}
if (*res) {
memcpy(buf, line, len);
FIX(name);
FIX(passwd);
FIX(gecos);
FIX(dir);
FIX(shell);
}
free(line);
pthread_setcancelstate(cs, 0);
if (rv) errno = rv;
return rv;
}
#define VERIFYPOOL(pool) if (!pool.ptr || pool.len == 0) { if (res) *res = NULL; return EINVAL; }
int getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t size, struct passwd **res)
{
return getpw_r(name, 0, pw, buf, size, res);
int ret;
int saved_errno;
DECLPOOL(pool, buf, size);
VERIFYPOOL(pool);
int fd = account_connect();
if (fd < 0) {
saved_errno = errno;
*res = NULL;
return saved_errno != 0 ? saved_errno : EIO;
}
ret = account_getpwnam(fd, name, pw, &pool);
saved_errno = errno;
spp_close(fd);
if (ret != 0) {
*res = NULL;
return 0;
}
*res = pw;
return 0;
}
int getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t size, struct passwd **res)
{
return getpw_r(0, uid, pw, buf, size, res);
int ret;
int saved_errno;
DECLPOOL(pool, buf, size);
VERIFYPOOL(pool);
int fd = account_connect();
if (fd < 0) {
saved_errno = errno;
*res = NULL;
return saved_errno != 0 ? saved_errno : EIO;
}
ret = account_getpwuid(fd, uid, pw, &pool);
saved_errno = errno;
spp_close(fd);
if (ret != 0) {
*res = NULL;
return 0;
}
*res = pw;
return 0;
}
+50 -17
View File
@@ -1,37 +1,70 @@
#include "pwf.h"
#include <pwd.h>
#include <string.h>
#include <errno.h>
#include "account_client.h"
static FILE *f;
static char *line;
static struct passwd pw;
static size_t size;
static char pwr_buf[16384];
unsigned int ipwent = 0;
void setpwent()
{
if (f) fclose(f);
f = 0;
ipwent = 0;
}
weak_alias(setpwent, endpwent);
struct passwd *getpwent()
{
struct passwd *res;
if (!f) f = fopen("/etc/passwd", "rbe");
if (!f) return 0;
__getpwent_a(f, &pw, &line, &size, &res);
return res;
memset(&pw, 0, sizeof(pw));
memset(pwr_buf, 0, sizeof(pwr_buf));
DECLPOOL(pool, pwr_buf, sizeof(pwr_buf));
int fd = account_connect();
int status = account_getpwent(fd, &ipwent, &pw, &pool);
spp_close(fd);
if (status != 0) return NULL;
return &pw;
}
struct passwd *getpwuid(uid_t uid)
{
struct passwd *res;
__getpw_a(0, uid, &pw, &line, &size, &res);
return res;
struct passwd *result;
int ret;
memset(&pw, 0, sizeof(pw));
memset(pwr_buf, 0, sizeof(pwr_buf));
ret = getpwuid_r(uid, &pw, pwr_buf, sizeof(pwr_buf), &result);
if (ret != 0) {
errno = ret;
return NULL;
}
if (result == NULL) {
errno = 0;
return NULL;
}
return &pw;
}
struct passwd *getpwnam(const char *name)
{
struct passwd *res;
__getpw_a(name, 0, &pw, &line, &size, &res);
return res;
struct passwd *result;
int ret;
memset(&pw, 0, sizeof(pw));
memset(pwr_buf, 0, sizeof(pwr_buf));
ret = getpwnam_r(name, &pw, pwr_buf, sizeof(pwr_buf), &result);
if (ret != 0) {
errno = ret;
return NULL;
}
if (result == NULL) {
errno = 0;
return NULL;
}
return &pw;
}
+3516
View File
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
#ifndef SPP_H
#define SPP_H
#include <sys/socket.h>
#include <sys/un.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
static inline int write_all(int fd, const void *buf, size_t len)
{
const char *p = buf;
size_t remaining = len;
while (remaining > 0) {
ssize_t n = write(fd, p, remaining);
if (n <= 0) return -1;
p += n;
remaining -= (size_t)n;
}
return 0;
}
static inline int read_all(int fd, void *buf, size_t len)
{
char *p = buf;
size_t remaining = len;
while (remaining > 0) {
ssize_t n = read(fd, p, remaining);
if (n <= 0) return -1;
p += n;
remaining -= (size_t)n;
}
return 0;
}
static inline int spp_connect_common(const char *path, int abstract)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) return -1;
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
size_t len = strlen(path);
if (len >= sizeof(addr.sun_path)) {
close(fd);
errno = ENAMETOOLONG;
return -1;
}
socklen_t addrlen;
if (abstract) {
addr.sun_path[0] = '\0';
memcpy(addr.sun_path + 1, path, len);
addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + len;
} else {
memcpy(addr.sun_path, path, len);
addrlen = offsetof(struct sockaddr_un, sun_path) + len;
}
if (connect(fd, (struct sockaddr *)&addr, addrlen) == -1) {
close(fd);
return -1;
}
return fd;
}
static inline int spp_connect_unix(char *path)
{
return spp_connect_common(path, 0);
}
static inline int spp_connect_linux(char *abstract_name)
{
return spp_connect_common(abstract_name, 1);
}
static inline void spp_close(int fd)
{
if (fd >= 0) close(fd);
}
static inline int spp_send(int fd, char *packet)
{
size_t data_len = strlen(packet);
if (data_len > UINT32_MAX) return -1;
uint32_t len = (uint32_t)data_len;
if (write_all(fd, &len, sizeof(len)) == -1) return -1;
if (data_len > 0 && write_all(fd, packet, data_len) == -1) return -1;
return 0;
}
static inline char *spp_recv(int fd)
{
uint32_t len;
if (read_all(fd, &len, sizeof(len)) == -1) return NULL;
char *buf = malloc(len + 1);
if (!buf) return NULL;
if (len > 0 && read_all(fd, buf, len) == -1) {
free(buf);
return NULL;
}
buf[len] = '\0';
return buf;
}
static inline void spp_free(void *p)
{
free(p);
}
#endif
+4
View File
@@ -69,6 +69,8 @@ _Noreturn void __pthread_exit(void *result)
__pthread_tsd_run_dtors();
__malloc_thread_done();
__block_app_sigs(&set);
/* This atomic potentially competes with a concurrent pthread_detach
@@ -204,6 +206,7 @@ static int start(void *p)
}
}
__syscall(SYS_rt_sigprocmask, SIG_SETMASK, &args->sig_mask, 0, _NSIG/8);
__malloc_thread_init();
__pthread_exit(args->start_func(args->start_arg));
return 0;
}
@@ -212,6 +215,7 @@ static int start_c11(void *p)
{
struct start_args *args = p;
int (*start)(void*) = (int(*)(void*)) args->start_func;
__malloc_thread_init();
__pthread_exit((void *)(uintptr_t)start(args->start_arg));
return 0;
}
+3 -3
View File
@@ -132,7 +132,7 @@ static void do_tzset()
"/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";
s = getenv("TZ");
if (!s) s = "/etc/localtime";
if (!s) s = "/var/config/localtime";
if (!*s) s = __utc;
if (old_tz && !strcmp(s, old_tz)) return;
@@ -163,7 +163,7 @@ static void do_tzset()
|| !strcmp(dummy_name, "UTC")
|| !strcmp(dummy_name, "GMT")))
posix_form = 1;
}
}
/* Non-suid can use an absolute tzfile pathname or a relative
* pathame beginning with "."; in secure mode, only the
@@ -171,7 +171,7 @@ static void do_tzset()
if (!posix_form) {
if (*s == ':') s++;
if (*s == '/' || *s == '.') {
if (!libc.secure || !strcmp(s, "/etc/localtime"))
if (!libc.secure || !strcmp(s, "/var/config/localtime"))
map = __map_file(s, &map_size);
} else {
size_t l = strlen(s);
+4 -3
View File
@@ -11,8 +11,7 @@ fn main() {
let dst = args.next().expect("please specify output file");
let mut octos = Vec::new();
let src_content = std::fs::read_to_string(&src)
.expect("cannot read source file");
let src_content = std::fs::read_to_string(&src).expect("cannot read source file");
let mut current_tag = None;
for (nline, line) in src_content.lines().enumerate() {
let line = line.trim();
@@ -129,7 +128,9 @@ fn do_arg(s: &str, content: &mut [u8; 8], cursor: &mut usize) -> Option<(usize,
_ => panic!("unknown radix"),
};
*cursor = 8;
*content = u64::from_str_radix(&digit[1..], radix).unwrap().to_be_bytes();
*content = u64::from_str_radix(&digit[1..], radix)
.unwrap()
.to_be_bytes();
None
} else if let Some(reg_id) = s.strip_prefix("&r") {
content[*cursor] = reg_id.parse::<u8>().unwrap();