| 
					
				 | 
			
			
				@@ -1,2015 +0,0 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit b6a6cd703ffefa6352249fb01f4da28d85d17306 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu Jun 4 11:45:17 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix dynamic linker regression processing R_*_NONE type relocations 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    commit f3ddd173806fd5c60b3f034528ca24542aecc5b9 inadvertently removed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the early check for "none" type relocations, causing the address 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    dso->base+0 to be dereferenced to obtain an addend. shared libraries, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (including libc.so) and PIE executables were unaffected, since their 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    base addresses are the actual address of their mappings and are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    readable. non-PIE main executables, however, have a base address of 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    because their load addresses are absolute and not offset at load time. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in practice none-type relocations do not arise with toolchains that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    are in use except on mips, and on mips it's moderately rare for a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    non-PIE executable to have a relocation table, since the mips-specific 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    got processing serves in its place for most purposes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 585ba14df4799d50ec9682ce75825d2eafec2a6a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed Jun 3 02:00:44 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add additional Makefile dependency rules for rcrt1.o PIE start file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 2b4fcfdacf93c3dfd6ac15e31790a9e154374679 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 28 23:08:12 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix failure of ungetc and ungetwc to work on files in eof status 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    these functions were written to handle clearing eof status, but failed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    to account for the __toread function's handling of eof. with this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    patch applied, __toread still returns EOF when the file is in eof 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status, so that read operations will fail, but it also sets up valid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    buffer pointers for read mode, which are set to the end of the buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rather than the beginning in order to make the whole buffer available 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    to ungetc/ungetwc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    minor changes to __uflow were needed since it's now possible to have 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    non-zero buffer pointers while in eof status. as made, these changes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    remove a 'fast path' bypassing the function call to __toread, which 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    could be reintroduced with slightly different logic, but since 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ordinary files have a syscall in f->read, optimizing the code path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    does not seem worthwhile. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the __stdio_read function is also updated not to zero the read buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pointers on eof/error. while not necessary for correctness, this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    change avoids the overhead of calling __toread in ungetc after 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    reaching eof, and it also reduces code size and increases consistency 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    with the fmemopen read operation which does not zero the pointers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit b6e7c664677ab7c77f183b8c41105f2be519800c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 28 15:37:23 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add missing legacy LFS64 macros in sys/resource.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    based on patch by Felix Janda, with RLIM64_SAVED_CUR and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    RLIM64_SAVED_MAX added for completeness. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit fc431d3f76bb9bde34a89e4a3e4d0c27de959855 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Shiz <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 28 05:52:22 2015 +0200 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    configure: work around compilers that merely warn for unknown options 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    some compilers (such as clang) accept unknown options without error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    but then print warnings on each invocation, cluttering the build 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    output and burying meaningful warnings. this patch makes configure's 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    tryflag and tryldflag functions use additional options to turn the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    unknown-option warnings into errors, if available, but only at check 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    time. these options are not output in config.mak to avoid the risk of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    spurious build breakage; if they work, they will have already done 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    their job at configure time. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit aeeac9ca5490d7d90fe061ab72da446c01ddf746 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed May 27 15:54:47 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    implement fail-safe static locales for newlocale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this frees applications which need to make temporary use of the C 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    locale (via uselocale) from the possibility that newlocale might fail. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the C.UTF-8 locale is also provided as a static locale. presently they 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    behave the same, but this may change in the future. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 11858d31aa020df3e7e7dedf49f9870ce12f31cc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed May 27 03:32:46 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rename internal locale file handling locale maps 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    since the __setlocalecat function was removed, the filename 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    __setlocalecat.c no longer made sense. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 61a3364d246e72b903da8b76c2e27a225a51351e 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed May 27 03:22:52 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    overhaul locale internals to treat categories roughly uniformly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    previously, LC_MESSAGES was treated specially as the only category 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    which could be set to a locale name without a definition file, in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    order to facilitate gettext message translations when no libc locale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    was available. LC_NUMERIC was completely un-settable, and LC_CTYPE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stored a flag intended to be used for a possible future byte-based C 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    locale, instead of storing a __locale_map pointer like the other 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    categories use. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this patch changes all categories to be represented by pointers to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    __locale_map structures, and allows locale names without definition 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    files to be treated as valid locales with trivial definition when used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in any category. outwardly visible functional changes should be minor, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    limited mainly to the strings read back from setlocale and the way 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gettext handles translations in categories other than LC_MESSAGES. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    various internal refactoring has also been performed, and improvements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in const correctness have been made. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 63c188ec42e76ff768e81f6b65b11c68fc43351e 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed May 27 00:22:43 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    replace atomics with locks in locale-setting code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this is part of a general program of removing direct use of atomics 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    where they are not necessary to meet correctness or performance needs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    but in this case it's also an optimization. only the global locale 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    needs synchronization; allocated locales referenced with locale_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    handles are immutable during their lifetimes, and using atomics to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    initialize them increases their cost of setup. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit dc031ee0b1ba11baa00cd7f0769e461a5f396c71 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Tue May 26 03:37:41 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add rcrt1 start file for fully static-linked PIE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    static-linked PIE files need startup code to relocate themselves, much 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    like the dynamic linker does. rcrt1.c reuses the code in dlstart.c, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stage 1 of the dynamic linker, which in turn reuses crt_arch.h, to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    achieve static PIE with no new code. only relative relocations are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    supported. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    existing toolchains that don't yet support static PIE directly can be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    repurposed by passing "-shared -Wl,-Bstatic -Wl,-Bsymbolic" instead of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "-static -pie" and substituting rcrt1.o in place of crt1.o. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    all libraries being linked must be built as PIC/PIE; TEXTRELs are not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    supported at this time. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit ed0c8249825161036356a3616e8c5247c15d0927 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Tue May 26 02:31:04 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix incorrect application of visibility to Scrt1.o 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    commit de2b67f8d41e08caa56bf6540277f6561edb647f attempted to avoid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    having vis.h affect crt files, but the Makefile variable used, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    CRT_LIBS, refers to the final output copies in the lib directory, not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the copies in the crt build directory, and thus the -DCRT was not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    applied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while unlikely to be noticed, this regression probably broke 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    production of PIE executables whose main functions are not in the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    executable but rather a shared library. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 9bbddf730f7837cf87f4c789fbb41a312e295d6c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 23:33:59 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    reprocess all libc/ldso symbolic relocations in dynamic linking stage 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    commit f3ddd173806fd5c60b3f034528ca24542aecc5b9 introduced early 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    relocations and subsequent reprocessing as part of the dynamic linker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    bootstrap overhaul, to allow use of arbitrary libc functions before 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the main application and libraries are loaded, but only reprocessed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GOT/PLT relocation types. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    commit c093e2e8201524db0d638920e76bcb6b1d925f3a added reprocessing of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    non-GOT/PLT relocations to fix an actual regression that was observed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    on powerpc, but only for RELA format tables with out-of-line addends. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    REL table (inline addends at the relocation address) reprocessing is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    trickier because the first relocation pass clobbers the addends. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this patch extends symbolic relocation reprocessing for libc/ldso to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    support all relocation types, whether REL or RELA format tables are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    used. it is believed not to alter behavior on any existing archs for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the current dynamic linker and libc code. the motivations for this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    change are consistency and future-proofing. it ensures that behavior 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    does not differ depending on whether REL or RELA tables are used, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    which could lead to undetected arch-specific bugs. it also ensures 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    that, if in the future code depending on additional relocation types 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    is added to libc.so, either at the source level or as part of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    compiler runtime that gets pulled in (for example, soft-float with TLS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for fenv), the new code will work properly. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the implementation concept is simple: stage 2 of the dynamic linker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    counts the number of symbolic relocations in the libc/ldso REL table 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    and allocates a VLA to save their addends into; stage 3 then uses the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    saved addends in place of the inline ones which were clobbered. for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stack safety, a hard limit (currently 4k) is imposed on the number of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    such addends; this should be a couple orders of magnitude larger than 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the actual need. this number is not a runtime variable that could 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    break fail-safety; it is constant for a given libc.so build. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 768b82c6de24e480267c4c251c440edfc71800e3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 19:15:17 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    move call to dynamic linker stage-3 into stage-2 function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this move eliminates a duplicate "by-hand" symbol lookup loop from the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stage-1 code and replaces it with a call to find_sym, which can be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    used once we're in stage 2. it reduces the size of the stage 1 code, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    which is helpful because stage 1 will become the crt start file for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    static-PIE executables, and it will allow stage 3 to access stage 2's 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    automatic storage, which will be important in an upcoming commit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 967bcbf67c3ffac587de4d79abc1e5e072d83e3e 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 16:02:49 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mark mips crt code as code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    otherwise disassemblers treat it as data. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 7b75c4877ddf22f219f944c61d939df1dee4f6d3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 15:56:36 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    mark mips cancellable syscall code as code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    otherwise disassemblers treat it as data. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 0e0e49421f08cfd670975ecd3604f7f9015e1833 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 00:32:37 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    simplify/shrink relocation processing in dynamic linker stage 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the outer-loop approach made sense when we were also processing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    DT_JMPREL, which might be in REL or RELA form, to avoid major code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    duplication. commit 09db855b35709aa627d7055c57a98e1e471920ab removed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    processing of DT_JMPREL, and in the remaining two tables, the format 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (REL or RELA) is known by the name of the table. simply writing two 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    versions of the loop results in smaller and simpler code. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 09db855b35709aa627d7055c57a98e1e471920ab 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 25 00:25:56 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    remove processing of DT_JMPREL from dynamic linker stage 1 bootstrap 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the DT_JMPREL relocation table necessarily consists entirely of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    JMP_SLOT (REL_PLT in internal nomenclature) relocations, which are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    symbolic; they cannot be resolved in stage 1, so there is no point in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    processing them. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 9f26ebded188ed78c3571a4ca1477dd6351bc647 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Sun May 24 23:03:47 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix stack alignment code in mips crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the instruction used to align the stack, "and $sp, $sp, -8", does not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    actually exist; it's expanded to 2 instructions using the 'at' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (assembler temporary) register, and thus cannot be used in a branch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    delay slot. since alignment mod 16 commutes with subtracting 8, simply 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    swapping these two operations fixes the problem. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    crt1.o was not affected because it's still being generated from a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    dedicated asm source file. dlstart.lo was not affected because the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stack pointer it receives is already aligned by the kernel. but 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Scrt1.o was affected in cases where the dynamic linker gave it a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    misaligned stack pointer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 63caf1d207d143fe405bbe0cda9aac8deca1171a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Fri May 22 01:50:05 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add .text section directive to all crt_arch.h files missing it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    i386 and x86_64 versions already had the .text directive; other archs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    did not. normally, top-level (file scope) __asm__ starts in the .text 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    section anyway, but problems were reported with some versions of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    clang, and it seems preferable to set it explicitly anyway, at least 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for the sake of consistency between archs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 3b0e83264d156f9e496ab32badd89e4447b807aa 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 21 17:06:28 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    remove outdated and misleading comment in iconv.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the comment claimed that EUC/GBK/Big5 are not implemented, which has 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    been incorrect since commit 19b4a0a20efc6b9df98b6a43536ecdd628ba4643. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 39b8ce66f2ed9c17427ec3a48be9bda29b93b9d7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 21 17:01:23 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in iconv_open, accept "CHAR" and "" as aliases for "UTF-8" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while not a requirement, it's common convention in other iconv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    implementations to accept "CHAR" as an alias for nl_langinfo(CODESET), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    meaning the encoding used for char[] strings in the current locale, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    and also "" as an alternate form. supporting this is not costly and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    improves compatibility. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit c648cefb27984db60474ec1747cbfde83c2856d0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Wed May 20 00:17:35 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix inconsistency in a_and and a_or argument types on x86[_64] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    conceptually, and on other archs, these functions take a pointer to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    int, but in the i386, x86_64, and x32 versions of atomic.h, they took 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    a pointer to void instead. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 390f93ef69153bf2087fcf3baa1776ad9a6765ab 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Bobby Bingham <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Sun May 17 13:46:38 2015 -0500 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    inline llsc atomics when building for sh4a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    If we're building for sh4a, the compiler is already free to use 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    instructions only available on sh4a, so we can do the same and inline the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    llsc atomics. If we're building for an older processor, we still do the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    same runtime atomics selection as before. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit c093e2e8201524db0d638920e76bcb6b1d925f3a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 18 16:51:54 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    reprocess libc/ldso RELA relocations in stage 3 of dynamic linking 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    this fixes a regression on powerpc that was introduced in commit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    f3ddd173806fd5c60b3f034528ca24542aecc5b9. global data accesses on 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    powerpc seem to be using a translation-unit-local GOT filled via 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    R_PPC_ADDR32 relocations rather than R_PPC_GLOB_DAT. being a non-GOT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    relocation type, these were not reprocessed after adding the main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    application and its libraries to the chain, causing libc code not to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    see copy relocations in the main program, and therefore to use the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pre-copy-relocation addresses for global data objects (like environ). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the motivation for the dynamic linker only reprocessing GOT/PLT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    relocation types in stage 3 is that these types always have a zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    addend, making them safe to process again even if the storage for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    addend has been clobbered. other relocation types which can be used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for address constants in initialized data objects may have non-zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    addends which will be clobbered during the first pass of relocation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    processing if they're stored inline (REL form) rather than out-of-line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (RELA form). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    powerpc generally uses only RELA, so this patch is sufficient to fix 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the regression in practice, but is not fully general, and would not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    suffice if an alternate toolchain generated REL for powerpc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 43e9f652bf4b2195b04fc14c93db591b30a7b790 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Mon May 18 12:11:25 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fix null pointer dereference in dcngettext under specific conditions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if setlocale has not been called, the current locale's messages_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    may be a null pointer. the code path where it's assumed to be non-null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    was only reachable if bindtextdomain had already been called, which is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    normally not done in programs which do not call setlocale, so the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    omitted check went unnoticed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    patch from Void Linux, with description rewritten. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 68630b55c0c7219fe9df70dc28ffbf9efc8021d8 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Sat May 16 01:53:54 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    eliminate costly tricks to avoid TLS access for current locale state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the code being removed used atomics to track whether any threads might 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    be using a locale other than the current global locale, and whether 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    any threads might have abstract 8-bit (non-UTF-8) LC_CTYPE active, a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    feature which was never committed (still pending). the motivations 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    were to support early execution prior to setup of the thread pointer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    to partially support systems (ancient kernels) where thread pointer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    setup is not possible, and to avoid high performance cost on archs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    where accessing the thread pointer may be very slow. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    since commit 19a1fe670acb3ab9ead0fe31859ca7d4fe40dd54, the thread 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pointer is always available, so these hacks are no longer needed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    removing them greatly simplifies the affected code. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 707d7c30f3379441de9b320536ddfd354f4c2143 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Sat May 16 01:15:40 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in i386 __set_thread_area, don't assume %gs register is initially zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    commit f630df09b1fd954eda16e2f779da0b5ecc9d80d3 added logic to handle 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the case where __set_thread_area is called more than once by reusing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the GDT slot already in the %gs register, and only setting up a new 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GDT slot when %gs is zero. this created a hidden assumption that %gs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    is zero when a new process image starts, which is true in practice on 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Linux, but does not seem to be documented ABI, and fails to hold under 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    qemu app-level emulation. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while it would in theory be possible to zero %gs in the entry point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    code, this code is shared between static and dynamic binaries, and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    dynamic binaries must not clobber the value of %gs already setup by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the dynamic linker. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the alternative solution implemented in this commit simply uses global 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    data to store the GDT index that's selected. __set_thread_area should 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    only be called in the initial thread anyway (subsequent threads get 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    their thread pointer setup by __clone), but even if it were called by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    another thread, it would simply read and write back the same GDT index 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    that was already assigned to the initial thread, and thus (in the x86 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    memory model) there is no data race. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit c0f10cf06725bd0de37f3ced7954a653bf9f1049 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 14 18:51:27 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    make arm reloc.h CRTJMP macro compatible with thumb 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    compilers targeting armv7 may be configured to produce thumb2 code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    instead of arm code by default, and in the future we may wish to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    support targets where only the thumb instruction set is available. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the instructions this patch omits in thumb mode are needed only for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    non-thumb versions of armv4 or earlier, which are not supported by any 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    current compilers/toolchains and thus rather pointless to have. at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    some point these compatibility return sequences may be removed from 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    all asm source files, and in that case it would make sense to remove 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    them here too and remove the ifdef. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-commit 83340c7a580e91b22f58321b7cf6d976af61084c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Author: Rich Felker <[email protected]> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-Date:   Thu May 14 18:26:16 2015 -0400 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    make arm crt_arch.h compatible with thumb code generation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    compilers targeting armv7 may be configured to produce thumb2 code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    instead of arm code by default, and in the future we may wish to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    support targets where only the thumb instruction set is available. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the changes made here avoid operating directly on the sp register, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    which is not possible in thumb code, and address an issue with the way 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    the address of _DYNAMIC is computed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    previously, the relative address of _DYNAMIC was stored with an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    additional offset of -8 versus the pc-relative add instruction, since 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    on arm the pc register evaluates to ".+8". in thumb code, it instead 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    evaluates to ".+4". both are two (normal-size) instructions beyond "." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    in the current execution mode, so the numbered label 2 used in the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    relative address expression is simply moved two instructions ahead to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    be compatible with both instruction sets. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/Makefile 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/Makefile 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -44,7 +44,7 @@ ALL_INCLUDES = $(sort $(wildcard include 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--CRT_LIBS = lib/crt1.o lib/Scrt1.o lib/crti.o lib/crtn.o 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+CRT_LIBS = lib/crt1.o lib/Scrt1.o lib/rcrt1.o lib/crti.o lib/crtn.o 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- STATIC_LIBS = lib/libc.a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- SHARED_LIBS = lib/libc.so 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- TOOL_LIBS = lib/musl-gcc.specs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -85,11 +85,13 @@ src/internal/version.h: $(wildcard VERSI 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- src/internal/version.lo: src/internal/version.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+crt/rcrt1.o src/ldso/dlstart.lo src/ldso/dynlink.lo: src/internal/dynlink.h arch/$(ARCH)/reloc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--crt/crt1.o crt/Scrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+crt/crt1.o crt/Scrt1.o crt/rcrt1.o src/ldso/dlstart.lo: $(wildcard arch/$(ARCH)/crt_arch.h) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--crt/Scrt1.o: CFLAGS += -fPIC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+crt/rcrt1.o: src/ldso/dlstart.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+crt/Scrt1.o crt/rcrt1.o: CFLAGS += -fPIC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=src/%)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- $(OPTIMIZE_SRCS:%.c=%.o) $(OPTIMIZE_SRCS:%.c=%.lo): CFLAGS += -O3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -104,7 +106,7 @@ NOSSP_SRCS = $(wildcard crt/*.c) \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	src/ldso/dlstart.c src/ldso/dynlink.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- $(NOSSP_SRCS:%.c=%.o) $(NOSSP_SRCS:%.c=%.lo): CFLAGS += $(CFLAGS_NOSSP) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--$(CRT_LIBS): CFLAGS += -DCRT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+$(CRT_LIBS:lib/%=crt/%): CFLAGS += -DCRT 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- # This incantation ensures that changes to any subarch asm files will 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- # force the corresponding object file to be rebuilt, even if the implicit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/aarch64/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/aarch64/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,4 +1,5 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START "\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".type " START ",%function\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ":\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/arm/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/arm/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,15 +1,18 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START " \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".type " START ",%function \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ": \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	mov fp, #0 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	mov lr, #0 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"	mov a1, sp \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	ldr a2, 1f \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"2:	add a2, pc, a2 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"	and sp, sp, #-16 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"	add a2, pc, a2 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"	mov a1, sp \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"2:	and ip, a1, #-16 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"	mov sp, ip \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	bl " START "_c \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".weak _DYNAMIC \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".hidden _DYNAMIC \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"1:	.word _DYNAMIC-2b-8 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".align 2 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"1:	.word _DYNAMIC-2b \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/arm/reloc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/arm/reloc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -28,5 +28,10 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define REL_TPOFF       R_ARM_TLS_TPOFF32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- //#define REL_TLSDESC     R_ARM_TLS_DESC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#ifdef __thumb__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define CRTJMP(pc,sp) __asm__ __volatile__( \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"mov sp,%1 ; bx %0" : : "r"(pc), "r"(sp) : "memory" ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define CRTJMP(pc,sp) __asm__ __volatile__( \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	"mov sp,%1 ; tst %0,#1 ; moveq pc,%0 ; bx %0" : : "r"(pc), "r"(sp) : "memory" ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/i386/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/i386/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -50,16 +50,16 @@ static inline int a_cas(volatile int *p, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_or(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_or(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; orl %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_and(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_and(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; andl %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static inline int a_swap(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/microblaze/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/microblaze/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,4 +1,5 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START " \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".align  2 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ": \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/mips/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/mips/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,6 +1,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".set push\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".set noreorder\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global _" START "\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START "\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".type   _" START ", @function\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -21,8 +22,8 @@ __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	addu $5, $5, $gp \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	lw $25, 4($ra) \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	addu $25, $25, $gp \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"	subu $sp, $sp, 16 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"	and $sp, $sp, -8 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	jalr $25 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"	 and $sp, $sp, -8 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"	 subu $sp, $sp, 16 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".set pop \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/or1k/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/or1k/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,4 +1,5 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START " \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".align  4 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ": \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/powerpc/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/powerpc/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,4 +1,5 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START " \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".type   " START ", %function \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ": \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/sh/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/sh/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -22,6 +22,88 @@ static inline int a_ctz_64(uint64_t x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return a_ctz_l(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define LLSC_CLOBBERS "r0", "t", "memory" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define LLSC_START(mem) "synco\n"  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"0:	movli.l @" mem ", r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define LLSC_END(mem)              \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"1:	movco.l r0, @" mem "\n"    \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"	bf 0b\n"                   \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline int __sh_cas_llsc(volatile int *p, int t, int s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	cmp/eq %0, %2\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	bf 1f\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov %3, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old) : "r"(p), "r"(t), "r"(s) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline int __sh_swap_llsc(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov %2, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline int __sh_fetch_add_llsc(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	add %2, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void __sh_store_llsc(volatile int *p, int x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov.l %1, @%0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: : "r"(p), "r"(x) : "memory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void __sh_and_llsc(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_START("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	and %1, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_END("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void __sh_or_llsc(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_START("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	or %1, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		LLSC_END("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#ifdef __SH4A__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_cas(p,t,s)     __sh_cas_llsc(p,t,s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_swap(x,v)      __sh_swap_llsc(x,v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_fetch_add(x,v) __sh_fetch_add_llsc(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_store(x,v)     __sh_store_llsc(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_and(x,v)       __sh_and_llsc(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define a_or(x,v)        __sh_or_llsc(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int  __sh_cas(volatile int *, int, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int  __sh_swap(volatile int *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int  __sh_fetch_add(volatile int *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -35,6 +117,7 @@ void __sh_or(volatile int *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define a_store(x,v)     __sh_store(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define a_and(x,v)       __sh_and(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define a_or(x,v)        __sh_or(x, v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static inline void *a_cas_p(volatile void *p, void *t, void *s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/sh/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/sh/crt_arch.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,4 +1,5 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __asm__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+".text \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ".global " START " \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- START ": \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "	mova 1f, r0 \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/sh/src/atomic.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/sh/src/atomic.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,12 +1,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#ifndef __SH4A__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define LLSC_CLOBBERS   "r0", "t", "memory" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define LLSC_START(mem) "synco\n"  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"0:	movli.l @" mem ", r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define LLSC_END(mem)              \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"1:	movco.l r0, @" mem "\n"    \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"	bf 0b\n"                   \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "atomic.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- /* 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 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -34,114 +29,74 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int __sh_cas(volatile int *p, int t, int s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_cas_llsc(p, t, s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	int old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	cmp/eq %0, %2\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	bf 1f\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov %3, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old) : "r"(p), "r"(t), "r"(s) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_START_EVEN("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	cmp/eq %0, %2\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	bf 1f\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_END("%1", "%3") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old) : "r"(p), "r"(t), "r"(s) : GUSA_CLOBBERS, "t"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_START_EVEN("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	cmp/eq %0, %2\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	bf 1f\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_END("%1", "%3") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old) : "r"(p), "r"(t), "r"(s) : GUSA_CLOBBERS, "t"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int __sh_swap(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_swap_llsc(x, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	int old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov %2, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_START_EVEN("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_END("%1", "%2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_START_EVEN("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_END("%1", "%2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int __sh_fetch_add(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_fetch_add_llsc(x, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	int old, dummy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_START("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov r0, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	add %2, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_END("%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_START_EVEN("%2", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov %0, %1\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	add %3, %1\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_END("%2", "%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_START_EVEN("%2", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov %0, %1\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	add %3, %1\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_END("%2", "%1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- void __sh_store(volatile int *p, int x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov.l %1, @%0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	synco\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: : "r"(p), "r"(x) : "memory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	mov.l %1, @%0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: : "r"(p), "r"(x) : "memory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_store_llsc(p, x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	mov.l %1, @%0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: : "r"(p), "r"(x) : "memory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- void __sh_and(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_and_llsc(x, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	int dummy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_START("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	and %1, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_END("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_START_ODD("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	and %2, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_END("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_START_ODD("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	and %2, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_END("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- void __sh_or(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__hwcap & CPU_HAS_LLSC) return __sh_or_llsc(x, v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	int dummy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (__hwcap & CPU_HAS_LLSC) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_START("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	or %1, r0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			LLSC_END("%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: : "r"(x), "r"(v) : LLSC_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_START_ODD("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			"	or %2, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			GUSA_END("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__asm__ __volatile__( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_START_ODD("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		"	or %2, %0\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		GUSA_END("%1", "%0") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/x32/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/x32/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -47,16 +47,16 @@ static inline int a_cas(volatile int *p, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_or(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_or(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; or %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_and(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_and(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; and %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static inline int a_swap(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/arch/x86_64/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/arch/x86_64/atomic.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -47,16 +47,16 @@ static inline int a_cas(volatile int *p, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_or(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_or(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; or %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static inline void a_and(volatile void *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static inline void a_and(volatile int *p, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	__asm__( "lock ; and %1, %0" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		: "=m"(*(int *)p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		: "=m"(*p) : "r"(v) : "memory" ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static inline int a_swap(volatile int *x, int v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/configure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/configure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -80,7 +80,7 @@ fi 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- tryflag () { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- printf "checking whether compiler accepts %s... " "$2" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- echo "typedef int x;" > "$tmpc" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--if $CC $2 -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+if $CC $CFLAGS_TRY $2 -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- printf "yes\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- eval "$1=\"\${$1} \$2\"" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- eval "$1=\${$1# }" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -94,7 +94,7 @@ fi 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- tryldflag () { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- printf "checking whether linker accepts %s... " "$2" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- echo "typedef int x;" > "$tmpc" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--if $CC -nostdlib -shared "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+if $CC $LDFLAGS_TRY -nostdlib -shared "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- printf "yes\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- eval "$1=\"\${$1} \$2\"" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- eval "$1=\${$1# }" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -113,7 +113,9 @@ CFLAGS_C99FSE= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- CFLAGS_AUTO= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- CFLAGS_MEMOPS= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- CFLAGS_NOSSP= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+CFLAGS_TRY= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- LDFLAGS_AUTO= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+LDFLAGS_TRY= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- OPTIMIZE_GLOBS= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- prefix=/usr/local/musl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- exec_prefix='$(prefix)' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -205,6 +207,14 @@ exit 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- fi 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- # 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+# Figure out options to force errors on unknown flags. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+# 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+tryflag   CFLAGS_TRY  -Werror=unknown-warning-option 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+tryflag   CFLAGS_TRY  -Werror=unused-command-line-argument 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+tryldflag LDFLAGS_TRY -Werror=unknown-warning-option 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+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. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- # 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/crt/mips/crt1.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/crt/mips/crt1.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -4,6 +4,8 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .weak  _fini 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global __start 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global _start 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type __start,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type _start,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- __start: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- _start: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	subu    $fp, $fp, $fp            # Zero the frame pointer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/crt/mips/crti.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/crt/mips/crti.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -2,6 +2,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .section .init 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global _init 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type _init,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .align 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- _init: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	subu $sp,$sp,32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -10,6 +11,7 @@ _init: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .section .fini 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global _fini 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type _fini,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .align 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- _fini: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	subu $sp,$sp,32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- /dev/null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/crt/rcrt1.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -0,0 +1,15 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define SHARED 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define START "_start" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define _dlstart_c _start_c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "../src/ldso/dlstart.c" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+int main(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+void _init() __attribute__((weak)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+void _fini() __attribute__((weak)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+_Noreturn int __libc_start_main(int (*)(), int, char **, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	void (*)(), void(*)(), void(*)()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+_Noreturn void __dls2(unsigned char *base, size_t *sp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	__libc_start_main(main, *sp, (void *)(sp+1), _init, _fini, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/include/sys/resource.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/include/sys/resource.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -96,6 +96,9 @@ int prlimit(pid_t, int, const struct rli 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define RLIM_NLIMITS RLIMIT_NLIMITS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define RLIM64_INFINITY RLIM_INFINITY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define RLIM64_SAVED_CUR RLIM_SAVED_CUR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define RLIM64_SAVED_MAX RLIM_SAVED_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define getrlimit64 getrlimit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define setrlimit64 setrlimit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define rlimit64 rlimit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/internal/dynlink.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/internal/dynlink.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -51,7 +51,7 @@ enum { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define AUX_CNT 32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define DYN_CNT 32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--typedef void (*stage2_func)(unsigned char *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+typedef void (*stage2_func)(unsigned char *, size_t *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- typedef _Noreturn void (*stage3_func)(size_t *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/internal/libc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/internal/libc.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -8,9 +8,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- struct __locale_map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- struct __locale_struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	volatile int ctype_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	char *messages_name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *volatile cat[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *volatile cat[6]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- struct __libc { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -23,8 +21,6 @@ struct __libc { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	volatile int ofl_lock[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t tls_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t page_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	volatile int uselocale_cnt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	volatile int bytelocale_cnt_minus_1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct __locale_struct global_locale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/internal/locale_impl.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/internal/locale_impl.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -9,22 +9,20 @@ struct __locale_map { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	const void *map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t map_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	char name[LOCALE_NAME_MAX+1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--int __setlocalecat(locale_t, int, const char *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+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 *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- const char *__lctrans_cur(const char *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)-2]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define LCTRANS_CUR(msg) __lctrans_cur(msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define CURRENT_LOCALE \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	(libc.uselocale_cnt ? __pthread_self()->locale : &libc.global_locale) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define CURRENT_LOCALE (__pthread_self()->locale) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#define CURRENT_UTF8 \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	(libc.bytelocale_cnt_minus_1<0 || __pthread_self()->locale->ctype_utf8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #undef MB_CUR_MAX 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/ldso/dlstart.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/ldso/dlstart.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -56,31 +56,22 @@ void _dlstart_c(size_t *sp, size_t *dynv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		for (i=0; i<local_cnt; i++) got[i] += (size_t)base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	/* The use of the reloc_info structure and nested loops is a trick 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	 * to work around the fact that we can't necessarily make function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	 * calls yet. Each struct in the array serves like the arguments 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	 * to a function call. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		void *rel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		size_t size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		size_t stride; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} reloc_info[] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		{ base+dyn[DT_JMPREL], dyn[DT_PLTRELSZ], 2+(dyn[DT_PLTREL]==DT_RELA) }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		{ base+dyn[DT_REL], dyn[DT_RELSZ], 2 }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		{ base+dyn[DT_RELA], dyn[DT_RELASZ], 3 }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		{ 0, 0, 0 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (i=0; reloc_info[i].stride; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		size_t *rel = reloc_info[i].rel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		size_t rel_size = reloc_info[i].size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		size_t stride = reloc_info[i].stride; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			if (!IS_RELATIVE(rel[1])) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			size_t *rel_addr = (void *)(base + rel[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			size_t addend = stride==3 ? rel[2] : *rel_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			*rel_addr = (size_t)base + addend; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t *rel, rel_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	rel = (void *)(base+dyn[DT_REL]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	rel_size = dyn[DT_RELSZ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (!IS_RELATIVE(rel[1])) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		size_t *rel_addr = (void *)(base + rel[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		*rel_addr += (size_t)base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	rel = (void *)(base+dyn[DT_RELA]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	rel_size = dyn[DT_RELASZ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (!IS_RELATIVE(rel[1])) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		size_t *rel_addr = (void *)(base + rel[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		*rel_addr = (size_t)base + rel[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	const char *strings = (void *)(base + dyn[DT_STRTAB]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -93,16 +84,7 @@ void _dlstart_c(size_t *sp, size_t *dynv 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		 && s[3]=='l' && s[4]=='s' && s[5]=='2' && !s[6]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	((stage2_func)(base + syms[i].st_value))(base); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	/* Call dynamic linker stage-3, __dls3 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (i=0; ;i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		const char *s = strings + syms[i].st_name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (s[0]=='_' && s[1]=='_' && s[2]=='d' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		 && s[3]=='l' && s[4]=='s' && s[5]=='3' && !s[6]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	((stage3_func)(base + syms[i].st_value))(sp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	((stage2_func)(base + syms[i].st_value))(base, sp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/ldso/dynlink.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/ldso/dynlink.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -74,7 +74,6 @@ struct dso { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	volatile int new_dtv_idx, new_tls_idx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct td_index *td_index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct dso *fini_next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	int rel_early_relative, rel_update_got; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	char *shortname; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	char buf[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -96,6 +95,9 @@ static struct builtin_tls { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } builtin_tls[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#define ADDEND_LIMIT 4096 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static size_t *saved_addends, *apply_addends_to; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static struct dso ldso; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static struct dso *head, *tail, *fini_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static char *env_path, *sys_path; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -256,10 +258,19 @@ static void do_relocs(struct dso *dso, s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t sym_val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t tls_val; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t addend; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int skip_relative = 0, reuse_addends = 0, save_slot = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (dso == &ldso) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		/* Only ldso's REL table needs addend saving/reuse. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (rel == apply_addends_to) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			reuse_addends = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		skip_relative = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (dso->rel_early_relative && IS_RELATIVE(rel[1])) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (skip_relative && IS_RELATIVE(rel[1])) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		type = R_TYPE(rel[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (type == REL_NONE) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		sym_index = R_SYM(rel[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		reloc_addr = (void *)(base + rel[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		if (sym_index) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -280,12 +291,20 @@ static void do_relocs(struct dso *dso, s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 			def.dso = dso; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		int gotplt = (type == REL_GOT || type == REL_PLT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (dso->rel_update_got && !gotplt) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		addend = stride>2 ? rel[2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: gotplt || type==REL_COPY ? 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			: *reloc_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (stride > 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			addend = rel[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			addend = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} else if (reuse_addends) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			/* Save original addend in stage 2 where the dso 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			 * chain consists of just ldso; otherwise read back 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			 * saved addend since the inline one was clobbered. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			if (head==&ldso) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				saved_addends[save_slot] = *reloc_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			addend = saved_addends[save_slot++]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			addend = *reloc_addr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		sym_val = def.sym ? (size_t)def.dso->base+def.sym->st_value : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		tls_val = def.sym ? def.sym->st_value : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -879,7 +898,7 @@ static void do_mips_relocs(struct dso *p 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t i, j, rel[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	unsigned char *base = p->base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	i=0; search_vec(p->dynv, &i, DT_MIPS_LOCAL_GOTNO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (p->rel_early_relative) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (p==&ldso) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		got += i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		while (i--) *got++ += (size_t)base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1116,7 +1135,7 @@ static void update_tls_size() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  * linker itself, but some of the relocations performed may need to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  * replaced later due to copy relocations in the main program. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--void __dls2(unsigned char *base) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+void __dls2(unsigned char *base, size_t *sp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	Ehdr *ehdr = (void *)base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	ldso.base = base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1125,15 +1144,35 @@ void __dls2(unsigned char *base) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	ldso.phnum = ehdr->e_phnum; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	ldso.phdr = (void *)(base + ehdr->e_phoff); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	ldso.phentsize = ehdr->e_phentsize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	ldso.rel_early_relative = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	kernel_mapped_dso(&ldso); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	decode_dyn(&ldso); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* Prepare storage for to save clobbered REL addends so they 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * can be reused in stage 3. There should be very few. If 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * something goes wrong and there are a huge number, abort 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * instead of risking stack overflow. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t dyn[DYN_CNT]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	decode_vec(ldso.dynv, dyn, DYN_CNT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t *rel = (void *)(base+dyn[DT_REL]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t rel_size = dyn[DT_RELSZ]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t symbolic_rel_cnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	apply_addends_to = rel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (!IS_RELATIVE(rel[1])) symbolic_rel_cnt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (symbolic_rel_cnt >= ADDEND_LIMIT) a_crash(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t addends[symbolic_rel_cnt+1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	saved_addends = addends; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	head = &ldso; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	reloc_all(&ldso); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	ldso.relocated = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	ldso.rel_update_got = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* Call dynamic linker stage-3, __dls3, looking it up 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * symbolically as a barrier against moving the address 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * load across the above relocation processing. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	struct symdef dls3_def = find_sym(&ldso, "__dls3", 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	((stage3_func)(ldso.base+dls3_def.sym->st_value))(sp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- /* Stage 3 of the dynamic linker is called with the dynamic linker/libc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/__lctrans.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/__lctrans.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -16,5 +16,5 @@ const char *__lctrans(const char *msg, c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- const char *__lctrans_cur(const char *msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	return __lctrans_impl(msg, CURRENT_LOCALE->cat[LC_MESSAGES-2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return __lctrans_impl(msg, CURRENT_LOCALE->cat[LC_MESSAGES]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/__setlocalecat.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ /dev/null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,111 +0,0 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include <locale.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include "locale_impl.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--#include "atomic.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	const char *trans = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	return trans ? trans : msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--const unsigned char *__map_file(const char *, size_t *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--int __munmap(void *, size_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--char *__strchrnul(const char *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static struct __locale_map *findlocale(const char *name, size_t n) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	static void *volatile loc_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *p, *new, *old_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	const char *path = 0, *z; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	char buf[256]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	size_t l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	const void *map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	size_t map_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (p=loc_head; p; p=p->next) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (!strcmp(name, p->name)) return p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (!libc.secure) path = getenv("MUSL_LOCPATH"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	/* FIXME: add a default path? */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (!path) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (; *path; path=z+!!*z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		z = __strchrnul(path, ':'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		l = z - path - !!*z; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (l >= sizeof buf - n - 2) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		memcpy(buf, path, l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		buf[l] = '/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		memcpy(buf+l+1, name, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		buf[l+1+n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		map = __map_file(buf, &map_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (map) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			new = malloc(sizeof *new); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			if (!new) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				__munmap((void *)map, map_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			new->map = map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			new->map_size = map_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			memcpy(new->name, name, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			new->name[n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			do { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				old_head = loc_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				new->next = old_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			} while (a_cas_p(&loc_head, old_head, new) != old_head); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			return new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static const char envvars[][12] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_CTYPE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_NUMERIC", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_TIME", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_COLLATE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_MONETARY", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	"LC_MESSAGES", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--int __setlocalecat(locale_t loc, int cat, const char *val) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (!*val) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		(val = getenv("LC_ALL")) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		(val = getenv(envvars[cat])) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		(val = getenv("LANG")) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		(val = "C.UTF-8"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	size_t n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (val[0]=='.' || val[n]) val = "C.UTF-8"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	int builtin = (val[0]=='C' && !val[1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		|| !strcmp(val, "C.UTF-8") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		|| !strcmp(val, "POSIX"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *data, *old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	switch (cat) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_CTYPE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		a_store(&loc->ctype_utf8, !builtin || val[1]=='.'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_MESSAGES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (builtin) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			loc->messages_name[0] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			memcpy(loc->messages_name, val, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			loc->messages_name[n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		/* fall through */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		data = builtin ? 0 : findlocale(val, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (data == loc->cat[cat-2]) break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		do old = loc->cat[cat-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		while (a_cas_p(&loc->cat[cat-2], old, data) != old); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_NUMERIC: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/dcngettext.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/dcngettext.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -84,13 +84,15 @@ char *bindtextdomain(const char *domainn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static const char catnames[][12] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_CTYPE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_NUMERIC", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	"LC_TIME", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	"LC_COLLATE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	"LC_MONETARY", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	"LC_MESSAGES", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static const char catlens[] = { 7, 10, 11, 11 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static const char catlens[] = { 8, 10, 7, 10, 11, 11 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- struct msgcat { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct msgcat *next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -117,10 +119,12 @@ char *dcngettext(const char *domainname, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	static struct msgcat *volatile cats; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct msgcat *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	struct __locale_struct *loc = CURRENT_LOCALE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	const char *dirname, *locname, *catname; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t dirlen, loclen, catlen, domlen; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if ((unsigned)category >= LC_ALL) goto notrans; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (!domainname) domainname = __gettextdomain(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	domlen = strlen(domainname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -129,25 +133,15 @@ char *dcngettext(const char *domainname, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	dirname = gettextdir(domainname, &dirlen); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (!dirname) goto notrans; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	switch (category) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_MESSAGES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		locname = loc->messages_name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (!*locname) goto notrans; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_TIME: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_MONETARY: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_COLLATE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		lm = loc->cat[category-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (!lm) goto notrans; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		locname = lm->name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	lm = loc->cat[category]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!lm) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- notrans: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return (char *) ((n == 1) ? msgid1 : msgid2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	locname = lm->name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	catname = catnames[category-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	catlen = catlens[category-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	catname = catnames[category]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	catlen = catlens[category]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	loclen = strlen(locname); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	size_t namelen = dirlen+1 + loclen+1 + catlen+1 + domlen+3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/duplocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/duplocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -5,17 +5,10 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- locale_t __duplocale(locale_t old) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	locale_t new = calloc(1, sizeof *new + LOCALE_NAME_MAX + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	locale_t new = malloc(sizeof *new); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (!new) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	new->messages_name = (void *)(new+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (old == LC_GLOBAL_LOCALE) old = &libc.global_locale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	new->ctype_utf8 = old->ctype_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (old->messages_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		strcpy(new->messages_name, old->messages_name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (size_t i=0; i<sizeof new->cat/sizeof new->cat[0]; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		new->cat[i] = old->cat[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	*new = *old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/freelocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/freelocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -2,9 +2,11 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #include "locale_impl.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+int __loc_is_allocated(locale_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- void freelocale(locale_t l) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	free(l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__loc_is_allocated(l)) free(l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- weak_alias(freelocale, __freelocale); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/iconv.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/iconv.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -23,19 +23,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define BIG5        0340 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #define EUC_KR      0350 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--/* FIXME: these are not implemented yet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- * EUC:   A1-FE A1-FE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- * GBK:   81-FE 40-7E,80-FE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- * Big5:  A1-FE 40-7E,A1-FE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- /* Definitions of charmaps. Each charmap consists of: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  * 1. Empty-string-terminated list of null-terminated aliases. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  * 2. Special type code or number of elided entries. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  * 3. Character table (size determined by field 2). */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static const unsigned char charmaps[] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--"utf8\0\0\310" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+"utf8\0char\0\0\310" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "wchart\0\0\306" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "ucs2\0ucs2be\0\0\304" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- "ucs2le\0\0\305" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -90,6 +84,7 @@ static int fuzzycmp(const unsigned char 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- static size_t find_charmap(const void *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	const unsigned char *s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!*(char *)name) name=charmaps; /* "utf8" */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	for (s=charmaps; *s; ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		if (!fuzzycmp(name, s)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 			for (; *s; s+=strlen((void *)s)+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- /dev/null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/locale_map.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -0,0 +1,124 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include <locale.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "locale_impl.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+#include "atomic.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const char *trans = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return trans ? trans : msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+const unsigned char *__map_file(const char *, size_t *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+int __munmap(void *, size_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+char *__strchrnul(const char *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static const char envvars[][12] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_CTYPE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_NUMERIC", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_TIME", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_COLLATE", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"LC_MONETARY", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	"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]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	static void *volatile loc_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	struct __locale_map *new = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const char *path = 0, *z; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	char buf[256]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	size_t l, n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!*val) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		(val = getenv("LC_ALL")) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		(val = getenv(envvars[cat])) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		(val = getenv("LANG")) && *val || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		(val = "C.UTF-8"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* Limit name length and forbid leading dot or any slashes. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (val[0]=='.' || val[n]) val = "C.UTF-8"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int builtin = (val[0]=='C' && !val[1]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		|| !strcmp(val, "C.UTF-8") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		|| !strcmp(val, "POSIX"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (builtin) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (cat == LC_CTYPE && val[1]=='.') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			return (void *)&__c_dot_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (p=loc_head; p; p=p->next) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (!strcmp(val, p->name)) return p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	LOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (p=loc_head; p; p=p->next) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (!strcmp(val, p->name)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			UNLOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			return p; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!libc.secure) path = getenv("MUSL_LOCPATH"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* FIXME: add a default path? */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (path) for (; *path; path=z+!!*z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		z = __strchrnul(path, ':'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		l = z - path - !!*z; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (l >= sizeof buf - n - 2) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		memcpy(buf, path, l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		buf[l] = '/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		memcpy(buf+l+1, val, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		buf[l+1+n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		size_t map_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		const void *map = __map_file(buf, &map_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (map) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			new = malloc(sizeof *new); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			if (!new) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				__munmap((void *)map, map_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			new->map = map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			new->map_size = map_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			memcpy(new->name, val, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			new->name[n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			new->next = loc_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			loc_head = new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* If no locale definition was found, make a locale map 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * object anyway to store the name, which is kept for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		memcpy(new->name, val, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		new->name[n] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		new->next = loc_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		loc_head = new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* For LC_CTYPE, never return a null pointer unless the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * requested name was "C" or "POSIX". */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	UNLOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/newlocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/newlocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -3,22 +3,52 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- locale_t __newlocale(int mask, const char *name, locale_t loc) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	int i, j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	struct __locale_struct tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (!loc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		loc = calloc(1, sizeof *loc + LOCALE_NAME_MAX + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (!loc) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		loc->messages_name = (void *)(loc+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* For locales with allocated storage, modify in-place. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (__loc_is_allocated(loc)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		for (i=0; i<LC_ALL; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			if (!(mask & (1<<i))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				__setlocalecat(loc, i, ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			if (mask & (1<<i)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				loc->cat[i] = __get_locale(i, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		return loc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	/* Otherwise, build a temporary locale object, which will only 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * be instantiated in allocated storage if it does not match 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * one of the built-in static locales. This makes the common 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * usage case for newlocale, getting a C locale with predictable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	 * behavior, very fast, and more importantly, fail-safe. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	for (j=i=0; i<LC_ALL; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (loc && !(mask & (1<<i))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			lm = loc->cat[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			lm = __get_locale(i, mask & (1<<i) ? name : ""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		if (lm) j++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		tmp.cat[i] = lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	for (i=0; i<LC_ALL; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (mask & (1<<i)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			__setlocalecat(loc, i, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if ((loc = malloc(sizeof *loc))) *loc = tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return loc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/setlocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/setlocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -5,73 +5,66 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #include "libc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #include "atomic.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--static char buf[2+4*(LOCALE_NAME_MAX+1)]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static char buf[LC_ALL*(LOCALE_NAME_MAX+1)]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--char *setlocale(int cat, const char *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+static char *setlocale_one_unlocked(int cat, const char *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	struct __locale_map *lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	int i, j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	const struct __locale_map *lm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (!libc.global_locale.messages_name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		libc.global_locale.messages_name = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			buf + 2 + 3*(LOCALE_NAME_MAX+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (name) libc.global_locale.cat[cat] = lm = __get_locale(cat, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	else lm = libc.global_locale.cat[cat]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return lm ? (char *)lm->name : "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+char *__strchrnul(const char *, int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+char *setlocale(int cat, const char *name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	static volatile int lock[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if ((unsigned)cat > LC_ALL) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	LOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	/* For LC_ALL, setlocale is required to return a string which 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * encodes the current setting for all categories. The format of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * this string is unspecified, and only the following code, which 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * performs both the serialization and deserialization, depends 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * on the format, so it can easily be changed if needed. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (cat == LC_ALL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		if (name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			char part[LOCALE_NAME_MAX+1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			if (name[0] && name[1]==';' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			    && strlen(name) > 2 + 3*(LOCALE_NAME_MAX+1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				part[0] = name[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				part[1] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				setlocale(LC_CTYPE, part); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				part[LOCALE_NAME_MAX] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				for (i=LC_TIME; i<LC_MESSAGES; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--					memcpy(part, name + 2 + (i-2)*(LOCALE_NAME_MAX+1), LOCALE_NAME_MAX); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--					for (j=LOCALE_NAME_MAX-1; j && part[j]==';'; j--) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--						part[j] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--					setlocale(i, part); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			char part[LOCALE_NAME_MAX+1] = "C.UTF-8"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			const char *p = name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			for (i=0; i<LC_ALL; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				const char *z = __strchrnul(p, ';'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				if (z-p <= LOCALE_NAME_MAX) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+					memcpy(part, p, z-p); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+					part[z-p] = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+					if (*z) p = z+1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				setlocale(LC_MESSAGES, name + 2 + 3*(LOCALE_NAME_MAX+1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				for (i=0; i<LC_ALL; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--					setlocale(i, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				setlocale_one_unlocked(i, part); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		memset(buf, ';', 2 + 3*(LOCALE_NAME_MAX+1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		buf[0] = libc.global_locale.ctype_utf8 ? 'U' : 'C'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		for (i=LC_TIME; i<LC_MESSAGES; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			lm = libc.global_locale.cat[i-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			if (lm) memcpy(buf + 2 + (i-2)*(LOCALE_NAME_MAX+1), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--				lm->name, strlen(lm->name)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		char *s = buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		for (i=0; i<LC_ALL; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			const struct __locale_map *lm = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+				libc.global_locale.cat[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			const char *part = lm ? lm->name : "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			size_t l = strlen(part); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			memcpy(s, part, l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			s[l] = ';'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+			s += l+1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		*--s = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		UNLOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		int adj = libc.global_locale.ctype_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		__setlocalecat(&libc.global_locale, cat, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		adj -= libc.global_locale.ctype_utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (adj) a_fetch_add(&libc.bytelocale_cnt_minus_1, adj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	char *ret = setlocale_one_unlocked(cat, name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	switch (cat) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_CTYPE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		return libc.global_locale.ctype_utf8 ? "C.UTF-8" : "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_NUMERIC: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		return "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	case LC_MESSAGES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		return libc.global_locale.messages_name[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			? libc.global_locale.messages_name : "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		lm = libc.global_locale.cat[cat-2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		return lm ? lm->name : "C"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	UNLOCK(lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/locale/uselocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/locale/uselocale.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -10,15 +10,7 @@ locale_t __uselocale(locale_t new) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (new == LC_GLOBAL_LOCALE) new = global; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (new && new != old) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		int adj = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (new == global) a_dec(&libc.uselocale_cnt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		else if (!new->ctype_utf8) adj++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (old == global) a_inc(&libc.uselocale_cnt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		else if (!old->ctype_utf8) adj--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		a_fetch_add(&libc.bytelocale_cnt_minus_1, adj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		self->locale = new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	self->locale = new; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return old == global ? LC_GLOBAL_LOCALE : old; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/stdio/__stdio_read.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/stdio/__stdio_read.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -21,7 +21,6 @@ size_t __stdio_read(FILE *f, unsigned ch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	pthread_cleanup_pop(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (cnt <= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		f->rpos = f->rend = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return cnt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (cnt <= iov[0].iov_len) return cnt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/stdio/__toread.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/stdio/__toread.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -5,12 +5,12 @@ int __toread(FILE *f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	f->mode |= f->mode-1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	if (f->wpos > f->buf) f->write(f, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	f->wpos = f->wbase = f->wend = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (f->flags & (F_EOF|F_NORD)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (f->flags & F_NORD) f->flags |= F_ERR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (f->flags & F_NORD) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+		f->flags |= F_ERR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return EOF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	f->rpos = f->rend = f->buf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	f->rpos = f->rend = f->buf + f->buf_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	return (f->flags & F_EOF) ? EOF : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- void __stdio_exit_needed(void); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/stdio/__uflow.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/stdio/__uflow.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -1,11 +1,11 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- #include "stdio_impl.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--/* This function will never be called if there is already data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- * buffered for reading. Thus we can get by with very few branches. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+/* This function assumes it will never be called if there is already 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ * data buffered for reading. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- int __uflow(FILE *f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	unsigned char c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if ((f->rend || !__toread(f)) && f->read(f, &c, 1)==1) return c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!__toread(f) && f->read(f, &c, 1)==1) return c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	return EOF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/stdio/ungetc.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/stdio/ungetc.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -6,7 +6,8 @@ int ungetc(int c, FILE *f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	FLOCK(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if ((!f->rend && __toread(f)) || f->rpos <= f->buf - UNGET) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!f->rpos) __toread(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!f->rpos || f->rpos <= f->buf - UNGET) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		FUNLOCK(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return EOF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/stdio/ungetwc.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/stdio/ungetwc.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -19,7 +19,8 @@ wint_t ungetwc(wint_t c, FILE *f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	f->mode |= f->mode+1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if ((!f->rend && __toread(f)) || f->rpos < f->buf - UNGET + l) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!f->rpos) __toread(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	if (!f->rpos || f->rpos < f->buf - UNGET + l) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		FUNLOCK(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		return EOF; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/thread/i386/__set_thread_area.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/thread/i386/__set_thread_area.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -6,10 +6,10 @@ __set_thread_area: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	push $0x51 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	push $0xfffff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	push 16(%esp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	xor %edx,%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	mov %gs,%dx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	sub $3,%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	sar $3,%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	call 1f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+1:	addl $4f-1b,(%esp) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	pop %ecx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	mov (%ecx),%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	push %edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	mov %esp,%ebx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	xor %eax,%eax 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -18,6 +18,7 @@ __set_thread_area: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	testl %eax,%eax 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	jnz 2f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	movl (%esp),%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	movl %edx,(%ecx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	leal 3(,%edx,8),%edx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 3:	movw %dx,%gs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -38,3 +39,7 @@ __set_thread_area: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	mov $7,%dl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	inc %al 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	jmp 3b 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+	.align 4 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+4:	.long -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/thread/mips/syscall_cp.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/thread/mips/syscall_cp.s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -2,10 +2,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global __cp_begin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .hidden __cp_begin 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type   __cp_begin,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global __cp_end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .hidden __cp_end 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type   __cp_end,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global __cp_cancel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .hidden __cp_cancel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+.type   __cp_cancel,@function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .hidden __cancel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .global __syscall_cp_asm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- .hidden __syscall_cp_asm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				---- a/src/thread/pthread_create.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-+++ b/src/thread/pthread_create.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-@@ -67,12 +67,6 @@ _Noreturn void __pthread_exit(void *resu 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 		exit(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	if (self->locale != &libc.global_locale) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		a_dec(&libc.uselocale_cnt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--		if (self->locale->ctype_utf8) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--			a_dec(&libc.bytelocale_cnt_minus_1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				--	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	/* Process robust list in userspace to handle non-pshared mutexes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * and the detached thread case where the robust list head will 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 	 * be invalid when the kernel would process it. */ 
			 |