Compare commits
222 Commits
marshmallo
...
android-m-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,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 \
|
||||
@@ -579,6 +580,13 @@ libc_common_cflags += -DTARGET_USES_LOGD
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
ifeq ($(use_clang),)
|
||||
use_clang := false
|
||||
endif
|
||||
@@ -657,7 +665,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 +706,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 +752,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 +785,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 +820,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 +861,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 +899,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 +937,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 +962,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 +990,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 +1011,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 +1038,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 +1062,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 +1090,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 +1112,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 +1138,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 +1222,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 +1260,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 +1283,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 +1316,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 +1398,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 +1452,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 +1492,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 +1523,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 +1539,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)
|
||||
|
||||
|
||||
@@ -124,7 +124,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
|
||||
|
||||
@@ -39,6 +39,7 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/bionic/__bionic_clone.S \
|
||||
arch-arm/bionic/_exit_with_stack_teardown.S \
|
||||
arch-arm/bionic/libgcc_compat.c \
|
||||
arch-arm/bionic/libgcc_protect_unwind.c \
|
||||
arch-arm/bionic/__restore.S \
|
||||
arch-arm/bionic/setjmp.S \
|
||||
arch-arm/bionic/syscall.S \
|
||||
|
||||
93
libc/arch-arm/bionic/libgcc_protect_unwind.c
Normal file
93
libc/arch-arm/bionic/libgcc_protect_unwind.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TODO: This file should go away once unwinder migration to libc++.so is complete.
|
||||
|
||||
extern char _Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetCFA __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char _Unwind_Complete __attribute((visibility("protected")));
|
||||
extern char _Unwind_DeleteException __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Get __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Set __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
|
||||
extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
|
||||
extern char ___Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char _Unwind_RaiseException __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char _Unwind_Resume __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
|
||||
extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
|
||||
extern char ___Unwind_Backtrace __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
|
||||
extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
|
||||
|
||||
void* __bionic_libgcc_unwind_symbols[] = {
|
||||
&_Unwind_Backtrace,
|
||||
&__gnu_Unwind_Find_exidx,
|
||||
&__gnu_Unwind_Restore_VFP_D,
|
||||
&__gnu_Unwind_Restore_VFP,
|
||||
&__gnu_Unwind_Restore_VFP_D_16_to_31,
|
||||
&__gnu_Unwind_Restore_WMMXD,
|
||||
&__gnu_Unwind_Restore_WMMXC,
|
||||
&_Unwind_GetCFA,
|
||||
&__gnu_Unwind_RaiseException,
|
||||
&__gnu_Unwind_ForcedUnwind,
|
||||
&__gnu_Unwind_Resume,
|
||||
&__gnu_Unwind_Resume_or_Rethrow,
|
||||
&_Unwind_Complete,
|
||||
&_Unwind_DeleteException,
|
||||
&_Unwind_VRS_Get,
|
||||
&_Unwind_VRS_Set,
|
||||
&__gnu_Unwind_Backtrace,
|
||||
&_Unwind_VRS_Pop,
|
||||
&__gnu_Unwind_Save_VFP_D,
|
||||
&__gnu_Unwind_Save_VFP,
|
||||
&__gnu_Unwind_Save_VFP_D_16_to_31,
|
||||
&__gnu_Unwind_Save_WMMXD,
|
||||
&__gnu_Unwind_Save_WMMXC,
|
||||
&___Unwind_RaiseException,
|
||||
&_Unwind_RaiseException,
|
||||
&___Unwind_Resume,
|
||||
&_Unwind_Resume,
|
||||
&___Unwind_Resume_or_Rethrow,
|
||||
&_Unwind_Resume_or_Rethrow,
|
||||
&___Unwind_ForcedUnwind,
|
||||
&_Unwind_ForcedUnwind,
|
||||
&___Unwind_Backtrace,
|
||||
&_Unwind_GetRegionStart,
|
||||
&_Unwind_GetLanguageSpecificData,
|
||||
&_Unwind_GetDataRelBase,
|
||||
&_Unwind_GetTextRelBase,
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(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
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private/bionic_lock.h"
|
||||
#include "private/bionic_systrace.h"
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
@@ -30,17 +29,12 @@
|
||||
|
||||
#define WRITE_OFFSET 32
|
||||
|
||||
constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
|
||||
|
||||
static Lock g_lock;
|
||||
static const prop_info* g_pinfo;
|
||||
static const prop_info* g_pinfo = NULL;
|
||||
static uint32_t g_serial = -1;
|
||||
static uint64_t g_tags;
|
||||
static uint64_t g_tags = 0;
|
||||
static int g_trace_marker_fd = -1;
|
||||
|
||||
static bool should_trace() {
|
||||
bool result = false;
|
||||
g_lock.lock();
|
||||
// If g_pinfo is null, this means that systrace hasn't been run and it's safe to
|
||||
// assume that no trace writing will need to take place. However, to avoid running
|
||||
// this costly find check each time, we set it to a non-tracing value so that next
|
||||
@@ -48,39 +42,32 @@ static bool should_trace() {
|
||||
// this function also deals with the bootup case, during which the call to property
|
||||
// set will fail if the property server hasn't yet started.
|
||||
if (g_pinfo == NULL) {
|
||||
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
|
||||
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
|
||||
if (g_pinfo == NULL) {
|
||||
__system_property_set(SYSTRACE_PROPERTY_NAME, "0");
|
||||
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
|
||||
__system_property_set("debug.atrace.tags.enableflags", "0");
|
||||
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
|
||||
if (g_pinfo == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_pinfo != NULL) {
|
||||
// Find out which tags have been enabled on the command line and set
|
||||
// the value of tags accordingly. If the value of the property changes,
|
||||
// the serial will also change, so the costly system_property_read function
|
||||
// can be avoided by calling the much cheaper system_property_serial
|
||||
// first. The values within pinfo may change, but its location is guaranteed
|
||||
// not to move.
|
||||
uint32_t cur_serial = __system_property_serial(g_pinfo);
|
||||
if (cur_serial != g_serial) {
|
||||
g_serial = cur_serial;
|
||||
char value[PROP_VALUE_MAX];
|
||||
__system_property_read(g_pinfo, 0, value);
|
||||
g_tags = strtoull(value, NULL, 0);
|
||||
}
|
||||
result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
|
||||
}
|
||||
g_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
static int get_trace_marker_fd() {
|
||||
g_lock.lock();
|
||||
if (g_trace_marker_fd == -1) {
|
||||
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
|
||||
// Find out which tags have been enabled on the command line and set
|
||||
// the value of tags accordingly. If the value of the property changes,
|
||||
// the serial will also change, so the costly system_property_read function
|
||||
// can be avoided by calling the much cheaper system_property_serial
|
||||
// first. The values within pinfo may change, but its location is guaranteed
|
||||
// not to move.
|
||||
const uint32_t cur_serial = __system_property_serial(g_pinfo);
|
||||
if (cur_serial != g_serial) {
|
||||
g_serial = cur_serial;
|
||||
char value[PROP_VALUE_MAX];
|
||||
__system_property_read(g_pinfo, 0, value);
|
||||
g_tags = strtoull(value, NULL, 0);
|
||||
}
|
||||
g_lock.unlock();
|
||||
return g_trace_marker_fd;
|
||||
|
||||
// Finally, verify that this tag value enables bionic tracing.
|
||||
return ((g_tags & ATRACE_TAG_BIONIC) != 0);
|
||||
}
|
||||
|
||||
ScopedTrace::ScopedTrace(const char* message) {
|
||||
@@ -88,9 +75,11 @@ ScopedTrace::ScopedTrace(const char* message) {
|
||||
return;
|
||||
}
|
||||
|
||||
int trace_marker_fd = get_trace_marker_fd();
|
||||
if (trace_marker_fd == -1) {
|
||||
return;
|
||||
if (g_trace_marker_fd == -1) {
|
||||
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
|
||||
if (g_trace_marker_fd == -1) {
|
||||
__libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// If bionic tracing has been enabled, then write the message to the
|
||||
@@ -98,10 +87,12 @@ ScopedTrace::ScopedTrace(const char* message) {
|
||||
int length = strlen(message);
|
||||
char buf[length + WRITE_OFFSET];
|
||||
size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
|
||||
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
|
||||
|
||||
// Tracing may stop just after checking property and before writing the message.
|
||||
// So the write is acceptable to fail. See b/20666100.
|
||||
TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
|
||||
// Error while writing
|
||||
if (static_cast<size_t>(wbytes) != len) {
|
||||
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
ScopedTrace::~ScopedTrace() {
|
||||
@@ -109,10 +100,10 @@ ScopedTrace::~ScopedTrace() {
|
||||
return;
|
||||
}
|
||||
|
||||
int trace_marker_fd = get_trace_marker_fd();
|
||||
if (trace_marker_fd == -1) {
|
||||
return;
|
||||
}
|
||||
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
|
||||
|
||||
TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
|
||||
// Error while writing
|
||||
if (static_cast<size_t>(wbytes) != 1) {
|
||||
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <elf.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -36,22 +35,14 @@
|
||||
#include "debug_mapinfo.h"
|
||||
#include "malloc_debug_disable.h"
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define Elf_W(x) Elf64_##x
|
||||
#else
|
||||
#define Elf_W(x) Elf32_##x
|
||||
#endif
|
||||
|
||||
// Format of /proc/<PID>/maps:
|
||||
// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
|
||||
static mapinfo_t* parse_maps_line(char* line) {
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
uintptr_t offset;
|
||||
char permissions[4];
|
||||
int name_pos;
|
||||
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
|
||||
&end, permissions, &offset, &name_pos) < 2) {
|
||||
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
|
||||
&end, &name_pos) < 2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -68,14 +59,6 @@ static mapinfo_t* parse_maps_line(char* line) {
|
||||
if (mi) {
|
||||
mi->start = start;
|
||||
mi->end = end;
|
||||
mi->offset = offset;
|
||||
if (permissions[0] != 'r') {
|
||||
// Any unreadable map will just get a zero load base.
|
||||
mi->load_base = 0;
|
||||
mi->load_base_read = true;
|
||||
} else {
|
||||
mi->load_base_read = false;
|
||||
}
|
||||
memcpy(mi->name, name, name_len);
|
||||
mi->name[name_len] = '\0';
|
||||
}
|
||||
@@ -112,58 +95,11 @@ __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
|
||||
if (addr < mi->start || addr + sizeof(T) > mi->end) {
|
||||
return false;
|
||||
}
|
||||
// Make sure the address is aligned properly.
|
||||
if (addr & (sizeof(T)-1)) {
|
||||
return false;
|
||||
}
|
||||
*store = *reinterpret_cast<T*>(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
|
||||
mi->load_base = 0;
|
||||
mi->load_base_read = true;
|
||||
uintptr_t addr = mi->start;
|
||||
Elf_W(Ehdr) ehdr;
|
||||
if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
|
||||
return;
|
||||
}
|
||||
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
|
||||
return;
|
||||
}
|
||||
addr += ehdr.e_phoff;
|
||||
for (size_t i = 0; i < ehdr.e_phnum; i++) {
|
||||
Elf_W(Phdr) phdr;
|
||||
if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
|
||||
return;
|
||||
}
|
||||
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
|
||||
return;
|
||||
}
|
||||
if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
|
||||
if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
|
||||
return;
|
||||
}
|
||||
mi->load_base = phdr.p_vaddr;
|
||||
return;
|
||||
}
|
||||
addr += sizeof(phdr);
|
||||
}
|
||||
}
|
||||
|
||||
// Find the containing map info for the PC.
|
||||
__LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
|
||||
for (; mi != NULL; mi = mi->next) {
|
||||
if ((pc >= mi->start) && (pc < mi->end)) {
|
||||
if (!mi->load_base_read) {
|
||||
mapinfo_read_loadbase(mi);
|
||||
}
|
||||
*rel_pc = pc - mi->start + mi->load_base;
|
||||
*rel_pc = pc - mi->start;
|
||||
return mi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,6 @@ struct mapinfo_t {
|
||||
struct mapinfo_t* next;
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
uintptr_t offset;
|
||||
uintptr_t load_base;
|
||||
bool load_base_read;
|
||||
char name[];
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -133,9 +133,8 @@ static HashEntry* record_backtrace(uintptr_t* backtrace, size_t numEntries, size
|
||||
size |= SIZE_FLAG_ZYGOTE_CHILD;
|
||||
}
|
||||
|
||||
// Keep the lock held for as little time as possible to prevent deadlocks.
|
||||
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
|
||||
HashEntry* entry = find_entry(g_hash_table, slot, backtrace, numEntries, size);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->allocations++;
|
||||
} else {
|
||||
@@ -303,6 +302,8 @@ extern "C" void* leak_malloc(size_t bytes) {
|
||||
|
||||
void* base = g_malloc_dispatch->malloc(size);
|
||||
if (base != NULL) {
|
||||
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
|
||||
|
||||
uintptr_t backtrace[BACKTRACE_SIZE];
|
||||
size_t numEntries = GET_BACKTRACE(backtrace, BACKTRACE_SIZE);
|
||||
|
||||
@@ -327,6 +328,8 @@ extern "C" void leak_free(void* mem) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
|
||||
|
||||
// check the guard to make sure it is valid
|
||||
AllocationEntry* header = to_header(mem);
|
||||
|
||||
@@ -339,7 +342,6 @@ extern "C" void leak_free(void* mem) {
|
||||
}
|
||||
}
|
||||
|
||||
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
|
||||
if (header->guard == GUARD || is_valid_entry(header->entry)) {
|
||||
// decrement the allocations
|
||||
HashEntry* entry = header->entry;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -47,7 +47,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;
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -97,6 +97,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];
|
||||
@@ -277,7 +285,6 @@ static void soinfo_free(soinfo* si) {
|
||||
sonext = prev;
|
||||
}
|
||||
|
||||
si->~soinfo();
|
||||
g_soinfo_allocator.free(si);
|
||||
}
|
||||
|
||||
@@ -309,6 +316,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);
|
||||
@@ -1119,7 +1158,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;
|
||||
@@ -1162,8 +1201,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)) {
|
||||
@@ -1190,7 +1230,7 @@ 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.
|
||||
@@ -1210,7 +1250,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 +1363,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 +1376,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 +1424,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 +1437,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
|
||||
@@ -1468,13 +1512,13 @@ 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) {
|
||||
needed_by->add_child(si);
|
||||
}
|
||||
@@ -1921,32 +1965,9 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
|
||||
return false;
|
||||
}
|
||||
} else { // We got a definition.
|
||||
#if !defined(__LP64__)
|
||||
// When relocating dso with text_relocation .text segment is
|
||||
// not executable. We need to restore elf flags before resolving
|
||||
// STT_GNU_IFUNC symbol.
|
||||
bool protect_segments = has_text_relocations &&
|
||||
lsi == this &&
|
||||
ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
|
||||
if (protect_segments) {
|
||||
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
|
||||
DL_ERR("can't protect segments for \"%s\": %s",
|
||||
get_realpath(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// We got a definition.
|
||||
sym_addr = lsi->resolve_symbol_address(s);
|
||||
#if !defined(__LP64__)
|
||||
if (protect_segments) {
|
||||
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
|
||||
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
|
||||
get_realpath(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
count_relocation(kRelocSymbol);
|
||||
}
|
||||
@@ -1983,32 +2004,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
|
||||
reinterpret_cast<void*>(reloc),
|
||||
reinterpret_cast<void*>(load_bias + addend));
|
||||
{
|
||||
#if !defined(__LP64__)
|
||||
// When relocating dso with text_relocation .text segment is
|
||||
// not executable. We need to restore elf flags for this
|
||||
// particular call.
|
||||
if (has_text_relocations) {
|
||||
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
|
||||
DL_ERR("can't protect segments for \"%s\": %s",
|
||||
get_realpath(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
|
||||
#if !defined(__LP64__)
|
||||
// Unprotect it afterwards...
|
||||
if (has_text_relocations) {
|
||||
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
|
||||
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
|
||||
get_realpath(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
|
||||
}
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(load_bias + addend);
|
||||
break;
|
||||
|
||||
#if defined(__aarch64__)
|
||||
@@ -2419,6 +2415,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 +2861,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 +2874,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 +2904,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +250,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 +338,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 +401,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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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,126 @@ 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 compiles lack the new abiflags section.
|
||||
// These compilers used -mfp32 -mdouble-float -modd-spreg defaults,
|
||||
// ie FP32 aka DOUBLE, using odd-numbered single-prec regs
|
||||
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___
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
|
||||
@@ -407,7 +407,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
|
||||
|
||||
LOCAL_CXX = $(LOCAL_PATH)/file-check-cxx \
|
||||
$(HOST_OUT_EXECUTABLES)/FileCheck \
|
||||
$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CXX) \
|
||||
$($(LOCAL_2ND_ARCH_VAR_PREFIX)CXX_BARE) \
|
||||
GCC \
|
||||
|
||||
LOCAL_CLANG := false
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
@@ -20,6 +20,7 @@ TEST_PATH := $(LOCAL_PATH)/..
|
||||
common_cppflags += -std=gnu++11
|
||||
common_additional_dependencies := \
|
||||
$(LOCAL_PATH)/Android.mk \
|
||||
$(LOCAL_PATH)/Android.build.dt_runpath.mk \
|
||||
$(LOCAL_PATH)/Android.build.dlext_testzip.mk \
|
||||
$(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk \
|
||||
$(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
|
||||
@@ -179,6 +180,11 @@ libtest_nodelete_dt_flags_1_ldflags := -Wl,-z,nodelete
|
||||
module := libtest_nodelete_dt_flags_1
|
||||
include $(LOCAL_PATH)/Android.build.testlib.mk
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build DT_RUNPATH test helper libraries
|
||||
# -----------------------------------------------------------------------------
|
||||
include $(LOCAL_PATH)/Android.build.dt_runpath.mk
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build library with two parents
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
15
tests/libs/dlopen_b.cpp
Normal file
15
tests/libs/dlopen_b.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <dlfcn.h>
|
||||
extern "C" void *dlopen_b() {
|
||||
// TODO (dimitry): this is to work around http://b/20049306
|
||||
// remove once it is fixed
|
||||
static int dummy = 0;
|
||||
|
||||
// This is not supposed to succeed. Even though this library has DT_RUNPATH
|
||||
// for libtest_dt_runpath_x.so, it is not taked into account for dlopen.
|
||||
void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
|
||||
if (handle != nullptr) {
|
||||
dummy++;
|
||||
return handle;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
21
tests/pthread_test.cpp
Executable file → Normal file
21
tests/pthread_test.cpp
Executable file → Normal file
@@ -1154,6 +1154,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
||||
// The two methods of asking for the stack size should agree.
|
||||
EXPECT_EQ(stack_size, stack_size2);
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
// What does /proc/self/maps' [stack] line say?
|
||||
void* maps_stack_hi = NULL;
|
||||
FILE* fp = fopen("/proc/self/maps", "r");
|
||||
@@ -1170,15 +1171,18 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
|
||||
// Remember that the stack grows down (and is mapped in on demand), so the low address of the
|
||||
// region isn't very interesting.
|
||||
EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
|
||||
|
||||
// The stack size should correspond to RLIMIT_STACK.
|
||||
rlimit rl;
|
||||
ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
|
||||
uint64_t original_rlim_cur = rl.rlim_cur;
|
||||
#if defined(__BIONIC__)
|
||||
if (rl.rlim_cur == RLIM_INFINITY) {
|
||||
rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
|
||||
}
|
||||
#endif
|
||||
EXPECT_EQ(rl.rlim_cur, stack_size);
|
||||
|
||||
auto guard = make_scope_guard([&rl, original_rlim_cur]() {
|
||||
@@ -1186,11 +1190,6 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
||||
ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
|
||||
});
|
||||
|
||||
// The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
|
||||
// Remember that the stack grows down (and is mapped in on demand), so the low address of the
|
||||
// region isn't very interesting.
|
||||
EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
|
||||
|
||||
//
|
||||
// What if RLIMIT_STACK is smaller than the stack's current extent?
|
||||
//
|
||||
@@ -1218,6 +1217,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
||||
|
||||
EXPECT_EQ(stack_size, stack_size2);
|
||||
ASSERT_EQ(6666U, stack_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pthread_attr_getstack_18908062_helper(void*) {
|
||||
@@ -1244,11 +1244,8 @@ TEST(pthread, pthread_attr_getstack_18908062) {
|
||||
}
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
static pthread_mutex_t gettid_mutex;
|
||||
static void* pthread_gettid_np_helper(void* arg) {
|
||||
pthread_mutex_lock(&gettid_mutex);
|
||||
*reinterpret_cast<pid_t*>(arg) = gettid();
|
||||
pthread_mutex_unlock(&gettid_mutex);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -1259,15 +1256,11 @@ TEST(pthread, pthread_gettid_np) {
|
||||
|
||||
pid_t t_gettid_result;
|
||||
pthread_t t;
|
||||
pthread_mutex_init(&gettid_mutex, NULL);
|
||||
pthread_mutex_lock(&gettid_mutex);
|
||||
pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result);
|
||||
|
||||
pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
|
||||
pthread_mutex_unlock(&gettid_mutex);
|
||||
|
||||
pthread_join(t, NULL);
|
||||
pthread_mutex_destroy(&gettid_mutex);
|
||||
|
||||
ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
|
||||
#else
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ TEST(time, timer_create_SIGEV_SIGNAL) {
|
||||
ts.it_value.tv_nsec = 1;
|
||||
ts.it_interval.tv_sec = 0;
|
||||
ts.it_interval.tv_nsec = 0;
|
||||
ASSERT_EQ(0, timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL));
|
||||
ASSERT_EQ(0, timer_settime(timer_id, 0, &ts, NULL));
|
||||
|
||||
usleep(500000);
|
||||
ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
|
||||
@@ -296,8 +296,8 @@ TEST(time, timer_settime_0) {
|
||||
Counter counter(Counter::CountAndDisarmNotifyFunction);
|
||||
ASSERT_EQ(0, counter.Value());
|
||||
|
||||
counter.SetTime(0, 500000000, 1, 0);
|
||||
sleep(1);
|
||||
counter.SetTime(0, 1, 1, 0);
|
||||
usleep(500000);
|
||||
|
||||
// The count should just be 1 because we disarmed the timer the first time it fired.
|
||||
ASSERT_EQ(1, counter.Value());
|
||||
@@ -381,8 +381,8 @@ TEST(time, timer_create_multiple) {
|
||||
ASSERT_EQ(0, counter2.Value());
|
||||
ASSERT_EQ(0, counter3.Value());
|
||||
|
||||
counter2.SetTime(0, 500000000, 0, 0);
|
||||
sleep(1);
|
||||
counter2.SetTime(0, 1, 0, 0);
|
||||
usleep(500000);
|
||||
|
||||
EXPECT_EQ(0, counter1.Value());
|
||||
EXPECT_EQ(1, counter2.Value());
|
||||
|
||||
@@ -73,8 +73,10 @@ def clean_project(dry_run):
|
||||
build = 'clean-bionic-presubmit'
|
||||
if build in jenkins:
|
||||
if not dry_run:
|
||||
job = jenkins[build].invoke()
|
||||
url = job.get_build().baseurl
|
||||
_ = jenkins[build].invoke()
|
||||
# https://issues.jenkins-ci.org/browse/JENKINS-27256
|
||||
# url = job.get_build().baseurl
|
||||
url = 'URL UNAVAILABLE'
|
||||
else:
|
||||
url = 'DRY_RUN_URL'
|
||||
logging.info('Cleaning: %s %s', build, url)
|
||||
|
||||
@@ -96,5 +96,11 @@ $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so))
|
||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so))
|
||||
|
||||
endif
|
||||
|
||||
@@ -302,13 +302,75 @@ static void AdjustSectionHeadersForHole(Elf* elf,
|
||||
}
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the offsets of any program headers
|
||||
// that have offsets currently beyond the hole start.
|
||||
// Helpers for ResizeSection(). On packing, reduce p_align for LOAD segments
|
||||
// to 4kb if larger. On unpacking, restore p_align for LOAD segments if
|
||||
// packing reduced it to 4kb. Return true if p_align was changed.
|
||||
template <typename ELF>
|
||||
static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
|
||||
static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If large, reduce p_align for a LOAD segment to page size on packing.
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Phdr* program_header) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
// If p_align was reduced on packing, restore it to its previous value
|
||||
// on unpacking. We do this by searching for a different LOAD segment
|
||||
// and setting p_align to that of the other LOAD segment found.
|
||||
//
|
||||
// Relies on the following observations:
|
||||
// - a packable ELF executable has more than one LOAD segment;
|
||||
// - before packing all LOAD segments have the same p_align;
|
||||
// - on packing we reduce only one LOAD segment's p_align.
|
||||
if (program_header->p_align == kPageSize) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* other_header = &program_headers[i];
|
||||
if (other_header->p_type == PT_LOAD && other_header != program_header) {
|
||||
program_header->p_align = other_header->p_align;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ELF>
|
||||
static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
typename ELF::Phdr* program_header,
|
||||
ssize_t hole_size) {
|
||||
CHECK(program_header->p_type == PT_LOAD);
|
||||
|
||||
bool status = false;
|
||||
if (hole_size < 0) {
|
||||
status = ClampLoadSegmentAlignment<ELF>(program_header);
|
||||
} else if (hole_size > 0) {
|
||||
status = RestoreLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Adjust the offsets of any program headers
|
||||
// that have offsets currently beyond the hole start, and adjust the
|
||||
// virtual and physical addrs (and perhaps alignment) of the others.
|
||||
template <typename ELF>
|
||||
static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
int alignment_changes = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
typename ELF::Phdr* program_header = &program_headers[i];
|
||||
|
||||
@@ -327,9 +389,20 @@ static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
|
||||
} else {
|
||||
program_header->p_vaddr -= hole_size;
|
||||
program_header->p_paddr -= hole_size;
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
|
||||
// If packing, clamp LOAD segment alignment to 4kb to prevent strip
|
||||
// from adjusting it unnecessarily if run on a packed file. If
|
||||
// unpacking, attempt to restore a reduced alignment to its previous
|
||||
// value. Ensure that we do this on at most one LOAD segment.
|
||||
if (program_header->p_type == PT_LOAD) {
|
||||
alignment_changes += AdjustLoadSegmentAlignment<ELF>(program_headers,
|
||||
count,
|
||||
program_header,
|
||||
hole_size);
|
||||
LOG_IF(FATAL, alignment_changes > 1)
|
||||
<< "Changed p_align on more than one LOAD segment";
|
||||
}
|
||||
|
||||
VLOG(1) << "phdr[" << i
|
||||
<< "] p_vaddr adjusted to "<< program_header->p_vaddr
|
||||
<< "; p_paddr adjusted to "<< program_header->p_paddr
|
||||
@@ -383,10 +456,10 @@ static void RewriteProgramHeadersForHole(Elf* elf,
|
||||
target_load_header->p_memsz += hole_size;
|
||||
|
||||
// Adjust the offsets and p_vaddrs
|
||||
AdjustProgramHeaderOffsets<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
AdjustProgramHeaderFields<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Locate and return the dynamic section.
|
||||
|
||||
@@ -183,6 +183,18 @@ TEST(ElfFile, PackRelocationsArm64) {
|
||||
RunPackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsMips32) {
|
||||
RunPackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsIa32) {
|
||||
RunPackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, PackRelocationsX64) {
|
||||
RunPackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsArm32) {
|
||||
RunUnpackRelocationsTestFor("arm32");
|
||||
}
|
||||
@@ -191,4 +203,16 @@ TEST(ElfFile, UnpackRelocationsArm64) {
|
||||
RunUnpackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsMips32) {
|
||||
RunUnpackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsIa32) {
|
||||
RunUnpackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsX64) {
|
||||
RunUnpackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
Executable file
Binary file not shown.
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
Executable file
BIN
tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
Executable file
Binary file not shown.
Reference in New Issue
Block a user