Compare commits
334 Commits
android-6.
...
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;
|
||||
}
|
||||
|
@@ -130,13 +130,8 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
|
||||
*/
|
||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
|
||||
|
||||
// Leave room for a guard page in the internally created signal stacks.
|
||||
#if defined(__LP64__)
|
||||
// SIGSTKSZ is not big enough for 64-bit arch. See http://b/23041777.
|
||||
#define SIGNAL_STACK_SIZE (16 * 1024 + PAGE_SIZE)
|
||||
#else
|
||||
/* Leave room for a guard page in the internally created signal stacks. */
|
||||
#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE)
|
||||
#endif
|
||||
|
||||
/* Needed by fork. */
|
||||
__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
|
||||
|
@@ -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;
|
||||
}
|
@@ -27,7 +27,6 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <unwind.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <regex>
|
||||
@@ -1155,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");
|
||||
@@ -1171,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]() {
|
||||
@@ -1187,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?
|
||||
//
|
||||
@@ -1219,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*) {
|
||||
@@ -1572,26 +1571,3 @@ TEST_F(pthread_DeathTest, pthread_mutex_unlock_null_64) {
|
||||
GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
|
||||
#endif
|
||||
}
|
||||
|
||||
extern _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx, void* arg);
|
||||
|
||||
static volatile bool signal_handler_on_altstack_done;
|
||||
|
||||
static void SignalHandlerOnAltStack(int signo, siginfo_t*, void*) {
|
||||
ASSERT_EQ(SIGUSR1, signo);
|
||||
// Check if we have enough stack space for unwinding.
|
||||
int count = 0;
|
||||
_Unwind_Backtrace(FrameCounter, &count);
|
||||
ASSERT_GT(count, 0);
|
||||
// Check if we have enough stack space for logging.
|
||||
std::string s(2048, '*');
|
||||
GTEST_LOG_(INFO) << s;
|
||||
signal_handler_on_altstack_done = true;
|
||||
}
|
||||
|
||||
TEST(pthread, big_enough_signal_stack_for_64bit_arch) {
|
||||
signal_handler_on_altstack_done = false;
|
||||
ScopedSignalHandler handler(SIGUSR1, SignalHandlerOnAltStack, SA_SIGINFO | SA_ONSTACK);
|
||||
kill(getpid(), SIGUSR1);
|
||||
ASSERT_TRUE(signal_handler_on_altstack_done);
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@
|
||||
#define noinline __attribute__((__noinline__))
|
||||
#define __unused __attribute__((__unused__))
|
||||
|
||||
_Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) {
|
||||
static _Unwind_Reason_Code FrameCounter(_Unwind_Context* ctx __unused, void* arg) {
|
||||
int* count_ptr = reinterpret_cast<int*>(arg);
|
||||
|
||||
#if SHOW_FRAME_LOCATIONS
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user