diff options
author | Felix Fietkau <nbd@openwrt.org> | 2015-09-02 15:44:17 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-09-02 15:44:17 +0000 |
commit | 58ab3ad6b0f2cd1e302011e492832673f017ed08 (patch) | |
tree | 8db648d8e2d2a924f19168fad5fc8250508d83d6 /toolchain/musl/patches/001-git-2015-07-22.patch | |
parent | 3d1890053c68ea22c2b4532d2e839638261de8be (diff) | |
download | upstream-58ab3ad6b0f2cd1e302011e492832673f017ed08.tar.gz upstream-58ab3ad6b0f2cd1e302011e492832673f017ed08.tar.bz2 upstream-58ab3ad6b0f2cd1e302011e492832673f017ed08.zip |
musl: update to version 1.1.11
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 46772
Diffstat (limited to 'toolchain/musl/patches/001-git-2015-07-22.patch')
-rw-r--r-- | toolchain/musl/patches/001-git-2015-07-22.patch | 3146 |
1 files changed, 0 insertions, 3146 deletions
diff --git a/toolchain/musl/patches/001-git-2015-07-22.patch b/toolchain/musl/patches/001-git-2015-07-22.patch deleted file mode 100644 index 939de6bcd6..0000000000 --- a/toolchain/musl/patches/001-git-2015-07-22.patch +++ /dev/null @@ -1,3146 +0,0 @@ -commit 3975577922aedab7d60788dd320a2c8e4e94bc6e -Author: Roman Yeryomin <roman@ubnt.com> -Date: Thu Jul 2 12:29:00 2015 +0300 - - socket.h: cleanup/reorder mips and powerpc bits/socket.h - - ....to be somewhat consistent and easily comparable with asm/socket.h - - Signed-off-by: Roman Yeryomin <roman@ubnt.com> - -commit 29ec7677a73a5227badbb1064205be09e707e466 -Author: Roman Yeryomin <roman@ubnt.com> -Date: Thu Jul 2 12:28:41 2015 +0300 - - socket.h: fix SO_* for mips - - Signed-off-by: Roman Yeryomin <roman@ubnt.com> - -commit 3fffa7a658aa925b8f95d36aef7531c1827dbf28 -Author: Felix Fietkau <nbd@openwrt.org> -Date: Tue Jul 21 15:01:25 2015 +0200 - - mips: fix mcontext_t register array field name - - glibc and uclibc use gregs instead of regs - - Signed-off-by: Felix Fietkau <nbd@openwrt.org> - -commit 0f9c2666aca95eb98eb0ef4f4d8d1473c8ce3fa0 -Author: Rich Felker <dalias@aerifal.cx> -Date: Thu Jul 9 18:36:02 2015 +0000 - - handle loss of syslog socket connection - - when traditional syslogd implementations are restarted, the old server - socket ceases to exist and a new unix socket with the same pathname is - created. when this happens, the default destination address associated - with the client socket via connect is no longer valid, and attempts to - send produce errors. this happens despite the socket being datagram - type, and is in contrast to the behavior that would be seen with an IP - datagram (UDP) socket. - - in order to avoid a situation where the application is unable to send - further syslog messages without calling closelog, this patch makes - syslog attempt to reconnect the socket when send returns an error - indicating a lost connection. - - additionally, initial failure to connect the socket no longer results - in the socket being closed. this ensures that an application which - calls openlog to reserve the socket file descriptor will not run into - a situation where transient connection failure (e.g. due to syslogd - restart) prevents fd reservation. however, applications which may be - unable to connect the socket later (e.g. due to chroot, restricted - permissions, seccomp, etc.) will still fail to log if the syslog - socket cannot be connected at openlog time or if it has to be - reconnected later. - -commit 11894f6d3a80be950a490dc7dfab349f057a545f -Author: Rich Felker <dalias@aerifal.cx> -Date: Thu Jul 9 17:07:35 2015 +0000 - - fix incorrect void return type for syncfs function - - being nonstandard, the closest thing to a specification for this - function is its man page, which documents it as returning int. it can - fail with EBADF if the file descriptor passed is invalid. - -commit e8cbe0bad4284906230a53af4c91ad2b9713d03b -Author: Rich Felker <dalias@aerifal.cx> -Date: Wed Jul 8 02:46:45 2015 +0000 - - fix negated return value of ns_skiprr, breakage in related functions - - due to a reversed pointer difference computation, ns_skiprr always - returned a negative value, which functions using it would interpret as - an error. - - patch by Yu Lu. - -commit fb58545f8d1c5fa32122244caeaf3625c12ddc01 -Author: Shiz <hi@shiz.me> -Date: Sun Jun 28 23:08:21 2015 +0200 - - add musl-clang, a wrapper for system clang installs - - musl-clang allows the user to compile musl-powered programs using their - already existent clang install, without the need of a special cross compiler. - it achieves this by wrapping around both the system clang install and the - linker and passing them special flags to re-target musl at runtime. - it does only affect invocations done through the special musl-clang wrapper - script, so that the user setup remains fully intact otherwise. - - the clang wrapper consists of the compiler frontend wrapper script, - musl-clang, and the linker wrapper script, ld.musl-clang. - musl-clang makes sure clang invokes ld.musl-clang to link objects; neither - script needs to be in PATH for the wrapper to work. - -commit f8db6f74b2c74a50c4dec7e30be5215f0e2c37a6 -Author: Shiz <hi@shiz.me> -Date: Sun Jun 28 23:08:20 2015 +0200 - - build: fix musl-targeting toolchain test - - the old test was broken in that it would never fail on a toolchains built - without dynamic linking support, leading to the wrapper script possibly being - installed on compilers that do not support it. in addition, the new test is - portable across compilers: the old test only worked on GCC. - - the new test works by testing whether the toolchain libc defines __GLIBC__: - most non-musl Linux libc's do define this for compatibility even when they - are not glibc, so this is a safe bet to check for musl. in addition, the - compiler runtime would need to have a somewhat glibc-compatible ABI in the - first place, so any non-glibc compatible libc's compiler runtime might not - work. it is safer to disable these cases by default and have the user enable - the wrappers manually there using --enable-wrapper if they certain it works. - -commit b3cd7d13fe630ba1847326242525298e361018c1 -Author: Shiz <hi@shiz.me> -Date: Sun Jun 28 23:08:19 2015 +0200 - - build: overhaul wrapper script system for multiple wrapper support - - this overhauls part of the build system in order to support multiple - toolchain wrapper scripts, as opposed to solely the musl-gcc wrapper as - before. it thereby replaces --enable-gcc-wrapper with --enable-wrapper=..., - which has the options 'auto' (the default, detect whether to use wrappers), - 'all' (build and install all wrappers), 'no' (don't build any) and finally - the options named after the individual compiler scripts (currently only - 'gcc' is available) to build and install only that wrapper. - the old --enable-gcc-wrapper is removed from --help, but still available. - - it also modifies the wrappers to use the C compiler specified to the build - system as 'inner' compiler, when applicable. as wrapper detection works by - probing this compiler, it may not work with any other. - -commit 2a780aa3050b86d888489361f04220bfb58890a1 -Author: Rich Felker <dalias@aerifal.cx> -Date: Mon Jul 6 22:13:11 2015 +0000 - - treat empty TZ environment variable as GMT rather than default - - this improves compatibility with the behavior of other systems and - with some applications which set an empty TZ var to disable use of - local time by mktime, etc. - -commit 8f08a58c635bea5cdfae6bc0e323c80aa9ff82a7 -Author: Alexander Monakov <amonakov@ispras.ru> -Date: Sun Jun 28 02:48:33 2015 +0300 - - dynlink.c: pass gnu-hash table pointer to gnu_lookup - - The callers need to check the value of the pointer anyway, so make - them pass the pointer to gnu_lookup instead of reloading it there. - - Reorder gnu_lookup arguments so that always-used ones are listed - first. GCC can choose a calling convention with arguments in registers - (e.g. up to 3 arguments in eax, ecx, edx on x86), but cannot reorder - the arguments for static functions. - -commit 5b4286e12cd6baac343b10a41dc17ac578832089 -Author: Alexander Monakov <amonakov@ispras.ru> -Date: Sun Jun 28 02:48:32 2015 +0300 - - dynlink.c: slim down gnu_lookup - - Do not reference dso->syms and dso->strings until point of use. - Check 'h1 == (h2|1)', the simplest condition, before the others. - -commit 84389c64562e2b2ba43225b5b7a9df7d974479b1 -Author: Alexander Monakov <amonakov@ispras.ru> -Date: Sun Jun 28 02:48:31 2015 +0300 - - dynlink.c: use bloom filter in gnu hash lookup - - Introduce gnu_lookup_filtered and use it to speed up symbol lookups in - find_sym (do_dlsym is left as is, based on an expectation that - frequently dlsym queries will use a dlopen handle rather than - RTLD_NEXT or RTLD_DEFAULT, and will not need to look at more than one - DSO). - -commit 66d45787c865a1807ae397a89a14699394ed4fa4 -Author: Alexander Monakov <amonakov@ispras.ru> -Date: Sun Jun 28 02:48:30 2015 +0300 - - dynlink.c: use a faster expression in gnu_hash - - With -Os, GCC uses a multiply rather than a shift and addition for 'h*33'. - Use a more efficient expression explicitely. - -commit 6ba5517a460c6c438f64d69464fdfc3269a4c91a -Author: Rich Felker <dalias@aerifal.cx> -Date: Thu Jun 25 22:22:00 2015 +0000 - - fix local-dynamic model TLS on mips and powerpc - - the TLS ABI spec for mips, powerpc, and some other (presently - unsupported) RISC archs has the return value of __tls_get_addr offset - by +0x8000 and the result of DTPOFF relocations offset by -0x8000. I - had previously assumed this part of the ABI was actually just an - implementation detail, since the adjustments cancel out. however, when - the local dynamic model is used for accessing TLS that's known to be - in the same DSO, either of the following may happen: - - 1. the -0x8000 offset may already be applied to the argument structure - passed to __tls_get_addr at ld time, without any opportunity for - runtime relocations. - - 2. __tls_get_addr may be used with a zero offset argument to obtain a - base address for the module's TLS, to which the caller then applies - immediate offsets for individual objects accessed using the local - dynamic model. since the immediate offsets have the -0x8000 adjustment - applied to them, the base address they use needs to include the - +0x8000 offset. - - it would be possible, but more complex, to store the pointers in the - dtv[] array with the +0x8000 offset pre-applied, to avoid the runtime - cost of adding 0x8000 on each call to __tls_get_addr. this change - could be made later if measurements show that it would help. - -commit ce337daa00e42d4f2d9a4d9ae0ed51b20249d924 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 23 04:03:42 2015 +0000 - - make dynamic linker work around MAP_FAILED mmap failure on nommu kernels - - previously, loading of additional libraries beyond libc/ldso did not - work on nommu kernels, nor did loading programs via invocation of the - dynamic linker as a command. - -commit a59341420fdedb288d9ff80e73609ae44e9cf258 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 23 00:12:25 2015 +0000 - - reimplement strverscmp to fix corner cases - - this interface is non-standardized and is a GNU invention, and as - such, our implementation should match the behavior of the GNU - function. one peculiarity the old implementation got wrong was the - handling of all-zero digit sequences: they are supposed to compare - greater than digit sequences of which they are a proper prefix, as in - 009 < 00. - - in addition, high bytes were treated with char signedness rather than - as unsigned. this was wrong regardless of what the GNU function does - since the resulting order relation varied by arch. - - the new strverscmp implementation makes explicit the cases where the - order differs from what strcmp would produce, of which there are only - two. - -commit 153e952e1a688859d7095345b17e6c1df74a295c -Author: Rich Felker <dalias@aerifal.cx> -Date: Mon Jun 22 20:33:28 2015 +0000 - - fix regression/typo that disabled __simple_malloc when calloc is used - - commit ba819787ee93ceae94efd274f7849e317c1bff58 introduced this - regression. since the __malloc0 weak alias was not properly provided - by __simple_malloc, use of calloc forced the full malloc to be linked. - -commit ba819787ee93ceae94efd274f7849e317c1bff58 -Author: Rich Felker <dalias@aerifal.cx> -Date: Mon Jun 22 18:50:09 2015 +0000 - - fix calloc when __simple_malloc implementation is used - - previously, calloc's implementation encoded assumptions about the - implementation of malloc, accessing a size_t word just prior to the - allocated memory to determine if it was obtained by mmap to optimize - out the zero-filling. when __simple_malloc is used (static linking a - program with no realloc/free), it doesn't matter if the result of this - check is wrong, since all allocations are zero-initialized anyway. but - the access could be invalid if it crosses a page boundary or if the - pointer is not sufficiently aligned, which can happen for very small - allocations. - - this patch fixes the issue by moving the zero-fill logic into malloc.c - with the full malloc, as a new function named __malloc0, which is - provided by a weak alias to __simple_malloc (which always gives - zero-filled memory) when the full malloc is not in use. - -commit 55d061f031085f24d138664c897791aebe9a2fab -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 20 03:01:07 2015 +0000 - - provide __stack_chk_fail_local in libc.a - - this symbol is needed only on archs where the PLT call ABI is klunky, - and only for position-independent code compiled with stack protector. - thus references usually only appear in shared libraries or PIE - executables, but they can also appear when linking statically if some - of the object files being linked were built as PIC/PIE. - - normally libssp_nonshared.a from the compiler toolchain should provide - __stack_chk_fail_local, but reportedly it appears prior to -lc in the - link order, thus failing to satisfy references from libc itself (which - arise only if libc.a was built as PIC/PIE with stack protector - enabled). - -commit ce3688eca920aa77549323f84e21f33522397115 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 20 02:54:30 2015 +0000 - - work around mips detached thread exit breakage due to kernel regression - - linux kernel commit 46e12c07b3b9603c60fc1d421ff18618241cb081 caused - the mips syscall mechanism to fail with EFAULT when the userspace - stack pointer is invalid, breaking __unmapself used for detached - thread exit. the workaround is to set $sp to a known-valid, readable - address, and the simplest one to obtain is the address of the current - function, which is available (per o32 calling convention) in $25. - -commit 75eceb3ae824d54e865686c0c538551aeebf3372 -Author: Rich Felker <dalias@aerifal.cx> -Date: Wed Jun 17 17:21:46 2015 +0000 - - ignore ENOSYS error from mprotect in pthread_create and dynamic linker - - this error simply indicated a system without memory protection (NOMMU) - and should not cause failure in the caller. - -commit 10d0268ccfab9152250eeeed3952ce3fed44131a -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 15:25:02 2015 +0000 - - switch to using trap number 31 for syscalls on sh - - nominally the low bits of the trap number on sh are the number of - syscall arguments, but they have never been used by the kernel, and - some code making syscalls does not even know the number of arguments - and needs to pass an arbitrary high number anyway. - - sh3/sh4 traditionally used the trap range 16-31 for syscalls, but part - of this range overlapped with hardware exceptions/interrupts on sh2 - hardware, so an incompatible range 32-47 was chosen for sh2. - - using trap number 31 everywhere, since it's in the existing sh3/sh4 - range and does not conflict with sh2 hardware, is a proposed - unification of the kernel syscall convention that will allow binaries - to be shared between sh2 and sh3/sh4. if this is not accepted into the - kernel, we can refit the sh2 target with runtime selection mechanisms - for the trap number, but doing so would be invasive and would entail - non-trivial overhead. - -commit 3366a99b17847b58f2d8cc52cbb5d65deb824f8a -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 14:55:06 2015 +0000 - - switch sh port's __unmapself to generic version when running on sh2/nommu - - due to the way the interrupt and syscall trap mechanism works, - userspace on sh2 must never set the stack pointer to an invalid value. - thus, the approach used on most archs, where __unmapself executes with - no stack for the interval between SYS_munmap and SYS_exit, is not - viable on sh2. - - in order not to pessimize sh3/sh4, the sh asm version of __unmapself - is not removed. instead it's renamed and redirected through code that - calls either the generic (safe) __unmapself or the sh3/sh4 asm, - depending on compile-time and run-time conditions. - -commit f9d84554bae0fa17c9a1d724549c4408022228a5 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 14:28:30 2015 +0000 - - add support for sh2 interrupt-masking-based atomics to sh port - - the sh2 target is being considered an ISA subset of sh3/sh4, in the - sense that binaries built for sh2 are intended to be usable on later - cpu models/kernels with mmu support. so rather than hard-coding - sh2-specific atomics, the runtime atomic selection mechanisms that was - already in place has been extended to add sh2 atomics. - - at this time, the sh2 atomics are not SMP-compatible; since the ISA - lacks actual atomic operations, the new code instead masks interrupts - for the duration of the atomic operation, producing an atomic result - on single-core. this is only possible because the kernel/hardware does - not impose protections against userspace doing so. additional changes - will be needed to support future SMP systems. - - care has been taken to avoid producing significant additional code - size in the case where it's known at compile-time that the target is - not sh2 and does not need sh2-specific code. - -commit 1b0cdc8700d29ef018bf226d74b2b58b23bce91c -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 07:11:19 2015 +0000 - - refactor stdio open file list handling, move it out of global libc struct - - functions which open in-memory FILE stream variants all shared a tail - with __fdopen, adding the FILE structure to stdio's open file list. - replacing this common tail with a function call reduces code size and - duplication of logic. the list is also partially encapsulated now. - - function signatures were chosen to facilitate tail call optimization - and reduce the need for additional accessor functions. - - with these changes, static linked programs that do not use stdio no - longer have an open file list at all. - -commit f22a9edaf8a6f2ca1d314d18b3785558279a5c03 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 06:18:00 2015 +0000 - - byte-based C locale, phase 3: make MB_CUR_MAX variable to activate code - - this patch activates the new byte-based C locale (high bytes treated - as abstract code unit "characters" rather than decoded as multibyte - characters) by making the value of MB_CUR_MAX depend on the active - locale. for the C locale, the LC_CTYPE category pointer is null, - yielding a value of 1. all other locales yield a value of 4. - -commit 16f18d036d9a7bf590ee6eb86785c0a9658220b6 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 05:35:31 2015 +0000 - - byte-based C locale, phase 2: stdio and iconv (multibyte callers) - - this patch adjusts libc components which use the multibyte functions - internally, and which depend on them operating in a particular - encoding, to make the appropriate locale changes before calling them - and restore the calling thread's locale afterwards. activating the - byte-based C locale without these changes would cause regressions in - stdio and iconv. - - in the case of iconv, the current implementation was simply using the - multibyte functions as UTF-8 conversions. setting a multibyte UTF-8 - locale for the duration of the iconv operation allows the code to - continue working. - - in the case of stdio, POSIX requires that FILE streams have an - encoding rule bound at the time of setting wide orientation. as long - as all locales, including the C locale, used the same encoding, - treating high bytes as UTF-8, there was no need to store an encoding - rule as part of the stream's state. - - a new locale field in the FILE structure points to the locale that - should be made active during fgetwc/fputwc/ungetwc on the stream. it - cannot point to the locale active at the time the stream becomes - oriented, because this locale could be mutable (the global locale) or - could be destroyed (locale_t objects produced by newlocale) before the - stream is closed. instead, a pointer to the static C or C.UTF-8 locale - object added in commit commit aeeac9ca5490d7d90fe061ab72da446c01ddf746 - is used. this is valid since categories other than LC_CTYPE will not - affect these functions. - -commit 1507ebf837334e9e07cfab1ca1c2e88449069a80 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 04:44:17 2015 +0000 - - byte-based C locale, phase 1: multibyte character handling functions - - this patch makes the functions which work directly on multibyte - characters treat the high bytes as individual abstract code units - rather than as multibyte sequences when MB_CUR_MAX is 1. since - MB_CUR_MAX is presently defined as a constant 4, all of the new code - added is dead code, and optimizing compilers' code generation should - not be affected at all. a future commit will activate the new code. - - as abstract code units, bytes 0x80 to 0xff are represented by wchar_t - values 0xdf80 to 0xdfff, at the end of the surrogates range. this - ensures that they will never be misinterpreted as Unicode characters, - and that all wctype functions return false for these "characters" - without needing locale-specific logic. a high range outside of Unicode - such as 0x7fffff80 to 0x7fffffff was also considered, but since C11's - char16_t also needs to be able to represent conversions of these - bytes, the surrogate range was the natural choice. - -commit 38e2f727237230300fea6aff68802db04625fd23 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 16 04:21:38 2015 +0000 - - fix btowc corner case - - btowc is required to interpret its argument by conversion to unsigned - char, unless the argument is equal to EOF. since the conversion to - produces a non-character value anyway, we can just unconditionally - convert, for now. - -commit ee59c296d56bf26f49f354d6eb32b4b6d4190188 -Author: Szabolcs Nagy <nsz@port70.net> -Date: Wed Jun 3 10:32:14 2015 +0100 - - arm: add vdso support - - vdso will be available on arm in linux v4.2, the user-space code - for it is in kernel commit 8512287a8165592466cb9cb347ba94892e9c56a5 - -commit e3bc22f1eff87b8f029a6ab31f1a269d69e4b053 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sun Jun 14 01:59:02 2015 +0000 - - refactor malloc's expand_heap to share with __simple_malloc - - this extends the brk/stack collision protection added to full malloc - in commit 276904c2f6bde3a31a24ebfa201482601d18b4f9 to also protect the - __simple_malloc function used in static-linked programs that don't - reference the free function. - - it also extends support for using mmap when brk fails, which full - malloc got in commit 5446303328adf4b4e36d9fba21848e6feb55fab4, to - __simple_malloc. - - since __simple_malloc may expand the heap by arbitrarily large - increments, the stack collision detection is enhanced to detect - interval overlap rather than just proximity of a single address to the - stack. code size is increased a bit, but this is partly offset by the - sharing of code between the two malloc implementations, which due to - linking semantics, both get linked in a program that needs the full - malloc with realloc/free support. - -commit 4ef9b828c1f39553a69e0635ac91f0fcadd6e8c6 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 13 20:53:02 2015 +0000 - - remove cancellation points in stdio - - commit 58165923890865a6ac042fafce13f440ee986fd9 added these optional - cancellation points on the basis that cancellable stdio could be - useful, to unblock threads stuck on stdio operations that will never - complete. however, the only way to ensure that cancellation can - achieve this is to violate the rules for side effects when - cancellation is acted upon, discarding knowledge of any partial data - transfer already completed. our implementation exhibited this behavior - and was thus non-conforming. - - in addition to improving correctness, removing these cancellation - points moderately reduces code size, and should significantly improve - performance on i386, where sysenter/syscall instructions can be used - instead of "int $128" for non-cancellable syscalls. - -commit 536c6d5a4205e2a3f161f2983ce1e0ac3082187d -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 13 05:17:16 2015 +0000 - - fix idiom for setting stdio stream orientation to wide - - the old idiom, f->mode |= f->mode+1, was adapted from the idiom for - setting byte orientation, f->mode |= f->mode-1, but the adaptation was - incorrect. unless the stream was alreasdy set byte-oriented, this code - incremented f->mode each time it was executed, which would eventually - lead to overflow. it could be fixed by changing it to f->mode |= 1, - but upcoming changes will require slightly more work at the time of - wide orientation, so it makes sense to just call fwide. as an - optimization in the single-character functions, fwide is only called - if the stream is not already wide-oriented. - -commit f8f565df467c13248104223f99abf7f37cef7584 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 13 04:42:38 2015 +0000 - - add printing of null %s arguments as "(null)" in wide printf - - this is undefined, but supported in our implementation of the normal - printf, so for consistency the wide variant should support it too. - -commit f9e25d813860d53cd1e9b6145cc63375d2fe2529 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 13 04:37:27 2015 +0000 - - add %m support to wide printf - -commit ec634aad91f57479ef17525e33ed446c780a61f4 -Author: Rich Felker <dalias@aerifal.cx> -Date: Thu Jun 11 05:01:04 2015 +0000 - - add sh asm for vfork - -commit c30cbcb0a646b1f13a22c645616dce624465b883 -Author: Rich Felker <dalias@aerifal.cx> -Date: Wed Jun 10 02:27:40 2015 +0000 - - implement arch-generic version of __unmapself - - this can be used to put off writing an asm version of __unmapself for - new archs, or as a permanent solution on archs where it's not - practical or even possible to run momentarily with no stack. - - the concept here is simple: the caller takes a lock on a global shared - stack and uses it to make the munmap and exit syscalls. the only trick - is unlocking, which must be done after the thread exits, and this is - achieved by using the set_tid_address syscall to have the kernel zero - and futex-wake the lock word as part of the exit syscall. - -commit 276904c2f6bde3a31a24ebfa201482601d18b4f9 -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 9 20:30:35 2015 +0000 - - in malloc, refuse to use brk if it grows into stack - - the linux/nommu fdpic ELF loader sets up the brk range to overlap - entirely with the main thread's stack (but growing from opposite - ends), so that the resulting failure mode for malloc is not to return - a null pointer but to start returning pointers to memory that overlaps - with the caller's stack. needless to say this extremely dangerous and - makes brk unusable. - - since it's non-trivial to detect execution environments that might be - affected by this kernel bug, and since the severity of the bug makes - any sort of detection that might yield false-negatives unsafe, we - instead check the proximity of the brk to the stack pointer each time - the brk is to be expanded. both the main thread's stack (where the - real known risk lies) and the calling thread's stack are checked. an - arbitrary gap distance of 8 MB is imposed, chosen to be larger than - linux default main-thread stack reservation sizes and larger than any - reasonable stack configuration on nommu. - - the effeciveness of this patch relies on an assumption that the amount - by which the brk is being grown is smaller than the gap limit, which - is always true for malloc's use of brk. reliance on this assumption is - why the check is being done in malloc-specific code and not in __brk. - -commit bd1eaceaa3975bd2a2a34e211cff896affaecadf -Author: Rich Felker <dalias@aerifal.cx> -Date: Tue Jun 9 20:09:27 2015 +0000 - - fix spurious errors from pwd/grp functions when nscd backend is absent - - for several pwd/grp functions, the only way the caller can distinguish - between a successful negative result ("no such user/group") and an - internal error is by clearing errno before the call and checking errno - afterwards. the nscd backend support code correctly simulated a - not-found response on systems where such a backend is not running, but - failed to restore errno. - - this commit also fixed an outdated/incorrect comment. - -commit 75ce4503950621b11fcc7f1fd1187dbcf3cde312 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sun Jun 7 20:55:23 2015 +0000 - - fix regression in pre-v7 arm on kernels with kuser helper removed - - the arm atomics/TLS runtime selection code is called from - __set_thread_area and depends on having libc.auxv and __hwcap - available. commit 71f099cb7db821c51d8f39dfac622c61e54d794c moved the - first call to __set_thread_area to the top of dynamic linking stage 3, - before this data is made available, causing the runtime detection code - to always see __hwcap as zero and thereby select the atomics/TLS - implementations based on kuser helper. - - upcoming work on superh will use similar runtime detection. - - ideally this early-init code should be cleanly refactored and shared - between the dynamic linker and static-linked startup. - -commit 32f3c4f70633488550c29a2444f819aafdf345ff -Author: Rich Felker <dalias@aerifal.cx> -Date: Sun Jun 7 03:09:16 2015 +0000 - - add multiple inclusion guard to locale_impl.h - -commit 04b8360adbb6487f61aa0c00e53ec3a90a5a0d29 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sun Jun 7 02:59:49 2015 +0000 - - remove redefinition of MB_CUR_MAX in locale_impl.h - - unless/until the byte-based C locale is implemented, defining - MB_CUR_MAX to 1 in the C locale is wrong. no internal code currently - uses the MB_CUR_MAX macro, but having it defined inconsistently is - error-prone. applications get the value from stdlib.h and were - unaffected. - -commit 16bf466532d7328e971012b0731ad493b017ad29 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 6 18:53:02 2015 +0000 - - make static C and C.UTF-8 locales available outside of newlocale - -commit 312eea2ea4f4363fb01b73660c08bfcf43dd3bb4 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 6 18:20:30 2015 +0000 - - remove another invalid skip of locking in ungetwc - -commit 3d7e32d28dc9962e9efc1c317c5b44b5b2df3008 -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 6 18:16:22 2015 +0000 - - add macro version of ctype.h isascii function - - presumably internal code (ungetwc and fputwc) was written assuming a - macro implementation existed; otherwise use of isascii is just a - pessimization. - -commit 7e816a6487932cbb3cb71d94b609e50e81f4e5bf -Author: Rich Felker <dalias@aerifal.cx> -Date: Sat Jun 6 18:11:17 2015 +0000 - - remove invalid skip of locking in ungetwc - - aside from being invalid, the early check only optimized the error - case, and likely pessimized the common case by separating the - two branches on isascii(c) at opposite ends of the function. - -commit 63f4b9f18f3674124d8bcb119739fec85e6da005 -Author: Timo Teräs <timo.teras@iki.fi> -Date: Fri Jun 5 10:39:42 2015 +0300 - - fix uselocale((locale_t)0) not to modify locale - - commit 68630b55c0c7219fe9df70dc28ffbf9efc8021d8 made the new locale to - be assigned unconditonally resulting in crashes later on. - ---- a/.gitignore -+++ b/.gitignore -@@ -7,5 +7,7 @@ arch/*/bits/alltypes.h - config.mak - include/bits - tools/musl-gcc -+tools/musl-clang -+tools/ld.musl-clang - lib/musl-gcc.specs - src/internal/version.h ---- a/Makefile -+++ b/Makefile -@@ -51,6 +51,9 @@ TOOL_LIBS = lib/musl-gcc.specs - ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS) - ALL_TOOLS = tools/musl-gcc - -+WRAPCC_GCC = gcc -+WRAPCC_CLANG = clang -+ - LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1 - - -include config.mak -@@ -155,7 +158,11 @@ lib/musl-gcc.specs: tools/musl-gcc.specs - sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@ - - tools/musl-gcc: config.mak -- printf '#!/bin/sh\nexec "$${REALGCC:-gcc}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@ -+ printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@ -+ chmod +x $@ -+ -+tools/%-clang: tools/%-clang.in config.mak -+ sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@ - chmod +x $@ - - $(DESTDIR)$(bindir)/%: tools/% ---- a/arch/arm/syscall_arch.h -+++ b/arch/arm/syscall_arch.h -@@ -72,3 +72,7 @@ static inline long __syscall6(long n, lo - register long r5 __asm__("r5") = f; - __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); - } -+ -+#define VDSO_USEFUL -+#define VDSO_CGT_SYM "__vdso_clock_gettime" -+#define VDSO_CGT_VER "LINUX_2.6" ---- a/arch/mips/bits/signal.h -+++ b/arch/mips/bits/signal.h -@@ -28,7 +28,7 @@ struct sigcontext - typedef struct - { - unsigned regmask, status; -- unsigned long long pc, regs[32], fpregs[32]; -+ unsigned long long pc, gregs[32], fpregs[32]; - unsigned ownedfp, fpc_csr, fpc_eir, used_math, dsp; - unsigned long long mdhi, mdlo; - unsigned long hi1, lo1, hi2, lo2, hi3, lo3; ---- a/arch/mips/bits/socket.h -+++ b/arch/mips/bits/socket.h -@@ -22,26 +22,31 @@ struct cmsghdr - #define SOL_SOCKET 65535 - - #define SO_DEBUG 1 --#define SO_REUSEADDR 4 --#define SO_TYPE 0x1008 --#define SO_ERROR 0x1007 --#define SO_DONTROUTE 16 --#define SO_BROADCAST 32 -+ -+#define SO_REUSEADDR 0x0004 -+#define SO_KEEPALIVE 0x0008 -+#define SO_DONTROUTE 0x0010 -+#define SO_BROADCAST 0x0020 -+#define SO_LINGER 0x0080 -+#define SO_OOBINLINE 0x0100 -+#define SO_REUSEPORT 0x0200 - #define SO_SNDBUF 0x1001 - #define SO_RCVBUF 0x1002 --#define SO_KEEPALIVE 8 --#define SO_OOBINLINE 256 -+#define SO_SNDLOWAT 0x1003 -+#define SO_RCVLOWAT 0x1004 -+#define SO_RCVTIMEO 0x1006 -+#define SO_SNDTIMEO 0x1005 -+#define SO_ERROR 0x1007 -+#define SO_TYPE 0x1008 -+#define SO_ACCEPTCONN 0x1009 -+#define SO_PROTOCOL 0x1028 -+#define SO_DOMAIN 0x1029 -+ - #define SO_NO_CHECK 11 - #define SO_PRIORITY 12 --#define SO_LINGER 128 - #define SO_BSDCOMPAT 14 --#define SO_REUSEPORT 512 - #define SO_PASSCRED 17 - #define SO_PEERCRED 18 --#define SO_RCVLOWAT 0x1004 --#define SO_SNDLOWAT 0x1003 --#define SO_RCVTIMEO 0x1006 --#define SO_SNDTIMEO 0x1005 - #define SO_SNDBUFFORCE 31 - #define SO_RCVBUFFORCE 33 - ---- a/arch/mips/pthread_arch.h -+++ b/arch/mips/pthread_arch.h -@@ -13,4 +13,6 @@ static inline struct pthread *__pthread_ - #define TLS_ABOVE_TP - #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) - -+#define DTP_OFFSET 0x8000 -+ - #define CANCEL_REG_IP (3-(union {int __i; char __b;}){1}.__b) ---- a/arch/powerpc/bits/socket.h -+++ b/arch/powerpc/bits/socket.h -@@ -24,8 +24,6 @@ struct cmsghdr - #define SO_BROADCAST 6 - #define SO_SNDBUF 7 - #define SO_RCVBUF 8 --#define SO_SNDBUFFORCE 32 --#define SO_RCVBUFFORCE 33 - #define SO_KEEPALIVE 9 - #define SO_OOBINLINE 10 - #define SO_NO_CHECK 11 -@@ -39,4 +37,8 @@ struct cmsghdr - #define SO_SNDTIMEO 19 - #define SO_PASSCRED 20 - #define SO_PEERCRED 21 -- -+#define SO_ACCEPTCONN 30 -+#define SO_SNDBUFFORCE 32 -+#define SO_RCVBUFFORCE 33 -+#define SO_PROTOCOL 38 -+#define SO_DOMAIN 39 ---- a/arch/powerpc/pthread_arch.h -+++ b/arch/powerpc/pthread_arch.h -@@ -12,6 +12,8 @@ static inline struct pthread *__pthread_ - #define TLS_ABOVE_TP - #define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000) - -+#define DTP_OFFSET 0x8000 -+ - // offset of the PC register in mcontext_t, divided by the system wordsize - // the kernel calls the ip "nip", it's the first saved value after the 32 - // GPRs. ---- /dev/null -+++ b/arch/sh/src/__set_thread_area.c -@@ -0,0 +1,34 @@ -+#include "pthread_impl.h" -+#include "libc.h" -+#include "sh_atomic.h" -+#include <elf.h> -+ -+/* Also perform sh-specific init */ -+ -+#define CPU_HAS_LLSC 0x0040 -+ -+__attribute__((__visibility__("hidden"))) unsigned __sh_atomic_model, __sh_nommu; -+ -+int __set_thread_area(void *p) -+{ -+ size_t *aux; -+ __asm__ __volatile__ ( "ldc %0, gbr" : : "r"(p) : "memory" ); -+#ifndef __SH4A__ -+ if (__hwcap & CPU_HAS_LLSC) { -+ __sh_atomic_model = SH_A_LLSC; -+ return 0; -+ } -+#if !defined(__SH3__) && !defined(__SH4__) -+ for (aux=libc.auxv; *aux; aux+=2) { -+ if (*aux != AT_PLATFORM) continue; -+ const char *s = (void *)aux[1]; -+ if (s[0]!='s' || s[1]!='h' || s[2]!='2' || s[3]-'0'<10u) break; -+ __sh_atomic_model = SH_A_IMASK; -+ __sh_nommu = 1; -+ return 0; -+ } -+#endif -+ /* __sh_atomic_model = SH_A_GUSA; */ /* 0, default */ -+#endif -+ return 0; -+} ---- /dev/null -+++ b/arch/sh/src/__unmapself.c -@@ -0,0 +1,19 @@ -+#include "pthread_impl.h" -+ -+void __unmapself_sh_mmu(void *, size_t); -+void __unmapself_sh_nommu(void *, size_t); -+ -+#if !defined(__SH3__) && !defined(__SH4__) -+#define __unmapself __unmapself_sh_nommu -+#include "../../../src/thread/__unmapself.c" -+#undef __unmapself -+extern __attribute__((__visibility__("hidden"))) unsigned __sh_nommu; -+#else -+#define __sh_nommu 0 -+#endif -+ -+void __unmapself(void *base, size_t size) -+{ -+ if (__sh_nommu) __unmapself_sh_nommu(base, size); -+ else __unmapself_sh_mmu(base, size); -+} ---- a/arch/sh/src/atomic.c -+++ b/arch/sh/src/atomic.c -@@ -1,8 +1,26 @@ - #ifndef __SH4A__ - -+#include "sh_atomic.h" - #include "atomic.h" - #include "libc.h" - -+static inline unsigned mask() -+{ -+ unsigned sr; -+ __asm__ __volatile__ ( "\n" -+ " stc sr,r0 \n" -+ " mov r0,%0 \n" -+ " or #0xf0,r0 \n" -+ " ldc r0,sr \n" -+ : "=&r"(sr) : : "memory", "r0" ); -+ return sr; -+} -+ -+static inline void unmask(unsigned sr) -+{ -+ __asm__ __volatile__ ( "ldc %0,sr" : : "r"(sr) : "memory" ); -+} -+ - /* gusa is a hack in the kernel which lets you create a sequence of instructions - * which will be restarted if the process is preempted in the middle of the - * sequence. It will do for implementing atomics on non-smp systems. ABI is: -@@ -25,11 +43,17 @@ - " mov.l " new ", @" mem "\n" \ - "1: mov r1, r15\n" - --#define CPU_HAS_LLSC 0x0040 -- - int __sh_cas(volatile int *p, int t, int s) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_cas_llsc(p, t, s); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_cas_llsc(p, t, s); -+ -+ if (__sh_atomic_model == SH_A_IMASK) { -+ unsigned sr = mask(); -+ int old = *p; -+ if (old==t) *p = s; -+ unmask(sr); -+ return old; -+ } - - int old; - __asm__ __volatile__( -@@ -43,7 +67,15 @@ int __sh_cas(volatile int *p, int t, int - - int __sh_swap(volatile int *x, int v) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_swap_llsc(x, v); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_swap_llsc(x, v); -+ -+ if (__sh_atomic_model == SH_A_IMASK) { -+ unsigned sr = mask(); -+ int old = *x; -+ *x = v; -+ unmask(sr); -+ return old; -+ } - - int old; - __asm__ __volatile__( -@@ -55,7 +87,15 @@ int __sh_swap(volatile int *x, int v) - - int __sh_fetch_add(volatile int *x, int v) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_fetch_add_llsc(x, v); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_fetch_add_llsc(x, v); -+ -+ if (__sh_atomic_model == SH_A_IMASK) { -+ unsigned sr = mask(); -+ int old = *x; -+ *x = old + v; -+ unmask(sr); -+ return old; -+ } - - int old, dummy; - __asm__ __volatile__( -@@ -69,7 +109,7 @@ int __sh_fetch_add(volatile int *x, int - - void __sh_store(volatile int *p, int x) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_store_llsc(p, x); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_store_llsc(p, x); - __asm__ __volatile__( - " mov.l %1, @%0\n" - : : "r"(p), "r"(x) : "memory"); -@@ -77,7 +117,15 @@ void __sh_store(volatile int *p, int x) - - void __sh_and(volatile int *x, int v) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_and_llsc(x, v); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_and_llsc(x, v); -+ -+ if (__sh_atomic_model == SH_A_IMASK) { -+ unsigned sr = mask(); -+ int old = *x; -+ *x = old & v; -+ unmask(sr); -+ return; -+ } - - int dummy; - __asm__ __volatile__( -@@ -89,7 +137,15 @@ void __sh_and(volatile int *x, int v) - - void __sh_or(volatile int *x, int v) - { -- if (__hwcap & CPU_HAS_LLSC) return __sh_or_llsc(x, v); -+ if (__sh_atomic_model == SH_A_LLSC) return __sh_or_llsc(x, v); -+ -+ if (__sh_atomic_model == SH_A_IMASK) { -+ unsigned sr = mask(); -+ int old = *x; -+ *x = old | v; -+ unmask(sr); -+ return; -+ } - - int dummy; - __asm__ __volatile__( ---- /dev/null -+++ b/arch/sh/src/sh_atomic.h -@@ -0,0 +1,15 @@ -+#ifndef _SH_ATOMIC_H -+#define _SH_ATOMIC_H -+ -+#define SH_A_GUSA 0 -+#define SH_A_LLSC 1 -+#define SH_A_CAS 2 -+#if !defined(__SH3__) && !defined(__SH4__) -+#define SH_A_IMASK 3 -+#else -+#define SH_A_IMASK -1LL /* unmatchable by unsigned int */ -+#endif -+ -+extern __attribute__((__visibility__("hidden"))) unsigned __sh_atomic_model; -+ -+#endif ---- a/arch/sh/syscall_arch.h -+++ b/arch/sh/syscall_arch.h -@@ -8,7 +8,7 @@ - */ - #define __asm_syscall(trapno, ...) do { \ - __asm__ __volatile__ ( \ -- "trapa #" #trapno "\n" \ -+ "trapa #31\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ - "or r0, r0\n" \ ---- a/configure -+++ b/configure -@@ -28,7 +28,7 @@ Optional features: - --enable-debug build with debugging information [disabled] - --enable-warnings build with recommended warnings flags [disabled] - --enable-visibility use global visibility options to optimize PIC [auto] -- --enable-gcc-wrapper build musl-gcc toolchain wrapper [auto] -+ --enable-wrapper=... build given musl toolchain wrapper [auto] - --disable-shared inhibit building shared library [enabled] - --disable-static inhibit building static library [enabled] - -@@ -123,6 +123,8 @@ bindir='$(exec_prefix)/bin' - libdir='$(prefix)/lib' - includedir='$(prefix)/include' - syslibdir='/lib' -+tools= -+tool_libs= - target= - optimize=auto - debug=no -@@ -131,6 +133,8 @@ visibility=auto - shared=auto - static=yes - wrapper=auto -+gcc_wrapper=no -+clang_wrapper=no - - for arg ; do - case "$arg" in -@@ -154,7 +158,12 @@ case "$arg" in - --disable-warnings|--enable-warnings=no) warnings=no ;; - --enable-visibility|--enable-visibility=yes) visibility=yes ;; - --disable-visibility|--enable-visibility=no) visibility=no ;; ----enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ;; -+--enable-wrapper|--enable-wrapper=yes) wrapper=detect ;; -+--enable-wrapper=all) wrapper=yes ; gcc_wrapper=yes ; clang_wrapper=yes ;; -+--enable-wrapper=gcc) wrapper=yes ; gcc_wrapper=yes ;; -+--enable-wrapper=clang) wrapper=yes ; clang_wrapper=yes ;; -+--disable-wrapper|--enable-wrapper=no) wrapper=no ;; -+--enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ; gcc_wrapper=yes ;; - --disable-gcc-wrapper|--enable-gcc-wrapper=no) wrapper=no ;; - --enable-*|--disable-*|--with-*|--without-*|--*dir=*|--build=*) ;; - --host=*|--target=*) target=${arg#*=} ;; -@@ -215,36 +224,51 @@ tryldflag LDFLAGS_TRY -Werror=unknown-wa - tryldflag LDFLAGS_TRY -Werror=unused-command-line-argument - - # --# Need to know if the compiler is gcc to decide whether to build the --# musl-gcc wrapper, and for critical bug detection in some gcc versions. -+# Need to know if the compiler is gcc or clang to decide which toolchain -+# wrappers to build. - # --printf "checking whether compiler is gcc... " --if fnmatch '*gcc\ version*' "$(LC_ALL=C $CC -v 2>&1)" ; then --cc_is_gcc=yes -+printf "checking for C compiler family... " -+cc_ver="$(LC_ALL=C $CC -v 2>&1)" -+cc_family=unknown -+if fnmatch '*gcc\ version*' "$cc_ver" ; then -+cc_family=gcc -+elif fnmatch '*clang\ version*' "$cc_ver" ; then -+cc_family=clang -+fi -+echo "$cc_family" -+ -+# -+# Figure out toolchain wrapper to build -+# -+if test "$wrapper" = auto -o "$wrapper" = detect ; then -+echo "#include <stdlib.h>" > "$tmpc" -+echo "#if ! __GLIBC__" >> "$tmpc" -+echo "#error no" >> "$tmpc" -+echo "#endif" >> "$tmpc" -+printf "checking for toolchain wrapper to build... " -+if test "$wrapper" = auto && ! $CC -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then -+echo "none" -+elif test "$cc_family" = gcc ; then -+gcc_wrapper=yes -+echo "gcc" -+elif test "$cc_family" = clang ; then -+clang_wrapper=yes -+echo "clang" - else --cc_is_gcc=no -+echo "none" -+if test "$wrapper" = detect ; then -+fail "$0: could not find an appropriate toolchain wrapper" - fi --echo "$cc_is_gcc" -- --# --# Only build musl-gcc wrapper if toolchain does not already target musl --# --if test "$wrapper" = auto ; then --printf "checking whether to build musl-gcc wrapper... " --if test "$cc_is_gcc" = yes ; then --wrapper=yes --while read line ; do --case "$line" in */ld-musl-*) wrapper=no ;; esac --done <<EOF --$($CC -dumpspecs) --EOF --else --wrapper=no - fi --echo "$wrapper" - fi - -- -+if test "$gcc_wrapper" = yes ; then -+tools="$tools tools/musl-gcc" -+tool_libs="$tool_libs lib/musl-gcc.specs" -+fi -+if test "$clang_wrapper" = yes ; then -+tools="$tools tools/musl-clang tools/ld.musl-clang" -+fi - - # - # Find the target architecture -@@ -580,11 +604,13 @@ LDFLAGS = $LDFLAGS_AUTO $LDFLAGS - CROSS_COMPILE = $CROSS_COMPILE - LIBCC = $LIBCC - OPTIMIZE_GLOBS = $OPTIMIZE_GLOBS -+ALL_TOOLS = $tools -+TOOL_LIBS = $tool_libs - EOF - test "x$static" = xno && echo "STATIC_LIBS =" - test "x$shared" = xno && echo "SHARED_LIBS =" --test "x$wrapper" = xno && echo "ALL_TOOLS =" --test "x$wrapper" = xno && echo "TOOL_LIBS =" -+test "x$cc_family" = xgcc && echo 'WRAPCC_GCC = $(CC)' -+test "x$cc_family" = xclang && echo 'WRAPCC_CLANG = $(CC)' - exec 1>&3 3>&- - - printf "done\n" ---- a/include/ctype.h -+++ b/include/ctype.h -@@ -64,6 +64,7 @@ int isascii(int); - int toascii(int); - #define _tolower(a) ((a)|0x20) - #define _toupper(a) ((a)&0x5f) -+#define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128) - - #endif - ---- a/include/stdlib.h -+++ b/include/stdlib.h -@@ -76,7 +76,8 @@ size_t wcstombs (char *__restrict, const - #define EXIT_FAILURE 1 - #define EXIT_SUCCESS 0 - --#define MB_CUR_MAX ((size_t)+4) -+size_t __ctype_get_mb_cur_max(void); -+#define MB_CUR_MAX (__ctype_get_mb_cur_max()) - - #define RAND_MAX (0x7fffffff) - ---- a/include/sys/socket.h -+++ b/include/sys/socket.h -@@ -177,8 +177,11 @@ struct linger - #define SO_SNDLOWAT 19 - #define SO_RCVTIMEO 20 - #define SO_SNDTIMEO 21 -+#define SO_ACCEPTCONN 30 - #define SO_SNDBUFFORCE 32 - #define SO_RCVBUFFORCE 33 -+#define SO_PROTOCOL 38 -+#define SO_DOMAIN 39 - #endif - - #define SO_SECURITY_AUTHENTICATION 22 -@@ -195,7 +198,6 @@ struct linger - #define SO_TIMESTAMP 29 - #define SCM_TIMESTAMP SO_TIMESTAMP - --#define SO_ACCEPTCONN 30 - #define SO_PEERSEC 31 - #define SO_PASSSEC 34 - #define SO_TIMESTAMPNS 35 -@@ -203,8 +205,6 @@ struct linger - #define SO_MARK 36 - #define SO_TIMESTAMPING 37 - #define SCM_TIMESTAMPING SO_TIMESTAMPING --#define SO_PROTOCOL 38 --#define SO_DOMAIN 39 - #define SO_RXQ_OVFL 40 - #define SO_WIFI_STATUS 41 - #define SCM_WIFI_STATUS SO_WIFI_STATUS ---- a/include/unistd.h -+++ b/include/unistd.h -@@ -185,7 +185,7 @@ int setresgid(gid_t, gid_t, gid_t); - int getresuid(uid_t *, uid_t *, uid_t *); - int getresgid(gid_t *, gid_t *, gid_t *); - char *get_current_dir_name(void); --void syncfs(int); -+int syncfs(int); - int euidaccess(const char *, int); - int eaccess(const char *, int); - #endif ---- a/src/ctype/__ctype_get_mb_cur_max.c -+++ b/src/ctype/__ctype_get_mb_cur_max.c -@@ -1,6 +1,7 @@ --#include <stddef.h> -+#include <stdlib.h> -+#include "locale_impl.h" - - size_t __ctype_get_mb_cur_max() - { -- return 4; -+ return MB_CUR_MAX; - } ---- a/src/ctype/isascii.c -+++ b/src/ctype/isascii.c -@@ -1,4 +1,5 @@ - #include <ctype.h> -+#undef isascii - - int isascii(int c) - { ---- a/src/env/__stack_chk_fail.c -+++ b/src/env/__stack_chk_fail.c -@@ -25,4 +25,8 @@ void __stack_chk_fail_local(void) - a_crash(); - } - -+#else -+ -+weak_alias(__stack_chk_fail, __stack_chk_fail_local); -+ - #endif ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -17,8 +17,6 @@ struct __libc { - int secure; - volatile int threads_minus_1; - size_t *auxv; -- FILE *ofl_head; -- volatile int ofl_lock[2]; - size_t tls_size; - size_t page_size; - struct __locale_struct global_locale; ---- a/src/internal/locale_impl.h -+++ b/src/internal/locale_impl.h -@@ -1,3 +1,6 @@ -+#ifndef _LOCALE_IMPL_H -+#define _LOCALE_IMPL_H -+ - #include <locale.h> - #include <stdlib.h> - #include "libc.h" -@@ -12,6 +15,10 @@ struct __locale_map { - const struct __locale_map *next; - }; - -+extern const struct __locale_map __c_dot_utf8; -+extern const struct __locale_struct __c_locale; -+extern const struct __locale_struct __c_dot_utf8_locale; -+ - const struct __locale_map *__get_locale(int, const char *); - const char *__mo_lookup(const void *, size_t, const char *); - const char *__lctrans(const char *, const struct __locale_map *); -@@ -20,9 +27,14 @@ const char *__lctrans_cur(const char *); - #define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)]) - #define LCTRANS_CUR(msg) __lctrans_cur(msg) - -+#define C_LOCALE ((locale_t)&__c_locale) -+#define UTF8_LOCALE ((locale_t)&__c_dot_utf8_locale) -+ - #define CURRENT_LOCALE (__pthread_self()->locale) - - #define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE]) - - #undef MB_CUR_MAX - #define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1) -+ -+#endif ---- a/src/internal/pthread_impl.h -+++ b/src/internal/pthread_impl.h -@@ -94,6 +94,10 @@ struct __timer { - #define CANARY canary - #endif - -+#ifndef DTP_OFFSET -+#define DTP_OFFSET 0 -+#endif -+ - #define SIGTIMER 32 - #define SIGCANCEL 33 - #define SIGSYNCCALL 34 ---- a/src/internal/sh/syscall.s -+++ b/src/internal/sh/syscall.s -@@ -13,7 +13,7 @@ __syscall: - mov.l @r15, r7 - mov.l @(4,r15), r0 - mov.l @(8,r15), r1 -- trapa #22 -+ trapa #31 - or r0, r0 - or r0, r0 - or r0, r0 ---- a/src/internal/stdio_impl.h -+++ b/src/internal/stdio_impl.h -@@ -47,6 +47,7 @@ struct _IO_FILE { - unsigned char *shend; - off_t shlim, shcnt; - FILE *prev_locked, *next_locked; -+ struct __locale_struct *locale; - }; - - size_t __stdio_read(FILE *, unsigned char *, size_t); -@@ -75,8 +76,9 @@ int __putc_unlocked(int, FILE *); - FILE *__fdopen(int, const char *); - int __fmodeflags(const char *); - --#define OFLLOCK() LOCK(libc.ofl_lock) --#define OFLUNLOCK() UNLOCK(libc.ofl_lock) -+FILE *__ofl_add(FILE *f); -+FILE **__ofl_lock(void); -+void __ofl_unlock(void); - - #define feof(f) ((f)->flags & F_EOF) - #define ferror(f) ((f)->flags & F_ERR) ---- a/src/ldso/dynlink.c -+++ b/src/ldso/dynlink.c -@@ -156,7 +156,7 @@ static uint32_t gnu_hash(const char *s0) - const unsigned char *s = (void *)s0; - uint_fast32_t h = 5381; - for (; *s; s++) -- h = h*33 + *s; -+ h += h*32 + *s; - return h; - } - -@@ -174,32 +174,39 @@ static Sym *sysv_lookup(const char *s, u - return 0; - } - --static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso) -+static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s) - { -- Sym *syms = dso->syms; -- char *strings = dso->strings; -- uint32_t *hashtab = dso->ghashtab; - uint32_t nbuckets = hashtab[0]; - uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4); -- uint32_t h2; -- uint32_t *hashval; - uint32_t i = buckets[h1 % nbuckets]; - - if (!i) return 0; - -- hashval = buckets + nbuckets + (i - hashtab[1]); -+ uint32_t *hashval = buckets + nbuckets + (i - hashtab[1]); - - for (h1 |= 1; ; i++) { -- h2 = *hashval++; -- if ((!dso->versym || dso->versym[i] >= 0) -- && (h1 == (h2|1)) && !strcmp(s, strings + syms[i].st_name)) -- return syms+i; -+ uint32_t h2 = *hashval++; -+ if ((h1 == (h2|1)) && (!dso->versym || dso->versym[i] >= 0) -+ && !strcmp(s, dso->strings + dso->syms[i].st_name)) -+ return dso->syms+i; - if (h2 & 1) break; - } - - return 0; - } - -+static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s, uint32_t fofs, size_t fmask) -+{ -+ const size_t *bloomwords = (const void *)(hashtab+4); -+ size_t f = bloomwords[fofs & (hashtab[2]-1)]; -+ if (!(f & fmask)) return 0; -+ -+ f >>= (h1 >> hashtab[3]) % (8 * sizeof f); -+ if (!(f & 1)) return 0; -+ -+ return gnu_lookup(h1, hashtab, dso, s); -+} -+ - #define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS) - #define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE) - -@@ -209,14 +216,20 @@ static Sym *gnu_lookup(const char *s, ui - - static struct symdef find_sym(struct dso *dso, const char *s, int need_def) - { -- uint32_t h = 0, gh = 0; -+ uint32_t h = 0, gh, gho, *ght; -+ size_t ghm = 0; - struct symdef def = {0}; - for (; dso; dso=dso->next) { - Sym *sym; - if (!dso->global) continue; -- if (dso->ghashtab) { -- if (!gh) gh = gnu_hash(s); -- sym = gnu_lookup(s, gh, dso); -+ if ((ght = dso->ghashtab)) { -+ if (!ghm) { -+ gh = gnu_hash(s); -+ int maskbits = 8 * sizeof ghm; -+ gho = gh / maskbits; -+ ghm = 1ul << gh % maskbits; -+ } -+ sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm); - } else { - if (!h) h = sysv_hash(s); - sym = sysv_lookup(s, h, dso); -@@ -337,7 +350,7 @@ static void do_relocs(struct dso *dso, s - *reloc_addr = def.dso->tls_id; - break; - case REL_DTPOFF: -- *reloc_addr = tls_val + addend; -+ *reloc_addr = tls_val + addend - DTP_OFFSET; - break; - #ifdef TLS_ABOVE_TP - case REL_TPOFF: -@@ -423,6 +436,28 @@ static void reclaim_gaps(struct dso *dso - } - } - -+static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off) -+{ -+ char *q = mmap(p, n, prot, flags, fd, off); -+ if (q != MAP_FAILED || errno != EINVAL) return q; -+ /* Fallbacks for MAP_FIXED failure on NOMMU kernels. */ -+ if (flags & MAP_ANONYMOUS) { -+ memset(p, 0, n); -+ return p; -+ } -+ ssize_t r; -+ if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED; -+ for (q=p; n; q+=r, off+=r, n-=r) { -+ r = read(fd, q, n); -+ if (r < 0 && errno != EINTR) return MAP_FAILED; -+ if (!r) { -+ memset(q, 0, n); -+ break; -+ } -+ } -+ return p; -+} -+ - static void *map_library(int fd, struct dso *dso) - { - Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)]; -@@ -524,19 +559,20 @@ static void *map_library(int fd, struct - prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) | - ((ph->p_flags&PF_W) ? PROT_WRITE: 0) | - ((ph->p_flags&PF_X) ? PROT_EXEC : 0)); -- if (mmap(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) -+ if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED) - goto error; - if (ph->p_memsz > ph->p_filesz) { - size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz; - size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE; - memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1); -- if (pgbrk-(size_t)base < this_max && mmap((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) -+ if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, (size_t)base+this_max-pgbrk, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) - goto error; - } - } - for (i=0; ((size_t *)(base+dyn))[i]; i+=2) - if (((size_t *)(base+dyn))[i]==DT_TEXTREL) { -- if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC) < 0) -+ if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC) -+ && errno != ENOSYS) - goto error; - break; - } -@@ -927,7 +963,8 @@ static void reloc_all(struct dso *p) - do_relocs(p, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ], 3); - - if (head != &ldso && p->relro_start != p->relro_end && -- mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) < 0) { -+ mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) -+ && errno != ENOSYS) { - error("Error relocating %s: RELRO protection failed: %m", - p->name); - if (runtime) longjmp(*rtld_fail, 1); -@@ -1078,7 +1115,7 @@ void *__tls_get_new(size_t *v) - __block_all_sigs(&set); - if (v[0]<=(size_t)self->dtv[0]) { - __restore_sigs(&set); -- return (char *)self->dtv[v[0]]+v[1]; -+ return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET; - } - - /* This is safe without any locks held because, if the caller -@@ -1111,7 +1148,7 @@ void *__tls_get_new(size_t *v) - if (p->tls_id == v[0]) break; - } - __restore_sigs(&set); -- return mem + v[1]; -+ return mem + v[1] + DTP_OFFSET; - } - - static void update_tls_size() -@@ -1192,6 +1229,17 @@ _Noreturn void __dls3(size_t *sp) - char **argv_orig = argv; - char **envp = argv+argc+1; - -+ /* Find aux vector just past environ[] and use it to initialize -+ * global data that may be needed before we can make syscalls. */ -+ __environ = envp; -+ for (i=argc+1; argv[i]; i++); -+ libc.auxv = auxv = (void *)(argv+i+1); -+ decode_vec(auxv, aux, AUX_CNT); -+ __hwcap = aux[AT_HWCAP]; -+ libc.page_size = aux[AT_PAGESZ]; -+ libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID] -+ || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]); -+ - /* Setup early thread pointer in builtin_tls for ldso/libc itself to - * use during dynamic linking. If possible it will also serve as the - * thread pointer at runtime. */ -@@ -1200,25 +1248,11 @@ _Noreturn void __dls3(size_t *sp) - a_crash(); - } - -- /* Find aux vector just past environ[] */ -- for (i=argc+1; argv[i]; i++) -- if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16)) -- env_path = argv[i]+16; -- else if (!memcmp(argv[i], "LD_PRELOAD=", 11)) -- env_preload = argv[i]+11; -- auxv = (void *)(argv+i+1); -- -- decode_vec(auxv, aux, AUX_CNT); -- - /* Only trust user/env if kernel says we're not suid/sgid */ -- if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID] -- || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]) { -- env_path = 0; -- env_preload = 0; -- libc.secure = 1; -+ if (!libc.secure) { -+ env_path = getenv("LD_LIBRARY_PATH"); -+ env_preload = getenv("LD_PRELOAD"); - } -- libc.page_size = aux[AT_PAGESZ]; -- libc.auxv = auxv; - - /* If the main program was already loaded by the kernel, - * AT_PHDR will point to some location other than the dynamic -@@ -1523,7 +1557,7 @@ void *__tls_get_addr(size_t *); - static void *do_dlsym(struct dso *p, const char *s, void *ra) - { - size_t i; -- uint32_t h = 0, gh = 0; -+ uint32_t h = 0, gh = 0, *ght; - Sym *sym; - if (p == head || p == RTLD_DEFAULT || p == RTLD_NEXT) { - if (p == RTLD_DEFAULT) { -@@ -1541,9 +1575,9 @@ static void *do_dlsym(struct dso *p, con - } - if (invalid_dso_handle(p)) - return 0; -- if (p->ghashtab) { -+ if ((ght = p->ghashtab)) { - gh = gnu_hash(s); -- sym = gnu_lookup(s, gh, p); -+ sym = gnu_lookup(gh, ght, p, s); - } else { - h = sysv_hash(s); - sym = sysv_lookup(s, h, p); -@@ -1553,9 +1587,9 @@ static void *do_dlsym(struct dso *p, con - if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) - return p->base + sym->st_value; - if (p->deps) for (i=0; p->deps[i]; i++) { -- if (p->deps[i]->ghashtab) { -+ if ((ght = p->deps[i]->ghashtab)) { - if (!gh) gh = gnu_hash(s); -- sym = gnu_lookup(s, gh, p->deps[i]); -+ sym = gnu_lookup(gh, ght, p->deps[i], s); - } else { - if (!h) h = sysv_hash(s); - sym = sysv_lookup(s, h, p->deps[i]); ---- a/src/linux/syncfs.c -+++ b/src/linux/syncfs.c -@@ -2,7 +2,7 @@ - #include <unistd.h> - #include "syscall.h" - --void syncfs(int fd) -+int syncfs(int fd) - { -- __syscall(SYS_syncfs, fd); -+ return syscall(SYS_syncfs, fd); - } ---- /dev/null -+++ b/src/locale/c_locale.c -@@ -0,0 +1,15 @@ -+#include "locale_impl.h" -+#include <stdint.h> -+ -+static const uint32_t empty_mo[] = { 0x950412de, 0, -1, -1, -1 }; -+ -+const struct __locale_map __c_dot_utf8 = { -+ .map = empty_mo, -+ .map_size = sizeof empty_mo, -+ .name = "C.UTF-8" -+}; -+ -+const struct __locale_struct __c_locale = { 0 }; -+const struct __locale_struct __c_dot_utf8_locale = { -+ .cat[LC_CTYPE] = &__c_dot_utf8 -+}; ---- a/src/locale/iconv.c -+++ b/src/locale/iconv.c -@@ -5,6 +5,7 @@ - #include <stdlib.h> - #include <limits.h> - #include <stdint.h> -+#include "locale_impl.h" - - #define UTF_32BE 0300 - #define UTF_16LE 0301 -@@ -165,9 +166,12 @@ size_t iconv(iconv_t cd0, char **restric - int err; - unsigned char type = map[-1]; - unsigned char totype = tomap[-1]; -+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; - - if (!in || !*in || !*inb) return 0; - -+ *ploc = UTF8_LOCALE; -+ - for (; *inb; *in+=l, *inb-=l) { - c = *(unsigned char *)*in; - l = 1; -@@ -431,6 +435,7 @@ size_t iconv(iconv_t cd0, char **restric - break; - } - } -+ *ploc = loc; - return x; - ilseq: - err = EILSEQ; -@@ -445,5 +450,6 @@ starved: - x = -1; - end: - errno = err; -+ *ploc = loc; - return x; - } ---- a/src/locale/langinfo.c -+++ b/src/locale/langinfo.c -@@ -33,7 +33,8 @@ char *__nl_langinfo_l(nl_item item, loca - int idx = item & 65535; - const char *str; - -- if (item == CODESET) return "UTF-8"; -+ if (item == CODESET) -+ return MB_CUR_MAX==1 ? "UTF-8-CODE-UNITS" : "UTF-8"; - - switch (cat) { - case LC_NUMERIC: ---- a/src/locale/locale_map.c -+++ b/src/locale/locale_map.c -@@ -24,14 +24,6 @@ static const char envvars[][12] = { - "LC_MESSAGES", - }; - --static const uint32_t empty_mo[] = { 0x950412de, 0, -1, -1, -1 }; -- --const struct __locale_map __c_dot_utf8 = { -- .map = empty_mo, -- .map_size = sizeof empty_mo, -- .name = "C.UTF-8" --}; -- - const struct __locale_map *__get_locale(int cat, const char *val) - { - static int lock[2]; -@@ -107,8 +99,8 @@ const struct __locale_map *__get_locale( - * sake of being able to do message translations at the - * application level. */ - if (!new && (new = malloc(sizeof *new))) { -- new->map = empty_mo; -- new->map_size = sizeof empty_mo; -+ new->map = __c_dot_utf8.map; -+ new->map_size = __c_dot_utf8.map_size; - memcpy(new->name, val, n); - new->name[n] = 0; - new->next = loc_head; ---- a/src/locale/newlocale.c -+++ b/src/locale/newlocale.c -@@ -3,16 +3,9 @@ - #include "locale_impl.h" - #include "libc.h" - --extern const struct __locale_map __c_dot_utf8; -- --static const struct __locale_struct c_locale = { 0 }; --static const struct __locale_struct c_dot_utf8_locale = { -- .cat[LC_CTYPE] = &__c_dot_utf8 --}; -- - int __loc_is_allocated(locale_t loc) - { -- return loc && loc != &c_locale && loc != &c_dot_utf8_locale; -+ return loc && loc != C_LOCALE && loc != UTF8_LOCALE; - } - - locale_t __newlocale(int mask, const char *name, locale_t loc) -@@ -44,9 +37,9 @@ locale_t __newlocale(int mask, const cha - } - - if (!j) -- return (locale_t)&c_locale; -- if (j==1 && tmp.cat[LC_CTYPE]==c_dot_utf8_locale.cat[LC_CTYPE]) -- return (locale_t)&c_dot_utf8_locale; -+ return C_LOCALE; -+ if (j==1 && tmp.cat[LC_CTYPE]==&__c_dot_utf8) -+ return UTF8_LOCALE; - - if ((loc = malloc(sizeof *loc))) *loc = tmp; - ---- a/src/locale/uselocale.c -+++ b/src/locale/uselocale.c -@@ -8,9 +8,7 @@ locale_t __uselocale(locale_t new) - locale_t old = self->locale; - locale_t global = &libc.global_locale; - -- if (new == LC_GLOBAL_LOCALE) new = global; -- -- self->locale = new; -+ if (new) self->locale = new == LC_GLOBAL_LOCALE ? global : new; - - return old == global ? LC_GLOBAL_LOCALE : old; - } ---- a/src/malloc/calloc.c -+++ b/src/malloc/calloc.c -@@ -1,22 +1,13 @@ - #include <stdlib.h> - #include <errno.h> - -+void *__malloc0(size_t); -+ - void *calloc(size_t m, size_t n) - { -- void *p; -- size_t *z; - if (n && m > (size_t)-1/n) { - errno = ENOMEM; - return 0; - } -- n *= m; -- p = malloc(n); -- if (!p) return 0; -- /* Only do this for non-mmapped chunks */ -- if (((size_t *)p)[-1] & 7) { -- /* Only write words that are not already zero */ -- m = (n + sizeof *z - 1)/sizeof *z; -- for (z=p; m; m--, z++) if (*z) *z=0; -- } -- return p; -+ return __malloc0(n * m); - } ---- /dev/null -+++ b/src/malloc/expand_heap.c -@@ -0,0 +1,72 @@ -+#include <limits.h> -+#include <stdint.h> -+#include <errno.h> -+#include <sys/mman.h> -+#include "libc.h" -+#include "syscall.h" -+ -+/* 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; -+} -+ -+void *__mmap(void *, size_t, int, int, int, off_t); -+ -+/* 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. */ -+ -+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; -+} ---- a/src/malloc/lite_malloc.c -+++ b/src/malloc/lite_malloc.c -@@ -4,43 +4,47 @@ - #include <errno.h> - #include "libc.h" - --uintptr_t __brk(uintptr_t); -- - #define ALIGN 16 - -+void *__expand_heap(size_t *); -+ - void *__simple_malloc(size_t n) - { -- static uintptr_t cur, brk; -- uintptr_t base, new; -+ static char *cur, *end; - static volatile int lock[2]; -- size_t align=1; -+ size_t align=1, pad; -+ void *p; - - if (!n) n++; -- if (n > SIZE_MAX/2) goto toobig; -- - while (align<n && align<ALIGN) - align += align; -- n = n + align - 1 & -align; - - LOCK(lock); -- if (!cur) cur = brk = __brk(0)+16; -- base = cur + align-1 & -align; -- if (n > SIZE_MAX - PAGE_SIZE - base) goto fail; -- if (base+n > brk) { -- new = base+n + PAGE_SIZE-1 & -PAGE_SIZE; -- if (__brk(new) != new) goto fail; -- brk = new; -- } -- cur = base+n; -- UNLOCK(lock); - -- return (void *)base; -+ pad = -(uintptr_t)cur & align-1; -+ -+ if (n <= SIZE_MAX/2 + ALIGN) n += pad; -+ -+ if (n > end-cur) { -+ size_t m = n; -+ char *new = __expand_heap(&m); -+ if (!new) { -+ UNLOCK(lock); -+ return 0; -+ } -+ if (new != end) { -+ cur = new; -+ n -= pad; -+ pad = 0; -+ } -+ end = new + m; -+ } - --fail: -+ p = cur + pad; -+ cur += n; - UNLOCK(lock); --toobig: -- errno = ENOMEM; -- return 0; -+ return p; - } - - weak_alias(__simple_malloc, malloc); -+weak_alias(__simple_malloc, __malloc0); ---- a/src/malloc/malloc.c -+++ b/src/malloc/malloc.c -@@ -13,7 +13,6 @@ - #define inline inline __attribute__((always_inline)) - #endif - --uintptr_t __brk(uintptr_t); - void *__mmap(void *, size_t, int, int, int, off_t); - int __munmap(void *, size_t); - void *__mremap(void *, size_t, size_t, int, ...); -@@ -31,13 +30,9 @@ struct bin { - }; - - static struct { -- uintptr_t brk; -- size_t *heap; - volatile uint64_t binmap; - struct bin bins[64]; -- volatile int brk_lock[2]; - volatile int free_lock[2]; -- unsigned mmap_step; - } mal; - - -@@ -152,69 +147,52 @@ void __dump_heap(int x) - } - #endif - -+void *__expand_heap(size_t *); -+ - static struct chunk *expand_heap(size_t n) - { -- static int init; -+ static int heap_lock[2]; -+ static void *end; -+ void *p; - struct chunk *w; -- uintptr_t new; -- -- lock(mal.brk_lock); -- -- if (!init) { -- mal.brk = __brk(0); --#ifdef SHARED -- mal.brk = mal.brk + PAGE_SIZE-1 & -PAGE_SIZE; --#endif -- mal.brk = mal.brk + 2*SIZE_ALIGN-1 & -SIZE_ALIGN; -- mal.heap = (void *)mal.brk; -- init = 1; -- } -- -- if (n > SIZE_MAX - mal.brk - 2*PAGE_SIZE) goto fail; -- new = mal.brk + n + SIZE_ALIGN + PAGE_SIZE - 1 & -PAGE_SIZE; -- n = new - mal.brk; -- -- if (__brk(new) != new) { -- size_t min = (size_t)PAGE_SIZE << mal.mmap_step/2; -- n += -n & PAGE_SIZE-1; -- if (n < min) n = min; -- void *area = __mmap(0, n, PROT_READ|PROT_WRITE, -- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); -- if (area == MAP_FAILED) goto fail; - -- mal.mmap_step++; -- area = (char *)area + SIZE_ALIGN - OVERHEAD; -- w = area; -+ /* 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; -+ -+ lock(heap_lock); -+ -+ p = __expand_heap(&n); -+ if (!p) { -+ unlock(heap_lock); -+ 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; -- w->csize = n | C_INUSE; -- w = NEXT_CHUNK(w); -- w->psize = n | C_INUSE; -- w->csize = 0 | C_INUSE; -- -- unlock(mal.brk_lock); -- -- return area; - } - -- w = MEM_TO_CHUNK(mal.heap); -- w->psize = 0 | C_INUSE; -- -- w = MEM_TO_CHUNK(new); -+ /* 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; - -- w = MEM_TO_CHUNK(mal.brk); -+ /* 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; -- mal.brk = new; -- -- unlock(mal.brk_lock); -+ -+ unlock(heap_lock); - - return w; --fail: -- unlock(mal.brk_lock); -- errno = ENOMEM; -- return 0; - } - - static int adjust_size(size_t *n) -@@ -378,6 +356,17 @@ void *malloc(size_t n) - return CHUNK_TO_MEM(c); - } - -+void *__malloc0(size_t n) -+{ -+ void *p = malloc(n); -+ if (p && !IS_MMAPPED(MEM_TO_CHUNK(p))) { -+ size_t *z; -+ n = (n + sizeof *z - 1)/sizeof *z; -+ for (z=p; n; n--, z++) if (*z) *z=0; -+ } -+ return p; -+} -+ - void *realloc(void *p, size_t n) - { - struct chunk *self, *next; ---- a/src/misc/syslog.c -+++ b/src/misc/syslog.c -@@ -48,12 +48,8 @@ void closelog(void) - - static void __openlog() - { -- int fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); -- if (fd < 0) return; -- if (connect(fd, (void *)&log_addr, sizeof log_addr) < 0) -- close(fd); -- else -- log_fd = fd; -+ log_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); -+ if (log_fd >= 0) connect(log_fd, (void *)&log_addr, sizeof log_addr); - } - - void openlog(const char *ident, int opt, int facility) -@@ -78,6 +74,11 @@ void openlog(const char *ident, int opt, - pthread_setcancelstate(cs, 0); - } - -+static int is_lost_conn(int e) -+{ -+ return e==ECONNREFUSED || e==ECONNRESET || e==ENOTCONN || e==EPIPE; -+} -+ - static void _vsyslog(int priority, const char *message, va_list ap) - { - char timebuf[16]; -@@ -107,7 +108,10 @@ static void _vsyslog(int priority, const - if (l2 >= sizeof buf - l) l = sizeof buf - 1; - else l += l2; - if (buf[l-1] != '\n') buf[l++] = '\n'; -- if (send(log_fd, buf, l, 0) < 0 && (log_opt & LOG_CONS)) { -+ if (send(log_fd, buf, l, 0) < 0 && (!is_lost_conn(errno) -+ || connect(log_fd, (void *)&log_addr, sizeof log_addr) < 0 -+ || send(log_fd, buf, l, 0) < 0) -+ && (log_opt & LOG_CONS)) { - fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); - if (fd >= 0) { - dprintf(fd, "%.*s", l-hlen, buf+hlen); ---- a/src/multibyte/btowc.c -+++ b/src/multibyte/btowc.c -@@ -1,7 +1,10 @@ - #include <stdio.h> - #include <wchar.h> -+#include <stdlib.h> -+#include "internal.h" - - wint_t btowc(int c) - { -- return c<128U ? c : EOF; -+ int b = (unsigned char)c; -+ return b<128U ? b : (MB_CUR_MAX==1 && c!=EOF) ? CODEUNIT(c) : WEOF; - } ---- a/src/multibyte/internal.h -+++ b/src/multibyte/internal.h -@@ -23,3 +23,10 @@ extern const uint32_t bittab[]; - - #define SA 0xc2u - #define SB 0xf4u -+ -+/* Arbitrary encoding for representing code units instead of characters. */ -+#define CODEUNIT(c) (0xdfff & (signed char)(c)) -+#define IS_CODEUNIT(c) ((unsigned)(c)-0xdf80 < 0x80) -+ -+/* Get inline definition of MB_CUR_MAX. */ -+#include "locale_impl.h" ---- a/src/multibyte/mbrtowc.c -+++ b/src/multibyte/mbrtowc.c -@@ -4,6 +4,7 @@ - * unnecessary. - */ - -+#include <stdlib.h> - #include <wchar.h> - #include <errno.h> - #include "internal.h" -@@ -27,6 +28,7 @@ size_t mbrtowc(wchar_t *restrict wc, con - if (!n) return -2; - if (!c) { - if (*s < 0x80) return !!(*wc = *s); -+ if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; - if (*s-SA > SB-SA) goto ilseq; - c = bittab[*s++-SA]; n--; - } ---- a/src/multibyte/mbsrtowcs.c -+++ b/src/multibyte/mbsrtowcs.c -@@ -7,6 +7,8 @@ - #include <stdint.h> - #include <wchar.h> - #include <errno.h> -+#include <string.h> -+#include <stdlib.h> - #include "internal.h" - - size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st) -@@ -24,6 +26,23 @@ size_t mbsrtowcs(wchar_t *restrict ws, c - } - } - -+ if (MB_CUR_MAX==1) { -+ if (!ws) return strlen((const char *)s); -+ for (;;) { -+ if (!wn) { -+ *src = (const void *)s; -+ return wn0; -+ } -+ if (!*s) break; -+ c = *s++; -+ *ws++ = CODEUNIT(c); -+ wn--; -+ } -+ *ws = 0; -+ *src = 0; -+ return wn0-wn; -+ } -+ - if (!ws) for (;;) { - if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { - while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { ---- a/src/multibyte/mbtowc.c -+++ b/src/multibyte/mbtowc.c -@@ -4,6 +4,7 @@ - * unnecessary. - */ - -+#include <stdlib.h> - #include <wchar.h> - #include <errno.h> - #include "internal.h" -@@ -19,6 +20,7 @@ int mbtowc(wchar_t *restrict wc, const c - if (!wc) wc = &dummy; - - if (*s < 0x80) return !!(*wc = *s); -+ if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; - if (*s-SA > SB-SA) goto ilseq; - c = bittab[*s++-SA]; - ---- a/src/multibyte/wcrtomb.c -+++ b/src/multibyte/wcrtomb.c -@@ -4,8 +4,10 @@ - * unnecessary. - */ - -+#include <stdlib.h> - #include <wchar.h> - #include <errno.h> -+#include "internal.h" - - size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st) - { -@@ -13,6 +15,13 @@ size_t wcrtomb(char *restrict s, wchar_t - if ((unsigned)wc < 0x80) { - *s = wc; - return 1; -+ } else if (MB_CUR_MAX == 1) { -+ if (!IS_CODEUNIT(wc)) { -+ errno = EILSEQ; -+ return -1; -+ } -+ *s = wc; -+ return 1; - } else if ((unsigned)wc < 0x800) { - *s++ = 0xc0 | (wc>>6); - *s = 0x80 | (wc&0x3f); ---- a/src/multibyte/wctob.c -+++ b/src/multibyte/wctob.c -@@ -1,8 +1,10 @@ --#include <stdio.h> - #include <wchar.h> -+#include <stdlib.h> -+#include "internal.h" - - int wctob(wint_t c) - { - if (c < 128U) return c; -+ if (MB_CUR_MAX==1 && IS_CODEUNIT(c)) return (unsigned char)c; - return EOF; - } ---- a/src/network/ns_parse.c -+++ b/src/network/ns_parse.c -@@ -95,7 +95,7 @@ int ns_skiprr(const unsigned char *ptr, - p += r; - } - } -- return ptr - p; -+ return p - ptr; - bad: - errno = EMSGSIZE; - return -1; ---- a/src/passwd/nscd_query.c -+++ b/src/passwd/nscd_query.c -@@ -32,6 +32,7 @@ FILE *__nscd_query(int32_t req, const ch - }, - .msg_iovlen = 2 - }; -+ int errno_save = errno; - - *swap = 0; - retry: -@@ -50,11 +51,14 @@ retry: - return f; - - if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { -- /* If there isn't a running nscd we return -1 to indicate that -- * that is precisely what happened -- */ -- if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) -+ /* If there isn't a running nscd we simulate a "not found" -+ * result and the caller is responsible for calling -+ * fclose on the (unconnected) socket. The value of -+ * errno must be left unchanged in this case. */ -+ if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) { -+ errno = errno_save; - return f; -+ } - goto error; - } - ---- /dev/null -+++ b/src/process/sh/vfork.s -@@ -0,0 +1,23 @@ -+.global __vfork -+.weak vfork -+.type __vfork,@function -+.type vfork,@function -+__vfork: -+vfork: -+ mov #95, r3 -+ add r3, r3 -+ -+ trapa #31 -+ or r0, r0 -+ or r0, r0 -+ or r0, r0 -+ or r0, r0 -+ or r0, r0 -+ -+ mov r0, r4 -+ mov.l 1f, r0 -+2: braf r0 -+ nop -+ .align 2 -+ .hidden __syscall_ret -+1: .long __syscall_ret@PLT-(2b+4-.) ---- a/src/regex/fnmatch.c -+++ b/src/regex/fnmatch.c -@@ -18,6 +18,7 @@ - #include <stdlib.h> - #include <wchar.h> - #include <wctype.h> -+#include "locale_impl.h" - - #define END 0 - #define UNMATCHABLE -2 -@@ -229,7 +230,7 @@ static int fnmatch_internal(const char * - * On illegal sequences we may get it wrong, but in that case - * we necessarily have a matching failure anyway. */ - for (s=endstr; s>str && tailcnt; tailcnt--) { -- if (s[-1] < 128U) s--; -+ if (s[-1] < 128U || MB_CUR_MAX==1) s--; - else while ((unsigned char)*--s-0x80U<0x40 && s>str); - } - if (tailcnt) return FNM_NOMATCH; ---- a/src/signal/sh/restore.s -+++ b/src/signal/sh/restore.s -@@ -2,7 +2,7 @@ - .type __restore, @function - __restore: - mov #119, r3 !__NR_sigreturn -- trapa #16 -+ trapa #31 - - or r0, r0 - or r0, r0 -@@ -15,7 +15,7 @@ __restore: - __restore_rt: - mov #100, r3 !__NR_rt_sigreturn - add #73, r3 -- trapa #16 -+ trapa #31 - - or r0, r0 - or r0, r0 ---- a/src/stdio/__fdopen.c -+++ b/src/stdio/__fdopen.c -@@ -54,13 +54,7 @@ FILE *__fdopen(int fd, const char *mode) - if (!libc.threaded) f->lock = -1; - - /* Add new FILE to open file list */ -- OFLLOCK(); -- f->next = libc.ofl_head; -- if (libc.ofl_head) libc.ofl_head->prev = f; -- libc.ofl_head = f; -- OFLUNLOCK(); -- -- return f; -+ return __ofl_add(f); - } - - weak_alias(__fdopen, fdopen); ---- a/src/stdio/__stdio_exit.c -+++ b/src/stdio/__stdio_exit.c -@@ -16,8 +16,7 @@ static void close_file(FILE *f) - void __stdio_exit(void) - { - FILE *f; -- OFLLOCK(); -- for (f=libc.ofl_head; f; f=f->next) close_file(f); -+ for (f=*__ofl_lock(); f; f=f->next) close_file(f); - close_file(__stdin_used); - close_file(__stdout_used); - } ---- a/src/stdio/__stdio_read.c -+++ b/src/stdio/__stdio_read.c -@@ -1,12 +1,5 @@ - #include "stdio_impl.h" - #include <sys/uio.h> --#include <pthread.h> -- --static void cleanup(void *p) --{ -- FILE *f = p; -- if (!f->lockcount) __unlockfile(f); --} - - size_t __stdio_read(FILE *f, unsigned char *buf, size_t len) - { -@@ -16,9 +9,7 @@ size_t __stdio_read(FILE *f, unsigned ch - }; - ssize_t cnt; - -- pthread_cleanup_push(cleanup, f); -- cnt = syscall_cp(SYS_readv, f->fd, iov, 2); -- pthread_cleanup_pop(0); -+ cnt = syscall(SYS_readv, f->fd, iov, 2); - if (cnt <= 0) { - f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt); - return cnt; ---- a/src/stdio/__stdio_write.c -+++ b/src/stdio/__stdio_write.c -@@ -1,12 +1,5 @@ - #include "stdio_impl.h" - #include <sys/uio.h> --#include <pthread.h> -- --static void cleanup(void *p) --{ -- FILE *f = p; -- if (!f->lockcount) __unlockfile(f); --} - - size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len) - { -@@ -19,9 +12,7 @@ size_t __stdio_write(FILE *f, const unsi - int iovcnt = 2; - ssize_t cnt; - for (;;) { -- pthread_cleanup_push(cleanup, f); -- cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt); -- pthread_cleanup_pop(0); -+ cnt = syscall(SYS_writev, f->fd, iov, iovcnt); - if (cnt == rem) { - f->wend = f->buf + f->buf_size; - f->wpos = f->wbase = f->buf; -@@ -34,11 +25,8 @@ size_t __stdio_write(FILE *f, const unsi - } - rem -= cnt; - if (cnt > iov[0].iov_len) { -- f->wpos = f->wbase = f->buf; - cnt -= iov[0].iov_len; - iov++; iovcnt--; -- } else if (iovcnt == 2) { -- f->wbase += cnt; - } - iov[0].iov_base = (char *)iov[0].iov_base + cnt; - iov[0].iov_len -= cnt; ---- a/src/stdio/fclose.c -+++ b/src/stdio/fclose.c -@@ -14,11 +14,11 @@ int fclose(FILE *f) - __unlist_locked_file(f); - - if (!(perm = f->flags & F_PERM)) { -- OFLLOCK(); -+ FILE **head = __ofl_lock(); - if (f->prev) f->prev->next = f->next; - if (f->next) f->next->prev = f->prev; -- if (libc.ofl_head == f) libc.ofl_head = f->next; -- OFLUNLOCK(); -+ if (*head == f) *head = f->next; -+ __ofl_unlock(); - } - - r = fflush(f); ---- a/src/stdio/fflush.c -+++ b/src/stdio/fflush.c -@@ -35,13 +35,12 @@ int fflush(FILE *f) - - r = __stdout_used ? fflush(__stdout_used) : 0; - -- OFLLOCK(); -- for (f=libc.ofl_head; f; f=f->next) { -+ for (f=*__ofl_lock(); f; f=f->next) { - FLOCK(f); - if (f->wpos > f->wbase) r |= __fflush_unlocked(f); - FUNLOCK(f); - } -- OFLUNLOCK(); -+ __ofl_unlock(); - - return r; - } ---- a/src/stdio/fgetwc.c -+++ b/src/stdio/fgetwc.c -@@ -1,8 +1,9 @@ - #include "stdio_impl.h" -+#include "locale_impl.h" - #include <wchar.h> - #include <errno.h> - --wint_t __fgetwc_unlocked(FILE *f) -+static wint_t __fgetwc_unlocked_internal(FILE *f) - { - mbstate_t st = { 0 }; - wchar_t wc; -@@ -10,8 +11,6 @@ wint_t __fgetwc_unlocked(FILE *f) - unsigned char b; - size_t l; - -- f->mode |= f->mode+1; -- - /* Convert character from buffer if possible */ - if (f->rpos < f->rend) { - l = mbrtowc(&wc, (void *)f->rpos, f->rend - f->rpos, &st); -@@ -39,6 +38,16 @@ wint_t __fgetwc_unlocked(FILE *f) - return wc; - } - -+wint_t __fgetwc_unlocked(FILE *f) -+{ -+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; -+ if (f->mode <= 0) fwide(f, 1); -+ *ploc = f->locale; -+ wchar_t wc = __fgetwc_unlocked_internal(f); -+ *ploc = loc; -+ return wc; -+} -+ - wint_t fgetwc(FILE *f) - { - wint_t c; ---- a/src/stdio/fmemopen.c -+++ b/src/stdio/fmemopen.c -@@ -110,11 +110,5 @@ FILE *fmemopen(void *restrict buf, size_ - - if (!libc.threaded) f->lock = -1; - -- OFLLOCK(); -- f->next = libc.ofl_head; -- if (libc.ofl_head) libc.ofl_head->prev = f; -- libc.ofl_head = f; -- OFLUNLOCK(); -- -- return f; -+ return __ofl_add(f); - } ---- a/src/stdio/fopen.c -+++ b/src/stdio/fopen.c -@@ -18,7 +18,7 @@ FILE *fopen(const char *restrict filenam - /* Compute the flags to pass to open() */ - flags = __fmodeflags(mode); - -- fd = sys_open_cp(filename, flags, 0666); -+ fd = sys_open(filename, flags, 0666); - if (fd < 0) return 0; - if (flags & O_CLOEXEC) - __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC); ---- a/src/stdio/fputwc.c -+++ b/src/stdio/fputwc.c -@@ -1,4 +1,5 @@ - #include "stdio_impl.h" -+#include "locale_impl.h" - #include <wchar.h> - #include <limits.h> - #include <ctype.h> -@@ -7,8 +8,10 @@ wint_t __fputwc_unlocked(wchar_t c, FILE - { - char mbc[MB_LEN_MAX]; - int l; -+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; - -- f->mode |= f->mode+1; -+ if (f->mode <= 0) fwide(f, 1); -+ *ploc = f->locale; - - if (isascii(c)) { - c = putc_unlocked(c, f); -@@ -20,6 +23,8 @@ wint_t __fputwc_unlocked(wchar_t c, FILE - l = wctomb(mbc, c); - if (l < 0 || __fwritex((void *)mbc, l, f) < l) c = WEOF; - } -+ if (c==WEOF) f->flags |= F_ERR; -+ *ploc = loc; - return c; - } - ---- a/src/stdio/fputws.c -+++ b/src/stdio/fputws.c -@@ -1,23 +1,28 @@ - #include "stdio_impl.h" -+#include "locale_impl.h" - #include <wchar.h> - - int fputws(const wchar_t *restrict ws, FILE *restrict f) - { - unsigned char buf[BUFSIZ]; - size_t l=0; -+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; - - FLOCK(f); - -- f->mode |= f->mode+1; -+ fwide(f, 1); -+ *ploc = f->locale; - - while (ws && (l = wcsrtombs((void *)buf, (void*)&ws, sizeof buf, 0))+1 > 1) - if (__fwritex(buf, l, f) < l) { - FUNLOCK(f); -+ *ploc = loc; - return -1; - } - - FUNLOCK(f); - -+ *ploc = loc; - return l; /* 0 or -1 */ - } - ---- a/src/stdio/fwide.c -+++ b/src/stdio/fwide.c -@@ -1,13 +1,14 @@ --#include <wchar.h> - #include "stdio_impl.h" -- --#define SH (8*sizeof(int)-1) --#define NORMALIZE(x) ((x)>>SH | -((-(x))>>SH)) -+#include "locale_impl.h" - - int fwide(FILE *f, int mode) - { - FLOCK(f); -- if (!f->mode) f->mode = NORMALIZE(mode); -+ if (mode) { -+ if (!f->locale) f->locale = MB_CUR_MAX==1 -+ ? C_LOCALE : UTF8_LOCALE; -+ if (!f->mode) f->mode = mode>0 ? 1 : -1; -+ } - mode = f->mode; - FUNLOCK(f); - return mode; ---- /dev/null -+++ b/src/stdio/ofl.c -@@ -0,0 +1,16 @@ -+#include "stdio_impl.h" -+#include "libc.h" -+ -+static FILE *ofl_head; -+static volatile int ofl_lock[2]; -+ -+FILE **__ofl_lock() -+{ -+ LOCK(ofl_lock); -+ return &ofl_head; -+} -+ -+void __ofl_unlock() -+{ -+ UNLOCK(ofl_lock); -+} ---- /dev/null -+++ b/src/stdio/ofl_add.c -@@ -0,0 +1,11 @@ -+#include "stdio_impl.h" -+ -+FILE *__ofl_add(FILE *f) -+{ -+ FILE **head = __ofl_lock(); -+ f->next = *head; -+ if (*head) (*head)->prev = f; -+ *head = f; -+ __ofl_unlock(); -+ return f; -+} ---- a/src/stdio/open_memstream.c -+++ b/src/stdio/open_memstream.c -@@ -79,11 +79,5 @@ FILE *open_memstream(char **bufp, size_t - - if (!libc.threaded) f->lock = -1; - -- OFLLOCK(); -- f->next = libc.ofl_head; -- if (libc.ofl_head) libc.ofl_head->prev = f; -- libc.ofl_head = f; -- OFLUNLOCK(); -- -- return f; -+ return __ofl_add(f); - } ---- a/src/stdio/open_wmemstream.c -+++ b/src/stdio/open_wmemstream.c -@@ -81,11 +81,5 @@ FILE *open_wmemstream(wchar_t **bufp, si - - if (!libc.threaded) f->lock = -1; - -- OFLLOCK(); -- f->next = libc.ofl_head; -- if (libc.ofl_head) libc.ofl_head->prev = f; -- libc.ofl_head = f; -- OFLUNLOCK(); -- -- return f; -+ return __ofl_add(f); - } ---- a/src/stdio/ungetwc.c -+++ b/src/stdio/ungetwc.c -@@ -1,4 +1,5 @@ - #include "stdio_impl.h" -+#include "locale_impl.h" - #include <wchar.h> - #include <limits.h> - #include <ctype.h> -@@ -8,21 +9,19 @@ wint_t ungetwc(wint_t c, FILE *f) - { - unsigned char mbc[MB_LEN_MAX]; - int l=1; -- -- if (c == WEOF) return c; -- -- /* Try conversion early so we can fail without locking if invalid */ -- if (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0) -- return WEOF; -+ locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; - - FLOCK(f); - -- f->mode |= f->mode+1; -+ if (f->mode <= 0) fwide(f, 1); -+ *ploc = f->locale; - - if (!f->rpos) __toread(f); -- if (!f->rpos || f->rpos < f->buf - UNGET + l) { -+ if (!f->rpos || f->rpos < f->buf - UNGET + l || c == WEOF || -+ (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0)) { - FUNLOCK(f); -- return EOF; -+ *ploc = loc; -+ return WEOF; - } - - if (isascii(c)) *--f->rpos = c; -@@ -31,5 +30,6 @@ wint_t ungetwc(wint_t c, FILE *f) - f->flags &= ~F_EOF; - - FUNLOCK(f); -+ *ploc = loc; - return c; - } ---- a/src/stdio/vfwprintf.c -+++ b/src/stdio/vfwprintf.c -@@ -293,7 +293,10 @@ static int wprintf_core(FILE *f, const w - if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, ""); - l=w; - continue; -+ case 'm': -+ arg.p = strerror(errno); - case 's': -+ if (!arg.p) arg.p = "(null)"; - bs = arg.p; - if (p<0) p = INT_MAX; - for (i=l=0; l<p && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++); -@@ -356,7 +359,7 @@ int vfwprintf(FILE *restrict f, const wc - } - - FLOCK(f); -- f->mode |= f->mode+1; -+ fwide(f, 1); - olderr = f->flags & F_ERR; - f->flags &= ~F_ERR; - ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type); ---- a/src/stdio/vfwscanf.c -+++ b/src/stdio/vfwscanf.c -@@ -104,7 +104,7 @@ int vfwscanf(FILE *restrict f, const wch - - FLOCK(f); - -- f->mode |= f->mode+1; -+ fwide(f, 1); - - for (p=fmt; *p; p++) { - ---- a/src/string/strverscmp.c -+++ b/src/string/strverscmp.c -@@ -2,40 +2,33 @@ - #include <ctype.h> - #include <string.h> - --int strverscmp(const char *l, const char *r) -+int strverscmp(const char *l0, const char *r0) - { -- int haszero=1; -- while (*l==*r) { -- if (!*l) return 0; -+ const unsigned char *l = (const void *)l0; -+ const unsigned char *r = (const void *)r0; -+ size_t i, dp, j; -+ int z = 1; - -- if (*l=='0') { -- if (haszero==1) { -- haszero=0; -- } -- } else if (isdigit(*l)) { -- if (haszero==1) { -- haszero=2; -- } -- } else { -- haszero=1; -- } -- l++; r++; -+ /* Find maximal matching prefix and track its maximal digit -+ * suffix and whether those digits are all zeros. */ -+ for (dp=i=0; l[i]==r[i]; i++) { -+ int c = l[i]; -+ if (!c) return 0; -+ if (!isdigit(c)) dp=i+1, z=1; -+ else if (c!='0') z=0; - } -- if (haszero==1 && (*l=='0' || *r=='0')) { -- haszero=0; -- } -- if ((isdigit(*l) && isdigit(*r) ) && haszero) { -- size_t lenl=0, lenr=0; -- while (isdigit(l[lenl]) ) lenl++; -- while (isdigit(r[lenr]) ) lenr++; -- if (lenl==lenr) { -- return (*l - *r); -- } else if (lenl>lenr) { -- return 1; -- } else { -- return -1; -- } -- } else { -- return (*l - *r); -+ -+ if (l[dp]!='0' && r[dp]!='0') { -+ /* If we're not looking at a digit sequence that began -+ * with a zero, longest digit string is greater. */ -+ for (j=i; isdigit(l[j]); j++) -+ if (!isdigit(r[j])) return 1; -+ if (isdigit(r[j])) return -1; -+ } else if (z && dp<i && (isdigit(l[i]) || isdigit(r[i]))) { -+ /* Otherwise, if common prefix of digit sequence is -+ * all zeros, digits order less than non-digits. */ -+ return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0'); - } -+ -+ return l[i] - r[i]; - } ---- a/src/thread/__tls_get_addr.c -+++ b/src/thread/__tls_get_addr.c -@@ -8,9 +8,9 @@ void *__tls_get_addr(size_t *v) - __attribute__((__visibility__("hidden"))) - void *__tls_get_new(size_t *); - if (v[0]<=(size_t)self->dtv[0]) -- return (char *)self->dtv[v[0]]+v[1]; -+ return (char *)self->dtv[v[0]]+v[1]+DTP_OFFSET; - return __tls_get_new(v); - #else -- return (char *)self->dtv[1]+v[1]; -+ return (char *)self->dtv[1]+v[1]+DTP_OFFSET; - #endif - } ---- /dev/null -+++ b/src/thread/__unmapself.c -@@ -0,0 +1,29 @@ -+#include "pthread_impl.h" -+#include "atomic.h" -+#include "syscall.h" -+/* cheat and reuse CRTJMP macro from dynlink code */ -+#include "dynlink.h" -+ -+static volatile int lock; -+static void *unmap_base; -+static size_t unmap_size; -+static char shared_stack[256]; -+ -+static void do_unmap() -+{ -+ __syscall(SYS_munmap, unmap_base, unmap_size); -+ __syscall(SYS_exit); -+} -+ -+void __unmapself(void *base, size_t size) -+{ -+ int tid=__pthread_self()->tid; -+ char *stack = shared_stack + sizeof shared_stack; -+ stack -= (uintptr_t)stack % 16; -+ while (lock || a_cas(&lock, 0, tid)) -+ a_spin(); -+ __syscall(SYS_set_tid_address, &lock); -+ unmap_base = base; -+ unmap_size = size; -+ CRTJMP(do_unmap, stack); -+} ---- a/src/thread/mips/__unmapself.s -+++ b/src/thread/mips/__unmapself.s -@@ -2,6 +2,7 @@ - .global __unmapself - .type __unmapself,@function - __unmapself: -+ move $sp, $25 - li $2, 4091 - syscall - li $4, 0 ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -191,8 +191,9 @@ int __pthread_create(pthread_t *restrict - if (!libc.can_do_threads) return ENOSYS; - self = __pthread_self(); - if (!libc.threaded) { -- for (FILE *f=libc.ofl_head; f; f=f->next) -+ for (FILE *f=*__ofl_lock(); f; f=f->next) - init_file_lock(f); -+ __ofl_unlock(); - init_file_lock(__stdin_used); - init_file_lock(__stdout_used); - init_file_lock(__stderr_used); -@@ -231,7 +232,8 @@ int __pthread_create(pthread_t *restrict - if (guard) { - map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0); - if (map == MAP_FAILED) goto fail; -- if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)) { -+ if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE) -+ && errno != ENOSYS) { - __munmap(map, size); - goto fail; - } ---- a/src/thread/sh/__set_thread_area.s -+++ b/src/thread/sh/__set_thread_area.s -@@ -1,6 +0,0 @@ --.global __set_thread_area --.type __set_thread_area, @function --__set_thread_area: -- ldc r4, gbr -- rts -- mov #0, r0 ---- a/src/thread/sh/__unmapself.s -+++ b/src/thread/sh/__unmapself.s -@@ -1,9 +1,9 @@ - .text --.global __unmapself --.type __unmapself, @function --__unmapself: -+.global __unmapself_sh_mmu -+.type __unmapself_sh_mmu, @function -+__unmapself_sh_mmu: - mov #91, r3 ! SYS_munmap -- trapa #18 -+ trapa #31 - - or r0, r0 - or r0, r0 -@@ -13,7 +13,7 @@ __unmapself: - - mov #1, r3 ! SYS_exit - mov #0, r4 -- trapa #17 -+ trapa #31 - - or r0, r0 - or r0, r0 ---- a/src/thread/sh/clone.s -+++ b/src/thread/sh/clone.s -@@ -17,7 +17,7 @@ __clone: - mov.l @r15, r6 ! r6 = ptid - mov.l @(8,r15), r7 ! r7 = ctid - mov.l @(4,r15), r0 ! r0 = tls -- trapa #21 -+ trapa #31 - - or r0, r0 - or r0, r0 -@@ -38,7 +38,7 @@ __clone: - - mov #1, r3 ! __NR_exit - mov r0, r4 -- trapa #17 -+ trapa #31 - - or r0, r0 - or r0, r0 ---- a/src/thread/sh/syscall_cp.s -+++ b/src/thread/sh/syscall_cp.s -@@ -31,7 +31,7 @@ L1: .long __cancel@PLT-(1b-.) - mov.l @(4,r15), r7 - mov.l @(8,r15), r0 - mov.l @(12,r15), r1 -- trapa #22 -+ trapa #31 - - __cp_end: - ! work around hardware bug ---- a/src/time/__tz.c -+++ b/src/time/__tz.c -@@ -125,7 +125,8 @@ static void do_tzset() - "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; - - s = getenv("TZ"); -- if (!s || !*s) s = "/etc/localtime"; -+ if (!s) s = "/etc/localtime"; -+ if (!*s) s = __gmt; - - if (old_tz && !strcmp(s, old_tz)) return; - ---- a/src/unistd/sh/pipe.s -+++ b/src/unistd/sh/pipe.s -@@ -2,7 +2,7 @@ - .type pipe, @function - pipe: - mov #42, r3 -- trapa #17 -+ trapa #31 - - ! work around hardware bug - or r0, r0 ---- /dev/null -+++ b/tools/ld.musl-clang.in -@@ -0,0 +1,51 @@ -+#!/bin/sh -+cc="@CC@" -+libc_lib="@LIBDIR@" -+ldso="@LDSO@" -+cleared= -+shared= -+userlinkdir= -+userlink= -+ -+for x ; do -+ test "$cleared" || set -- ; cleared=1 -+ -+ case "$x" in -+ -L-user-start) -+ userlinkdir=1 -+ ;; -+ -L-user-end) -+ userlinkdir= -+ ;; -+ -L*) -+ test "$userlinkdir" && set -- "$@" "$x" -+ ;; -+ -l-user-start) -+ userlink=1 -+ ;; -+ -l-user-end) -+ userlink= -+ ;; -+ crtbegin*.o|crtend*.o) -+ set -- "$@" $($cc -print-file-name=$x) -+ ;; -+ -lgcc|-lgcc_eh) -+ file=lib${x#-l}.a -+ set -- "$@" $($cc -print-file-name=$file) -+ ;; -+ -l*) -+ test "$userlink" && set -- "$@" "$x" -+ ;; -+ -shared) -+ shared=1 -+ set -- "$@" -shared -+ ;; -+ -sysroot=*|--sysroot=*) -+ ;; -+ *) -+ set -- "$@" "$x" -+ ;; -+ esac -+done -+ -+exec $($cc -print-prog-name=ld) -nostdlib "$@" -lc -dynamic-linker "$ldso" ---- /dev/null -+++ b/tools/musl-clang.in -@@ -0,0 +1,35 @@ -+#!/bin/sh -+cc="@CC@" -+libc="@PREFIX@" -+libc_inc="@INCDIR@" -+libc_lib="@LIBDIR@" -+thisdir="`cd "$(dirname "$0")"; pwd`" -+ -+# prevent clang from running the linker (and erroring) on no input. -+sflags= -+eflags= -+for x ; do -+ case "$x" in -+ -l*) input=1 ;; -+ *) input= ;; -+ esac -+ if test "$input" ; then -+ sflags="-l-user-start" -+ eflags="-l-user-end" -+ break -+ fi -+done -+ -+exec $cc \ -+ -B"$thisdir" \ -+ -fuse-ld=musl-clang \ -+ -static-libgcc \ -+ -nostdinc \ -+ --sysroot "$libc" \ -+ -isystem "$libc_inc" \ -+ -L-user-start \ -+ $sflags \ -+ "$@" \ -+ $eflags \ -+ -L"$libc_lib" \ -+ -L-user-end |