Compare commits
	
		
			334 Commits
		
	
	
		
			marshmallo
			...
			android-m-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b4f2112fa9 | ||
| 
						 | 
					61d9ae5ab1 | ||
| 
						 | 
					f2985ed840 | ||
| 
						 | 
					2b93492478 | ||
| 
						 | 
					a40a21110d | ||
| 
						 | 
					3fe1515e38 | ||
| 
						 | 
					a3c01467ec | ||
| 
						 | 
					5341691955 | ||
| 
						 | 
					ff4afc136e | ||
| 
						 | 
					182b91f628 | ||
| 
						 | 
					bf830ade7f | ||
| 
						 | 
					5891abdc66 | ||
| 
						 | 
					e80369ab0c | ||
| 
						 | 
					b3db7764d0 | ||
| 
						 | 
					f57f794515 | ||
| 
						 | 
					17379d2b08 | ||
| 
						 | 
					2278d29ada | ||
| 
						 | 
					516fcb28f2 | ||
| 
						 | 
					7e919daeaa | ||
| 
						 | 
					9101b00400 | ||
| 
						 | 
					0acb15ead6 | ||
| 
						 | 
					2590705858 | ||
| 
						 | 
					c46c0e960d | ||
| 
						 | 
					61c21b63bc | ||
| 
						 | 
					4c43aac9a5 | ||
| 
						 | 
					442a3fcae6 | ||
| 
						 | 
					89a121d43a | ||
| 
						 | 
					807f27f954 | ||
| 
						 | 
					9f03ed12a6 | ||
| 
						 | 
					4498917406 | ||
| 
						 | 
					b447440a4b | ||
| 
						 | 
					34c5f5eacd | ||
| 
						 | 
					36443fd542 | ||
| 
						 | 
					9bbb5a7a09 | ||
| 
						 | 
					374adfee47 | ||
| 
						 | 
					5390173ad4 | ||
| 
						 | 
					1ff4094a7f | ||
| 
						 | 
					820a86f2df | ||
| 
						 | 
					c8ba22c847 | ||
| 
						 | 
					afab3ffcce | ||
| 
						 | 
					1923d4c03a | ||
| 
						 | 
					667dc75ee1 | ||
| 
						 | 
					4955cde2c5 | ||
| 
						 | 
					d2a9fb3267 | ||
| 
						 | 
					cebef1a781 | ||
| 
						 | 
					7656d0cec0 | ||
| 
						 | 
					e8ceb95c68 | ||
| 
						 | 
					8af3263349 | ||
| 
						 | 
					f16c6e17b2 | ||
| 
						 | 
					8264cbba7e | ||
| 
						 | 
					bff1968222 | ||
| 
						 | 
					f0a73476a1 | ||
| 
						 | 
					ec83a61c8b | ||
| 
						 | 
					adc5795fb7 | ||
| 
						 | 
					189394b885 | ||
| 
						 | 
					a3a619835d | ||
| 
						 | 
					fed2659869 | ||
| 
						 | 
					795a8e3d69 | ||
| 
						 | 
					9e1c862cb6 | ||
| 
						 | 
					1661125315 | ||
| 
						 | 
					2565492db0 | ||
| 
						 | 
					c4786d366b | ||
| 
						 | 
					3b49d61ac2 | ||
| 
						 | 
					10726d52ac | ||
| 
						 | 
					86ac443cd1 | ||
| 
						 | 
					361d4b4c87 | ||
| 
						 | 
					bc0b8ff2fb | ||
| 
						 | 
					d29486343a | ||
| 
						 | 
					c99fabb7a0 | ||
| 
						 | 
					3bcfd47c68 | ||
| 
						 | 
					f37c237b8b | ||
| 
						 | 
					95fd031c4d | ||
| 
						 | 
					613f814508 | ||
| 
						 | 
					e70d7a78f0 | ||
| 
						 | 
					3fef96f827 | ||
| 
						 | 
					e5544ae1f8 | ||
| 
						 | 
					6c9ad82b1c | ||
| 
						 | 
					1946856b1f | ||
| 
						 | 
					a7a87dda4a | ||
| 
						 | 
					4f2e1d3b1e | ||
| 
						 | 
					2cc41d3e00 | ||
| 
						 | 
					ca7bc509cf | ||
| 
						 | 
					df1a3c6d21 | ||
| 
						 | 
					a58d249840 | ||
| 
						 | 
					e5cfafe344 | ||
| 
						 | 
					70b6e1daff | ||
| 
						 | 
					60bc90909a | ||
| 
						 | 
					0875ba3095 | ||
| 
						 | 
					cd588f847f | ||
| 
						 | 
					730ed9dfec | ||
| 
						 | 
					b31409040f | ||
| 
						 | 
					d11c3e5c3a | ||
| 
						 | 
					e9774a5227 | ||
| 
						 | 
					d640b225ec | ||
| 
						 | 
					60a11dcb44 | ||
| 
						 | 
					91ce715af1 | ||
| 
						 | 
					a8d82f126d | ||
| 
						 | 
					dda4fd4644 | ||
| 
						 | 
					5e3dc45a16 | ||
| 
						 | 
					3a40a0000a | ||
| 
						 | 
					147a50d06e | ||
| 
						 | 
					a20a35fdda | ||
| 
						 | 
					880a293390 | ||
| 
						 | 
					d1e10d7d16 | ||
| 
						 | 
					4d44675283 | ||
| 
						 | 
					609f11b31e | ||
| 
						 | 
					c6f25641eb | ||
| 
						 | 
					e55151472b | ||
| 
						 | 
					33ef6c20f2 | ||
| 
						 | 
					90de6820f7 | ||
| 
						 | 
					e1e434af12 | ||
| 
						 | 
					0cdef7e7f3 | ||
| 
						 | 
					7a9732d663 | ||
| 
						 | 
					7ea817d39e | ||
| 
						 | 
					89bbb846b9 | ||
| 
						 | 
					dbb17b2831 | ||
| 
						 | 
					f542b30970 | ||
| 
						 | 
					eeb6b57e75 | ||
| 
						 | 
					77455f85ab | ||
| 
						 | 
					86061f39c2 | ||
| 
						 | 
					416695a75c | ||
| 
						 | 
					c2247478d5 | ||
| 
						 | 
					b9f76dc829 | ||
| 
						 | 
					7f46cf9a5f | ||
| 
						 | 
					83474cd387 | ||
| 
						 | 
					7271caf93d | ||
| 
						 | 
					46d24d12e1 | ||
| 
						 | 
					25da2d7ca2 | ||
| 
						 | 
					59d5854d14 | ||
| 
						 | 
					71107cdd02 | ||
| 
						 | 
					a05bee544a | ||
| 
						 | 
					01e37c9665 | ||
| 
						 | 
					eeb9f5e416 | ||
| 
						 | 
					3f987f5b3e | ||
| 
						 | 
					56f40fbb82 | ||
| 
						 | 
					d19c271599 | ||
| 
						 | 
					6589febec2 | ||
| 
						 | 
					fef58353f4 | ||
| 
						 | 
					bc425c73e0 | ||
| 
						 | 
					c666838ad6 | ||
| 
						 | 
					cc83890464 | ||
| 
						 | 
					d807b9a12d | ||
| 
						 | 
					e79d06b0e8 | ||
| 
						 | 
					af6ee5b5bc | ||
| 
						 | 
					aff18fd608 | ||
| 
						 | 
					7d09a8cd11 | ||
| 
						 | 
					a8993c994e | ||
| 
						 | 
					e4ad91f86a | ||
| 
						 | 
					13cee57dee | ||
| 
						 | 
					de4e27e231 | ||
| 
						 | 
					6a5ead6990 | ||
| 
						 | 
					d02ec08427 | ||
| 
						 | 
					6cc98af72b | ||
| 
						 | 
					d1ade7ce02 | ||
| 
						 | 
					547fa54e6d | ||
| 
						 | 
					a9703332f6 | ||
| 
						 | 
					bfa601a999 | ||
| 
						 | 
					9ae6f794ca | ||
| 
						 | 
					d2c81ed000 | ||
| 
						 | 
					f448ef491c | ||
| 
						 | 
					61cbd02f10 | ||
| 
						 | 
					455c145e3c | ||
| 
						 | 
					3b5a4b0c33 | ||
| 
						 | 
					dee130f598 | ||
| 
						 | 
					38f2eaa07b | ||
| 
						 | 
					81b2382df6 | ||
| 
						 | 
					895241efbb | ||
| 
						 | 
					b628b7db39 | ||
| 
						 | 
					11ea08c5cb | ||
| 
						 | 
					9876aa273d | ||
| 
						 | 
					48fa28bacd | ||
| 
						 | 
					cd1be3b69e | ||
| 
						 | 
					665607a6b7 | ||
| 
						 | 
					a73b2c961f | ||
| 
						 | 
					b1304935b6 | ||
| 
						 | 
					636f5ddddc | ||
| 
						 | 
					df11f340ca | ||
| 
						 | 
					0577733c2e | ||
| 
						 | 
					27f5c37b12 | ||
| 
						 | 
					333bdad361 | ||
| 
						 | 
					469b418784 | ||
| 
						 | 
					bf18c61798 | ||
| 
						 | 
					713ae464ab | ||
| 
						 | 
					402a75060d | ||
| 
						 | 
					9ef26a3c4c | ||
| 
						 | 
					173ad0a53e | ||
| 
						 | 
					b90e9b7183 | ||
| 
						 | 
					175dae92d7 | ||
| 
						 | 
					c910de9d5e | ||
| 
						 | 
					be57a40d29 | ||
| 
						 | 
					db68b4600d | ||
| 
						 | 
					bd3b961186 | ||
| 
						 | 
					72af1235e4 | ||
| 
						 | 
					6865082ca6 | ||
| 
						 | 
					ba1d40a3f1 | ||
| 
						 | 
					f3463db7eb | ||
| 
						 | 
					6a494915d7 | ||
| 
						 | 
					60907c7f4e | ||
| 
						 | 
					1801db3d3f | ||
| 
						 | 
					1cfbd94a2f | ||
| 
						 | 
					8a11628355 | ||
| 
						 | 
					866d6fb090 | ||
| 
						 | 
					4900f1c4cd | ||
| 
						 | 
					624b8f17a1 | ||
| 
						 | 
					12fb28bbd8 | ||
| 
						 | 
					d9dc13d417 | ||
| 
						 | 
					e1d0810cd7 | ||
| 
						 | 
					f9554a1776 | ||
| 
						 | 
					966f84b11d | ||
| 
						 | 
					19fee2ca8b | ||
| 
						 | 
					12ca831b0e | ||
| 
						 | 
					9cf6fc304b | ||
| 
						 | 
					b68b8b4b95 | ||
| 
						 | 
					c062218a9b | ||
| 
						 | 
					5cce2e7205 | ||
| 
						 | 
					6cda074289 | ||
| 
						 | 
					3931b6d9b3 | ||
| 
						 | 
					1913352c6b | ||
| 
						 | 
					11b15b23aa | ||
| 
						 | 
					75108f4f83 | ||
| 
						 | 
					ef55f96723 | ||
| 
						 | 
					e7deb145c6 | ||
| 
						 | 
					2825f10b7f | ||
| 
						 | 
					f439b5a318 | ||
| 
						 | 
					ef607cdae2 | ||
| 
						 | 
					9d476a02e9 | ||
| 
						 | 
					d70891687d | ||
| 
						 | 
					5511551009 | ||
| 
						 | 
					6c2dba8651 | ||
| 
						 | 
					d974e88046 | ||
| 
						 | 
					087005f37e | ||
| 
						 | 
					d717b1a3e5 | ||
| 
						 | 
					79fd668bb4 | ||
| 
						 | 
					560aacee84 | ||
| 
						 | 
					1011e1a402 | ||
| 
						 | 
					fad15145f8 | ||
| 
						 | 
					41c99cdbb9 | ||
| 
						 | 
					3cec6eca92 | ||
| 
						 | 
					aaafbe128f | ||
| 
						 | 
					b96ac41b32 | ||
| 
						 | 
					ffe01a3de6 | ||
| 
						 | 
					4fc106d34b | ||
| 
						 | 
					b0c6f2dba2 | ||
| 
						 | 
					c05554ec5c | ||
| 
						 | 
					c02bdc76a2 | ||
| 
						 | 
					40a8f214a5 | ||
| 
						 | 
					a42b5bcd89 | ||
| 
						 | 
					9185e04f72 | ||
| 
						 | 
					882283e9e2 | ||
| 
						 | 
					4e8ef698d0 | ||
| 
						 | 
					1d52b8b07c | ||
| 
						 | 
					b00c23a8db | ||
| 
						 | 
					e77e335b54 | ||
| 
						 | 
					933332462d | ||
| 
						 | 
					0378d8f651 | ||
| 
						 | 
					706eafc9b0 | ||
| 
						 | 
					0346ad7a4f | ||
| 
						 | 
					c217373bd6 | ||
| 
						 | 
					fe77d2d003 | ||
| 
						 | 
					697bd9fd38 | ||
| 
						 | 
					d0763ba076 | ||
| 
						 | 
					f58ac87182 | ||
| 
						 | 
					3ff027e550 | ||
| 
						 | 
					7e54c762fc | ||
| 
						 | 
					8a330cad8d | ||
| 
						 | 
					c69ace87ec | ||
| 
						 | 
					972d7fe63a | ||
| 
						 | 
					33f33515b5 | ||
| 
						 | 
					c9310266dc | ||
| 
						 | 
					ec738d9494 | ||
| 
						 | 
					75f2dfca65 | ||
| 
						 | 
					4e8cda641a | ||
| 
						 | 
					267f39bf63 | ||
| 
						 | 
					88e777d6f4 | ||
| 
						 | 
					11fc3f47af | ||
| 
						 | 
					a924d4ba26 | ||
| 
						 | 
					7d6b8db28e | ||
| 
						 | 
					ce16a53d39 | ||
| 
						 | 
					f9eeea6d65 | ||
| 
						 | 
					2957cc5f10 | ||
| 
						 | 
					ded34ce94f | ||
| 
						 | 
					7c2c01d681 | ||
| 
						 | 
					6f0d7005f9 | ||
| 
						 | 
					f920f821e2 | ||
| 
						 | 
					dc10b077ea | ||
| 
						 | 
					e543c7612e | ||
| 
						 | 
					9c1894186c | ||
| 
						 | 
					3edb9182ff | ||
| 
						 | 
					fff06e624d | ||
| 
						 | 
					5624a6a1e5 | ||
| 
						 | 
					c95a9e9dad | ||
| 
						 | 
					406d99665c | ||
| 
						 | 
					f3392791bc | ||
| 
						 | 
					dbe26fdcc7 | ||
| 
						 | 
					2c3d8d8b2c | ||
| 
						 | 
					4637f3d66d | ||
| 
						 | 
					64a8698809 | ||
| 
						 | 
					7fbd6355ae | ||
| 
						 | 
					f39cb63603 | ||
| 
						 | 
					7e4bbbae4a | ||
| 
						 | 
					788ea593ec | ||
| 
						 | 
					31b408d2c2 | ||
| 
						 | 
					033a68f1ac | ||
| 
						 | 
					6a4c9d9bf9 | ||
| 
						 | 
					df877d7b28 | ||
| 
						 | 
					18c935ceab | ||
| 
						 | 
					f29640c2d8 | ||
| 
						 | 
					c6b9b254dc | ||
| 
						 | 
					0373d4f473 | ||
| 
						 | 
					c3f4c964a3 | ||
| 
						 | 
					fa6f649607 | ||
| 
						 | 
					e1a61f5e93 | ||
| 
						 | 
					0bf650373e | ||
| 
						 | 
					11331f60dd | ||
| 
						 | 
					f8093a9485 | ||
| 
						 | 
					b4e5067cab | ||
| 
						 | 
					b904afa16e | ||
| 
						 | 
					9f0d99d298 | ||
| 
						 | 
					62d6533c1a | ||
| 
						 | 
					bed7a7e5eb | ||
| 
						 | 
					a85bcc2e99 | ||
| 
						 | 
					6fa65e7cd5 | ||
| 
						 | 
					e0905c94d3 | ||
| 
						 | 
					520cbf51b1 | ||
| 
						 | 
					42d7468f99 | ||
| 
						 | 
					b293969c6d | ||
| 
						 | 
					032907d8c7 | ||
| 
						 | 
					2ea504fed1 | ||
| 
						 | 
					59bce688c7 | ||
| 
						 | 
					bfd65279a5 | ||
| 
						 | 
					682a240c5d | ||
| 
						 | 
					6f88821e5d | ||
| 
						 | 
					d2177404e2 | ||
| 
						 | 
					0a93df369c | 
@@ -194,14 +194,15 @@ The tests are all built from the tests/ directory.
 | 
				
			|||||||
### Device tests
 | 
					### Device tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $ mma
 | 
					    $ mma
 | 
				
			||||||
 | 
					    $ adb remount
 | 
				
			||||||
    $ adb sync
 | 
					    $ adb sync
 | 
				
			||||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
					    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
				
			||||||
    $ adb shell \
 | 
					    $ adb shell \
 | 
				
			||||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
 | 
					        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
 | 
				
			||||||
    # Only for 64-bit targets
 | 
					    # Only for 64-bit targets
 | 
				
			||||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
 | 
					    $ adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests64
 | 
				
			||||||
    $ adb shell \
 | 
					    $ adb shell \
 | 
				
			||||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
					        /data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Host tests
 | 
					### Host tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,6 @@ benchmark_cflags := \
 | 
				
			|||||||
    -Wunused \
 | 
					    -Wunused \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
