Compare commits
193 Commits
android-we
...
android-m-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d717b1a3e5 | ||
|
|
79fd668bb4 | ||
|
|
560aacee84 | ||
|
|
1011e1a402 | ||
|
|
fad15145f8 | ||
|
|
41c99cdbb9 | ||
|
|
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 | ||
|
|
1d76f1cc8b | ||
|
|
42502d702e | ||
|
|
2eaff07839 | ||
|
|
f327fae69c | ||
|
|
9a2744df30 | ||
|
|
d1aea30b2a | ||
|
|
2c256a0f09 | ||
|
|
440242f038 | ||
|
|
e91e66f223 | ||
|
|
ea295f68f1 | ||
|
|
ebfb55e4cd | ||
|
|
6612d7a347 | ||
|
|
2bb93482a7 | ||
|
|
b0b9338ff8 | ||
|
|
6f88821e5d | ||
|
|
d2177404e2 | ||
|
|
6c63ee41ac | ||
|
|
094f58fb2a | ||
|
|
41ebceaf3a | ||
|
|
adfcb97317 | ||
|
|
e3ecedd306 | ||
|
|
0a93df369c | ||
|
|
3da9373fe0 | ||
|
|
7280e507b6 | ||
|
|
3391a9ff13 | ||
|
|
dc405b5230 | ||
|
|
6df122f852 | ||
|
|
ff18108981 | ||
|
|
18870d350c | ||
|
|
9ceec1a75d | ||
|
|
f15ceeb784 | ||
|
|
457c34ad84 | ||
|
|
913fe559f6 | ||
|
|
7592008030 | ||
|
|
2a6342187a | ||
|
|
a00a9f0b7e | ||
|
|
6fb8e96e5f | ||
|
|
da3c4f2f0d | ||
|
|
bb25bbe19e | ||
|
|
0776f0f6e2 | ||
|
|
3d7bea1fa0 | ||
|
|
3244d9f07f | ||
|
|
c5bd96efd2 | ||
|
|
72a6fdcdc7 | ||
|
|
af7538b496 | ||
|
|
4ae773633a | ||
|
|
7a8c7c48db | ||
|
|
21988a3b16 | ||
|
|
cb6ae56b3e | ||
|
|
d3fe4f1229 | ||
|
|
42281880a8 | ||
|
|
3875744f89 | ||
|
|
fc4850e37b | ||
|
|
2a81536144 | ||
|
|
a9325133aa | ||
|
|
31128da28f | ||
|
|
f84a5c6c5c | ||
|
|
a4061cddbe | ||
|
|
14af27a147 | ||
|
|
e7e1c875b0 | ||
|
|
a40cb0ca7f | ||
|
|
12d8902745 | ||
|
|
2587c6a2f0 | ||
|
|
95f1ee235a | ||
|
|
c0f89283cc | ||
|
|
43e020ce93 | ||
|
|
c6ccdfaf1f | ||
|
|
163ab8ba86 | ||
|
|
66aa0b61f7 | ||
|
|
cafc948069 | ||
|
|
940d3122c9 | ||
|
|
a529efac4e | ||
|
|
605ee81b06 | ||
|
|
8f3f04184a | ||
|
|
5ddbb3f936 | ||
|
|
447cd19681 | ||
|
|
a0ecd5b2b4 | ||
|
|
de88974120 | ||
|
|
c921eb6770 | ||
|
|
d032378790 | ||
|
|
9ce9bf5aec | ||
|
|
ef25592f14 | ||
|
|
c0e7dbb1db | ||
|
|
0a92ac8848 | ||
|
|
9f2c2f53d3 | ||
|
|
f9ff2eeaee | ||
|
|
aba687a09c | ||
|
|
694282b172 | ||
|
|
4d3abcb033 | ||
|
|
41efc92e35 | ||
|
|
5cf46f81ea | ||
|
|
76615dae93 | ||
|
|
dadac10fcc | ||
|
|
3da136aa47 |
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -63,14 +63,22 @@ libc_common_src_files := \
|
||||
stdio/sprintf.c \
|
||||
stdio/stdio.c \
|
||||
stdio/stdio_ext.cpp \
|
||||
stdlib/atexit.c \
|
||||
stdlib/exit.c \
|
||||
|
||||
# Fortify implementations of libc functions.
|
||||
libc_common_src_files += \
|
||||
bionic/__FD_chk.cpp \
|
||||
bionic/__fgets_chk.cpp \
|
||||
bionic/__memchr_chk.cpp \
|
||||
bionic/__memmove_chk.cpp \
|
||||
bionic/__memrchr_chk.cpp \
|
||||
bionic/__poll_chk.cpp \
|
||||
bionic/__pread64_chk.cpp \
|
||||
bionic/__pread_chk.cpp \
|
||||
bionic/__read_chk.cpp \
|
||||
bionic/__readlink_chk.cpp \
|
||||
bionic/__readlinkat_chk.cpp \
|
||||
bionic/__recvfrom_chk.cpp \
|
||||
bionic/__stpcpy_chk.cpp \
|
||||
bionic/__stpncpy_chk.cpp \
|
||||
@@ -104,6 +112,7 @@ libc_bionic_ndk_src_files := \
|
||||
bionic/clock_getcpuclockid.cpp \
|
||||
bionic/clock_nanosleep.cpp \
|
||||
bionic/clone.cpp \
|
||||
bionic/close.cpp \
|
||||
bionic/__cmsg_nxthdr.cpp \
|
||||
bionic/connect.cpp \
|
||||
bionic/ctype.cpp \
|
||||
@@ -122,6 +131,7 @@ libc_bionic_ndk_src_files := \
|
||||
bionic/ffs.cpp \
|
||||
bionic/flockfile.cpp \
|
||||
bionic/fpclassify.cpp \
|
||||
bionic/ftruncate.cpp \
|
||||
bionic/futimens.cpp \
|
||||
bionic/getcwd.cpp \
|
||||
bionic/gethostname.cpp \
|
||||
@@ -476,11 +486,9 @@ libc_upstream_openbsd_ndk_src_files := \
|
||||
upstream-openbsd/lib/libc/stdio/wprintf.c \
|
||||
upstream-openbsd/lib/libc/stdio/wscanf.c \
|
||||
upstream-openbsd/lib/libc/stdio/wsetup.c \
|
||||
upstream-openbsd/lib/libc/stdlib/atexit.c \
|
||||
upstream-openbsd/lib/libc/stdlib/atoi.c \
|
||||
upstream-openbsd/lib/libc/stdlib/atol.c \
|
||||
upstream-openbsd/lib/libc/stdlib/atoll.c \
|
||||
upstream-openbsd/lib/libc/stdlib/exit.c \
|
||||
upstream-openbsd/lib/libc/stdlib/getenv.c \
|
||||
upstream-openbsd/lib/libc/stdlib/insque.c \
|
||||
upstream-openbsd/lib/libc/stdlib/lsearch.c \
|
||||
@@ -820,12 +828,7 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := $(libc_upstream_openbsd_ndk_src_files)
|
||||
ifneq (,$(filter $(TARGET_ARCH),x86 x86_64))
|
||||
# Clang has wrong long double size or LDBL_MANT_DIG, http://b/17163651.
|
||||
LOCAL_CLANG := false
|
||||
else
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
endif
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
$(libc_common_cflags) \
|
||||
@@ -863,12 +866,7 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := $(libc_upstream_openbsd_src_files)
|
||||
ifneq (,$(filter $(TARGET_ARCH),x86 x86_64))
|
||||
# Clang has wrong long double size or LDBL_MANT_DIG, http://b/17163651.
|
||||
LOCAL_CLANG := false
|
||||
else
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
endif
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
$(libc_common_cflags) \
|
||||
@@ -908,12 +906,7 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES_32 := $(libc_upstream_openbsd_gdtoa_src_files_32)
|
||||
LOCAL_SRC_FILES_64 := $(libc_upstream_openbsd_gdtoa_src_files_64)
|
||||
ifneq (,$(filter $(TARGET_ARCH),x86 x86_64))
|
||||
# Clang has wrong long double size or LDBL_MANT_DIG, http://b/17163651.
|
||||
LOCAL_CLANG := false
|
||||
else
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
endif
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
$(libc_common_cflags) \
|
||||
@@ -949,13 +942,6 @@ LOCAL_SRC_FILES := $(libc_bionic_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# ssse3-strcmp-slm.S does not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
|
||||
@@ -983,13 +969,6 @@ LOCAL_SRC_FILES := $(libc_bionic_ndk_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# ssse3-strcmp-slm.S does not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
|
||||
@@ -1007,7 +986,7 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(libc_thread_atexit_impl_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -fno-data-sections -Wframe-larger-than=2048
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -Wframe-larger-than=2048
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
@@ -1038,13 +1017,6 @@ LOCAL_SRC_FILES := $(libc_pthread_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# ssse3-strcmp-slm.S does not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
@@ -1232,10 +1204,6 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
|
||||
@@ -1328,6 +1296,11 @@ LOCAL_MODULE := libc
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
LOCAL_ADDRESS_SANITIZER := false
|
||||
@@ -1349,10 +1322,13 @@ LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
LOCAL_SRC_FILES := \
|
||||
arch-common/bionic/crtbegin_so.c \
|
||||
arch-common/bionic/crtbrand.S \
|
||||
$(libc_arch_dynamic_src_files) \
|
||||
bionic/malloc_debug_common.cpp \
|
||||
bionic/libc_init_dynamic.cpp \
|
||||
bionic/NetdClient.cpp \
|
||||
arch-common/bionic/crtend_so.S \
|
||||
|
||||
LOCAL_MODULE := libc
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
@@ -1365,6 +1341,9 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
|
||||
# meaningful name resolution.
|
||||
LOCAL_STRIP_MODULE := keep_symbols
|
||||
|
||||
# Do not pack libc.so relocations; see http://b/20645321 for details.
|
||||
LOCAL_PACK_MODULE_RELOCATIONS := false
|
||||
|
||||
# WARNING: The only library libc.so should depend on is libdl.so! If you add other libraries,
|
||||
# make sure to add -Wl,--exclude-libs=libgcc.a to the LOCAL_LDFLAGS for those libraries. This
|
||||
# ensures that symbols that are pulled into those new libraries from libgcc.a are not declared
|
||||
@@ -1375,6 +1354,11 @@ LOCAL_STRIP_MODULE := keep_symbols
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libdl
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
|
||||
@@ -1384,23 +1368,23 @@ LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
|
||||
# We'd really like to do this for all architectures, but since this wasn't done
|
||||
# before, these symbols must continue to be exported on LP32 for binary
|
||||
# compatibility.
|
||||
# TODO: disabled for http://b/20065774.
|
||||
#LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
|
||||
LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
|
||||
|
||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
|
||||
|
||||
LOCAL_NO_CRT := true
|
||||
LOCAL_ASFLAGS += $(libc_crt_target_cflags)
|
||||
|
||||
# special for arm
|
||||
LOCAL_NO_CRT_arm := true
|
||||
LOCAL_CFLAGS_arm += -DCRT_LEGACY_WORKAROUND
|
||||
LOCAL_ASFLAGS_arm += $(libc_crt_target_cflags)
|
||||
LOCAL_SRC_FILES_arm += \
|
||||
arch-common/bionic/crtbegin_so.c \
|
||||
arch-common/bionic/crtbrand.S \
|
||||
arch-arm/bionic/atexit_legacy.c \
|
||||
arch-common/bionic/crtend_so.S
|
||||
arch-arm/bionic/atexit_legacy.c
|
||||
|
||||
LOCAL_ADDRESS_SANITIZER := false
|
||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
|
||||
|
||||
@@ -1518,7 +1502,8 @@ LOCAL_CFLAGS := $(libc_common_cflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
|
||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
|
||||
LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
|
||||
LOCAL_MODULE:= libstdc++
|
||||
|
||||
156
libc/NOTICE
156
libc/NOTICE
@@ -307,34 +307,6 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2008-2010 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -454,22 +426,6 @@ Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2011 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2011 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
@@ -688,6 +644,50 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1980, 1983, 1988, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
@@ -2550,33 +2550,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1995, 1996 Carnegie-Mellon University.
|
||||
All rights reserved.
|
||||
|
||||
Author: Chris G. Demetriou
|
||||
|
||||
Permission to use, copy, modify and distribute this software and
|
||||
its documentation is hereby granted, provided that both the copyright
|
||||
notice and this permission notice appear in all copies of the
|
||||
software, derivative works or modified versions, and any portions
|
||||
thereof, and that both notices appear in supporting documentation.
|
||||
|
||||
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
||||
FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
|
||||
Carnegie Mellon requests users of this software to return to
|
||||
|
||||
Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
School of Computer Science
|
||||
Carnegie Mellon University
|
||||
Pittsburgh PA 15213-3890
|
||||
|
||||
any improvements or extensions that they make and grant Carnegie the
|
||||
rights to redistribute these changes.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1996 by Internet Software Consortium.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -3795,6 +3768,22 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2007-2008 Michael G Schwern
|
||||
|
||||
This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
|
||||
@@ -4733,31 +4722,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 2000 David E. O'Brien, John D. Polstra.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 2008 Android Open Source Project (source port randomization)
|
||||
Copyright (c) 1985, 1989, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
@@ -95,7 +95,7 @@ ssize_t pread64(int, void*, size_t, off64_t) arm,mips,x86
|
||||
ssize_t pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
|
||||
ssize_t pwrite64(int, void*, size_t, off64_t) arm,mips,x86
|
||||
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
|
||||
int close(int) all
|
||||
int ___close:close(int) all
|
||||
pid_t __getpid:getpid() all
|
||||
int munmap(void*, size_t) all
|
||||
void* mremap(void*, size_t, size_t, unsigned long) all
|
||||
@@ -151,7 +151,6 @@ int utimensat(int, const char*, const struct timespec times[2], int) all
|
||||
off_t lseek(int, off_t, int) arm,mips,x86
|
||||
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
|
||||
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
|
||||
int ftruncate(int, off_t) arm,mips,x86
|
||||
int ftruncate64(int, off64_t) arm,mips,x86
|
||||
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
|
||||
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
|
||||
@@ -223,7 +222,7 @@ int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
|
||||
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
|
||||
int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all
|
||||
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all
|
||||
int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
|
||||
int ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
|
||||
int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all
|
||||
|
||||
# sockets
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 The Android Open Source Project
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/cortex-a15/bionic/memcpy.S \
|
||||
arch-arm/cortex-a15/bionic/memset.S \
|
||||
arch-arm/cortex-a15/bionic/stpcpy.S \
|
||||
@@ -10,5 +9,8 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
|
||||
arch-arm/cortex-a15/bionic/strlen.S \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/denver/bionic/memmove.S \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
*/
|
||||
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
@@ -100,9 +101,9 @@ ENTRY(memset)
|
||||
1: bge 2f
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
strmib r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
END(memset)
|
||||
@@ -131,11 +132,11 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
orr r1, r1, r1, lsr #16
|
||||
|
||||
movs r12, r3, lsl #31
|
||||
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strcsb r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strbcs r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
subs r2, r2, r3
|
||||
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
|
||||
popls {r0, r4-r7, lr} /* return */
|
||||
bxls lr
|
||||
|
||||
/* align the destination to a cache-line */
|
||||
@@ -155,9 +156,9 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
|
||||
/* conditionally writes 0 to 7 words (length in r3) */
|
||||
movs r3, r3, lsl #28
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
movs r3, r3, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
|
||||
@@ -172,13 +173,13 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
|
||||
/* conditionally stores 0 to 31 bytes */
|
||||
movs r2, r2, lsl #28
|
||||
stmcsia r0!, {r1,r3,r12,lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
stmcs r0!, {r1,r3,r12,lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
movs r2, r2, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
strmih r1, [r0], #2
|
||||
strhmi r1, [r0], #2
|
||||
movs r2, r2, lsl #2
|
||||
strcsb r1, [r0]
|
||||
strbcs r1, [r0]
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(__memset_large_copy)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/cortex-a9/bionic/memcpy.S \
|
||||
arch-arm/cortex-a9/bionic/memset.S \
|
||||
arch-arm/cortex-a9/bionic/stpcpy.S \
|
||||
@@ -10,5 +9,8 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/cortex-a9/bionic/__strcpy_chk.S \
|
||||
arch-arm/cortex-a9/bionic/strlen.S \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/denver/bionic/memmove.S \
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
* Optimized memcmp() for Cortex-A9.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(memcmp)
|
||||
pld [r0, #(CACHE_LINE_SIZE * 0)]
|
||||
pld [r0, #(CACHE_LINE_SIZE * 1)]
|
||||
@@ -161,25 +163,25 @@ ENTRY(memcmp)
|
||||
eors r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eoreqs r0, r0, lr
|
||||
eorseq r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eoreqs r0, r0, lr
|
||||
eorseq r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eoreqs r0, r0, lr
|
||||
eorseq r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eoreqs r0, r0, lr
|
||||
eorseq r0, r0, lr
|
||||
bne 2f
|
||||
subs r2, r2, #32
|
||||
bhs 0b
|
||||
@@ -263,17 +265,17 @@ ENTRY(memcmp)
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
moveq ip, lr, lsr #16
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
moveq ip, lr, lsr #16
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
bne 7f
|
||||
subs r2, r2, #16
|
||||
bhs 6b
|
||||
@@ -317,7 +319,7 @@ ENTRY(memcmp)
|
||||
ldreq r7, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, r7, lsl r6
|
||||
eoreqs r0, r0, ip
|
||||
eorseq r0, r0, ip
|
||||
bne 7f
|
||||
subs r2, r2, #8
|
||||
bhs 6b
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
* so we have to preserve R0.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memcpy_chk)
|
||||
cmp r2, r3
|
||||
bhi __memcpy_chk_fail
|
||||
@@ -81,12 +83,12 @@ ENTRY(memcpy)
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb r4, [r1], #1
|
||||
ldrcsb r12,[r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb r4, [r0], #1
|
||||
strcsb r12,[r0], #1
|
||||
ldrbmi r3, [r1], #1
|
||||
ldrbcs r4, [r1], #1
|
||||
ldrbcs r12,[r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
strbcs r4, [r0], #1
|
||||
strbcs r12,[r0], #1
|
||||
|
||||
.Lsrc_aligned:
|
||||
|
||||
@@ -109,10 +111,10 @@ ENTRY(memcpy)
|
||||
|
||||
/* conditionally copies 0 to 7 words (length in r3) */
|
||||
movs r12, r3, lsl #28
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmi r1!, {r8, r9} /* 8 bytes */
|
||||
stmcs r0!, {r4, r5, r6, r7}
|
||||
stmmi r0!, {r8, r9}
|
||||
tst r3, #0x4
|
||||
ldrne r10,[r1], #4 /* 4 bytes */
|
||||
strne r10,[r0], #4
|
||||
@@ -177,18 +179,18 @@ ENTRY(memcpy)
|
||||
|
||||
/* conditionnaly copies 0 to 31 bytes */
|
||||
movs r12, r2, lsl #28
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmi r1!, {r8, r9} /* 8 bytes */
|
||||
stmcs r0!, {r4, r5, r6, r7}
|
||||
stmmi r0!, {r8, r9}
|
||||
movs r12, r2, lsl #30
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
ldrmih r4, [r1], #2 /* 2 bytes */
|
||||
ldrhmi r4, [r1], #2 /* 2 bytes */
|
||||
strcs r3, [r0], #4
|
||||
strmih r4, [r0], #2
|
||||
strhmi r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
ldrneb r3, [r1] /* last byte */
|
||||
strneb r3, [r0]
|
||||
ldrbne r3, [r1] /* last byte */
|
||||
strbne r3, [r0]
|
||||
|
||||
/* we're done! restore everything and return */
|
||||
1: ldmfd sp!, {r5-r11}
|
||||
@@ -228,11 +230,11 @@ ENTRY(memcpy)
|
||||
* becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
|
||||
*/
|
||||
movs r5, r5, lsl #31
|
||||
strmib r3, [r0], #1
|
||||
strbmi r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
|
||||
cmp r2, #4
|
||||
@@ -363,23 +365,23 @@ ENTRY(memcpy)
|
||||
.Lpartial_word_tail:
|
||||
/* we have a partial word in the input buffer */
|
||||
movs r5, lr, lsl #(31-3)
|
||||
strmib r3, [r0], #1
|
||||
strbmi r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strcsb r3, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
|
||||
/* Refill spilled registers from the stack. Don't update sp. */
|
||||
ldmfd sp, {r5-r11}
|
||||
|
||||
.Lcopy_last_3_and_return:
|
||||
movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
|
||||
ldrmib r2, [r1], #1
|
||||
ldrcsb r3, [r1], #1
|
||||
ldrcsb r12,[r1]
|
||||
strmib r2, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
strcsb r12,[r0]
|
||||
ldrbmi r2, [r1], #1
|
||||
ldrbcs r3, [r1], #1
|
||||
ldrbcs r12,[r1]
|
||||
strbmi r2, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
strbcs r12,[r0]
|
||||
|
||||
/* we're done! restore sp and spilled registers and return */
|
||||
add sp, sp, #28
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
* memset() returns its first argument.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
bls done
|
||||
@@ -76,11 +78,11 @@ ENTRY(memset)
|
||||
orr r1, r1, r1, lsr #16
|
||||
|
||||
movs r12, r3, lsl #31
|
||||
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strcsb r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strbcs r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
subs r2, r2, r3
|
||||
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
|
||||
popls {r0, r4-r7, lr} /* return */
|
||||
bxls lr
|
||||
|
||||
/* align the destination to a cache-line */
|
||||
@@ -100,9 +102,9 @@ ENTRY(memset)
|
||||
|
||||
/* conditionally writes 0 to 7 words (length in r3) */
|
||||
movs r3, r3, lsl #28
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
movs r3, r3, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
|
||||
@@ -117,13 +119,13 @@ ENTRY(memset)
|
||||
|
||||
/* conditionally stores 0 to 31 bytes */
|
||||
movs r2, r2, lsl #28
|
||||
stmcsia r0!, {r1,r3,r12,lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
stmcs r0!, {r1,r3,r12,lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
movs r2, r2, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
strmih r1, [r0], #2
|
||||
strhmi r1, [r0], #2
|
||||
movs r2, r2, lsl #2
|
||||
strcsb r1, [r0]
|
||||
strbcs r1, [r0]
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(memset)
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <machine/cpu-features.h>
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(strcpy)
|
||||
pld [r1, #0]
|
||||
eor r2, r0, r1
|
||||
@@ -108,15 +110,15 @@ ENTRY(strcpy)
|
||||
#ifdef __ARMEB__
|
||||
tst r2, #0xff00
|
||||
iteet ne
|
||||
strneh r2, [ip], #2
|
||||
strhne r2, [ip], #2
|
||||
lsreq r2, r2, #8
|
||||
streqb r2, [ip]
|
||||
strbeq r2, [ip]
|
||||
tstne r2, #0xff
|
||||
#else
|
||||
tst r2, #0xff
|
||||
itet ne
|
||||
strneh r2, [ip], #2
|
||||
streqb r2, [ip]
|
||||
strhne r2, [ip], #2
|
||||
strbeq r2, [ip]
|
||||
tstne r2, #0xff00
|
||||
#endif
|
||||
bne 5b
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
*/
|
||||
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
@@ -98,9 +99,9 @@ ENTRY(memset)
|
||||
1: bge 2f
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
strmib r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
END(memset)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
arch-arm/krait/bionic/memcpy.S \
|
||||
arch-arm/krait/bionic/memset.S \
|
||||
arch-arm/krait/bionic/strcmp.S \
|
||||
@@ -13,5 +12,8 @@ libc_bionic_src_files_arm += \
|
||||
arch-arm/cortex-a15/bionic/strcpy.S \
|
||||
arch-arm/cortex-a15/bionic/strlen.S \
|
||||
|
||||
libc_openbsd_src_files_arm += \
|
||||
upstream-openbsd/lib/libc/string/memmove.c \
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/generic/bionic/memcmp.S \
|
||||
|
||||
libc_bionic_src_files_arm += \
|
||||
arch-arm/denver/bionic/memmove.S \
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_close
|
||||
swi #0
|
||||
@@ -11,4 +11,5 @@ ENTRY(close)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_rt_sigqueueinfo
|
||||
swi #0
|
||||
@@ -11,4 +11,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(__rt_sigqueueinfo)
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -1,14 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(ftruncate)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_ftruncate
|
||||
swi #0
|
||||
mov r7, ip
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(ftruncate)
|
||||
@@ -40,8 +40,6 @@ libc_bionic_src_files_arm64 += \
|
||||
arch-arm64/bionic/syscall.S \
|
||||
arch-arm64/bionic/vfork.S \
|
||||
|
||||
# Work around for http://b/20065774.
|
||||
libc_bionic_src_files_arm64 += arch-arm64/bionic/libgcc_compat.c
|
||||
|
||||
libc_crt_target_cflags_arm64 := \
|
||||
-I$(LOCAL_PATH)/arch-arm64/include
|
||||
|
||||
@@ -67,3 +67,4 @@ __asm__ (
|
||||
|
||||
#include "../../arch-common/bionic/__dso_handle.h"
|
||||
#include "../../arch-common/bionic/atexit.h"
|
||||
#include "../../arch-common/bionic/pthread_atfork.h"
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/* STOPSHIP: remove this once the flounder blobs have been rebuilt (http://b/20065774). */
|
||||
|
||||
#if !defined(__clang__)
|
||||
|
||||
extern void __clear_cache(char*, char*);
|
||||
extern char _Unwind_Backtrace;
|
||||
extern char _Unwind_GetIP;
|
||||
|
||||
void* __bionic_libgcc_compat_symbols[] = {
|
||||
&__clear_cache,
|
||||
&_Unwind_Backtrace,
|
||||
&_Unwind_GetIP,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -101,7 +101,7 @@ ENTRY(memchr)
|
||||
and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
|
||||
addp vend.16b, vhas_chr1.16b, vhas_chr2.16b /* 256->128 */
|
||||
addp vend.16b, vend.16b, vend.16b /* 128->64 */
|
||||
mov synd, vend.2d[0]
|
||||
mov synd, vend.d[0]
|
||||
/* Clear the soff*2 lower bits */
|
||||
lsl tmp, soff, #1
|
||||
lsr synd, synd, tmp
|
||||
@@ -121,7 +121,7 @@ ENTRY(memchr)
|
||||
/* Use a fast check for the termination condition */
|
||||
orr vend.16b, vhas_chr1.16b, vhas_chr2.16b
|
||||
addp vend.2d, vend.2d, vend.2d
|
||||
mov synd, vend.2d[0]
|
||||
mov synd, vend.d[0]
|
||||
/* We're not out of data, loop if we haven't found the character */
|
||||
cbz synd, .Lloop
|
||||
|
||||
@@ -131,7 +131,7 @@ ENTRY(memchr)
|
||||
and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
|
||||
addp vend.16b, vhas_chr1.16b, vhas_chr2.16b /* 256->128 */
|
||||
addp vend.16b, vend.16b, vend.16b /* 128->64 */
|
||||
mov synd, vend.2d[0]
|
||||
mov synd, vend.d[0]
|
||||
/* Only do the clear for the last possible block */
|
||||
b.hi .Ltail
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ ENTRY(strchr)
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 128->64
|
||||
lsr tmp1, tmp3, tmp1
|
||||
|
||||
mov tmp3, vend1.2d[0]
|
||||
mov tmp3, vend1.d[0]
|
||||
bic tmp1, tmp3, tmp1 // Mask padding bits.
|
||||
cbnz tmp1, .Ltail
|
||||
|
||||
@@ -124,7 +124,7 @@ ENTRY(strchr)
|
||||
orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
|
||||
orr vend1.16b, vend1.16b, vend2.16b
|
||||
addp vend1.2d, vend1.2d, vend1.2d
|
||||
mov tmp1, vend1.2d[0]
|
||||
mov tmp1, vend1.d[0]
|
||||
cbz tmp1, .Lloop
|
||||
|
||||
/* Termination condition found. Now need to establish exactly why
|
||||
@@ -138,7 +138,7 @@ ENTRY(strchr)
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 256->128
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 128->64
|
||||
|
||||
mov tmp1, vend1.2d[0]
|
||||
mov tmp1, vend1.d[0]
|
||||
.Ltail:
|
||||
/* Count the trailing zeros, by bit reversing... */
|
||||
rbit tmp1, tmp1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
mov x8, __NR_close
|
||||
svc #0
|
||||
|
||||
@@ -11,4 +11,5 @@ ENTRY(close)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
mov x8, __NR_rt_sigqueueinfo
|
||||
svc #0
|
||||
|
||||
@@ -11,5 +11,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(__rt_sigqueueinfo)
|
||||
.hidden __rt_sigqueueinfo
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
#ifdef __LP64__
|
||||
# define ASM_PTR_SIZE(x) .quad x
|
||||
# define ASM_ALIGN(x)
|
||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 8
|
||||
#else
|
||||
# define ASM_PTR_SIZE(x) .long x
|
||||
# define ASM_ALIGN(x) .align x
|
||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 4
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ void _start() {
|
||||
|
||||
#include "__dso_handle.h"
|
||||
#include "atexit.h"
|
||||
#include "pthread_atfork.h"
|
||||
#ifdef __i386__
|
||||
# include "../../arch-x86/bionic/__stack_chk_fail_local.h"
|
||||
#endif
|
||||
|
||||
@@ -56,6 +56,7 @@ void __on_dlclose() {
|
||||
# include "__dso_handle_so.h"
|
||||
# include "atexit.h"
|
||||
#endif
|
||||
#include "pthread_atfork.h"
|
||||
#ifdef __i386__
|
||||
# include "../../arch-x86/bionic/__stack_chk_fail_local.h"
|
||||
#endif
|
||||
|
||||
@@ -29,12 +29,15 @@
|
||||
#include "asm_multiarch.h"
|
||||
|
||||
.section .preinit_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .init_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .fini_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
@@ -42,7 +45,9 @@
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
.section .eh_frame,"a",@progbits
|
||||
ASM_ALIGN(4)
|
||||
#if defined(__i386__)
|
||||
.balign 4
|
||||
#endif
|
||||
.type __FRAME_END__, @object
|
||||
.size __FRAME_END__, 4
|
||||
__FRAME_END__:
|
||||
|
||||
@@ -26,22 +26,14 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "asm_multiarch.h"
|
||||
|
||||
#ifndef __arm__
|
||||
.section .init_array, "aw"
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .fini_array, "aw"
|
||||
ASM_PTR_SIZE(0)
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
.section .eh_frame,"a",@progbits
|
||||
ASM_ALIGN(4)
|
||||
#if defined(__i386__)
|
||||
.balign 4
|
||||
#endif
|
||||
.type __FRAME_END__, @object
|
||||
.size __FRAME_END__, 4
|
||||
__FRAME_END__:
|
||||
|
||||
29
libc/arch-common/bionic/pthread_atfork.h
Normal file
29
libc/arch-common/bionic/pthread_atfork.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern void* __dso_handle;
|
||||
|
||||
extern int __register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void), void* dso);
|
||||
|
||||
#ifndef _LIBC
|
||||
// Libc used to export this in previous versions, therefore it needs
|
||||
// to remain global for binary compatibility.
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
#endif
|
||||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) {
|
||||
return __register_atfork(prepare, parent, child, &__dso_handle);
|
||||
}
|
||||
|
||||
@@ -92,3 +92,4 @@ __asm__ (
|
||||
|
||||
#include "../../arch-common/bionic/__dso_handle.h"
|
||||
#include "../../arch-common/bionic/atexit.h"
|
||||
#include "../../arch-common/bionic/pthread_atfork.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 The Android Open Source Project
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_close
|
||||
@@ -16,4 +16,5 @@ ENTRY(close)
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_rt_sigqueueinfo
|
||||
@@ -16,4 +16,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(__rt_sigqueueinfo)
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -1,19 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(ftruncate)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_ftruncate
|
||||
syscall
|
||||
bnez a3, 1f
|
||||
move a0, v0
|
||||
j ra
|
||||
nop
|
||||
1:
|
||||
la t9,__set_errno_internal
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(ftruncate)
|
||||
@@ -92,3 +92,4 @@ __asm__ (
|
||||
|
||||
#include "../../arch-common/bionic/__dso_handle.h"
|
||||
#include "../../arch-common/bionic/atexit.h"
|
||||
#include "../../arch-common/bionic/pthread_atfork.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_close
|
||||
@@ -22,4 +22,5 @@ ENTRY(close)
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_rt_sigqueueinfo
|
||||
@@ -22,5 +22,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(__rt_sigqueueinfo)
|
||||
.hidden __rt_sigqueueinfo
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -3,8 +3,14 @@
|
||||
// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
|
||||
ENTRY(__bionic_clone)
|
||||
pushl %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebx, 0
|
||||
pushl %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
pushl %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
|
||||
# Load system call arguments into registers.
|
||||
movl 16(%esp), %ebx # flags
|
||||
@@ -46,8 +52,14 @@ ENTRY(__bionic_clone)
|
||||
# We're the parent; nothing to do.
|
||||
.L_bc_return:
|
||||
popl %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
popl %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
popl %ebx
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
ret
|
||||
END(__bionic_clone)
|
||||
.hidden __bionic_clone
|
||||
|
||||
@@ -15,9 +15,17 @@
|
||||
ENTRY(syscall)
|
||||
# Push the callee save registers.
|
||||
push %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebx, 0
|
||||
push %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
push %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
push %ebp
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebp, 0
|
||||
|
||||
# Load all the arguments from the calling frame.
|
||||
# (Not all will be valid, depending on the syscall.)
|
||||
@@ -43,8 +51,16 @@ ENTRY(syscall)
|
||||
1:
|
||||
# Restore the callee save registers.
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebx
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
ret
|
||||
END(syscall)
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
ENTRY(vfork)
|
||||
popl %ecx // Grab the return address.
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ecx, 0
|
||||
movl $__NR_vfork, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
@@ -18,4 +18,5 @@ ENTRY(close)
|
||||
1:
|
||||
popl %ebx
|
||||
ret
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
@@ -28,4 +28,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(__rt_sigqueueinfo)
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -1,26 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(ftruncate)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
pushl %ecx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ecx, 0
|
||||
mov 12(%esp), %ebx
|
||||
mov 16(%esp), %ecx
|
||||
movl $__NR_ftruncate, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
jb 1f
|
||||
negl %eax
|
||||
pushl %eax
|
||||
call __set_errno_internal
|
||||
addl $4, %esp
|
||||
1:
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(ftruncate)
|
||||
@@ -1897,8 +1897,8 @@ L(strcmp_exitz):
|
||||
|
||||
.p2align 4
|
||||
L(Byte0):
|
||||
movzx (%rsi), %ecx
|
||||
movzx (%rdi), %eax
|
||||
movzbl (%rsi), %ecx
|
||||
movzbl (%rdi), %eax
|
||||
|
||||
sub %ecx, %eax
|
||||
ret
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(close)
|
||||
ENTRY(___close)
|
||||
movl $__NR_close, %eax
|
||||
syscall
|
||||
cmpq $-MAX_ERRNO, %rax
|
||||
@@ -12,4 +12,5 @@ ENTRY(close)
|
||||
call __set_errno_internal
|
||||
1:
|
||||
ret
|
||||
END(close)
|
||||
END(___close)
|
||||
.hidden ___close
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
movl $__NR_rt_sigqueueinfo, %eax
|
||||
syscall
|
||||
cmpq $-MAX_ERRNO, %rax
|
||||
@@ -12,5 +12,5 @@ ENTRY(__rt_sigqueueinfo)
|
||||
call __set_errno_internal
|
||||
1:
|
||||
ret
|
||||
END(__rt_sigqueueinfo)
|
||||
.hidden __rt_sigqueueinfo
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
@@ -22,7 +22,7 @@ struct thread_local_dtor {
|
||||
thread_local_dtor* next;
|
||||
};
|
||||
|
||||
__thread thread_local_dtor* thread_local_dtors = nullptr;
|
||||
static __thread thread_local_dtor* thread_local_dtors = nullptr;
|
||||
|
||||
extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
|
||||
thread_local_dtor* dtor = new thread_local_dtor();
|
||||
|
||||
39
libc/bionic/__memchr_chk.cpp
Normal file
39
libc/bionic/__memchr_chk.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <string.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" void* __memchr_chk(const void* s, int c, size_t n, size_t buf_size) {
|
||||
if (__predict_false(n > buf_size)) {
|
||||
__fortify_chk_fail("memchr: prevented read past end of buffer", 0);
|
||||
}
|
||||
|
||||
return memchr(s, c, n);
|
||||
}
|
||||
39
libc/bionic/__memrchr_chk.cpp
Normal file
39
libc/bionic/__memrchr_chk.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <string.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" void* __memrchr_chk(const void* s, int c, size_t n, size_t buf_size) {
|
||||
if (__predict_false(n > buf_size)) {
|
||||
__fortify_chk_fail("memrchr: prevented read past end of buffer", 0);
|
||||
}
|
||||
|
||||
return memrchr(s, c, n);
|
||||
}
|
||||
43
libc/bionic/__pread64_chk.cpp
Normal file
43
libc/bionic/__pread64_chk.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <unistd.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" ssize_t __pread64_chk(int fd, void* buf, size_t count, off64_t offset, size_t buf_size) {
|
||||
if (__predict_false(count > buf_size)) {
|
||||
__fortify_chk_fail("pread64: prevented write past end of buffer", 0);
|
||||
}
|
||||
|
||||
if (__predict_false(count > SSIZE_MAX)) {
|
||||
__fortify_chk_fail("pread64: count > SSIZE_MAX", 0);
|
||||
}
|
||||
|
||||
return pread64(fd, buf, count, offset);
|
||||
}
|
||||
43
libc/bionic/__pread_chk.cpp
Normal file
43
libc/bionic/__pread_chk.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <unistd.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" ssize_t __pread_chk(int fd, void* buf, size_t count, off_t offset, size_t buf_size) {
|
||||
if (__predict_false(count > buf_size)) {
|
||||
__fortify_chk_fail("pread: prevented write past end of buffer", 0);
|
||||
}
|
||||
|
||||
if (__predict_false(count > SSIZE_MAX)) {
|
||||
__fortify_chk_fail("pread: count > SSIZE_MAX", 0);
|
||||
}
|
||||
|
||||
return pread(fd, buf, count, offset);
|
||||
}
|
||||
43
libc/bionic/__readlink_chk.cpp
Normal file
43
libc/bionic/__readlink_chk.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <unistd.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" ssize_t __readlink_chk(const char* path, char* buf, size_t size, size_t buf_size) {
|
||||
if (__predict_false(size > buf_size)) {
|
||||
__fortify_chk_fail("readlink: prevented write past end of buffer", 0);
|
||||
}
|
||||
|
||||
if (__predict_false(size > SSIZE_MAX)) {
|
||||
__fortify_chk_fail("readlink: size > SSIZE_MAX", 0);
|
||||
}
|
||||
|
||||
return readlink(path, buf, size);
|
||||
}
|
||||
43
libc/bionic/__readlinkat_chk.cpp
Normal file
43
libc/bionic/__readlinkat_chk.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
#include <unistd.h>
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" ssize_t __readlinkat_chk(int dirfd, const char* path, char* buf, size_t size, size_t buf_size) {
|
||||
if (__predict_false(size > buf_size)) {
|
||||
__fortify_chk_fail("readlinkat: prevented write past end of buffer", 0);
|
||||
}
|
||||
|
||||
if (__predict_false(size > SSIZE_MAX)) {
|
||||
__fortify_chk_fail("readlinkat: size > SSIZE_MAX", 0);
|
||||
}
|
||||
|
||||
return readlinkat(dirfd, path, buf, size);
|
||||
}
|
||||
56
libc/bionic/close.cpp
Normal file
56
libc/bionic/close.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" int ___close(int);
|
||||
|
||||
int close(int fd) {
|
||||
int rc = ___close(fd);
|
||||
if (rc == -1 && errno == EINTR) {
|
||||
// POSIX says that if close returns with EINTR, the fd must not be closed.
|
||||
// Linus disagrees: http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
|
||||
// The future POSIX solution is posix_close (http://austingroupbugs.net/view.php?id=529),
|
||||
// with the state after EINTR being undefined, and EINPROGRESS for the case where close
|
||||
// was interrupted by a signal but the file descriptor was actually closed.
|
||||
// My concern with that future behavior is that it breaks existing code that assumes
|
||||
// that close only returns -1 if it failed. Unlike other system calls, I have real
|
||||
// difficulty even imagining a caller that would need to know that close was interrupted
|
||||
// but succeeded. So returning EINTR is wrong (because Linux always closes) and EINPROGRESS
|
||||
// is harmful because callers need to be rewritten to understand that EINPROGRESS isn't
|
||||
// actually a failure, but will be reported as one.
|
||||
|
||||
// We don't restore errno because that would incur a cost (the TLS read) for every caller.
|
||||
// Since callers don't know ahead of time whether close will legitimately fail, they need
|
||||
// to have stashed the old errno value anyway if they plan on using it afterwards, so
|
||||
// us clobbering errno here doesn't change anything in that respect.
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
28
libc/bionic/ftruncate.cpp
Normal file
28
libc/bionic/ftruncate.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__USE_FILE_OFFSET64) && !defined(__LP64__)
|
||||
// The kernel's implementation of ftruncate uses an unsigned long for the length
|
||||
// parameter, so it will not catch negative values. On the other hand
|
||||
// ftruncate64 does check for this, so just forward the call.
|
||||
int ftruncate(int filedes, off_t length) {
|
||||
return ftruncate64(filedes, length);
|
||||
}
|
||||
#endif
|
||||
@@ -26,6 +26,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -56,6 +56,7 @@ enum AndroidEventLogType {
|
||||
EVENT_TYPE_LONG = 1,
|
||||
EVENT_TYPE_STRING = 2,
|
||||
EVENT_TYPE_LIST = 3,
|
||||
EVENT_TYPE_FLOAT = 4,
|
||||
};
|
||||
|
||||
struct BufferOutputStream {
|
||||
|
||||
@@ -26,14 +26,15 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "pthread_internal.h"
|
||||
#include "private/bionic_futex.h"
|
||||
#include "private/kernel_sigset_t.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// System calls.
|
||||
extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const struct timespec*, size_t);
|
||||
@@ -59,11 +60,11 @@ struct PosixTimer {
|
||||
|
||||
int sigev_notify;
|
||||
|
||||
// These fields are only needed for a SIGEV_THREAD timer.
|
||||
// The fields below are only needed for a SIGEV_THREAD timer.
|
||||
pthread_t callback_thread;
|
||||
void (*callback)(sigval_t);
|
||||
sigval_t callback_argument;
|
||||
volatile bool armed;
|
||||
atomic_bool deleted; // Set when the timer is deleted, to prevent further calling of callback.
|
||||
};
|
||||
|
||||
static __kernel_timer_t to_kernel_timer_id(timer_t timer) {
|
||||
@@ -85,8 +86,13 @@ static void* __timer_thread_start(void* arg) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (si.si_code == SI_TIMER && timer->armed) {
|
||||
if (si.si_code == SI_TIMER) {
|
||||
// This signal was sent because a timer fired, so call the callback.
|
||||
|
||||
// All events to the callback will be ignored when the timer is deleted.
|
||||
if (atomic_load(&timer->deleted) == true) {
|
||||
continue;
|
||||
}
|
||||
timer->callback(timer->callback_argument);
|
||||
} else if (si.si_code == SI_TKILL) {
|
||||
// This signal was sent because someone wants us to exit.
|
||||
@@ -97,9 +103,7 @@ static void* __timer_thread_start(void* arg) {
|
||||
}
|
||||
|
||||
static void __timer_thread_stop(PosixTimer* timer) {
|
||||
// Immediately mark the timer as disarmed so even if some events
|
||||
// continue to happen, the callback won't be called.
|
||||
timer->armed = false;
|
||||
atomic_store(&timer->deleted, true);
|
||||
pthread_kill(timer->callback_thread, TIMER_SIGNAL);
|
||||
}
|
||||
|
||||
@@ -126,7 +130,7 @@ int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) {
|
||||
// Otherwise, this must be SIGEV_THREAD timer...
|
||||
timer->callback = evp->sigev_notify_function;
|
||||
timer->callback_argument = evp->sigev_value;
|
||||
timer->armed = false;
|
||||
atomic_init(&timer->deleted, false);
|
||||
|
||||
// Check arguments that the kernel doesn't care about but we do.
|
||||
if (timer->callback == NULL) {
|
||||
@@ -170,10 +174,10 @@ int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Give the thread a meaningful name.
|
||||
// Give the thread a specific meaningful name.
|
||||
// It can't do this itself because the kernel timer isn't created until after it's running.
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "POSIX interval timer %d", to_kernel_timer_id(timer));
|
||||
char name[16]; // 16 is the kernel-imposed limit.
|
||||
snprintf(name, sizeof(name), "POSIX timer %d", to_kernel_timer_id(timer));
|
||||
pthread_setname_np(timer->callback_thread, name);
|
||||
|
||||
*timer_id = timer;
|
||||
@@ -199,25 +203,19 @@ int timer_delete(timer_t id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html
|
||||
int timer_gettime(timer_t id, itimerspec* ts) {
|
||||
return __timer_gettime(to_kernel_timer_id(id), ts);
|
||||
}
|
||||
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html
|
||||
// When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small
|
||||
// period (like below 1ms), the kernel may continue to send events to the callback thread
|
||||
// for a few extra times. This behavior is fine because in POSIX standard: The effect of
|
||||
// disarming or resetting a timer with pending expiration notifications is unspecified.
|
||||
int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) {
|
||||
PosixTimer* timer= reinterpret_cast<PosixTimer*>(id);
|
||||
int rc = __timer_settime(timer->kernel_timer_id, flags, ts, ots);
|
||||
if (rc == 0) {
|
||||
// Mark the timer as either being armed or disarmed. This avoids the
|
||||
// callback being called after the disarm for SIGEV_THREAD timers only.
|
||||
if (ts->it_value.tv_sec != 0 || ts->it_value.tv_nsec != 0) {
|
||||
timer->armed = true;
|
||||
} else {
|
||||
timer->armed = false;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
return __timer_settime(timer->kernel_timer_id, flags, ts, ots);
|
||||
}
|
||||
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "private/bionic_macros.h"
|
||||
|
||||
struct atfork_t {
|
||||
atfork_t* next;
|
||||
atfork_t* prev;
|
||||
@@ -37,79 +39,143 @@ struct atfork_t {
|
||||
void (*prepare)(void);
|
||||
void (*child)(void);
|
||||
void (*parent)(void);
|
||||
|
||||
void* dso_handle;
|
||||
};
|
||||
|
||||
struct atfork_list_t {
|
||||
atfork_t* first;
|
||||
atfork_t* last;
|
||||
class atfork_list_t {
|
||||
public:
|
||||
atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
|
||||
template<typename F>
|
||||
void walk_forward(F f) {
|
||||
for (atfork_t* it = first_; it != nullptr; it = it->next) {
|
||||
f(it);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void walk_backwards(F f) {
|
||||
for (atfork_t* it = last_; it != nullptr; it = it->prev) {
|
||||
f(it);
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(atfork_t* entry) {
|
||||
entry->next = nullptr;
|
||||
entry->prev = last_;
|
||||
if (entry->prev != nullptr) {
|
||||
entry->prev->next = entry;
|
||||
}
|
||||
if (first_ == nullptr) {
|
||||
first_ = entry;
|
||||
}
|
||||
last_ = entry;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void remove_if(F predicate) {
|
||||
atfork_t* it = first_;
|
||||
while (it != nullptr) {
|
||||
if (predicate(it)) {
|
||||
atfork_t* entry = it;
|
||||
it = it->next;
|
||||
remove(entry);
|
||||
} else {
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void remove(atfork_t* entry) {
|
||||
if (entry->prev != nullptr) {
|
||||
entry->prev->next = entry->next;
|
||||
} else {
|
||||
first_ = entry->next;
|
||||
}
|
||||
|
||||
if (entry->next != nullptr) {
|
||||
entry->next->prev = entry->prev;
|
||||
} else {
|
||||
last_ = entry->prev;
|
||||
}
|
||||
|
||||
free(entry);
|
||||
}
|
||||
|
||||
atfork_t* first_;
|
||||
atfork_t* last_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(atfork_list_t);
|
||||
};
|
||||
|
||||
static pthread_mutex_t g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
static atfork_list_t g_atfork_list = { NULL, NULL };
|
||||
static atfork_list_t g_atfork_list;
|
||||
|
||||
void __bionic_atfork_run_prepare() {
|
||||
// We lock the atfork list here, unlock it in the parent, and reset it in the child.
|
||||
// This ensures that nobody can modify the handler array between the calls
|
||||
// to the prepare and parent/child handlers.
|
||||
//
|
||||
// TODO: If a handler tries to mutate the list, they'll block. We should probably copy
|
||||
// the list before forking, and have prepare, parent, and child all work on the consistent copy.
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
|
||||
// Call pthread_atfork() prepare handlers. POSIX states that the prepare
|
||||
// handlers should be called in the reverse order of the parent/child
|
||||
// handlers, so we iterate backwards.
|
||||
for (atfork_t* it = g_atfork_list.last; it != NULL; it = it->prev) {
|
||||
if (it->prepare != NULL) {
|
||||
g_atfork_list.walk_backwards([](atfork_t* it) {
|
||||
if (it->prepare != nullptr) {
|
||||
it->prepare();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void __bionic_atfork_run_child() {
|
||||
for (atfork_t* it = g_atfork_list.first; it != NULL; it = it->next) {
|
||||
if (it->child != NULL) {
|
||||
g_atfork_list.walk_forward([](atfork_t* it) {
|
||||
if (it->child != nullptr) {
|
||||
it->child();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
}
|
||||
|
||||
void __bionic_atfork_run_parent() {
|
||||
for (atfork_t* it = g_atfork_list.first; it != NULL; it = it->next) {
|
||||
if (it->parent != NULL) {
|
||||
g_atfork_list.walk_forward([](atfork_t* it) {
|
||||
if (it->parent != nullptr) {
|
||||
it->parent();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
}
|
||||
|
||||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void)) {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
atfork_t* entry = reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t)));
|
||||
if (entry == NULL) {
|
||||
if (entry == nullptr) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->prepare = prepare;
|
||||
entry->parent = parent;
|
||||
entry->child = child;
|
||||
entry->dso_handle = dso;
|
||||
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
|
||||
// Append 'entry' to the list.
|
||||
entry->next = NULL;
|
||||
entry->prev = g_atfork_list.last;
|
||||
if (entry->prev != NULL) {
|
||||
entry->prev->next = entry;
|
||||
}
|
||||
if (g_atfork_list.first == NULL) {
|
||||
g_atfork_list.first = entry;
|
||||
}
|
||||
g_atfork_list.last = entry;
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void __unregister_atfork(void* dso) {
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
g_atfork_list.remove_if([&](const atfork_t* entry) {
|
||||
return entry->dso_handle == dso;
|
||||
});
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,15 @@ static inline bool SeqOfKeyInUse(uintptr_t seq) {
|
||||
return seq & (1 << SEQ_KEY_IN_USE_BIT);
|
||||
}
|
||||
|
||||
#define KEY_VALID_FLAG (1 << 31)
|
||||
|
||||
static_assert(sizeof(pthread_key_t) == sizeof(int) && static_cast<pthread_key_t>(-1) < 0,
|
||||
"pthread_key_t should be typedef to int");
|
||||
|
||||
static inline bool KeyInValidRange(pthread_key_t key) {
|
||||
return key >= 0 && key < BIONIC_PTHREAD_KEY_COUNT;
|
||||
// key < 0 means bit 31 is set.
|
||||
// Then key < (2^31 | BIONIC_PTHREAD_KEY_COUNT) means the index part of key < BIONIC_PTHREAD_KEY_COUNT.
|
||||
return (key < (KEY_VALID_FLAG | BIONIC_PTHREAD_KEY_COUNT));
|
||||
}
|
||||
|
||||
// Called from pthread_exit() to remove all pthread keys. This must call the destructor of
|
||||
@@ -114,7 +121,7 @@ int pthread_key_create(pthread_key_t* key, void (*key_destructor)(void*)) {
|
||||
while (!SeqOfKeyInUse(seq)) {
|
||||
if (atomic_compare_exchange_weak(&key_map[i].seq, &seq, seq + SEQ_INCREMENT_STEP)) {
|
||||
atomic_store(&key_map[i].key_destructor, reinterpret_cast<uintptr_t>(key_destructor));
|
||||
*key = i;
|
||||
*key = i | KEY_VALID_FLAG;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -127,9 +134,10 @@ int pthread_key_create(pthread_key_t* key, void (*key_destructor)(void*)) {
|
||||
// responsibility of the caller to properly dispose of the corresponding data
|
||||
// and resources, using any means it finds suitable.
|
||||
int pthread_key_delete(pthread_key_t key) {
|
||||
if (!KeyInValidRange(key)) {
|
||||
if (__predict_false(!KeyInValidRange(key))) {
|
||||
return EINVAL;
|
||||
}
|
||||
key &= ~KEY_VALID_FLAG;
|
||||
// Increase seq to invalidate values in all threads.
|
||||
uintptr_t seq = atomic_load_explicit(&key_map[key].seq, memory_order_relaxed);
|
||||
if (SeqOfKeyInUse(seq)) {
|
||||
@@ -141,9 +149,10 @@ int pthread_key_delete(pthread_key_t key) {
|
||||
}
|
||||
|
||||
void* pthread_getspecific(pthread_key_t key) {
|
||||
if (!KeyInValidRange(key)) {
|
||||
if (__predict_false(!KeyInValidRange(key))) {
|
||||
return NULL;
|
||||
}
|
||||
key &= ~KEY_VALID_FLAG;
|
||||
uintptr_t seq = atomic_load_explicit(&key_map[key].seq, memory_order_relaxed);
|
||||
pthread_key_data_t* data = &(__get_thread()->key_data[key]);
|
||||
// It is user's responsibility to synchornize between the creation and use of pthread keys,
|
||||
@@ -151,16 +160,19 @@ void* pthread_getspecific(pthread_key_t key) {
|
||||
if (__predict_true(SeqOfKeyInUse(seq) && data->seq == seq)) {
|
||||
return data->data;
|
||||
}
|
||||
// We arrive here when current thread holds the seq of an deleted pthread key. So the
|
||||
// data is for the deleted pthread key, and should be cleared.
|
||||
data->data = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pthread_setspecific(pthread_key_t key, const void* ptr) {
|
||||
if (!KeyInValidRange(key)) {
|
||||
if (__predict_false(!KeyInValidRange(key))) {
|
||||
return EINVAL;
|
||||
}
|
||||
key &= ~KEY_VALID_FLAG;
|
||||
uintptr_t seq = atomic_load_explicit(&key_map[key].seq, memory_order_relaxed);
|
||||
if (SeqOfKeyInUse(seq)) {
|
||||
if (__predict_true(SeqOfKeyInUse(seq))) {
|
||||
pthread_key_data_t* data = &(__get_thread()->key_data[key]);
|
||||
data->seq = seq;
|
||||
data->data = const_cast<void*>(ptr);
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
#include "private/bionic_futex.h"
|
||||
#include "private/bionic_lock.h"
|
||||
#include "private/bionic_time_conversions.h"
|
||||
|
||||
/* Technical note:
|
||||
@@ -53,18 +55,39 @@
|
||||
* - This implementation will return EDEADLK in "write after write" and "read after
|
||||
* write" cases and will deadlock in write after read case.
|
||||
*
|
||||
* TODO: As it stands now, pending_readers and pending_writers could be merged into a
|
||||
* a single waiters variable. Keeping them separate adds a bit of clarity and keeps
|
||||
* the door open for a writer-biased implementation.
|
||||
*
|
||||
*/
|
||||
|
||||
#define RWLOCKATTR_DEFAULT 0
|
||||
#define RWLOCKATTR_SHARED_MASK 0x0010
|
||||
// A rwlockattr is implemented as a 32-bit integer which has following fields:
|
||||
// bits name description
|
||||
// 1 rwlock_kind have rwlock preference like PTHREAD_RWLOCK_PREFER_READER_NP.
|
||||
// 0 process_shared set to 1 if the rwlock is shared between processes.
|
||||
|
||||
#define RWLOCKATTR_PSHARED_SHIFT 0
|
||||
#define RWLOCKATTR_KIND_SHIFT 1
|
||||
|
||||
#define RWLOCKATTR_PSHARED_MASK 1
|
||||
#define RWLOCKATTR_KIND_MASK 2
|
||||
#define RWLOCKATTR_RESERVED_MASK (~3)
|
||||
|
||||
static inline __always_inline __always_inline bool __rwlockattr_getpshared(const pthread_rwlockattr_t* attr) {
|
||||
return (*attr & RWLOCKATTR_PSHARED_MASK) >> RWLOCKATTR_PSHARED_SHIFT;
|
||||
}
|
||||
|
||||
static inline __always_inline __always_inline void __rwlockattr_setpshared(pthread_rwlockattr_t* attr, int pshared) {
|
||||
*attr = (*attr & ~RWLOCKATTR_PSHARED_MASK) | (pshared << RWLOCKATTR_PSHARED_SHIFT);
|
||||
}
|
||||
|
||||
static inline __always_inline int __rwlockattr_getkind(const pthread_rwlockattr_t* attr) {
|
||||
return (*attr & RWLOCKATTR_KIND_MASK) >> RWLOCKATTR_KIND_SHIFT;
|
||||
}
|
||||
|
||||
static inline __always_inline void __rwlockattr_setkind(pthread_rwlockattr_t* attr, int kind) {
|
||||
*attr = (*attr & ~RWLOCKATTR_KIND_MASK) | (kind << RWLOCKATTR_KIND_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t* attr) {
|
||||
*attr = PTHREAD_PROCESS_PRIVATE;
|
||||
*attr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -73,40 +96,121 @@ int pthread_rwlockattr_destroy(pthread_rwlockattr_t* attr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t* attr, int* pshared) {
|
||||
if (__rwlockattr_getpshared(attr)) {
|
||||
*pshared = PTHREAD_PROCESS_SHARED;
|
||||
} else {
|
||||
*pshared = PTHREAD_PROCESS_PRIVATE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t* attr, int pshared) {
|
||||
switch (pshared) {
|
||||
case PTHREAD_PROCESS_PRIVATE:
|
||||
__rwlockattr_setpshared(attr, 0);
|
||||
return 0;
|
||||
case PTHREAD_PROCESS_SHARED:
|
||||
*attr = pshared;
|
||||
__rwlockattr_setpshared(attr, 1);
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t* attr, int* pshared) {
|
||||
*pshared = *attr;
|
||||
int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t* attr, int* pref) {
|
||||
*pref = __rwlockattr_getkind(attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pthread_rwlock_internal_t {
|
||||
atomic_int state; // 0=unlock, -1=writer lock, +n=reader lock
|
||||
atomic_int writer_thread_id;
|
||||
atomic_uint pending_readers;
|
||||
atomic_uint pending_writers;
|
||||
int32_t attr;
|
||||
|
||||
bool process_shared() const {
|
||||
return attr == PTHREAD_PROCESS_SHARED;
|
||||
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t* attr, int pref) {
|
||||
switch (pref) {
|
||||
case PTHREAD_RWLOCK_PREFER_READER_NP: // Fall through.
|
||||
case PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP:
|
||||
__rwlockattr_setkind(attr, pref);
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
// A rwlock state is implemented as a 32-bit integer which has following rules:
|
||||
// bits name description
|
||||
// 31 owned_by_writer_flag set to 1 if the lock is owned by a writer now.
|
||||
// 30-2 reader_count the count of readers holding the lock.
|
||||
// 1 have_pending_writers set to 1 if having pending writers.
|
||||
// 0 have_pending_readers set to 1 if having pending readers.
|
||||
|
||||
#define STATE_HAVE_PENDING_READERS_SHIFT 0
|
||||
#define STATE_HAVE_PENDING_WRITERS_SHIFT 1
|
||||
#define STATE_READER_COUNT_SHIFT 2
|
||||
#define STATE_OWNED_BY_WRITER_SHIFT 31
|
||||
|
||||
#define STATE_HAVE_PENDING_READERS_FLAG (1 << STATE_HAVE_PENDING_READERS_SHIFT)
|
||||
#define STATE_HAVE_PENDING_WRITERS_FLAG (1 << STATE_HAVE_PENDING_WRITERS_SHIFT)
|
||||
#define STATE_READER_COUNT_CHANGE_STEP (1 << STATE_READER_COUNT_SHIFT)
|
||||
#define STATE_OWNED_BY_WRITER_FLAG (1 << STATE_OWNED_BY_WRITER_SHIFT)
|
||||
|
||||
#define STATE_HAVE_PENDING_READERS_OR_WRITERS_FLAG \
|
||||
(STATE_HAVE_PENDING_READERS_FLAG | STATE_HAVE_PENDING_WRITERS_FLAG)
|
||||
|
||||
struct pthread_rwlock_internal_t {
|
||||
atomic_int state;
|
||||
atomic_int writer_tid;
|
||||
|
||||
bool pshared;
|
||||
bool writer_nonrecursive_preferred;
|
||||
uint16_t __pad;
|
||||
|
||||
// When a reader thread plans to suspend on the rwlock, it will add STATE_HAVE_PENDING_READERS_FLAG
|
||||
// in state, increase pending_reader_count, and wait on pending_reader_wakeup_serial. After woken
|
||||
// up, the reader thread decreases pending_reader_count, and the last pending reader thread should
|
||||
// remove STATE_HAVE_PENDING_READERS_FLAG in state. A pending writer thread works in a similar way,
|
||||
// except that it uses flag and members for writer threads.
|
||||
|
||||
Lock pending_lock; // All pending members below are protected by pending_lock.
|
||||
uint32_t pending_reader_count; // Count of pending reader threads.
|
||||
uint32_t pending_writer_count; // Count of pending writer threads.
|
||||
uint32_t pending_reader_wakeup_serial; // Pending reader threads wait on this address by futex_wait.
|
||||
uint32_t pending_writer_wakeup_serial; // Pending writer threads wait on this address by futex_wait.
|
||||
|
||||
#if defined(__LP64__)
|
||||
char __reserved[36];
|
||||
#else
|
||||
char __reserved[20];
|
||||
#else
|
||||
char __reserved[4];
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline __always_inline bool __state_owned_by_writer(int state) {
|
||||
return state < 0;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __state_owned_by_readers(int state) {
|
||||
// If state >= 0, the owned_by_writer_flag is not set.
|
||||
// And if state >= STATE_READER_COUNT_CHANGE_STEP, the reader_count field is not empty.
|
||||
return state >= STATE_READER_COUNT_CHANGE_STEP;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __state_owned_by_readers_or_writer(int state) {
|
||||
return state < 0 || state >= STATE_READER_COUNT_CHANGE_STEP;
|
||||
}
|
||||
|
||||
static inline __always_inline int __state_add_writer_flag(int state) {
|
||||
return state | STATE_OWNED_BY_WRITER_FLAG;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __state_is_last_reader(int state) {
|
||||
return (state >> STATE_READER_COUNT_SHIFT) == 1;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __state_have_pending_writers(int state) {
|
||||
return state & STATE_HAVE_PENDING_WRITERS_FLAG;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __state_have_pending_readers_or_writers(int state) {
|
||||
return state & STATE_HAVE_PENDING_READERS_OR_WRITERS_FLAG;
|
||||
}
|
||||
|
||||
static_assert(sizeof(pthread_rwlock_t) == sizeof(pthread_rwlock_internal_t),
|
||||
"pthread_rwlock_t should actually be pthread_rwlock_internal_t in implementation.");
|
||||
|
||||
@@ -115,31 +219,35 @@ static_assert(sizeof(pthread_rwlock_t) == sizeof(pthread_rwlock_internal_t),
|
||||
static_assert(alignof(pthread_rwlock_t) == 4,
|
||||
"pthread_rwlock_t should fulfill the alignment requirement of pthread_rwlock_internal_t.");
|
||||
|
||||
static inline pthread_rwlock_internal_t* __get_internal_rwlock(pthread_rwlock_t* rwlock_interface) {
|
||||
static inline __always_inline pthread_rwlock_internal_t* __get_internal_rwlock(pthread_rwlock_t* rwlock_interface) {
|
||||
return reinterpret_cast<pthread_rwlock_internal_t*>(rwlock_interface);
|
||||
}
|
||||
|
||||
int pthread_rwlock_init(pthread_rwlock_t* rwlock_interface, const pthread_rwlockattr_t* attr) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
if (__predict_true(attr == NULL)) {
|
||||
rwlock->attr = 0;
|
||||
} else {
|
||||
switch (*attr) {
|
||||
case PTHREAD_PROCESS_SHARED:
|
||||
case PTHREAD_PROCESS_PRIVATE:
|
||||
rwlock->attr= *attr;
|
||||
memset(rwlock, 0, sizeof(pthread_rwlock_internal_t));
|
||||
|
||||
if (__predict_false(attr != NULL)) {
|
||||
rwlock->pshared = __rwlockattr_getpshared(attr);
|
||||
int kind = __rwlockattr_getkind(attr);
|
||||
switch (kind) {
|
||||
case PTHREAD_RWLOCK_PREFER_READER_NP:
|
||||
rwlock->writer_nonrecursive_preferred = false;
|
||||
break;
|
||||
case PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP:
|
||||
rwlock->writer_nonrecursive_preferred = true;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
if ((*attr & RWLOCKATTR_RESERVED_MASK) != 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_init(&rwlock->state, 0);
|
||||
atomic_init(&rwlock->writer_thread_id, 0);
|
||||
atomic_init(&rwlock->pending_readers, 0);
|
||||
atomic_init(&rwlock->pending_writers, 0);
|
||||
|
||||
rwlock->pending_lock.init(rwlock->pshared);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -152,105 +260,173 @@ int pthread_rwlock_destroy(pthread_rwlock_t* rwlock_interface) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline __always_inline bool __can_acquire_read_lock(int old_state,
|
||||
bool writer_nonrecursive_preferred) {
|
||||
// If writer is preferred with nonrecursive reader, we prevent further readers from acquiring
|
||||
// the lock when there are writers waiting for the lock.
|
||||
bool cannot_apply = __state_owned_by_writer(old_state) ||
|
||||
(writer_nonrecursive_preferred && __state_have_pending_writers(old_state));
|
||||
return !cannot_apply;
|
||||
}
|
||||
|
||||
static inline __always_inline int __pthread_rwlock_tryrdlock(pthread_rwlock_internal_t* rwlock) {
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
|
||||
while (__predict_true(__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred))) {
|
||||
|
||||
int new_state = old_state + STATE_READER_COUNT_CHANGE_STEP;
|
||||
if (__predict_false(!__state_owned_by_readers(new_state))) { // Happens when reader count overflows.
|
||||
return EAGAIN;
|
||||
}
|
||||
if (__predict_true(atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state, new_state,
|
||||
memory_order_acquire, memory_order_relaxed))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
|
||||
const timespec* abs_timeout_or_null) {
|
||||
|
||||
if (__predict_false(__get_thread()->tid == atomic_load_explicit(&rwlock->writer_thread_id,
|
||||
memory_order_relaxed))) {
|
||||
if (atomic_load_explicit(&rwlock->writer_tid, memory_order_relaxed) == __get_thread()->tid) {
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int ret = __pthread_rwlock_tryrdlock(rwlock);
|
||||
if (ret == 0 || ret == EAGAIN) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
if (__predict_true(old_state >= 0)) {
|
||||
if (atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state, old_state + 1,
|
||||
memory_order_acquire, memory_order_relaxed)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
if (__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
|
||||
// To avoid losing wake ups, the pending_readers increment should be observed before
|
||||
// futex_wait by all threads. A seq_cst fence instead of a seq_cst operation is used
|
||||
// here. Because only a seq_cst fence can ensure sequential consistency for non-atomic
|
||||
// operations in futex_wait.
|
||||
atomic_fetch_add_explicit(&rwlock->pending_readers, 1, memory_order_relaxed);
|
||||
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
|
||||
int ret = __futex_wait_ex(&rwlock->state, rwlock->process_shared(), old_state,
|
||||
rel_timeout);
|
||||
|
||||
atomic_fetch_sub_explicit(&rwlock->pending_readers, 1, memory_order_relaxed);
|
||||
|
||||
if (ret == -ETIMEDOUT) {
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_reader_count++;
|
||||
|
||||
// We rely on the fact that all atomic exchange operations on the same object (here it is
|
||||
// rwlock->state) always appear to occur in a single total order. If the pending flag is added
|
||||
// before unlocking, the unlocking thread will wakeup the waiter. Otherwise, we will see the
|
||||
// state is unlocked and will not wait anymore.
|
||||
old_state = atomic_fetch_or_explicit(&rwlock->state, STATE_HAVE_PENDING_READERS_FLAG,
|
||||
memory_order_relaxed);
|
||||
|
||||
int old_serial = rwlock->pending_reader_wakeup_serial;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
int futex_ret = 0;
|
||||
if (!__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) {
|
||||
futex_ret = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
|
||||
old_serial, rel_timeout);
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_reader_count--;
|
||||
if (rwlock->pending_reader_count == 0) {
|
||||
atomic_fetch_and_explicit(&rwlock->state, ~STATE_HAVE_PENDING_READERS_FLAG,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
if (futex_ret == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline __always_inline bool __can_acquire_write_lock(int old_state) {
|
||||
return !__state_owned_by_readers_or_writer(old_state);
|
||||
}
|
||||
|
||||
static inline __always_inline int __pthread_rwlock_trywrlock(pthread_rwlock_internal_t* rwlock) {
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
|
||||
while (__predict_true(__can_acquire_write_lock(old_state))) {
|
||||
if (__predict_true(atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state,
|
||||
__state_add_writer_flag(old_state), memory_order_acquire, memory_order_relaxed))) {
|
||||
|
||||
atomic_store_explicit(&rwlock->writer_tid, __get_thread()->tid, memory_order_relaxed);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
|
||||
const timespec* abs_timeout_or_null) {
|
||||
|
||||
if (__predict_false(__get_thread()->tid == atomic_load_explicit(&rwlock->writer_thread_id,
|
||||
memory_order_relaxed))) {
|
||||
if (atomic_load_explicit(&rwlock->writer_tid, memory_order_relaxed) == __get_thread()->tid) {
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int ret = __pthread_rwlock_trywrlock(rwlock);
|
||||
if (ret == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
if (__predict_true(old_state == 0)) {
|
||||
if (atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state, -1,
|
||||
memory_order_acquire, memory_order_relaxed)) {
|
||||
// writer_thread_id is protected by rwlock and can only be modified in rwlock write
|
||||
// owner thread. Other threads may read it for EDEADLK error checking, atomic operation
|
||||
// is safe enough for it.
|
||||
atomic_store_explicit(&rwlock->writer_thread_id, __get_thread()->tid, memory_order_relaxed);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
if (__can_acquire_write_lock(old_state)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
|
||||
// To avoid losing wake ups, the pending_writers increment should be observed before
|
||||
// futex_wait by all threads. A seq_cst fence instead of a seq_cst operation is used
|
||||
// here. Because only a seq_cst fence can ensure sequential consistency for non-atomic
|
||||
// operations in futex_wait.
|
||||
atomic_fetch_add_explicit(&rwlock->pending_writers, 1, memory_order_relaxed);
|
||||
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
|
||||
int ret = __futex_wait_ex(&rwlock->state, rwlock->process_shared(), old_state,
|
||||
rel_timeout);
|
||||
|
||||
atomic_fetch_sub_explicit(&rwlock->pending_writers, 1, memory_order_relaxed);
|
||||
|
||||
if (ret == -ETIMEDOUT) {
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_writer_count++;
|
||||
|
||||
old_state = atomic_fetch_or_explicit(&rwlock->state, STATE_HAVE_PENDING_WRITERS_FLAG,
|
||||
memory_order_relaxed);
|
||||
|
||||
int old_serial = rwlock->pending_writer_wakeup_serial;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
int futex_ret = 0;
|
||||
if (!__can_acquire_write_lock(old_state)) {
|
||||
futex_ret = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
|
||||
old_serial, rel_timeout);
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_writer_count--;
|
||||
if (rwlock->pending_writer_count == 0) {
|
||||
atomic_fetch_and_explicit(&rwlock->state, ~STATE_HAVE_PENDING_WRITERS_FLAG,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
if (futex_ret == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock_interface) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
// Avoid slowing down fast path of rdlock.
|
||||
if (__predict_true(__pthread_rwlock_tryrdlock(rwlock) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return __pthread_rwlock_timedrdlock(rwlock, NULL);
|
||||
}
|
||||
|
||||
@@ -261,19 +437,15 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock_interface, const timespe
|
||||
}
|
||||
|
||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock_interface) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
|
||||
while (old_state >= 0 && !atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state,
|
||||
old_state + 1, memory_order_acquire, memory_order_relaxed)) {
|
||||
}
|
||||
return (old_state >= 0) ? 0 : EBUSY;
|
||||
return __pthread_rwlock_tryrdlock(__get_internal_rwlock(rwlock_interface));
|
||||
}
|
||||
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock_interface) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
// Avoid slowing down fast path of wrlock.
|
||||
if (__predict_true(__pthread_rwlock_trywrlock(rwlock) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return __pthread_rwlock_timedwrlock(rwlock, NULL);
|
||||
}
|
||||
|
||||
@@ -284,65 +456,52 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock_interface, const timespe
|
||||
}
|
||||
|
||||
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock_interface) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
|
||||
while (old_state == 0 && !atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state, -1,
|
||||
memory_order_acquire, memory_order_relaxed)) {
|
||||
}
|
||||
if (old_state == 0) {
|
||||
atomic_store_explicit(&rwlock->writer_thread_id, __get_thread()->tid, memory_order_relaxed);
|
||||
return 0;
|
||||
}
|
||||
return EBUSY;
|
||||
return __pthread_rwlock_trywrlock(__get_internal_rwlock(rwlock_interface));
|
||||
}
|
||||
|
||||
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock_interface) {
|
||||
pthread_rwlock_internal_t* rwlock = __get_internal_rwlock(rwlock_interface);
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
if (__predict_false(old_state == 0)) {
|
||||
return EPERM;
|
||||
} else if (old_state == -1) {
|
||||
if (atomic_load_explicit(&rwlock->writer_thread_id, memory_order_relaxed) != __get_thread()->tid) {
|
||||
if (__state_owned_by_writer(old_state)) {
|
||||
if (atomic_load_explicit(&rwlock->writer_tid, memory_order_relaxed) != __get_thread()->tid) {
|
||||
return EPERM;
|
||||
}
|
||||
// We're no longer the owner.
|
||||
atomic_store_explicit(&rwlock->writer_thread_id, 0, memory_order_relaxed);
|
||||
// Change state from -1 to 0.
|
||||
atomic_store_explicit(&rwlock->state, 0, memory_order_release);
|
||||
|
||||
} else { // old_state > 0
|
||||
// Reduce state by 1.
|
||||
while (old_state > 0 && !atomic_compare_exchange_weak_explicit(&rwlock->state, &old_state,
|
||||
old_state - 1, memory_order_release, memory_order_relaxed)) {
|
||||
}
|
||||
|
||||
if (old_state <= 0) {
|
||||
return EPERM;
|
||||
} else if (old_state > 1) {
|
||||
atomic_store_explicit(&rwlock->writer_tid, 0, memory_order_relaxed);
|
||||
old_state = atomic_fetch_and_explicit(&rwlock->state, ~STATE_OWNED_BY_WRITER_FLAG,
|
||||
memory_order_release);
|
||||
if (!__state_have_pending_readers_or_writers(old_state)) {
|
||||
return 0;
|
||||
}
|
||||
// old_state = 1, which means the last reader calling unlock. It has to wake up waiters.
|
||||
|
||||
} else if (__state_owned_by_readers(old_state)) {
|
||||
old_state = atomic_fetch_sub_explicit(&rwlock->state, STATE_READER_COUNT_CHANGE_STEP,
|
||||
memory_order_release);
|
||||
if (!__state_is_last_reader(old_state) || !__state_have_pending_readers_or_writers(old_state)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
// If having waiters, wake up them.
|
||||
// To avoid losing wake ups, the update of state should be observed before reading
|
||||
// pending_readers/pending_writers by all threads. Use read locking as an example:
|
||||
// read locking thread unlocking thread
|
||||
// pending_readers++; state = 0;
|
||||
// seq_cst fence seq_cst fence
|
||||
// read state for futex_wait read pending_readers for futex_wake
|
||||
//
|
||||
// So when locking and unlocking threads are running in parallel, we will not get
|
||||
// in a situation that the locking thread reads state as negative and needs to wait,
|
||||
// while the unlocking thread reads pending_readers as zero and doesn't need to wake up waiters.
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
if (__predict_false(atomic_load_explicit(&rwlock->pending_readers, memory_order_relaxed) > 0 ||
|
||||
atomic_load_explicit(&rwlock->pending_writers, memory_order_relaxed) > 0)) {
|
||||
__futex_wake_ex(&rwlock->state, rwlock->process_shared(), INT_MAX);
|
||||
// Wake up pending readers or writers.
|
||||
rwlock->pending_lock.lock();
|
||||
if (rwlock->pending_writer_count != 0) {
|
||||
rwlock->pending_writer_wakeup_serial++;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
__futex_wake_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared, 1);
|
||||
|
||||
} else if (rwlock->pending_reader_count != 0) {
|
||||
rwlock->pending_reader_wakeup_serial++;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
__futex_wake_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared, INT_MAX);
|
||||
|
||||
} else {
|
||||
// It happens when waiters are woken up by timeout.
|
||||
rwlock->pending_lock.unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#undef _FORTIFY_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" int __rt_sigqueueinfo(pid_t, int, siginfo_t*);
|
||||
extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
|
||||
|
||||
int sigqueue(pid_t pid, int signo, const sigval value) {
|
||||
siginfo_t info;
|
||||
@@ -42,5 +42,5 @@ int sigqueue(pid_t pid, int signo, const sigval value) {
|
||||
info.si_uid = getuid();
|
||||
info.si_value = value;
|
||||
|
||||
return __rt_sigqueueinfo(pid, signo, &info);
|
||||
return ___rt_sigqueueinfo(pid, signo, &info);
|
||||
}
|
||||
|
||||
@@ -245,6 +245,7 @@ static id_t app_id_from_name(const char* name, bool is_group) {
|
||||
appid = android_ids[n].aid;
|
||||
// Move the end pointer to the null terminator.
|
||||
end += strlen(android_ids[n].name) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,6 +598,16 @@ int __system_property_area_init()
|
||||
return map_prop_area_rw();
|
||||
}
|
||||
|
||||
unsigned int __system_property_area_serial()
|
||||
{
|
||||
prop_area *pa = __system_property_area__;
|
||||
if (!pa) {
|
||||
return -1;
|
||||
}
|
||||
// Make sure this read fulfilled before __system_property_serial
|
||||
return atomic_load_explicit(&(pa->serial), memory_order_acquire);
|
||||
}
|
||||
|
||||
const prop_info *__system_property_find(const char *name)
|
||||
{
|
||||
if (__predict_false(compat_mode)) {
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
|
||||
#include <machine/elf_machdep.h>
|
||||
|
||||
#define ELF32_R_INFO(sym, type) ((((Elf32_Word)sym) << 8) | ((type) & 0xff))
|
||||
#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)sym) << 32) | ((type) & 0xffffffff))
|
||||
|
||||
typedef __s64 Elf32_Sxword;
|
||||
|
||||
typedef struct {
|
||||
__u32 a_type;
|
||||
union {
|
||||
@@ -48,6 +53,71 @@ typedef struct {
|
||||
} a_un;
|
||||
} Elf64_auxv_t;
|
||||
|
||||
typedef Elf32_Half Elf32_Versym;
|
||||
typedef Elf64_Half Elf64_Versym;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Half vd_version;
|
||||
Elf32_Half vd_flags;
|
||||
Elf32_Half vd_ndx;
|
||||
Elf32_Half vd_cnt;
|
||||
Elf32_Word vd_hash;
|
||||
Elf32_Word vd_aux;
|
||||
Elf32_Word vd_next;
|
||||
} Elf32_Verdef;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word vda_name;
|
||||
Elf32_Word vda_next;
|
||||
} Elf32_Verdaux;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Half vd_version;
|
||||
Elf64_Half vd_flags;
|
||||
Elf64_Half vd_ndx;
|
||||
Elf64_Half vd_cnt;
|
||||
Elf64_Word vd_hash;
|
||||
Elf64_Word vd_aux;
|
||||
Elf64_Word vd_next;
|
||||
} Elf64_Verdef;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word vda_name;
|
||||
Elf64_Word vda_next;
|
||||
} Elf64_Verdaux;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Half vn_version;
|
||||
Elf32_Half vn_cnt;
|
||||
Elf32_Word vn_file;
|
||||
Elf32_Word vn_aux;
|
||||
Elf32_Word vn_next;
|
||||
} Elf32_Verneed;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word vna_hash;
|
||||
Elf32_Half vna_flags;
|
||||
Elf32_Half vna_other;
|
||||
Elf32_Word vna_name;
|
||||
Elf32_Word vna_next;
|
||||
} Elf32_Vernaux;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Half vn_version;
|
||||
Elf64_Half vn_cnt;
|
||||
Elf64_Word vn_file;
|
||||
Elf64_Word vn_aux;
|
||||
Elf64_Word vn_next;
|
||||
} Elf64_Verneed;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word vna_hash;
|
||||
Elf64_Half vna_flags;
|
||||
Elf64_Half vna_other;
|
||||
Elf64_Word vna_name;
|
||||
Elf64_Word vna_next;
|
||||
} Elf64_Vernaux;
|
||||
|
||||
#define DF_ORIGIN 0x00000001
|
||||
#define DF_SYMBOLIC 0x00000002
|
||||
#define DF_TEXTREL 0x00000004
|
||||
@@ -122,6 +192,11 @@ typedef struct {
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
|
||||
#define STV_DEFAULT 0
|
||||
#define STV_INTERNAL 1
|
||||
#define STV_HIDDEN 2
|
||||
#define STV_PROTECTED 3
|
||||
|
||||
/* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */
|
||||
#define NT_FPREGSET NT_PRFPREG
|
||||
|
||||
@@ -129,4 +204,10 @@ typedef struct {
|
||||
|
||||
#define NT_GNU_BUILD_ID 3
|
||||
|
||||
#define VER_FLG_BASE 0x1
|
||||
#define VER_FLG_WEAK 0x2
|
||||
|
||||
#define VER_NDX_LOCAL 0
|
||||
#define VER_NDX_GLOBAL 1
|
||||
|
||||
#endif /* _ELF_H */
|
||||
|
||||
@@ -85,6 +85,11 @@ typedef long pthread_rwlockattr_t;
|
||||
|
||||
#define PTHREAD_RWLOCK_INITIALIZER { { 0 } }
|
||||
|
||||
enum {
|
||||
PTHREAD_RWLOCK_PREFER_READER_NP = 0,
|
||||
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 1,
|
||||
};
|
||||
|
||||
typedef int pthread_key_t;
|
||||
|
||||
typedef int pthread_once_t;
|
||||
@@ -178,10 +183,12 @@ int pthread_mutex_unlock(pthread_mutex_t*) __nonnull((1));
|
||||
|
||||
int pthread_once(pthread_once_t*, void (*)(void)) __nonnull((1, 2));
|
||||
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t*) __nonnull((1));
|
||||
int pthread_rwlockattr_destroy(pthread_rwlockattr_t*) __nonnull((1));
|
||||
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t*, int*) __nonnull((1, 2));
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t*) __nonnull((1));
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int) __nonnull((1));
|
||||
int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t*, int*) __nonnull((1, 2));
|
||||
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t*, int) __nonnull((1));
|
||||
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t*) __nonnull((1));
|
||||
int pthread_rwlock_init(pthread_rwlock_t*, const pthread_rwlockattr_t*) __nonnull((1));
|
||||
|
||||
@@ -176,6 +176,27 @@ extern size_t __ctype_get_mb_cur_max(void);
|
||||
#include <android/legacy_stdlib_inlines.h>
|
||||
#endif
|
||||
|
||||
#if defined(__BIONIC_FORTIFY)
|
||||
|
||||
extern char* __realpath_real(const char*, char*) __RENAME(realpath);
|
||||
__errordecl(__realpath_size_error, "realpath output parameter must be NULL or a >= PATH_MAX bytes buffer");
|
||||
|
||||
#if !defined(__clang__)
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
char* realpath(const char* path, char* resolved) {
|
||||
size_t bos = __bos(resolved);
|
||||
|
||||
/* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */
|
||||
if (bos != __BIONIC_FORTIFY_UNKNOWN_SIZE && bos < 4096) {
|
||||
__realpath_size_error();
|
||||
}
|
||||
|
||||
return __realpath_real(path, resolved);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(__BIONIC_FORTIFY) */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _STDLIB_H */
|
||||
|
||||
@@ -121,6 +121,13 @@ extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
|
||||
#define __bionic_using_gnu_basename
|
||||
#endif
|
||||
|
||||
extern void* __memchr_chk(const void*, int, size_t, size_t);
|
||||
__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer");
|
||||
|
||||
extern void* __memrchr_chk(const void*, int, size_t, size_t);
|
||||
__errordecl(__memrchr_buf_size_error, "memrchr called with size bigger than buffer");
|
||||
extern void* __memrchr_real(const void*, int, size_t) __RENAME(memrchr);
|
||||
|
||||
extern char* __stpncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t);
|
||||
extern char* __strncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t);
|
||||
extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t) __RENAME(strlcpy);
|
||||
@@ -130,6 +137,48 @@ extern size_t __strlcat_chk(char* __restrict, const char* __restrict, size_t, si
|
||||
|
||||
#if defined(__BIONIC_FORTIFY)
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void* memchr(const void *s, int c, size_t n) {
|
||||
size_t bos = __bos(s);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __builtin_memchr(s, c, n);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(n) && (n > bos)) {
|
||||
__memchr_buf_size_error();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(n) && (n <= bos)) {
|
||||
return __builtin_memchr(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __memchr_chk(s, c, n, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void* memrchr(const void *s, int c, size_t n) {
|
||||
size_t bos = __bos(s);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __memrchr_real(s, c, n);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(n) && (n > bos)) {
|
||||
__memrchr_buf_size_error();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(n) && (n <= bos)) {
|
||||
return __memrchr_real(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __memrchr_chk(s, c, n, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) {
|
||||
return __builtin___memcpy_chk(dest, src, copy_amount, __bos0(dest));
|
||||
|
||||
@@ -80,9 +80,7 @@ struct prop_msg
|
||||
|
||||
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"
|
||||
#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"
|
||||
#define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop"
|
||||
#define PROP_PATH_VENDOR_BUILD "/vendor/build.prop"
|
||||
#define PROP_PATH_BOOTIMAGE_BUILD "/build.prop"
|
||||
#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
|
||||
#define PROP_PATH_FACTORY "/factory/factory.prop"
|
||||
|
||||
@@ -99,6 +97,30 @@ int __system_property_set_filename(const char *filename);
|
||||
*/
|
||||
int __system_property_area_init();
|
||||
|
||||
/* Read the global serial number of the system properties
|
||||
**
|
||||
** Called to predict if a series of cached __system_property_find
|
||||
** objects will have seen __system_property_serial values change.
|
||||
** But also aids the converse, as changes in the global serial can
|
||||
** also be used to predict if a failed __system_property_find
|
||||
** could in-turn now find a new object; thus preventing the
|
||||
** cycles of effort to poll __system_property_find.
|
||||
**
|
||||
** Typically called at beginning of a cache cycle to signal if _any_ possible
|
||||
** changes have occurred since last. If there is, one may check each individual
|
||||
** __system_property_serial to confirm dirty, or __system_property_find
|
||||
** to check if the property now exists. If a call to __system_property_add
|
||||
** or __system_property_update has completed between two calls to
|
||||
** __system_property_area_serial then the second call will return a larger
|
||||
** value than the first call. Beware of race conditions as changes to the
|
||||
** properties are not atomic, the main value of this call is to determine
|
||||
** whether the expensive __system_property_find is worth retrying to see if
|
||||
** a property now exists.
|
||||
**
|
||||
** Returns the serial number on success, -1 on error.
|
||||
*/
|
||||
unsigned int __system_property_area_serial();
|
||||
|
||||
/* Add a new system property. Can only be done by a single
|
||||
** process that has write access to the property area, and
|
||||
** that process must handle sequencing to ensure the property
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 5 && !defined(__cplusplus)
|
||||
typedef __CHAR16_TYPE__ char16_t;
|
||||
typedef __CHAR32_TYPE__ char32_t;
|
||||
#endif
|
||||
|
||||
#define __STD_UTF_16__ 1
|
||||
#define __STD_UTF_32__ 1
|
||||
|
||||
|
||||
@@ -224,13 +224,89 @@ extern int tcsetpgrp(int fd, pid_t _pid);
|
||||
} while (_rc == -1 && errno == EINTR); \
|
||||
_rc; })
|
||||
|
||||
extern ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
|
||||
__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
|
||||
__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
|
||||
extern ssize_t __pread_real(int, void*, size_t, off_t) __RENAME(pread);
|
||||
|
||||
extern ssize_t __pread64_chk(int, void*, size_t, off64_t, size_t);
|
||||
__errordecl(__pread64_dest_size_error, "pread64 called with size bigger than destination");
|
||||
__errordecl(__pread64_count_toobig_error, "pread64 called with count > SSIZE_MAX");
|
||||
extern ssize_t __pread64_real(int, void*, size_t, off64_t) __RENAME(pread64);
|
||||
|
||||
extern ssize_t __read_chk(int, void*, size_t, size_t);
|
||||
__errordecl(__read_dest_size_error, "read called with size bigger than destination");
|
||||
__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
|
||||
extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
|
||||
|
||||
extern ssize_t __readlink_chk(const char*, char*, size_t, size_t);
|
||||
__errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
|
||||
__errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
|
||||
extern ssize_t __readlink_real(const char*, char*, size_t) __RENAME(readlink);
|
||||
|
||||
extern ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t);
|
||||
__errordecl(__readlinkat_dest_size_error, "readlinkat called with size bigger than destination");
|
||||
__errordecl(__readlinkat_size_toobig_error, "readlinkat called with size > SSIZE_MAX");
|
||||
extern ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME(readlinkat);
|
||||
|
||||
#if defined(__BIONIC_FORTIFY)
|
||||
|
||||
#if defined(__USE_FILE_OFFSET64)
|
||||
#define __PREAD_PREFIX(x) __pread64_ ## x
|
||||
#else
|
||||
#define __PREAD_PREFIX(x) __pread_ ## x
|
||||
#endif
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
|
||||
__PREAD_PREFIX(count_toobig_error)();
|
||||
}
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __PREAD_PREFIX(real)(fd, buf, count, offset);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(count) && (count > bos)) {
|
||||
__PREAD_PREFIX(dest_size_error)();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(count) && (count <= bos)) {
|
||||
return __PREAD_PREFIX(real)(fd, buf, count, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) {
|
||||
size_t bos = __bos0(buf);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
|
||||
__pread64_count_toobig_error();
|
||||
}
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __pread64_real(fd, buf, count, offset);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(count) && (count > bos)) {
|
||||
__pread64_dest_size_error();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(count) && (count <= bos)) {
|
||||
return __pread64_real(fd, buf, count, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __pread64_chk(fd, buf, count, offset, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t read(int fd, void* buf, size_t count) {
|
||||
size_t bos = __bos0(buf);
|
||||
@@ -255,6 +331,57 @@ ssize_t read(int fd, void* buf, size_t count) {
|
||||
|
||||
return __read_chk(fd, buf, count, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t readlink(const char* path, char* buf, size_t size) {
|
||||
size_t bos = __bos(buf);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
|
||||
__readlink_size_toobig_error();
|
||||
}
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __readlink_real(path, buf, size);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(size) && (size > bos)) {
|
||||
__readlink_dest_size_error();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(size) && (size <= bos)) {
|
||||
return __readlink_real(path, buf, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __readlink_chk(path, buf, size, bos);
|
||||
}
|
||||
|
||||
__BIONIC_FORTIFY_INLINE
|
||||
ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size) {
|
||||
size_t bos = __bos(buf);
|
||||
|
||||
#if !defined(__clang__)
|
||||
if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
|
||||
__readlinkat_size_toobig_error();
|
||||
}
|
||||
|
||||
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
|
||||
return __readlinkat_real(dirfd, path, buf, size);
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(size) && (size > bos)) {
|
||||
__readlinkat_dest_size_error();
|
||||
}
|
||||
|
||||
if (__builtin_constant_p(size) && (size <= bos)) {
|
||||
return __readlinkat_real(dirfd, path, buf, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __readlinkat_chk(dirfd, path, buf, size, bos);
|
||||
}
|
||||
|
||||
#endif /* defined(__BIONIC_FORTIFY) */
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@@ -14,7 +14,6 @@ if top is None:
|
||||
|
||||
# Set up the env vars for libclang.
|
||||
site.addsitedir(os.path.join(top, 'external/clang/bindings/python'))
|
||||
os.putenv('LD_LIBRARY_PATH', os.path.join(top, 'prebuilts/sdk/tools/linux'))
|
||||
|
||||
import clang.cindex
|
||||
from clang.cindex import conf
|
||||
@@ -26,6 +25,10 @@ from clang.cindex import TokenGroup
|
||||
from clang.cindex import TokenKind
|
||||
from clang.cindex import TranslationUnit
|
||||
|
||||
# Set up LD_LIBRARY_PATH to include libclang.so, libLLVM.so, and etc.
|
||||
# Note that setting LD_LIBRARY_PATH with os.putenv() sometimes doesn't help.
|
||||
clang.cindex.Config.set_library_path(os.path.join(top, 'prebuilts/sdk/tools/linux/lib64'))
|
||||
|
||||
from defaults import kCppUndefinedMacro
|
||||
from defaults import kernel_remove_config_macros
|
||||
from defaults import kernel_token_replacements
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_FD_H
|
||||
#define SCOPED_FD_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include "bionic_macros.h"
|
||||
|
||||
// A smart pointer that closes the given fd on going out of scope.
|
||||
// Use this when the fd is incidental to the purpose of your function,
|
||||
// but needs to be cleaned up on exit.
|
||||
class ScopedFd {
|
||||
public:
|
||||
explicit ScopedFd(int fd) : fd(fd) {
|
||||
}
|
||||
|
||||
~ScopedFd() {
|
||||
reset();
|
||||
}
|
||||
|
||||
int get() const {
|
||||
return fd;
|
||||
}
|
||||
|
||||
int release() __attribute__((warn_unused_result)) {
|
||||
int localFd = fd;
|
||||
fd = -1;
|
||||
return localFd;
|
||||
}
|
||||
|
||||
void reset(int new_fd = -1) {
|
||||
if (fd != -1) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
}
|
||||
fd = new_fd;
|
||||
}
|
||||
|
||||
private:
|
||||
int fd;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedFd);
|
||||
};
|
||||
|
||||
#endif // SCOPED_FD_H
|
||||
74
libc/private/bionic_lock.h
Normal file
74
libc/private/bionic_lock.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _BIONIC_LOCK_H
|
||||
#define _BIONIC_LOCK_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include "private/bionic_futex.h"
|
||||
|
||||
class Lock {
|
||||
private:
|
||||
enum LockState {
|
||||
Unlocked = 0,
|
||||
LockedWithoutWaiter,
|
||||
LockedWithWaiter,
|
||||
};
|
||||
_Atomic(LockState) state;
|
||||
bool process_shared;
|
||||
|
||||
public:
|
||||
Lock(bool process_shared = false) {
|
||||
init(process_shared);
|
||||
}
|
||||
|
||||
void init(bool process_shared) {
|
||||
atomic_init(&state, Unlocked);
|
||||
this->process_shared = process_shared;
|
||||
}
|
||||
|
||||
void lock() {
|
||||
LockState old_state = Unlocked;
|
||||
if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
|
||||
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) {
|
||||
return;
|
||||
}
|
||||
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
|
||||
// TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
|
||||
__futex_wait_ex(&state, process_shared, LockedWithWaiter, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) {
|
||||
__futex_wake_ex(&state, process_shared, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _BIONIC_LOCK_H
|
||||
@@ -97,14 +97,8 @@ enum {
|
||||
#define LIBC_PTHREAD_KEY_RESERVED_COUNT 12
|
||||
|
||||
#if defined(USE_JEMALLOC)
|
||||
/* Following are current pthread keys used internally by jemalloc:
|
||||
* je_thread_allocated_tsd jemalloc
|
||||
* je_arenas_tsd jemalloc
|
||||
* je_tcache_tsd jemalloc
|
||||
* je_tcache_enabled_tsd jemalloc
|
||||
* je_quarantine_tsd jemalloc
|
||||
*/
|
||||
#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 5
|
||||
/* Internally, jemalloc uses a single key for per thread data. */
|
||||
#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1
|
||||
#define BIONIC_PTHREAD_KEY_RESERVED_COUNT (LIBC_PTHREAD_KEY_RESERVED_COUNT + JEMALLOC_PTHREAD_KEY_RESERVED_COUNT)
|
||||
#else
|
||||
#define BIONIC_PTHREAD_KEY_RESERVED_COUNT LIBC_PTHREAD_KEY_RESERVED_COUNT
|
||||
|
||||
@@ -86,5 +86,5 @@ __sseek(void *cookie, fpos_t offset, int whence)
|
||||
int
|
||||
__sclose(void *cookie)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY(close(((FILE *)cookie)->_file));
|
||||
return close(((FILE *)cookie)->_file);
|
||||
}
|
||||
|
||||
@@ -35,11 +35,15 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "atexit.h"
|
||||
#include "thread_private.h"
|
||||
#include "private/thread_private.h"
|
||||
|
||||
struct atexit *__atexit;
|
||||
static int restartloop;
|
||||
|
||||
/* BEGIN android-changed: __unregister_atfork is used by __cxa_finalize */
|
||||
extern void __unregister_atfork(void* dso);
|
||||
/* END android-changed */
|
||||
|
||||
/*
|
||||
* Function pointers are stored in a linked list of pages. The list
|
||||
* is initially empty, and pages are allocated on demand. The first
|
||||
@@ -62,7 +66,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
|
||||
{
|
||||
struct atexit *p = __atexit;
|
||||
struct atexit_fn *fnp;
|
||||
int pgsize = getpagesize();
|
||||
size_t pgsize = getpagesize();
|
||||
int ret = -1;
|
||||
|
||||
if (pgsize < sizeof(*p))
|
||||
@@ -161,6 +165,12 @@ restart:
|
||||
__atexit = NULL;
|
||||
}
|
||||
_ATEXIT_UNLOCK();
|
||||
|
||||
/* BEGIN android-changed: call __unregister_atfork if dso is not null */
|
||||
if (dso != NULL) {
|
||||
__unregister_atfork(dso);
|
||||
}
|
||||
/* END android-changed */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -170,7 +180,7 @@ void
|
||||
__atexit_register_cleanup(void (*func)(void))
|
||||
{
|
||||
struct atexit *p;
|
||||
int pgsize = getpagesize();
|
||||
size_t pgsize = getpagesize();
|
||||
|
||||
if (pgsize < sizeof(*p))
|
||||
return;
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "atexit.h"
|
||||
#include "thread_private.h"
|
||||
|
||||
/*
|
||||
* This variable is zero until a process has created a thread.
|
||||
@@ -44,12 +42,21 @@
|
||||
*/
|
||||
int __isthreaded = 0;
|
||||
|
||||
/* BEGIN android-added: using __cxa_finalize and __cxa_thread_finalize */
|
||||
extern void __cxa_finalize(void* dso_handle);
|
||||
extern void __cxa_thread_finalize();
|
||||
/* END android-added */
|
||||
|
||||
/*
|
||||
* Exit, flushing stdio buffers if necessary.
|
||||
*/
|
||||
void
|
||||
exit(int status)
|
||||
{
|
||||
/* BEGIN android-added: call thread_local d-tors */
|
||||
__cxa_thread_finalize();
|
||||
/* END android-added */
|
||||
|
||||
/*
|
||||
* Call functions registered by atexit() or _cxa_atexit()
|
||||
* (including the stdio cleanup routine) and then _exit().
|
||||
@@ -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:
|
||||
if m.group(1) == 'FUNC' and functions_or_variables == 'functions':
|
||||
@@ -54,6 +70,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")
|
||||
|
||||
@@ -33,9 +33,12 @@ CheckDirExists(bionic_libc_zoneinfo_dir, 'bionic/libc/zoneinfo')
|
||||
CheckDirExists(bionic_libc_tools_zoneinfo_dir, 'bionic/libc/tools/zoneinfo')
|
||||
print 'Found bionic in %s ...' % bionic_dir
|
||||
|
||||
# Find the icu4c directory.
|
||||
icu_dir = os.path.realpath('%s/../external/icu/icu4c/source' % bionic_dir)
|
||||
CheckDirExists(icu_dir, 'external/icu/icu4c/source')
|
||||
# Find the icu directory.
|
||||
icu_dir = os.path.realpath('%s/../external/icu' % bionic_dir)
|
||||
icu4c_dir = os.path.realpath('%s/icu4c/source' % icu_dir)
|
||||
icu4j_dir = os.path.realpath('%s/icu4j' % icu_dir)
|
||||
CheckDirExists(icu4c_dir, 'external/icu/icu4c/source')
|
||||
CheckDirExists(icu4j_dir, 'external/icu/icu4j')
|
||||
print 'Found icu in %s ...' % icu_dir
|
||||
|
||||
|
||||
@@ -116,14 +119,14 @@ def BuildIcuToolsAndData(data_filename):
|
||||
|
||||
# Build the ICU tools.
|
||||
print 'Configuring ICU tools...'
|
||||
subprocess.check_call(['%s/runConfigureICU' % icu_dir, 'Linux'])
|
||||
subprocess.check_call(['%s/runConfigureICU' % icu4c_dir, 'Linux'])
|
||||
|
||||
# Run the ICU tools.
|
||||
os.chdir('tools/tzcode')
|
||||
|
||||
# The tz2icu tool only picks up icuregions and icuzones in they are in the CWD
|
||||
for icu_data_file in [ 'icuregions', 'icuzones']:
|
||||
icu_data_file_source = '%s/tools/tzcode/%s' % (icu_dir, icu_data_file)
|
||||
icu_data_file_source = '%s/tools/tzcode/%s' % (icu4c_dir, icu_data_file)
|
||||
icu_data_file_symlink = './%s' % icu_data_file
|
||||
os.symlink(icu_data_file_source, icu_data_file_symlink)
|
||||
|
||||
@@ -134,7 +137,7 @@ def BuildIcuToolsAndData(data_filename):
|
||||
subprocess.check_call(['make'])
|
||||
|
||||
# Copy the source file to its ultimate destination.
|
||||
icu_txt_data_dir = '%s/data/misc' % icu_dir
|
||||
icu_txt_data_dir = '%s/data/misc' % icu4c_dir
|
||||
print 'Copying zoneinfo64.txt to %s ...' % icu_txt_data_dir
|
||||
shutil.copy('zoneinfo64.txt', icu_txt_data_dir)
|
||||
|
||||
@@ -143,7 +146,7 @@ def BuildIcuToolsAndData(data_filename):
|
||||
subprocess.check_call(['make', 'INCLUDE_UNI_CORE_DATA=1', '-j32'])
|
||||
|
||||
# Copy the .dat file to its ultimate destination.
|
||||
icu_dat_data_dir = '%s/stubdata' % icu_dir
|
||||
icu_dat_data_dir = '%s/stubdata' % icu4c_dir
|
||||
datfiles = glob.glob('data/out/tmp/icudt??l.dat')
|
||||
if len(datfiles) != 1:
|
||||
print 'ERROR: Unexpectedly found %d .dat files (%s). Halting.' % (len(datfiles), datfiles)
|
||||
@@ -152,6 +155,20 @@ def BuildIcuToolsAndData(data_filename):
|
||||
print 'Copying %s to %s ...' % (datfile, icu_dat_data_dir)
|
||||
shutil.copy(datfile, icu_dat_data_dir)
|
||||
|
||||
# Generate the ICU4J .jar files
|
||||
os.chdir('%s/data' % icu_working_dir)
|
||||
subprocess.check_call(['make', 'icu4j-data'])
|
||||
|
||||
# Copy the ICU4J .jar files to their ultimate destination.
|
||||
icu_jar_data_dir = '%s/main/shared/data' % icu4j_dir
|
||||
jarfiles = glob.glob('out/icu4j/*.jar')
|
||||
if len(jarfiles) != 2:
|
||||
print 'ERROR: Unexpectedly found %d .jar files (%s). Halting.' % (len(jarfiles), jarfiles)
|
||||
sys.exit(1)
|
||||
for jarfile in jarfiles:
|
||||
print 'Copying %s to %s ...' % (jarfile, icu_jar_data_dir)
|
||||
shutil.copy(jarfile, icu_jar_data_dir)
|
||||
|
||||
# Switch back to the original working cwd.
|
||||
os.chdir(original_working_dir)
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
LIBC {
|
||||
global:
|
||||
/* Work-around for http://b/20065774. */
|
||||
__clear_cache;
|
||||
_Unwind_Backtrace;
|
||||
_Unwind_GetIP;
|
||||
local:
|
||||
_ZSt7nothrow;
|
||||
_ZdaPv;
|
||||
|
||||
Binary file not shown.
@@ -15,7 +15,7 @@ include $(CLEAR_VARS)
|
||||
#
|
||||
# DO NOT REMOVE --exclude-libs!
|
||||
|
||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a
|
||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a -Wl,--version-script=$(LOCAL_PATH)/libdl.map
|
||||
|
||||
# for x86, exclude libgcc_eh.a for the same reasons as above
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--exclude-libs=libgcc_eh.a
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <android/dlext.h>
|
||||
|
||||
// These are stubs for functions that are actually defined
|
||||
@@ -38,3 +39,6 @@ void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unu
|
||||
void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
|
||||
|
||||
void* android_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
|
||||
|
||||
void android_set_application_target_sdk_version(uint32_t target __unused) { }
|
||||
uint32_t android_get_application_target_sdk_version() { return 0; }
|
||||
|
||||
39
libdl/libdl.map
Normal file
39
libdl/libdl.map
Normal file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (C) 2015 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
LIBC {
|
||||
global:
|
||||
android_dlopen_ext;
|
||||
dl_iterate_phdr;
|
||||
# begin arm-only
|
||||
dl_unwind_find_exidx;
|
||||
# end arm-only
|
||||
dladdr;
|
||||
dlclose;
|
||||
dlerror;
|
||||
dlopen;
|
||||
dlsym;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
@@ -501,9 +501,6 @@ LOCAL_CFLAGS += \
|
||||
-fno-builtin-rintf \
|
||||
-fno-builtin-rintl \
|
||||
|
||||
LOCAL_CONLY_FLAGS := \
|
||||
-std=c99 \
|
||||
|
||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
|
||||
LOCAL_ADDRESS_SANITIZER := false
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -514,7 +511,8 @@ include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
|
||||
LOCAL_MODULE := libm
|
||||
LOCAL_CLANG := $(libm_clang)
|
||||
|
||||
108
libm/NOTICE
108
libm/NOTICE
@@ -1002,6 +1002,114 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved.
|
||||
Johhnny Qiu <joqiu@nvidia.com>
|
||||
Shu Zhang <chazhang@nvidia.com>
|
||||
|
||||
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.
|
||||
* Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved.
|
||||
Johnny Qiu <joqiu@nvidia.com>
|
||||
Shu Zhang <chazhang@nvidia.com>
|
||||
|
||||
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.
|
||||
* Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2014, Intel Corporation
|
||||
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.
|
||||
|
||||
* Neither the name of Intel Corporation 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 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
From: @(#)s_ilogb.c 5.1 93/09/24
|
||||
====================================================
|
||||
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
|
||||
@@ -7,6 +7,7 @@ LOCAL_SRC_FILES:= \
|
||||
dlfcn.cpp \
|
||||
linker.cpp \
|
||||
linker_allocator.cpp \
|
||||
linker_sdk_versions.cpp \
|
||||
linker_block_allocator.cpp \
|
||||
linker_environ.cpp \
|
||||
linker_libc_support.c \
|
||||
@@ -35,6 +36,9 @@ LOCAL_CFLAGS += \
|
||||
-fvisibility=hidden \
|
||||
-Wall -Wextra -Wunused -Werror \
|
||||
|
||||
LOCAL_CFLAGS_arm += -D__work_around_b_19059885__
|
||||
LOCAL_CFLAGS_x86 += -D__work_around_b_19059885__
|
||||
|
||||
LOCAL_CONLYFLAGS += \
|
||||
-std=gnu99 \
|
||||
|
||||
|
||||
100
linker/NOTICE
100
linker/NOTICE
@@ -42,62 +42,6 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2008, 2009 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2008-2010 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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2010 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
@@ -214,3 +158,47 @@ limitations under the License.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -205,15 +205,6 @@ static bool have_siginfo(int signum) {
|
||||
}
|
||||
|
||||
static void send_debuggerd_packet(siginfo_t* info) {
|
||||
if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
|
||||
// process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
|
||||
// Honor that intention by not connecting to debuggerd and asking it
|
||||
// to dump our internal state.
|
||||
__libc_format_log(ANDROID_LOG_INFO, "libc",
|
||||
"Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
|
||||
return;
|
||||
}
|
||||
|
||||
// Mutex to prevent multiple crashing threads from trying to talk
|
||||
// to debuggerd at the same time.
|
||||
static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -100,7 +100,7 @@ void* dlsym(void* handle, const char* symbol) {
|
||||
}
|
||||
|
||||
soinfo* found = nullptr;
|
||||
ElfW(Sym)* sym = nullptr;
|
||||
const ElfW(Sym)* sym = nullptr;
|
||||
void* caller_addr = __builtin_return_address(0);
|
||||
soinfo* caller = find_containing_library(caller_addr);
|
||||
|
||||
@@ -157,6 +157,14 @@ int dlclose(void* handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void android_set_application_target_sdk_version(uint32_t target) {
|
||||
set_application_target_sdk_version(target);
|
||||
}
|
||||
|
||||
uint32_t android_get_application_target_sdk_version() {
|
||||
return get_application_target_sdk_version();
|
||||
}
|
||||
|
||||
// name_offset: starting index of the name in libdl_info.strtab
|
||||
#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
|
||||
{ name_offset, \
|
||||
@@ -176,19 +184,21 @@ int dlclose(void* handle) {
|
||||
/* st_size */ 0, \
|
||||
}
|
||||
|
||||
static const char ANDROID_LIBDL_STRTAB[] =
|
||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 99999
|
||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 56789
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_it"
|
||||
// 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
|
||||
// 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
|
||||
"erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
|
||||
// 0000000000111111
|
||||
// 0123456789012345
|
||||
"get_sdk_version\0"
|
||||
#if defined(__arm__)
|
||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222 333333333344444444445
|
||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789 012345678901234567890
|
||||
# define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0dl_unwind_find_exidx\0"
|
||||
#elif defined(__aarch64__) || defined(__i386__) || defined(__mips__) || defined(__x86_64__)
|
||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222
|
||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789
|
||||
# define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0"
|
||||
#else
|
||||
# error Unsupported architecture. Only arm, arm64, mips, mips64, x86 and x86_64 are presently supported.
|
||||
// 216
|
||||
"dl_unwind_find_exidx\0"
|
||||
#endif
|
||||
;
|
||||
|
||||
static ElfW(Sym) g_libdl_symtab[] = {
|
||||
// Total length of libdl_info.strtab, including trailing 0.
|
||||
@@ -205,8 +215,10 @@ static ElfW(Sym) g_libdl_symtab[] = {
|
||||
ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1),
|
||||
ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1),
|
||||
ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
|
||||
ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
|
||||
ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
|
||||
#if defined(__arm__)
|
||||
ELFW(SYM_INITIALIZER)(130, &dl_unwind_find_exidx, 1),
|
||||
ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -223,9 +235,9 @@ static ElfW(Sym) g_libdl_symtab[] = {
|
||||
// Note that adding any new symbols here requires stubbing them out in libdl.
|
||||
static unsigned g_libdl_buckets[1] = { 1 };
|
||||
#if defined(__arm__)
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
|
||||
#else
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
|
||||
#endif
|
||||
|
||||
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
|
||||
|
||||
@@ -136,6 +136,17 @@ class LinkedList {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
T* find_if(F predicate) const {
|
||||
for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
|
||||
if (predicate(e->element)) {
|
||||
return e->element;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t copy_to_array(T* array[], size_t array_length) const {
|
||||
size_t sz = 0;
|
||||
for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,7 @@
|
||||
#include "linked_list.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define DL_ERR(fmt, x...) \
|
||||
do { \
|
||||
@@ -96,7 +97,7 @@
|
||||
|
||||
#define SOINFO_VERSION 2
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#define SOINFO_NAME_LEN 128
|
||||
#endif
|
||||
|
||||
@@ -142,10 +143,36 @@ class SymbolName {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolName);
|
||||
};
|
||||
|
||||
struct version_info {
|
||||
version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {}
|
||||
|
||||
uint32_t elf_hash;
|
||||
const char* name;
|
||||
const soinfo* target_si;
|
||||
};
|
||||
|
||||
// Class used construct version dependency graph.
|
||||
class VersionTracker {
|
||||
public:
|
||||
VersionTracker() = default;
|
||||
bool init(const soinfo* si_from);
|
||||
|
||||
const version_info* get_version_info(ElfW(Versym) source_symver) const;
|
||||
private:
|
||||
bool init_verneed(const soinfo* si_from);
|
||||
bool init_verdef(const soinfo* si_from);
|
||||
void add_version_info(size_t source_index, ElfW(Word) elf_hash,
|
||||
const char* ver_name, const soinfo* target_si);
|
||||
|
||||
std::vector<version_info> version_infos;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(VersionTracker);
|
||||
};
|
||||
|
||||
struct soinfo {
|
||||
public:
|
||||
typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
|
||||
#if defined(__arm__)
|
||||
#if defined(__work_around_b_19059885__)
|
||||
private:
|
||||
char old_name_[SOINFO_NAME_LEN];
|
||||
#endif
|
||||
@@ -156,13 +183,13 @@ struct soinfo {
|
||||
ElfW(Addr) base;
|
||||
size_t size;
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__work_around_b_19059885__)
|
||||
uint32_t unused1; // DO NOT USE, maintained for compatibility.
|
||||
#endif
|
||||
|
||||
ElfW(Dyn)* dynamic;
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__work_around_b_19059885__)
|
||||
uint32_t unused2; // DO NOT USE, maintained for compatibility
|
||||
uint32_t unused3; // DO NOT USE, maintained for compatibility
|
||||
#endif
|
||||
@@ -220,7 +247,9 @@ struct soinfo {
|
||||
uint32_t mips_symtabno_;
|
||||
uint32_t mips_local_gotno_;
|
||||
uint32_t mips_gotsym_;
|
||||
bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||
bool mips_relocate_got(const VersionTracker& version_tracker,
|
||||
const soinfo_list_t& global_group,
|
||||
const soinfo_list_t& local_group);
|
||||
|
||||
#endif
|
||||
size_t ref_count_;
|
||||
@@ -260,18 +289,23 @@ struct soinfo {
|
||||
void set_dt_flags_1(uint32_t dt_flags_1);
|
||||
|
||||
soinfo_list_t& get_children();
|
||||
const soinfo_list_t& get_children() const;
|
||||
|
||||
soinfo_list_t& get_parents();
|
||||
|
||||
ElfW(Sym)* find_symbol_by_name(SymbolName& symbol_name);
|
||||
bool find_symbol_by_name(SymbolName& symbol_name,
|
||||
const version_info* vi,
|
||||
const ElfW(Sym)** symbol) const;
|
||||
|
||||
ElfW(Sym)* find_symbol_by_address(const void* addr);
|
||||
ElfW(Addr) resolve_symbol_address(ElfW(Sym)* s);
|
||||
ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const;
|
||||
|
||||
const char* get_string(ElfW(Word) index) const;
|
||||
bool can_unload() const;
|
||||
bool is_gnu_hash() const;
|
||||
|
||||
bool inline has_min_version(uint32_t min_version __unused) const {
|
||||
#if defined(__arm__)
|
||||
#if defined(__work_around_b_19059885__)
|
||||
return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
|
||||
#else
|
||||
return true;
|
||||
@@ -292,18 +326,28 @@ struct soinfo {
|
||||
|
||||
const char* get_soname() const;
|
||||
const char* get_realpath() const;
|
||||
const ElfW(Versym)* get_versym(size_t n) const;
|
||||
ElfW(Addr) get_verneed_ptr() const;
|
||||
size_t get_verneed_cnt() const;
|
||||
ElfW(Addr) get_verdef_ptr() const;
|
||||
size_t get_verdef_cnt() const;
|
||||
|
||||
bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const;
|
||||
|
||||
private:
|
||||
ElfW(Sym)* elf_lookup(SymbolName& symbol_name);
|
||||
bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
|
||||
ElfW(Sym)* elf_addr_lookup(const void* addr);
|
||||
ElfW(Sym)* gnu_lookup(SymbolName& symbol_name);
|
||||
bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
|
||||
ElfW(Sym)* gnu_addr_lookup(const void* addr);
|
||||
|
||||
bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
|
||||
const char* sym_name, const version_info** vi);
|
||||
|
||||
void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
|
||||
void call_function(const char* function_name, linker_function_t function);
|
||||
template<typename ElfRelIteratorT>
|
||||
bool relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
|
||||
const soinfo_list_t& local_group);
|
||||
bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
|
||||
const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||
|
||||
private:
|
||||
// This part of the structure is only available
|
||||
@@ -341,11 +385,20 @@ struct soinfo {
|
||||
const char* soname_;
|
||||
std::string realpath_;
|
||||
|
||||
const ElfW(Versym)* versym_;
|
||||
|
||||
ElfW(Addr) verdef_ptr_;
|
||||
size_t verdef_cnt_;
|
||||
|
||||
ElfW(Addr) verneed_ptr_;
|
||||
size_t verneed_cnt_;
|
||||
|
||||
friend soinfo* get_libdl_info();
|
||||
};
|
||||
|
||||
ElfW(Sym)* soinfo_do_lookup(soinfo* si_from, const char* name, soinfo** si_found_in,
|
||||
const soinfo::soinfo_list_t& global_group, const soinfo::soinfo_list_t& local_group);
|
||||
bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
|
||||
soinfo** si_found_in, const soinfo::soinfo_list_t& global_group,
|
||||
const soinfo::soinfo_list_t& local_group, const ElfW(Sym)** symbol);
|
||||
|
||||
enum RelocationKind {
|
||||
kRelocAbsolute = 0,
|
||||
@@ -364,10 +417,10 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
|
||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
|
||||
void do_dlclose(soinfo* si);
|
||||
|
||||
ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
|
||||
const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
|
||||
soinfo* find_containing_library(const void* addr);
|
||||
|
||||
ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
|
||||
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
|
||||
|
||||
void debuggerd_init();
|
||||
extern "C" abort_msg_t* g_abort_message;
|
||||
@@ -376,4 +429,7 @@ extern "C" void notify_gdb_of_libraries();
|
||||
char* linker_get_error_buffer();
|
||||
size_t linker_get_error_buffer_size();
|
||||
|
||||
void set_application_target_sdk_version(uint32_t target);
|
||||
uint32_t get_application_target_sdk_version();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 The Android Open Source Project
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user