Compare commits
	
		
			334 Commits
		
	
	
		
			android-ct
			...
			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
 | 
			
		||||
 | 
			
		||||
    $ mma
 | 
			
		||||
    $ adb remount
 | 
			
		||||
    $ adb sync
 | 
			
		||||
    $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
 | 
			
		||||
    $ adb shell \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
 | 
			
		||||
    # 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 \
 | 
			
		||||
        /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
			
		||||
        /data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static64
 | 
			
		||||
 | 
			
		||||
### Host tests
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ benchmark_cflags := \
 | 
			
		||||
    -Wunused \
 | 
			
		||||
 | 
			
		||||
benchmark_cppflags := \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
benchmarklib_src_files := \
 | 
			
		||||
    Benchmark.cpp \
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdio_ext.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +74,7 @@ static void FopenFgetsFclose(int iters, bool no_locking) {
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    FILE* fp = fopen("/proc/version", "re");
 | 
			
		||||
    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
    fgets(buf, sizeof(buf), fp);
 | 
			
		||||
    if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
 | 
			
		||||
    fclose(fp);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
@@ -21,7 +23,7 @@
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include <base/stringprintf.h>
 | 
			
		||||
 | 
			
		||||
int Round(int n) {
 | 
			
		||||
  int base = 1;
 | 
			
		||||
@@ -72,10 +74,7 @@ std::string PrettyInt(long value, size_t base) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  char* s = NULL;
 | 
			
		||||
  asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
 | 
			
		||||
           count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
  std::string result(s);
 | 
			
		||||
  free(s);
 | 
			
		||||
  return result;
 | 
			
		||||
  return android::base::StringPrintf("%s%" PRId64 "%s",
 | 
			
		||||
                                     negative_number ? "-" : "",
 | 
			
		||||
                                     count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,9 @@ libc_common_src_files := \
 | 
			
		||||
libc_common_src_files += \
 | 
			
		||||
    bionic/__FD_chk.cpp \
 | 
			
		||||
    bionic/__fgets_chk.cpp \
 | 
			
		||||
    bionic/__fread_chk.cpp \
 | 
			
		||||
    bionic/__fwrite_chk.cpp \
 | 
			
		||||
    bionic/__getcwd_chk.cpp \
 | 
			
		||||
    bionic/__memchr_chk.cpp \
 | 
			
		||||
    bionic/__memmove_chk.cpp \
 | 
			
		||||
    bionic/__memrchr_chk.cpp \
 | 
			
		||||
@@ -130,6 +133,7 @@ libc_bionic_ndk_src_files := \
 | 
			
		||||
    bionic/fchmodat.cpp \
 | 
			
		||||
    bionic/ffs.cpp \
 | 
			
		||||
    bionic/fgetxattr.cpp \
 | 
			
		||||
    bionic/flistxattr.cpp \
 | 
			
		||||
    bionic/flockfile.cpp \
 | 
			
		||||
    bionic/fpclassify.cpp \
 | 
			
		||||
    bionic/fsetxattr.cpp \
 | 
			
		||||
@@ -574,11 +578,14 @@ libc_common_cflags := \
 | 
			
		||||
    -D_LIBC=1 \
 | 
			
		||||
    -Wall -Wextra -Wunused \
 | 
			
		||||
 | 
			
		||||
ifneq ($(TARGET_USES_LOGD),false)
 | 
			
		||||
libc_common_cflags += -DTARGET_USES_LOGD
 | 
			
		||||
use_clang := $(USE_CLANG_PLATFORM_BUILD)
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
use_clang := $(USE_CLANG_PLATFORM_BUILD)
 | 
			
		||||
ifeq ($(use_clang),)
 | 
			
		||||
  use_clang := false
 | 
			
		||||
endif
 | 
			
		||||
@@ -616,7 +623,6 @@ libc_common_conlyflags := \
 | 
			
		||||
 | 
			
		||||
# Define some common cppflags
 | 
			
		||||
libc_common_cppflags := \
 | 
			
		||||
    -std=gnu++11
 | 
			
		||||
 | 
			
		||||
# Define some common includes
 | 
			
		||||
# ========================================================
 | 
			
		||||
@@ -657,7 +663,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -698,7 +704,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -744,7 +750,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -777,7 +783,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -812,7 +818,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -853,7 +859,7 @@ LOCAL_MODULE := libc_openbsd_ndk
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -891,7 +897,7 @@ LOCAL_MODULE := libc_openbsd
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -929,7 +935,7 @@ LOCAL_MODULE := libc_gdtoa
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -954,7 +960,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -982,7 +988,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1003,7 +1009,7 @@ LOCAL_CLANG := false
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -1030,7 +1036,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -1054,7 +1060,7 @@ LOCAL_CLANG := true # GCC refuses to hide new/delete
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
# 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
 | 
			
		||||
# libprofile_rt when it is linked into the final binary. Since the final binary
 | 
			
		||||
@@ -1082,7 +1088,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -1104,7 +1110,7 @@ LOCAL_CFLAGS := $(libc_common_cflags) -fno-builtin
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -1130,7 +1136,7 @@ LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) -fvisibility=hidden -O0
 | 
			
		||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
 | 
			
		||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
 | 
			
		||||
@@ -1214,7 +1220,7 @@ LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
 | 
			
		||||
# TODO: split out the asflags.
 | 
			
		||||
LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1252,7 +1258,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1275,7 +1281,7 @@ LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
			
		||||
LOCAL_MODULE := libc_malloc
 | 
			
		||||
LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -1308,7 +1314,7 @@ endif
 | 
			
		||||
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1390,7 +1396,7 @@ LOCAL_CFLAGS_arm += -DCRT_LEGACY_WORKAROUND
 | 
			
		||||
LOCAL_SRC_FILES_arm += \
 | 
			
		||||
    arch-arm/bionic/atexit_legacy.c
 | 
			
		||||
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
@@ -1444,7 +1450,7 @@ LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
 | 
			
		||||
 | 
			
		||||
# Don't install on release build
 | 
			
		||||
LOCAL_MODULE_TAGS := eng debug
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1484,7 +1490,7 @@ LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
 | 
			
		||||
 | 
			
		||||
# Don't install on release build
 | 
			
		||||
LOCAL_MODULE_TAGS := eng debug
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
@@ -1515,7 +1521,7 @@ LOCAL_MODULE:= libstdc++
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
 | 
			
		||||
@@ -1531,7 +1537,7 @@ LOCAL_MODULE:= libstdc++
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
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:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 | 
			
		||||
int     setpgid(pid_t, pid_t)  all
 | 
			
		||||
pid_t   vfork(void)  arm
 | 
			
		||||
int     setregid:setregid32(gid_t, gid_t)  arm,x86
 | 
			
		||||
int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
			
		||||
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
 | 
			
		||||
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     flistxattr(int, char*, size_t) all
 | 
			
		||||
ssize_t     ___flistxattr:flistxattr(int, char*, size_t) all
 | 
			
		||||
int         fremovexattr(int, const char*) all
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
# vdso stuff.
 | 
			
		||||
int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64,x86
 | 
			
		||||
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
 | 
			
		||||
int gettimeofday(timeval*, timezone*)                   arm,mips,mips64,x86
 | 
			
		||||
int __gettimeofday:gettimeofday(timeval*, timezone*)    arm64,x86_64
 | 
			
		||||
int clock_gettime(clockid_t, timespec*)                 arm,mips,mips64
 | 
			
		||||
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
 | 
			
		||||
int gettimeofday(timeval*, timezone*)                   arm,mips,mips64
 | 
			
		||||
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/setjmp.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_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
 | 
			
		||||
    ldrb    r3, [r0]
 | 
			
		||||
    cbz     r3, strcat_r0_scan_done
 | 
			
		||||
    cbz     r3, .L_strcat_r0_scan_done
 | 
			
		||||
    add     r0, #1
 | 
			
		||||
    .endm // m_scan_byte
 | 
			
		||||
 | 
			
		||||
@@ -84,10 +84,10 @@ ENTRY(strcat)
 | 
			
		||||
    // Quick check to see if src is empty.
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    cbnz    r2, strcat_continue
 | 
			
		||||
    cbnz    r2, .L_strcat_continue
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
strcat_continue:
 | 
			
		||||
.L_strcat_continue:
 | 
			
		||||
    // To speed up really small dst strings, unroll checking the first 4 bytes.
 | 
			
		||||
    m_push
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
@@ -96,95 +96,95 @@ strcat_continue:
 | 
			
		||||
    m_scan_byte
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     strcat_mainloop
 | 
			
		||||
    beq     .L_strcat_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcat_align_to_32
 | 
			
		||||
    beq     .L_strcat_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r5, [r0]
 | 
			
		||||
    cbz     r5, strcat_r0_scan_done
 | 
			
		||||
    cbz     r5, .L_strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
 | 
			
		||||
strcat_align_to_32:
 | 
			
		||||
    bcc     strcat_align_to_64
 | 
			
		||||
.L_strcat_align_to_32:
 | 
			
		||||
    bcc     .L_strcat_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r0]
 | 
			
		||||
    cbz     r2, strcat_r0_scan_done
 | 
			
		||||
    cbz     r2, .L_strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
    ldrb    r4, [r0]
 | 
			
		||||
    cbz     r4, strcat_r0_scan_done
 | 
			
		||||
    cbz     r4, .L_strcat_r0_scan_done
 | 
			
		||||
    add     r0, r0, #1
 | 
			
		||||
 | 
			
		||||
strcat_align_to_64:
 | 
			
		||||
.L_strcat_align_to_64:
 | 
			
		||||
    tst     r3, #4
 | 
			
		||||
    beq     strcat_mainloop
 | 
			
		||||
    beq     .L_strcat_mainloop
 | 
			
		||||
    ldr     r3, [r0], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
    bne     .L_strcat_zero_in_second_register
 | 
			
		||||
    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
 | 
			
		||||
    // new code doesn't win until after about 8 bytes.
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
 | 
			
		||||
    m_copy_byte reg=r5, cmd=cbnz, label=.L_strcpy_continue
 | 
			
		||||
 | 
			
		||||
strcpy_finish:
 | 
			
		||||
.L_strcpy_finish:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_continue:
 | 
			
		||||
.L_strcpy_continue:
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     strcpy_check_src_align
 | 
			
		||||
    beq     .L_strcpy_check_src_align
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     strcpy_align_to_32
 | 
			
		||||
    beq     .L_strcpy_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
    cbz     r2, .L_strcpy_complete
 | 
			
		||||
 | 
			
		||||
strcpy_align_to_32:
 | 
			
		||||
    bcc     strcpy_align_to_64
 | 
			
		||||
.L_strcpy_align_to_32:
 | 
			
		||||
    bcc     .L_strcpy_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    cbz     r2, strcpy_complete
 | 
			
		||||
    cbz     r2, .L_strcpy_complete
 | 
			
		||||
    ldrb    r2, [r1], #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
 | 
			
		||||
    beq     strcpy_check_src_align
 | 
			
		||||
    beq     .L_strcpy_check_src_align
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
    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
 | 
			
		||||
    // is also aligned to a double word.
 | 
			
		||||
    ands    r3, r1, #7
 | 
			
		||||
    bne     strcpy_unaligned_copy
 | 
			
		||||
    bne     .L_strcpy_unaligned_copy
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcpy_mainloop:
 | 
			
		||||
.L_strcpy_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
@@ -192,128 +192,128 @@ strcpy_mainloop:
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_mainloop
 | 
			
		||||
    b       .L_strcpy_mainloop
 | 
			
		||||
 | 
			
		||||
strcpy_complete:
 | 
			
		||||
.L_strcpy_complete:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_first_register:
 | 
			
		||||
.L_strcpy_zero_in_first_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcpy_copy1byte
 | 
			
		||||
    bcs     strcpy_copy2bytes
 | 
			
		||||
    bne     .L_strcpy_copy1byte
 | 
			
		||||
    bcs     .L_strcpy_copy2bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcpy_copy3bytes
 | 
			
		||||
    bne     .L_strcpy_copy3bytes
 | 
			
		||||
 | 
			
		||||
strcpy_copy4bytes:
 | 
			
		||||
.L_strcpy_copy4bytes:
 | 
			
		||||
    // Copy 4 bytes to the destiniation.
 | 
			
		||||
    str     r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy1byte:
 | 
			
		||||
.L_strcpy_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy2bytes:
 | 
			
		||||
.L_strcpy_copy2bytes:
 | 
			
		||||
    strh    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy3bytes:
 | 
			
		||||
.L_strcpy_copy3bytes:
 | 
			
		||||
    strh    r2, [r0], #2
 | 
			
		||||
    lsr     r2, #16
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_zero_in_second_register:
 | 
			
		||||
.L_strcpy_zero_in_second_register:
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcpy_copy5bytes
 | 
			
		||||
    bcs     strcpy_copy6bytes
 | 
			
		||||
    bne     .L_strcpy_copy5bytes
 | 
			
		||||
    bcs     .L_strcpy_copy6bytes
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcpy_copy7bytes
 | 
			
		||||
    bne     .L_strcpy_copy7bytes
 | 
			
		||||
 | 
			
		||||
    // Copy 8 bytes to the destination.
 | 
			
		||||
    strd    r2, r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy5bytes:
 | 
			
		||||
.L_strcpy_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy6bytes:
 | 
			
		||||
.L_strcpy_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strh    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_copy7bytes:
 | 
			
		||||
.L_strcpy_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strh    r3, [r0], #2
 | 
			
		||||
    lsr     r3, #16
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unaligned_copy:
 | 
			
		||||
.L_strcpy_unaligned_copy:
 | 
			
		||||
    // Dst is aligned to a double word, while src is at an unknown alignment.
 | 
			
		||||
    // There are 7 different versions of the unaligned copy code
 | 
			
		||||
    // 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
 | 
			
		||||
    // be read without potentially crossing a page boundary.
 | 
			
		||||
    tbb     [pc, r3]
 | 
			
		||||
strcpy_unaligned_branchtable:
 | 
			
		||||
.L_strcpy_unaligned_branchtable:
 | 
			
		||||
    .byte 0
 | 
			
		||||
    .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign7 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign6 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign5 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign4 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign3 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign2 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
    .byte ((.L_strcpy_unalign1 - .L_strcpy_unaligned_branchtable)/2)
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 7 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign7:
 | 
			
		||||
.L_strcpy_unalign7:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r3, [r1]
 | 
			
		||||
    cbz     r3, strcpy_unalign7_copy5bytes
 | 
			
		||||
    cbz     r3, .L_strcpy_unalign7_copy5bytes
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, strcpy_unalign7_copy6bytes
 | 
			
		||||
    cbz     r4, .L_strcpy_unalign7_copy6bytes
 | 
			
		||||
    ldrb    r5, [r1, #2]
 | 
			
		||||
    cbz     r5, strcpy_unalign7_copy7bytes
 | 
			
		||||
    cbz     r5, .L_strcpy_unalign7_copy7bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign7
 | 
			
		||||
    beq     .L_strcpy_unalign_return
 | 
			
		||||
    b       .L_strcpy_unalign7
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy5bytes:
 | 
			
		||||
.L_strcpy_unalign7_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
strcpy_unalign_return:
 | 
			
		||||
.L_strcpy_unalign_return:
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy6bytes:
 | 
			
		||||
.L_strcpy_unalign7_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign7_copy7bytes:
 | 
			
		||||
.L_strcpy_unalign7_copy7bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
@@ -322,41 +322,41 @@ strcpy_unalign7_copy7bytes:
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 6 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign6:
 | 
			
		||||
.L_strcpy_unalign6:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
    cbz     r4, .L_strcpy_unalign_copy5bytes
 | 
			
		||||
    ldrb    r5, [r1, #1]
 | 
			
		||||
    cbz     r5, strcpy_unalign_copy6bytes
 | 
			
		||||
    cbz     r5, .L_strcpy_unalign_copy6bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r3, #0xff0000
 | 
			
		||||
    beq     strcpy_copy7bytes
 | 
			
		||||
    beq     .L_strcpy_copy7bytes
 | 
			
		||||
    lsrs    ip, r3, #24
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    beq     strcpy_unalign_return
 | 
			
		||||
    b       strcpy_unalign6
 | 
			
		||||
    beq     .L_strcpy_unalign_return
 | 
			
		||||
    b       .L_strcpy_unalign6
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 5 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign5:
 | 
			
		||||
.L_strcpy_unalign5:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldrb    r4, [r1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy5bytes
 | 
			
		||||
    cbz     r4, .L_strcpy_unalign_copy5bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
@@ -365,17 +365,17 @@ strcpy_unalign5:
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign5
 | 
			
		||||
    b       .L_strcpy_unalign5
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy5bytes:
 | 
			
		||||
.L_strcpy_unalign_copy5bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy6bytes:
 | 
			
		||||
.L_strcpy_unalign_copy6bytes:
 | 
			
		||||
    str     r2, [r0], #4
 | 
			
		||||
    strb    r4, [r0], #1
 | 
			
		||||
    strb    r5, [r0]
 | 
			
		||||
@@ -383,13 +383,13 @@ strcpy_unalign_copy6bytes:
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 4 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign4:
 | 
			
		||||
.L_strcpy_unalign4:
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
@@ -397,20 +397,20 @@ strcpy_unalign4:
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign4
 | 
			
		||||
    b       .L_strcpy_unalign4
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 3 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign3:
 | 
			
		||||
.L_strcpy_unalign3:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign3_copy1byte
 | 
			
		||||
    cbz     r2, .L_strcpy_unalign3_copy1byte
 | 
			
		||||
    ldrb    r3, [r1, #1]
 | 
			
		||||
    cbz     r3, strcpy_unalign3_copy2bytes
 | 
			
		||||
    cbz     r3, .L_strcpy_unalign3_copy2bytes
 | 
			
		||||
    ldrb    r4, [r1, #2]
 | 
			
		||||
    cbz     r4, strcpy_unalign3_copy3bytes
 | 
			
		||||
    cbz     r4, .L_strcpy_unalign3_copy3bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
@@ -418,26 +418,26 @@ strcpy_unalign3:
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    lsrs    lr, r2, #24
 | 
			
		||||
    beq     strcpy_copy4bytes
 | 
			
		||||
    beq     .L_strcpy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign3
 | 
			
		||||
    b       .L_strcpy_unalign3
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy1byte:
 | 
			
		||||
.L_strcpy_unalign3_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy2bytes:
 | 
			
		||||
.L_strcpy_unalign3_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign3_copy3bytes:
 | 
			
		||||
.L_strcpy_unalign3_copy3bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r3, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
@@ -445,34 +445,34 @@ strcpy_unalign3_copy3bytes:
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 2 bytes before possibly crossing a page.
 | 
			
		||||
strcpy_unalign2:
 | 
			
		||||
.L_strcpy_unalign2:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
    cbz     r2, .L_strcpy_unalign_copy1byte
 | 
			
		||||
    ldrb    r4, [r1, #1]
 | 
			
		||||
    cbz     r4, strcpy_unalign_copy2bytes
 | 
			
		||||
    cbz     r4, .L_strcpy_unalign_copy2bytes
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
 | 
			
		||||
    tst     r2, #0xff0000
 | 
			
		||||
    beq     strcpy_copy3bytes
 | 
			
		||||
    beq     .L_strcpy_copy3bytes
 | 
			
		||||
    lsrs    ip, r2, #24
 | 
			
		||||
    beq     strcpy_copy4bytes
 | 
			
		||||
    beq     .L_strcpy_copy4bytes
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign2
 | 
			
		||||
    b       .L_strcpy_unalign2
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
    // Can read 1 byte before possibly crossing a page.
 | 
			
		||||
strcpy_unalign1:
 | 
			
		||||
.L_strcpy_unalign1:
 | 
			
		||||
    ldrb    r2, [r1]
 | 
			
		||||
    cbz     r2, strcpy_unalign_copy1byte
 | 
			
		||||
    cbz     r2, .L_strcpy_unalign_copy1byte
 | 
			
		||||
 | 
			
		||||
    ldr     r2, [r1], #4
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
@@ -482,27 +482,27 @@ strcpy_unalign1:
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_first_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcpy_zero_in_second_register
 | 
			
		||||
    bne     .L_strcpy_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    strd    r2, r3, [r0], #8
 | 
			
		||||
    b       strcpy_unalign1
 | 
			
		||||
    b       .L_strcpy_unalign1
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy1byte:
 | 
			
		||||
.L_strcpy_unalign_copy1byte:
 | 
			
		||||
    strb    r2, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
strcpy_unalign_copy2bytes:
 | 
			
		||||
.L_strcpy_unalign_copy2bytes:
 | 
			
		||||
    strb    r2, [r0], #1
 | 
			
		||||
    strb    r4, [r0]
 | 
			
		||||
    m_pop
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
strcat_mainloop:
 | 
			
		||||
.L_strcat_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r0], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r0, #64]
 | 
			
		||||
@@ -510,59 +510,59 @@ strcat_mainloop:
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_first_register
 | 
			
		||||
    bne     .L_strcat_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     strcat_zero_in_second_register
 | 
			
		||||
    b       strcat_mainloop
 | 
			
		||||
    bne     .L_strcat_zero_in_second_register
 | 
			
		||||
    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.
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcat_sub8
 | 
			
		||||
    bcs     strcat_sub7
 | 
			
		||||
    bne     .L_strcat_sub8
 | 
			
		||||
    bcs     .L_strcat_sub7
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcat_sub6
 | 
			
		||||
    bne     .L_strcat_sub6
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #5
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub8:
 | 
			
		||||
.L_strcat_sub8:
 | 
			
		||||
    sub     r0, r0, #8
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub7:
 | 
			
		||||
.L_strcat_sub7:
 | 
			
		||||
    sub     r0, r0, #7
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub6:
 | 
			
		||||
.L_strcat_sub6:
 | 
			
		||||
    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.
 | 
			
		||||
    pld     [r1, #0]
 | 
			
		||||
    lsls    lr, ip, #17
 | 
			
		||||
    bne     strcat_sub4
 | 
			
		||||
    bcs     strcat_sub3
 | 
			
		||||
    bne     .L_strcat_sub4
 | 
			
		||||
    bcs     .L_strcat_sub3
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     strcat_sub2
 | 
			
		||||
    bne     .L_strcat_sub2
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub4:
 | 
			
		||||
.L_strcat_sub4:
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub3:
 | 
			
		||||
.L_strcat_sub3:
 | 
			
		||||
    sub     r0, r0, #3
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
 | 
			
		||||
strcat_sub2:
 | 
			
		||||
.L_strcat_sub2:
 | 
			
		||||
    sub     r0, r0, #2
 | 
			
		||||
    b       strcat_r0_scan_done
 | 
			
		||||
    b       .L_strcat_r0_scan_done
 | 
			
		||||
END(strcat)
 | 
			
		||||
 
 | 
			
		||||
@@ -65,38 +65,38 @@ ENTRY(strlen)
 | 
			
		||||
    mov     r1, r0
 | 
			
		||||
 | 
			
		||||
    ands    r3, r0, #7
 | 
			
		||||
    beq     mainloop
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
 | 
			
		||||
    // Align to a double word (64 bits).
 | 
			
		||||
    rsb     r3, r3, #8
 | 
			
		||||
    lsls    ip, r3, #31
 | 
			
		||||
    beq     align_to_32
 | 
			
		||||
    beq     .L_align_to_32
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, update_count_and_return
 | 
			
		||||
    cbz     r2, .L_update_count_and_return
 | 
			
		||||
 | 
			
		||||
align_to_32:
 | 
			
		||||
    bcc     align_to_64
 | 
			
		||||
.L_align_to_32:
 | 
			
		||||
    bcc     .L_align_to_64
 | 
			
		||||
    ands    ip, r3, #2
 | 
			
		||||
    beq     align_to_64
 | 
			
		||||
    beq     .L_align_to_64
 | 
			
		||||
 | 
			
		||||
    ldrb    r2, [r1], #1
 | 
			
		||||
    cbz     r2, update_count_and_return
 | 
			
		||||
    cbz     r2, .L_update_count_and_return
 | 
			
		||||
    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
 | 
			
		||||
    beq     mainloop
 | 
			
		||||
    beq     .L_mainloop
 | 
			
		||||
    ldr     r3, [r1], #4
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
 | 
			
		||||
    .p2align 2
 | 
			
		||||
mainloop:
 | 
			
		||||
.L_mainloop:
 | 
			
		||||
    ldrd    r2, r3, [r1], #8
 | 
			
		||||
 | 
			
		||||
    pld     [r1, #64]
 | 
			
		||||
@@ -104,62 +104,62 @@ mainloop:
 | 
			
		||||
    sub     ip, r2, #0x01010101
 | 
			
		||||
    bic     ip, ip, r2
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_first_register
 | 
			
		||||
    bne     .L_zero_in_first_register
 | 
			
		||||
 | 
			
		||||
    sub     ip, r3, #0x01010101
 | 
			
		||||
    bic     ip, ip, r3
 | 
			
		||||
    ands    ip, ip, #0x80808080
 | 
			
		||||
    bne     zero_in_second_register
 | 
			
		||||
    b       mainloop
 | 
			
		||||
    bne     .L_zero_in_second_register
 | 
			
		||||
    b       .L_mainloop
 | 
			
		||||
 | 
			
		||||
update_count_and_return:
 | 
			
		||||
.L_update_count_and_return:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
zero_in_first_register:
 | 
			
		||||
.L_zero_in_first_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    lsls    r3, ip, #17
 | 
			
		||||
    bne     sub8_and_return
 | 
			
		||||
    bcs     sub7_and_return
 | 
			
		||||
    bne     .L_sub8_and_return
 | 
			
		||||
    bcs     .L_sub7_and_return
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     sub6_and_return
 | 
			
		||||
    bne     .L_sub6_and_return
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #5
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub8_and_return:
 | 
			
		||||
.L_sub8_and_return:
 | 
			
		||||
    sub     r0, r0, #8
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub7_and_return:
 | 
			
		||||
.L_sub7_and_return:
 | 
			
		||||
    sub     r0, r0, #7
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub6_and_return:
 | 
			
		||||
.L_sub6_and_return:
 | 
			
		||||
    sub     r0, r0, #6
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
zero_in_second_register:
 | 
			
		||||
.L_zero_in_second_register:
 | 
			
		||||
    sub     r0, r1, r0
 | 
			
		||||
    lsls    r3, ip, #17
 | 
			
		||||
    bne     sub4_and_return
 | 
			
		||||
    bcs     sub3_and_return
 | 
			
		||||
    bne     .L_sub4_and_return
 | 
			
		||||
    bcs     .L_sub3_and_return
 | 
			
		||||
    lsls    ip, ip, #1
 | 
			
		||||
    bne     sub2_and_return
 | 
			
		||||
    bne     .L_sub2_and_return
 | 
			
		||||
 | 
			
		||||
    sub     r0, r0, #1
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub4_and_return:
 | 
			
		||||
.L_sub4_and_return:
 | 
			
		||||
    sub     r0, r0, #4
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub3_and_return:
 | 
			
		||||
.L_sub3_and_return:
 | 
			
		||||
    sub     r0, r0, #3
 | 
			
		||||
    bx      lr
 | 
			
		||||
 | 
			
		||||
sub2_and_return:
 | 
			
		||||
.L_sub2_and_return:
 | 
			
		||||
    sub     r0, r0, #2
 | 
			
		||||
    bx      lr
 | 
			
		||||
END(strlen)
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         __memcpy_base_aligned
 | 
			
		||||
        beq         MEMCPY_BASE_ALIGNED
 | 
			
		||||
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
        cmp         r2, #224
 | 
			
		||||
@@ -133,8 +133,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(MEMCPY_BASE)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
 | 
			
		||||
 
 | 
			
		||||
@@ -69,12 +69,9 @@ END(bzero)
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        // The neon memset only wins for less than 132.
 | 
			
		||||
        cmp         r2, #132
 | 
			
		||||
        bhi         __memset_large_copy
 | 
			
		||||
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
        bhi         .L_memset_large_copy
 | 
			
		||||
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
        /* 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 */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d0 - d3}, [r3]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* less than 32 left */
 | 
			
		||||
@@ -93,22 +90,20 @@ ENTRY(memset)
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        // 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) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
        vst1.8      {d0}, [r3]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r3]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        strbmi      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
.L_memset_large_copy:
 | 
			
		||||
        /* compute the offset to align the destination
 | 
			
		||||
         * offset = (4-(src&3))&3 = -src & 3
 | 
			
		||||
         */
 | 
			
		||||
@@ -136,8 +131,7 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
        popls       {r0, r4-r7, pc}   /* return */
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
        mov         r12, r1
 | 
			
		||||
@@ -180,9 +174,8 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_large_copy)
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, pc}
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
error_string:
 | 
			
		||||
 
 | 
			
		||||
@@ -221,8 +221,7 @@ ENTRY(memcmp)
 | 
			
		||||
        bne         8b
 | 
			
		||||
 | 
			
		||||
9:      /* restore registers and return */
 | 
			
		||||
        ldmfd       sp!, {r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r4, pc}
 | 
			
		||||
 | 
			
		||||
10:     /* process less than 12 bytes */
 | 
			
		||||
        cmp         r2, #0
 | 
			
		||||
 
 | 
			
		||||
@@ -194,8 +194,7 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
        ldmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r0, r4, pc}
 | 
			
		||||
 | 
			
		||||
        /********************************************************************/
 | 
			
		||||
 | 
			
		||||
@@ -385,8 +384,7 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
        ldmfd       sp!, {r0, r4, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r0, r4, pc}
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
        // Only reached when the __memcpy_chk check fails.
 | 
			
		||||
 
 | 
			
		||||
@@ -82,8 +82,7 @@ ENTRY(memset)
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
        popls       {r0, r4-r7, pc}    /* return */
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
        mov         r12, r1
 | 
			
		||||
@@ -126,8 +125,7 @@ ENTRY(memset)
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, pc}
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
        .data
 | 
			
		||||
 
 | 
			
		||||
@@ -118,6 +118,5 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        strbcs      ip, [r0], #1
 | 
			
		||||
        strbcs      lr, [r0], #1
 | 
			
		||||
 | 
			
		||||
        ldmfd       sp!, {r0, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
        ldmfd       sp!, {r0, pc}
 | 
			
		||||
END(MEMCPY_BASE)
 | 
			
		||||
 
 | 
			
		||||
@@ -69,10 +69,7 @@ END(bzero)
 | 
			
		||||
 | 
			
		||||
/* memset() returns its first argument.  */
 | 
			
		||||
ENTRY(memset)
 | 
			
		||||
        stmfd       sp!, {r0}
 | 
			
		||||
        .cfi_def_cfa_offset 4
 | 
			
		||||
        .cfi_rel_offset r0, 0
 | 
			
		||||
 | 
			
		||||
        mov         r3, r0
 | 
			
		||||
        vdup.8      q0, r1
 | 
			
		||||
 | 
			
		||||
        /* 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 */
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        vst1.8      {d0 - d3}, [r0]!
 | 
			
		||||
        vst1.8      {d0 - d3}, [r3]!
 | 
			
		||||
        bhs         1b
 | 
			
		||||
 | 
			
		||||
2:      /* less than 32 left */
 | 
			
		||||
@@ -91,18 +88,17 @@ ENTRY(memset)
 | 
			
		||||
        beq         3f
 | 
			
		||||
 | 
			
		||||
        // 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) */
 | 
			
		||||
        movs        ip, r2, lsl #29
 | 
			
		||||
        bcc         1f
 | 
			
		||||
        vst1.8      {d0}, [r0]!
 | 
			
		||||
        vst1.8      {d0}, [r3]!
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
        vst1.32     {d0[0]}, [r3]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        strbmi      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        strbcs      r1, [r3], #1
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_flistxattr
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,4 +11,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    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>
 | 
			
		||||
 | 
			
		||||
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     x1, xzr
 | 
			
		||||
    mov     x2, xzr
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    mov     x8, __NR_flistxattr
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,4 +11,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(flistxattr)
 | 
			
		||||
END(___flistxattr)
 | 
			
		||||
.hidden ___flistxattr
 | 
			
		||||
@@ -37,6 +37,14 @@ ENTRY(vfork)
 | 
			
		||||
	.set	noreorder
 | 
			
		||||
	.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	a1, 0
 | 
			
		||||
	li	a2, 0
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_flistxattr
 | 
			
		||||
@@ -16,4 +16,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(flistxattr)
 | 
			
		||||
END(___flistxattr)
 | 
			
		||||
.hidden ___flistxattr
 | 
			
		||||
@@ -46,6 +46,12 @@ LEAF(vfork,FRAMESZ)
 | 
			
		||||
	PTR_SUBU sp, FRAMESZ
 | 
			
		||||
#endif
 | 
			
		||||
	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)
 | 
			
		||||
	move	a1, $0
 | 
			
		||||
	move	a2, $0
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_flistxattr
 | 
			
		||||
@@ -22,4 +22,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(flistxattr)
 | 
			
		||||
END(___flistxattr)
 | 
			
		||||
.hidden ___flistxattr
 | 
			
		||||
@@ -34,6 +34,12 @@ ENTRY(vfork)
 | 
			
		||||
  popl    %ecx  // Grab the return address.
 | 
			
		||||
  .cfi_adjust_cfa_offset 4
 | 
			
		||||
  .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
 | 
			
		||||
  int     $0x80
 | 
			
		||||
  cmpl    $-MAX_ERRNO, %eax
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -28,4 +28,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(flistxattr)
 | 
			
		||||
END(___flistxattr)
 | 
			
		||||
.hidden ___flistxattr
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(clock_gettime)
 | 
			
		||||
ENTRY(__clock_gettime)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -23,4 +23,4 @@ ENTRY(clock_gettime)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(clock_gettime)
 | 
			
		||||
END(__clock_gettime)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(gettimeofday)
 | 
			
		||||
ENTRY(__gettimeofday)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -23,4 +23,4 @@ ENTRY(gettimeofday)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(gettimeofday)
 | 
			
		||||
END(__gettimeofday)
 | 
			
		||||
@@ -32,6 +32,12 @@
 | 
			
		||||
 | 
			
		||||
ENTRY(vfork)
 | 
			
		||||
  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
 | 
			
		||||
  syscall
 | 
			
		||||
  pushq   %rdi  // Restore the return address.
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(flistxattr)
 | 
			
		||||
ENTRY(___flistxattr)
 | 
			
		||||
    movl    $__NR_flistxattr, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
    cmpq    $-MAX_ERRNO, %rax
 | 
			
		||||
@@ -12,4 +12,5 @@ ENTRY(flistxattr)
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#undef _FORTIFY_SOURCE
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <malloc.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -64,18 +64,15 @@ char** environ;
 | 
			
		||||
// Declared in "private/bionic_ssp.h".
 | 
			
		||||
uintptr_t __stack_chk_guard = 0;
 | 
			
		||||
 | 
			
		||||
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
 | 
			
		||||
 * in memory. Beware: all writes to libc 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
 | 
			
		||||
 * 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
 | 
			
		||||
 * picked up by the libc constructor.
 | 
			
		||||
 */
 | 
			
		||||
void __libc_init_tls(KernelArgumentBlock& args) {
 | 
			
		||||
// Setup for the main thread. For dynamic executables, this is called by the
 | 
			
		||||
// linker _before_ libc is mapped in memory. This means that all writes to
 | 
			
		||||
// 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
 | 
			
		||||
// has to be done later from libc itself (see __libc_init_common).
 | 
			
		||||
void __libc_init_main_thread(KernelArgumentBlock& args) {
 | 
			
		||||
  __libc_auxv = args.auxv;
 | 
			
		||||
 | 
			
		||||
  static pthread_internal_t main_thread;
 | 
			
		||||
@@ -99,6 +96,9 @@ void __libc_init_tls(KernelArgumentBlock& args) {
 | 
			
		||||
  __init_thread(&main_thread);
 | 
			
		||||
  __init_tls(&main_thread);
 | 
			
		||||
  __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;
 | 
			
		||||
 | 
			
		||||
  __init_alternate_signal_stack(&main_thread);
 | 
			
		||||
 
 | 
			
		||||
@@ -49,16 +49,10 @@
 | 
			
		||||
#include "libc_init_common.h"
 | 
			
		||||
#include "pthread_internal.h"
 | 
			
		||||
 | 
			
		||||
#include "private/bionic_page.h"
 | 
			
		||||
#include "private/bionic_tls.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 *);
 | 
			
		||||
 | 
			
		||||
static void call_array(void(**list)()) {
 | 
			
		||||
@@ -90,7 +84,7 @@ __noreturn void __libc_init(void* raw_args,
 | 
			
		||||
                            int (*slingshot)(int, char**, char**),
 | 
			
		||||
                            structors_array_t const * const structors) {
 | 
			
		||||
  KernelArgumentBlock args(raw_args);
 | 
			
		||||
  __libc_init_tls(args);
 | 
			
		||||
  __libc_init_main_thread(args);
 | 
			
		||||
  __libc_init_AT_SECURE(args);
 | 
			
		||||
  __libc_init_common(args);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -448,7 +448,6 @@ static int __libc_write_stderr(const char* tag, const char* msg) {
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_USES_LOGD
 | 
			
		||||
static int __libc_open_log_socket() {
 | 
			
		||||
  // 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
 | 
			
		||||
@@ -486,10 +485,8 @@ struct log_time { // Wire format
 | 
			
		||||
  uint32_t tv_sec;
 | 
			
		||||
  uint32_t tv_nsec;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
  if (main_log_fd == -1) {
 | 
			
		||||
    // 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[5].iov_base = const_cast<char*>(msg);
 | 
			
		||||
  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])));
 | 
			
		||||
  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) {
 | 
			
		||||
#ifdef TARGET_USES_LOGD
 | 
			
		||||
  iovec vec[6];
 | 
			
		||||
  char log_id = LOG_ID_EVENTS;
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    return -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
static ThreadLocalBuffer<char, MAXPATHLEN> g_basename_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* endp = NULL;
 | 
			
		||||
  int len;
 | 
			
		||||
@@ -91,7 +91,12 @@ __LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_s
 | 
			
		||||
  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;
 | 
			
		||||
  int len;
 | 
			
		||||
  int result;
 | 
			
		||||
@@ -150,14 +155,19 @@ __LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_si
 | 
			
		||||
  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* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* dirname(const char* path) {
 | 
			
		||||
  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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -612,7 +612,7 @@ extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_di
 | 
			
		||||
        error_log("Unable to open /dev/qemu_trace");
 | 
			
		||||
        return false;
 | 
			
		||||
    } 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);
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
    // 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, 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);
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, space, stack_guard_size, "thread stack guard page");
 | 
			
		||||
 | 
			
		||||
  return space;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "private/android_filesystem_config.h"
 | 
			
		||||
#include "private/bionic_macros.h"
 | 
			
		||||
#include "private/ErrnoRestorer.h"
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
#include "private/ThreadLocalBuffer.h"
 | 
			
		||||
@@ -66,11 +67,15 @@ struct passwd_state_t {
 | 
			
		||||
static ThreadLocalBuffer<group_state_t> g_group_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() {
 | 
			
		||||
  group_state_t* result = g_group_tls_buffer.get();
 | 
			
		||||
  if (result != nullptr) {
 | 
			
		||||
    memset(result, 0, sizeof(group_state_t));
 | 
			
		||||
    result->group_.gr_mem = result->group_members_;
 | 
			
		||||
    init_group_state(result);
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
@@ -397,17 +402,28 @@ char* getlogin() { // NOLINT: implementing bad function.
 | 
			
		||||
  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_state_t* state = __group_state();
 | 
			
		||||
  if (state == NULL) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return getgrgid_internal(gid, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  group* gr = android_id_to_group(state, gid);
 | 
			
		||||
  if (gr != NULL) {
 | 
			
		||||
    return gr;
 | 
			
		||||
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(gid, state);
 | 
			
		||||
  return app_id_to_group(app_id_from_name(name, true), state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return getgrnam_internal(name, state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  if (android_name_to_group(state, name) != 0) {
 | 
			
		||||
    return &state->group_;
 | 
			
		||||
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;
 | 
			
		||||
  }
 | 
			
		||||
  return app_id_to_group(app_id_from_name(name, true), state);
 | 
			
		||||
  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.
 | 
			
		||||
 
 | 
			
		||||
@@ -97,8 +97,11 @@ long sysconf(int name) {
 | 
			
		||||
    case _SC_ATEXIT_MAX:        return LONG_MAX;    // Unlimited.
 | 
			
		||||
    case _SC_IOV_MAX:           return UIO_MAXIOV;
 | 
			
		||||
 | 
			
		||||
    case _SC_PAGESIZE:          // Fall through, PAGESIZE and PAGE_SIZE always hold the same value.
 | 
			
		||||
    case _SC_PAGE_SIZE:         return PAGE_SIZE;
 | 
			
		||||
    // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
 | 
			
		||||
    case _SC_PAGESIZE:
 | 
			
		||||
    case _SC_PAGE_SIZE:
 | 
			
		||||
      return static_cast<long>(getauxval(AT_PAGESZ));
 | 
			
		||||
 | 
			
		||||
    case _SC_XOPEN_UNIX:        return _XOPEN_UNIX;
 | 
			
		||||
    case _SC_AIO_LISTIO_MAX:    return _POSIX_AIO_LISTIO_MAX;     // Minimum requirement.
 | 
			
		||||
    case _SC_AIO_MAX:           return _POSIX_AIO_MAX;            // Minimum requirement.
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,9 @@
 | 
			
		||||
#include <sys/sysinfo.h>
 | 
			
		||||
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.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) {
 | 
			
		||||
    long total;
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,19 +19,24 @@
 | 
			
		||||
#include <sys/auxv.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
// x86 has a vdso, but there's nothing useful to us in it.
 | 
			
		||||
#if defined(__aarch64__) || defined(__x86_64__)
 | 
			
		||||
#if defined(__aarch64__) || defined(__x86_64__) || defined (__i386__)
 | 
			
		||||
 | 
			
		||||
#if defined(__aarch64__)
 | 
			
		||||
#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
 | 
			
		||||
#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_GETTIMEOFDAY_SYMBOL  "__vdso_gettimeofday"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include "private/bionic_prctl.h"
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
 | 
			
		||||
extern "C" int __clock_gettime(int, timespec*);
 | 
			
		||||
extern "C" int __gettimeofday(timeval*, struct timezone*);
 | 
			
		||||
 | 
			
		||||
@@ -46,28 +51,31 @@ enum {
 | 
			
		||||
  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_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
 | 
			
		||||
};
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
int clock_gettime(int clock_id, timespec* tp) {
 | 
			
		||||
  static int (*vdso_clock_gettime)(int, timespec*) =
 | 
			
		||||
      reinterpret_cast<int (*)(int, timespec*)>(vdso_entries[VDSO_CLOCK_GETTIME].fn);
 | 
			
		||||
  int (*vdso_clock_gettime)(int, timespec*) =
 | 
			
		||||
      reinterpret_cast<int (*)(int, timespec*)>(vdso.entries[VDSO_CLOCK_GETTIME].fn);
 | 
			
		||||
  return vdso_clock_gettime(clock_id, tp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gettimeofday(timeval* tv, struct timezone* tz) {
 | 
			
		||||
  static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
 | 
			
		||||
      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso_entries[VDSO_GETTIMEOFDAY].fn);
 | 
			
		||||
  int (*vdso_gettimeofday)(timeval*, struct timezone*) =
 | 
			
		||||
      reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso.entries[VDSO_GETTIMEOFDAY].fn);
 | 
			
		||||
  return vdso_gettimeofday(tv, tz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __libc_init_vdso() {
 | 
			
		||||
static void __libc_init_vdso_entries() {
 | 
			
		||||
  // Do we have a vdso?
 | 
			
		||||
  uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
 | 
			
		||||
  ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
 | 
			
		||||
  if (vdso_ehdr == NULL) {
 | 
			
		||||
  if (vdso_ehdr == nullptr) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -85,7 +93,7 @@ void __libc_init_vdso() {
 | 
			
		||||
 | 
			
		||||
  // Where's the dynamic table?
 | 
			
		||||
  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);
 | 
			
		||||
  for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (vdso_addr == 0 || vdso_dyn == NULL) {
 | 
			
		||||
  if (vdso_addr == 0 || vdso_dyn == nullptr) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Where are the string and symbol tables?
 | 
			
		||||
  const char* strtab = NULL;
 | 
			
		||||
  ElfW(Sym)* symtab = NULL;
 | 
			
		||||
  const char* strtab = nullptr;
 | 
			
		||||
  ElfW(Sym)* symtab = nullptr;
 | 
			
		||||
  for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
 | 
			
		||||
    if (d->d_tag == DT_STRTAB) {
 | 
			
		||||
      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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (strtab == NULL || symtab == NULL) {
 | 
			
		||||
  if (strtab == nullptr || symtab == nullptr) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Are there any symbols we want?
 | 
			
		||||
  for (size_t i = 0; i < symbol_count; ++i) {
 | 
			
		||||
    for (size_t j = 0; j < VDSO_END; ++j) {
 | 
			
		||||
      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);
 | 
			
		||||
      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);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
void __libc_init_vdso() {
 | 
			
		||||
 
 | 
			
		||||
@@ -81,17 +81,6 @@
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
/* 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_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)
 | 
			
		||||
 | 
			
		||||
__BIONIC_FORTIFY_INLINE
 | 
			
		||||
@@ -428,6 +438,58 @@ int sprintf(char *dest, const char *format, ...)
 | 
			
		||||
}
 | 
			
		||||
#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__)
 | 
			
		||||
 | 
			
		||||
__BIONIC_FORTIFY_INLINE
 | 
			
		||||
 
 | 
			
		||||
@@ -520,6 +520,11 @@
 | 
			
		||||
#include <android/api-level.h>
 | 
			
		||||
 | 
			
		||||
/* glibc compatibility. */
 | 
			
		||||
#if __POSIX_VISIBLE >= 200809
 | 
			
		||||
#define __USE_ISOC99 1
 | 
			
		||||
#define __USE_XOPEN2K 1
 | 
			
		||||
#define __USE_XOPEN2K8 1
 | 
			
		||||
#endif
 | 
			
		||||
#if __LP64__
 | 
			
		||||
#define __WORDSIZE 64
 | 
			
		||||
#else
 | 
			
		||||
@@ -573,4 +578,19 @@
 | 
			
		||||
#define _BIONIC_NOT_BEFORE_21(x)
 | 
			
		||||
#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_ */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
 | 
			
		||||
#if defined(__i386__)
 | 
			
		||||
typedef struct user_fpxregs_struct elf_fpxregset_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef elf_gregset_t prgregset_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
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _SYS_TIME_H_
 | 
			
		||||
#define _SYS_TIME_H_
 | 
			
		||||
 | 
			
		||||
@@ -32,6 +33,9 @@
 | 
			
		||||
#include <sys/types.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
 | 
			
		||||
 | 
			
		||||
extern int gettimeofday(struct timeval *, struct timezone *);
 | 
			
		||||
@@ -73,6 +77,15 @@ extern int utimes(const char *, const struct timeval *);
 | 
			
		||||
        }                                             \
 | 
			
		||||
    } 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
 | 
			
		||||
 | 
			
		||||
#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_
 | 
			
		||||
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
#include <limits.h> /* For PAGE_SIZE. */
 | 
			
		||||
#include <stddef.h> /* For size_t. */
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define PAGE_SIZE 4096
 | 
			
		||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
 | 
			
		||||
 | 
			
		||||
#if __i386__
 | 
			
		||||
 | 
			
		||||
struct user_fpregs_struct {
 | 
			
		||||
@@ -47,7 +49,7 @@ struct user_fpregs_struct {
 | 
			
		||||
  long fos;
 | 
			
		||||
  long st_space[20];
 | 
			
		||||
};
 | 
			
		||||
struct user_fxsr_struct {
 | 
			
		||||
struct user_fpxregs_struct {
 | 
			
		||||
  unsigned short cwd;
 | 
			
		||||
  unsigned short swd;
 | 
			
		||||
  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>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
#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_32__ 1
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -224,6 +224,10 @@ extern int   tcsetpgrp(int fd, pid_t _pid);
 | 
			
		||||
    } while (_rc == -1 && errno == EINTR); \
 | 
			
		||||
    _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);
 | 
			
		||||
__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
 | 
			
		||||
__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)
 | 
			
		||||
 | 
			
		||||
__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)
 | 
			
		||||
#define __PREAD_PREFIX(x) __pread64_ ## x
 | 
			
		||||
#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_ACTIVE_CU_COUNT 0x20
 | 
			
		||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
			
		||||
#define RADEON_INFO_VA_UNMAP_WORKING 0x25
 | 
			
		||||
struct drm_radeon_info {
 | 
			
		||||
  uint32_t request;
 | 
			
		||||
  uint32_t pad;
 | 
			
		||||
  uint64_t value;
 | 
			
		||||
/* 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_1D 13
 | 
			
		||||
#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
 | 
			
		||||
/* 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_16BPP 15
 | 
			
		||||
#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 */
 | 
			
		||||
#define SI_TILE_MODE_COLOR_2D_64BPP 17
 | 
			
		||||
#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11
 | 
			
		||||
#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12
 | 
			
		||||
#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 */
 | 
			
		||||
#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
 | 
			
		||||
#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_8AA 2
 | 
			
		||||
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
 | 
			
		||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 | 
			
		||||
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
 | 
			
		||||
#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))
 | 
			
		||||
 
 | 
			
		||||
@@ -1332,6 +1332,15 @@ LIBC {
 | 
			
		||||
    *;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIBC_N {
 | 
			
		||||
  global:
 | 
			
		||||
    __fread_chk;
 | 
			
		||||
    __fwrite_chk;
 | 
			
		||||
    __getcwd_chk;
 | 
			
		||||
    getgrgid_r;
 | 
			
		||||
    getgrnam_r;
 | 
			
		||||
} LIBC;
 | 
			
		||||
 | 
			
		||||
LIBC_PRIVATE {
 | 
			
		||||
  global:
 | 
			
		||||
    ___Unwind_Backtrace; # arm
 | 
			
		||||
@@ -1453,4 +1462,4 @@ LIBC_PRIVATE {
 | 
			
		||||
    SHA1Init; # arm x86 mips
 | 
			
		||||
    SHA1Transform; # 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_DLERROR,
 | 
			
		||||
 | 
			
		||||
  // Fast storage for Thread::Current() in ART.
 | 
			
		||||
  TLS_SLOT_ART_THREAD_SELF,
 | 
			
		||||
 | 
			
		||||
  BIONIC_TLS_SLOTS // Must come last!
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -114,7 +117,7 @@ __END_DECLS
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
class KernelArgumentBlock;
 | 
			
		||||
extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
 | 
			
		||||
extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@
 | 
			
		||||
#include "atexit.h"
 | 
			
		||||
#include "private/thread_private.h"
 | 
			
		||||
 | 
			
		||||
/* BEGIN android-changed */
 | 
			
		||||
#include "private/bionic_prctl.h"
 | 
			
		||||
/* END android-changed */
 | 
			
		||||
 | 
			
		||||
struct atexit {
 | 
			
		||||
	struct atexit *next;		/* next in list */
 | 
			
		||||
	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);
 | 
			
		||||
		if (p == MAP_FAILED)
 | 
			
		||||
			goto unlock;
 | 
			
		||||
/* BEGIN android-changed */
 | 
			
		||||
		prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
 | 
			
		||||
		    "atexit handlers");
 | 
			
		||||
/* END android-changed */
 | 
			
		||||
		if (__atexit == NULL) {
 | 
			
		||||
			memset(&p->fns[0], 0, sizeof(p->fns[0]));
 | 
			
		||||
			p->ind = 1;
 | 
			
		||||
@@ -204,6 +212,10 @@ __atexit_register_cleanup(void (*func)(void))
 | 
			
		||||
		    MAP_ANON | MAP_PRIVATE, -1, 0);
 | 
			
		||||
		if (p == MAP_FAILED)
 | 
			
		||||
			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->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
 | 
			
		||||
		    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)
 | 
			
		||||
 | 
			
		||||
def GetSymbols(library, functions_or_variables):
 | 
			
		||||
  global api
 | 
			
		||||
  global arch
 | 
			
		||||
 | 
			
		||||
  api = '9'
 | 
			
		||||
  if library == 'libm' and arch == 'arm':
 | 
			
		||||
    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)
 | 
			
		||||
  symbols = set()
 | 
			
		||||
  for line in open(path, 'r'):
 | 
			
		||||
@@ -26,7 +38,11 @@ def GetSymbols(library, functions_or_variables):
 | 
			
		||||
def CheckSymbols(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:
 | 
			
		||||
  #   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+)')
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
    if m:
 | 
			
		||||
      symbol = string.split(m.group(2), '@')[0]
 | 
			
		||||
@@ -55,6 +71,12 @@ def CheckSymbols(library, functions_or_variables):
 | 
			
		||||
    for miss in sorted(missing):
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
CheckSymbols("libc", "functions")
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,8 @@
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
 | 
			
		||||
#include "private/bionic_prctl.h"
 | 
			
		||||
 | 
			
		||||
// Android gets these from "thread_private.h".
 | 
			
		||||
#include "thread_private.h"
 | 
			
		||||
//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)
 | 
			
		||||
		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,
 | 
			
		||||
	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
 | 
			
		||||
		munmap(*rsxp, sizeof(**rsxp));
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp),
 | 
			
		||||
	    "arc4random _rsx structure");
 | 
			
		||||
 | 
			
		||||
	_ARC4_ATFORK(_rs_forkhandler);
 | 
			
		||||
	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.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
@@ -88,7 +88,6 @@
 | 
			
		||||
#include <fnmatch.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
#include "charclass.h"
 | 
			
		||||
 | 
			
		||||
@@ -193,6 +192,8 @@ static int fnmatch_ch(const char **pattern, const char **string, int flags)
 | 
			
		||||
                result = 0;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (!**pattern)
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
leadingclosebrace:
 | 
			
		||||
            /* 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;
 | 
			
		||||
    int matchlen = 0;
 | 
			
		||||
 | 
			
		||||
    if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
 | 
			
		||||
        strnlen(string, PATH_MAX) == PATH_MAX)
 | 
			
		||||
            return (FNM_NOMATCH);
 | 
			
		||||
 | 
			
		||||
    if (*pattern == '*')
 | 
			
		||||
        goto firstsegment;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -36,7 +36,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
 | 
			
		||||
# 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_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,9 @@ LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
 | 
			
		||||
bionic_coverage := false
 | 
			
		||||
 | 
			
		||||
ifneq (,$(filter $(TARGET_ARCH),x86 x86_64))
 | 
			
		||||
# Clang has wrong long double sizes for x86.
 | 
			
		||||
# Clang/llvm has incompatible long double (fp128) for x86_64.
 | 
			
		||||
# https://llvm.org/bugs/show_bug.cgi?id=23897
 | 
			
		||||
ifeq ($(TARGET_ARCH),x86_64)
 | 
			
		||||
libm_clang := false
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
@@ -501,11 +502,8 @@ LOCAL_CFLAGS += \
 | 
			
		||||
    -fno-builtin-rintf \
 | 
			
		||||
    -fno-builtin-rintl \
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLY_FLAGS := \
 | 
			
		||||
    -std=c99 \
 | 
			
		||||
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
@@ -527,7 +525,7 @@ LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 | 
			
		||||
LOCAL_WHOLE_STATIC_LIBRARIES := libm
 | 
			
		||||
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
 | 
			
		||||
LOCAL_CXX_STL := none
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,6 @@ LOCAL_CONLYFLAGS += \
 | 
			
		||||
    -std=gnu99 \
 | 
			
		||||
 | 
			
		||||
LOCAL_CPPFLAGS += \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
    -Wold-style-cast \
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_IS_64_BIT),true)
 | 
			
		||||
@@ -60,7 +59,7 @@ LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@@ -83,4 +82,26 @@ LOCAL_POST_LINK_CMD = $(hide) $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJCOPY) \
 | 
			
		||||
 | 
			
		||||
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))
 | 
			
		||||
 
 | 
			
		||||
@@ -135,9 +135,6 @@ static void log_signal_summary(int signum, const siginfo_t* info) {
 | 
			
		||||
      signal_name = "SIGILL";
 | 
			
		||||
      has_address = true;
 | 
			
		||||
      break;
 | 
			
		||||
    case SIGPIPE:
 | 
			
		||||
      signal_name = "SIGPIPE";
 | 
			
		||||
      break;
 | 
			
		||||
    case SIGSEGV:
 | 
			
		||||
      signal_name = "SIGSEGV";
 | 
			
		||||
      has_address = true;
 | 
			
		||||
@@ -273,7 +270,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
 | 
			
		||||
  signal(signal_number, SIG_DFL);
 | 
			
		||||
 | 
			
		||||
  // 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 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
 | 
			
		||||
@@ -281,7 +278,6 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
 | 
			
		||||
  switch (signal_number) {
 | 
			
		||||
    case SIGABRT:
 | 
			
		||||
    case SIGFPE:
 | 
			
		||||
    case SIGPIPE:
 | 
			
		||||
#if defined(SIGSTKFLT)
 | 
			
		||||
    case SIGSTKFLT:
 | 
			
		||||
#endif
 | 
			
		||||
@@ -307,7 +303,6 @@ __LIBC_HIDDEN__ void debuggerd_init() {
 | 
			
		||||
  sigaction(SIGBUS, &action, nullptr);
 | 
			
		||||
  sigaction(SIGFPE, &action, nullptr);
 | 
			
		||||
  sigaction(SIGILL, &action, nullptr);
 | 
			
		||||
  sigaction(SIGPIPE, &action, nullptr);
 | 
			
		||||
  sigaction(SIGSEGV, &action, nullptr);
 | 
			
		||||
#if defined(SIGSTKFLT)
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
  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) {
 | 
			
		||||
    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
 | 
			
		||||
    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) {
 | 
			
		||||
  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) {
 | 
			
		||||
  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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,8 @@
 | 
			
		||||
#include "linker_phdr.h"
 | 
			
		||||
#include "linker_relocs.h"
 | 
			
		||||
#include "linker_reloc_iterators.h"
 | 
			
		||||
 | 
			
		||||
#include "base/strings.h"
 | 
			
		||||
#include "ziparchive/zip_archive.h"
 | 
			
		||||
 | 
			
		||||
extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
 | 
			
		||||
@@ -85,9 +87,26 @@ static const char* const kDefaultLdPaths[] = {
 | 
			
		||||
  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) 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_preload_names;
 | 
			
		||||
 | 
			
		||||
@@ -97,6 +116,14 @@ __LIBC_HIDDEN__ int g_ld_debug_verbosity;
 | 
			
		||||
 | 
			
		||||
__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
 | 
			
		||||
struct linker_stats_t {
 | 
			
		||||
  int count[kRelocMax];
 | 
			
		||||
@@ -283,25 +310,9 @@ static void soinfo_free(soinfo* si) {
 | 
			
		||||
 | 
			
		||||
static void parse_path(const char* path, const char* delimiters,
 | 
			
		||||
                       std::vector<std::string>* paths) {
 | 
			
		||||
  if (path == nullptr) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  paths->clear();
 | 
			
		||||
 | 
			
		||||
  for (const char *p = path; ; ++p) {
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
  if (path != nullptr) {
 | 
			
		||||
    *paths = android::base::Split(path, delimiters);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -309,6 +320,38 @@ static void parse_LD_LIBRARY_PATH(const char* path) {
 | 
			
		||||
  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) {
 | 
			
		||||
  // We have historically supported ':' as well as ' ' in LD_PRELOAD.
 | 
			
		||||
  parse_path(path, " :", &g_ld_preload_names);
 | 
			
		||||
@@ -1086,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.
 | 
			
		||||
  // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
 | 
			
		||||
  // "bar/bas/x.so" within "foo.zip".
 | 
			
		||||
  const char* separator = strstr(path, "!/");
 | 
			
		||||
  const char* separator = strstr(path, kZipFileSeparator);
 | 
			
		||||
  if (separator == nullptr) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
@@ -1119,7 +1162,7 @@ static int open_library_in_zipfile(const char* const path,
 | 
			
		||||
 | 
			
		||||
  ZipEntry entry;
 | 
			
		||||
 | 
			
		||||
  if (FindEntry(handle, ZipEntryName(file_path), &entry) != 0) {
 | 
			
		||||
  if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
 | 
			
		||||
    // Entry was not found.
 | 
			
		||||
    close(fd);
 | 
			
		||||
    return -1;
 | 
			
		||||
@@ -1146,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) {
 | 
			
		||||
  for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) {
 | 
			
		||||
  for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1162,8 +1205,9 @@ static int open_library_on_default_path(const char* name, off64_t* file_offset)
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int open_library_on_ld_library_path(const char* name, off64_t* file_offset) {
 | 
			
		||||
  for (const auto& path_str : g_ld_library_paths) {
 | 
			
		||||
static int open_library_on_paths(const char* name, off64_t* file_offset,
 | 
			
		||||
                                 const std::vector<std::string>& paths) {
 | 
			
		||||
  for (const auto& path_str : paths) {
 | 
			
		||||
    char buf[512];
 | 
			
		||||
    const char* const path = path_str.c_str();
 | 
			
		||||
    if (!format_path(buf, sizeof(buf), path, name)) {
 | 
			
		||||
@@ -1171,7 +1215,7 @@ static int open_library_on_ld_library_path(const char* name, off64_t* file_offse
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int fd = -1;
 | 
			
		||||
    if (strchr(buf, '!') != nullptr) {
 | 
			
		||||
    if (strstr(buf, kZipFileSeparator) != nullptr) {
 | 
			
		||||
      fd = open_library_in_zipfile(buf, file_offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1190,12 +1234,12 @@ static int open_library_on_ld_library_path(const char* name, off64_t* file_offse
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  // 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 (strstr(name, kZipFileSeparator) != nullptr) {
 | 
			
		||||
      int fd = open_library_in_zipfile(name, file_offset);
 | 
			
		||||
      if (fd != -1) {
 | 
			
		||||
        return fd;
 | 
			
		||||
@@ -1210,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.
 | 
			
		||||
  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) {
 | 
			
		||||
    fd = open_library_on_default_path(name, file_offset);
 | 
			
		||||
  }
 | 
			
		||||
@@ -1320,8 +1367,8 @@ static soinfo* load_library(int fd, off64_t file_offset,
 | 
			
		||||
  return si;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static soinfo* load_library(LoadTaskList& load_tasks,
 | 
			
		||||
                            const char* name, int rtld_flags,
 | 
			
		||||
static soinfo* load_library(LoadTaskList& load_tasks, const char* name,
 | 
			
		||||
                            soinfo* needed_by, int rtld_flags,
 | 
			
		||||
                            const android_dlextinfo* extinfo) {
 | 
			
		||||
  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
			
		||||
    off64_t file_offset = 0;
 | 
			
		||||
@@ -1333,7 +1380,7 @@ static soinfo* load_library(LoadTaskList& load_tasks,
 | 
			
		||||
 | 
			
		||||
  // Open the file.
 | 
			
		||||
  off64_t file_offset;
 | 
			
		||||
  int fd = open_library(name, &file_offset);
 | 
			
		||||
  int fd = open_library(name, needed_by, &file_offset);
 | 
			
		||||
  if (fd == -1) {
 | 
			
		||||
    DL_ERR("library \"%s\" not found", name);
 | 
			
		||||
    return nullptr;
 | 
			
		||||
@@ -1381,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,
 | 
			
		||||
                                     int rtld_flags, const android_dlextinfo* extinfo) {
 | 
			
		||||
                                     soinfo* needed_by, int rtld_flags,
 | 
			
		||||
                                     const android_dlextinfo* extinfo) {
 | 
			
		||||
  soinfo* candidate;
 | 
			
		||||
 | 
			
		||||
  if (find_loaded_library_by_soname(name, &candidate)) {
 | 
			
		||||
@@ -1393,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...]",
 | 
			
		||||
      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
 | 
			
		||||
  // is a candidate loaded under the same soname but different
 | 
			
		||||
@@ -1425,9 +1473,17 @@ static soinfo::soinfo_list_t make_global_group() {
 | 
			
		||||
  return global_group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
// add_as_children - add first-level loaded libraries (i.e. library_names[], but
 | 
			
		||||
// not their transitive dependencies) as children of the start_with library.
 | 
			
		||||
// 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.
 | 
			
		||||
  LoadTaskList load_tasks;
 | 
			
		||||
  for (size_t i = 0; i < library_names_count; ++i) {
 | 
			
		||||
@@ -1468,14 +1524,14 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
			
		||||
  // Step 1: load and pre-link all DT_NEEDED libraries in breadth first order.
 | 
			
		||||
  for (LoadTask::unique_ptr task(load_tasks.pop_front());
 | 
			
		||||
      task.get() != nullptr; task.reset(load_tasks.pop_front())) {
 | 
			
		||||
    soinfo* si = find_library_internal(load_tasks, task->get_name(), rtld_flags, extinfo);
 | 
			
		||||
    soinfo* needed_by = task->get_needed_by();
 | 
			
		||||
    soinfo* si = find_library_internal(load_tasks, task->get_name(), needed_by,
 | 
			
		||||
                                       rtld_flags, extinfo);
 | 
			
		||||
    if (si == nullptr) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    soinfo* needed_by = task->get_needed_by();
 | 
			
		||||
 | 
			
		||||
    if (needed_by != nullptr) {
 | 
			
		||||
    if (needed_by != nullptr && (needed_by != start_with || add_as_children)) {
 | 
			
		||||
      needed_by->add_child(si);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1502,8 +1558,8 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
			
		||||
  // Step 2: link libraries.
 | 
			
		||||
  soinfo::soinfo_list_t local_group;
 | 
			
		||||
  walk_dependencies_tree(
 | 
			
		||||
      start_with == nullptr ? soinfos : &start_with,
 | 
			
		||||
      start_with == nullptr ? soinfos_count : 1,
 | 
			
		||||
      (start_with != nullptr && add_as_children) ? &start_with : soinfos,
 | 
			
		||||
      (start_with != nullptr && add_as_children) ? 1 : soinfos_count,
 | 
			
		||||
      [&] (soinfo* si) {
 | 
			
		||||
    local_group.push_back(si);
 | 
			
		||||
    return true;
 | 
			
		||||
@@ -1535,12 +1591,15 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
  if (name == nullptr) {
 | 
			
		||||
    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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1602,7 +1661,7 @@ static void soinfo_unload(soinfo* root) {
 | 
			
		||||
          TRACE("deprecated (old format of soinfo): %s needs to unload %s",
 | 
			
		||||
              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) {
 | 
			
		||||
            // Not found: for example if symlink was deleted between dlopen and dlclose
 | 
			
		||||
            // Since we cannot really handle errors at this point - print and continue.
 | 
			
		||||
@@ -1650,21 +1709,26 @@ void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
 | 
			
		||||
  // See b/17302493 for further details.
 | 
			
		||||
  // Once the above bug is fixed, this code can be modified to use
 | 
			
		||||
  // 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) {
 | 
			
		||||
    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
 | 
			
		||||
                 "buffer len %zu, required len %zu", buffer_size, required_len);
 | 
			
		||||
  }
 | 
			
		||||
  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
 | 
			
		||||
  *end = ':';
 | 
			
		||||
  strcpy(end + 1, kDefaultLdPaths[1]);
 | 
			
		||||
  char* end = buffer;
 | 
			
		||||
  for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
 | 
			
		||||
    if (i > 0) *end++ = ':';
 | 
			
		||||
    end = stpcpy(end, g_default_ld_paths[i]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void do_android_update_LD_LIBRARY_PATH(const char* 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) {
 | 
			
		||||
    DL_ERR("invalid flags to dlopen: %x", flags);
 | 
			
		||||
    return nullptr;
 | 
			
		||||
@@ -1683,7 +1747,7 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ProtectedDataGuard guard;
 | 
			
		||||
  soinfo* si = find_library(name, flags, extinfo);
 | 
			
		||||
  soinfo* si = find_library(name, flags, extinfo, caller);
 | 
			
		||||
  if (si != nullptr) {
 | 
			
		||||
    si->call_constructors();
 | 
			
		||||
  }
 | 
			
		||||
@@ -2419,6 +2483,16 @@ soinfo::soinfo_list_t& soinfo::get_parents() {
 | 
			
		||||
  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 {
 | 
			
		||||
  if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
 | 
			
		||||
    return call_ifunc_resolver(s->st_value + load_bias);
 | 
			
		||||
@@ -2855,6 +2929,10 @@ bool soinfo::prelink_image() {
 | 
			
		||||
        verneed_cnt_ = d->d_un.d_val;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      case DT_RUNPATH:
 | 
			
		||||
        // this is parsed after we have strtab initialized (see below).
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
        if (!relocating_linker) {
 | 
			
		||||
          DL_WARN("%s: unused DT entry: type %p arg %p", get_realpath(),
 | 
			
		||||
@@ -2864,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",
 | 
			
		||||
        reinterpret_cast<void*>(base), strtab_, symtab_);
 | 
			
		||||
 | 
			
		||||
@@ -2888,12 +2972,17 @@ bool soinfo::prelink_image() {
 | 
			
		||||
 | 
			
		||||
  // second pass - parse entries relying on strtab
 | 
			
		||||
  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
 | 
			
		||||
    if (d->d_tag == DT_SONAME) {
 | 
			
		||||
      soname_ = get_string(d->d_un.d_val);
 | 
			
		||||
    switch (d->d_tag) {
 | 
			
		||||
      case DT_SONAME:
 | 
			
		||||
        soname_ = get_string(d->d_un.d_val);
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
      strlcpy(old_name_, soname_, sizeof(old_name_));
 | 
			
		||||
        strlcpy(old_name_, soname_, sizeof(old_name_));
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
        break;
 | 
			
		||||
      case DT_RUNPATH:
 | 
			
		||||
        // FIXME: $LIB, $PLATFORM unsupported.
 | 
			
		||||
        set_dt_runpath(get_string(d->d_un.d_val));
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -3123,6 +3212,16 @@ static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -3213,6 +3312,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
 | 
			
		||||
  somain = si;
 | 
			
		||||
 | 
			
		||||
  init_default_ld_library_path();
 | 
			
		||||
 | 
			
		||||
  if (!si->prelink_image()) {
 | 
			
		||||
    __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
@@ -3244,7 +3345,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
 | 
			
		||||
  if (needed_libraries_count > 0 &&
 | 
			
		||||
      !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());
 | 
			
		||||
    exit(EXIT_FAILURE);
 | 
			
		||||
  } else if (needed_libraries_count == 0) {
 | 
			
		||||
@@ -3397,7 +3499,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
 | 
			
		||||
    _exit(EXIT_FAILURE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  __libc_init_tls(args);
 | 
			
		||||
  __libc_init_main_thread(args);
 | 
			
		||||
 | 
			
		||||
  // Initialize the linker's own global variables
 | 
			
		||||
  linker_so.call_constructors();
 | 
			
		||||
 
 | 
			
		||||
@@ -29,13 +29,14 @@
 | 
			
		||||
#ifndef _LINKER_H_
 | 
			
		||||
#define _LINKER_H_
 | 
			
		||||
 | 
			
		||||
#include <android/dlext.h>
 | 
			
		||||
#include <elf.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <link.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <android/dlext.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "private/bionic_page.h"
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
#include "linked_list.h"
 | 
			
		||||
 | 
			
		||||
@@ -77,16 +78,6 @@
 | 
			
		||||
#define ELF64_R_TYPE(info)  (((info) >> 56) & 0xff)
 | 
			
		||||
#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_EXE        0x00000004 // The main executable
 | 
			
		||||
#define FLAG_LINKER     0x00000010 // The linker itself
 | 
			
		||||
@@ -250,7 +241,9 @@ struct soinfo {
 | 
			
		||||
  bool mips_relocate_got(const VersionTracker& version_tracker,
 | 
			
		||||
                         const soinfo_list_t& global_group,
 | 
			
		||||
                         const soinfo_list_t& local_group);
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
  bool mips_check_and_adjust_fp_modes();
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
  size_t ref_count_;
 | 
			
		||||
 public:
 | 
			
		||||
@@ -336,6 +329,8 @@ struct soinfo {
 | 
			
		||||
 | 
			
		||||
  uint32_t get_target_sdk_version() const;
 | 
			
		||||
 | 
			
		||||
  const std::vector<std::string>& get_dt_runpath() const;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
 | 
			
		||||
  ElfW(Sym)* elf_addr_lookup(const void* addr);
 | 
			
		||||
@@ -397,6 +392,9 @@ struct soinfo {
 | 
			
		||||
 | 
			
		||||
  uint32_t target_sdk_version_;
 | 
			
		||||
 | 
			
		||||
  void set_dt_runpath(const char *);
 | 
			
		||||
  std::vector<std::string> dt_runpath_;
 | 
			
		||||
 | 
			
		||||
  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_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);
 | 
			
		||||
 | 
			
		||||
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,21 @@
 | 
			
		||||
 * 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_debug.h"
 | 
			
		||||
#include "linker_phdr.h"
 | 
			
		||||
#include "linker_relocs.h"
 | 
			
		||||
#include "linker_reloc_iterators.h"
 | 
			
		||||
#include "linker_sleb128.h"
 | 
			
		||||
@@ -62,7 +75,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
 | 
			
		||||
    ElfW(Addr) sym_addr = 0;
 | 
			
		||||
    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) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
@@ -84,7 +97,8 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
 | 
			
		||||
 | 
			
		||||
      if (s == nullptr) {
 | 
			
		||||
        // 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;
 | 
			
		||||
      } else {
 | 
			
		||||
        // We got a definition.
 | 
			
		||||
@@ -171,20 +185,22 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
 | 
			
		||||
      }
 | 
			
		||||
    } else if (st_visibility == STV_PROTECTED) {
 | 
			
		||||
      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;
 | 
			
		||||
      }
 | 
			
		||||
      s = local_sym;
 | 
			
		||||
      lsi = this;
 | 
			
		||||
    } 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s == nullptr) {
 | 
			
		||||
      // We only allow an undefined symbol if this is a weak reference.
 | 
			
		||||
      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;
 | 
			
		||||
      }
 | 
			
		||||
      *got = 0;
 | 
			
		||||
@@ -198,3 +214,134 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
 | 
			
		||||
  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
 | 
			
		||||
// 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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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(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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 | 
			
		||||
 | 
			
		||||
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_SRC_FILES := \
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ endif
 | 
			
		||||
LOCAL_CLANG := $($(module)_clang_$(build_type))
 | 
			
		||||
 | 
			
		||||
ifneq ($($(module)_allow_asan),true)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_SANITIZE := never
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
 | 
			
		||||
@@ -48,6 +48,10 @@ ifneq ($($(module)_multilib),)
 | 
			
		||||
    LOCAL_MULTILIB := $($(module)_multilib)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq ($($(module)_relative_path),)
 | 
			
		||||
    LOCAL_MODULE_RELATIVE_PATH := $($(module)_relative_path)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LOCAL_CFLAGS := \
 | 
			
		||||
    $(common_cflags) \
 | 
			
		||||
    $($(module)_cflags) \
 | 
			
		||||
 
 | 
			
		||||
@@ -46,8 +46,7 @@ else
 | 
			
		||||
test_cflags += -DUSE_JEMALLOC
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
test_cppflags = \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
test_cppflags := \
 | 
			
		||||
 | 
			
		||||
libBionicStandardTests_src_files := \
 | 
			
		||||
    arpa_inet_test.cpp \
 | 
			
		||||
@@ -93,6 +92,7 @@ libBionicStandardTests_src_files := \
 | 
			
		||||
    sys_epoll_test.cpp \
 | 
			
		||||
    sys_mman_test.cpp \
 | 
			
		||||
    sys_personality_test.cpp \
 | 
			
		||||
    sys_prctl_test.cpp \
 | 
			
		||||
    sys_procfs_test.cpp \
 | 
			
		||||
    sys_resource_test.cpp \
 | 
			
		||||
    sys_select_test.cpp \
 | 
			
		||||
@@ -137,6 +137,11 @@ libBionicStandardTests_static_libraries := \
 | 
			
		||||
libBionicStandardTests_ldlibs_host := \
 | 
			
		||||
    -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_tag := optional
 | 
			
		||||
build_type := target
 | 
			
		||||
@@ -241,12 +246,7 @@ libBionicCtsGtestMain_src_files := gtest_main.cpp
 | 
			
		||||
 | 
			
		||||
libBionicCtsGtestMain_cflags := $(test_cflags)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
libBionicCtsGtestMain_cppflags := $(test_cppflags) -DUSING_GTEST_OUTPUT_FORMAT
 | 
			
		||||
 | 
			
		||||
module := libBionicCtsGtestMain
 | 
			
		||||
module_tag := optional
 | 
			
		||||
@@ -279,6 +279,7 @@ bionic-unit-tests_src_files := \
 | 
			
		||||
    dlfcn_test.cpp \
 | 
			
		||||
    libdl_test.cpp \
 | 
			
		||||
    pthread_dlfcn_test.cpp \
 | 
			
		||||
    thread_local_test.cpp \
 | 
			
		||||
 | 
			
		||||
bionic-unit-tests_cflags := $(test_cflags)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -256,7 +256,7 @@ void RunSingleBufferAlignTest(
 | 
			
		||||
      VerifyFencepost(&buf_align[len]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  delete buf;
 | 
			
		||||
  delete[] buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunSrcDstBufferAlignTest(
 | 
			
		||||
@@ -292,8 +292,8 @@ void RunSrcDstBufferAlignTest(
 | 
			
		||||
      VerifyFencepost(&dst_align[len]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  delete src;
 | 
			
		||||
  delete dst;
 | 
			
		||||
  delete[] src;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunCmpBufferAlignTest(
 | 
			
		||||
@@ -344,8 +344,8 @@ void RunCmpBufferAlignTest(
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  delete buf1;
 | 
			
		||||
  delete buf2;
 | 
			
		||||
  delete[] buf1;
 | 
			
		||||
  delete[] buf2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
  free(memory);
 | 
			
		||||
  delete dst;
 | 
			
		||||
  delete[] dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunCmpBufferOverreadTest(
 | 
			
		||||
 
 | 
			
		||||
@@ -51,12 +51,12 @@ TEST(dlfcn, ctor_function_call) {
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlsym_in_executable) {
 | 
			
		||||
  dlerror(); // Clear any pending errors.
 | 
			
		||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != NULL);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
			
		||||
  void* self = dlopen(nullptr, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != nullptr);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == nullptr);
 | 
			
		||||
 | 
			
		||||
  void* sym = dlsym(self, "DlSymTestFunction");
 | 
			
		||||
  ASSERT_TRUE(sym != NULL);
 | 
			
		||||
  ASSERT_TRUE(sym != nullptr);
 | 
			
		||||
 | 
			
		||||
  void (*function)() = reinterpret_cast<void(*)()>(sym);
 | 
			
		||||
 | 
			
		||||
@@ -175,11 +175,11 @@ TEST(dlfcn, dlsym_with_dependencies) {
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlopen_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);
 | 
			
		||||
  void* handle2 = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
 | 
			
		||||
  ASSERT_TRUE(handle != NULL);
 | 
			
		||||
  ASSERT_TRUE(handle2 != NULL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr);
 | 
			
		||||
  ASSERT_TRUE(handle2 != nullptr);
 | 
			
		||||
  ASSERT_TRUE(handle == handle2);
 | 
			
		||||
  ASSERT_EQ(0, dlclose(handle));
 | 
			
		||||
  ASSERT_EQ(0, dlclose(handle2));
 | 
			
		||||
@@ -220,11 +220,11 @@ TEST(dlfcn, ifunc) {
 | 
			
		||||
  // first check the set case
 | 
			
		||||
  setenv("IFUNC_CHOICE", "set", 1);
 | 
			
		||||
  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_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
			
		||||
  ASSERT_TRUE(foo_ptr != NULL);
 | 
			
		||||
  ASSERT_TRUE(foo_library_ptr != NULL);
 | 
			
		||||
  ASSERT_TRUE(foo_ptr != nullptr);
 | 
			
		||||
  ASSERT_TRUE(foo_library_ptr != nullptr);
 | 
			
		||||
  ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
 | 
			
		||||
  ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
 | 
			
		||||
  dlclose(handle);
 | 
			
		||||
@@ -232,11 +232,11 @@ TEST(dlfcn, ifunc) {
 | 
			
		||||
  // then check the unset case
 | 
			
		||||
  unsetenv("IFUNC_CHOICE");
 | 
			
		||||
  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_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
 | 
			
		||||
  ASSERT_TRUE(foo_ptr != NULL);
 | 
			
		||||
  ASSERT_TRUE(foo_library_ptr != NULL);
 | 
			
		||||
  ASSERT_TRUE(foo_ptr != nullptr);
 | 
			
		||||
  ASSERT_TRUE(foo_library_ptr != nullptr);
 | 
			
		||||
  ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
 | 
			
		||||
  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
 | 
			
		||||
  dlclose(handle);
 | 
			
		||||
@@ -315,9 +315,9 @@ TEST(dlfcn, dlopen_check_order_dlsym) {
 | 
			
		||||
  typedef int (*fn_t) (void);
 | 
			
		||||
  fn_t fn, fn2;
 | 
			
		||||
  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"));
 | 
			
		||||
  ASSERT_TRUE(fn2 != NULL) << dlerror();
 | 
			
		||||
  ASSERT_TRUE(fn2 != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(42, fn());
 | 
			
		||||
  ASSERT_EQ(43, fn2());
 | 
			
		||||
@@ -718,7 +718,7 @@ TEST(dlfcn, dlsym_df_1_global) {
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlopen_failure) {
 | 
			
		||||
  void* self = dlopen("/does/not/exist", RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self == NULL);
 | 
			
		||||
  ASSERT_TRUE(self == nullptr);
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  ASSERT_STREQ("dlopen failed: library \"/does/not/exist\" not found", dlerror());
 | 
			
		||||
#else
 | 
			
		||||
@@ -737,7 +737,7 @@ TEST(dlfcn, dlerror_concurrent) {
 | 
			
		||||
  ASSERT_SUBSTR("/main/thread", main_thread_error);
 | 
			
		||||
 | 
			
		||||
  pthread_t t;
 | 
			
		||||
  ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentDlErrorFn, NULL));
 | 
			
		||||
  ASSERT_EQ(0, pthread_create(&t, nullptr, ConcurrentDlErrorFn, nullptr));
 | 
			
		||||
  void* result;
 | 
			
		||||
  ASSERT_EQ(0, pthread_join(t, &result));
 | 
			
		||||
  char* child_thread_error = static_cast<char*>(result);
 | 
			
		||||
@@ -749,31 +749,31 @@ TEST(dlfcn, dlerror_concurrent) {
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlsym_failures) {
 | 
			
		||||
  dlerror(); // Clear any pending errors.
 | 
			
		||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != NULL);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
			
		||||
  void* self = dlopen(nullptr, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != nullptr);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == nullptr);
 | 
			
		||||
 | 
			
		||||
  void* sym;
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__) && !defined(__LP64__)
 | 
			
		||||
  // RTLD_DEFAULT in lp32 bionic is not (void*)0
 | 
			
		||||
  // so it can be distinguished from the NULL handle.
 | 
			
		||||
  sym = dlsym(NULL, "test");
 | 
			
		||||
  ASSERT_TRUE(sym == NULL);
 | 
			
		||||
  sym = dlsym(nullptr, "test");
 | 
			
		||||
  ASSERT_TRUE(sym == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("dlsym library handle is null", dlerror());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // NULL symbol name.
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  // glibc marks this parameter non-null and SEGVs if you cheat.
 | 
			
		||||
  sym = dlsym(self, NULL);
 | 
			
		||||
  ASSERT_TRUE(sym == NULL);
 | 
			
		||||
  sym = dlsym(self, nullptr);
 | 
			
		||||
  ASSERT_TRUE(sym == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("", dlerror());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Symbol that doesn't exist.
 | 
			
		||||
  sym = dlsym(self, "ThisSymbolDoesNotExist");
 | 
			
		||||
  ASSERT_TRUE(sym == NULL);
 | 
			
		||||
  ASSERT_TRUE(sym == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("undefined symbol: ThisSymbolDoesNotExist", dlerror());
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(0, dlclose(self));
 | 
			
		||||
@@ -781,12 +781,12 @@ TEST(dlfcn, dlsym_failures) {
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dladdr_executable) {
 | 
			
		||||
  dlerror(); // Clear any pending errors.
 | 
			
		||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != NULL);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == NULL);
 | 
			
		||||
  void* self = dlopen(nullptr, RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(self != nullptr);
 | 
			
		||||
  ASSERT_TRUE(dlerror() == nullptr);
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
  void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
 | 
			
		||||
@@ -861,12 +861,12 @@ TEST(dlfcn, dladdr_invalid) {
 | 
			
		||||
  dlerror(); // Clear any pending errors.
 | 
			
		||||
 | 
			
		||||
  // No symbol corresponding to NULL.
 | 
			
		||||
  ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success.
 | 
			
		||||
  ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3).
 | 
			
		||||
  ASSERT_EQ(dladdr(nullptr, &info), 0); // Zero on error, non-zero on success.
 | 
			
		||||
  ASSERT_TRUE(dlerror() == nullptr); // dladdr(3) doesn't set dlerror(3).
 | 
			
		||||
 | 
			
		||||
  // No symbol corresponding to a stack address.
 | 
			
		||||
  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.
 | 
			
		||||
@@ -922,49 +922,49 @@ TEST(dlfcn, dlopen_bad_flags) {
 | 
			
		||||
 | 
			
		||||
#if defined(__GLIBC__)
 | 
			
		||||
  // glibc was smart enough not to define RTLD_NOW as 0, so it can detect missing flags.
 | 
			
		||||
  handle = dlopen(NULL, 0);
 | 
			
		||||
  ASSERT_TRUE(handle == NULL);
 | 
			
		||||
  handle = dlopen(nullptr, 0);
 | 
			
		||||
  ASSERT_TRUE(handle == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("invalid", dlerror());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  handle = dlopen(NULL, 0xffffffff);
 | 
			
		||||
  ASSERT_TRUE(handle == NULL);
 | 
			
		||||
  handle = dlopen(nullptr, 0xffffffff);
 | 
			
		||||
  ASSERT_TRUE(handle == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("invalid", dlerror());
 | 
			
		||||
 | 
			
		||||
  // 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);
 | 
			
		||||
  ASSERT_TRUE(handle != NULL);
 | 
			
		||||
  ASSERT_SUBSTR(NULL, dlerror());
 | 
			
		||||
  handle = dlopen(nullptr, RTLD_NOW|RTLD_LAZY);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr);
 | 
			
		||||
  ASSERT_SUBSTR(nullptr, dlerror());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, rtld_default_unknown_symbol) {
 | 
			
		||||
  void* addr = dlsym(RTLD_DEFAULT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
			
		||||
  ASSERT_TRUE(addr == NULL);
 | 
			
		||||
  ASSERT_TRUE(addr == nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, rtld_default_known_symbol) {
 | 
			
		||||
  void* addr = dlsym(RTLD_DEFAULT, "fopen");
 | 
			
		||||
  ASSERT_TRUE(addr != NULL);
 | 
			
		||||
  ASSERT_TRUE(addr != nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, rtld_next_unknown_symbol) {
 | 
			
		||||
  void* addr = dlsym(RTLD_NEXT, "ANY_UNKNOWN_SYMBOL_NAME");
 | 
			
		||||
  ASSERT_TRUE(addr == NULL);
 | 
			
		||||
  ASSERT_TRUE(addr == nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, rtld_next_known_symbol) {
 | 
			
		||||
  void* addr = dlsym(RTLD_NEXT, "fopen");
 | 
			
		||||
  ASSERT_TRUE(addr != NULL);
 | 
			
		||||
  ASSERT_TRUE(addr != nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlsym_weak_func) {
 | 
			
		||||
  dlerror();
 | 
			
		||||
  void* handle = dlopen("libtest_dlsym_weak_func.so", RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(handle != NULL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr);
 | 
			
		||||
 | 
			
		||||
  int (*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());
 | 
			
		||||
  dlclose(handle);
 | 
			
		||||
}
 | 
			
		||||
@@ -982,8 +982,8 @@ TEST(dlfcn, dlopen_undefined_weak_func) {
 | 
			
		||||
TEST(dlfcn, dlopen_symlink) {
 | 
			
		||||
  void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
 | 
			
		||||
  void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(handle1 != NULL);
 | 
			
		||||
  ASSERT_TRUE(handle2 != NULL);
 | 
			
		||||
  ASSERT_TRUE(handle1 != nullptr);
 | 
			
		||||
  ASSERT_TRUE(handle2 != nullptr);
 | 
			
		||||
  ASSERT_EQ(handle1, handle2);
 | 
			
		||||
  dlclose(handle1);
 | 
			
		||||
  dlclose(handle2);
 | 
			
		||||
@@ -1062,3 +1062,17 @@ extern "C" int version_zero_function() {
 | 
			
		||||
extern "C" int version_zero_function2() {
 | 
			
		||||
  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
 | 
			
		||||
  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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
  char buf[1];
 | 
			
		||||
  size_t ct = atoi("2"); // prevent optimizations
 | 
			
		||||
@@ -647,6 +653,22 @@ TEST_F(DEATHTEST, read_fortified) {
 | 
			
		||||
  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) {
 | 
			
		||||
  char buf[1];
 | 
			
		||||
  size_t ct = atoi("2"); // prevent optimizations
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ using testing::internal::COLOR_GREEN;
 | 
			
		||||
using testing::internal::COLOR_YELLOW;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
// 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)) {
 | 
			
		||||
      ++p;
 | 
			
		||||
    }
 | 
			
		||||
    if (*p != '\0') {
 | 
			
		||||
    if (*p != '\0' && *p != '#') {
 | 
			
		||||
      // This is not we want, gtest must meet with some error when parsing the arguments.
 | 
			
		||||
      fprintf(stderr, "argument error, check with --help\n");
 | 
			
		||||
      return false;
 | 
			
		||||
@@ -839,12 +839,8 @@ static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>&
 | 
			
		||||
  return all_tests_passed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t GetDefaultJobCount() {
 | 
			
		||||
#if defined(JOB_COUNT_FIXED)
 | 
			
		||||
  return JOB_COUNT_FIXED;
 | 
			
		||||
#else
 | 
			
		||||
static size_t GetProcessorCount() {
 | 
			
		||||
  return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
  options.job_count = GetDefaultJobCount();
 | 
			
		||||
  options.job_count = GetProcessorCount();
 | 
			
		||||
  options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
 | 
			
		||||
  options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
 | 
			
		||||
  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)
 | 
			
		||||
TEST_PATH := $(LOCAL_PATH)/..
 | 
			
		||||
 | 
			
		||||
common_cppflags += -std=gnu++11
 | 
			
		||||
common_cppflags :=
 | 
			
		||||
common_additional_dependencies := \
 | 
			
		||||
    $(LOCAL_PATH)/Android.mk \
 | 
			
		||||
    $(LOCAL_PATH)/Android.build.dt_runpath.mk \
 | 
			
		||||
    $(LOCAL_PATH)/Android.build.dlext_testzip.mk \
 | 
			
		||||
    $(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk \
 | 
			
		||||
    $(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
 | 
			
		||||
@@ -179,6 +180,11 @@ libtest_nodelete_dt_flags_1_ldflags := -Wl,-z,nodelete
 | 
			
		||||
module := libtest_nodelete_dt_flags_1
 | 
			
		||||
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
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								tests/pthread_test.cpp
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/pthread_test.cpp
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							@@ -1154,6 +1154,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
  // The two methods of asking for the stack size should agree.
 | 
			
		||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  // What does /proc/self/maps' [stack] line say?
 | 
			
		||||
  void* maps_stack_hi = NULL;
 | 
			
		||||
  FILE* fp = fopen("/proc/self/maps", "r");
 | 
			
		||||
@@ -1170,15 +1171,18 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
  }
 | 
			
		||||
  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.
 | 
			
		||||
  rlimit rl;
 | 
			
		||||
  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
 | 
			
		||||
  uint64_t original_rlim_cur = rl.rlim_cur;
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  if (rl.rlim_cur == RLIM_INFINITY) {
 | 
			
		||||
    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  EXPECT_EQ(rl.rlim_cur, stack_size);
 | 
			
		||||
 | 
			
		||||
  auto guard = make_scope_guard([&rl, original_rlim_cur]() {
 | 
			
		||||
@@ -1186,11 +1190,6 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
    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?
 | 
			
		||||
  //
 | 
			
		||||
@@ -1218,6 +1217,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
			
		||||
  ASSERT_EQ(6666U, stack_size);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pthread_attr_getstack_18908062_helper(void*) {
 | 
			
		||||
@@ -1244,11 +1244,8 @@ TEST(pthread, pthread_attr_getstack_18908062) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
static pthread_mutex_t gettid_mutex;
 | 
			
		||||
static void* pthread_gettid_np_helper(void* arg) {
 | 
			
		||||
  pthread_mutex_lock(&gettid_mutex);
 | 
			
		||||
  *reinterpret_cast<pid_t*>(arg) = gettid();
 | 
			
		||||
  pthread_mutex_unlock(&gettid_mutex);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1259,15 +1256,11 @@ TEST(pthread, pthread_gettid_np) {
 | 
			
		||||
 | 
			
		||||
  pid_t t_gettid_result;
 | 
			
		||||
  pthread_t t;
 | 
			
		||||
  pthread_mutex_init(&gettid_mutex, NULL);
 | 
			
		||||
  pthread_mutex_lock(&gettid_mutex);
 | 
			
		||||
  pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result);
 | 
			
		||||
 | 
			
		||||
  pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
 | 
			
		||||
  pthread_mutex_unlock(&gettid_mutex);
 | 
			
		||||
 | 
			
		||||
  pthread_join(t, NULL);
 | 
			
		||||
  pthread_mutex_destroy(&gettid_mutex);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
 | 
			
		||||
#else
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
#include <malloc.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "buffer_tests.h"
 | 
			
		||||
 | 
			
		||||
@@ -1396,6 +1397,10 @@ TEST(string, strnlen_147048) {
 | 
			
		||||
  delete[] heap_src;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(string, strnlen_74741) {
 | 
			
		||||
  ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(string, mempcpy) {
 | 
			
		||||
  char dst[6];
 | 
			
		||||
  ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
 | 
			
		||||
 
 | 
			
		||||
@@ -163,8 +163,6 @@ TEST(getpwnam, app_id_u1_i0) {
 | 
			
		||||
  check_get_passwd("u1_i0", 199000, TYPE_APP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
static void check_group(const group* grp, const char* group_name, gid_t gid) {
 | 
			
		||||
  ASSERT_TRUE(grp != NULL);
 | 
			
		||||
  ASSERT_STREQ(group_name, grp->gr_name);
 | 
			
		||||
@@ -174,6 +172,8 @@ static void check_group(const group* grp, const char* group_name, gid_t gid) {
 | 
			
		||||
  ASSERT_TRUE(grp->gr_mem[1] == NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
static void check_getgrgid(const char* group_name, gid_t gid) {
 | 
			
		||||
  errno = 0;
 | 
			
		||||
  group* grp = getgrgid(gid);
 | 
			
		||||
@@ -190,17 +190,49 @@ static void check_getgrnam(const char* group_name, gid_t gid) {
 | 
			
		||||
  check_group(grp, group_name, gid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_getgrgid_r(const char* group_name, gid_t gid) {
 | 
			
		||||
  group grp_storage;
 | 
			
		||||
  char buf[512];
 | 
			
		||||
  group* grp;
 | 
			
		||||
 | 
			
		||||
  errno = 0;
 | 
			
		||||
  int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  ASSERT_EQ(0, errno);
 | 
			
		||||
  SCOPED_TRACE("getgrgid_r");
 | 
			
		||||
  check_group(grp, group_name, gid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_getgrnam_r(const char* group_name, gid_t gid) {
 | 
			
		||||
  group grp_storage;
 | 
			
		||||
  char buf[512];
 | 
			
		||||
  group* grp;
 | 
			
		||||
 | 
			
		||||
  errno = 0;
 | 
			
		||||
  int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  ASSERT_EQ(0, errno);
 | 
			
		||||
  SCOPED_TRACE("getgrnam_r");
 | 
			
		||||
  check_group(grp, group_name, gid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_get_group(const char* group_name, gid_t gid) {
 | 
			
		||||
  check_getgrgid(group_name, gid);
 | 
			
		||||
  check_getgrnam(group_name, gid);
 | 
			
		||||
  check_getgrgid_r(group_name, gid);
 | 
			
		||||
  check_getgrnam_r(group_name, gid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else // !defined(__BIONIC__)
 | 
			
		||||
 | 
			
		||||
static void check_get_group(const char* /* group_name */, gid_t /* gid */) {
 | 
			
		||||
static void print_no_getgrnam_test_info() {
 | 
			
		||||
  GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_get_group(const char*, gid_t) {
 | 
			
		||||
  print_no_getgrnam_test_info();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
TEST(getgrnam, system_id_root) {
 | 
			
		||||
@@ -259,3 +291,53 @@ TEST(getgrnam, app_id_u1_a40000) {
 | 
			
		||||
TEST(getgrnam, app_id_u1_i0) {
 | 
			
		||||
  check_get_group("u1_i0", 199000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(getgrnam_r, reentrancy) {
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  group grp_storage[2];
 | 
			
		||||
  char buf[2][512];
 | 
			
		||||
  group* grp[3];
 | 
			
		||||
  int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  check_group(grp[0], "root", 0);
 | 
			
		||||
  grp[1] = getgrnam("system");
 | 
			
		||||
  check_group(grp[1], "system", 1000);
 | 
			
		||||
  result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  check_group(grp[2], "radio", 1001);
 | 
			
		||||
  check_group(grp[0], "root", 0);
 | 
			
		||||
  check_group(grp[1], "system", 1000);
 | 
			
		||||
#else
 | 
			
		||||
  print_no_getgrnam_test_info();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(getgrgid_r, reentrancy) {
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  group grp_storage[2];
 | 
			
		||||
  char buf[2][512];
 | 
			
		||||
  group* grp[3];
 | 
			
		||||
  int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  check_group(grp[0], "root", 0);
 | 
			
		||||
  grp[1] = getgrgid(1000);
 | 
			
		||||
  check_group(grp[1], "system", 1000);
 | 
			
		||||
  result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
 | 
			
		||||
  ASSERT_EQ(0, result);
 | 
			
		||||
  check_group(grp[2], "radio", 1001);
 | 
			
		||||
  check_group(grp[0], "root", 0);
 | 
			
		||||
  check_group(grp[1], "system", 1000);
 | 
			
		||||
#else
 | 
			
		||||
  print_no_getgrnam_test_info();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(getgrnam_r, large_enough_suggested_buffer_size) {
 | 
			
		||||
  long size = sysconf(_SC_GETGR_R_SIZE_MAX);
 | 
			
		||||
  ASSERT_GT(size, 0);
 | 
			
		||||
  char buf[size];
 | 
			
		||||
  group grp_storage;
 | 
			
		||||
  group* grp;
 | 
			
		||||
  ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
 | 
			
		||||
  check_group(grp, "root", 0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								tests/sys_prctl_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tests/sys_prctl_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/prctl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "private/bionic_prctl.h"
 | 
			
		||||
 | 
			
		||||
// http://b/20017123.
 | 
			
		||||
TEST(sys_prctl, bug_20017123) {
 | 
			
		||||
#if defined(__ANDROID__)
 | 
			
		||||
  size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
 | 
			
		||||
  void* p = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 | 
			
		||||
  ASSERT_NE(MAP_FAILED, p);
 | 
			
		||||
  ASSERT_EQ(0, mprotect(p, page_size, PROT_NONE));
 | 
			
		||||
  ASSERT_NE(-1, prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, page_size * 3, "anonymous map space"));
 | 
			
		||||
  volatile char* vp = reinterpret_cast<volatile char*>(p);
 | 
			
		||||
  // Below memory access causes SEGV if the memory map is screwed up.
 | 
			
		||||
  *(vp + page_size) = 0;
 | 
			
		||||
  ASSERT_EQ(0, munmap(p, page_size * 3));
 | 
			
		||||
#else
 | 
			
		||||
  GTEST_LOG_(INFO) << "This test does nothing as it tests an Android specific kernel feature.";
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -80,6 +80,7 @@ TEST(sys_xattr, fsetxattr_with_opath) {
 | 
			
		||||
  ASSERT_EQ(-1, res);
 | 
			
		||||
  ASSERT_EQ(EBADF, errno);
 | 
			
		||||
#endif
 | 
			
		||||
  close(fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
 | 
			
		||||
@@ -97,4 +98,32 @@ TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
 | 
			
		||||
  ASSERT_EQ(-1, res);
 | 
			
		||||
  ASSERT_EQ(EBADF, errno);
 | 
			
		||||
#endif
 | 
			
		||||
  close(fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(sys_xattr, flistattr) {
 | 
			
		||||
  TemporaryFile tf;
 | 
			
		||||
  char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
 | 
			
		||||
  ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
 | 
			
		||||
  ssize_t result = flistxattr(tf.fd, buf, sizeof(buf));
 | 
			
		||||
  ASSERT_TRUE(result >= 9);
 | 
			
		||||
  ASSERT_TRUE(memmem(buf, sizeof(buf), "user.foo", 9) != NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(sys_xattr, flistattr_opath) {
 | 
			
		||||
  TemporaryFile tf;
 | 
			
		||||
  char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
 | 
			
		||||
  ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
 | 
			
		||||
  int fd = open(tf.filename, O_PATH);
 | 
			
		||||
  ASSERT_NE(-1, fd);
 | 
			
		||||
  ssize_t res = flistxattr(fd, buf, sizeof(buf));
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  ASSERT_TRUE(res >= 9);
 | 
			
		||||
  ASSERT_TRUE(static_cast<size_t>(res) <= sizeof(buf));
 | 
			
		||||
  ASSERT_TRUE(memmem(buf, res, "user.foo", 9) != NULL);
 | 
			
		||||
#else
 | 
			
		||||
  ASSERT_EQ(-1, res);
 | 
			
		||||
  ASSERT_EQ(EBADF, errno);
 | 
			
		||||
#endif
 | 
			
		||||
  close(fd);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								tests/thread_local_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								tests/thread_local_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
// Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
 | 
			
		||||
// Until that bug is fixed, disable optimization since
 | 
			
		||||
// it is not essential for this test.
 | 
			
		||||
#pragma GCC optimize("-O0")
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__thread int local_var = 100;
 | 
			
		||||
int shared_var = 200;
 | 
			
		||||
 | 
			
		||||
static void reset_vars() {
 | 
			
		||||
  local_var = 1000;
 | 
			
		||||
  shared_var = 2000;
 | 
			
		||||
  // local_var should be reset by threads
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void* (*MyThread)(void*);
 | 
			
		||||
 | 
			
		||||
static void* inc_shared_var(void* p) {
 | 
			
		||||
  int *data = reinterpret_cast<int*>(p);
 | 
			
		||||
  shared_var++;
 | 
			
		||||
  *data = shared_var;
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* inc_local_var(void* p) {
 | 
			
		||||
  int *data = reinterpret_cast<int*>(p);
 | 
			
		||||
  local_var++;
 | 
			
		||||
  *data = local_var;
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int run_one_thread(MyThread foo) {
 | 
			
		||||
  pthread_t t;
 | 
			
		||||
  int data;
 | 
			
		||||
  int error = pthread_create(&t, nullptr, foo, &data);
 | 
			
		||||
  if (!error)
 | 
			
		||||
      error = pthread_join(t, nullptr);
 | 
			
		||||
  return error ? error : data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(thread_local_storage, shared) {
 | 
			
		||||
  reset_vars();
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2000);
 | 
			
		||||
 | 
			
		||||
  // Update shared_var, local_var remains 1000.
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_shared_var), 2001);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2001);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_shared_var), 2002);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2002);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_shared_var), 2003);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2003);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(thread_local_storage, local) {
 | 
			
		||||
  reset_vars();
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2000);
 | 
			
		||||
 | 
			
		||||
  // When a child thread updates its own TLS variable,
 | 
			
		||||
  // this thread's local_var and shared_var are not changed.
 | 
			
		||||
  // TLS local_var is initialized to 100 in a thread.
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_local_var), 101);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2000);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_local_var), 101);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2000);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(inc_local_var), 101);
 | 
			
		||||
  ASSERT_EQ(local_var, 1000);
 | 
			
		||||
  ASSERT_EQ(shared_var, 2000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test TLS initialization of more complicated type, array of struct.
 | 
			
		||||
struct Point {
 | 
			
		||||
  int x, y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef Point Triangle[3];
 | 
			
		||||
 | 
			
		||||
__thread Triangle local_triangle = {{10,10}, {20,20}, {30,30}};
 | 
			
		||||
Triangle shared_triangle = {{1,1}, {2,2}, {3,3}};
 | 
			
		||||
 | 
			
		||||
static void reset_triangle() {
 | 
			
		||||
  static const Triangle t1 = {{3,3}, {4,4}, {5,5}};
 | 
			
		||||
  static const Triangle t2 = {{2,2}, {3,3}, {4,4}};
 | 
			
		||||
  memcpy(local_triangle, t1, sizeof(local_triangle));
 | 
			
		||||
  memcpy(shared_triangle, t2, sizeof(shared_triangle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* move_shared_triangle(void* p) {
 | 
			
		||||
  int *data = reinterpret_cast<int*>(p);
 | 
			
		||||
  shared_triangle[1].y++;
 | 
			
		||||
  *data = shared_triangle[1].y;
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* move_local_triangle(void* p) {
 | 
			
		||||
  int *data = reinterpret_cast<int*>(p);
 | 
			
		||||
  local_triangle[1].y++;
 | 
			
		||||
  *data = local_triangle[1].y;
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(thread_local_storage, shared_triangle) {
 | 
			
		||||
  reset_triangle();
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 3);
 | 
			
		||||
 | 
			
		||||
  // Update shared_triangle, local_triangle remains 1000.
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_shared_triangle), 4);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 4);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_shared_triangle), 5);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 5);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_shared_triangle), 6);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(thread_local_storage, local_triangle) {
 | 
			
		||||
  reset_triangle();
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 3);
 | 
			
		||||
 | 
			
		||||
  // Update local_triangle, parent thread's
 | 
			
		||||
  // shared_triangle and local_triangle are unchanged.
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_local_triangle), 21);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 3);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_local_triangle), 21);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 3);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(run_one_thread(move_local_triangle), 21);
 | 
			
		||||
  ASSERT_EQ(local_triangle[1].y, 4);
 | 
			
		||||
  ASSERT_EQ(shared_triangle[1].y, 3);
 | 
			
		||||
}
 | 
			
		||||
@@ -223,7 +223,7 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
 | 
			
		||||
  ts.it_value.tv_nsec = 1;
 | 
			
		||||
  ts.it_interval.tv_sec = 0;
 | 
			
		||||
  ts.it_interval.tv_nsec = 0;
 | 
			
		||||
  ASSERT_EQ(0, timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL));
 | 
			
		||||
  ASSERT_EQ(0, timer_settime(timer_id, 0, &ts, NULL));
 | 
			
		||||
 | 
			
		||||
  usleep(500000);
 | 
			
		||||
  ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
 | 
			
		||||
@@ -296,8 +296,8 @@ TEST(time, timer_settime_0) {
 | 
			
		||||
  Counter counter(Counter::CountAndDisarmNotifyFunction);
 | 
			
		||||
  ASSERT_EQ(0, counter.Value());
 | 
			
		||||
 | 
			
		||||
  counter.SetTime(0, 500000000, 1, 0);
 | 
			
		||||
  sleep(1);
 | 
			
		||||
  counter.SetTime(0, 1, 1, 0);
 | 
			
		||||
  usleep(500000);
 | 
			
		||||
 | 
			
		||||
  // The count should just be 1 because we disarmed the timer the first time it fired.
 | 
			
		||||
  ASSERT_EQ(1, counter.Value());
 | 
			
		||||
@@ -381,8 +381,8 @@ TEST(time, timer_create_multiple) {
 | 
			
		||||
  ASSERT_EQ(0, counter2.Value());
 | 
			
		||||
  ASSERT_EQ(0, counter3.Value());
 | 
			
		||||
 | 
			
		||||
  counter2.SetTime(0, 500000000, 0, 0);
 | 
			
		||||
  sleep(1);
 | 
			
		||||
  counter2.SetTime(0, 1, 0, 0);
 | 
			
		||||
  usleep(500000);
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(0, counter1.Value());
 | 
			
		||||
  EXPECT_EQ(1, counter2.Value());
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user