benchmark_cppflags := \
 | 
					benchmark_cppflags := \
 | 
				
			||||||
    -std=gnu++11 \
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
benchmarklib_src_files := \
 | 
					benchmarklib_src_files := \
 | 
				
			||||||
    Benchmark.cpp \
 | 
					    Benchmark.cpp \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdio_ext.h>
 | 
					#include <stdio_ext.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <benchmark/Benchmark.h>
 | 
					#include <benchmark/Benchmark.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,7 +74,7 @@ static void FopenFgetsFclose(int iters, bool no_locking) {
 | 
				
			|||||||
  for (int i = 0; i < iters; ++i) {
 | 
					  for (int i = 0; i < iters; ++i) {
 | 
				
			||||||
    FILE* fp = fopen("/proc/version", "re");
 | 
					    FILE* fp = fopen("/proc/version", "re");
 | 
				
			||||||
    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
					    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
				
			||||||
    fgets(buf, sizeof(buf), fp);
 | 
					    if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
 | 
				
			||||||
    fclose(fp);
 | 
					    fclose(fp);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
#include <sys/syscall.h>
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
#include <sys/time.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <benchmark/Benchmark.h>
 | 
					#include <benchmark/Benchmark.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,8 @@
 | 
				
			|||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
@@ -21,7 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "utils.h"
 | 
					#include <base/stringprintf.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Round(int n) {
 | 
					int Round(int n) {
 | 
				
			||||||
  int base = 1;
 | 
					  int base = 1;
 | 
				
			||||||
@@ -72,10 +74,7 @@ std::string PrettyInt(long value, size_t base) {
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  char* s = NULL;
 | 
					  return android::base::StringPrintf("%s%" PRId64 "%s",
 | 
				
			||||||
  asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
 | 
					                                     negative_number ? "-" : "",
 | 
				
			||||||
                                     count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
					                                     count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
				
			||||||
  std::string result(s);
 | 
					 | 
				
			||||||
  free(s);
 | 
					 | 
				
			||||||
  return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,9 @@ libc_common_src_files := \
 | 
				
			|||||||
libc_common_src_files += \
 | 
					libc_common_src_files += \
 | 
				
			||||||
    bionic/__FD_chk.cpp \
 | 
					    bionic/__FD_chk.cpp \
 | 
				
			||||||
    bionic/__fgets_chk.cpp \
 | 
					    bionic/__fgets_chk.cpp \
 | 
				
			||||||
 | 
					    bionic/__fread_chk.cpp \
 | 
				
			||||||
 | 
					    bionic/__fwrite_chk.cpp \
 | 
				
			||||||
 | 
					    bionic/__getcwd_chk.cpp \
 | 
				
			||||||
    bionic/__memchr_chk.cpp \
 | 
					    bionic/__memchr_chk.cpp \
 | 
				
			||||||
    bionic/__memmove_chk.cpp \
 | 
					    bionic/__memmove_chk.cpp \
 | 
				
			||||||
    bionic/__memrchr_chk.cpp \
 | 
					    bionic/__memrchr_chk.cpp \
 | 
				
			||||||
@@ -130,6 +133,7 @@ libc_bionic_ndk_src_files := \
 | 
				
			|||||||
    bionic/fchmodat.cpp \
 | 
					    bionic/fchmodat.cpp \
 | 
				
			||||||
    bionic/ffs.cpp \
 | 
					    bionic/ffs.cpp \
 | 
				
			||||||
    bionic/fgetxattr.cpp \
 | 
					    bionic/fgetxattr.cpp \
 | 
				
			||||||
 | 
					    bionic/flistxattr.cpp \
 | 
				
			||||||
    bionic/flockfile.cpp \
 | 
					    bionic/flockfile.cpp \
 | 
				
			||||||
    bionic/fpclassify.cpp \
 | 
					    bionic/fpclassify.cpp \
 | 
				
			||||||
    bionic/fsetxattr.cpp \
 | 
					    bionic/fsetxattr.cpp \
 | 
				
			||||||
@@ -309,7 +313,6 @@ libc_upstream_netbsd_src_files := \
 | 
				
			|||||||
    upstream-netbsd/lib/libc/stdlib/nrand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/nrand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/_rand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/_rand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/rand_r.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/rand_r.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/reallocarr.c \
 | 
					 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/seed48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/seed48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/srand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/srand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/string/memccpy.c \
 | 
					    upstream-netbsd/lib/libc/string/memccpy.c \
 | 
				
			||||||
@@ -575,11 +578,14 @@ libc_common_cflags := \
 | 
				
			|||||||
    -D_LIBC=1 \
 | 
					    -D_LIBC=1 \
 | 
				
			||||||
    -Wall -Wextra -Wunused \
 | 
					    -Wall -Wextra -Wunused \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifneq ($(TARGET_USES_LOGD),false)
 | 
					use_clang := $(USE_CLANG_PLATFORM_BUILD)
 | 
				
			||||||
libc_common_cflags += -DTARGET_USES_LOGD
 | 
					
 | 
				
			||||||
 | 
					# Clang/llvm has incompatible long double (fp128) for x86_64.
 | 
				
			||||||
 | 
					# https://llvm.org/bugs/show_bug.cgi?id=23897
 | 
				
			||||||
 | 
					ifeq ($(TARGET_ARCH),x86_64)
 | 
				
			||||||
 | 
					  use_clang := false
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use_clang := $(USE_CLANG_PLATFORM_BUILD)
 | 
					 | 
				
			||||||
ifeq ($(use_clang),)
 | 
					ifeq ($(use_clang),)
 | 
				
			||||||
  use_clang := false
 | 
					  use_clang := false
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
@@ -617,7 +623,6 @@ libc_common_conlyflags := \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Define some common cppflags
 | 
					# Define some common cppflags
 | 
				
			||||||
libc_common_cppflags := \
 | 
					libc_common_cppflags := \
 | 
				
			||||||
    -std=gnu++11
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Define some common includes
 | 
					# Define some common includes
 | 
				
			||||||
# ========================================================
 | 
					# ========================================================
 | 
				
			||||||
@@ -658,7 +663,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -699,7 +704,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -745,7 +750,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -778,7 +783,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -813,7 +818,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -854,7 +859,7 @@ LOCAL_MODULE := libc_openbsd_ndk
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -892,7 +897,7 @@ LOCAL_MODULE := libc_openbsd
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -930,7 +935,7 @@ LOCAL_MODULE := libc_gdtoa
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -955,7 +960,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -983,7 +988,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1004,7 +1009,7 @@ LOCAL_CLANG := false
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
@@ -1031,7 +1036,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
@@ -1055,7 +1060,7 @@ LOCAL_CLANG := true # GCC refuses to hide new/delete
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
# b/17574078: Need to disable coverage until we have a prebuilt libprofile_rt.
 | 
					# b/17574078: Need to disable coverage until we have a prebuilt libprofile_rt.
 | 
				
			||||||
# Since this is a static library built with clang, it needs to link
 | 
					# Since this is a static library built with clang, it needs to link
 | 
				
			||||||
# libprofile_rt when it is linked into the final binary. Since the final binary
 | 
					# libprofile_rt when it is linked into the final binary. Since the final binary
 | 
				
			||||||
@@ -1083,7 +1088,7 @@ LOCAL_CLANG := $(use_clang)
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
@@ -1105,7 +1110,7 @@ LOCAL_CFLAGS := $(libc_common_cflags) -fno-builtin
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
@@ -1131,7 +1136,7 @@ LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 | 
				
			|||||||
LOCAL_CFLAGS := $(libc_common_cflags) -fvisibility=hidden -O0
 | 
					LOCAL_CFLAGS := $(libc_common_cflags) -fvisibility=hidden -O0
 | 
				
			||||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
 | 
					LOCAL_CPPFLAGS := $(libc_common_cppflags)
 | 
				
			||||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
					LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1215,7 +1220,7 @@ LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# TODO: split out the asflags.
 | 
					# TODO: split out the asflags.
 | 
				
			||||||
LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 | 
					LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1253,7 +1258,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			|||||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 | 
					LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1276,7 +1281,7 @@ LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
				
			|||||||
LOCAL_MODULE := libc_malloc
 | 
					LOCAL_MODULE := libc_malloc
 | 
				
			||||||
LOCAL_CLANG := $(use_clang)
 | 
					LOCAL_CLANG := $(use_clang)
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
@@ -1309,7 +1314,7 @@ endif
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1391,7 +1396,7 @@ LOCAL_CFLAGS_arm += -DCRT_LEGACY_WORKAROUND
 | 
				
			|||||||
LOCAL_SRC_FILES_arm += \
 | 
					LOCAL_SRC_FILES_arm += \
 | 
				
			||||||
    arch-arm/bionic/atexit_legacy.c
 | 
					    arch-arm/bionic/atexit_legacy.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BUILD_SHARED_LIBRARY)
 | 
					include $(BUILD_SHARED_LIBRARY)
 | 
				
			||||||
@@ -1445,7 +1450,7 @@ LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Don't install on release build
 | 
					# Don't install on release build
 | 
				
			||||||
LOCAL_MODULE_TAGS := eng debug
 | 
					LOCAL_MODULE_TAGS := eng debug
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1485,7 +1490,7 @@ LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Don't install on release build
 | 
					# Don't install on release build
 | 
				
			||||||
LOCAL_MODULE_TAGS := eng debug
 | 
					LOCAL_MODULE_TAGS := eng debug
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
					$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
				
			||||||
@@ -1516,7 +1521,7 @@ LOCAL_MODULE:= libstdc++
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
include $(BUILD_SHARED_LIBRARY)
 | 
					include $(BUILD_SHARED_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1532,7 +1537,7 @@ LOCAL_MODULE:= libstdc++
 | 
				
			|||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,6 @@ int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*)  arm,mips,x8
 | 
				
			|||||||
int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 | 
					int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 | 
				
			||||||
int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 | 
					int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 | 
				
			||||||
int     setpgid(pid_t, pid_t)  all
 | 
					int     setpgid(pid_t, pid_t)  all
 | 
				
			||||||
pid_t   vfork(void)  arm
 | 
					 | 
				
			||||||
int     setregid:setregid32(gid_t, gid_t)  arm,x86
 | 
					int     setregid:setregid32(gid_t, gid_t)  arm,x86
 | 
				
			||||||
int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
					int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
				
			||||||
int     chroot(const char*)  all
 | 
					int     chroot(const char*)  all
 | 
				
			||||||
@@ -124,7 +123,7 @@ int         fchown:fchown(int, uid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
				
			|||||||
void        sync(void)  all
 | 
					void        sync(void)  all
 | 
				
			||||||
int         ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
 | 
					int         ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
 | 
				
			||||||
ssize_t     ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
 | 
					ssize_t     ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
 | 
				
			||||||
ssize_t     flistxattr(int, char*, size_t) all
 | 
					ssize_t     ___flistxattr:flistxattr(int, char*, size_t) all
 | 
				
			||||||
int         fremovexattr(int, const char*) all
 | 
					int         fremovexattr(int, const char*) all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int)   arm,arm64,mips,mips64,x86,x86_64
 | 
					int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int)   arm,arm64,mips,mips64,x86,x86_64
 | 
				
			||||||
@@ -333,7 +332,7 @@ int     __set_tls:set_thread_area(void*) mips,mips64
 | 
				
			|||||||
int     __set_thread_area:set_thread_area(void*) x86
 | 
					int     __set_thread_area:set_thread_area(void*) x86
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# vdso stuff.
 | 
					# vdso stuff.
 | 
				
			||||||
int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
 | 
					int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64
 | 
				
			||||||
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
 | 
					int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
 | 
				
			||||||
int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
 | 
					int gettimeofday(timeval*, timezone*)                   arm,mips,mips64
 | 
				
			||||||
int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
 | 
					int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86,x86_64
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ libc_bionic_src_files_arm += \
 | 
				
			|||||||
    arch-arm/bionic/__restore.S \
 | 
					    arch-arm/bionic/__restore.S \
 | 
				
			||||||
    arch-arm/bionic/setjmp.S \
 | 
					    arch-arm/bionic/setjmp.S \
 | 
				
			||||||
    arch-arm/bionic/syscall.S \
 | 
					    arch-arm/bionic/syscall.S \
 | 
				
			||||||
 | 
					    arch-arm/bionic/vfork.S \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 | 
					libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 | 
				
			||||||
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
 | 
					libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								libc/arch-arm/bionic/vfork.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libc/arch-arm/bionic/vfork.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					 *    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					 *    distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
				
			||||||
 | 
					 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
				
			||||||
 | 
					 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
				
			||||||
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRY(vfork)
 | 
				
			||||||
 | 
					    // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
					    mrc     p15, 0, r3, c13, c0, 3
 | 
				
			||||||
 | 
					    ldr     r3, [r3, #4]
 | 
				
			||||||
 | 
					    mov     r0, #0
 | 
				
			||||||
 | 
					    str     r0, [r3, #12]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mov     ip, r7
 | 
				
			||||||
 | 
					    ldr     r7, =__NR_vfork
 | 
				
			||||||
 | 
					    swi     #0
 | 
				
			||||||
 | 
					    mov     r7, ip
 | 
				
			||||||
 | 
					    cmn     r0, #(MAX_ERRNO + 1)
 | 
				
			||||||
 | 
					    bxls    lr
 | 
				
			||||||
 | 
					    neg     r0, r0
 | 
				
			||||||
 | 
					    b       __set_errno_internal
 | 
				
			||||||
 | 
					END(vfork)
 | 
				
			||||||
@@ -70,7 +70,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .macro m_scan_byte
 | 
					    .macro m_scan_byte
 | 
				
			||||||
    ldrb    r3, [r0]
 | 
					    ldrb    r3, [r0]
 | 
				
			||||||
    cbz     r3, strcat_r0_scan_done
 | 
					    cbz     r3, .L_strcat_r0_scan_done
 | 
				
			||||||
    add     r0, #1
 | 
					    add     r0, #1
 | 
				
			||||||
    .endm // m_scan_byte
 | 
					    .endm // m_scan_byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,10 +84,10 @@ ENTRY(strcat)
 | 
				
			|||||||
    // Quick check to see if src is empty.
 | 
					    // Quick check to see if src is empty.
 | 
				
			||||||
    ldrb    r2, [r1]
 | 
					    ldrb    r2, [r1]
 | 
				
			||||||
    pld     [r1, #0]
 | 
					    pld     [r1, #0]
 | 
				
			||||||
    cbnz    r2, strcat_continue
 | 
					    cbnz    r2, .L_strcat_continue
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_continue:
 | 
					.L_strcat_continue:
 | 
				
			||||||
    // To speed up really small dst strings, unroll checking the first 4 bytes.
 | 
					    // To speed up really small dst strings, unroll checking the first 4 bytes.
 | 
				
			||||||
    m_push
 | 
					    m_push
 | 
				
			||||||
    m_scan_byte
 | 
					    m_scan_byte
 | 
				
			||||||
@@ -96,95 +96,95 @@ strcat_continue:
 | 
				
			|||||||
    m_scan_byte
 | 
					    m_scan_byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ands    r3, r0, #7
 | 
					    ands    r3, r0, #7
 | 
				
			||||||
    beq     strcat_mainloop
 | 
					    beq     .L_strcat_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Align to a double word (64 bits).
 | 
					    // Align to a double word (64 bits).
 | 
				
			||||||
    rsb     r3, r3, #8
 | 
					    rsb     r3, r3, #8
 | 
				
			||||||
    lsls    ip, r3, #31
 | 
					    lsls    ip, r3, #31
 | 
				
			||||||
    beq     strcat_align_to_32
 | 
					    beq     .L_strcat_align_to_32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r5, [r0]
 | 
					    ldrb    r5, [r0]
 | 
				
			||||||
    cbz     r5, strcat_r0_scan_done
 | 
					    cbz     r5, .L_strcat_r0_scan_done
 | 
				
			||||||
    add     r0, r0, #1
 | 
					    add     r0, r0, #1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_align_to_32:
 | 
					.L_strcat_align_to_32:
 | 
				
			||||||
    bcc     strcat_align_to_64
 | 
					    bcc     .L_strcat_align_to_64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r2, [r0]
 | 
					    ldrb    r2, [r0]
 | 
				
			||||||
    cbz     r2, strcat_r0_scan_done
 | 
					    cbz     r2, .L_strcat_r0_scan_done
 | 
				
			||||||
    add     r0, r0, #1
 | 
					    add     r0, r0, #1
 | 
				
			||||||
    ldrb    r4, [r0]
 | 
					    ldrb    r4, [r0]
 | 
				
			||||||
    cbz     r4, strcat_r0_scan_done
 | 
					    cbz     r4, .L_strcat_r0_scan_done
 | 
				
			||||||
    add     r0, r0, #1
 | 
					    add     r0, r0, #1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_align_to_64:
 | 
					.L_strcat_align_to_64:
 | 
				
			||||||
    tst     r3, #4
 | 
					    tst     r3, #4
 | 
				
			||||||
    beq     strcat_mainloop
 | 
					    beq     .L_strcat_mainloop
 | 
				
			||||||
    ldr     r3, [r0], #4
 | 
					    ldr     r3, [r0], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcat_zero_in_second_register
 | 
					    bne     .L_strcat_zero_in_second_register
 | 
				
			||||||
    b       strcat_mainloop
 | 
					    b       .L_strcat_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_r0_scan_done:
 | 
					.L_strcat_r0_scan_done:
 | 
				
			||||||
    // For short copies, hard-code checking the first 8 bytes since this
 | 
					    // For short copies, hard-code checking the first 8 bytes since this
 | 
				
			||||||
    // new code doesn't win until after about 8 bytes.
 | 
					    // new code doesn't win until after about 8 bytes.
 | 
				
			||||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r5, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
					    m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
 | 
				
			||||||
    m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
 | 
					    m_copy_byte reg=r5, cmd=cbnz, label=.L_strcpy_continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_finish:
 | 
					.L_strcpy_finish:
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_continue:
 | 
					.L_strcpy_continue:
 | 
				
			||||||
    ands    r3, r0, #7
 | 
					    ands    r3, r0, #7
 | 
				
			||||||
    beq     strcpy_check_src_align
 | 
					    beq     .L_strcpy_check_src_align
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Align to a double word (64 bits).
 | 
					    // Align to a double word (64 bits).
 | 
				
			||||||
    rsb     r3, r3, #8
 | 
					    rsb     r3, r3, #8
 | 
				
			||||||
    lsls    ip, r3, #31
 | 
					    lsls    ip, r3, #31
 | 
				
			||||||
    beq     strcpy_align_to_32
 | 
					    beq     .L_strcpy_align_to_32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    cbz     r2, strcpy_complete
 | 
					    cbz     r2, .L_strcpy_complete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_align_to_32:
 | 
					.L_strcpy_align_to_32:
 | 
				
			||||||
    bcc     strcpy_align_to_64
 | 
					    bcc     .L_strcpy_align_to_64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    cbz     r2, strcpy_complete
 | 
					    cbz     r2, .L_strcpy_complete
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    cbz     r2, strcpy_complete
 | 
					    cbz     r2, .L_strcpy_complete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_align_to_64:
 | 
					.L_strcpy_align_to_64:
 | 
				
			||||||
    tst     r3, #4
 | 
					    tst     r3, #4
 | 
				
			||||||
    beq     strcpy_check_src_align
 | 
					    beq     .L_strcpy_check_src_align
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_check_src_align:
 | 
					.L_strcpy_check_src_align:
 | 
				
			||||||
    // At this point dst is aligned to a double word, check if src
 | 
					    // At this point dst is aligned to a double word, check if src
 | 
				
			||||||
    // is also aligned to a double word.
 | 
					    // is also aligned to a double word.
 | 
				
			||||||
    ands    r3, r1, #7
 | 
					    ands    r3, r1, #7
 | 
				
			||||||
    bne     strcpy_unaligned_copy
 | 
					    bne     .L_strcpy_unaligned_copy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
strcpy_mainloop:
 | 
					.L_strcpy_mainloop:
 | 
				
			||||||
    ldrd    r2, r3, [r1], #8
 | 
					    ldrd    r2, r3, [r1], #8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
@@ -192,128 +192,128 @@ strcpy_mainloop:
 | 
				
			|||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_mainloop
 | 
					    b       .L_strcpy_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_complete:
 | 
					.L_strcpy_complete:
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_zero_in_first_register:
 | 
					.L_strcpy_zero_in_first_register:
 | 
				
			||||||
    lsls    lr, ip, #17
 | 
					    lsls    lr, ip, #17
 | 
				
			||||||
    bne     strcpy_copy1byte
 | 
					    bne     .L_strcpy_copy1byte
 | 
				
			||||||
    bcs     strcpy_copy2bytes
 | 
					    bcs     .L_strcpy_copy2bytes
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     strcpy_copy3bytes
 | 
					    bne     .L_strcpy_copy3bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy4bytes:
 | 
					.L_strcpy_copy4bytes:
 | 
				
			||||||
    // Copy 4 bytes to the destiniation.
 | 
					    // Copy 4 bytes to the destiniation.
 | 
				
			||||||
    str     r2, [r0]
 | 
					    str     r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy1byte:
 | 
					.L_strcpy_copy1byte:
 | 
				
			||||||
    strb    r2, [r0]
 | 
					    strb    r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy2bytes:
 | 
					.L_strcpy_copy2bytes:
 | 
				
			||||||
    strh    r2, [r0]
 | 
					    strh    r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy3bytes:
 | 
					.L_strcpy_copy3bytes:
 | 
				
			||||||
    strh    r2, [r0], #2
 | 
					    strh    r2, [r0], #2
 | 
				
			||||||
    lsr     r2, #16
 | 
					    lsr     r2, #16
 | 
				
			||||||
    strb    r2, [r0]
 | 
					    strb    r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_zero_in_second_register:
 | 
					.L_strcpy_zero_in_second_register:
 | 
				
			||||||
    lsls    lr, ip, #17
 | 
					    lsls    lr, ip, #17
 | 
				
			||||||
    bne     strcpy_copy5bytes
 | 
					    bne     .L_strcpy_copy5bytes
 | 
				
			||||||
    bcs     strcpy_copy6bytes
 | 
					    bcs     .L_strcpy_copy6bytes
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     strcpy_copy7bytes
 | 
					    bne     .L_strcpy_copy7bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Copy 8 bytes to the destination.
 | 
					    // Copy 8 bytes to the destination.
 | 
				
			||||||
    strd    r2, r3, [r0]
 | 
					    strd    r2, r3, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy5bytes:
 | 
					.L_strcpy_copy5bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r3, [r0]
 | 
					    strb    r3, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy6bytes:
 | 
					.L_strcpy_copy6bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strh    r3, [r0]
 | 
					    strh    r3, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_copy7bytes:
 | 
					.L_strcpy_copy7bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strh    r3, [r0], #2
 | 
					    strh    r3, [r0], #2
 | 
				
			||||||
    lsr     r3, #16
 | 
					    lsr     r3, #16
 | 
				
			||||||
    strb    r3, [r0]
 | 
					    strb    r3, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unaligned_copy:
 | 
					.L_strcpy_unaligned_copy:
 | 
				
			||||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
					    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
				
			||||||
    // There are 7 different versions of the unaligned copy code
 | 
					    // There are 7 different versions of the unaligned copy code
 | 
				
			||||||
    // to prevent overreading the src. The mainloop of every single version
 | 
					    // to prevent overreading the src. The mainloop of every single version
 | 
				
			||||||
    // will store 64 bits per loop. The difference is how much of src can
 | 
					    // will store 64 bits per loop. The difference is how much of src can
 | 
				
			||||||
    // be read without potentially crossing a page boundary.
 | 
					    // be read without potentially crossing a page boundary.
 | 
				
			||||||
    tbb     [pc, r3]
 | 
					    tbb     [pc, r3]
 | 
				
			||||||
strcpy_unaligned_branchtable:
 | 
					.L_strcpy_unaligned_branchtable:
 | 
				
			||||||
    .byte 0
 | 
					    .byte 0
 | 
				
			||||||
    .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign7 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign6 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign5 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign4 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign3 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign2 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
    .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
 | 
					    .byte ((.L_strcpy_unalign1 - .L_strcpy_unaligned_branchtable)/2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 7 bytes before possibly crossing a page.
 | 
					    // Can read 7 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign7:
 | 
					.L_strcpy_unalign7:
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r3, [r1]
 | 
					    ldrb    r3, [r1]
 | 
				
			||||||
    cbz     r3, strcpy_unalign7_copy5bytes
 | 
					    cbz     r3, .L_strcpy_unalign7_copy5bytes
 | 
				
			||||||
    ldrb    r4, [r1, #1]
 | 
					    ldrb    r4, [r1, #1]
 | 
				
			||||||
    cbz     r4, strcpy_unalign7_copy6bytes
 | 
					    cbz     r4, .L_strcpy_unalign7_copy6bytes
 | 
				
			||||||
    ldrb    r5, [r1, #2]
 | 
					    ldrb    r5, [r1, #2]
 | 
				
			||||||
    cbz     r5, strcpy_unalign7_copy7bytes
 | 
					    cbz     r5, .L_strcpy_unalign7_copy7bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lsrs    ip, r3, #24
 | 
					    lsrs    ip, r3, #24
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    beq     strcpy_unalign_return
 | 
					    beq     .L_strcpy_unalign_return
 | 
				
			||||||
    b       strcpy_unalign7
 | 
					    b       .L_strcpy_unalign7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign7_copy5bytes:
 | 
					.L_strcpy_unalign7_copy5bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r3, [r0]
 | 
					    strb    r3, [r0]
 | 
				
			||||||
strcpy_unalign_return:
 | 
					.L_strcpy_unalign_return:
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign7_copy6bytes:
 | 
					.L_strcpy_unalign7_copy6bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r3, [r0], #1
 | 
					    strb    r3, [r0], #1
 | 
				
			||||||
    strb    r4, [r0], #1
 | 
					    strb    r4, [r0], #1
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign7_copy7bytes:
 | 
					.L_strcpy_unalign7_copy7bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r3, [r0], #1
 | 
					    strb    r3, [r0], #1
 | 
				
			||||||
    strb    r4, [r0], #1
 | 
					    strb    r4, [r0], #1
 | 
				
			||||||
@@ -322,41 +322,41 @@ strcpy_unalign7_copy7bytes:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 6 bytes before possibly crossing a page.
 | 
					    // Can read 6 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign6:
 | 
					.L_strcpy_unalign6:
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r4, [r1]
 | 
					    ldrb    r4, [r1]
 | 
				
			||||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
					    cbz     r4, .L_strcpy_unalign_copy5bytes
 | 
				
			||||||
    ldrb    r5, [r1, #1]
 | 
					    ldrb    r5, [r1, #1]
 | 
				
			||||||
    cbz     r5, strcpy_unalign_copy6bytes
 | 
					    cbz     r5, .L_strcpy_unalign_copy6bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tst     r3, #0xff0000
 | 
					    tst     r3, #0xff0000
 | 
				
			||||||
    beq     strcpy_copy7bytes
 | 
					    beq     .L_strcpy_copy7bytes
 | 
				
			||||||
    lsrs    ip, r3, #24
 | 
					    lsrs    ip, r3, #24
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    beq     strcpy_unalign_return
 | 
					    beq     .L_strcpy_unalign_return
 | 
				
			||||||
    b       strcpy_unalign6
 | 
					    b       .L_strcpy_unalign6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 5 bytes before possibly crossing a page.
 | 
					    // Can read 5 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign5:
 | 
					.L_strcpy_unalign5:
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r4, [r1]
 | 
					    ldrb    r4, [r1]
 | 
				
			||||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
					    cbz     r4, .L_strcpy_unalign_copy5bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -365,17 +365,17 @@ strcpy_unalign5:
 | 
				
			|||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_unalign5
 | 
					    b       .L_strcpy_unalign5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign_copy5bytes:
 | 
					.L_strcpy_unalign_copy5bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r4, [r0]
 | 
					    strb    r4, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign_copy6bytes:
 | 
					.L_strcpy_unalign_copy6bytes:
 | 
				
			||||||
    str     r2, [r0], #4
 | 
					    str     r2, [r0], #4
 | 
				
			||||||
    strb    r4, [r0], #1
 | 
					    strb    r4, [r0], #1
 | 
				
			||||||
    strb    r5, [r0]
 | 
					    strb    r5, [r0]
 | 
				
			||||||
@@ -383,13 +383,13 @@ strcpy_unalign_copy6bytes:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 4 bytes before possibly crossing a page.
 | 
					    // Can read 4 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign4:
 | 
					.L_strcpy_unalign4:
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
@@ -397,20 +397,20 @@ strcpy_unalign4:
 | 
				
			|||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_unalign4
 | 
					    b       .L_strcpy_unalign4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 3 bytes before possibly crossing a page.
 | 
					    // Can read 3 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign3:
 | 
					.L_strcpy_unalign3:
 | 
				
			||||||
    ldrb    r2, [r1]
 | 
					    ldrb    r2, [r1]
 | 
				
			||||||
    cbz     r2, strcpy_unalign3_copy1byte
 | 
					    cbz     r2, .L_strcpy_unalign3_copy1byte
 | 
				
			||||||
    ldrb    r3, [r1, #1]
 | 
					    ldrb    r3, [r1, #1]
 | 
				
			||||||
    cbz     r3, strcpy_unalign3_copy2bytes
 | 
					    cbz     r3, .L_strcpy_unalign3_copy2bytes
 | 
				
			||||||
    ldrb    r4, [r1, #2]
 | 
					    ldrb    r4, [r1, #2]
 | 
				
			||||||
    cbz     r4, strcpy_unalign3_copy3bytes
 | 
					    cbz     r4, .L_strcpy_unalign3_copy3bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
@@ -418,26 +418,26 @@ strcpy_unalign3:
 | 
				
			|||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lsrs    lr, r2, #24
 | 
					    lsrs    lr, r2, #24
 | 
				
			||||||
    beq     strcpy_copy4bytes
 | 
					    beq     .L_strcpy_copy4bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_unalign3
 | 
					    b       .L_strcpy_unalign3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign3_copy1byte:
 | 
					.L_strcpy_unalign3_copy1byte:
 | 
				
			||||||
    strb    r2, [r0]
 | 
					    strb    r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign3_copy2bytes:
 | 
					.L_strcpy_unalign3_copy2bytes:
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    strb    r3, [r0]
 | 
					    strb    r3, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign3_copy3bytes:
 | 
					.L_strcpy_unalign3_copy3bytes:
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    strb    r3, [r0], #1
 | 
					    strb    r3, [r0], #1
 | 
				
			||||||
    strb    r4, [r0]
 | 
					    strb    r4, [r0]
 | 
				
			||||||
@@ -445,34 +445,34 @@ strcpy_unalign3_copy3bytes:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 2 bytes before possibly crossing a page.
 | 
					    // Can read 2 bytes before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign2:
 | 
					.L_strcpy_unalign2:
 | 
				
			||||||
    ldrb    r2, [r1]
 | 
					    ldrb    r2, [r1]
 | 
				
			||||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
					    cbz     r2, .L_strcpy_unalign_copy1byte
 | 
				
			||||||
    ldrb    r4, [r1, #1]
 | 
					    ldrb    r4, [r1, #1]
 | 
				
			||||||
    cbz     r4, strcpy_unalign_copy2bytes
 | 
					    cbz     r4, .L_strcpy_unalign_copy2bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tst     r2, #0xff0000
 | 
					    tst     r2, #0xff0000
 | 
				
			||||||
    beq     strcpy_copy3bytes
 | 
					    beq     .L_strcpy_copy3bytes
 | 
				
			||||||
    lsrs    ip, r2, #24
 | 
					    lsrs    ip, r2, #24
 | 
				
			||||||
    beq     strcpy_copy4bytes
 | 
					    beq     .L_strcpy_copy4bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_unalign2
 | 
					    b       .L_strcpy_unalign2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
    // Can read 1 byte before possibly crossing a page.
 | 
					    // Can read 1 byte before possibly crossing a page.
 | 
				
			||||||
strcpy_unalign1:
 | 
					.L_strcpy_unalign1:
 | 
				
			||||||
    ldrb    r2, [r1]
 | 
					    ldrb    r2, [r1]
 | 
				
			||||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
					    cbz     r2, .L_strcpy_unalign_copy1byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldr     r2, [r1], #4
 | 
					    ldr     r2, [r1], #4
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
@@ -482,27 +482,27 @@ strcpy_unalign1:
 | 
				
			|||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_first_register
 | 
					    bne     .L_strcpy_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcpy_zero_in_second_register
 | 
					    bne     .L_strcpy_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strd    r2, r3, [r0], #8
 | 
					    strd    r2, r3, [r0], #8
 | 
				
			||||||
    b       strcpy_unalign1
 | 
					    b       .L_strcpy_unalign1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign_copy1byte:
 | 
					.L_strcpy_unalign_copy1byte:
 | 
				
			||||||
    strb    r2, [r0]
 | 
					    strb    r2, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcpy_unalign_copy2bytes:
 | 
					.L_strcpy_unalign_copy2bytes:
 | 
				
			||||||
    strb    r2, [r0], #1
 | 
					    strb    r2, [r0], #1
 | 
				
			||||||
    strb    r4, [r0]
 | 
					    strb    r4, [r0]
 | 
				
			||||||
    m_pop
 | 
					    m_pop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
strcat_mainloop:
 | 
					.L_strcat_mainloop:
 | 
				
			||||||
    ldrd    r2, r3, [r0], #8
 | 
					    ldrd    r2, r3, [r0], #8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pld     [r0, #64]
 | 
					    pld     [r0, #64]
 | 
				
			||||||
@@ -510,59 +510,59 @@ strcat_mainloop:
 | 
				
			|||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcat_zero_in_first_register
 | 
					    bne     .L_strcat_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     strcat_zero_in_second_register
 | 
					    bne     .L_strcat_zero_in_second_register
 | 
				
			||||||
    b       strcat_mainloop
 | 
					    b       .L_strcat_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_zero_in_first_register:
 | 
					.L_strcat_zero_in_first_register:
 | 
				
			||||||
    // Prefetch the src now, it's going to be used soon.
 | 
					    // Prefetch the src now, it's going to be used soon.
 | 
				
			||||||
    pld     [r1, #0]
 | 
					    pld     [r1, #0]
 | 
				
			||||||
    lsls    lr, ip, #17
 | 
					    lsls    lr, ip, #17
 | 
				
			||||||
    bne     strcat_sub8
 | 
					    bne     .L_strcat_sub8
 | 
				
			||||||
    bcs     strcat_sub7
 | 
					    bcs     .L_strcat_sub7
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     strcat_sub6
 | 
					    bne     .L_strcat_sub6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     r0, r0, #5
 | 
					    sub     r0, r0, #5
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub8:
 | 
					.L_strcat_sub8:
 | 
				
			||||||
    sub     r0, r0, #8
 | 
					    sub     r0, r0, #8
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub7:
 | 
					.L_strcat_sub7:
 | 
				
			||||||
    sub     r0, r0, #7
 | 
					    sub     r0, r0, #7
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub6:
 | 
					.L_strcat_sub6:
 | 
				
			||||||
    sub     r0, r0, #6
 | 
					    sub     r0, r0, #6
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_zero_in_second_register:
 | 
					.L_strcat_zero_in_second_register:
 | 
				
			||||||
    // Prefetch the src now, it's going to be used soon.
 | 
					    // Prefetch the src now, it's going to be used soon.
 | 
				
			||||||
    pld     [r1, #0]
 | 
					    pld     [r1, #0]
 | 
				
			||||||
    lsls    lr, ip, #17
 | 
					    lsls    lr, ip, #17
 | 
				
			||||||
    bne     strcat_sub4
 | 
					    bne     .L_strcat_sub4
 | 
				
			||||||
    bcs     strcat_sub3
 | 
					    bcs     .L_strcat_sub3
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     strcat_sub2
 | 
					    bne     .L_strcat_sub2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     r0, r0, #1
 | 
					    sub     r0, r0, #1
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub4:
 | 
					.L_strcat_sub4:
 | 
				
			||||||
    sub     r0, r0, #4
 | 
					    sub     r0, r0, #4
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub3:
 | 
					.L_strcat_sub3:
 | 
				
			||||||
    sub     r0, r0, #3
 | 
					    sub     r0, r0, #3
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
strcat_sub2:
 | 
					.L_strcat_sub2:
 | 
				
			||||||
    sub     r0, r0, #2
 | 
					    sub     r0, r0, #2
 | 
				
			||||||
    b       strcat_r0_scan_done
 | 
					    b       .L_strcat_r0_scan_done
 | 
				
			||||||
END(strcat)
 | 
					END(strcat)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,38 +65,38 @@ ENTRY(strlen)
 | 
				
			|||||||
    mov     r1, r0
 | 
					    mov     r1, r0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ands    r3, r0, #7
 | 
					    ands    r3, r0, #7
 | 
				
			||||||
    beq     mainloop
 | 
					    beq     .L_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Align to a double word (64 bits).
 | 
					    // Align to a double word (64 bits).
 | 
				
			||||||
    rsb     r3, r3, #8
 | 
					    rsb     r3, r3, #8
 | 
				
			||||||
    lsls    ip, r3, #31
 | 
					    lsls    ip, r3, #31
 | 
				
			||||||
    beq     align_to_32
 | 
					    beq     .L_align_to_32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    cbz     r2, update_count_and_return
 | 
					    cbz     r2, .L_update_count_and_return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
align_to_32:
 | 
					.L_align_to_32:
 | 
				
			||||||
    bcc     align_to_64
 | 
					    bcc     .L_align_to_64
 | 
				
			||||||
    ands    ip, r3, #2
 | 
					    ands    ip, r3, #2
 | 
				
			||||||
    beq     align_to_64
 | 
					    beq     .L_align_to_64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    cbz     r2, update_count_and_return
 | 
					    cbz     r2, .L_update_count_and_return
 | 
				
			||||||
    ldrb    r2, [r1], #1
 | 
					    ldrb    r2, [r1], #1
 | 
				
			||||||
    cbz     r2, update_count_and_return
 | 
					    cbz     r2, .L_update_count_and_return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
align_to_64:
 | 
					.L_align_to_64:
 | 
				
			||||||
    tst     r3, #4
 | 
					    tst     r3, #4
 | 
				
			||||||
    beq     mainloop
 | 
					    beq     .L_mainloop
 | 
				
			||||||
    ldr     r3, [r1], #4
 | 
					    ldr     r3, [r1], #4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     zero_in_second_register
 | 
					    bne     .L_zero_in_second_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .p2align 2
 | 
					    .p2align 2
 | 
				
			||||||
mainloop:
 | 
					.L_mainloop:
 | 
				
			||||||
    ldrd    r2, r3, [r1], #8
 | 
					    ldrd    r2, r3, [r1], #8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pld     [r1, #64]
 | 
					    pld     [r1, #64]
 | 
				
			||||||
@@ -104,62 +104,62 @@ mainloop:
 | 
				
			|||||||
    sub     ip, r2, #0x01010101
 | 
					    sub     ip, r2, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r2
 | 
					    bic     ip, ip, r2
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     zero_in_first_register
 | 
					    bne     .L_zero_in_first_register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     ip, r3, #0x01010101
 | 
					    sub     ip, r3, #0x01010101
 | 
				
			||||||
    bic     ip, ip, r3
 | 
					    bic     ip, ip, r3
 | 
				
			||||||
    ands    ip, ip, #0x80808080
 | 
					    ands    ip, ip, #0x80808080
 | 
				
			||||||
    bne     zero_in_second_register
 | 
					    bne     .L_zero_in_second_register
 | 
				
			||||||
    b       mainloop
 | 
					    b       .L_mainloop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
update_count_and_return:
 | 
					.L_update_count_and_return:
 | 
				
			||||||
    sub     r0, r1, r0
 | 
					    sub     r0, r1, r0
 | 
				
			||||||
    sub     r0, r0, #1
 | 
					    sub     r0, r0, #1
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
zero_in_first_register:
 | 
					.L_zero_in_first_register:
 | 
				
			||||||
    sub     r0, r1, r0
 | 
					    sub     r0, r1, r0
 | 
				
			||||||
    lsls    r3, ip, #17
 | 
					    lsls    r3, ip, #17
 | 
				
			||||||
    bne     sub8_and_return
 | 
					    bne     .L_sub8_and_return
 | 
				
			||||||
    bcs     sub7_and_return
 | 
					    bcs     .L_sub7_and_return
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     sub6_and_return
 | 
					    bne     .L_sub6_and_return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     r0, r0, #5
 | 
					    sub     r0, r0, #5
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub8_and_return:
 | 
					.L_sub8_and_return:
 | 
				
			||||||
    sub     r0, r0, #8
 | 
					    sub     r0, r0, #8
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub7_and_return:
 | 
					.L_sub7_and_return:
 | 
				
			||||||
    sub     r0, r0, #7
 | 
					    sub     r0, r0, #7
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub6_and_return:
 | 
					.L_sub6_and_return:
 | 
				
			||||||
    sub     r0, r0, #6
 | 
					    sub     r0, r0, #6
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
zero_in_second_register:
 | 
					.L_zero_in_second_register:
 | 
				
			||||||
    sub     r0, r1, r0
 | 
					    sub     r0, r1, r0
 | 
				
			||||||
    lsls    r3, ip, #17
 | 
					    lsls    r3, ip, #17
 | 
				
			||||||
    bne     sub4_and_return
 | 
					    bne     .L_sub4_and_return
 | 
				
			||||||
    bcs     sub3_and_return
 | 
					    bcs     .L_sub3_and_return
 | 
				
			||||||
    lsls    ip, ip, #1
 | 
					    lsls    ip, ip, #1
 | 
				
			||||||
    bne     sub2_and_return
 | 
					    bne     .L_sub2_and_return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub     r0, r0, #1
 | 
					    sub     r0, r0, #1
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub4_and_return:
 | 
					.L_sub4_and_return:
 | 
				
			||||||
    sub     r0, r0, #4
 | 
					    sub     r0, r0, #4
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub3_and_return:
 | 
					.L_sub3_and_return:
 | 
				
			||||||
    sub     r0, r0, #3
 | 
					    sub     r0, r0, #3
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sub2_and_return:
 | 
					.L_sub2_and_return:
 | 
				
			||||||
    sub     r0, r0, #2
 | 
					    sub     r0, r0, #2
 | 
				
			||||||
    bx      lr
 | 
					    bx      lr
 | 
				
			||||||
END(strlen)
 | 
					END(strlen)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
				
			|||||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
					        /* check if buffers are aligned. If so, run arm-only version */
 | 
				
			||||||
        eor         r3, r0, r1
 | 
					        eor         r3, r0, r1
 | 
				
			||||||
        ands        r3, r3, #0x3
 | 
					        ands        r3, r3, #0x3
 | 
				
			||||||
        beq         __memcpy_base_aligned
 | 
					        beq         MEMCPY_BASE_ALIGNED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
					        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
				
			||||||
        cmp         r2, #224
 | 
					        cmp         r2, #224
 | 
				
			||||||
@@ -133,8 +133,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
				
			|||||||
        strbcs      ip, [r0], #1
 | 
					        strbcs      ip, [r0], #1
 | 
				
			||||||
        strbcs      lr, [r0], #1
 | 
					        strbcs      lr, [r0], #1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ldmfd       sp!, {r0, lr}
 | 
					        ldmfd       sp!, {r0, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
END(MEMCPY_BASE)
 | 
					END(MEMCPY_BASE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
 | 
					ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,12 +69,9 @@ END(bzero)
 | 
				
			|||||||
ENTRY(memset)
 | 
					ENTRY(memset)
 | 
				
			||||||
        // The neon memset only wins for less than 132.
 | 
					        // The neon memset only wins for less than 132.
 | 
				
			||||||
        cmp         r2, #132
 | 
					        cmp         r2, #132
 | 
				
			||||||
        bhi         __memset_large_copy
 | 
					        bhi         .L_memset_large_copy
 | 
				
			||||||
 | 
					 | 
				
			||||||
        stmfd       sp!, {r0}
 | 
					 | 
				
			||||||
        .cfi_def_cfa_offset 4
 | 
					 | 
				
			||||||
        .cfi_rel_offset r0, 0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mov         r3, r0
 | 
				
			||||||
        vdup.8      q0, r1
 | 
					        vdup.8      q0, r1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* make sure we have at least 32 bytes to write */
 | 
					        /* make sure we have at least 32 bytes to write */
 | 
				
			||||||
@@ -84,7 +81,7 @@ ENTRY(memset)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
1:      /* The main loop writes 32 bytes at a time */
 | 
					1:      /* The main loop writes 32 bytes at a time */
 | 
				
			||||||
        subs        r2, r2, #32
 | 
					        subs        r2, r2, #32
 | 
				
			||||||
        vst1.8      {d0 - d3}, [r0]!
 | 
					        vst1.8      {d0 - d3}, [r3]!
 | 
				
			||||||
        bhs         1b
 | 
					        bhs         1b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2:      /* less than 32 left */
 | 
					2:      /* less than 32 left */
 | 
				
			||||||
@@ -93,22 +90,20 @@ ENTRY(memset)
 | 
				
			|||||||
        beq         3f
 | 
					        beq         3f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // writes 16 bytes, 128-bits aligned
 | 
					        // writes 16 bytes, 128-bits aligned
 | 
				
			||||||
        vst1.8      {d0, d1}, [r0]!
 | 
					        vst1.8      {d0, d1}, [r3]!
 | 
				
			||||||
3:      /* write up to 15-bytes (count in r2) */
 | 
					3:      /* write up to 15-bytes (count in r2) */
 | 
				
			||||||
        movs        ip, r2, lsl #29
 | 
					        movs        ip, r2, lsl #29
 | 
				
			||||||
        bcc         1f
 | 
					        bcc         1f
 | 
				
			||||||
        vst1.8      {d0}, [r0]!
 | 
					        vst1.8      {d0}, [r3]!
 | 
				
			||||||
1:      bge         2f
 | 
					1:      bge         2f
 | 
				
			||||||
        vst1.32     {d0[0]}, [r0]!
 | 
					        vst1.32     {d0[0]}, [r3]!
 | 
				
			||||||
2:      movs        ip, r2, lsl #31
 | 
					2:      movs        ip, r2, lsl #31
 | 
				
			||||||
        strbmi      r1, [r0], #1
 | 
					        strbmi      r1, [r3], #1
 | 
				
			||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r3], #1
 | 
				
			||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r3], #1
 | 
				
			||||||
        ldmfd       sp!, {r0}
 | 
					 | 
				
			||||||
        bx          lr
 | 
					        bx          lr
 | 
				
			||||||
END(memset)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY_PRIVATE(__memset_large_copy)
 | 
					.L_memset_large_copy:
 | 
				
			||||||
        /* compute the offset to align the destination
 | 
					        /* compute the offset to align the destination
 | 
				
			||||||
         * offset = (4-(src&3))&3 = -src & 3
 | 
					         * offset = (4-(src&3))&3 = -src & 3
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
@@ -136,8 +131,7 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
				
			|||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r0], #1
 | 
				
			||||||
        strbmi      r1, [r0], #1
 | 
					        strbmi      r1, [r0], #1
 | 
				
			||||||
        subs        r2, r2, r3
 | 
					        subs        r2, r2, r3
 | 
				
			||||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
					        popls       {r0, r4-r7, pc}   /* return */
 | 
				
			||||||
        bxls        lr
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* align the destination to a cache-line */
 | 
					        /* align the destination to a cache-line */
 | 
				
			||||||
        mov         r12, r1
 | 
					        mov         r12, r1
 | 
				
			||||||
@@ -180,9 +174,8 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
				
			|||||||
        strhmi      r1, [r0], #2
 | 
					        strhmi      r1, [r0], #2
 | 
				
			||||||
        movs        r2, r2, lsl #2
 | 
					        movs        r2, r2, lsl #2
 | 
				
			||||||
        strbcs      r1, [r0]
 | 
					        strbcs      r1, [r0]
 | 
				
			||||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
					        ldmfd       sp!, {r0, r4-r7, pc}
 | 
				
			||||||
        bx          lr
 | 
					END(memset)
 | 
				
			||||||
END(__memset_large_copy)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .data
 | 
					        .data
 | 
				
			||||||
error_string:
 | 
					error_string:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -221,8 +221,7 @@ ENTRY(memcmp)
 | 
				
			|||||||
        bne         8b
 | 
					        bne         8b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
9:      /* restore registers and return */
 | 
					9:      /* restore registers and return */
 | 
				
			||||||
        ldmfd       sp!, {r4, lr}
 | 
					        ldmfd       sp!, {r4, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
10:     /* process less than 12 bytes */
 | 
					10:     /* process less than 12 bytes */
 | 
				
			||||||
        cmp         r2, #0
 | 
					        cmp         r2, #0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,8 +194,7 @@ ENTRY(memcpy)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* we're done! restore everything and return */
 | 
					        /* we're done! restore everything and return */
 | 
				
			||||||
1:      ldmfd       sp!, {r5-r11}
 | 
					1:      ldmfd       sp!, {r5-r11}
 | 
				
			||||||
        ldmfd       sp!, {r0, r4, lr}
 | 
					        ldmfd       sp!, {r0, r4, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /********************************************************************/
 | 
					        /********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,8 +384,7 @@ ENTRY(memcpy)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* we're done! restore sp and spilled registers and return */
 | 
					        /* we're done! restore sp and spilled registers and return */
 | 
				
			||||||
        add         sp,  sp, #28
 | 
					        add         sp,  sp, #28
 | 
				
			||||||
        ldmfd       sp!, {r0, r4, lr}
 | 
					        ldmfd       sp!, {r0, r4, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
END(memcpy)
 | 
					END(memcpy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Only reached when the __memcpy_chk check fails.
 | 
					        // Only reached when the __memcpy_chk check fails.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,8 +82,7 @@ ENTRY(memset)
 | 
				
			|||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r0], #1
 | 
				
			||||||
        strbmi      r1, [r0], #1
 | 
					        strbmi      r1, [r0], #1
 | 
				
			||||||
        subs        r2, r2, r3
 | 
					        subs        r2, r2, r3
 | 
				
			||||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
					        popls       {r0, r4-r7, pc}    /* return */
 | 
				
			||||||
        bxls        lr
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* align the destination to a cache-line */
 | 
					        /* align the destination to a cache-line */
 | 
				
			||||||
        mov         r12, r1
 | 
					        mov         r12, r1
 | 
				
			||||||
@@ -126,8 +125,7 @@ ENTRY(memset)
 | 
				
			|||||||
        strhmi      r1, [r0], #2
 | 
					        strhmi      r1, [r0], #2
 | 
				
			||||||
        movs        r2, r2, lsl #2
 | 
					        movs        r2, r2, lsl #2
 | 
				
			||||||
        strbcs      r1, [r0]
 | 
					        strbcs      r1, [r0]
 | 
				
			||||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
					        ldmfd       sp!, {r0, r4-r7, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
END(memset)
 | 
					END(memset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .data
 | 
					        .data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,5 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
				
			|||||||
        strbcs      ip, [r0], #1
 | 
					        strbcs      ip, [r0], #1
 | 
				
			||||||
        strbcs      lr, [r0], #1
 | 
					        strbcs      lr, [r0], #1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ldmfd       sp!, {r0, lr}
 | 
					        ldmfd       sp!, {r0, pc}
 | 
				
			||||||
        bx          lr
 | 
					 | 
				
			||||||
END(MEMCPY_BASE)
 | 
					END(MEMCPY_BASE)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,10 +69,7 @@ END(bzero)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* memset() returns its first argument.  */
 | 
					/* memset() returns its first argument.  */
 | 
				
			||||||
ENTRY(memset)
 | 
					ENTRY(memset)
 | 
				
			||||||
        stmfd       sp!, {r0}
 | 
					        mov         r3, r0
 | 
				
			||||||
        .cfi_def_cfa_offset 4
 | 
					 | 
				
			||||||
        .cfi_rel_offset r0, 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        vdup.8      q0, r1
 | 
					        vdup.8      q0, r1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* make sure we have at least 32 bytes to write */
 | 
					        /* make sure we have at least 32 bytes to write */
 | 
				
			||||||
@@ -82,7 +79,7 @@ ENTRY(memset)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
1:      /* The main loop writes 32 bytes at a time */
 | 
					1:      /* The main loop writes 32 bytes at a time */
 | 
				
			||||||
        subs        r2, r2, #32
 | 
					        subs        r2, r2, #32
 | 
				
			||||||
        vst1.8      {d0 - d3}, [r0]!
 | 
					        vst1.8      {d0 - d3}, [r3]!
 | 
				
			||||||
        bhs         1b
 | 
					        bhs         1b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2:      /* less than 32 left */
 | 
					2:      /* less than 32 left */
 | 
				
			||||||
@@ -91,18 +88,17 @@ ENTRY(memset)
 | 
				
			|||||||
        beq         3f
 | 
					        beq         3f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // writes 16 bytes, 128-bits aligned
 | 
					        // writes 16 bytes, 128-bits aligned
 | 
				
			||||||
        vst1.8      {d0, d1}, [r0]!
 | 
					        vst1.8      {d0, d1}, [r3]!
 | 
				
			||||||
3:      /* write up to 15-bytes (count in r2) */
 | 
					3:      /* write up to 15-bytes (count in r2) */
 | 
				
			||||||
        movs        ip, r2, lsl #29
 | 
					        movs        ip, r2, lsl #29
 | 
				
			||||||
        bcc         1f
 | 
					        bcc         1f
 | 
				
			||||||
        vst1.8      {d0}, [r0]!
 | 
					        vst1.8      {d0}, [r3]!
 | 
				
			||||||
1:      bge         2f
 | 
					1:      bge         2f
 | 
				
			||||||
        vst1.32     {d0[0]}, [r0]!
 | 
					        vst1.32     {d0[0]}, [r3]!
 | 
				
			||||||
2:      movs        ip, r2, lsl #31
 | 
					2:      movs        ip, r2, lsl #31
 | 
				
			||||||
        strbmi      r1, [r0], #1
 | 
					        strbmi      r1, [r3], #1
 | 
				
			||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r3], #1
 | 
				
			||||||
        strbcs      r1, [r0], #1
 | 
					        strbcs      r1, [r3], #1
 | 
				
			||||||
        ldmfd       sp!, {r0}
 | 
					 | 
				
			||||||
        bx          lr
 | 
					        bx          lr
 | 
				
			||||||
END(memset)
 | 
					END(memset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    mov     ip, r7
 | 
					    mov     ip, r7
 | 
				
			||||||
    ldr     r7, =__NR_flistxattr
 | 
					    ldr     r7, =__NR_flistxattr
 | 
				
			||||||
    swi     #0
 | 
					    swi     #0
 | 
				
			||||||
@@ -11,4 +11,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    bxls    lr
 | 
					    bxls    lr
 | 
				
			||||||
    neg     r0, r0
 | 
					    neg     r0, r0
 | 
				
			||||||
    b       __set_errno_internal
 | 
					    b       __set_errno_internal
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENTRY(vfork)
 | 
					 | 
				
			||||||
    mov     ip, r7
 | 
					 | 
				
			||||||
    ldr     r7, =__NR_vfork
 | 
					 | 
				
			||||||
    swi     #0
 | 
					 | 
				
			||||||
    mov     r7, ip
 | 
					 | 
				
			||||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
					 | 
				
			||||||
    bxls    lr
 | 
					 | 
				
			||||||
    neg     r0, r0
 | 
					 | 
				
			||||||
    b       __set_errno_internal
 | 
					 | 
				
			||||||
END(vfork)
 | 
					 | 
				
			||||||
@@ -31,6 +31,11 @@
 | 
				
			|||||||
#include <linux/sched.h>
 | 
					#include <linux/sched.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(vfork)
 | 
					ENTRY(vfork)
 | 
				
			||||||
 | 
					    // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
					    mrs     x0, tpidr_el0
 | 
				
			||||||
 | 
					    ldr     x0, [x0, #8]
 | 
				
			||||||
 | 
					    str     wzr, [x0, #20]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mov     x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
					    mov     x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
				
			||||||
    mov     x1, xzr
 | 
					    mov     x1, xzr
 | 
				
			||||||
    mov     x2, xzr
 | 
					    mov     x2, xzr
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    mov     x8, __NR_flistxattr
 | 
					    mov     x8, __NR_flistxattr
 | 
				
			||||||
    svc     #0
 | 
					    svc     #0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,4 +11,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    b.hi    __set_errno_internal
 | 
					    b.hi    __set_errno_internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret
 | 
					    ret
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
@@ -37,6 +37,14 @@ ENTRY(vfork)
 | 
				
			|||||||
	.set	noreorder
 | 
						.set	noreorder
 | 
				
			||||||
	.cpload	t9
 | 
						.cpload	t9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
						.set	push
 | 
				
			||||||
 | 
						.set	mips32r2
 | 
				
			||||||
 | 
						rdhwr	v0, $29			// v0 = tls; kernel trap on mips32r1
 | 
				
			||||||
 | 
						.set	pop
 | 
				
			||||||
 | 
						lw	v0, REGSZ*1(v0)		// v0 = v0[TLS_SLOT_THREAD_ID ie 1]
 | 
				
			||||||
 | 
						sw	$0, REGSZ*2+4(v0)	// v0->cached_pid_ = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	li	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
						li	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
				
			||||||
	li	a1, 0
 | 
						li	a1, 0
 | 
				
			||||||
	li	a2, 0
 | 
						li	a2, 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    .set noreorder
 | 
					    .set noreorder
 | 
				
			||||||
    .cpload t9
 | 
					    .cpload t9
 | 
				
			||||||
    li v0, __NR_flistxattr
 | 
					    li v0, __NR_flistxattr
 | 
				
			||||||
@@ -16,4 +16,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    j t9
 | 
					    j t9
 | 
				
			||||||
    nop
 | 
					    nop
 | 
				
			||||||
    .set reorder
 | 
					    .set reorder
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
@@ -46,6 +46,12 @@ LEAF(vfork,FRAMESZ)
 | 
				
			|||||||
	PTR_SUBU sp, FRAMESZ
 | 
						PTR_SUBU sp, FRAMESZ
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	SETUP_GP64(a5, vfork)
 | 
						SETUP_GP64(a5, vfork)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
						rdhwr	v0, $29			// v0 = tls
 | 
				
			||||||
 | 
						REG_L	v0, REGSZ*1(v0)		// v0 = v0[TLS_SLOT_THREAD_ID ie 1]
 | 
				
			||||||
 | 
						sw	$0, REGSZ*2+4(v0)	// v0->cached_pid_ = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LI	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
						LI	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
 | 
				
			||||||
	move	a1, $0
 | 
						move	a1, $0
 | 
				
			||||||
	move	a2, $0
 | 
						move	a2, $0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    .set push
 | 
					    .set push
 | 
				
			||||||
    .set noreorder
 | 
					    .set noreorder
 | 
				
			||||||
    li v0, __NR_flistxattr
 | 
					    li v0, __NR_flistxattr
 | 
				
			||||||
@@ -22,4 +22,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    j t9
 | 
					    j t9
 | 
				
			||||||
    move ra, t0
 | 
					    move ra, t0
 | 
				
			||||||
    .set pop
 | 
					    .set pop
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
@@ -34,6 +34,12 @@ ENTRY(vfork)
 | 
				
			|||||||
  popl    %ecx  // Grab the return address.
 | 
					  popl    %ecx  // Grab the return address.
 | 
				
			||||||
  .cfi_adjust_cfa_offset 4
 | 
					  .cfi_adjust_cfa_offset 4
 | 
				
			||||||
  .cfi_rel_offset ecx, 0
 | 
					  .cfi_rel_offset ecx, 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
					  movl    %gs:0, %eax
 | 
				
			||||||
 | 
					  movl    4(%eax), %eax
 | 
				
			||||||
 | 
					  movl    $0, 12(%eax)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  movl    $__NR_vfork, %eax
 | 
					  movl    $__NR_vfork, %eax
 | 
				
			||||||
  int     $0x80
 | 
					  int     $0x80
 | 
				
			||||||
  cmpl    $-MAX_ERRNO, %eax
 | 
					  cmpl    $-MAX_ERRNO, %eax
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    pushl   %ebx
 | 
					    pushl   %ebx
 | 
				
			||||||
    .cfi_def_cfa_offset 8
 | 
					    .cfi_def_cfa_offset 8
 | 
				
			||||||
    .cfi_rel_offset ebx, 0
 | 
					    .cfi_rel_offset ebx, 0
 | 
				
			||||||
@@ -28,4 +28,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    popl    %ecx
 | 
					    popl    %ecx
 | 
				
			||||||
    popl    %ebx
 | 
					    popl    %ebx
 | 
				
			||||||
    ret
 | 
					    ret
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(clock_gettime)
 | 
					ENTRY(__clock_gettime)
 | 
				
			||||||
    pushl   %ebx
 | 
					    pushl   %ebx
 | 
				
			||||||
    .cfi_def_cfa_offset 8
 | 
					    .cfi_def_cfa_offset 8
 | 
				
			||||||
    .cfi_rel_offset ebx, 0
 | 
					    .cfi_rel_offset ebx, 0
 | 
				
			||||||
@@ -23,4 +23,4 @@ ENTRY(clock_gettime)
 | 
				
			|||||||
    popl    %ecx
 | 
					    popl    %ecx
 | 
				
			||||||
    popl    %ebx
 | 
					    popl    %ebx
 | 
				
			||||||
    ret
 | 
					    ret
 | 
				
			||||||
END(clock_gettime)
 | 
					END(__clock_gettime)
 | 
				
			||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(gettimeofday)
 | 
					ENTRY(__gettimeofday)
 | 
				
			||||||
    pushl   %ebx
 | 
					    pushl   %ebx
 | 
				
			||||||
    .cfi_def_cfa_offset 8
 | 
					    .cfi_def_cfa_offset 8
 | 
				
			||||||
    .cfi_rel_offset ebx, 0
 | 
					    .cfi_rel_offset ebx, 0
 | 
				
			||||||
@@ -23,4 +23,4 @@ ENTRY(gettimeofday)
 | 
				
			|||||||
    popl    %ecx
 | 
					    popl    %ecx
 | 
				
			||||||
    popl    %ebx
 | 
					    popl    %ebx
 | 
				
			||||||
    ret
 | 
					    ret
 | 
				
			||||||
END(gettimeofday)
 | 
					END(__gettimeofday)
 | 
				
			||||||
@@ -32,6 +32,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ENTRY(vfork)
 | 
					ENTRY(vfork)
 | 
				
			||||||
  popq    %rdi  // Grab the return address.
 | 
					  popq    %rdi  // Grab the return address.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
 | 
				
			||||||
 | 
					  mov    %fs:0, %rax
 | 
				
			||||||
 | 
					  mov    8(%rax), %rax
 | 
				
			||||||
 | 
					  movl   $0, 20(%rax)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  movl    $__NR_vfork, %eax
 | 
					  movl    $__NR_vfork, %eax
 | 
				
			||||||
  syscall
 | 
					  syscall
 | 
				
			||||||
  pushq   %rdi  // Restore the return address.
 | 
					  pushq   %rdi  // Restore the return address.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <private/bionic_asm.h>
 | 
					#include <private/bionic_asm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENTRY(flistxattr)
 | 
					ENTRY(___flistxattr)
 | 
				
			||||||
    movl    $__NR_flistxattr, %eax
 | 
					    movl    $__NR_flistxattr, %eax
 | 
				
			||||||
    syscall
 | 
					    syscall
 | 
				
			||||||
    cmpq    $-MAX_ERRNO, %rax
 | 
					    cmpq    $-MAX_ERRNO, %rax
 | 
				
			||||||
@@ -12,4 +12,5 @@ ENTRY(flistxattr)
 | 
				
			|||||||
    call    __set_errno_internal
 | 
					    call    __set_errno_internal
 | 
				
			||||||
1:
 | 
					1:
 | 
				
			||||||
    ret
 | 
					    ret
 | 
				
			||||||
END(flistxattr)
 | 
					END(___flistxattr)
 | 
				
			||||||
 | 
					.hidden ___flistxattr
 | 
				
			||||||
							
								
								
									
										47
									
								
								libc/bionic/__fread_chk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								libc/bionic/__fread_chk.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					 *    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					 *    distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
				
			||||||
 | 
					 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
				
			||||||
 | 
					 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
				
			||||||
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" size_t __fread_chk(void * __restrict buf, size_t size, size_t count,
 | 
				
			||||||
 | 
					                              FILE * __restrict stream, size_t buf_size) {
 | 
				
			||||||
 | 
					  size_t total;
 | 
				
			||||||
 | 
					  if (__predict_false(__size_mul_overflow(size, count, &total))) {
 | 
				
			||||||
 | 
					    // overflow: trigger the error path in fread
 | 
				
			||||||
 | 
					    return fread(buf, size, count, stream);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (__predict_false(total > buf_size)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("fread: prevented write past end of buffer", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return fread(buf, size, count, stream);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								libc/bionic/__fwrite_chk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								libc/bionic/__fwrite_chk.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					 *    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					 *    distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
				
			||||||
 | 
					 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
				
			||||||
 | 
					 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
				
			||||||
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" size_t __fwrite_chk(const void * __restrict buf, size_t size, size_t count,
 | 
				
			||||||
 | 
					                               FILE * __restrict stream, size_t buf_size) {
 | 
				
			||||||
 | 
					  size_t total;
 | 
				
			||||||
 | 
					  if (__predict_false(__size_mul_overflow(size, count, &total))) {
 | 
				
			||||||
 | 
					    // overflow: trigger the error path in fwrite
 | 
				
			||||||
 | 
					    return fwrite(buf, size, count, stream);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (__predict_false(total > buf_size)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("fwrite: prevented read past end of buffer", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return fwrite(buf, size, count, stream);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								libc/bionic/__getcwd_chk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libc/bionic/__getcwd_chk.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					 *    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					 *    distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
				
			||||||
 | 
					 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
				
			||||||
 | 
					 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
				
			||||||
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char* __getcwd_chk(char* buf, size_t len, size_t buflen) {
 | 
				
			||||||
 | 
					  if (__predict_false(len > buflen)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("getcwd: prevented write past end of buffer", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return getcwd(buf, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										59
									
								
								libc/bionic/flistxattr.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								libc/bionic/flistxattr.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					 *    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					 *    distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
				
			||||||
 | 
					 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
				
			||||||
 | 
					 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
				
			||||||
 | 
					 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
				
			||||||
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/xattr.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" ssize_t ___flistxattr(int, char*, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ssize_t flistxattr(int fd, char *list, size_t size) {
 | 
				
			||||||
 | 
					  int saved_errno = errno;
 | 
				
			||||||
 | 
					  ssize_t result = ___flistxattr(fd, list, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((result != -1) || (errno != EBADF)) {
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // fd could be an O_PATH file descriptor, and the kernel
 | 
				
			||||||
 | 
					  // may not directly support fgetxattr() on such a file descriptor.
 | 
				
			||||||
 | 
					  // Use /proc/self/fd instead to emulate this support.
 | 
				
			||||||
 | 
					  int fd_flag = fcntl(fd, F_GETFL);
 | 
				
			||||||
 | 
					  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
 | 
				
			||||||
 | 
					    errno = EBADF;
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char buf[40];
 | 
				
			||||||
 | 
					  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
 | 
				
			||||||
 | 
					  errno = saved_errno;
 | 
				
			||||||
 | 
					  return listxattr(buf, list, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -26,6 +26,7 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <malloc.h>
 | 
					#include <malloc.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,18 +64,15 @@ char** environ;
 | 
				
			|||||||
// Declared in "private/bionic_ssp.h".
 | 
					// Declared in "private/bionic_ssp.h".
 | 
				
			||||||
uintptr_t __stack_chk_guard = 0;
 | 
					uintptr_t __stack_chk_guard = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
 | 
					// Setup for the main thread. For dynamic executables, this is called by the
 | 
				
			||||||
 * in memory. Beware: all writes to libc globals from this function will
 | 
					// linker _before_ libc is mapped in memory. This means that all writes to
 | 
				
			||||||
 * apply to linker-private copies and will not be visible from libc later on.
 | 
					// globals from this function will apply to linker-private copies and will not
 | 
				
			||||||
 *
 | 
					// be visible from libc later on.
 | 
				
			||||||
 * Note: this function creates a pthread_internal_t for the initial thread and
 | 
					//
 | 
				
			||||||
 * stores the pointer in TLS, but does not add it to pthread's thread list. This
 | 
					// Note: this function creates a pthread_internal_t for the initial thread and
 | 
				
			||||||
 * has to be done later from libc itself (see __libc_init_common).
 | 
					// stores the pointer in TLS, but does not add it to pthread's thread list. This
 | 
				
			||||||
 *
 | 
					// has to be done later from libc itself (see __libc_init_common).
 | 
				
			||||||
 * This function also stores a pointer to the kernel argument block in a TLS slot to be
 | 
					void __libc_init_main_thread(KernelArgumentBlock& args) {
 | 
				
			||||||
 * picked up by the libc constructor.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void __libc_init_tls(KernelArgumentBlock& args) {
 | 
					 | 
				
			||||||
  __libc_auxv = args.auxv;
 | 
					  __libc_auxv = args.auxv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static pthread_internal_t main_thread;
 | 
					  static pthread_internal_t main_thread;
 | 
				
			||||||
@@ -99,6 +96,9 @@ void __libc_init_tls(KernelArgumentBlock& args) {
 | 
				
			|||||||
  __init_thread(&main_thread);
 | 
					  __init_thread(&main_thread);
 | 
				
			||||||
  __init_tls(&main_thread);
 | 
					  __init_tls(&main_thread);
 | 
				
			||||||
  __set_tls(main_thread.tls);
 | 
					  __set_tls(main_thread.tls);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Store a pointer to the kernel argument block in a TLS slot to be
 | 
				
			||||||
 | 
					  // picked up by the libc constructor.
 | 
				
			||||||
  main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
 | 
					  main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  __init_alternate_signal_stack(&main_thread);
 | 
					  __init_alternate_signal_stack(&main_thread);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,16 +49,10 @@
 | 
				
			|||||||
#include "libc_init_common.h"
 | 
					#include "libc_init_common.h"
 | 
				
			||||||
#include "pthread_internal.h"
 | 
					#include "pthread_internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "private/bionic_page.h"
 | 
				
			||||||
#include "private/bionic_tls.h"
 | 
					#include "private/bionic_tls.h"
 | 
				
			||||||
#include "private/KernelArgumentBlock.h"
 | 
					#include "private/KernelArgumentBlock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Returns the address of the page containing address 'x'.
 | 
					 | 
				
			||||||
#define PAGE_START(x)  ((x) & PAGE_MASK)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Returns the address of the next page after address 'x', unless 'x' is
 | 
					 | 
				
			||||||
// itself at the start of a page.
 | 
					 | 
				
			||||||
#define PAGE_END(x)    PAGE_START((x) + (PAGE_SIZE-1))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
 | 
					extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void call_array(void(**list)()) {
 | 
					static void call_array(void(**list)()) {
 | 
				
			||||||
@@ -90,7 +84,7 @@ __noreturn void __libc_init(void* raw_args,
 | 
				
			|||||||
                            int (*slingshot)(int, char**, char**),
 | 
					                            int (*slingshot)(int, char**, char**),
 | 
				
			||||||
                            structors_array_t const * const structors) {
 | 
					                            structors_array_t const * const structors) {
 | 
				
			||||||
  KernelArgumentBlock args(raw_args);
 | 
					  KernelArgumentBlock args(raw_args);
 | 
				
			||||||
  __libc_init_tls(args);
 | 
					  __libc_init_main_thread(args);
 | 
				
			||||||
  __libc_init_AT_SECURE(args);
 | 
					  __libc_init_AT_SECURE(args);
 | 
				
			||||||
  __libc_init_common(args);
 | 
					  __libc_init_common(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -448,7 +448,6 @@ static int __libc_write_stderr(const char* tag, const char* msg) {
 | 
				
			|||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TARGET_USES_LOGD
 | 
					 | 
				
			||||||
static int __libc_open_log_socket() {
 | 
					static int __libc_open_log_socket() {
 | 
				
			||||||
  // ToDo: Ideally we want this to fail if the gid of the current
 | 
					  // ToDo: Ideally we want this to fail if the gid of the current
 | 
				
			||||||
  // process is AID_LOGD, but will have to wait until we have
 | 
					  // process is AID_LOGD, but will have to wait until we have
 | 
				
			||||||
@@ -486,10 +485,8 @@ struct log_time { // Wire format
 | 
				
			|||||||
  uint32_t tv_sec;
 | 
					  uint32_t tv_sec;
 | 
				
			||||||
  uint32_t tv_nsec;
 | 
					  uint32_t tv_nsec;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __libc_write_log(int priority, const char* tag, const char* msg) {
 | 
					static int __libc_write_log(int priority, const char* tag, const char* msg) {
 | 
				
			||||||
#ifdef TARGET_USES_LOGD
 | 
					 | 
				
			||||||
  int main_log_fd = __libc_open_log_socket();
 | 
					  int main_log_fd = __libc_open_log_socket();
 | 
				
			||||||
  if (main_log_fd == -1) {
 | 
					  if (main_log_fd == -1) {
 | 
				
			||||||
    // Try stderr instead.
 | 
					    // Try stderr instead.
 | 
				
			||||||
@@ -517,24 +514,6 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) {
 | 
				
			|||||||
  vec[4].iov_len = strlen(tag) + 1;
 | 
					  vec[4].iov_len = strlen(tag) + 1;
 | 
				
			||||||
  vec[5].iov_base = const_cast<char*>(msg);
 | 
					  vec[5].iov_base = const_cast<char*>(msg);
 | 
				
			||||||
  vec[5].iov_len = strlen(msg) + 1;
 | 
					  vec[5].iov_len = strlen(msg) + 1;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
 | 
					 | 
				
			||||||
  if (main_log_fd == -1) {
 | 
					 | 
				
			||||||
    if (errno == ENOTDIR) {
 | 
					 | 
				
			||||||
      // /dev/log isn't a directory? Maybe we're running on the host? Try stderr instead.
 | 
					 | 
				
			||||||
      return __libc_write_stderr(tag, msg);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  iovec vec[3];
 | 
					 | 
				
			||||||
  vec[0].iov_base = &priority;
 | 
					 | 
				
			||||||
  vec[0].iov_len = 1;
 | 
					 | 
				
			||||||
  vec[1].iov_base = const_cast<char*>(tag);
 | 
					 | 
				
			||||||
  vec[1].iov_len = strlen(tag) + 1;
 | 
					 | 
				
			||||||
  vec[2].iov_base = const_cast<char*>(msg);
 | 
					 | 
				
			||||||
  vec[2].iov_len = strlen(msg) + 1;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
 | 
					  int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
 | 
				
			||||||
  close(main_log_fd);
 | 
					  close(main_log_fd);
 | 
				
			||||||
@@ -557,7 +536,6 @@ int __libc_format_log(int priority, const char* tag, const char* format, ...) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
 | 
					static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
 | 
				
			||||||
#ifdef TARGET_USES_LOGD
 | 
					 | 
				
			||||||
  iovec vec[6];
 | 
					  iovec vec[6];
 | 
				
			||||||
  char log_id = LOG_ID_EVENTS;
 | 
					  char log_id = LOG_ID_EVENTS;
 | 
				
			||||||
  vec[0].iov_base = &log_id;
 | 
					  vec[0].iov_base = &log_id;
 | 
				
			||||||
@@ -581,17 +559,6 @@ static int __libc_android_log_event(int32_t tag, char type, const void* payload,
 | 
				
			|||||||
  vec[5].iov_len = len;
 | 
					  vec[5].iov_len = len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int event_log_fd = __libc_open_log_socket();
 | 
					  int event_log_fd = __libc_open_log_socket();
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  iovec vec[3];
 | 
					 | 
				
			||||||
  vec[0].iov_base = &tag;
 | 
					 | 
				
			||||||
  vec[0].iov_len = sizeof(tag);
 | 
					 | 
				
			||||||
  vec[1].iov_base = &type;
 | 
					 | 
				
			||||||
  vec[1].iov_len = sizeof(type);
 | 
					 | 
				
			||||||
  vec[2].iov_base = const_cast<void*>(payload);
 | 
					 | 
				
			||||||
  vec[2].iov_len = len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (event_log_fd == -1) {
 | 
					  if (event_log_fd == -1) {
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@
 | 
				
			|||||||
static ThreadLocalBuffer<char, MAXPATHLEN> g_basename_tls_buffer;
 | 
					static ThreadLocalBuffer<char, MAXPATHLEN> g_basename_tls_buffer;
 | 
				
			||||||
static ThreadLocalBuffer<char, MAXPATHLEN> g_dirname_tls_buffer;
 | 
					static ThreadLocalBuffer<char, MAXPATHLEN> g_dirname_tls_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
 | 
					static int __basename_r(const char* path, char* buffer, size_t buffer_size) {
 | 
				
			||||||
  const char* startp = NULL;
 | 
					  const char* startp = NULL;
 | 
				
			||||||
  const char* endp = NULL;
 | 
					  const char* endp = NULL;
 | 
				
			||||||
  int len;
 | 
					  int len;
 | 
				
			||||||
@@ -91,7 +91,12 @@ __LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_s
 | 
				
			|||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
 | 
					// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
 | 
				
			||||||
 | 
					__LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
 | 
				
			||||||
 | 
					  return __basename_r(path, buffer, buffer_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __dirname_r(const char* path, char* buffer, size_t buffer_size) {
 | 
				
			||||||
  const char* endp = NULL;
 | 
					  const char* endp = NULL;
 | 
				
			||||||
  int len;
 | 
					  int len;
 | 
				
			||||||
  int result;
 | 
					  int result;
 | 
				
			||||||
@@ -150,14 +155,19 @@ __LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_si
 | 
				
			|||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
 | 
				
			||||||
 | 
					__LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
 | 
				
			||||||
 | 
					  return __dirname_r(path, buffer, buffer_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* basename(const char* path) {
 | 
					char* basename(const char* path) {
 | 
				
			||||||
  char* buf = g_basename_tls_buffer.get();
 | 
					  char* buf = g_basename_tls_buffer.get();
 | 
				
			||||||
  int rc = basename_r(path, buf, g_basename_tls_buffer.size());
 | 
					  int rc = __basename_r(path, buf, g_basename_tls_buffer.size());
 | 
				
			||||||
  return (rc < 0) ? NULL : buf;
 | 
					  return (rc < 0) ? NULL : buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char* dirname(const char* path) {
 | 
					char* dirname(const char* path) {
 | 
				
			||||||
  char* buf = g_dirname_tls_buffer.get();
 | 
					  char* buf = g_dirname_tls_buffer.get();
 | 
				
			||||||
  int rc = dirname_r(path, buf, g_dirname_tls_buffer.size());
 | 
					  int rc = __dirname_r(path, buf, g_dirname_tls_buffer.size());
 | 
				
			||||||
  return (rc < 0) ? NULL : buf;
 | 
					  return (rc < 0) ? NULL : buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -612,7 +612,7 @@ extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_di
 | 
				
			|||||||
        error_log("Unable to open /dev/qemu_trace");
 | 
					        error_log("Unable to open /dev/qemu_trace");
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 | 
					        qtrace = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 | 
				
			||||||
        close(fd);
 | 
					        close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (qtrace == MAP_FAILED) {
 | 
					        if (qtrace == MAP_FAILED) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,7 @@ void __init_alternate_signal_stack(pthread_internal_t* thread) {
 | 
				
			|||||||
    // We can only use const static allocated string for mapped region name, as Android kernel
 | 
					    // We can only use const static allocated string for mapped region name, as Android kernel
 | 
				
			||||||
    // uses the string pointer directly when dumping /proc/pid/maps.
 | 
					    // uses the string pointer directly when dumping /proc/pid/maps.
 | 
				
			||||||
    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ss.ss_sp, ss.ss_size, "thread signal stack");
 | 
					    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ss.ss_sp, ss.ss_size, "thread signal stack");
 | 
				
			||||||
 | 
					    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, stack_base, PAGE_SIZE, "thread signal stack guard page");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -140,6 +141,7 @@ static void* __create_thread_mapped_space(size_t mmap_size, size_t stack_guard_s
 | 
				
			|||||||
    munmap(space, mmap_size);
 | 
					    munmap(space, mmap_size);
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, space, stack_guard_size, "thread stack guard page");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return space;
 | 
					  return space;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,13 +130,8 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
 | 
					#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Leave room for a guard page in the internally created signal stacks.
 | 
					/* Leave room for a guard page in the internally created signal stacks. */
 | 
				
			||||||
#if defined(__LP64__)
 | 
					 | 
				
			||||||
// SIGSTKSZ is not big enough for 64-bit arch. See http://b/23041777.
 | 
					 | 
				
			||||||
#define SIGNAL_STACK_SIZE (16 * 1024 + PAGE_SIZE)
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE)
 | 
					#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE)
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Needed by fork. */
 | 
					/* Needed by fork. */
 | 
				
			||||||
__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 | 
					__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@
 | 
				
			|||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "private/android_filesystem_config.h"
 | 
					#include "private/android_filesystem_config.h"
 | 
				
			||||||
 | 
					#include "private/bionic_macros.h"
 | 
				
			||||||
#include "private/ErrnoRestorer.h"
 | 
					#include "private/ErrnoRestorer.h"
 | 
				
			||||||
#include "private/libc_logging.h"
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
#include "private/ThreadLocalBuffer.h"
 | 
					#include "private/ThreadLocalBuffer.h"
 | 
				
			||||||
@@ -66,11 +67,15 @@ struct passwd_state_t {
 | 
				
			|||||||
static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
 | 
					static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
 | 
				
			||||||
static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
 | 
					static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void init_group_state(group_state_t* state) {
 | 
				
			||||||
 | 
					  memset(state, 0, sizeof(group_state_t));
 | 
				
			||||||
 | 
					  state->group_.gr_mem = state->group_members_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static group_state_t* __group_state() {
 | 
					static group_state_t* __group_state() {
 | 
				
			||||||
  group_state_t* result = g_group_tls_buffer.get();
 | 
					  group_state_t* result = g_group_tls_buffer.get();
 | 
				
			||||||
  if (result != nullptr) {
 | 
					  if (result != nullptr) {
 | 
				
			||||||
    memset(result, 0, sizeof(group_state_t));
 | 
					    init_group_state(result);
 | 
				
			||||||
    result->group_.gr_mem = result->group_members_;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -397,17 +402,28 @@ char* getlogin() { // NOLINT: implementing bad function.
 | 
				
			|||||||
  return (pw != NULL) ? pw->pw_name : NULL;
 | 
					  return (pw != NULL) ? pw->pw_name : NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static group* getgrgid_internal(gid_t gid, group_state_t* state) {
 | 
				
			||||||
 | 
					  group* grp = android_id_to_group(state, gid);
 | 
				
			||||||
 | 
					  if (grp != NULL) {
 | 
				
			||||||
 | 
					    return grp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return app_id_to_group(gid, state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
 | 
					group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
 | 
				
			||||||
  group_state_t* state = __group_state();
 | 
					  group_state_t* state = __group_state();
 | 
				
			||||||
  if (state == NULL) {
 | 
					  if (state == NULL) {
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  return getgrgid_internal(gid, state);
 | 
				
			||||||
  group* gr = android_id_to_group(state, gid);
 | 
					 | 
				
			||||||
  if (gr != NULL) {
 | 
					 | 
				
			||||||
    return gr;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  return app_id_to_group(gid, state);
 | 
					
 | 
				
			||||||
 | 
					static group* getgrnam_internal(const char* name, group_state_t* state) {
 | 
				
			||||||
 | 
					  group* grp = android_name_to_group(state, name);
 | 
				
			||||||
 | 
					  if (grp != NULL) {
 | 
				
			||||||
 | 
					    return grp;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return app_id_to_group(app_id_from_name(name, true), state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
 | 
					group* getgrnam(const char* name) { // NOLINT: implementing bad function.
 | 
				
			||||||
@@ -415,11 +431,36 @@ group* getgrnam(const char* name) { // NOLINT: implementing bad function.
 | 
				
			|||||||
  if (state == NULL) {
 | 
					  if (state == NULL) {
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  return getgrnam_internal(name, state);
 | 
				
			||||||
  if (android_name_to_group(state, name) != 0) {
 | 
					 | 
				
			||||||
    return &state->group_;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
  return app_id_to_group(app_id_from_name(name, true), state);
 | 
					
 | 
				
			||||||
 | 
					static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
 | 
				
			||||||
 | 
					                      size_t buflen, struct group** result) {
 | 
				
			||||||
 | 
					  ErrnoRestorer errno_restorer;
 | 
				
			||||||
 | 
					  *result = NULL;
 | 
				
			||||||
 | 
					  char* p = reinterpret_cast<char*>(
 | 
				
			||||||
 | 
					      BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
 | 
				
			||||||
 | 
					  if (p + sizeof(group_state_t) > buf + buflen) {
 | 
				
			||||||
 | 
					    return ERANGE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  group_state_t* state = reinterpret_cast<group_state_t*>(p);
 | 
				
			||||||
 | 
					  init_group_state(state);
 | 
				
			||||||
 | 
					  group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
 | 
				
			||||||
 | 
					  if (retval != NULL) {
 | 
				
			||||||
 | 
					    *grp = *retval;
 | 
				
			||||||
 | 
					    *result = grp;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return errno;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
 | 
				
			||||||
 | 
					  return getgroup_r(false, NULL, gid, grp, buf, buflen, result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
 | 
				
			||||||
 | 
					               struct group **result) {
 | 
				
			||||||
 | 
					  return getgroup_r(true, name, 0, grp, buf, buflen, result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We don't have an /etc/networks, so all inputs return NULL.
 | 
					// We don't have an /etc/networks, so all inputs return NULL.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,8 +97,11 @@ long sysconf(int name) {
 | 
				
			|||||||
    case _SC_ATEXIT_MAX:        return LONG_MAX;    // Unlimited.
 | 
					    case _SC_ATEXIT_MAX:        return LONG_MAX;    // Unlimited.
 | 
				
			||||||
    case _SC_IOV_MAX:           return UIO_MAXIOV;
 | 
					    case _SC_IOV_MAX:           return UIO_MAXIOV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case _SC_PAGESIZE:          // Fall through, PAGESIZE and PAGE_SIZE always hold the same value.
 | 
					    // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
 | 
				
			||||||
    case _SC_PAGE_SIZE:         return PAGE_SIZE;
 | 
					    case _SC_PAGESIZE:
 | 
				
			||||||
 | 
					    case _SC_PAGE_SIZE:
 | 
				
			||||||
 | 
					      return static_cast<long>(getauxval(AT_PAGESZ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case _SC_XOPEN_UNIX:        return _XOPEN_UNIX;
 | 
					    case _SC_XOPEN_UNIX:        return _XOPEN_UNIX;
 | 
				
			||||||
    case _SC_AIO_LISTIO_MAX:    return _POSIX_AIO_LISTIO_MAX;     // Minimum requirement.
 | 
					    case _SC_AIO_LISTIO_MAX:    return _POSIX_AIO_LISTIO_MAX;     // Minimum requirement.
 | 
				
			||||||
    case _SC_AIO_MAX:           return _POSIX_AIO_MAX;            // Minimum requirement.
 | 
					    case _SC_AIO_MAX:           return _POSIX_AIO_MAX;            // Minimum requirement.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,9 @@
 | 
				
			|||||||
#include <sys/sysinfo.h>
 | 
					#include <sys/sysinfo.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <dirent.h>
 | 
					#include <dirent.h>
 | 
				
			||||||
#include <limits.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "private/ScopedReaddir.h"
 | 
					#include "private/ScopedReaddir.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,7 +94,7 @@ static int __get_meminfo_page_count(const char* pattern) {
 | 
				
			|||||||
  while (fgets(buf, sizeof(buf), fp) != NULL) {
 | 
					  while (fgets(buf, sizeof(buf), fp) != NULL) {
 | 
				
			||||||
    long total;
 | 
					    long total;
 | 
				
			||||||
    if (sscanf(buf, pattern, &total) == 1) {
 | 
					    if (sscanf(buf, pattern, &total) == 1) {
 | 
				
			||||||
      page_count = static_cast<int>(total / (PAGE_SIZE / 1024));
 | 
					      page_count = static_cast<int>(total / (sysconf(_SC_PAGE_SIZE) / 1024));
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,19 +19,24 @@
 | 
				
			|||||||
#include <sys/auxv.h>
 | 
					#include <sys/auxv.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// x86 has a vdso, but there's nothing useful to us in it.
 | 
					#if defined(__aarch64__) || defined(__x86_64__) || defined (__i386__)
 | 
				
			||||||
#if defined(__aarch64__) || defined(__x86_64__)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__aarch64__)
 | 
					#if defined(__aarch64__)
 | 
				
			||||||
#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
 | 
					#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
 | 
				
			||||||
#define VDSO_GETTIMEOFDAY_SYMBOL  "__kernel_gettimeofday"
 | 
					#define VDSO_GETTIMEOFDAY_SYMBOL  "__kernel_gettimeofday"
 | 
				
			||||||
#elif defined(__x86_64__)
 | 
					#elif defined(__x86_64__) || defined(__i386__)
 | 
				
			||||||
#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
 | 
					#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
 | 
				
			||||||
#define VDSO_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
 | 
					#define VDSO_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "private/bionic_prctl.h"
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" int __clock_gettime(int, timespec*);
 | 
					extern "C" int __clock_gettime(int, timespec*);
 | 
				
			||||||
extern "C" int __gettimeofday(timeval*, struct timezone*);
 | 
					extern "C" int __gettimeofday(timeval*, struct timezone*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,28 +51,31 @@ enum {
 | 
				
			|||||||
  VDSO_END
 | 
					  VDSO_END
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static vdso_entry vdso_entries[] = {
 | 
					static union {
 | 
				
			||||||
 | 
					  vdso_entry entries[VDSO_END];
 | 
				
			||||||
 | 
					  char padding[PAGE_SIZE];
 | 
				
			||||||
 | 
					} vdso __attribute__((aligned(PAGE_SIZE))) = {{
 | 
				
			||||||
  [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
 | 
					  [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
 | 
				
			||||||
  [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
 | 
					  [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
 | 
				
			||||||
};
 | 
					}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int clock_gettime(int clock_id, timespec* tp) {
 | 
					int clock_gettime(int clock_id, timespec* tp) {
 | 
				
			||||||
  static int (*vdso_clock_gettime)(int, timespec*) =
 | 
					  int (*vdso_clock_gettime)(int, timespec*) =
 | 
				
			||||||
      reinterpret_cast<int (*)(int, timespec*)>(vdso_entries[VDSO_CLOCK_GETTIME].fn);
 | 
					      reinterpret_cast<int (*)(int, timespec*)>(vdso.entries[VDSO_CLOCK_GETTIME].fn);
 | 
				
			||||||
  return vdso_clock_gettime(clock_id, tp);
 | 
					  return vdso_clock_gettime(clock_id, tp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gettimeofday(timeval* tv, struct timezone* tz) {
 | 
					int gettimeofday(timeval* tv, struct timezone* tz) {
 | 
				
			||||||
  static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
 | 
					  int (*vdso_gettimeofday)(timeval*, struct timezone*) =
 | 
				
			||||||
      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso_entries[VDSO_GETTIMEOFDAY].fn);
 | 
					      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso.entries[VDSO_GETTIMEOFDAY].fn);
 | 
				
			||||||
  return vdso_gettimeofday(tv, tz);
 | 
					  return vdso_gettimeofday(tv, tz);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __libc_init_vdso() {
 | 
					static void __libc_init_vdso_entries() {
 | 
				
			||||||
  // Do we have a vdso?
 | 
					  // Do we have a vdso?
 | 
				
			||||||
  uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
 | 
					  uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
 | 
				
			||||||
  ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
 | 
					  ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
 | 
				
			||||||
  if (vdso_ehdr == NULL) {
 | 
					  if (vdso_ehdr == nullptr) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -85,7 +93,7 @@ void __libc_init_vdso() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Where's the dynamic table?
 | 
					  // Where's the dynamic table?
 | 
				
			||||||
  ElfW(Addr) vdso_addr = 0;
 | 
					  ElfW(Addr) vdso_addr = 0;
 | 
				
			||||||
  ElfW(Dyn)* vdso_dyn = NULL;
 | 
					  ElfW(Dyn)* vdso_dyn = nullptr;
 | 
				
			||||||
  ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
 | 
					  ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
 | 
				
			||||||
  for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
 | 
					  for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
 | 
				
			||||||
    if (vdso_phdr[i].p_type == PT_DYNAMIC) {
 | 
					    if (vdso_phdr[i].p_type == PT_DYNAMIC) {
 | 
				
			||||||
@@ -94,13 +102,13 @@ void __libc_init_vdso() {
 | 
				
			|||||||
      vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
 | 
					      vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (vdso_addr == 0 || vdso_dyn == NULL) {
 | 
					  if (vdso_addr == 0 || vdso_dyn == nullptr) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Where are the string and symbol tables?
 | 
					  // Where are the string and symbol tables?
 | 
				
			||||||
  const char* strtab = NULL;
 | 
					  const char* strtab = nullptr;
 | 
				
			||||||
  ElfW(Sym)* symtab = NULL;
 | 
					  ElfW(Sym)* symtab = nullptr;
 | 
				
			||||||
  for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
 | 
					  for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
 | 
				
			||||||
    if (d->d_tag == DT_STRTAB) {
 | 
					    if (d->d_tag == DT_STRTAB) {
 | 
				
			||||||
      strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
 | 
					      strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
 | 
				
			||||||
@@ -108,20 +116,31 @@ void __libc_init_vdso() {
 | 
				
			|||||||
      symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
 | 
					      symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (strtab == NULL || symtab == NULL) {
 | 
					  if (strtab == nullptr || symtab == nullptr) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Are there any symbols we want?
 | 
					  // Are there any symbols we want?
 | 
				
			||||||
  for (size_t i = 0; i < symbol_count; ++i) {
 | 
					  for (size_t i = 0; i < symbol_count; ++i) {
 | 
				
			||||||
    for (size_t j = 0; j < VDSO_END; ++j) {
 | 
					    for (size_t j = 0; j < VDSO_END; ++j) {
 | 
				
			||||||
      if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
 | 
					      if (strcmp(vdso.entries[j].name, strtab + symtab[i].st_name) == 0) {
 | 
				
			||||||
        vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
 | 
					        vdso.entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void __libc_init_vdso() {
 | 
				
			||||||
 | 
					  __libc_init_vdso_entries();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // We can't use PR_SET_VMA because this isn't an anonymous region.
 | 
				
			||||||
 | 
					  // Long-term we should be able to replace all of this with ifuncs.
 | 
				
			||||||
 | 
					  static_assert(PAGE_SIZE == sizeof(vdso), "sizeof(vdso) too large");
 | 
				
			||||||
 | 
					  if (mprotect(vdso.entries, sizeof(vdso), PROT_READ) == -1) {
 | 
				
			||||||
 | 
					    __libc_fatal("failed to mprotect PROT_READ vdso function pointer table: %s", strerror(errno));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __libc_init_vdso() {
 | 
					void __libc_init_vdso() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,17 +81,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define MB_LEN_MAX 4
 | 
					#define MB_LEN_MAX 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* New code should use sysconf(_SC_PAGE_SIZE) instead. */
 | 
					 | 
				
			||||||
#ifndef PAGE_SIZE
 | 
					 | 
				
			||||||
#define PAGE_SIZE 4096
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifndef PAGESIZE
 | 
					 | 
				
			||||||
#define  PAGESIZE  PAGE_SIZE
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* glibc's PAGE_MASK is the bitwise negation of BSD's! TODO: remove? */
 | 
					 | 
				
			||||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SEM_VALUE_MAX 0x3fffffff
 | 
					#define SEM_VALUE_MAX 0x3fffffff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
 | 
					/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -382,6 +382,16 @@ extern char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
 | 
				
			|||||||
__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
 | 
					__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
 | 
				
			||||||
__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
 | 
					__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern size_t __fread_chk(void * __restrict, size_t, size_t, FILE * __restrict, size_t);
 | 
				
			||||||
 | 
					extern size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
 | 
				
			||||||
 | 
					__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
 | 
				
			||||||
 | 
					__errordecl(__fread_overflow, "fread called with overflowing size * count");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern size_t __fwrite_chk(const void * __restrict, size_t, size_t, FILE * __restrict, size_t);
 | 
				
			||||||
 | 
					extern size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
 | 
				
			||||||
 | 
					__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
 | 
				
			||||||
 | 
					__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__BIONIC_FORTIFY)
 | 
					#if defined(__BIONIC_FORTIFY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__BIONIC_FORTIFY_INLINE
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
@@ -428,6 +438,58 @@ int sprintf(char *dest, const char *format, ...)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 | 
					size_t fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
 | 
				
			||||||
 | 
					    size_t bos = __bos0(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__clang__)
 | 
				
			||||||
 | 
					    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
 | 
				
			||||||
 | 
					        return __fread_real(buf, size, count, stream);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
 | 
				
			||||||
 | 
					        size_t total;
 | 
				
			||||||
 | 
					        if (__size_mul_overflow(size, count, &total)) {
 | 
				
			||||||
 | 
					            __fread_overflow();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (total > bos) {
 | 
				
			||||||
 | 
					            __fread_too_big_error();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return __fread_real(buf, size, count, stream);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return __fread_chk(buf, size, count, stream, bos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 | 
					size_t fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
 | 
				
			||||||
 | 
					    size_t bos = __bos0(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__clang__)
 | 
				
			||||||
 | 
					    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
 | 
				
			||||||
 | 
					        return __fwrite_real(buf, size, count, stream);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
 | 
				
			||||||
 | 
					        size_t total;
 | 
				
			||||||
 | 
					        if (__size_mul_overflow(size, count, &total)) {
 | 
				
			||||||
 | 
					            __fwrite_overflow();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (total > bos) {
 | 
				
			||||||
 | 
					            __fwrite_too_big_error();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return __fwrite_real(buf, size, count, stream);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return __fwrite_chk(buf, size, count, stream, bos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__clang__)
 | 
					#if !defined(__clang__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__BIONIC_FORTIFY_INLINE
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -520,6 +520,11 @@
 | 
				
			|||||||
#include <android/api-level.h>
 | 
					#include <android/api-level.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* glibc compatibility. */
 | 
					/* glibc compatibility. */
 | 
				
			||||||
 | 
					#if __POSIX_VISIBLE >= 200809
 | 
				
			||||||
 | 
					#define __USE_ISOC99 1
 | 
				
			||||||
 | 
					#define __USE_XOPEN2K 1
 | 
				
			||||||
 | 
					#define __USE_XOPEN2K8 1
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#if __LP64__
 | 
					#if __LP64__
 | 
				
			||||||
#define __WORDSIZE 64
 | 
					#define __WORDSIZE 64
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
@@ -573,4 +578,19 @@
 | 
				
			|||||||
#define _BIONIC_NOT_BEFORE_21(x)
 | 
					#define _BIONIC_NOT_BEFORE_21(x)
 | 
				
			||||||
#endif /* __ANDROID_API__ >= 21 */
 | 
					#endif /* __ANDROID_API__ >= 21 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
 | 
				
			||||||
 | 
					#if __LP64__
 | 
				
			||||||
 | 
					#define __size_mul_overflow(a, b, result) __builtin_umull_overflow(a, b, result)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define __size_mul_overflow(a, b, result) __builtin_umul_overflow(a, b, result)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static __inline__ __always_inline int __size_mul_overflow(__SIZE_TYPE__ a, __SIZE_TYPE__ b,
 | 
				
			||||||
 | 
					                                                          __SIZE_TYPE__ *result) {
 | 
				
			||||||
 | 
					    *result = a * b;
 | 
				
			||||||
 | 
					    static const __SIZE_TYPE__ mul_no_overflow = 1UL << (sizeof(__SIZE_TYPE__) * 4);
 | 
				
			||||||
 | 
					    return (a >= mul_no_overflow || b >= mul_no_overflow) && a > 0 && (__SIZE_TYPE__)-1 / a < b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* !_SYS_CDEFS_H_ */
 | 
					#endif /* !_SYS_CDEFS_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								libc/include/sys/fcntl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libc/include/sys/fcntl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
@@ -39,6 +39,10 @@ typedef elf_greg_t elf_gregset_t[NGREG];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef fpregset_t elf_fpregset_t;
 | 
					typedef fpregset_t elf_fpregset_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__i386__)
 | 
				
			||||||
 | 
					typedef struct user_fpxregs_struct elf_fpxregset_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef elf_gregset_t prgregset_t;
 | 
					typedef elf_gregset_t prgregset_t;
 | 
				
			||||||
typedef elf_fpregset_t prfpregset_t;
 | 
					typedef elf_fpregset_t prfpregset_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								libc/include/sys/syslog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libc/include/sys/syslog.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include <syslog.h>
 | 
				
			||||||
@@ -25,6 +25,7 @@
 | 
				
			|||||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
					 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _SYS_TIME_H_
 | 
					#ifndef _SYS_TIME_H_
 | 
				
			||||||
#define _SYS_TIME_H_
 | 
					#define _SYS_TIME_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,6 +33,9 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
#include <linux/time.h>
 | 
					#include <linux/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* POSIX says <sys/time.h> gets you most of <sys/select.h> and may get you all of it. */
 | 
				
			||||||
 | 
					#include <sys/select.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__BEGIN_DECLS
 | 
					__BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int gettimeofday(struct timeval *, struct timezone *);
 | 
					extern int gettimeofday(struct timeval *, struct timezone *);
 | 
				
			||||||
@@ -73,6 +77,15 @@ extern int utimes(const char *, const struct timeval *);
 | 
				
			|||||||
        }                                             \
 | 
					        }                                             \
 | 
				
			||||||
    } while (0)
 | 
					    } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TIMEVAL_TO_TIMESPEC(tv, ts) {     \
 | 
				
			||||||
 | 
					    (ts)->tv_sec = (tv)->tv_sec;          \
 | 
				
			||||||
 | 
					    (ts)->tv_nsec = (tv)->tv_usec * 1000; \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define TIMESPEC_TO_TIMEVAL(tv, ts) {     \
 | 
				
			||||||
 | 
					    (tv)->tv_sec = (ts)->tv_sec;          \
 | 
				
			||||||
 | 
					    (tv)->tv_usec = (ts)->tv_nsec / 1000; \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__END_DECLS
 | 
					__END_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _SYS_TIME_H_ */
 | 
					#endif /* _SYS_TIME_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								libc/include/sys/unistd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libc/include/sys/unistd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
@@ -30,11 +30,13 @@
 | 
				
			|||||||
#define _SYS_USER_H_
 | 
					#define _SYS_USER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
#include <limits.h> /* For PAGE_SIZE. */
 | 
					 | 
				
			||||||
#include <stddef.h> /* For size_t. */
 | 
					#include <stddef.h> /* For size_t. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__BEGIN_DECLS
 | 
					__BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PAGE_SIZE 4096
 | 
				
			||||||
 | 
					#define PAGE_MASK (~(PAGE_SIZE - 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if __i386__
 | 
					#if __i386__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct user_fpregs_struct {
 | 
					struct user_fpregs_struct {
 | 
				
			||||||
@@ -47,7 +49,7 @@ struct user_fpregs_struct {
 | 
				
			|||||||
  long fos;
 | 
					  long fos;
 | 
				
			||||||
  long st_space[20];
 | 
					  long st_space[20];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
struct user_fxsr_struct {
 | 
					struct user_fpxregs_struct {
 | 
				
			||||||
  unsigned short cwd;
 | 
					  unsigned short cwd;
 | 
				
			||||||
  unsigned short swd;
 | 
					  unsigned short swd;
 | 
				
			||||||
  unsigned short twd;
 | 
					  unsigned short twd;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,28 +1 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
					 | 
				
			||||||
 * All rights reserved.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
 * modification, are permitted provided that the following conditions
 | 
					 | 
				
			||||||
 * are met:
 | 
					 | 
				
			||||||
 *  * Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
 *    notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
					 | 
				
			||||||
 *    notice, this list of conditions and the following disclaimer in
 | 
					 | 
				
			||||||
 *    the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
 *    distribution.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
					 | 
				
			||||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
					 | 
				
			||||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
					 | 
				
			||||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
					 | 
				
			||||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
					 | 
				
			||||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
					 | 
				
			||||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
					 | 
				
			||||||
 * SUCH DAMAGE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include <linux/vt.h>
 | 
					#include <linux/vt.h>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								libc/include/syscall.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libc/include/syscall.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
							
								
								
									
										119
									
								
								libc/include/sysexits.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								libc/include/sysexits.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					/*	$OpenBSD: sysexits.h,v 1.5 2003/06/02 19:34:12 millert Exp $	*/
 | 
				
			||||||
 | 
					/*	$NetBSD: sysexits.h,v 1.4 1994/10/26 00:56:33 cgd Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 1987 Regents of the University of California.
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *    documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. Neither the name of the University nor the names of its contributors
 | 
				
			||||||
 | 
					 *    may be used to endorse or promote products derived from this software
 | 
				
			||||||
 | 
					 *    without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
				
			||||||
 | 
					 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
				
			||||||
 | 
					 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
				
			||||||
 | 
					 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
				
			||||||
 | 
					 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	@(#)sysexits.h	4.8 (Berkeley) 4/3/91
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef	_SYSEXITS_H_
 | 
				
			||||||
 | 
					#define	_SYSEXITS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  SYSEXITS.H -- Exit status codes for system programs.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	This include file attempts to categorize possible error
 | 
				
			||||||
 | 
					 *	exit statuses for system programs, notably delivermail
 | 
				
			||||||
 | 
					 *	and the Berkeley network.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	Error numbers begin at EX__BASE to reduce the possibility of
 | 
				
			||||||
 | 
					 *	clashing with other exit statuses that random programs may
 | 
				
			||||||
 | 
					 *	already return.  The meaning of the codes is approximately
 | 
				
			||||||
 | 
					 *	as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *	EX_USAGE -- The command was used incorrectly, e.g., with
 | 
				
			||||||
 | 
					 *		the wrong number of arguments, a bad flag, a bad
 | 
				
			||||||
 | 
					 *		syntax in a parameter, or whatever.
 | 
				
			||||||
 | 
					 *	EX_DATAERR -- The input data was incorrect in some way.
 | 
				
			||||||
 | 
					 *		This should only be used for user's data & not
 | 
				
			||||||
 | 
					 *		system files.
 | 
				
			||||||
 | 
					 *	EX_NOINPUT -- An input file (not a system file) did not
 | 
				
			||||||
 | 
					 *		exist or was not readable.  This could also include
 | 
				
			||||||
 | 
					 *		errors like "No message" to a mailer (if it cared
 | 
				
			||||||
 | 
					 *		to catch it).
 | 
				
			||||||
 | 
					 *	EX_NOUSER -- The user specified did not exist.  This might
 | 
				
			||||||
 | 
					 *		be used for mail addresses or remote logins.
 | 
				
			||||||
 | 
					 *	EX_NOHOST -- The host specified did not exist.  This is used
 | 
				
			||||||
 | 
					 *		in mail addresses or network requests.
 | 
				
			||||||
 | 
					 *	EX_UNAVAILABLE -- A service is unavailable.  This can occur
 | 
				
			||||||
 | 
					 *		if a support program or file does not exist.  This
 | 
				
			||||||
 | 
					 *		can also be used as a catchall message when something
 | 
				
			||||||
 | 
					 *		you wanted to do doesn't work, but you don't know
 | 
				
			||||||
 | 
					 *		why.
 | 
				
			||||||
 | 
					 *	EX_SOFTWARE -- An internal software error has been detected.
 | 
				
			||||||
 | 
					 *		This should be limited to non-operating system related
 | 
				
			||||||
 | 
					 *		errors as possible.
 | 
				
			||||||
 | 
					 *	EX_OSERR -- An operating system error has been detected.
 | 
				
			||||||
 | 
					 *		This is intended to be used for such things as "cannot
 | 
				
			||||||
 | 
					 *		fork", "cannot create pipe", or the like.  It includes
 | 
				
			||||||
 | 
					 *		things like getuid returning a user that does not
 | 
				
			||||||
 | 
					 *		exist in the passwd file.
 | 
				
			||||||
 | 
					 *	EX_OSFILE -- Some system file (e.g., /etc/passwd, /var/run/utmp,
 | 
				
			||||||
 | 
					 *		etc.) does not exist, cannot be opened, or has some
 | 
				
			||||||
 | 
					 *		sort of error (e.g., syntax error).
 | 
				
			||||||
 | 
					 *	EX_CANTCREAT -- A (user specified) output file cannot be
 | 
				
			||||||
 | 
					 *		created.
 | 
				
			||||||
 | 
					 *	EX_IOERR -- An error occurred while doing I/O on some file.
 | 
				
			||||||
 | 
					 *	EX_TEMPFAIL -- temporary failure, indicating something that
 | 
				
			||||||
 | 
					 *		is not really an error.  In sendmail, this means
 | 
				
			||||||
 | 
					 *		that a mailer (e.g.) could not create a connection,
 | 
				
			||||||
 | 
					 *		and the request should be reattempted later.
 | 
				
			||||||
 | 
					 *	EX_PROTOCOL -- the remote system returned something that
 | 
				
			||||||
 | 
					 *		was "not possible" during a protocol exchange.
 | 
				
			||||||
 | 
					 *	EX_NOPERM -- You did not have sufficient permission to
 | 
				
			||||||
 | 
					 *		perform the operation.  This is not intended for
 | 
				
			||||||
 | 
					 *		file system problems, which should use EX_NOINPUT or
 | 
				
			||||||
 | 
					 *		EX_CANTCREAT, but rather for higher level permissions.
 | 
				
			||||||
 | 
					 *	EX_CONFIG -- Something was found in an unconfigured or
 | 
				
			||||||
 | 
					 *		misconfigured state.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EX_OK		0	/* successful termination */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EX__BASE	64	/* base value for error messages */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EX_USAGE	64	/* command line usage error */
 | 
				
			||||||
 | 
					#define EX_DATAERR	65	/* data format error */
 | 
				
			||||||
 | 
					#define EX_NOINPUT	66	/* cannot open input */
 | 
				
			||||||
 | 
					#define EX_NOUSER	67	/* addressee unknown */
 | 
				
			||||||
 | 
					#define EX_NOHOST	68	/* host name unknown */
 | 
				
			||||||
 | 
					#define EX_UNAVAILABLE	69	/* service unavailable */
 | 
				
			||||||
 | 
					#define EX_SOFTWARE	70	/* internal software error */
 | 
				
			||||||
 | 
					#define EX_OSERR	71	/* system error (e.g., can't fork) */
 | 
				
			||||||
 | 
					#define EX_OSFILE	72	/* critical OS file missing */
 | 
				
			||||||
 | 
					#define EX_CANTCREAT	73	/* can't create (user) output file */
 | 
				
			||||||
 | 
					#define EX_IOERR	74	/* input/output error */
 | 
				
			||||||
 | 
					#define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
 | 
				
			||||||
 | 
					#define EX_PROTOCOL	76	/* remote error in protocol */
 | 
				
			||||||
 | 
					#define EX_NOPERM	77	/* permission denied */
 | 
				
			||||||
 | 
					#define EX_CONFIG	78	/* configuration error */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EX__MAX		78	/* maximum listed value */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* !_SYSEXITS_H_ */
 | 
				
			||||||
@@ -34,6 +34,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
__BEGIN_DECLS
 | 
					__BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
 | 
				
			||||||
 | 
					typedef __CHAR16_TYPE__ char16_t;
 | 
				
			||||||
 | 
					typedef __CHAR32_TYPE__ char32_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define __STD_UTF_16__ 1
 | 
					#define __STD_UTF_16__ 1
 | 
				
			||||||
#define __STD_UTF_32__ 1
 | 
					#define __STD_UTF_32__ 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,6 +224,10 @@ extern int   tcsetpgrp(int fd, pid_t _pid);
 | 
				
			|||||||
    } while (_rc == -1 && errno == EINTR); \
 | 
					    } while (_rc == -1 && errno == EINTR); \
 | 
				
			||||||
    _rc; })
 | 
					    _rc; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char* __getcwd_chk(char*, size_t, size_t);
 | 
				
			||||||
 | 
					__errordecl(__getcwd_dest_size_error, "getcwd called with size bigger than destination");
 | 
				
			||||||
 | 
					extern char* __getcwd_real(char*, size_t) __RENAME(getcwd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
 | 
					extern ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
 | 
				
			||||||
__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
 | 
					__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
 | 
				
			||||||
__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
 | 
					__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
 | 
				
			||||||
@@ -251,6 +255,37 @@ extern ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if defined(__BIONIC_FORTIFY)
 | 
					#if defined(__BIONIC_FORTIFY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 | 
					char* getcwd(char* buf, size_t size) {
 | 
				
			||||||
 | 
					    size_t bos = __bos(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__clang__)
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Work around LLVM's incorrect __builtin_object_size implementation here
 | 
				
			||||||
 | 
					     * to avoid needing the workaround in the __getcwd_chk ABI forever.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * https://llvm.org/bugs/show_bug.cgi?id=23277
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (buf == NULL) {
 | 
				
			||||||
 | 
					        bos = __BIONIC_FORTIFY_UNKNOWN_SIZE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
 | 
				
			||||||
 | 
					        return __getcwd_real(buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size > bos)) {
 | 
				
			||||||
 | 
					        __getcwd_dest_size_error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size <= bos)) {
 | 
				
			||||||
 | 
					        return __getcwd_real(buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return __getcwd_chk(buf, size, bos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__USE_FILE_OFFSET64)
 | 
					#if defined(__USE_FILE_OFFSET64)
 | 
				
			||||||
#define __PREAD_PREFIX(x) __pread64_ ## x
 | 
					#define __PREAD_PREFIX(x) __pread64_ ## x
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								libc/include/wait.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libc/include/wait.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					#include <sys/wait.h>
 | 
				
			||||||
@@ -961,29 +961,30 @@ struct drm_radeon_cs {
 | 
				
			|||||||
#define RADEON_INFO_GTT_USAGE 0x1f
 | 
					#define RADEON_INFO_GTT_USAGE 0x1f
 | 
				
			||||||
#define RADEON_INFO_ACTIVE_CU_COUNT 0x20
 | 
					#define RADEON_INFO_ACTIVE_CU_COUNT 0x20
 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					#define RADEON_INFO_VA_UNMAP_WORKING 0x25
 | 
				
			||||||
struct drm_radeon_info {
 | 
					struct drm_radeon_info {
 | 
				
			||||||
  uint32_t request;
 | 
					  uint32_t request;
 | 
				
			||||||
  uint32_t pad;
 | 
					  uint32_t pad;
 | 
				
			||||||
  uint64_t value;
 | 
					 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					  uint64_t value;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8
 | 
					#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_1D 13
 | 
					#define SI_TILE_MODE_COLOR_1D 13
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
 | 
					 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_8BPP 14
 | 
					#define SI_TILE_MODE_COLOR_2D_8BPP 14
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_16BPP 15
 | 
					#define SI_TILE_MODE_COLOR_2D_16BPP 15
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_32BPP 16
 | 
					#define SI_TILE_MODE_COLOR_2D_32BPP 16
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_64BPP 17
 | 
					 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					#define SI_TILE_MODE_COLOR_2D_64BPP 17
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11
 | 
					#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11
 | 
				
			||||||
#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12
 | 
					#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12
 | 
				
			||||||
#define SI_TILE_MODE_DEPTH_STENCIL_1D 4
 | 
					#define SI_TILE_MODE_DEPTH_STENCIL_1D 4
 | 
				
			||||||
#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
 | 
					 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
 | 
				
			||||||
#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3
 | 
					#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3
 | 
				
			||||||
#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3
 | 
					#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3
 | 
				
			||||||
#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2
 | 
					#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2
 | 
				
			||||||
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
 | 
					 | 
				
			||||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
					/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
				
			||||||
 | 
					#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,5 +16,5 @@
 | 
				
			|||||||
 ***
 | 
					 ***
 | 
				
			||||||
 ****************************************************************************
 | 
					 ****************************************************************************
 | 
				
			||||||
 ****************************************************************************/
 | 
					 ****************************************************************************/
 | 
				
			||||||
#define LINUX_VERSION_CODE 201226
 | 
					#define LINUX_VERSION_CODE 201234
 | 
				
			||||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 | 
					#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1332,6 +1332,15 @@ LIBC {
 | 
				
			|||||||
    *;
 | 
					    *;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIBC_N {
 | 
				
			||||||
 | 
					  global:
 | 
				
			||||||
 | 
					    __fread_chk;
 | 
				
			||||||
 | 
					    __fwrite_chk;
 | 
				
			||||||
 | 
					    __getcwd_chk;
 | 
				
			||||||
 | 
					    getgrgid_r;
 | 
				
			||||||
 | 
					    getgrnam_r;
 | 
				
			||||||
 | 
					} LIBC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LIBC_PRIVATE {
 | 
					LIBC_PRIVATE {
 | 
				
			||||||
  global:
 | 
					  global:
 | 
				
			||||||
    ___Unwind_Backtrace; # arm
 | 
					    ___Unwind_Backtrace; # arm
 | 
				
			||||||
@@ -1453,4 +1462,4 @@ LIBC_PRIVATE {
 | 
				
			|||||||
    SHA1Init; # arm x86 mips
 | 
					    SHA1Init; # arm x86 mips
 | 
				
			||||||
    SHA1Transform; # arm x86 mips
 | 
					    SHA1Transform; # arm x86 mips
 | 
				
			||||||
    SHA1Update; # arm x86 mips
 | 
					    SHA1Update; # arm x86 mips
 | 
				
			||||||
} LIBC;
 | 
					} LIBC_N;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								libc/private/bionic_page.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								libc/private/bionic_page.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _BIONIC_PAGE_H_
 | 
				
			||||||
 | 
					#define _BIONIC_PAGE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get PAGE_SIZE and PAGE_MASK.
 | 
				
			||||||
 | 
					#include <sys/user.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the address of the page containing address 'x'.
 | 
				
			||||||
 | 
					#define PAGE_START(x) ((x) & PAGE_MASK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the offset of address 'x' in its page.
 | 
				
			||||||
 | 
					#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the address of the next page after address 'x', unless 'x' is
 | 
				
			||||||
 | 
					// itself at the start of a page.
 | 
				
			||||||
 | 
					#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _BIONIC_PAGE_H_
 | 
				
			||||||
@@ -67,6 +67,9 @@ enum {
 | 
				
			|||||||
  TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
 | 
					  TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
 | 
				
			||||||
  TLS_SLOT_DLERROR,
 | 
					  TLS_SLOT_DLERROR,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Fast storage for Thread::Current() in ART.
 | 
				
			||||||
 | 
					  TLS_SLOT_ART_THREAD_SELF,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BIONIC_TLS_SLOTS // Must come last!
 | 
					  BIONIC_TLS_SLOTS // Must come last!
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,7 +117,7 @@ __END_DECLS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if defined(__cplusplus)
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
class KernelArgumentBlock;
 | 
					class KernelArgumentBlock;
 | 
				
			||||||
extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
 | 
					extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
 | 
					#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,10 @@
 | 
				
			|||||||
#include "atexit.h"
 | 
					#include "atexit.h"
 | 
				
			||||||
#include "private/thread_private.h"
 | 
					#include "private/thread_private.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* BEGIN android-changed */
 | 
				
			||||||
 | 
					#include "private/bionic_prctl.h"
 | 
				
			||||||
 | 
					/* END android-changed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct atexit {
 | 
					struct atexit {
 | 
				
			||||||
	struct atexit *next;		/* next in list */
 | 
						struct atexit *next;		/* next in list */
 | 
				
			||||||
	int ind;			/* next index in this table */
 | 
						int ind;			/* next index in this table */
 | 
				
			||||||
@@ -95,6 +99,10 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
 | 
				
			|||||||
		    MAP_ANON | MAP_PRIVATE, -1, 0);
 | 
							    MAP_ANON | MAP_PRIVATE, -1, 0);
 | 
				
			||||||
		if (p == MAP_FAILED)
 | 
							if (p == MAP_FAILED)
 | 
				
			||||||
			goto unlock;
 | 
								goto unlock;
 | 
				
			||||||
 | 
					/* BEGIN android-changed */
 | 
				
			||||||
 | 
							prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
 | 
				
			||||||
 | 
							    "atexit handlers");
 | 
				
			||||||
 | 
					/* END android-changed */
 | 
				
			||||||
		if (__atexit == NULL) {
 | 
							if (__atexit == NULL) {
 | 
				
			||||||
			memset(&p->fns[0], 0, sizeof(p->fns[0]));
 | 
								memset(&p->fns[0], 0, sizeof(p->fns[0]));
 | 
				
			||||||
			p->ind = 1;
 | 
								p->ind = 1;
 | 
				
			||||||
@@ -204,6 +212,10 @@ __atexit_register_cleanup(void (*func)(void))
 | 
				
			|||||||
		    MAP_ANON | MAP_PRIVATE, -1, 0);
 | 
							    MAP_ANON | MAP_PRIVATE, -1, 0);
 | 
				
			||||||
		if (p == MAP_FAILED)
 | 
							if (p == MAP_FAILED)
 | 
				
			||||||
			goto unlock;
 | 
								goto unlock;
 | 
				
			||||||
 | 
					/* BEGIN android-changed */
 | 
				
			||||||
 | 
							prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
 | 
				
			||||||
 | 
							    "atexit handlers");
 | 
				
			||||||
 | 
					/* END android-changed */
 | 
				
			||||||
		p->ind = 1;
 | 
							p->ind = 1;
 | 
				
			||||||
		p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
 | 
							p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
 | 
				
			||||||
		    sizeof(p->fns[0]);
 | 
							    sizeof(p->fns[0]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,21 @@ arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
 | 
				
			|||||||
sys.stderr.write('Checking symbols for arch "%s"...\n' % arch)
 | 
					sys.stderr.write('Checking symbols for arch "%s"...\n' % arch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def GetSymbols(library, functions_or_variables):
 | 
					def GetSymbols(library, functions_or_variables):
 | 
				
			||||||
 | 
					  global api
 | 
				
			||||||
 | 
					  global arch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  api = '9'
 | 
					  api = '9'
 | 
				
			||||||
  if library == 'libm' and arch == 'arm':
 | 
					  if library == 'libm' and arch == 'arm':
 | 
				
			||||||
    api = '3'
 | 
					    api = '3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # There were no 64-bit ABIs before API level 21.
 | 
				
			||||||
 | 
					  if '64' in arch:
 | 
				
			||||||
 | 
					    api = '21'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # What GCC calls aarch64, Android calls arm64.
 | 
				
			||||||
 | 
					  if arch == 'aarch64':
 | 
				
			||||||
 | 
					    arch = 'arm64'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  path = '%s/development/ndk/platforms/android-%s/arch-%s/symbols/%s.so.%s.txt' % (os.environ['ANDROID_BUILD_TOP'], api, arch, library, functions_or_variables)
 | 
					  path = '%s/development/ndk/platforms/android-%s/arch-%s/symbols/%s.so.%s.txt' % (os.environ['ANDROID_BUILD_TOP'], api, arch, library, functions_or_variables)
 | 
				
			||||||
  symbols = set()
 | 
					  symbols = set()
 | 
				
			||||||
  for line in open(path, 'r'):
 | 
					  for line in open(path, 'r'):
 | 
				
			||||||
@@ -26,7 +38,11 @@ def GetSymbols(library, functions_or_variables):
 | 
				
			|||||||
def CheckSymbols(library, functions_or_variables):
 | 
					def CheckSymbols(library, functions_or_variables):
 | 
				
			||||||
  expected_symbols = GetSymbols(library, functions_or_variables)
 | 
					  expected_symbols = GetSymbols(library, functions_or_variables)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  so_file = '%s/system/lib/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], library)
 | 
					  lib_dir = 'lib'
 | 
				
			||||||
 | 
					  if '64' in arch:
 | 
				
			||||||
 | 
					    lib_dir = 'lib64'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  so_file = '%s/system/%s/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], lib_dir, library)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Example readelf output:
 | 
					  # Example readelf output:
 | 
				
			||||||
  #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf
 | 
					  #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf
 | 
				
			||||||
@@ -38,7 +54,7 @@ def CheckSymbols(library, functions_or_variables):
 | 
				
			|||||||
  r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
 | 
					  r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  actual_symbols = set()
 | 
					  actual_symbols = set()
 | 
				
			||||||
  for line in subprocess.check_output(['readelf', '--dyn-syms', so_file]).split('\n'):
 | 
					  for line in subprocess.check_output(['readelf', '-W', '--dyn-syms', so_file]).split('\n'):
 | 
				
			||||||
    m = r.match(line)
 | 
					    m = r.match(line)
 | 
				
			||||||
    if m:
 | 
					    if m:
 | 
				
			||||||
      symbol = string.split(m.group(2), '@')[0]
 | 
					      symbol = string.split(m.group(2), '@')[0]
 | 
				
			||||||
@@ -55,6 +71,12 @@ def CheckSymbols(library, functions_or_variables):
 | 
				
			|||||||
    for miss in sorted(missing):
 | 
					    for miss in sorted(missing):
 | 
				
			||||||
      sys.stderr.write('  %s\n' % miss)
 | 
					      sys.stderr.write('  %s\n' % miss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  extra = actual_symbols - expected_symbols
 | 
				
			||||||
 | 
					  if len(extra) > 0:
 | 
				
			||||||
 | 
					    sys.stderr.write('%d extra %s in %s for %s:\n' % (len(extra), functions_or_variables, library, arch))
 | 
				
			||||||
 | 
					    for s in sorted(extra):
 | 
				
			||||||
 | 
					      sys.stderr.write('  %s\n' % s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return len(missing) == 0
 | 
					  return len(missing) == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CheckSymbols("libc", "functions")
 | 
					CheckSymbols("libc", "functions")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,4 @@
 | 
				
			|||||||
#define __readlockenv() 0
 | 
					#define __readlockenv() 0
 | 
				
			||||||
#define __unlockenv() 0
 | 
					#define __unlockenv() 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stddef.h>
 | 
					 | 
				
			||||||
__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
/*	$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $	*/
 | 
					/*	$NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-
 | 
					/*-
 | 
				
			||||||
 * Copyright (c) 1992, 1993, 1994
 | 
					 * Copyright (c) 1992, 1993, 1994
 | 
				
			||||||
@@ -76,7 +76,7 @@
 | 
				
			|||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";
 | 
					static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
__RCSID("$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $");
 | 
					__RCSID("$NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif /* LIBC_SCCS and not lint */
 | 
					#endif /* LIBC_SCCS and not lint */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -262,11 +262,12 @@ regcomp(
 | 
				
			|||||||
		len = strlen(pattern);
 | 
							len = strlen(pattern);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* do the mallocs early so failure handling is easy */
 | 
						/* do the mallocs early so failure handling is easy */
 | 
				
			||||||
	g = malloc(sizeof(struct re_guts) + (NC - 1) * sizeof(cat_t));
 | 
						g = (struct re_guts *)malloc(sizeof(struct re_guts) +
 | 
				
			||||||
 | 
												(NC-1)*sizeof(cat_t));
 | 
				
			||||||
	if (g == NULL)
 | 
						if (g == NULL)
 | 
				
			||||||
		return(REG_ESPACE);
 | 
							return(REG_ESPACE);
 | 
				
			||||||
	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
 | 
						p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
 | 
				
			||||||
	p->strip = calloc(p->ssize, sizeof(sop));
 | 
						p->strip = malloc(p->ssize * sizeof(sop));
 | 
				
			||||||
	p->slen = 0;
 | 
						p->slen = 0;
 | 
				
			||||||
	if (p->strip == NULL) {
 | 
						if (p->strip == NULL) {
 | 
				
			||||||
		free(g);
 | 
							free(g);
 | 
				
			||||||
@@ -1074,19 +1075,19 @@ ordinary(
 | 
				
			|||||||
    int ch)
 | 
					    int ch)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	cat_t *cap;
 | 
						cat_t *cap;
 | 
				
			||||||
	unsigned char uc = (unsigned char)ch;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_DIAGASSERT(p != NULL);
 | 
						_DIAGASSERT(p != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cap = p->g->categories;
 | 
						cap = p->g->categories;
 | 
				
			||||||
	if ((p->g->cflags & REG_ICASE) && isalpha(uc) && othercase(uc) != uc)
 | 
						if ((p->g->cflags®_ICASE) && isalpha((unsigned char) ch)
 | 
				
			||||||
		bothcases(p, uc);
 | 
						    && othercase((unsigned char) ch) != (unsigned char) ch)
 | 
				
			||||||
 | 
							bothcases(p, (unsigned char) ch);
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		EMIT(OCHAR, (sopno)uc);
 | 
							EMIT(OCHAR, (sopno)(unsigned char)ch);
 | 
				
			||||||
		if (cap[uc] == 0) {
 | 
							if (cap[ch] == 0) {
 | 
				
			||||||
			_DIAGASSERT(__type_fit(unsigned char,
 | 
								_DIAGASSERT(__type_fit(unsigned char,
 | 
				
			||||||
			    p->g->ncategories + 1));
 | 
								    p->g->ncategories + 1));
 | 
				
			||||||
			cap[uc] = (unsigned char)p->g->ncategories++;
 | 
								cap[ch] = (unsigned char)p->g->ncategories++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1235,7 +1236,6 @@ allocset(
 | 
				
			|||||||
	cset *cs;
 | 
						cset *cs;
 | 
				
			||||||
	size_t css;
 | 
						size_t css;
 | 
				
			||||||
	size_t i;
 | 
						size_t i;
 | 
				
			||||||
	void *old_ptr;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_DIAGASSERT(p != NULL);
 | 
						_DIAGASSERT(p != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1248,18 +1248,28 @@ allocset(
 | 
				
			|||||||
		nbytes = nc / CHAR_BIT * css;
 | 
							nbytes = nc / CHAR_BIT * css;
 | 
				
			||||||
		if (MEMSIZE(p) > MEMLIMIT)
 | 
							if (MEMSIZE(p) > MEMLIMIT)
 | 
				
			||||||
			goto oomem;
 | 
								goto oomem;
 | 
				
			||||||
		if (reallocarr(&p->g->sets, nc, sizeof(cset)))
 | 
							if (p->g->sets == NULL)
 | 
				
			||||||
			goto oomem;
 | 
								p->g->sets = malloc(nc * sizeof(cset));
 | 
				
			||||||
		old_ptr = p->g->setbits;
 | 
							else
 | 
				
			||||||
		if (reallocarr(&p->g->setbits, nc / CHAR_BIT, css)) {
 | 
								p->g->sets = realloc(p->g->sets, nc * sizeof(cset));
 | 
				
			||||||
			free(old_ptr);
 | 
							if (p->g->setbits == NULL)
 | 
				
			||||||
			goto oomem;
 | 
								p->g->setbits = malloc(nbytes);
 | 
				
			||||||
		}
 | 
							else {
 | 
				
			||||||
		if (old_ptr != p->g->setbits) {
 | 
								p->g->setbits = realloc(p->g->setbits, nbytes);
 | 
				
			||||||
 | 
								/* xxx this isn't right if setbits is now NULL */
 | 
				
			||||||
			for (i = 0; i < no; i++)
 | 
								for (i = 0; i < no; i++)
 | 
				
			||||||
				p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
 | 
									p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		(void) memset((char *)p->g->setbits + (nbytes - css), 0, css);
 | 
							if (p->g->sets != NULL && p->g->setbits != NULL)
 | 
				
			||||||
 | 
								(void) memset((char *)p->g->setbits + (nbytes - css),
 | 
				
			||||||
 | 
													0, css);
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
					oomem:
 | 
				
			||||||
 | 
								no = 0;
 | 
				
			||||||
 | 
								SETERROR(REG_ESPACE);
 | 
				
			||||||
 | 
								/* caller's responsibility not to do set ops */
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cs = &p->g->sets[no];
 | 
						cs = &p->g->sets[no];
 | 
				
			||||||
@@ -1270,11 +1280,6 @@ allocset(
 | 
				
			|||||||
	cs->multis = NULL;
 | 
						cs->multis = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return(cs);
 | 
						return(cs);
 | 
				
			||||||
 | 
					 | 
				
			||||||
oomem:
 | 
					 | 
				
			||||||
	SETERROR(REG_ESPACE);
 | 
					 | 
				
			||||||
	/* caller's responsibility not to do set ops */
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -1758,18 +1763,30 @@ dofwd(
 | 
				
			|||||||
 == static void enlarge(struct parse *p, sopno size);
 | 
					 == static void enlarge(struct parse *p, sopno size);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
enlarge(struct parse *p, sopno size)
 | 
					enlarge(
 | 
				
			||||||
 | 
					    struct parse *p,
 | 
				
			||||||
 | 
					    sopno size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						sop *sp;
 | 
				
			||||||
 | 
						sopno osize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_DIAGASSERT(p != NULL);
 | 
						_DIAGASSERT(p != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (p->ssize >= size)
 | 
						if (p->ssize >= size)
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (MEMSIZE(p) > MEMLIMIT || reallocarr(&p->strip, size, sizeof(sop))) {
 | 
						osize = p->ssize;
 | 
				
			||||||
 | 
						p->ssize = size;
 | 
				
			||||||
 | 
						if (MEMSIZE(p) > MEMLIMIT)
 | 
				
			||||||
 | 
							goto oomem;
 | 
				
			||||||
 | 
						sp = realloc(p->strip, p->ssize * sizeof(sop));
 | 
				
			||||||
 | 
						if (sp == NULL) {
 | 
				
			||||||
 | 
					oomem:
 | 
				
			||||||
 | 
							p->ssize = osize;
 | 
				
			||||||
		SETERROR(REG_ESPACE);
 | 
							SETERROR(REG_ESPACE);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p->ssize = size;
 | 
						p->strip = sp;
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1787,9 +1804,11 @@ stripsnug(
 | 
				
			|||||||
	_DIAGASSERT(g != NULL);
 | 
						_DIAGASSERT(g != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g->nstates = p->slen;
 | 
						g->nstates = p->slen;
 | 
				
			||||||
 | 
						g->strip = realloc(p->strip, p->slen * sizeof(sop));
 | 
				
			||||||
 | 
						if (g->strip == NULL) {
 | 
				
			||||||
 | 
							SETERROR(REG_ESPACE);
 | 
				
			||||||
		g->strip = p->strip;
 | 
							g->strip = p->strip;
 | 
				
			||||||
	reallocarr(&g->strip, p->slen, sizeof(sop));
 | 
						}
 | 
				
			||||||
	/* Ignore error as tries to free memory only. */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,95 +0,0 @@
 | 
				
			|||||||
/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*-
 | 
					 | 
				
			||||||
 * Copyright (c) 2015 Joerg Sonnenberger <joerg@NetBSD.org>.
 | 
					 | 
				
			||||||
 * All rights reserved.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
 * modification, are permitted provided that the following conditions
 | 
					 | 
				
			||||||
 * are met:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 1. Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
 *    notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
					 | 
				
			||||||
 *    notice, this list of conditions and the following disclaimer in
 | 
					 | 
				
			||||||
 *    the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
 *    distribution.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
					 | 
				
			||||||
 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
					 | 
				
			||||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
					 | 
				
			||||||
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
					 | 
				
			||||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
					 | 
				
			||||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
					 | 
				
			||||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
					 | 
				
			||||||
 * SUCH DAMAGE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if HAVE_NBTOOL_CONFIG_H
 | 
					 | 
				
			||||||
#include "nbtool_config.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					 | 
				
			||||||
__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "namespace.h"
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
/* Old POSIX has SIZE_MAX in limits.h */
 | 
					 | 
				
			||||||
#include <limits.h>
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef _LIBC
 | 
					 | 
				
			||||||
#ifdef __weak_alias
 | 
					 | 
				
			||||||
__weak_alias(reallocarr, _reallocarr)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if !HAVE_REALLOCARR
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
reallocarr(void *ptr, size_t number, size_t size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int saved_errno, result;
 | 
					 | 
				
			||||||
	void *optr;
 | 
					 | 
				
			||||||
	void *nptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	saved_errno = errno;
 | 
					 | 
				
			||||||
	memcpy(&optr, ptr, sizeof(ptr));
 | 
					 | 
				
			||||||
	if (number == 0 || size == 0) {
 | 
					 | 
				
			||||||
		free(optr);
 | 
					 | 
				
			||||||
		nptr = NULL;
 | 
					 | 
				
			||||||
		memcpy(ptr, &nptr, sizeof(ptr));
 | 
					 | 
				
			||||||
		errno = saved_errno;
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Try to avoid division here.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * It isn't possible to overflow during multiplication if neither
 | 
					 | 
				
			||||||
	 * operand uses any of the most significant half of the bits.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (__predict_false((number|size) >= SQRT_SIZE_MAX &&
 | 
					 | 
				
			||||||
	                    number > SIZE_MAX / size)) {
 | 
					 | 
				
			||||||
		errno = saved_errno;
 | 
					 | 
				
			||||||
		return EOVERFLOW;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nptr = realloc(optr, number * size);
 | 
					 | 
				
			||||||
	if (__predict_false(nptr == NULL)) {
 | 
					 | 
				
			||||||
		result = errno;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		result = 0;
 | 
					 | 
				
			||||||
		memcpy(ptr, &nptr, sizeof(ptr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	errno = saved_errno;
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -27,6 +27,8 @@
 | 
				
			|||||||
#include <pthread.h>
 | 
					#include <pthread.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "private/bionic_prctl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Android gets these from "thread_private.h".
 | 
					// Android gets these from "thread_private.h".
 | 
				
			||||||
#include "thread_private.h"
 | 
					#include "thread_private.h"
 | 
				
			||||||
//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
 | 
					//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
 | 
				
			||||||
@@ -76,12 +78,18 @@ _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
 | 
				
			|||||||
	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
 | 
						    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsp, sizeof(**rsp),
 | 
				
			||||||
 | 
						    "arc4random _rs structure");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
 | 
						if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
 | 
				
			||||||
	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
 | 
						    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
 | 
				
			||||||
		munmap(*rsxp, sizeof(**rsxp));
 | 
							munmap(*rsxp, sizeof(**rsxp));
 | 
				
			||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp),
 | 
				
			||||||
 | 
						    "arc4random _rsx structure");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ARC4_ATFORK(_rs_forkhandler);
 | 
						_ARC4_ATFORK(_rs_forkhandler);
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
/*	$OpenBSD: fnmatch.c,v 1.17 2013/11/24 23:51:29 deraadt Exp $	*/
 | 
					/*	$OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Copyright (c) 2011, VMware, Inc.
 | 
					/* Copyright (c) 2011, VMware, Inc.
 | 
				
			||||||
 * All rights reserved.
 | 
					 * All rights reserved.
 | 
				
			||||||
@@ -88,7 +88,6 @@
 | 
				
			|||||||
#include <fnmatch.h>
 | 
					#include <fnmatch.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <limits.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "charclass.h"
 | 
					#include "charclass.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -193,6 +192,8 @@ static int fnmatch_ch(const char **pattern, const char **string, int flags)
 | 
				
			|||||||
                result = 0;
 | 
					                result = 0;
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (!**pattern)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
leadingclosebrace:
 | 
					leadingclosebrace:
 | 
				
			||||||
            /* Look at only well-formed range patterns; 
 | 
					            /* Look at only well-formed range patterns; 
 | 
				
			||||||
@@ -294,10 +295,6 @@ int fnmatch(const char *pattern, const char *string, int flags)
 | 
				
			|||||||
    const char *mismatch = NULL;
 | 
					    const char *mismatch = NULL;
 | 
				
			||||||
    int matchlen = 0;
 | 
					    int matchlen = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
 | 
					 | 
				
			||||||
        strnlen(string, PATH_MAX) == PATH_MAX)
 | 
					 | 
				
			||||||
            return (FNM_NOMATCH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (*pattern == '*')
 | 
					    if (*pattern == '*')
 | 
				
			||||||
        goto firstsegment;
 | 
					        goto firstsegment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							@@ -36,7 +36,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			|||||||
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 | 
					LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 | 
				
			||||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
					LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
include $(BUILD_SHARED_LIBRARY)
 | 
					include $(BUILD_SHARED_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# A dummy libdl.a. Need for static executables using the LLVM unwinder. Most
 | 
					# A dummy libdl.a. Need for static executables using the LLVM unwinder. Most
 | 
				
			||||||
@@ -49,5 +49,5 @@ LOCAL_CXX_STL := none
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LOCAL_MODULE := libdl
 | 
					LOCAL_MODULE := libdl
 | 
				
			||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,9 @@ LOCAL_PATH:= $(call my-dir)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bionic_coverage := false
 | 
					bionic_coverage := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifneq (,$(filter $(TARGET_ARCH),x86 x86_64))
 | 
					# Clang/llvm has incompatible long double (fp128) for x86_64.
 | 
				
			||||||
# Clang has wrong long double sizes for x86.
 | 
					# https://llvm.org/bugs/show_bug.cgi?id=23897
 | 
				
			||||||
 | 
					ifeq ($(TARGET_ARCH),x86_64)
 | 
				
			||||||
libm_clang := false
 | 
					libm_clang := false
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -501,11 +502,8 @@ LOCAL_CFLAGS += \
 | 
				
			|||||||
    -fno-builtin-rintf \
 | 
					    -fno-builtin-rintf \
 | 
				
			||||||
    -fno-builtin-rintl \
 | 
					    -fno-builtin-rintl \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_CONLY_FLAGS := \
 | 
					 | 
				
			||||||
    -std=c99 \
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
include $(BUILD_STATIC_LIBRARY)
 | 
					include $(BUILD_STATIC_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
@@ -527,7 +525,7 @@ LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
				
			|||||||
LOCAL_WHOLE_STATIC_LIBRARIES := libm
 | 
					LOCAL_WHOLE_STATIC_LIBRARIES := libm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
					LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_CXX_STL := none
 | 
					LOCAL_CXX_STL := none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,6 @@ LOCAL_CONLYFLAGS += \
 | 
				
			|||||||
    -std=gnu99 \
 | 
					    -std=gnu99 \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_CPPFLAGS += \
 | 
					LOCAL_CPPFLAGS += \
 | 
				
			||||||
    -std=gnu++11 \
 | 
					 | 
				
			||||||
    -Wold-style-cast \
 | 
					    -Wold-style-cast \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(TARGET_IS_64_BIT),true)
 | 
					ifeq ($(TARGET_IS_64_BIT),true)
 | 
				
			||||||
@@ -60,7 +59,7 @@ LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libz liblog
 | 
					LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libbase libz liblog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
 | 
					LOCAL_FORCE_STATIC_EXECUTABLE := true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,4 +82,26 @@ LOCAL_POST_LINK_CMD = $(hide) $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJCOPY) \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
include $(BUILD_EXECUTABLE)
 | 
					include $(BUILD_EXECUTABLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq (address, $(strip $(SANITIZE_TARGET)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define add-linker-symlink
 | 
				
			||||||
 | 
					$(eval _from := $(TARGET_OUT)/bin/$(1))
 | 
				
			||||||
 | 
					$(eval _to:=$(2))
 | 
				
			||||||
 | 
					$(_from): $(LOCAL_MODULE_MAKEFILE)
 | 
				
			||||||
 | 
						@echo "Symlink: $$@ -> $(_to)"
 | 
				
			||||||
 | 
						@mkdir -p $$(dir $$@)
 | 
				
			||||||
 | 
						@rm -rf $$@
 | 
				
			||||||
 | 
						$(hide) ln -sf $(_to) $$@
 | 
				
			||||||
 | 
					ALL_MODULES.linker.INSTALLED += $(_from)
 | 
				
			||||||
 | 
					linker: $(_from)
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(eval $(call add-linker-symlink,linker_asan,linker))
 | 
				
			||||||
 | 
					ifeq ($(TARGET_IS_64_BIT),true)
 | 
				
			||||||
 | 
					$(eval $(call add-linker-symlink,linker_asan64,linker64))
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					ALL_MODULES += linker
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(call first-makefiles-under,$(LOCAL_PATH))
 | 
					include $(call first-makefiles-under,$(LOCAL_PATH))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,9 +135,6 @@ static void log_signal_summary(int signum, const siginfo_t* info) {
 | 
				
			|||||||
      signal_name = "SIGILL";
 | 
					      signal_name = "SIGILL";
 | 
				
			||||||
      has_address = true;
 | 
					      has_address = true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case SIGPIPE:
 | 
					 | 
				
			||||||
      signal_name = "SIGPIPE";
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case SIGSEGV:
 | 
					    case SIGSEGV:
 | 
				
			||||||
      signal_name = "SIGSEGV";
 | 
					      signal_name = "SIGSEGV";
 | 
				
			||||||
      has_address = true;
 | 
					      has_address = true;
 | 
				
			||||||
@@ -273,7 +270,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
 | 
				
			|||||||
  signal(signal_number, SIG_DFL);
 | 
					  signal(signal_number, SIG_DFL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // These signals are not re-thrown when we resume.  This means that
 | 
					  // These signals are not re-thrown when we resume.  This means that
 | 
				
			||||||
  // crashing due to (say) SIGPIPE doesn't work the way you'd expect it
 | 
					  // crashing due to (say) SIGABRT doesn't work the way you'd expect it
 | 
				
			||||||
  // to.  We work around this by throwing them manually.  We don't want
 | 
					  // to.  We work around this by throwing them manually.  We don't want
 | 
				
			||||||
  // to do this for *all* signals because it'll screw up the si_addr for
 | 
					  // to do this for *all* signals because it'll screw up the si_addr for
 | 
				
			||||||
  // faults like SIGSEGV. It does screw up the si_code, which is why we
 | 
					  // faults like SIGSEGV. It does screw up the si_code, which is why we
 | 
				
			||||||
@@ -281,7 +278,6 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
 | 
				
			|||||||
  switch (signal_number) {
 | 
					  switch (signal_number) {
 | 
				
			||||||
    case SIGABRT:
 | 
					    case SIGABRT:
 | 
				
			||||||
    case SIGFPE:
 | 
					    case SIGFPE:
 | 
				
			||||||
    case SIGPIPE:
 | 
					 | 
				
			||||||
#if defined(SIGSTKFLT)
 | 
					#if defined(SIGSTKFLT)
 | 
				
			||||||
    case SIGSTKFLT:
 | 
					    case SIGSTKFLT:
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -307,7 +303,6 @@ __LIBC_HIDDEN__ void debuggerd_init() {
 | 
				
			|||||||
  sigaction(SIGBUS, &action, nullptr);
 | 
					  sigaction(SIGBUS, &action, nullptr);
 | 
				
			||||||
  sigaction(SIGFPE, &action, nullptr);
 | 
					  sigaction(SIGFPE, &action, nullptr);
 | 
				
			||||||
  sigaction(SIGILL, &action, nullptr);
 | 
					  sigaction(SIGILL, &action, nullptr);
 | 
				
			||||||
  sigaction(SIGPIPE, &action, nullptr);
 | 
					 | 
				
			||||||
  sigaction(SIGSEGV, &action, nullptr);
 | 
					  sigaction(SIGSEGV, &action, nullptr);
 | 
				
			||||||
#if defined(SIGSTKFLT)
 | 
					#if defined(SIGSTKFLT)
 | 
				
			||||||
  sigaction(SIGSTKFLT, &action, nullptr);
 | 
					  sigaction(SIGSTKFLT, &action, nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,9 +67,11 @@ void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
 | 
				
			|||||||
  do_android_update_LD_LIBRARY_PATH(ld_library_path);
 | 
					  do_android_update_LD_LIBRARY_PATH(ld_library_path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
 | 
					static void* dlopen_ext(const char* filename, int flags,
 | 
				
			||||||
 | 
					                        const android_dlextinfo* extinfo, void* caller_addr) {
 | 
				
			||||||
  ScopedPthreadMutexLocker locker(&g_dl_mutex);
 | 
					  ScopedPthreadMutexLocker locker(&g_dl_mutex);
 | 
				
			||||||
  soinfo* result = do_dlopen(filename, flags, extinfo);
 | 
					  soinfo* caller = find_containing_library(caller_addr);
 | 
				
			||||||
 | 
					  soinfo* result = do_dlopen(filename, flags, extinfo, caller);
 | 
				
			||||||
  if (result == nullptr) {
 | 
					  if (result == nullptr) {
 | 
				
			||||||
    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
 | 
					    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
@@ -78,11 +80,13 @@ static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
 | 
					void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
 | 
				
			||||||
  return dlopen_ext(filename, flags, extinfo);
 | 
					  void* caller_addr = __builtin_return_address(0);
 | 
				
			||||||
 | 
					  return dlopen_ext(filename, flags, extinfo, caller_addr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void* dlopen(const char* filename, int flags) {
 | 
					void* dlopen(const char* filename, int flags) {
 | 
				
			||||||
  return dlopen_ext(filename, flags, nullptr);
 | 
					  void* caller_addr = __builtin_return_address(0);
 | 
				
			||||||
 | 
					  return dlopen_ext(filename, flags, nullptr, caller_addr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void* dlsym(void* handle, const char* symbol) {
 | 
					void* dlsym(void* handle, const char* symbol) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,6 @@
 | 
				
			|||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#include <sys/param.h>
 | 
					#include <sys/param.h>
 | 
				
			||||||
#include <sys/prctl.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <new>
 | 
					#include <new>
 | 
				
			||||||
@@ -58,6 +57,8 @@
 | 
				
			|||||||
#include "linker_phdr.h"
 | 
					#include "linker_phdr.h"
 | 
				
			||||||
#include "linker_relocs.h"
 | 
					#include "linker_relocs.h"
 | 
				
			||||||
#include "linker_reloc_iterators.h"
 | 
					#include "linker_reloc_iterators.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "base/strings.h"
 | 
				
			||||||
#include "ziparchive/zip_archive.h"
 | 
					#include "ziparchive/zip_archive.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
 | 
					extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
 | 
				
			||||||
@@ -86,9 +87,26 @@ static const char* const kDefaultLdPaths[] = {
 | 
				
			|||||||
  nullptr
 | 
					  nullptr
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char* const kAsanDefaultLdPaths[] = {
 | 
				
			||||||
 | 
					#if defined(__LP64__)
 | 
				
			||||||
 | 
					  "/data/vendor/lib64",
 | 
				
			||||||
 | 
					  "/vendor/lib64",
 | 
				
			||||||
 | 
					  "/data/lib64",
 | 
				
			||||||
 | 
					  "/system/lib64",
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  "/data/vendor/lib",
 | 
				
			||||||
 | 
					  "/vendor/lib",
 | 
				
			||||||
 | 
					  "/data/lib",
 | 
				
			||||||
 | 
					  "/system/lib",
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  nullptr
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const ElfW(Versym) kVersymNotNeeded = 0;
 | 
					static const ElfW(Versym) kVersymNotNeeded = 0;
 | 
				
			||||||
static const ElfW(Versym) kVersymGlobal = 1;
 | 
					static const ElfW(Versym) kVersymGlobal = 1;
 | 
				
			||||||
 | 
					static const char* const kZipFileSeparator = "!/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char* const* g_default_ld_paths;
 | 
				
			||||||
static std::vector<std::string> g_ld_library_paths;
 | 
					static std::vector<std::string> g_ld_library_paths;
 | 
				
			||||||
static std::vector<std::string> g_ld_preload_names;
 | 
					static std::vector<std::string> g_ld_preload_names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -98,6 +116,14 @@ __LIBC_HIDDEN__ int g_ld_debug_verbosity;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
__LIBC_HIDDEN__ abort_msg_t* g_abort_message = nullptr; // For debuggerd.
 | 
					__LIBC_HIDDEN__ abort_msg_t* g_abort_message = nullptr; // For debuggerd.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static std::string dirname(const char *path) {
 | 
				
			||||||
 | 
					  const char* last_slash = strrchr(path, '/');
 | 
				
			||||||
 | 
					  if (last_slash == path) return "/";
 | 
				
			||||||
 | 
					  else if (last_slash == nullptr) return ".";
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    return std::string(path, last_slash - path);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if STATS
 | 
					#if STATS
 | 
				
			||||||
struct linker_stats_t {
 | 
					struct linker_stats_t {
 | 
				
			||||||
  int count[kRelocMax];
 | 
					  int count[kRelocMax];
 | 
				
			||||||
@@ -284,25 +310,9 @@ static void soinfo_free(soinfo* si) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void parse_path(const char* path, const char* delimiters,
 | 
					static void parse_path(const char* path, const char* delimiters,
 | 
				
			||||||
                       std::vector<std::string>* paths) {
 | 
					                       std::vector<std::string>* paths) {
 | 
				
			||||||
  if (path == nullptr) {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  paths->clear();
 | 
					  paths->clear();
 | 
				
			||||||
 | 
					  if (path != nullptr) {
 | 
				
			||||||
  for (const char *p = path; ; ++p) {
 | 
					    *paths = android::base::Split(path, delimiters);
 | 
				
			||||||
    size_t len = strcspn(p, delimiters);
 | 
					 | 
				
			||||||
    // skip empty tokens
 | 
					 | 
				
			||||||
    if (len == 0) {
 | 
					 | 
				
			||||||
      continue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    paths->push_back(std::string(p, len));
 | 
					 | 
				
			||||||
    p += len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (*p == '\0') {
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -310,6 +320,38 @@ static void parse_LD_LIBRARY_PATH(const char* path) {
 | 
				
			|||||||
  parse_path(path, ":", &g_ld_library_paths);
 | 
					  parse_path(path, ":", &g_ld_library_paths);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void soinfo::set_dt_runpath(const char* path) {
 | 
				
			||||||
 | 
					  if (!has_min_version(2)) return;
 | 
				
			||||||
 | 
					  parse_path(path, ":", &dt_runpath_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::string origin = dirname(get_realpath());
 | 
				
			||||||
 | 
					  // FIXME: add $LIB and $PLATFORM.
 | 
				
			||||||
 | 
					  std::pair<std::string, std::string> substs[] = {{"ORIGIN", origin}};
 | 
				
			||||||
 | 
					  for (std::string& s : dt_runpath_) {
 | 
				
			||||||
 | 
					    size_t pos = 0;
 | 
				
			||||||
 | 
					    while (pos < s.size()) {
 | 
				
			||||||
 | 
					      pos = s.find("$", pos);
 | 
				
			||||||
 | 
					      if (pos == std::string::npos) break;
 | 
				
			||||||
 | 
					      for (const auto& subst : substs) {
 | 
				
			||||||
 | 
					        const std::string& token = subst.first;
 | 
				
			||||||
 | 
					        const std::string& replacement = subst.second;
 | 
				
			||||||
 | 
					        if (s.substr(pos + 1, token.size()) == token) {
 | 
				
			||||||
 | 
					          s.replace(pos, token.size() + 1, replacement);
 | 
				
			||||||
 | 
					          // -1 to compensate for the ++pos below.
 | 
				
			||||||
 | 
					          pos += replacement.size() - 1;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        } else if (s.substr(pos + 1, token.size() + 2) == "{" + token + "}") {
 | 
				
			||||||
 | 
					          s.replace(pos, token.size() + 3, replacement);
 | 
				
			||||||
 | 
					          pos += replacement.size() - 1;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // Skip $ in case it did not match any of the known substitutions.
 | 
				
			||||||
 | 
					      ++pos;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void parse_LD_PRELOAD(const char* path) {
 | 
					static void parse_LD_PRELOAD(const char* path) {
 | 
				
			||||||
  // We have historically supported ':' as well as ' ' in LD_PRELOAD.
 | 
					  // We have historically supported ':' as well as ' ' in LD_PRELOAD.
 | 
				
			||||||
  parse_path(path, " :", &g_ld_preload_names);
 | 
					  parse_path(path, " :", &g_ld_preload_names);
 | 
				
			||||||
@@ -318,13 +360,6 @@ static void parse_LD_PRELOAD(const char* path) {
 | 
				
			|||||||
static bool realpath_fd(int fd, std::string* realpath) {
 | 
					static bool realpath_fd(int fd, std::string* realpath) {
 | 
				
			||||||
  std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
 | 
					  std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
 | 
				
			||||||
  snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
 | 
					  snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
 | 
				
			||||||
  // set DUMPABLE to 1 to access /proc/self/fd
 | 
					 | 
				
			||||||
  int dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
 | 
					 | 
				
			||||||
  prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
 | 
					 | 
				
			||||||
  auto guard = make_scope_guard([&]() {
 | 
					 | 
				
			||||||
    // restore dumpable
 | 
					 | 
				
			||||||
    prctl(PR_SET_DUMPABLE, dumpable, 0, 0, 0);
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
 | 
					  if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
 | 
				
			||||||
    PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
 | 
					    PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
@@ -1094,7 +1129,7 @@ static int open_library_in_zipfile(const char* const path,
 | 
				
			|||||||
  // of the zip file on disk and the subdirectory to search within it.
 | 
					  // of the zip file on disk and the subdirectory to search within it.
 | 
				
			||||||
  // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
 | 
					  // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
 | 
				
			||||||
  // "bar/bas/x.so" within "foo.zip".
 | 
					  // "bar/bas/x.so" within "foo.zip".
 | 
				
			||||||
  const char* separator = strstr(path, "!/");
 | 
					  const char* separator = strstr(path, kZipFileSeparator);
 | 
				
			||||||
  if (separator == nullptr) {
 | 
					  if (separator == nullptr) {
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1127,7 +1162,7 @@ static int open_library_in_zipfile(const char* const path,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  ZipEntry entry;
 | 
					  ZipEntry entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (FindEntry(handle, ZipEntryName(file_path), &entry) != 0) {
 | 
					  if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
 | 
				
			||||||
    // Entry was not found.
 | 
					    // Entry was not found.
 | 
				
			||||||
    close(fd);
 | 
					    close(fd);
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
@@ -1154,9 +1189,9 @@ static bool format_path(char* buf, size_t buf_size, const char* path, const char
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int open_library_on_default_path(const char* name, off64_t* file_offset) {
 | 
					static int open_library_on_default_path(const char* name, off64_t* file_offset) {
 | 
				
			||||||
  for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) {
 | 
					  for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
 | 
				
			||||||
    char buf[512];
 | 
					    char buf[512];
 | 
				
			||||||
    if (!format_path(buf, sizeof(buf), kDefaultLdPaths[i], name)) {
 | 
					    if (!format_path(buf, sizeof(buf), g_default_ld_paths[i], name)) {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1170,8 +1205,9 @@ static int open_library_on_default_path(const char* name, off64_t* file_offset)
 | 
				
			|||||||
  return -1;
 | 
					  return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int open_library_on_ld_library_path(const char* name, off64_t* file_offset) {
 | 
					static int open_library_on_paths(const char* name, off64_t* file_offset,
 | 
				
			||||||
  for (const auto& path_str : g_ld_library_paths) {
 | 
					                                 const std::vector<std::string>& paths) {
 | 
				
			||||||
 | 
					  for (const auto& path_str : paths) {
 | 
				
			||||||
    char buf[512];
 | 
					    char buf[512];
 | 
				
			||||||
    const char* const path = path_str.c_str();
 | 
					    const char* const path = path_str.c_str();
 | 
				
			||||||
    if (!format_path(buf, sizeof(buf), path, name)) {
 | 
					    if (!format_path(buf, sizeof(buf), path, name)) {
 | 
				
			||||||
@@ -1179,7 +1215,7 @@ static int open_library_on_ld_library_path(const char* name, off64_t* file_offse
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int fd = -1;
 | 
					    int fd = -1;
 | 
				
			||||||
    if (strchr(buf, '!') != nullptr) {
 | 
					    if (strstr(buf, kZipFileSeparator) != nullptr) {
 | 
				
			||||||
      fd = open_library_in_zipfile(buf, file_offset);
 | 
					      fd = open_library_in_zipfile(buf, file_offset);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1198,12 +1234,12 @@ static int open_library_on_ld_library_path(const char* name, off64_t* file_offse
 | 
				
			|||||||
  return -1;
 | 
					  return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int open_library(const char* name, off64_t* file_offset) {
 | 
					static int open_library(const char* name, soinfo *needed_by, off64_t* file_offset) {
 | 
				
			||||||
  TRACE("[ opening %s ]", name);
 | 
					  TRACE("[ opening %s ]", name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If the name contains a slash, we should attempt to open it directly and not search the paths.
 | 
					  // If the name contains a slash, we should attempt to open it directly and not search the paths.
 | 
				
			||||||
  if (strchr(name, '/') != nullptr) {
 | 
					  if (strchr(name, '/') != nullptr) {
 | 
				
			||||||
    if (strchr(name, '!') != nullptr) {
 | 
					    if (strstr(name, kZipFileSeparator) != nullptr) {
 | 
				
			||||||
      int fd = open_library_in_zipfile(name, file_offset);
 | 
					      int fd = open_library_in_zipfile(name, file_offset);
 | 
				
			||||||
      if (fd != -1) {
 | 
					      if (fd != -1) {
 | 
				
			||||||
        return fd;
 | 
					        return fd;
 | 
				
			||||||
@@ -1218,7 +1254,10 @@ static int open_library(const char* name, off64_t* file_offset) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
 | 
					  // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
 | 
				
			||||||
  int fd = open_library_on_ld_library_path(name, file_offset);
 | 
					  int fd = open_library_on_paths(name, file_offset, g_ld_library_paths);
 | 
				
			||||||
 | 
					  if (fd == -1 && needed_by) {
 | 
				
			||||||
 | 
					    fd = open_library_on_paths(name, file_offset, needed_by->get_dt_runpath());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  if (fd == -1) {
 | 
					  if (fd == -1) {
 | 
				
			||||||
    fd = open_library_on_default_path(name, file_offset);
 | 
					    fd = open_library_on_default_path(name, file_offset);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1328,8 +1367,8 @@ static soinfo* load_library(int fd, off64_t file_offset,
 | 
				
			|||||||
  return si;
 | 
					  return si;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* load_library(LoadTaskList& load_tasks,
 | 
					static soinfo* load_library(LoadTaskList& load_tasks, const char* name,
 | 
				
			||||||
                            const char* name, int rtld_flags,
 | 
					                            soinfo* needed_by, int rtld_flags,
 | 
				
			||||||
                            const android_dlextinfo* extinfo) {
 | 
					                            const android_dlextinfo* extinfo) {
 | 
				
			||||||
  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
					  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
				
			||||||
    off64_t file_offset = 0;
 | 
					    off64_t file_offset = 0;
 | 
				
			||||||
@@ -1341,7 +1380,7 @@ static soinfo* load_library(LoadTaskList& load_tasks,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Open the file.
 | 
					  // Open the file.
 | 
				
			||||||
  off64_t file_offset;
 | 
					  off64_t file_offset;
 | 
				
			||||||
  int fd = open_library(name, &file_offset);
 | 
					  int fd = open_library(name, needed_by, &file_offset);
 | 
				
			||||||
  if (fd == -1) {
 | 
					  if (fd == -1) {
 | 
				
			||||||
    DL_ERR("library \"%s\" not found", name);
 | 
					    DL_ERR("library \"%s\" not found", name);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
@@ -1389,7 +1428,8 @@ static bool find_loaded_library_by_soname(const char* name, soinfo** candidate)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
 | 
					static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
 | 
				
			||||||
                                     int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					                                     soinfo* needed_by, int rtld_flags,
 | 
				
			||||||
 | 
					                                     const android_dlextinfo* extinfo) {
 | 
				
			||||||
  soinfo* candidate;
 | 
					  soinfo* candidate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (find_loaded_library_by_soname(name, &candidate)) {
 | 
					  if (find_loaded_library_by_soname(name, &candidate)) {
 | 
				
			||||||
@@ -1401,7 +1441,7 @@ static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
 | 
				
			|||||||
  TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
 | 
					  TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
 | 
				
			||||||
      name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
 | 
					      name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  soinfo* si = load_library(load_tasks, name, rtld_flags, extinfo);
 | 
					  soinfo* si = load_library(load_tasks, name, needed_by, rtld_flags, extinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // In case we were unable to load the library but there
 | 
					  // In case we were unable to load the library but there
 | 
				
			||||||
  // is a candidate loaded under the same soname but different
 | 
					  // is a candidate loaded under the same soname but different
 | 
				
			||||||
@@ -1433,9 +1473,17 @@ static soinfo::soinfo_list_t make_global_group() {
 | 
				
			|||||||
  return global_group;
 | 
					  return global_group;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_libraries(soinfo* start_with, const char* const library_names[],
 | 
					// add_as_children - add first-level loaded libraries (i.e. library_names[], but
 | 
				
			||||||
      size_t library_names_count, soinfo* soinfos[], std::vector<soinfo*>* ld_preloads,
 | 
					// not their transitive dependencies) as children of the start_with library.
 | 
				
			||||||
      size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					// This is false when find_libraries is called for dlopen(), when newly loaded
 | 
				
			||||||
 | 
					// libraries must form a disjoint tree.
 | 
				
			||||||
 | 
					static bool find_libraries(soinfo* start_with,
 | 
				
			||||||
 | 
					                           const char* const library_names[],
 | 
				
			||||||
 | 
					                           size_t library_names_count, soinfo* soinfos[],
 | 
				
			||||||
 | 
					                           std::vector<soinfo*>* ld_preloads,
 | 
				
			||||||
 | 
					                           size_t ld_preloads_count, int rtld_flags,
 | 
				
			||||||
 | 
					                           const android_dlextinfo* extinfo,
 | 
				
			||||||
 | 
					                           bool add_as_children) {
 | 
				
			||||||
  // Step 0: prepare.
 | 
					  // Step 0: prepare.
 | 
				
			||||||
  LoadTaskList load_tasks;
 | 
					  LoadTaskList load_tasks;
 | 
				
			||||||
  for (size_t i = 0; i < library_names_count; ++i) {
 | 
					  for (size_t i = 0; i < library_names_count; ++i) {
 | 
				
			||||||
@@ -1477,14 +1525,13 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
  for (LoadTask::unique_ptr task(load_tasks.pop_front());
 | 
					  for (LoadTask::unique_ptr task(load_tasks.pop_front());
 | 
				
			||||||
      task.get() != nullptr; task.reset(load_tasks.pop_front())) {
 | 
					      task.get() != nullptr; task.reset(load_tasks.pop_front())) {
 | 
				
			||||||
    soinfo* needed_by = task->get_needed_by();
 | 
					    soinfo* needed_by = task->get_needed_by();
 | 
				
			||||||
 | 
					    soinfo* si = find_library_internal(load_tasks, task->get_name(), needed_by,
 | 
				
			||||||
    soinfo* si = find_library_internal(load_tasks, task->get_name(),
 | 
					                                       rtld_flags, extinfo);
 | 
				
			||||||
                                       rtld_flags, needed_by == nullptr ? extinfo : nullptr);
 | 
					 | 
				
			||||||
    if (si == nullptr) {
 | 
					    if (si == nullptr) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (needed_by != nullptr) {
 | 
					    if (needed_by != nullptr && (needed_by != start_with || add_as_children)) {
 | 
				
			||||||
      needed_by->add_child(si);
 | 
					      needed_by->add_child(si);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1511,8 +1558,8 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
  // Step 2: link libraries.
 | 
					  // Step 2: link libraries.
 | 
				
			||||||
  soinfo::soinfo_list_t local_group;
 | 
					  soinfo::soinfo_list_t local_group;
 | 
				
			||||||
  walk_dependencies_tree(
 | 
					  walk_dependencies_tree(
 | 
				
			||||||
      start_with == nullptr ? soinfos : &start_with,
 | 
					      (start_with != nullptr && add_as_children) ? &start_with : soinfos,
 | 
				
			||||||
      start_with == nullptr ? soinfos_count : 1,
 | 
					      (start_with != nullptr && add_as_children) ? 1 : soinfos_count,
 | 
				
			||||||
      [&] (soinfo* si) {
 | 
					      [&] (soinfo* si) {
 | 
				
			||||||
    local_group.push_back(si);
 | 
					    local_group.push_back(si);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
@@ -1544,12 +1591,15 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
				
			|||||||
  return linked;
 | 
					  return linked;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static soinfo* find_library(const char* name, int rtld_flags, const android_dlextinfo* extinfo) {
 | 
					static soinfo* find_library(const char* name, int rtld_flags,
 | 
				
			||||||
 | 
					                            const android_dlextinfo* extinfo,
 | 
				
			||||||
 | 
					                            soinfo* needed_by) {
 | 
				
			||||||
  soinfo* si;
 | 
					  soinfo* si;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (name == nullptr) {
 | 
					  if (name == nullptr) {
 | 
				
			||||||
    si = somain;
 | 
					    si = somain;
 | 
				
			||||||
  } else if (!find_libraries(nullptr, &name, 1, &si, nullptr, 0, rtld_flags, extinfo)) {
 | 
					  } else if (!find_libraries(needed_by, &name, 1, &si, nullptr, 0, rtld_flags,
 | 
				
			||||||
 | 
					                             extinfo, /* add_as_children */ false)) {
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1611,7 +1661,7 @@ static void soinfo_unload(soinfo* root) {
 | 
				
			|||||||
          TRACE("deprecated (old format of soinfo): %s needs to unload %s",
 | 
					          TRACE("deprecated (old format of soinfo): %s needs to unload %s",
 | 
				
			||||||
              si->get_realpath(), library_name);
 | 
					              si->get_realpath(), library_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr);
 | 
					          soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr, nullptr);
 | 
				
			||||||
          if (needed != nullptr) {
 | 
					          if (needed != nullptr) {
 | 
				
			||||||
            // Not found: for example if symlink was deleted between dlopen and dlclose
 | 
					            // Not found: for example if symlink was deleted between dlopen and dlclose
 | 
				
			||||||
            // Since we cannot really handle errors at this point - print and continue.
 | 
					            // Since we cannot really handle errors at this point - print and continue.
 | 
				
			||||||
@@ -1659,21 +1709,26 @@ void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
 | 
				
			|||||||
  // See b/17302493 for further details.
 | 
					  // See b/17302493 for further details.
 | 
				
			||||||
  // Once the above bug is fixed, this code can be modified to use
 | 
					  // Once the above bug is fixed, this code can be modified to use
 | 
				
			||||||
  // snprintf again.
 | 
					  // snprintf again.
 | 
				
			||||||
  size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
 | 
					  size_t required_len = 0;
 | 
				
			||||||
 | 
					  for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
 | 
				
			||||||
 | 
					    required_len += strlen(g_default_ld_paths[i]) + 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  if (buffer_size < required_len) {
 | 
					  if (buffer_size < required_len) {
 | 
				
			||||||
    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
 | 
					    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
 | 
				
			||||||
                 "buffer len %zu, required len %zu", buffer_size, required_len);
 | 
					                 "buffer len %zu, required len %zu", buffer_size, required_len);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
 | 
					  char* end = buffer;
 | 
				
			||||||
  *end = ':';
 | 
					  for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
 | 
				
			||||||
  strcpy(end + 1, kDefaultLdPaths[1]);
 | 
					    if (i > 0) *end++ = ':';
 | 
				
			||||||
 | 
					    end = stpcpy(end, g_default_ld_paths[i]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
 | 
					void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
 | 
				
			||||||
  parse_LD_LIBRARY_PATH(ld_library_path);
 | 
					  parse_LD_LIBRARY_PATH(ld_library_path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
 | 
					soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, soinfo *caller) {
 | 
				
			||||||
  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
 | 
					  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
 | 
				
			||||||
    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
					    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
@@ -1692,7 +1747,7 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ProtectedDataGuard guard;
 | 
					  ProtectedDataGuard guard;
 | 
				
			||||||
  soinfo* si = find_library(name, flags, extinfo);
 | 
					  soinfo* si = find_library(name, flags, extinfo, caller);
 | 
				
			||||||
  if (si != nullptr) {
 | 
					  if (si != nullptr) {
 | 
				
			||||||
    si->call_constructors();
 | 
					    si->call_constructors();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2428,6 +2483,16 @@ soinfo::soinfo_list_t& soinfo::get_parents() {
 | 
				
			|||||||
  return g_empty_list;
 | 
					  return g_empty_list;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static std::vector<std::string> g_empty_runpath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::vector<std::string>& soinfo::get_dt_runpath() const {
 | 
				
			||||||
 | 
					  if (has_min_version(2)) {
 | 
				
			||||||
 | 
					    return dt_runpath_;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return g_empty_runpath;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
 | 
					ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
 | 
				
			||||||
  if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
 | 
					  if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
 | 
				
			||||||
    return call_ifunc_resolver(s->st_value + load_bias);
 | 
					    return call_ifunc_resolver(s->st_value + load_bias);
 | 
				
			||||||
@@ -2864,6 +2929,10 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
        verneed_cnt_ = d->d_un.d_val;
 | 
					        verneed_cnt_ = d->d_un.d_val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case DT_RUNPATH:
 | 
				
			||||||
 | 
					        // this is parsed after we have strtab initialized (see below).
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        if (!relocating_linker) {
 | 
					        if (!relocating_linker) {
 | 
				
			||||||
          DL_WARN("%s: unused DT entry: type %p arg %p", get_realpath(),
 | 
					          DL_WARN("%s: unused DT entry: type %p arg %p", get_realpath(),
 | 
				
			||||||
@@ -2873,6 +2942,12 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__mips__) && !defined(__LP64__)
 | 
				
			||||||
 | 
					  if (!mips_check_and_adjust_fp_modes()) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
 | 
					  DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
 | 
				
			||||||
        reinterpret_cast<void*>(base), strtab_, symtab_);
 | 
					        reinterpret_cast<void*>(base), strtab_, symtab_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2897,12 +2972,17 @@ bool soinfo::prelink_image() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // second pass - parse entries relying on strtab
 | 
					  // second pass - parse entries relying on strtab
 | 
				
			||||||
  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
 | 
					  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
 | 
				
			||||||
    if (d->d_tag == DT_SONAME) {
 | 
					    switch (d->d_tag) {
 | 
				
			||||||
 | 
					      case DT_SONAME:
 | 
				
			||||||
        soname_ = get_string(d->d_un.d_val);
 | 
					        soname_ = get_string(d->d_un.d_val);
 | 
				
			||||||
#if defined(__work_around_b_19059885__)
 | 
					#if defined(__work_around_b_19059885__)
 | 
				
			||||||
        strlcpy(old_name_, soname_, sizeof(old_name_));
 | 
					        strlcpy(old_name_, soname_, sizeof(old_name_));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					      case DT_RUNPATH:
 | 
				
			||||||
 | 
					        // FIXME: $LIB, $PLATFORM unsupported.
 | 
				
			||||||
 | 
					        set_dt_runpath(get_string(d->d_un.d_val));
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2945,7 +3025,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
				
			|||||||
    // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed
 | 
					    // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed
 | 
				
			||||||
    if (get_application_target_sdk_version() != __ANDROID_API__
 | 
					    if (get_application_target_sdk_version() != __ANDROID_API__
 | 
				
			||||||
        && get_application_target_sdk_version() > 22) {
 | 
					        && get_application_target_sdk_version() > 22) {
 | 
				
			||||||
      PRINT("%s: has text relocations", get_realpath());
 | 
					 | 
				
			||||||
      DL_ERR("%s: has text relocations", get_realpath());
 | 
					      DL_ERR("%s: has text relocations", get_realpath());
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -3133,6 +3212,16 @@ static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
 | 
				
			|||||||
  insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
 | 
					  insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void init_default_ld_library_path() {
 | 
				
			||||||
 | 
					  const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
 | 
				
			||||||
 | 
					                                                       somain->load_bias);
 | 
				
			||||||
 | 
					  const char* bname = basename(interp);
 | 
				
			||||||
 | 
					  if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0))
 | 
				
			||||||
 | 
					    g_default_ld_paths = kAsanDefaultLdPaths;
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    g_default_ld_paths = kDefaultLdPaths;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" int __system_properties_init(void);
 | 
					extern "C" int __system_properties_init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -3223,6 +3312,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  somain = si;
 | 
					  somain = si;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  init_default_ld_library_path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!si->prelink_image()) {
 | 
					  if (!si->prelink_image()) {
 | 
				
			||||||
    __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
 | 
					    __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
 | 
				
			||||||
    exit(EXIT_FAILURE);
 | 
					    exit(EXIT_FAILURE);
 | 
				
			||||||
@@ -3254,7 +3345,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (needed_libraries_count > 0 &&
 | 
					  if (needed_libraries_count > 0 &&
 | 
				
			||||||
      !find_libraries(si, needed_library_names, needed_libraries_count, nullptr,
 | 
					      !find_libraries(si, needed_library_names, needed_libraries_count, nullptr,
 | 
				
			||||||
          &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) {
 | 
					                      &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr,
 | 
				
			||||||
 | 
					                      /* add_as_children */ true)) {
 | 
				
			||||||
    __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
 | 
					    __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
 | 
				
			||||||
    exit(EXIT_FAILURE);
 | 
					    exit(EXIT_FAILURE);
 | 
				
			||||||
  } else if (needed_libraries_count == 0) {
 | 
					  } else if (needed_libraries_count == 0) {
 | 
				
			||||||
@@ -3407,7 +3499,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
 | 
				
			|||||||
    _exit(EXIT_FAILURE);
 | 
					    _exit(EXIT_FAILURE);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  __libc_init_tls(args);
 | 
					  __libc_init_main_thread(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize the linker's own global variables
 | 
					  // Initialize the linker's own global variables
 | 
				
			||||||
  linker_so.call_constructors();
 | 
					  linker_so.call_constructors();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,13 +29,14 @@
 | 
				
			|||||||
#ifndef _LINKER_H_
 | 
					#ifndef _LINKER_H_
 | 
				
			||||||
#define _LINKER_H_
 | 
					#define _LINKER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <android/dlext.h>
 | 
				
			||||||
#include <elf.h>
 | 
					#include <elf.h>
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
#include <link.h>
 | 
					#include <link.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <android/dlext.h>
 | 
					 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "private/bionic_page.h"
 | 
				
			||||||
#include "private/libc_logging.h"
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
#include "linked_list.h"
 | 
					#include "linked_list.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -77,16 +78,6 @@
 | 
				
			|||||||
#define ELF64_R_TYPE(info)  (((info) >> 56) & 0xff)
 | 
					#define ELF64_R_TYPE(info)  (((info) >> 56) & 0xff)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Returns the address of the page containing address 'x'.
 | 
					 | 
				
			||||||
#define PAGE_START(x)  ((x) & PAGE_MASK)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Returns the offset of address 'x' in its page.
 | 
					 | 
				
			||||||
#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Returns the address of the next page after address 'x', unless 'x' is
 | 
					 | 
				
			||||||
// itself at the start of a page.
 | 
					 | 
				
			||||||
#define PAGE_END(x)    PAGE_START((x) + (PAGE_SIZE-1))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define FLAG_LINKED     0x00000001
 | 
					#define FLAG_LINKED     0x00000001
 | 
				
			||||||
#define FLAG_EXE        0x00000004 // The main executable
 | 
					#define FLAG_EXE        0x00000004 // The main executable
 | 
				
			||||||
#define FLAG_LINKER     0x00000010 // The linker itself
 | 
					#define FLAG_LINKER     0x00000010 // The linker itself
 | 
				
			||||||
@@ -250,7 +241,9 @@ struct soinfo {
 | 
				
			|||||||
  bool mips_relocate_got(const VersionTracker& version_tracker,
 | 
					  bool mips_relocate_got(const VersionTracker& version_tracker,
 | 
				
			||||||
                         const soinfo_list_t& global_group,
 | 
					                         const soinfo_list_t& global_group,
 | 
				
			||||||
                         const soinfo_list_t& local_group);
 | 
					                         const soinfo_list_t& local_group);
 | 
				
			||||||
 | 
					#if !defined(__LP64__)
 | 
				
			||||||
 | 
					  bool mips_check_and_adjust_fp_modes();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  size_t ref_count_;
 | 
					  size_t ref_count_;
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
@@ -336,6 +329,8 @@ struct soinfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint32_t get_target_sdk_version() const;
 | 
					  uint32_t get_target_sdk_version() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const std::vector<std::string>& get_dt_runpath() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 private:
 | 
					 private:
 | 
				
			||||||
  bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
 | 
					  bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
 | 
				
			||||||
  ElfW(Sym)* elf_addr_lookup(const void* addr);
 | 
					  ElfW(Sym)* elf_addr_lookup(const void* addr);
 | 
				
			||||||
@@ -397,6 +392,9 @@ struct soinfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint32_t target_sdk_version_;
 | 
					  uint32_t target_sdk_version_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void set_dt_runpath(const char *);
 | 
				
			||||||
 | 
					  std::vector<std::string> dt_runpath_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friend soinfo* get_libdl_info();
 | 
					  friend soinfo* get_libdl_info();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -418,7 +416,7 @@ soinfo* get_libdl_info();
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void do_android_get_LD_LIBRARY_PATH(char*, size_t);
 | 
					void do_android_get_LD_LIBRARY_PATH(char*, size_t);
 | 
				
			||||||
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 | 
					void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 | 
				
			||||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 | 
					soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, soinfo *caller);
 | 
				
			||||||
void do_dlclose(soinfo* si);
 | 
					void do_dlclose(soinfo* si);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
 | 
					int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,21 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__LP64__) && __mips_isa_rev >= 5
 | 
				
			||||||
 | 
					#include <sys/prctl.h>
 | 
				
			||||||
 | 
					#if defined(PR_SET_FP_MODE)
 | 
				
			||||||
 | 
					#error "remove following defs when avail in Android's kernel headers"
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define PR_SET_FP_MODE 45
 | 
				
			||||||
 | 
					#define PR_GET_FP_MODE 46
 | 
				
			||||||
 | 
					#define PR_FP_MODE_FR  (1 << 0)
 | 
				
			||||||
 | 
					#define PR_FP_MODE_FRE (1 << 1)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "linker.h"
 | 
					#include "linker.h"
 | 
				
			||||||
#include "linker_debug.h"
 | 
					#include "linker_debug.h"
 | 
				
			||||||
 | 
					#include "linker_phdr.h"
 | 
				
			||||||
#include "linker_relocs.h"
 | 
					#include "linker_relocs.h"
 | 
				
			||||||
#include "linker_reloc_iterators.h"
 | 
					#include "linker_reloc_iterators.h"
 | 
				
			||||||
#include "linker_sleb128.h"
 | 
					#include "linker_sleb128.h"
 | 
				
			||||||
@@ -62,7 +75,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
 | 
				
			|||||||
    ElfW(Addr) sym_addr = 0;
 | 
					    ElfW(Addr) sym_addr = 0;
 | 
				
			||||||
    const char* sym_name = nullptr;
 | 
					    const char* sym_name = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DEBUG("Processing '%s' relocation at index %zd", get_soname(), idx);
 | 
					    DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
 | 
				
			||||||
    if (type == R_GENERIC_NONE) {
 | 
					    if (type == R_GENERIC_NONE) {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -84,7 +97,8 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      if (s == nullptr) {
 | 
					      if (s == nullptr) {
 | 
				
			||||||
        // mips does not support relocation with weak-undefined symbols
 | 
					        // mips does not support relocation with weak-undefined symbols
 | 
				
			||||||
        DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_soname());
 | 
					        DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...",
 | 
				
			||||||
 | 
					               sym_name, get_realpath());
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // We got a definition.
 | 
					        // We got a definition.
 | 
				
			||||||
@@ -171,20 +185,22 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    } else if (st_visibility == STV_PROTECTED) {
 | 
					    } else if (st_visibility == STV_PROTECTED) {
 | 
				
			||||||
      if (local_sym->st_value == 0) {
 | 
					      if (local_sym->st_value == 0) {
 | 
				
			||||||
        DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ", get_soname(), sym_name);
 | 
					        DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ",
 | 
				
			||||||
 | 
					               get_realpath(), sym_name);
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      s = local_sym;
 | 
					      s = local_sym;
 | 
				
			||||||
      lsi = this;
 | 
					      lsi = this;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x", get_soname(), sym_name, st_visibility);
 | 
					      DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x",
 | 
				
			||||||
 | 
					             get_realpath(), sym_name, st_visibility);
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s == nullptr) {
 | 
					    if (s == nullptr) {
 | 
				
			||||||
      // We only allow an undefined symbol if this is a weak reference.
 | 
					      // We only allow an undefined symbol if this is a weak reference.
 | 
				
			||||||
      if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
 | 
					      if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
 | 
				
			||||||
        DL_ERR("%s: cannot locate \"%s\"...", get_soname(), sym_name);
 | 
					        DL_ERR("%s: cannot locate \"%s\"...", get_realpath(), sym_name);
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      *got = 0;
 | 
					      *got = 0;
 | 
				
			||||||
@@ -198,3 +214,134 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__LP64__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Checks for mips32's various floating point abis.
 | 
				
			||||||
 | 
					// (Mips64 Android has a single floating point abi and doesn't need any checks)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Linux kernel has declarations similar to the following
 | 
				
			||||||
 | 
					//   in <linux>/arch/mips/include/asm/elf.h,
 | 
				
			||||||
 | 
					// but that non-uapi internal header file will never be imported
 | 
				
			||||||
 | 
					// into bionic's kernel headers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PT_MIPS_ABIFLAGS  0x70000003	// is .MIPS.abiflags segment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mips_elf_abiflags_v0 {
 | 
				
			||||||
 | 
					  uint16_t version;  // version of this structure
 | 
				
			||||||
 | 
					  uint8_t  isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size;
 | 
				
			||||||
 | 
					  uint8_t  fp_abi;  // mips32 ABI variants for floating point
 | 
				
			||||||
 | 
					  uint16_t isa_ext, ases, flags1, flags2;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Bits of flags1:
 | 
				
			||||||
 | 
					#define MIPS_AFL_FLAGS1_ODDSPREG 1  // Uses odd-numbered single-prec fp regs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Some values of fp_abi:        via compiler flag:
 | 
				
			||||||
 | 
					#define MIPS_ABI_FP_DOUBLE 1  // -mdouble-float
 | 
				
			||||||
 | 
					#define MIPS_ABI_FP_XX     5  // -mfpxx
 | 
				
			||||||
 | 
					#define MIPS_ABI_FP_64A    7  // -mips32r* -mfp64 -mno-odd-spreg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if __mips_isa_rev >= 5
 | 
				
			||||||
 | 
					static bool mips_fre_mode_on = false;  // have set FRE=1 mode for process
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool soinfo::mips_check_and_adjust_fp_modes() {
 | 
				
			||||||
 | 
					  mips_elf_abiflags_v0* abiflags = nullptr;
 | 
				
			||||||
 | 
					  int mips_fpabi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Find soinfo's optional .MIPS.abiflags segment
 | 
				
			||||||
 | 
					  for (size_t i = 0; i<phnum; ++i) {
 | 
				
			||||||
 | 
					    const ElfW(Phdr)& ph = phdr[i];
 | 
				
			||||||
 | 
					    if (ph.p_type == PT_MIPS_ABIFLAGS) {
 | 
				
			||||||
 | 
					      if (ph.p_filesz < sizeof (mips_elf_abiflags_v0)) {
 | 
				
			||||||
 | 
					        DL_ERR("Corrupt PT_MIPS_ABIFLAGS header found \"%s\"", get_realpath());
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      abiflags = reinterpret_cast<mips_elf_abiflags_v0*>(ph.p_vaddr + load_bias);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // FP ABI-variant compatibility checks for MIPS o32 ABI
 | 
				
			||||||
 | 
					  if (abiflags == nullptr) {
 | 
				
			||||||
 | 
					    // Old compilers and some translators don't emit the new abiflags section.
 | 
				
			||||||
 | 
					    const char* filename = get_realpath();
 | 
				
			||||||
 | 
					    size_t len = strlen(filename);
 | 
				
			||||||
 | 
					    if (len > 4 && (strcmp(filename+len-4, ".dex") == 0 ||
 | 
				
			||||||
 | 
					                    strcmp(filename+len-4, ".oat") == 0   )) {
 | 
				
			||||||
 | 
					      // Assume dex2oat is compatible with target
 | 
				
			||||||
 | 
					      mips_fpabi = MIPS_ABI_FP_XX;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // Old Android compilers used -mfp32 -mdouble-float -modd-spreg defaults,
 | 
				
			||||||
 | 
					      //   ie FP32 aka DOUBLE, using FR=0 mode fpregs & odd single-prec fpregs
 | 
				
			||||||
 | 
					      mips_fpabi = MIPS_ABI_FP_DOUBLE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    mips_fpabi = abiflags->fp_abi;
 | 
				
			||||||
 | 
					    if ( (abiflags->flags1 & MIPS_AFL_FLAGS1_ODDSPREG)
 | 
				
			||||||
 | 
					         && (mips_fpabi == MIPS_ABI_FP_XX ||
 | 
				
			||||||
 | 
					             mips_fpabi == MIPS_ABI_FP_64A   ) ) {
 | 
				
			||||||
 | 
					      // Android supports fewer cases than Linux
 | 
				
			||||||
 | 
					      DL_ERR("Unsupported odd-single-prec FloatPt reg uses in \"%s\"",
 | 
				
			||||||
 | 
					             get_realpath());
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!(mips_fpabi == MIPS_ABI_FP_DOUBLE ||
 | 
				
			||||||
 | 
					#if __mips_isa_rev >= 5
 | 
				
			||||||
 | 
					        mips_fpabi == MIPS_ABI_FP_64A    ||
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        mips_fpabi == MIPS_ABI_FP_XX       )) {
 | 
				
			||||||
 | 
					    DL_ERR("Unsupported MIPS32 FloatPt ABI %d found in \"%s\"",
 | 
				
			||||||
 | 
					           mips_fpabi, get_realpath());
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if __mips_isa_rev >= 5
 | 
				
			||||||
 | 
					  // Adjust process's FR Emulation mode, if needed
 | 
				
			||||||
 | 
					  //
 | 
				
			||||||
 | 
					  // On Mips R5 & R6, Android runs continuously in FR=1 64bit-fpreg mode.
 | 
				
			||||||
 | 
					  // NDK mips32 apps compiled with old compilers generate FP32 code
 | 
				
			||||||
 | 
					  //   which expects FR=0 32-bit fp registers.
 | 
				
			||||||
 | 
					  // NDK mips32 apps compiled with newer compilers generate modeless
 | 
				
			||||||
 | 
					  //   FPXX code which runs on both FR=0 and FR=1 modes.
 | 
				
			||||||
 | 
					  // Android itself is compiled in FP64A which requires FR=1 mode.
 | 
				
			||||||
 | 
					  // FP32, FPXX, and FP64A all interlink okay, without dynamic FR mode
 | 
				
			||||||
 | 
					  //   changes during calls.  For details, see
 | 
				
			||||||
 | 
					  //   http://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
 | 
				
			||||||
 | 
					  // Processes containing FR32 FR=0 code are run via kernel software assist,
 | 
				
			||||||
 | 
					  //   which maps all odd-numbered single-precision reg refs onto the
 | 
				
			||||||
 | 
					  //   upper half of the paired even-numbered double-precision reg.
 | 
				
			||||||
 | 
					  // FRE=1 triggers traps to the kernel's emulator on every single-precision
 | 
				
			||||||
 | 
					  //   fp op (for both odd and even-numbered registers).
 | 
				
			||||||
 | 
					  // Turning on FRE=1 traps is done at most once per process, simultanously
 | 
				
			||||||
 | 
					  //   for all threads of that process, when dlopen discovers FP32 code.
 | 
				
			||||||
 | 
					  // The kernel repacks threads' registers when FRE mode is turn on or off.
 | 
				
			||||||
 | 
					  //   These asynchronous adjustments are wrong if any thread was executing
 | 
				
			||||||
 | 
					  //   FPXX code using odd-numbered single-precision regs.
 | 
				
			||||||
 | 
					  // Current Android compilers default to the -mno-oddspreg option,
 | 
				
			||||||
 | 
					  //   and this requirement is checked by Android's dlopen.
 | 
				
			||||||
 | 
					  //   So FRE can always be safely turned on for FP32, anytime.
 | 
				
			||||||
 | 
					  // Deferred enhancement: Allow loading of odd-spreg FPXX modules.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (mips_fpabi == MIPS_ABI_FP_DOUBLE && !mips_fre_mode_on) {
 | 
				
			||||||
 | 
					    // Turn on FRE mode, which emulates mode-sensitive FR=0 code on FR=1
 | 
				
			||||||
 | 
					    //   register files, by trapping to kernel on refs to single-precision regs
 | 
				
			||||||
 | 
					    if (prctl(PR_SET_FP_MODE, PR_FP_MODE_FR|PR_FP_MODE_FRE)) {
 | 
				
			||||||
 | 
					      DL_ERR("Kernel or cpu failed to set FRE mode required for running \"%s\"",
 | 
				
			||||||
 | 
					             get_realpath());
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    DL_WARN("Using FRE=1 mode to run \"%s\"", get_realpath());
 | 
				
			||||||
 | 
					    mips_fre_mode_on = true;  // Avoid future redundant mode-switch calls
 | 
				
			||||||
 | 
					    // FRE mode is never turned back off.
 | 
				
			||||||
 | 
					    // Deferred enhancement:
 | 
				
			||||||
 | 
					    //   Reset FRE mode when dlclose() removes all FP32 modules
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  // Android runs continuously in FR=0 32bit-fpreg mode.
 | 
				
			||||||
 | 
					#endif  // __mips_isa_rev
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif  // __LP64___
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -771,6 +771,26 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return the program interpreter string, or nullptr if missing.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Input:
 | 
				
			||||||
 | 
					 *   phdr_table  -> program header table
 | 
				
			||||||
 | 
					 *   phdr_count  -> number of entries in tables
 | 
				
			||||||
 | 
					 *   load_bias   -> load bias
 | 
				
			||||||
 | 
					 * Return:
 | 
				
			||||||
 | 
					 *   pointer to the program interpreter string.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
 | 
				
			||||||
 | 
					                                            ElfW(Addr) load_bias) {
 | 
				
			||||||
 | 
					  for (size_t i = 0; i<phdr_count; ++i) {
 | 
				
			||||||
 | 
					    const ElfW(Phdr)& phdr = phdr_table[i];
 | 
				
			||||||
 | 
					    if (phdr.p_type == PT_INTERP) {
 | 
				
			||||||
 | 
					      return reinterpret_cast<const char*>(load_bias + phdr.p_vaddr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets loaded_phdr_ to the address of the program header table as it appears
 | 
					// Sets loaded_phdr_ to the address of the program header table as it appears
 | 
				
			||||||
// in the loaded segments in memory. This is in contrast with phdr_table_,
 | 
					// in the loaded segments in memory. This is in contrast with phdr_table_,
 | 
				
			||||||
// which is temporary and will be released before the library is relocated.
 | 
					// which is temporary and will be released before the library is relocated.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,4 +109,7 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
 | 
				
			|||||||
                                    ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
 | 
					                                    ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
 | 
				
			||||||
                                    ElfW(Word)* dynamic_flags);
 | 
					                                    ElfW(Word)* dynamic_flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
 | 
				
			||||||
 | 
					                                            ElfW(Addr) load_bias);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LINKER_PHDR_H */
 | 
					#endif /* LINKER_PHDR_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
					LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror -std=gnu++11
 | 
					LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror
 | 
				
			||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
 | 
					LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_SRC_FILES := \
 | 
					LOCAL_SRC_FILES := \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ endif
 | 
				
			|||||||
LOCAL_CLANG := $($(module)_clang_$(build_type))
 | 
					LOCAL_CLANG := $($(module)_clang_$(build_type))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifneq ($($(module)_allow_asan),true)
 | 
					ifneq ($($(module)_allow_asan),true)
 | 
				
			||||||
LOCAL_ADDRESS_SANITIZER := false
 | 
					LOCAL_SANITIZE := never
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
 | 
					LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
 | 
				
			||||||
@@ -48,6 +48,10 @@ ifneq ($($(module)_multilib),)
 | 
				
			|||||||
    LOCAL_MULTILIB := $($(module)_multilib)
 | 
					    LOCAL_MULTILIB := $($(module)_multilib)
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifneq ($($(module)_relative_path),)
 | 
				
			||||||
 | 
					    LOCAL_MODULE_RELATIVE_PATH := $($(module)_relative_path)
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL_CFLAGS := \
 | 
					LOCAL_CFLAGS := \
 | 
				
			||||||
    $(common_cflags) \
 | 
					    $(common_cflags) \
 | 
				
			||||||
    $($(module)_cflags) \
 | 
					    $($(module)_cflags) \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,8 +46,7 @@ else
 | 
				
			|||||||
test_cflags += -DUSE_JEMALLOC
 | 
					test_cflags += -DUSE_JEMALLOC
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_cppflags = \
 | 
					test_cppflags := \
 | 
				
			||||||
    -std=gnu++11 \
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
libBionicStandardTests_src_files := \
 | 
					libBionicStandardTests_src_files := \
 | 
				
			||||||
    arpa_inet_test.cpp \
 | 
					    arpa_inet_test.cpp \
 | 
				
			||||||
@@ -93,6 +92,7 @@ libBionicStandardTests_src_files := \
 | 
				
			|||||||
    sys_epoll_test.cpp \
 | 
					    sys_epoll_test.cpp \
 | 
				
			||||||
    sys_mman_test.cpp \
 | 
					    sys_mman_test.cpp \
 | 
				
			||||||
    sys_personality_test.cpp \
 | 
					    sys_personality_test.cpp \
 | 
				
			||||||
 | 
					    sys_prctl_test.cpp \
 | 
				
			||||||
    sys_procfs_test.cpp \
 | 
					    sys_procfs_test.cpp \
 | 
				
			||||||
    sys_resource_test.cpp \
 | 
					    sys_resource_test.cpp \
 | 
				
			||||||
    sys_select_test.cpp \
 | 
					    sys_select_test.cpp \
 | 
				
			||||||
@@ -137,6 +137,11 @@ libBionicStandardTests_static_libraries := \
 | 
				
			|||||||
libBionicStandardTests_ldlibs_host := \
 | 
					libBionicStandardTests_ldlibs_host := \
 | 
				
			||||||
    -lrt \
 | 
					    -lrt \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Clang/llvm has incompatible long double (fp128) for x86_64.
 | 
				
			||||||
 | 
					# https://llvm.org/bugs/show_bug.cgi?id=23897
 | 
				
			||||||
 | 
					# This affects most of math_test.cpp.
 | 
				
			||||||
 | 
					libBionicStandardTests_clang_target := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module := libBionicStandardTests
 | 
					module := libBionicStandardTests
 | 
				
			||||||
module_tag := optional
 | 
					module_tag := optional
 | 
				
			||||||
build_type := target
 | 
					build_type := target
 | 
				
			||||||
@@ -241,12 +246,7 @@ libBionicCtsGtestMain_src_files := gtest_main.cpp
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
libBionicCtsGtestMain_cflags := $(test_cflags)
 | 
					libBionicCtsGtestMain_cflags := $(test_cflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libBionicCtsGtestMain_cppflags := $(test_cppflags) -DUSING_GTEST_OUTPUT_FORMAT \
 | 
					libBionicCtsGtestMain_cppflags := $(test_cppflags) -DUSING_GTEST_OUTPUT_FORMAT
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Temporarily fix the job count to 1 for CTS since on some devices the
 | 
					 | 
				
			||||||
# number of online cores is incorrectly read as the total number of cores
 | 
					 | 
				
			||||||
# in the system. When b/24376925 is fixed, this should be removed.
 | 
					 | 
				
			||||||
libBionicCtsGtestMain_cppflags += -DJOB_COUNT_FIXED=1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
module := libBionicCtsGtestMain
 | 
					module := libBionicCtsGtestMain
 | 
				
			||||||
module_tag := optional
 | 
					module_tag := optional
 | 
				
			||||||
@@ -279,6 +279,7 @@ bionic-unit-tests_src_files := \
 | 
				
			|||||||
    dlfcn_test.cpp \
 | 
					    dlfcn_test.cpp \
 | 
				
			||||||
    libdl_test.cpp \
 | 
					    libdl_test.cpp \
 | 
				
			||||||
    pthread_dlfcn_test.cpp \
 | 
					    pthread_dlfcn_test.cpp \
 | 
				
			||||||
 | 
					    thread_local_test.cpp \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bionic-unit-tests_cflags := $(test_cflags)
 | 
					bionic-unit-tests_cflags := $(test_cflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -256,7 +256,7 @@ void RunSingleBufferAlignTest(
 | 
				
			|||||||
      VerifyFencepost(&buf_align[len]);
 | 
					      VerifyFencepost(&buf_align[len]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  delete buf;
 | 
					  delete[] buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RunSrcDstBufferAlignTest(
 | 
					void RunSrcDstBufferAlignTest(
 | 
				
			||||||
@@ -292,8 +292,8 @@ void RunSrcDstBufferAlignTest(
 | 
				
			|||||||
      VerifyFencepost(&dst_align[len]);
 | 
					      VerifyFencepost(&dst_align[len]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  delete src;
 | 
					  delete[] src;
 | 
				
			||||||
  delete dst;
 | 
					  delete[] dst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RunCmpBufferAlignTest(
 | 
					void RunCmpBufferAlignTest(
 | 
				
			||||||
@@ -344,8 +344,8 @@ void RunCmpBufferAlignTest(
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  delete buf1;
 | 
					  delete[] buf1;
 | 
				
			||||||
  delete buf2;
 | 
					  delete[] buf2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RunSingleBufferOverreadTest(void (*test_func)(uint8_t*, size_t)) {
 | 
					void RunSingleBufferOverreadTest(void (*test_func)(uint8_t*, size_t)) {
 | 
				
			||||||
@@ -389,7 +389,7 @@ void RunSrcDstBufferOverreadTest(void (*test_func)(uint8_t*, uint8_t*, size_t))
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
 | 
					  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
 | 
				
			||||||
  free(memory);
 | 
					  free(memory);
 | 
				
			||||||
  delete dst;
 | 
					  delete[] dst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RunCmpBufferOverreadTest(
 | 
					void RunCmpBufferOverreadTest(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,12 +51,12 @@ TEST(dlfcn, ctor_function_call) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlsym_in_executable) {
 | 
					TEST(dlfcn, dlsym_in_executable) {
 | 
				
			||||||
  dlerror(); // Clear any pending errors.
 | 
					  dlerror(); // Clear any pending errors.
 | 
				
			||||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
					  void* self = dlopen(nullptr, RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self != NULL);
 | 
					  ASSERT_TRUE(self != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
					  ASSERT_TRUE(dlerror() == nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* sym = dlsym(self, "DlSymTestFunction");
 | 
					  void* sym = dlsym(self, "DlSymTestFunction");
 | 
				
			||||||
  ASSERT_TRUE(sym != NULL);
 | 
					  ASSERT_TRUE(sym != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void (*function)() = reinterpret_cast<void(*)()>(sym);
 | 
					  void (*function)() = reinterpret_cast<void(*)()>(sym);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -175,11 +175,11 @@ TEST(dlfcn, dlsym_with_dependencies) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlopen_noload) {
 | 
					TEST(dlfcn, dlopen_noload) {
 | 
				
			||||||
  void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
 | 
					  void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
 | 
				
			||||||
  ASSERT_TRUE(handle == NULL);
 | 
					  ASSERT_TRUE(handle == nullptr);
 | 
				
			||||||
  handle = dlopen("libtest_simple.so", RTLD_NOW);
 | 
					  handle = dlopen("libtest_simple.so", RTLD_NOW);
 | 
				
			||||||
  void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
 | 
					  void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(handle2 != NULL);
 | 
					  ASSERT_TRUE(handle2 != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(handle == handle2);
 | 
					  ASSERT_TRUE(handle == handle2);
 | 
				
			||||||
  ASSERT_EQ(0, dlclose(handle));
 | 
					  ASSERT_EQ(0, dlclose(handle));
 | 
				
			||||||
  ASSERT_EQ(0, dlclose(handle2));
 | 
					  ASSERT_EQ(0, dlclose(handle2));
 | 
				
			||||||
@@ -220,11 +220,11 @@ TEST(dlfcn, ifunc) {
 | 
				
			|||||||
  // first check the set case
 | 
					  // first check the set case
 | 
				
			||||||
  setenv("IFUNC_CHOICE", "set", 1);
 | 
					  setenv("IFUNC_CHOICE", "set", 1);
 | 
				
			||||||
  void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
 | 
					  void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != nullptr);
 | 
				
			||||||
  fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
 | 
					  fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
 | 
				
			||||||
  fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
					  fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
				
			||||||
  ASSERT_TRUE(foo_ptr != NULL);
 | 
					  ASSERT_TRUE(foo_ptr != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(foo_library_ptr != NULL);
 | 
					  ASSERT_TRUE(foo_library_ptr != nullptr);
 | 
				
			||||||
  ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
 | 
					  ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
 | 
				
			||||||
  ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
 | 
					  ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
 | 
				
			||||||
  dlclose(handle);
 | 
					  dlclose(handle);
 | 
				
			||||||
@@ -232,11 +232,11 @@ TEST(dlfcn, ifunc) {
 | 
				
			|||||||
  // then check the unset case
 | 
					  // then check the unset case
 | 
				
			||||||
  unsetenv("IFUNC_CHOICE");
 | 
					  unsetenv("IFUNC_CHOICE");
 | 
				
			||||||
  handle = dlopen("libtest_ifunc.so", RTLD_NOW);
 | 
					  handle = dlopen("libtest_ifunc.so", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != nullptr);
 | 
				
			||||||
  foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
 | 
					  foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
 | 
				
			||||||
  foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
					  foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
				
			||||||
  ASSERT_TRUE(foo_ptr != NULL);
 | 
					  ASSERT_TRUE(foo_ptr != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(foo_library_ptr != NULL);
 | 
					  ASSERT_TRUE(foo_library_ptr != nullptr);
 | 
				
			||||||
  ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
 | 
					  ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
 | 
				
			||||||
  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
 | 
					  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
 | 
				
			||||||
  dlclose(handle);
 | 
					  dlclose(handle);
 | 
				
			||||||
@@ -315,9 +315,9 @@ TEST(dlfcn, dlopen_check_order_dlsym) {
 | 
				
			|||||||
  typedef int (*fn_t) (void);
 | 
					  typedef int (*fn_t) (void);
 | 
				
			||||||
  fn_t fn, fn2;
 | 
					  fn_t fn, fn2;
 | 
				
			||||||
  fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"));
 | 
					  fn = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer"));
 | 
				
			||||||
  ASSERT_TRUE(fn != NULL) << dlerror();
 | 
					  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
				
			||||||
  fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2"));
 | 
					  fn2 = reinterpret_cast<fn_t>(dlsym(RTLD_DEFAULT, "check_order_dlsym_get_answer2"));
 | 
				
			||||||
  ASSERT_TRUE(fn2 != NULL) << dlerror();
 | 
					  ASSERT_TRUE(fn2 != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ASSERT_EQ(42, fn());
 | 
					  ASSERT_EQ(42, fn());
 | 
				
			||||||
  ASSERT_EQ(43, fn2());
 | 
					  ASSERT_EQ(43, fn2());
 | 
				
			||||||
@@ -718,7 +718,7 @@ TEST(dlfcn, dlsym_df_1_global) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlopen_failure) {
 | 
					TEST(dlfcn, dlopen_failure) {
 | 
				
			||||||
  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
					  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self == NULL);
 | 
					  ASSERT_TRUE(self == nullptr);
 | 
				
			||||||
#if defined(__BIONIC__)
 | 
					#if defined(__BIONIC__)
 | 
				
			||||||
  ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror());
 | 
					  ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror());
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
@@ -737,7 +737,7 @@ TEST(dlfcn, dlerror_concurrent) {
 | 
				
			|||||||
  ASSERT_SUBSTR("/main/thread", main_thread_error);
 | 
					  ASSERT_SUBSTR("/main/thread", main_thread_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pthread_t t;
 | 
					  pthread_t t;
 | 
				
			||||||
  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentDlErrorFn, NULL));
 | 
					  ASSERT_EQ(0, pthread_create(&t, nullptr, ConcurrentDlErrorFn, nullptr));
 | 
				
			||||||
  void* result;
 | 
					  void* result;
 | 
				
			||||||
  ASSERT_EQ(0, pthread_join(t, &result));
 | 
					  ASSERT_EQ(0, pthread_join(t, &result));
 | 
				
			||||||
  char* child_thread_error = static_cast<char*>(result);
 | 
					  char* child_thread_error = static_cast<char*>(result);
 | 
				
			||||||
@@ -749,31 +749,31 @@ TEST(dlfcn, dlerror_concurrent) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlsym_failures) {
 | 
					TEST(dlfcn, dlsym_failures) {
 | 
				
			||||||
  dlerror(); // Clear any pending errors.
 | 
					  dlerror(); // Clear any pending errors.
 | 
				
			||||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
					  void* self = dlopen(nullptr, RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self != NULL);
 | 
					  ASSERT_TRUE(self != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
					  ASSERT_TRUE(dlerror() == nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* sym;
 | 
					  void* sym;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__BIONIC__) && !defined(__LP64__)
 | 
					#if defined(__BIONIC__) && !defined(__LP64__)
 | 
				
			||||||
  // RTLD_DEFAULT in lp32 bionic is not (void*)0
 | 
					  // RTLD_DEFAULT in lp32 bionic is not (void*)0
 | 
				
			||||||
  // so it can be distinguished from the NULL handle.
 | 
					  // so it can be distinguished from the NULL handle.
 | 
				
			||||||
  sym = dlsym(NULL, "test");
 | 
					  sym = dlsym(nullptr, "test");
 | 
				
			||||||
  ASSERT_TRUE(sym == NULL);
 | 
					  ASSERT_TRUE(sym == nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR("dlsym library handle is null", dlerror());
 | 
					  ASSERT_SUBSTR("dlsym library handle is null", dlerror());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // NULL symbol name.
 | 
					  // NULL symbol name.
 | 
				
			||||||
#if defined(__BIONIC__)
 | 
					#if defined(__BIONIC__)
 | 
				
			||||||
  // glibc marks this parameter non-null and SEGVs if you cheat.
 | 
					  // glibc marks this parameter non-null and SEGVs if you cheat.
 | 
				
			||||||
  sym = dlsym(self, NULL);
 | 
					  sym = dlsym(self, nullptr);
 | 
				
			||||||
  ASSERT_TRUE(sym == NULL);
 | 
					  ASSERT_TRUE(sym == nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR("", dlerror());
 | 
					  ASSERT_SUBSTR("", dlerror());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Symbol that doesn't exist.
 | 
					  // Symbol that doesn't exist.
 | 
				
			||||||
  sym = dlsym(self, "ThisSymbolDoesNotExist");
 | 
					  sym = dlsym(self, "ThisSymbolDoesNotExist");
 | 
				
			||||||
  ASSERT_TRUE(sym == NULL);
 | 
					  ASSERT_TRUE(sym == nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror());
 | 
					  ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ASSERT_EQ(0, dlclose(self));
 | 
					  ASSERT_EQ(0, dlclose(self));
 | 
				
			||||||
@@ -781,12 +781,12 @@ TEST(dlfcn, dlsym_failures) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dladdr_executable) {
 | 
					TEST(dlfcn, dladdr_executable) {
 | 
				
			||||||
  dlerror(); // Clear any pending errors.
 | 
					  dlerror(); // Clear any pending errors.
 | 
				
			||||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
					  void* self = dlopen(nullptr, RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self != NULL);
 | 
					  ASSERT_TRUE(self != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
					  ASSERT_TRUE(dlerror() == nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void* sym = dlsym(self, "DlSymTestFunction");
 | 
					  void* sym = dlsym(self, "DlSymTestFunction");
 | 
				
			||||||
  ASSERT_TRUE(sym != NULL);
 | 
					  ASSERT_TRUE(sym != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address.
 | 
					  // Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address.
 | 
				
			||||||
  void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
 | 
					  void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
 | 
				
			||||||
@@ -861,12 +861,12 @@ TEST(dlfcn, dladdr_invalid) {
 | 
				
			|||||||
  dlerror(); // Clear any pending errors.
 | 
					  dlerror(); // Clear any pending errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // No symbol corresponding to NULL.
 | 
					  // No symbol corresponding to NULL.
 | 
				
			||||||
  ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success.
 | 
					  ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success.
 | 
				
			||||||
  ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3).
 | 
					  ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // No symbol corresponding to a stack address.
 | 
					  // No symbol corresponding to a stack address.
 | 
				
			||||||
  ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success.
 | 
					  ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success.
 | 
				
			||||||
  ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3).
 | 
					  ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GNU-style ELF hash tables are incompatible with the MIPS ABI.
 | 
					// GNU-style ELF hash tables are incompatible with the MIPS ABI.
 | 
				
			||||||
@@ -922,49 +922,49 @@ TEST(dlfcn, dlopen_bad_flags) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if defined(__GLIBC__)
 | 
					#if defined(__GLIBC__)
 | 
				
			||||||
  // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
 | 
					  // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
 | 
				
			||||||
  handle = dlopen(NULL, 0);
 | 
					  handle = dlopen(nullptr, 0);
 | 
				
			||||||
  ASSERT_TRUE(handle == NULL);
 | 
					  ASSERT_TRUE(handle == nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR("invalid", dlerror());
 | 
					  ASSERT_SUBSTR("invalid", dlerror());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handle = dlopen(NULL, 0xffffffff);
 | 
					  handle = dlopen(nullptr, 0xffffffff);
 | 
				
			||||||
  ASSERT_TRUE(handle == NULL);
 | 
					  ASSERT_TRUE(handle == nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR("invalid", dlerror());
 | 
					  ASSERT_SUBSTR("invalid", dlerror());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we.
 | 
					  // glibc actually allows you to choose both RTLD_NOW and RTLD_LAZY at the same time, and so do we.
 | 
				
			||||||
  handle = dlopen(NULL, RTLD_NOW|RTLD_LAZY);
 | 
					  handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != nullptr);
 | 
				
			||||||
  ASSERT_SUBSTR(NULL, dlerror());
 | 
					  ASSERT_SUBSTR(nullptr, dlerror());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, rtld_default_unknown_symbol) {
 | 
					TEST(dlfcn, rtld_default_unknown_symbol) {
 | 
				
			||||||
  void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
					  void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
				
			||||||
  ASSERT_TRUE(addr == NULL);
 | 
					  ASSERT_TRUE(addr == nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, rtld_default_known_symbol) {
 | 
					TEST(dlfcn, rtld_default_known_symbol) {
 | 
				
			||||||
  void* addr = dlsym(RTLD_DEFAULT, "fopen");
 | 
					  void* addr = dlsym(RTLD_DEFAULT, "fopen");
 | 
				
			||||||
  ASSERT_TRUE(addr != NULL);
 | 
					  ASSERT_TRUE(addr != nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, rtld_next_unknown_symbol) {
 | 
					TEST(dlfcn, rtld_next_unknown_symbol) {
 | 
				
			||||||
  void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
					  void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
				
			||||||
  ASSERT_TRUE(addr == NULL);
 | 
					  ASSERT_TRUE(addr == nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, rtld_next_known_symbol) {
 | 
					TEST(dlfcn, rtld_next_known_symbol) {
 | 
				
			||||||
  void* addr = dlsym(RTLD_NEXT, "fopen");
 | 
					  void* addr = dlsym(RTLD_NEXT, "fopen");
 | 
				
			||||||
  ASSERT_TRUE(addr != NULL);
 | 
					  ASSERT_TRUE(addr != nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlsym_weak_func) {
 | 
					TEST(dlfcn, dlsym_weak_func) {
 | 
				
			||||||
  dlerror();
 | 
					  dlerror();
 | 
				
			||||||
  void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW);
 | 
					  void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int (*weak_func)();
 | 
					  int (*weak_func)();
 | 
				
			||||||
  weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
 | 
					  weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
 | 
				
			||||||
  ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror();
 | 
					  ASSERT_TRUE(weak_func != nullptr) << "dlerror: " << dlerror();
 | 
				
			||||||
  EXPECT_EQ(42, weak_func());
 | 
					  EXPECT_EQ(42, weak_func());
 | 
				
			||||||
  dlclose(handle);
 | 
					  dlclose(handle);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -982,8 +982,8 @@ TEST(dlfcn, dlopen_undefined_weak_func) {
 | 
				
			|||||||
TEST(dlfcn, dlopen_symlink) {
 | 
					TEST(dlfcn, dlopen_symlink) {
 | 
				
			||||||
  void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
 | 
					  void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
 | 
				
			||||||
  void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
 | 
					  void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(handle1 != NULL);
 | 
					  ASSERT_TRUE(handle1 != nullptr);
 | 
				
			||||||
  ASSERT_TRUE(handle2 != NULL);
 | 
					  ASSERT_TRUE(handle2 != nullptr);
 | 
				
			||||||
  ASSERT_EQ(handle1, handle2);
 | 
					  ASSERT_EQ(handle1, handle2);
 | 
				
			||||||
  dlclose(handle1);
 | 
					  dlclose(handle1);
 | 
				
			||||||
  dlclose(handle2);
 | 
					  dlclose(handle2);
 | 
				
			||||||
@@ -1062,3 +1062,17 @@ extern "C" int version_zero_function() {
 | 
				
			|||||||
extern "C" int version_zero_function2() {
 | 
					extern "C" int version_zero_function2() {
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dt_runpath) {
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef void *(* dlopen_b_fn)();
 | 
				
			||||||
 | 
					  dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
 | 
				
			||||||
 | 
					  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void *p = fn();
 | 
				
			||||||
 | 
					  ASSERT_TRUE(p != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -230,3 +230,43 @@ void test_ppoll() {
 | 
				
			|||||||
  // clang should emit a warning, but doesn't
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
  ppoll(fds, 2, &timeout, NULL);
 | 
					  ppoll(fds, 2, &timeout, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_fread_overflow() {
 | 
				
			||||||
 | 
					  char buf[4];
 | 
				
			||||||
 | 
					  // NOLINTNEXTLINE(whitespace/line_length)
 | 
				
			||||||
 | 
					  // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count
 | 
				
			||||||
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
 | 
					  fread(buf, 2, (size_t)-1, stdin);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_fread_too_big() {
 | 
				
			||||||
 | 
					  char buf[4];
 | 
				
			||||||
 | 
					  // NOLINTNEXTLINE(whitespace/line_length)
 | 
				
			||||||
 | 
					  // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer
 | 
				
			||||||
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
 | 
					  fread(buf, 1, 5, stdin);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_fwrite_overflow() {
 | 
				
			||||||
 | 
					  char buf[4];
 | 
				
			||||||
 | 
					  // NOLINTNEXTLINE(whitespace/line_length)
 | 
				
			||||||
 | 
					  // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
 | 
				
			||||||
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
 | 
					  fwrite(buf, 2, (size_t)-1, stdout);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_fwrite_too_big() {
 | 
				
			||||||
 | 
					  char buf[4] = {0};
 | 
				
			||||||
 | 
					  // NOLINTNEXTLINE(whitespace/line_length)
 | 
				
			||||||
 | 
					  // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer
 | 
				
			||||||
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
 | 
					  fwrite(buf, 1, 5, stdout);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_getcwd() {
 | 
				
			||||||
 | 
					  char buf[4];
 | 
				
			||||||
 | 
					  // NOLINTNEXTLINE(whitespace/line_length)
 | 
				
			||||||
 | 
					  // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
 | 
				
			||||||
 | 
					  // clang should emit a warning, but doesn't
 | 
				
			||||||
 | 
					  getcwd(buf, 5);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -623,6 +623,12 @@ TEST_F(DEATHTEST, FD_ISSET_2_fortified) {
 | 
				
			|||||||
  ASSERT_FORTIFY(FD_ISSET(0, set));
 | 
					  ASSERT_FORTIFY(FD_ISSET(0, set));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DEATHTEST, getcwd_fortified) {
 | 
				
			||||||
 | 
					  char buf[1];
 | 
				
			||||||
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 | 
					  ASSERT_FORTIFY(getcwd(buf, ct));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DEATHTEST, pread_fortified) {
 | 
					TEST_F(DEATHTEST, pread_fortified) {
 | 
				
			||||||
  char buf[1];
 | 
					  char buf[1];
 | 
				
			||||||
  size_t ct = atoi("2"); // prevent optimizations
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
@@ -647,6 +653,22 @@ TEST_F(DEATHTEST, read_fortified) {
 | 
				
			|||||||
  close(fd);
 | 
					  close(fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DEATHTEST, fread_fortified) {
 | 
				
			||||||
 | 
					  char buf[1];
 | 
				
			||||||
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 | 
					  FILE* fp = fopen("/dev/null", "r");
 | 
				
			||||||
 | 
					  ASSERT_FORTIFY(fread(buf, 1, ct, fp));
 | 
				
			||||||
 | 
					  fclose(fp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DEATHTEST, fwrite_fortified) {
 | 
				
			||||||
 | 
					  char buf[1] = {0};
 | 
				
			||||||
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 | 
					  FILE* fp = fopen("/dev/null", "w");
 | 
				
			||||||
 | 
					  ASSERT_FORTIFY(fwrite(buf, 1, ct, fp));
 | 
				
			||||||
 | 
					  fclose(fp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_F(DEATHTEST, readlink_fortified) {
 | 
					TEST_F(DEATHTEST, readlink_fortified) {
 | 
				
			||||||
  char buf[1];
 | 
					  char buf[1];
 | 
				
			||||||
  size_t ct = atoi("2"); // prevent optimizations
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ using testing::internal::COLOR_GREEN;
 | 
				
			|||||||
using testing::internal::COLOR_YELLOW;
 | 
					using testing::internal::COLOR_YELLOW;
 | 
				
			||||||
using testing::internal::ColoredPrintf;
 | 
					using testing::internal::ColoredPrintf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 90000;
 | 
					constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 60000;
 | 
				
			||||||
constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000;
 | 
					constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The time each test can run before killed for the reason of timeout.
 | 
					// The time each test can run before killed for the reason of timeout.
 | 
				
			||||||
@@ -256,7 +256,7 @@ static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcas
 | 
				
			|||||||
    while (*p != '\0' && isspace(*p)) {
 | 
					    while (*p != '\0' && isspace(*p)) {
 | 
				
			||||||
      ++p;
 | 
					      ++p;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (*p != '\0') {
 | 
					    if (*p != '\0' && *p != '#') {
 | 
				
			||||||
      // This is not we want, gtest must meet with some error when parsing the arguments.
 | 
					      // This is not we want, gtest must meet with some error when parsing the arguments.
 | 
				
			||||||
      fprintf(stderr, "argument error, check with --help\n");
 | 
					      fprintf(stderr, "argument error, check with --help\n");
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
@@ -839,12 +839,8 @@ static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>&
 | 
				
			|||||||
  return all_tests_passed;
 | 
					  return all_tests_passed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t GetDefaultJobCount() {
 | 
					static size_t GetProcessorCount() {
 | 
				
			||||||
#if defined(JOB_COUNT_FIXED)
 | 
					 | 
				
			||||||
  return JOB_COUNT_FIXED;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
 | 
					  return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) {
 | 
					static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) {
 | 
				
			||||||
@@ -954,7 +950,7 @@ static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Init default isolation test options.
 | 
					  // Init default isolation test options.
 | 
				
			||||||
  options.job_count = GetDefaultJobCount();
 | 
					  options.job_count = GetProcessorCount();
 | 
				
			||||||
  options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
 | 
					  options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
 | 
				
			||||||
  options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
 | 
					  options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
 | 
				
			||||||
  options.gtest_color = testing::GTEST_FLAG(color);
 | 
					  options.gtest_color = testing::GTEST_FLAG(color);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										66
									
								
								tests/libs/Android.build.dt_runpath.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tests/libs/Android.build.dt_runpath.mk
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2012 The Android Open Source Project
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Libraries used by dt_runpath tests.
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A leaf library in a non-standard directory.
 | 
				
			||||||
 | 
					libtest_dt_runpath_a_src_files := \
 | 
				
			||||||
 | 
					    empty.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_dt_runpath_a_relative_path := dt_runpath_a
 | 
				
			||||||
 | 
					module := libtest_dt_runpath_a
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Depends on library A with a DT_RUNPATH
 | 
				
			||||||
 | 
					libtest_dt_runpath_b_src_files := \
 | 
				
			||||||
 | 
					    empty.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_dt_runpath_b_shared_libraries := libtest_dt_runpath_a
 | 
				
			||||||
 | 
					libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a -Wl,--enable-new-dtags
 | 
				
			||||||
 | 
					libtest_dt_runpath_b_relative_path := dt_runpath_b_c_x
 | 
				
			||||||
 | 
					module := libtest_dt_runpath_b
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Depends on library A with an incorrect DT_RUNPATH. This does not matter
 | 
				
			||||||
 | 
					# because B is the first in the D (below) dependency order, and library A
 | 
				
			||||||
 | 
					# is already loaded using the correct DT_RUNPATH from library B.
 | 
				
			||||||
 | 
					libtest_dt_runpath_c_src_files := \
 | 
				
			||||||
 | 
					    empty.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_dt_runpath_c_shared_libraries := libtest_dt_runpath_a
 | 
				
			||||||
 | 
					libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath -Wl,--enable-new-dtags
 | 
				
			||||||
 | 
					libtest_dt_runpath_c_relative_path := dt_runpath_b_c_x
 | 
				
			||||||
 | 
					module := libtest_dt_runpath_c
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# D depends on B and C with DT_RUNPATH.
 | 
				
			||||||
 | 
					libtest_dt_runpath_d_src_files := \
 | 
				
			||||||
 | 
					    dlopen_b.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_dt_runpath_d_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
 | 
				
			||||||
 | 
					libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
 | 
				
			||||||
 | 
					module := libtest_dt_runpath_d
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A leaf library in a directory library D has DT_RUNPATH for.
 | 
				
			||||||
 | 
					libtest_dt_runpath_x_src_files := \
 | 
				
			||||||
 | 
					    empty.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					libtest_dt_runpath_x_relative_path := dt_runpath_b_c_x
 | 
				
			||||||
 | 
					module := libtest_dt_runpath_x
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
@@ -17,9 +17,10 @@
 | 
				
			|||||||
LOCAL_PATH := $(call my-dir)
 | 
					LOCAL_PATH := $(call my-dir)
 | 
				
			||||||
TEST_PATH := $(LOCAL_PATH)/..
 | 
					TEST_PATH := $(LOCAL_PATH)/..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
common_cppflags += -std=gnu++11
 | 
					common_cppflags :=
 | 
				
			||||||
common_additional_dependencies := \
 | 
					common_additional_dependencies := \
 | 
				
			||||||
    $(LOCAL_PATH)/Android.mk \
 | 
					    $(LOCAL_PATH)/Android.mk \
 | 
				
			||||||
 | 
					    $(LOCAL_PATH)/Android.build.dt_runpath.mk \
 | 
				
			||||||
    $(LOCAL_PATH)/Android.build.dlext_testzip.mk \
 | 
					    $(LOCAL_PATH)/Android.build.dlext_testzip.mk \
 | 
				
			||||||
    $(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk \
 | 
					    $(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk \
 | 
				
			||||||
    $(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
 | 
					    $(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
 | 
				
			||||||
@@ -67,8 +68,6 @@ libdlext_test_src_files := \
 | 
				
			|||||||
libdlext_test_ldflags := \
 | 
					libdlext_test_ldflags := \
 | 
				
			||||||
    -Wl,-z,relro \
 | 
					    -Wl,-z,relro \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libdlext_test_shared_libraries := libtest_simple
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module := libdlext_test
 | 
					module := libdlext_test
 | 
				
			||||||
module_tag := optional
 | 
					module_tag := optional
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
@@ -181,6 +180,11 @@ libtest_nodelete_dt_flags_1_ldflags := -Wl,-z,nodelete
 | 
				
			|||||||
module := libtest_nodelete_dt_flags_1
 | 
					module := libtest_nodelete_dt_flags_1
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Build DT_RUNPATH test helper libraries
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.dt_runpath.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
# Build library with two parents
 | 
					# Build library with two parents
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								tests/libs/dlopen_b.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/libs/dlopen_b.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#include <dlfcn.h>
 | 
				
			||||||
 | 
					extern "C" void *dlopen_b() {
 | 
				
			||||||
 | 
					  // TODO (dimitry): this is to work around http://b/20049306
 | 
				
			||||||
 | 
					  // remove once it is fixed
 | 
				
			||||||
 | 
					  static int dummy = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // This is not supposed to succeed. Even though this library has DT_RUNPATH
 | 
				
			||||||
 | 
					  // for libtest_dt_runpath_x.so, it is not taked into account for dlopen.
 | 
				
			||||||
 | 
					  void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
 | 
				
			||||||
 | 
					  if (handle != nullptr) {
 | 
				
			||||||
 | 
					    dummy++;
 | 
				
			||||||
 | 
					    return handle;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -27,7 +27,6 @@
 | 
				
			|||||||
#include <sys/syscall.h>
 | 
					#include <sys/syscall.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <unwind.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <regex>
 | 
					#include <regex>
 | 
				
			||||||
@@ -1155,6 +1154,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
				
			|||||||
  // The two methods of asking for the stack size should agree.
 | 
					  // The two methods of asking for the stack size should agree.
 | 
				
			||||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
					  EXPECT_EQ(stack_size, stack_size2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__BIONIC__)
 | 
				
			||||||
  // What does /proc/self/maps' [stack] line say?
 | 
					  // What does /proc/self/maps' [stack] line say?
 | 
				
			||||||
  void* maps_stack_hi = NULL;
 | 
					  void* maps_stack_hi = NULL;
 | 
				
			||||||
  FILE* fp = fopen("/proc/self/maps", "r");
 | 
					  FILE* fp = fopen("/proc/self/maps", "r");
 | 
				
			||||||
@@ -1171,15 +1171,18 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  fclose(fp);
 | 
					  fclose(fp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
 | 
				
			||||||
 | 
					  // Remember that the stack grows down (and is mapped in on demand), so the low address of the
 | 
				
			||||||
 | 
					  // region isn't very interesting.
 | 
				
			||||||
 | 
					  EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // The stack size should correspond to RLIMIT_STACK.
 | 
					  // The stack size should correspond to RLIMIT_STACK.
 | 
				
			||||||
  rlimit rl;
 | 
					  rlimit rl;
 | 
				
			||||||
  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
 | 
					  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
 | 
				
			||||||
  uint64_t original_rlim_cur = rl.rlim_cur;
 | 
					  uint64_t original_rlim_cur = rl.rlim_cur;
 | 
				
			||||||
#if defined(__BIONIC__)
 | 
					 | 
				
			||||||
  if (rl.rlim_cur == RLIM_INFINITY) {
 | 
					  if (rl.rlim_cur == RLIM_INFINITY) {
 | 
				
			||||||
    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
 | 
					    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  EXPECT_EQ(rl.rlim_cur, stack_size);
 | 
					  EXPECT_EQ(rl.rlim_cur, stack_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto guard = make_scope_guard([&rl, original_rlim_cur]() {
 | 
					  auto guard = make_scope_guard([&rl, original_rlim_cur]() {
 | 
				
			||||||
@@ -1187,11 +1190,6 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
				
			|||||||
    ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
 | 
					    ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
 | 
					 | 
				
			||||||
  // Remember that the stack grows down (and is mapped in on demand), so the low address of the
 | 
					 | 
				
			||||||
  // region isn't very interesting.
 | 
					 | 
				
			||||||
  EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //
 | 
					  //
 | 
				
			||||||
  // What if RLIMIT_STACK is smaller than the stack's current extent?
 | 
					  // What if RLIMIT_STACK is smaller than the stack's current extent?
 | 
				
			||||||
  //
 | 
					  //
 | 
				
			||||||
@@ -1219,6 +1217,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
					  EXPECT_EQ(stack_size, stack_size2);
 | 
				
			||||||
  ASSERT_EQ(6666U, stack_size);
 | 
					  ASSERT_EQ(6666U, stack_size);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pthread_attr_getstack_18908062_helper(void*) {
 | 
					static void pthread_attr_getstack_18908062_helper(void*) {
 | 
				
			||||||
@@ -1572,26 +1571,3 @@ TEST_F(pthread_DeathTest, pthread_mutex_unlock_null_64) {
 | 
				
			|||||||
  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
 | 
					  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
extern _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx, void* arg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static volatile bool signal_handler_on_altstack_done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void SignalHandlerOnAltStack(int signo, siginfo_t*, void*) {
 | 
					 | 
				
			||||||
  ASSERT_EQ(SIGUSR1, signo);
 | 
					 | 
				
			||||||
  // Check if we have enough stack space for unwinding.
 | 
					 | 
				
			||||||
  int count = 0;
 | 
					 | 
				
			||||||
  _Unwind_Backtrace(FrameCounter, &count);
 | 
					 | 
				
			||||||
  ASSERT_GT(count, 0);
 | 
					 | 
				
			||||||
  // Check if we have enough stack space for logging.
 | 
					 | 
				
			||||||
  std::string s(2048, '*');
 | 
					 | 
				
			||||||
  GTEST_LOG_(INFO) << s;
 | 
					 | 
				
			||||||
  signal_handler_on_altstack_done = true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TEST(pthread, big_enough_signal_stack_for_64bit_arch) {
 | 
					 | 
				
			||||||
  signal_handler_on_altstack_done = false;
 | 
					 | 
				
			||||||
  ScopedSignalHandler handler(SIGUSR1, SignalHandlerOnAltStack, SA_SIGINFO | SA_ONSTACK);
 | 
					 | 
				
			||||||
  kill(getpid(), SIGUSR1);
 | 
					 | 
				
			||||||
  ASSERT_TRUE(signal_handler_on_altstack_done);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@
 | 
				
			|||||||
#define noinline __attribute__((__noinline__))
 | 
					#define noinline __attribute__((__noinline__))
 | 
				
			||||||
#define __unused __attribute__((__unused__))
 | 
					#define __unused __attribute__((__unused__))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) {
 | 
					static _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) {
 | 
				
			||||||
  int* count_ptr = reinterpret_cast<int*>(arg);
 | 
					  int* count_ptr = reinterpret_cast<int*>(arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if SHOW_FRAME_LOCATIONS
 | 
					#if SHOW_FRAME_LOCATIONS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@
 | 
				
			|||||||
#include <gtest/gtest.h>
 | 
					#include <gtest/gtest.h>
 | 
				
			||||||
#include <malloc.h>
 | 
					#include <malloc.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "buffer_tests.h"
 | 
					#include "buffer_tests.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1396,6 +1397,10 @@ TEST(string, strnlen_147048) {
 | 
				
			|||||||
  delete[] heap_src;
 | 
					  delete[] heap_src;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(string, strnlen_74741) {
 | 
				
			||||||
 | 
					  ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(string, mempcpy) {
 | 
					TEST(string, mempcpy) {
 | 
				
			||||||
  char dst[6];
 | 
					  char dst[6];
 | 
				
			||||||
  ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
 | 
					  ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user