Compare commits

..

No commits in common. "main" and "brillo-m7-dev" have entirely different histories.

139 changed files with 2580 additions and 10100 deletions

View File

@ -2,7 +2,6 @@ BasedOnStyle: Google
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: false AllowShortFunctionsOnASingleLine: false
ColumnLimit: 100
CommentPragmas: NOLINT:.* CommentPragmas: NOLINT:.*
DerivePointerAlignment: false DerivePointerAlignment: false
IndentWidth: 2 IndentWidth: 2

View File

@ -169,10 +169,9 @@ As mentioned above, this is currently a two-step process:
Updating tzdata Updating tzdata
--------------- ---------------
This is fully automated (and these days handled by the libcore team, because This is fully automated:
they own icu, and that needs to be updated in sync with bionic):
1. Run update-tzdata.py in external/icu/tools/. 1. Run update-tzdata.py.
Verifying changes Verifying changes
@ -269,22 +268,18 @@ However, this also makes it difficult to run the tests under GDB. To prevent
each test from being forked, run the tests with the flag `--no-isolate`. each test from being forked, run the tests with the flag `--no-isolate`.
32-bit ABI bugs LP32 ABI bugs
--------------- -------------
This probably belongs in the NDK documentation rather than here, but these This probably belongs in the NDK documentation rather than here, but these
are the known ABI bugs in the 32-bit ABI: are the known ABI bugs in LP32:
* `time_t` is 32-bit. <http://b/5819737>. In the 64-bit ABI, time_t is * `time_t` is 32-bit. <http://b/5819737>
64-bit.
* `off_t` is 32-bit. There is `off64_t`, and in newer releases there is * `off_t` is 32-bit. There is `off64_t`, but no `_FILE_OFFSET_BITS` support.
almost-complete support for `_FILE_OFFSET_BITS`. Unfortunately our stdio Many of the `off64_t` functions are missing in older releases, and
implementation uses 32-bit offsets and -- worse -- function pointers to stdio uses 32-bit offsets, so there's no way to fully implement
functions that use 32-bit offsets, so there's no good way to implement `_FILE_OFFSET_BITS`.
the last few pieces <http://b/24807045>. In the 64-bit ABI, off_t is
off64_t.
* `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support * `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
for real-time signals is broken. <http://b/5828899> In the 64-bit ABI, for real-time signals is broken. <http://b/5828899>
`sigset_t` is the correct size for every architecture.

View File

@ -24,7 +24,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <android-base/stringprintf.h> #include <base/stringprintf.h>
#include <benchmark/Benchmark.h> #include <benchmark/Benchmark.h>

View File

@ -23,7 +23,7 @@
#include <string> #include <string>
#include <android-base/stringprintf.h> #include <base/stringprintf.h>
int Round(int n) { int Round(int n) {
int base = 1; int base = 1;

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,7 @@ libc_common_src_files := \
bionic/if_indextoname.c \ bionic/if_indextoname.c \
bionic/if_nametoindex.c \ bionic/if_nametoindex.c \
bionic/initgroups.c \ bionic/initgroups.c \
bionic/ioctl.c \
bionic/isatty.c \ bionic/isatty.c \
bionic/memmem.c \ bionic/memmem.c \
bionic/pututline.c \ bionic/pututline.c \
@ -149,9 +150,7 @@ libc_bionic_ndk_src_files := \
bionic/getpid.cpp \ bionic/getpid.cpp \
bionic/gettid.cpp \ bionic/gettid.cpp \
bionic/__gnu_basename.cpp \ bionic/__gnu_basename.cpp \
bionic/ifaddrs.cpp \
bionic/inotify_init.cpp \ bionic/inotify_init.cpp \
bionic/ioctl.cpp \
bionic/lchown.cpp \ bionic/lchown.cpp \
bionic/lfs64_support.cpp \ bionic/lfs64_support.cpp \
bionic/__libc_current_sigrtmax.cpp \ bionic/__libc_current_sigrtmax.cpp \
@ -171,7 +170,6 @@ libc_bionic_ndk_src_files := \
bionic/mkfifo.cpp \ bionic/mkfifo.cpp \
bionic/mknod.cpp \ bionic/mknod.cpp \
bionic/mntent.cpp \ bionic/mntent.cpp \
bionic/mremap.cpp \
bionic/NetdClientDispatch.cpp \ bionic/NetdClientDispatch.cpp \
bionic/open.cpp \ bionic/open.cpp \
bionic/pathconf.cpp \ bionic/pathconf.cpp \
@ -244,11 +242,9 @@ libc_bionic_ndk_src_files := \
libc_bionic_src_files := libc_bionic_src_files :=
# The following implementations depend on pthread data, so we can't include # The fork implementation depends on pthread data, so we can't include it in
# them in libc_ndk.a. # libc_ndk.a.
libc_bionic_src_files += \ libc_bionic_src_files += bionic/fork.cpp
bionic/__cxa_thread_atexit_impl.cpp \
bionic/fork.cpp \
# The data that backs getauxval is initialized in the libc init functions which # The data that backs getauxval is initialized in the libc init functions which
# are invoked by the linker. If this file is included in libc_ndk.a, only one of # are invoked by the linker. If this file is included in libc_ndk.a, only one of
@ -567,7 +563,6 @@ libc_upstream_openbsd_ndk_src_files := \
libc_pthread_src_files := \ libc_pthread_src_files := \
bionic/pthread_atfork.cpp \ bionic/pthread_atfork.cpp \
bionic/pthread_attr.cpp \ bionic/pthread_attr.cpp \
bionic/pthread_barrier.cpp \
bionic/pthread_cond.cpp \ bionic/pthread_cond.cpp \
bionic/pthread_create.cpp \ bionic/pthread_create.cpp \
bionic/pthread_detach.cpp \ bionic/pthread_detach.cpp \
@ -587,7 +582,9 @@ libc_pthread_src_files := \
bionic/pthread_setname_np.cpp \ bionic/pthread_setname_np.cpp \
bionic/pthread_setschedparam.cpp \ bionic/pthread_setschedparam.cpp \
bionic/pthread_sigmask.cpp \ bionic/pthread_sigmask.cpp \
bionic/pthread_spinlock.cpp \
libc_thread_atexit_impl_src_files := \
bionic/__cxa_thread_atexit_impl.cpp \
libc_arch_static_src_files := \ libc_arch_static_src_files := \
bionic/dl_iterate_phdr_static.cpp \ bionic/dl_iterate_phdr_static.cpp \
@ -625,11 +622,6 @@ ifeq ($(TARGET_ARCH),x86_64)
use_clang := false use_clang := false
endif endif
# b/25291096, Clang/llvm compiled libc.so for mips/mips64 failed to boot.
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
use_clang := false
endif
ifeq ($(use_clang),) ifeq ($(use_clang),)
use_clang := false use_clang := false
endif endif
@ -645,7 +637,7 @@ ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
libc_common_cflags += -DDEBUG libc_common_cflags += -DDEBUG
endif endif
ifeq ($(MALLOC_SVELTE),true) ifeq ($(MALLOC_IMPL),dlmalloc)
libc_common_cflags += -DUSE_DLMALLOC libc_common_cflags += -DUSE_DLMALLOC
libc_malloc_src := bionic/dlmalloc.c libc_malloc_src := bionic/dlmalloc.c
else else
@ -654,6 +646,13 @@ else
libc_common_c_includes += external/jemalloc/include libc_common_c_includes += external/jemalloc/include
endif endif
# To customize dlmalloc's alignment, set BOARD_MALLOC_ALIGNMENT in
# the appropriate BoardConfig.mk file.
#
ifneq ($(BOARD_MALLOC_ALIGNMENT),)
libc_common_cflags += -DMALLOC_ALIGNMENT=$(BOARD_MALLOC_ALIGNMENT)
endif
# Define some common conlyflags # Define some common conlyflags
libc_common_conlyflags := \ libc_common_conlyflags := \
-std=gnu99 -std=gnu99
@ -684,21 +683,13 @@ endef
# libc_stack_protector.a - stack protector code # libc_stack_protector.a - stack protector code
# ======================================================== # ========================================================
# #
# Code that implements the stack protector (or that runs # The stack protector code needs to be compiled
# before TLS has been set up) needs to be compiled with # with -fno-stack-protector, since it modifies the
# -fno-stack-protector, since it accesses the stack canary # stack canary.
# TLS slot.
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
bionic/__libc_init_main_thread.cpp \
bionic/__stack_chk_fail.cpp \
LOCAL_SRC_FILES_arm64 := arch-arm64/bionic/__set_tls.c
LOCAL_SRC_FILES_x86 := arch-x86/bionic/__set_tls.c
LOCAL_SRC_FILES_x86_64 := arch-x86_64/bionic/__set_tls.c
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
LOCAL_CONLYFLAGS := $(libc_common_conlyflags) LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags) LOCAL_CPPFLAGS := $(libc_common_cppflags)
@ -715,30 +706,6 @@ $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
# libc_init_static.cpp also needs to be built without stack protector,
# because it's responsible for setting up TLS for static executables.
# This isn't the case for dynamic executables because the dynamic linker
# has already set up the main thread's TLS.
include $(CLEAR_VARS)
LOCAL_SRC_FILES := bionic/libc_init_static.cpp
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_init_static
LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_CXX_STL := none
LOCAL_SYSTEM_SHARED_LIBRARIES :=
LOCAL_SANITIZE := never
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
include $(BUILD_STATIC_LIBRARY)
# ======================================================== # ========================================================
# libc_tzcode.a - upstream 'tzcode' code # libc_tzcode.a - upstream 'tzcode' code
# ======================================================== # ========================================================
@ -757,7 +724,6 @@ LOCAL_CFLAGS := $(libc_common_cflags) \
LOCAL_CFLAGS += -DALL_STATE LOCAL_CFLAGS += -DALL_STATE
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time. # Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
LOCAL_CFLAGS += -DSTD_INSPIRED LOCAL_CFLAGS += -DSTD_INSPIRED
# Obviously, we want to be thread-safe.
LOCAL_CFLAGS += -DTHREAD_SAFE LOCAL_CFLAGS += -DTHREAD_SAFE
# The name of the tm_gmtoff field in our struct tm. # The name of the tm_gmtoff field in our struct tm.
LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
@ -765,8 +731,6 @@ LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\" LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
# Include timezone and daylight globals. # Include timezone and daylight globals.
LOCAL_CFLAGS += -DUSG_COMPAT=1 LOCAL_CFLAGS += -DUSG_COMPAT=1
# Use the empty string (instead of " ") as the timezone abbreviation fallback.
LOCAL_CFLAGS += -DWILDABBR=\"\"
LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
LOCAL_CFLAGS += -Dlint LOCAL_CFLAGS += -Dlint
@ -975,7 +939,6 @@ LOCAL_SANITIZE := never
LOCAL_NATIVE_COVERAGE := $(bionic_coverage) LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags)) $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_openbsd_src_files))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES_EXCLUDE,libc_openbsd_src_files_exclude)) $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES_EXCLUDE,libc_openbsd_src_files_exclude))
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
@ -1071,6 +1034,24 @@ $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files)) $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files))
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(libc_thread_atexit_impl_src_files)
LOCAL_CFLAGS := $(libc_common_cflags) -Wframe-larger-than=2048
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_thread_atexit_impl
# TODO: Clang tries to use __tls_get_addr which is not supported yet
# remove after it is implemented.
LOCAL_CLANG := false
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_CXX_STL := none
LOCAL_SYSTEM_SHARED_LIBRARIES :=
LOCAL_SANITIZE := never
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
include $(BUILD_STATIC_LIBRARY)
# ======================================================== # ========================================================
# libc_pthread.a - pthreads parts that previously lived in # libc_pthread.a - pthreads parts that previously lived in
@ -1228,7 +1209,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
LOCAL_CXX_STL := none LOCAL_CXX_STL := none
ifneq ($(MALLOC_SVELTE),true) ifneq ($(MALLOC_IMPL),dlmalloc)
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
endif endif
@ -1268,6 +1249,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
libc_pthread \ libc_pthread \
libc_stack_protector \ libc_stack_protector \
libc_syscalls \ libc_syscalls \
libc_thread_atexit_impl \
libc_tzcode \ libc_tzcode \
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
@ -1300,6 +1282,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
$(libc_arch_static_src_files) \ $(libc_arch_static_src_files) \
bionic/libc_init_static.cpp
LOCAL_C_INCLUDES := $(libc_common_c_includes) LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_CFLAGS := $(libc_common_cflags) \ LOCAL_CFLAGS := $(libc_common_cflags) \
@ -1311,7 +1294,7 @@ LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_MODULE := libc_nomalloc LOCAL_MODULE := libc_nomalloc
LOCAL_CLANG := $(use_clang) LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies) LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common libc_init_static LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_CXX_STL := none LOCAL_CXX_STL := none
LOCAL_SYSTEM_SHARED_LIBRARIES := LOCAL_SYSTEM_SHARED_LIBRARIES :=
LOCAL_SANITIZE := never LOCAL_SANITIZE := never
@ -1351,6 +1334,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
$(libc_arch_static_src_files) \ $(libc_arch_static_src_files) \
bionic/malloc_debug_common.cpp \ bionic/malloc_debug_common.cpp \
bionic/libc_init_static.cpp \
LOCAL_CFLAGS := $(libc_common_cflags) \ LOCAL_CFLAGS := $(libc_common_cflags) \
-DLIBC_STATIC \ -DLIBC_STATIC \
@ -1361,9 +1345,9 @@ LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc LOCAL_MODULE := libc
LOCAL_CLANG := $(use_clang) LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies) LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common libc_init_static LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
ifneq ($(MALLOC_SVELTE),true) ifneq ($(MALLOC_IMPL),dlmalloc)
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
endif endif
@ -1407,9 +1391,6 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
$(LOCAL_PATH)/libc.mips64.map \ $(LOCAL_PATH)/libc.mips64.map \
$(LOCAL_PATH)/libc.x86.map \ $(LOCAL_PATH)/libc.x86.map \
$(LOCAL_PATH)/libc.x86_64.map \ $(LOCAL_PATH)/libc.x86_64.map \
$(LOCAL_PATH)/libc.arm.brillo.map \
$(LOCAL_PATH)/libc.mips.brillo.map \
$(LOCAL_PATH)/libc.x86.brillo.map \
# Leave the symbols in the shared library so that stack unwinders can produce # Leave the symbols in the shared library so that stack unwinders can produce
# meaningful name resolution. # meaningful name resolution.
@ -1429,7 +1410,7 @@ LOCAL_PACK_MODULE_RELOCATIONS := false
LOCAL_SHARED_LIBRARIES := libdl LOCAL_SHARED_LIBRARIES := libdl
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
ifneq ($(MALLOC_SVELTE),true) ifneq ($(MALLOC_IMPL),dlmalloc)
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
endif endif
@ -1441,18 +1422,11 @@ LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
# Don't re-export new/delete and friends, even if the compiler really wants to. # Don't re-export new/delete and friends, even if the compiler really wants to.
ifdef BRILLO
LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.brillo.map
LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libc.mips.brillo.map
LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.brillo.map
else
LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.map LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.map
LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libc.mips.map
LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.map
endif
LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libc.arm64.map LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libc.arm64.map
LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libc.mips.map
LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libc.mips64.map LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libc.mips64.map
LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.map
LOCAL_LDFLAGS_x86_64 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86_64.map LOCAL_LDFLAGS_x86_64 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86_64.map
# We'd really like to do this for all architectures, but since this wasn't done # We'd really like to do this for all architectures, but since this wasn't done

View File

@ -107,7 +107,7 @@ ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) arm64,mips64
int ___close:close(int) all int ___close:close(int) all
pid_t __getpid:getpid() all pid_t __getpid:getpid() all
int munmap(void*, size_t) all int munmap(void*, size_t) all
void* ___mremap:mremap(void*, size_t, size_t, int, void*) all void* mremap(void*, size_t, size_t, unsigned long) all
int msync(const void*, size_t, int) all int msync(const void*, size_t, int) all
int mprotect(const void*, size_t, int) all int mprotect(const void*, size_t, int) all
int madvise(void*, size_t, int) all int madvise(void*, size_t, int) all

View File

@ -51,62 +51,34 @@ extern int __cxa_atexit(void (*)(void*), void*, void*);
*/ */
int __attribute__((weak)) int __attribute__((weak))
__aeabi_atexit_impl(void *object, void (*destructor) (void *), void *dso_handle) { __aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
return __cxa_atexit(destructor, object, dso_handle);
}
int __attribute__((weak))
__aeabi_atexit_impl2(void *object, void (*destructor) (void *), void *dso_handle) {
return __cxa_atexit(destructor, object, dso_handle); return __cxa_atexit(destructor, object, dso_handle);
} }
void __attribute__((weak)) __aeabi_memcpy8_impl(void *dest, const void *src, size_t n) { void __attribute__((weak))
__aeabi_memcpy8(void *dest, const void *src, size_t n) {
memcpy(dest, src, n); memcpy(dest, src, n);
} }
void __attribute__((weak)) __aeabi_memcpy4_impl(void *dest, const void *src, size_t n) { void __attribute__((weak)) __aeabi_memcpy4(void *dest, const void *src, size_t n) {
memcpy(dest, src, n); memcpy(dest, src, n);
} }
void __attribute__((weak)) __aeabi_memcpy_impl(void *dest, const void *src, size_t n) { void __attribute__((weak)) __aeabi_memcpy(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy8_impl2(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy4_impl2(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy_impl2(void *dest, const void *src, size_t n) {
memcpy(dest, src, n); memcpy(dest, src, n);
} }
void __attribute__((weak)) __aeabi_memmove8_impl(void *dest, const void *src, size_t n) { void __attribute__((weak)) __aeabi_memmove8(void *dest, const void *src, size_t n) {
memmove(dest, src, n); memmove(dest, src, n);
} }
void __attribute__((weak)) __aeabi_memmove4_impl(void *dest, const void *src, size_t n) { void __attribute__((weak)) __aeabi_memmove4(void *dest, const void *src, size_t n) {
memmove(dest, src, n); memmove(dest, src, n);
} }
void __attribute__((weak)) __aeabi_memmove_impl(void *dest, const void *src, size_t n) { void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove8_impl2(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove4_impl2(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove_impl2(void *dest, const void *src, size_t n) {
memmove(dest, src, n); memmove(dest, src, n);
} }
@ -115,71 +87,27 @@ void __attribute__((weak)) __aeabi_memmove_impl2(void *dest, const void *src, si
* This allows __aeabi_memclr to tail-call __aeabi_memset * This allows __aeabi_memclr to tail-call __aeabi_memset
*/ */
void __attribute__((weak)) __aeabi_memset8_impl(void *dest, size_t n, int c) { void __attribute__((weak)) __aeabi_memset8(void *dest, size_t n, int c) {
memset(dest, c, n); memset(dest, c, n);
} }
void __attribute__((weak)) __aeabi_memset4_impl(void *dest, size_t n, int c) { void __attribute__((weak)) __aeabi_memset4(void *dest, size_t n, int c) {
memset(dest, c, n); memset(dest, c, n);
} }
void __attribute__((weak)) __aeabi_memset_impl(void *dest, size_t n, int c) { void __attribute__((weak)) __aeabi_memset(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset8_impl2(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset4_impl2(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset_impl2(void *dest, size_t n, int c) {
memset(dest, c, n); memset(dest, c, n);
} }
void __attribute__((weak)) __aeabi_memclr8_impl(void *dest, size_t n) { void __attribute__((weak)) __aeabi_memclr8(void *dest, size_t n) {
__aeabi_memset8_impl(dest, n, 0); __aeabi_memset8(dest, n, 0);
} }
void __attribute__((weak)) __aeabi_memclr4_impl(void *dest, size_t n) { void __attribute__((weak)) __aeabi_memclr4(void *dest, size_t n) {
__aeabi_memset4_impl(dest, n, 0); __aeabi_memset4(dest, n, 0);
} }
void __attribute__((weak)) __aeabi_memclr_impl(void *dest, size_t n) { void __attribute__((weak)) __aeabi_memclr(void *dest, size_t n) {
__aeabi_memset_impl(dest, n, 0); __aeabi_memset(dest, n, 0);
} }
void __attribute__((weak)) __aeabi_memclr8_impl2(void *dest, size_t n) {
__aeabi_memset8_impl(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr4_impl2(void *dest, size_t n) {
__aeabi_memset4_impl(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr_impl2(void *dest, size_t n) {
__aeabi_memset_impl(dest, n, 0);
}
#define __AEABI_SYMVERS(fn_name) \
__asm__(".symver " #fn_name "_impl, " #fn_name "@@LIBC_N"); \
__asm__(".symver " #fn_name "_impl2, " #fn_name "@LIBC_PRIVATE")
__AEABI_SYMVERS(__aeabi_atexit);
__AEABI_SYMVERS(__aeabi_memcpy8);
__AEABI_SYMVERS(__aeabi_memcpy4);
__AEABI_SYMVERS(__aeabi_memcpy);
__AEABI_SYMVERS(__aeabi_memmove8);
__AEABI_SYMVERS(__aeabi_memmove4);
__AEABI_SYMVERS(__aeabi_memmove);
__AEABI_SYMVERS(__aeabi_memset8);
__AEABI_SYMVERS(__aeabi_memset4);
__AEABI_SYMVERS(__aeabi_memset);
__AEABI_SYMVERS(__aeabi_memclr8);
__AEABI_SYMVERS(__aeabi_memclr4);
__AEABI_SYMVERS(__aeabi_memclr);
#undef __AEABI_SYMVERS

View File

@ -37,13 +37,7 @@
* the expectation that libc will define it and call through to * the expectation that libc will define it and call through to
* a differently-named function in the dynamic linker. * a differently-named function in the dynamic linker.
*/ */
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl(_Unwind_Ptr pc, int *pcount) { _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount)
{
return dl_unwind_find_exidx(pc, pcount); return dl_unwind_find_exidx(pc, pcount);
} }
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl2(_Unwind_Ptr pc, int *pcount) {
return dl_unwind_find_exidx(pc, pcount);
}
__asm__(".symver __gnu_Unwind_Find_exidx_impl,__gnu_Unwind_Find_exidx@LIBC_PRIVATE");
__asm__(".symver __gnu_Unwind_Find_exidx_impl2,__gnu_Unwind_Find_exidx@@LIBC_N");

View File

@ -1,23 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(___mremap)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
ldmfd ip, {r4, r5, r6}
ldr r7, =__NR_mremap
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(___mremap)
.hidden ___mremap

View File

@ -0,0 +1,14 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(mremap)
mov ip, r7
ldr r7, =__NR_mremap
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(mremap)

View File

@ -42,6 +42,7 @@ libc_bionic_src_files_arm64 += \
arch-arm64/bionic/__bionic_clone.S \ arch-arm64/bionic/__bionic_clone.S \
arch-arm64/bionic/_exit_with_stack_teardown.S \ arch-arm64/bionic/_exit_with_stack_teardown.S \
arch-arm64/bionic/setjmp.S \ arch-arm64/bionic/setjmp.S \
arch-arm64/bionic/__set_tls.c \
arch-arm64/bionic/syscall.S \ arch-arm64/bionic/syscall.S \
arch-arm64/bionic/vfork.S \ arch-arm64/bionic/vfork.S \

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(___mremap) ENTRY(mremap)
mov x8, __NR_mremap mov x8, __NR_mremap
svc #0 svc #0
@ -11,5 +11,4 @@ ENTRY(___mremap)
b.hi __set_errno_internal b.hi __set_errno_internal
ret ret
END(___mremap) END(mremap)
.hidden ___mremap

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(___mremap) ENTRY(mremap)
.set noreorder .set noreorder
.cpload t9 .cpload t9
li v0, __NR_mremap li v0, __NR_mremap
@ -16,5 +16,4 @@ ENTRY(___mremap)
j t9 j t9
nop nop
.set reorder .set reorder
END(___mremap) END(mremap)
.hidden ___mremap

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(___mremap) ENTRY(mremap)
.set push .set push
.set noreorder .set noreorder
li v0, __NR_mremap li v0, __NR_mremap
@ -22,5 +22,4 @@ ENTRY(___mremap)
j t9 j t9
move ra, t0 move ra, t0
.set pop .set pop
END(___mremap) END(mremap)
.hidden ___mremap

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(___mremap) ENTRY(mremap)
pushl %ebx pushl %ebx
.cfi_def_cfa_offset 8 .cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0 .cfi_rel_offset ebx, 0
@ -15,14 +15,10 @@ ENTRY(___mremap)
pushl %esi pushl %esi
.cfi_adjust_cfa_offset 4 .cfi_adjust_cfa_offset 4
.cfi_rel_offset esi, 0 .cfi_rel_offset esi, 0
pushl %edi mov 20(%esp), %ebx
.cfi_adjust_cfa_offset 4 mov 24(%esp), %ecx
.cfi_rel_offset edi, 0 mov 28(%esp), %edx
mov 24(%esp), %ebx mov 32(%esp), %esi
mov 28(%esp), %ecx
mov 32(%esp), %edx
mov 36(%esp), %esi
mov 40(%esp), %edi
movl $__NR_mremap, %eax movl $__NR_mremap, %eax
int $0x80 int $0x80
cmpl $-MAX_ERRNO, %eax cmpl $-MAX_ERRNO, %eax
@ -32,11 +28,9 @@ ENTRY(___mremap)
call __set_errno_internal call __set_errno_internal
addl $4, %esp addl $4, %esp
1: 1:
popl %edi
popl %esi popl %esi
popl %edx popl %edx
popl %ecx popl %ecx
popl %ebx popl %ebx
ret ret
END(___mremap) END(mremap)
.hidden ___mremap

View File

@ -109,6 +109,7 @@ libc_bionic_src_files_x86 += \
arch-x86/bionic/libgcc_compat.c \ arch-x86/bionic/libgcc_compat.c \
arch-x86/bionic/__restore.S \ arch-x86/bionic/__restore.S \
arch-x86/bionic/setjmp.S \ arch-x86/bionic/setjmp.S \
arch-x86/bionic/__set_tls.c \
arch-x86/bionic/syscall.S \ arch-x86/bionic/syscall.S \
arch-x86/bionic/vfork.S \ arch-x86/bionic/vfork.S \

View File

@ -2,7 +2,7 @@
#include <private/bionic_asm.h> #include <private/bionic_asm.h>
ENTRY(___mremap) ENTRY(mremap)
movq %rcx, %r10 movq %rcx, %r10
movl $__NR_mremap, %eax movl $__NR_mremap, %eax
syscall syscall
@ -13,5 +13,4 @@ ENTRY(___mremap)
call __set_errno_internal call __set_errno_internal
1: 1:
ret ret
END(___mremap) END(mremap)
.hidden ___mremap

View File

@ -25,6 +25,7 @@ libc_bionic_src_files_x86_64 += \
arch-x86_64/bionic/_exit_with_stack_teardown.S \ arch-x86_64/bionic/_exit_with_stack_teardown.S \
arch-x86_64/bionic/__restore_rt.S \ arch-x86_64/bionic/__restore_rt.S \
arch-x86_64/bionic/setjmp.S \ arch-x86_64/bionic/setjmp.S \
arch-x86_64/bionic/__set_tls.c \
arch-x86_64/bionic/syscall.S \ arch-x86_64/bionic/syscall.S \
arch-x86_64/bionic/vfork.S \ arch-x86_64/bionic/vfork.S \

View File

@ -109,7 +109,7 @@ extern "C" int __cxa_guard_acquire(_guard_t* gv) {
} }
} }
__futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, false, nullptr); __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, NULL);
old_value = atomic_load_explicit(&gv->state, memory_order_relaxed); old_value = atomic_load_explicit(&gv->state, memory_order_relaxed);
} }
} }

View File

@ -15,34 +15,32 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "pthread_internal.h" struct thread_local_dtor {
class thread_local_dtor {
public:
void (*func) (void *); void (*func) (void *);
void *arg; void *arg;
void *dso_handle; // unused... void *dso_handle; // unused...
thread_local_dtor* next; thread_local_dtor* next;
}; };
static __thread thread_local_dtor* thread_local_dtors = nullptr;
extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) { extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
thread_local_dtor* dtor = new thread_local_dtor(); thread_local_dtor* dtor = new thread_local_dtor();
dtor->func = func; dtor->func = func;
dtor->arg = arg; dtor->arg = arg;
dtor->dso_handle = dso_handle; dtor->dso_handle = dso_handle;
dtor->next = thread_local_dtors;
thread_local_dtors = dtor;
pthread_internal_t* thread = __get_thread();
dtor->next = thread->thread_local_dtors;
thread->thread_local_dtors = dtor;
return 0; return 0;
} }
extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() { extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
pthread_internal_t* thread = __get_thread(); while (thread_local_dtors != nullptr) {
while (thread->thread_local_dtors != nullptr) { thread_local_dtor* current = thread_local_dtors;
thread_local_dtor* current = thread->thread_local_dtors; thread_local_dtors = current->next;
thread->thread_local_dtors = current->next;
current->func(current->arg); current->func(current->arg);
delete current; delete current;

View File

@ -1,85 +0,0 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "libc_init_common.h"
#include "private/bionic_auxv.h"
#include "private/bionic_globals.h"
#include "private/KernelArgumentBlock.h"
#include "pthread_internal.h"
extern "C" int __set_tls(void* ptr);
extern "C" int __set_tid_address(int* tid_address);
// Setup for the main thread. For dynamic executables, this is called by the
// linker _before_ libc is mapped in memory. This means that all writes to
// globals from this function will apply to linker-private copies and will not
// be visible from libc later on.
//
// Note: this function creates a pthread_internal_t for the initial thread and
// stores the pointer in TLS, but does not add it to pthread's thread list. This
// has to be done later from libc itself (see __libc_init_common).
//
// This is in a file by itself because it needs to be built with
// -fno-stack-protector because it's responsible for setting up the main
// thread's TLS (which stack protector relies on).
void __libc_init_main_thread(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
static pthread_internal_t main_thread;
// The -fstack-protector implementation uses TLS, so make sure that's
// set up before we call any function that might get a stack check inserted.
__set_tls(main_thread.tls);
// Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
// As a side-effect, this tells us our pid (which is the same as the main thread's tid).
main_thread.tid = __set_tid_address(&main_thread.tid);
main_thread.set_cached_pid(main_thread.tid);
// We don't want to free the main thread's stack even when the main thread exits
// because things like environment variables with global scope live on it.
// We also can't free the pthread_internal_t itself, since that lives on the main
// thread's stack rather than on the heap.
// The main thread has no mmap allocated space for stack or pthread_internal_t.
main_thread.mmap_size = 0;
pthread_attr_init(&main_thread.attr);
main_thread.attr.guard_size = 0; // The main thread has no guard page.
main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
// TODO: the main thread's sched_policy and sched_priority need to be queried.
__init_thread(&main_thread);
__init_tls(&main_thread);
// Store a pointer to the kernel argument block in a TLS slot to be
// picked up by the libc constructor.
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
__init_alternate_signal_stack(&main_thread);
}

View File

@ -34,25 +34,27 @@ constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
static Lock g_lock; static Lock g_lock;
static const prop_info* g_pinfo; static const prop_info* g_pinfo;
static uint32_t g_property_serial = -1; static uint32_t g_serial = -1;
static uint32_t g_property_area_serial = -1;
static uint64_t g_tags; static uint64_t g_tags;
static int g_trace_marker_fd = -1; static int g_trace_marker_fd = -1;
static bool should_trace() { static bool should_trace() {
bool result = false; bool result = false;
g_lock.lock(); g_lock.lock();
// debug.atrace.tags.enableflags is set to a safe non-tracing value during property // If g_pinfo is null, this means that systrace hasn't been run and it's safe to
// space initialization, so it should only be null in two cases, if there are // assume that no trace writing will need to take place. However, to avoid running
// insufficient permissions for this process to access the property, in which // this costly find check each time, we set it to a non-tracing value so that next
// case an audit will be logged, and during boot before the property server has // time, it will just check the serial to see if the value has been changed.
// been started, in which case we store the global property_area serial to prevent // this function also deals with the bootup case, during which the call to property
// the costly find operation until we see a changed property_area. // set will fail if the property server hasn't yet started.
if (!g_pinfo && g_property_area_serial != __system_property_area_serial()) { if (g_pinfo == NULL) {
g_property_area_serial = __system_property_area_serial(); g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
if (g_pinfo == NULL) {
__system_property_set(SYSTRACE_PROPERTY_NAME, "0");
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME); g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
} }
if (g_pinfo) { }
if (g_pinfo != NULL) {
// Find out which tags have been enabled on the command line and set // Find out which tags have been enabled on the command line and set
// the value of tags accordingly. If the value of the property changes, // the value of tags accordingly. If the value of the property changes,
// the serial will also change, so the costly system_property_read function // the serial will also change, so the costly system_property_read function
@ -60,11 +62,11 @@ static bool should_trace() {
// first. The values within pinfo may change, but its location is guaranteed // first. The values within pinfo may change, but its location is guaranteed
// not to move. // not to move.
uint32_t cur_serial = __system_property_serial(g_pinfo); uint32_t cur_serial = __system_property_serial(g_pinfo);
if (cur_serial != g_property_serial) { if (cur_serial != g_serial) {
g_property_serial = cur_serial; g_serial = cur_serial;
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
__system_property_read(g_pinfo, 0, value); __system_property_read(g_pinfo, 0, value);
g_tags = strtoull(value, nullptr, 0); g_tags = strtoull(value, NULL, 0);
} }
result = ((g_tags & ATRACE_TAG_BIONIC) != 0); result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
} }

View File

@ -52,12 +52,18 @@ void timeval_from_timespec(timeval& tv, const timespec& ts) {
tv.tv_usec = ts.tv_nsec / 1000; tv.tv_usec = ts.tv_nsec / 1000;
} }
void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, clockid_t clock) { // Initializes 'ts' with the difference between 'abs_ts' and the current time
clock_gettime(clock, &abs_ts); // according to 'clock'. Returns false if abstime already expired, true otherwise.
abs_ts.tv_sec += ts.tv_sec; bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) {
abs_ts.tv_nsec += ts.tv_nsec; clock_gettime(clock, &ts);
if (abs_ts.tv_nsec >= NS_PER_S) { ts.tv_sec = abs_ts.tv_sec - ts.tv_sec;
abs_ts.tv_nsec -= NS_PER_S; ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec;
abs_ts.tv_sec++; if (ts.tv_nsec < 0) {
ts.tv_sec--;
ts.tv_nsec += NS_PER_S;
} }
if (ts.tv_nsec < 0 || ts.tv_sec < 0) {
return false;
}
return true;
} }

View File

@ -36,15 +36,23 @@
// struct __sfileext (see fileext.h). // struct __sfileext (see fileext.h).
void flockfile(FILE* fp) { void flockfile(FILE* fp) {
if (fp != nullptr) { if (!__sdidinit) {
__sinit();
}
if (fp != NULL) {
pthread_mutex_lock(&_FLOCK(fp)); pthread_mutex_lock(&_FLOCK(fp));
} }
} }
int ftrylockfile(FILE* fp) { int ftrylockfile(FILE* fp) {
if (!__sdidinit) {
__sinit();
}
// The specification for ftrylockfile() says it returns 0 on success, // The specification for ftrylockfile() says it returns 0 on success,
// or non-zero on error. So return an errno code directly on error. // or non-zero on error. So return an errno code directly on error.
if (fp == nullptr) { if (fp == NULL) {
return EINVAL; return EINVAL;
} }
@ -52,7 +60,11 @@ int ftrylockfile(FILE* fp) {
} }
void funlockfile(FILE* fp) { void funlockfile(FILE* fp) {
if (fp != nullptr) { if (!__sdidinit) {
__sinit();
}
if (fp != NULL) {
pthread_mutex_unlock(&_FLOCK(fp)); pthread_mutex_unlock(&_FLOCK(fp));
} }
} }

View File

@ -1,241 +0,0 @@
/*
* 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 <ifaddrs.h>
#include <errno.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// The public ifaddrs struct is full of pointers. Rather than track several
// different allocations, we use a maximally-sized structure with the public
// part at offset 0, and pointers into its hidden tail.
struct ifaddrs_storage {
// Must come first, so that `ifaddrs_storage` is-a `ifaddrs`.
ifaddrs ifa;
// The interface index, so we can match RTM_NEWADDR messages with
// earlier RTM_NEWLINK messages (to copy the interface flags).
int interface_index;
// Storage for the pointers in `ifa`.
sockaddr_storage addr;
sockaddr_storage netmask;
sockaddr_storage ifa_ifu;
char name[IFNAMSIZ + 1];
ifaddrs_storage(ifaddrs** list) {
memset(this, 0, sizeof(*this));
// push_front onto `list`.
ifa.ifa_next = *list;
*list = reinterpret_cast<ifaddrs*>(this);
}
// Netlink gives us the address family in the header, and the
// sockaddr_in or sockaddr_in6 bytes as the payload. We need to
// stitch the two bits together into the sockaddr that's part of
// our portable interface.
void SetAddress(int family, const void* data, size_t byteCount) {
addr.ss_family = family;
memcpy(SockaddrBytes(family, &addr), data, byteCount);
ifa.ifa_addr = reinterpret_cast<sockaddr*>(&addr);
}
void SetBroadcastAddress(int family, const void* data, size_t byteCount) {
ifa_ifu.ss_family = family;
memcpy(SockaddrBytes(family, &ifa_ifu), data, byteCount);
ifa.ifa_dstaddr = reinterpret_cast<sockaddr*>(&ifa_ifu);
}
// Netlink gives us the prefix length as a bit count. We need to turn
// that into a BSD-compatible netmask represented by a sockaddr*.
void SetNetmask(int family, size_t prefix_length) {
// ...and work out the netmask from the prefix length.
netmask.ss_family = family;
uint8_t* dst = SockaddrBytes(family, &netmask);
memset(dst, 0xff, prefix_length / 8);
if ((prefix_length % 8) != 0) {
dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));
}
ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);
}
private:
// Returns a pointer to the first byte in the address data (which is
// stored in network byte order).
uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) {
if (family == AF_INET) {
sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
} else if (family == AF_INET6) {
sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
}
return nullptr;
}
};
#if !defined(__clang__)
// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style
// cast is from a system header and should be ignored.
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {
if (hdr->nlmsg_type == RTM_NEWLINK) {
ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
// Create a new ifaddr entry, and set the interface index and flags.
ifaddrs_storage* new_addr = new ifaddrs_storage(out);
new_addr->interface_index = ifi->ifi_index;
new_addr->ifa.ifa_flags = ifi->ifi_flags;
// Go through the various bits of information and find the name.
rtattr* rta = IFLA_RTA(ifi);
size_t rta_len = IFLA_PAYLOAD(hdr);
while (RTA_OK(rta, rta_len)) {
if (rta->rta_type == IFLA_IFNAME) {
if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) {
memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta));
new_addr->ifa.ifa_name = new_addr->name;
}
}
rta = RTA_NEXT(rta, rta_len);
}
} else if (hdr->nlmsg_type == RTM_NEWADDR) {
ifaddrmsg* msg = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
// We should already know about this from an RTM_NEWLINK message.
ifaddrs_storage* addr = reinterpret_cast<ifaddrs_storage*>(*out);
while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
addr = reinterpret_cast<ifaddrs_storage*>(addr->ifa.ifa_next);
}
// If this is an unknown interface, ignore whatever we're being told about it.
if (addr == nullptr) return;
// Create a new ifaddr entry and copy what we already know.
ifaddrs_storage* new_addr = new ifaddrs_storage(out);
// We can just copy the name rather than look for IFA_LABEL.
strcpy(new_addr->name, addr->name);
new_addr->ifa.ifa_name = new_addr->name;
new_addr->ifa.ifa_flags = addr->ifa.ifa_flags;
new_addr->interface_index = addr->interface_index;
// Go through the various bits of information and find the address
// and any broadcast/destination address.
rtattr* rta = IFA_RTA(msg);
size_t rta_len = IFA_PAYLOAD(hdr);
while (RTA_OK(rta, rta_len)) {
if (rta->rta_type == IFA_ADDRESS) {
if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);
}
} else if (rta->rta_type == IFA_BROADCAST) {
if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
}
}
rta = RTA_NEXT(rta, rta_len);
}
}
}
static bool __send_netlink_request(int fd, int type) {
struct NetlinkMessage {
nlmsghdr hdr;
rtgenmsg msg;
} request;
memset(&request, 0, sizeof(request));
request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
request.hdr.nlmsg_type = type;
request.hdr.nlmsg_len = sizeof(request);
request.msg.rtgen_family = AF_UNSPEC; // All families.
return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request));
}
static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) {
ssize_t bytes_read;
// Read through all the responses, handing interesting ones to __handle_netlink_response.
while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) {
nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf);
for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
if (hdr->nlmsg_type == NLMSG_DONE) return true;
if (hdr->nlmsg_type == NLMSG_ERROR) return false;
__handle_netlink_response(out, hdr);
}
}
// We only get here if recv fails before we see a NLMSG_DONE.
return false;
}
int getifaddrs(ifaddrs** out) {
// Make cleanup easy.
*out = nullptr;
// The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),
// but that's a bit too large to go on the stack.
size_t buf_len = 8192;
char* buf = new char[buf_len];
if (buf == nullptr) return -1;
// Open the netlink socket and ask for all the links and addresses.
int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
bool okay = fd != -1 &&
__send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) &&
__send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len);
if (!okay) {
freeifaddrs(*out);
// Ensure that callers crash if they forget to check for success.
*out = nullptr;
}
{
int saved_errno = errno;
close(fd);
delete[] buf;
errno = saved_errno;
}
return okay ? 0 : -1;
}
void freeifaddrs(ifaddrs* list) {
while (list != nullptr) {
ifaddrs* current = list;
list = list->ifa_next;
free(current);
}
}

View File

@ -25,16 +25,19 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <sys/ioctl.h>
#include <stdarg.h> #include <stdarg.h>
extern "C" int __ioctl(int, int, void *); extern int __ioctl(int, int, void *);
int ioctl(int fd, int request, ...) { int ioctl(int fd, int request, ...)
{
va_list ap; va_list ap;
void * arg;
va_start(ap, request); va_start(ap, request);
void* arg = va_arg(ap, void*); arg = va_arg(ap, void *);
va_end(ap); va_end(ap);
return __ioctl(fd, request, arg); return __ioctl(fd, request, arg);
} }

View File

@ -52,6 +52,8 @@
extern "C" abort_msg_t** __abort_message_ptr; extern "C" abort_msg_t** __abort_message_ptr;
extern "C" int __system_properties_init(void); extern "C" int __system_properties_init(void);
extern "C" int __set_tls(void* ptr);
extern "C" int __set_tid_address(int* tid_address);
__LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals; __LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals;
@ -64,11 +66,50 @@ char** environ;
// Declared in "private/bionic_ssp.h". // Declared in "private/bionic_ssp.h".
uintptr_t __stack_chk_guard = 0; uintptr_t __stack_chk_guard = 0;
// Setup for the main thread. For dynamic executables, this is called by the
// linker _before_ libc is mapped in memory. This means that all writes to
// globals from this function will apply to linker-private copies and will not
// be visible from libc later on.
//
// Note: this function creates a pthread_internal_t for the initial thread and
// stores the pointer in TLS, but does not add it to pthread's thread list. This
// has to be done later from libc itself (see __libc_init_common).
void __libc_init_main_thread(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
static pthread_internal_t main_thread;
// Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
// As a side-effect, this tells us our pid (which is the same as the main thread's tid).
main_thread.tid = __set_tid_address(&main_thread.tid);
main_thread.set_cached_pid(main_thread.tid);
// We don't want to free the main thread's stack even when the main thread exits
// because things like environment variables with global scope live on it.
// We also can't free the pthread_internal_t itself, since that lives on the main
// thread's stack rather than on the heap.
// The main thread has no mmap allocated space for stack or pthread_internal_t.
main_thread.mmap_size = 0;
pthread_attr_init(&main_thread.attr);
main_thread.attr.guard_size = 0; // The main thread has no guard page.
main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
// TODO: the main thread's sched_policy and sched_priority need to be queried.
__init_thread(&main_thread);
__init_tls(&main_thread);
__set_tls(main_thread.tls);
// Store a pointer to the kernel argument block in a TLS slot to be
// picked up by the libc constructor.
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
__init_alternate_signal_stack(&main_thread);
}
void __libc_init_globals(KernelArgumentBlock& args) { void __libc_init_globals(KernelArgumentBlock& args) {
// Initialize libc globals that are needed in both the linker and in libc. // Initialize libc globals that are needed in both the linker and in libc.
// In dynamic binaries, this is run at least twice for different copies of the // In dynamic binaries, this is run at least twice for different copies of the
// globals, once for the linker's copy and once for the one in libc.so. // globals, once for the linker's copy and once for the one in libc.so.
__libc_auxv = args.auxv;
__libc_globals.initialize(); __libc_globals.initialize();
__libc_globals.mutate([&args](libc_globals* globals) { __libc_globals.mutate([&args](libc_globals* globals) {
__libc_init_vdso(globals, args); __libc_init_vdso(globals, args);
@ -80,6 +121,7 @@ void __libc_init_common(KernelArgumentBlock& args) {
// Initialize various globals. // Initialize various globals.
environ = args.envp; environ = args.envp;
errno = 0; errno = 0;
__libc_auxv = args.auxv;
__progname = args.argv[0] ? args.argv[0] : "<unknown>"; __progname = args.argv[0] ? args.argv[0] : "<unknown>";
__abort_message_ptr = args.abort_message_ptr; __abort_message_ptr = args.abort_message_ptr;
@ -203,11 +245,7 @@ static bool __is_valid_environment_variable(const char* name) {
} }
static bool __is_unsafe_environment_variable(const char* name) { static bool __is_unsafe_environment_variable(const char* name) {
// None of these should be allowed when the AT_SECURE auxv // None of these should be allowed in setuid programs.
// flag is set. This flag is set to inform userspace that a
// security transition has occurred, for example, as a result
// of executing a setuid program or the result of an SELinux
// security transition.
static constexpr const char* UNSAFE_VARIABLE_NAMES[] = { static constexpr const char* UNSAFE_VARIABLE_NAMES[] = {
"GCONV_PATH", "GCONV_PATH",
"GETCONF_DIR", "GETCONF_DIR",
@ -291,7 +329,7 @@ void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
if (getauxval(AT_SECURE)) { if (getauxval(AT_SECURE)) {
// If this is a setuid/setgid program, close the security hole described in // If this is a setuid/setgid program, close the security hole described in
// https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc // ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
__nullify_closed_stdio(); __nullify_closed_stdio();
__sanitize_environment_variables(args.envp); __sanitize_environment_variables(args.envp);

View File

@ -25,7 +25,6 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/* /*
* libc_init_dynamic.c * libc_init_dynamic.c
* *

View File

@ -25,6 +25,17 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/*
* libc_init_static.c
*
* The program startup function __libc_init() defined here is
* used for static executables only (i.e. those that don't depend
* on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
* which is directly invoked by the kernel when the program is launched.
*
* The 'structors' parameter contains pointers to various initializer
* arrays that must be run before the program's 'main' routine is launched.
*/
#include <elf.h> #include <elf.h>
#include <errno.h> #include <errno.h>
@ -68,19 +79,12 @@ static void apply_gnu_relro() {
} }
} }
// The program startup function __libc_init() defined here is
// used for static executables only (i.e. those that don't depend
// on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
// which is directly invoked by the kernel when the program is launched.
//
// The 'structors' parameter contains pointers to various initializer
// arrays that must be run before the program's 'main' routine is launched.
__noreturn void __libc_init(void* raw_args, __noreturn void __libc_init(void* raw_args,
void (*onexit)(void) __unused, void (*onexit)(void) __unused,
int (*slingshot)(int, char**, char**), int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) { structors_array_t const * const structors) {
KernelArgumentBlock args(raw_args); KernelArgumentBlock args(raw_args);
__libc_init_main_thread(args); __libc_init_main_thread(args);
// Initializing the globals requires TLS to be available for errno. // Initializing the globals requires TLS to be available for errno.

View File

@ -31,7 +31,6 @@
#include <android/set_abort_message.h> #include <android/set_abort_message.h>
#include <assert.h> #include <assert.h>
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <pthread.h> #include <pthread.h>
@ -47,9 +46,6 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. __LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
@ -485,64 +481,6 @@ static int __libc_open_log_socket() {
return log_fd; return log_fd;
} }
struct cache {
const prop_info* pinfo;
uint32_t serial;
char c;
};
static void refresh_cache(struct cache *cache, const char *key)
{
if (!cache->pinfo) {
cache->pinfo = __system_property_find(key);
if (!cache->pinfo) {
return;
}
}
uint32_t serial = __system_property_serial(cache->pinfo);
if (serial == cache->serial) {
return;
}
cache->serial = serial;
char buf[PROP_VALUE_MAX];
__system_property_read(cache->pinfo, 0, buf);
cache->c = buf[0];
}
// Timestamp state generally remains constant, since a change is
// rare, we can accept a trylock failure gracefully.
static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER;
static clockid_t __android_log_clockid()
{
static struct cache r_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
static struct cache p_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
char c;
if (pthread_mutex_trylock(&lock_clockid)) {
// We are willing to accept some race in this context
if (!(c = p_time_cache.c)) {
c = r_time_cache.c;
}
} else {
static uint32_t serial;
uint32_t current_serial = __system_property_area_serial();
if (current_serial != serial) {
refresh_cache(&r_time_cache, "ro.logd.timestamp");
refresh_cache(&p_time_cache, "persist.logd.timestamp");
serial = current_serial;
}
if (!(c = p_time_cache.c)) {
c = r_time_cache.c;
}
pthread_mutex_unlock(&lock_clockid);
}
return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
struct log_time { // Wire format struct log_time { // Wire format
uint32_t tv_sec; uint32_t tv_sec;
uint32_t tv_nsec; uint32_t tv_nsec;
@ -563,7 +501,7 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) {
vec[1].iov_base = &tid; vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid); vec[1].iov_len = sizeof(tid);
timespec ts; timespec ts;
clock_gettime(__android_log_clockid(), &ts); clock_gettime(CLOCK_REALTIME, &ts);
log_time realtime_ts; log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec; realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec; realtime_ts.tv_nsec = ts.tv_nsec;
@ -606,7 +544,7 @@ static int __libc_android_log_event(int32_t tag, char type, const void* payload,
vec[1].iov_base = &tid; vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid); vec[1].iov_len = sizeof(tid);
timespec ts; timespec ts;
clock_gettime(__android_log_clockid(), &ts); clock_gettime(CLOCK_REALTIME, &ts);
log_time realtime_ts; log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec; realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec; realtime_ts.tv_nsec = ts.tv_nsec;

View File

@ -27,7 +27,6 @@
*/ */
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
@ -49,19 +48,15 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse
// prevent allocations large enough for `end - start` to overflow // prevent allocations large enough for `end - start` to overflow
size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE); size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE);
if (rounded < size || rounded > PTRDIFF_MAX) { if (rounded < size || size > PTRDIFF_MAX) {
errno = ENOMEM; errno = ENOMEM;
return MAP_FAILED; return MAP_FAILED;
} }
bool is_private_anonymous = bool is_private_anonymous = (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0;
(flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT); void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE && if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE && is_private_anonymous) {
is_private_anonymous && !is_stack_or_grows_down) {
ErrnoRestorer errno_restorer; ErrnoRestorer errno_restorer;
int rc = madvise(result, size, MADV_MERGEABLE); int rc = madvise(result, size, MADV_MERGEABLE);
if (rc == -1 && errno == EINVAL) { if (rc == -1 && errno == EINVAL) {

View File

@ -1,57 +0,0 @@
/*
* 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 <sys/mman.h>
#include <stdarg.h>
#include <stdint.h>
#include <unistd.h>
#include "private/bionic_macros.h"
extern "C" void* ___mremap(void*, size_t, size_t, int, void*);
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) {
// prevent allocations large enough for `end - start` to overflow
size_t rounded = BIONIC_ALIGN(new_size, PAGE_SIZE);
if (rounded < new_size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
void* new_address = nullptr;
// The optional argument is only valid if the MREMAP_FIXED flag is set,
// so we assume it's not present otherwise.
if ((flags & MREMAP_FIXED) != 0) {
va_list ap;
va_start(ap, flags);
new_address = va_arg(ap, void*);
va_end(ap);
}
return ___mremap(old_address, old_size, new_size, flags, new_address);
}

View File

@ -47,34 +47,37 @@
#include "private/libc_logging.h" #include "private/libc_logging.h"
extern "C" { // Brillo doesn't need to support any legacy cruft.
#if !defined(__BRILLO__)
// Brillo and LP64 don't need to support any legacy cruft. // Most of the cruft is only for 32-bit Android targets.
#if !defined(__BRILLO__) && !defined(__LP64__) #if !defined(__LP64__)
// These were accidentally declared in <unistd.h> because we stupidly used to inline // These were accidentally declared in <unistd.h> because we stupidly used to inline
// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps. // getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
extern "C" {
unsigned int __page_size = PAGE_SIZE; unsigned int __page_size = PAGE_SIZE;
unsigned int __page_shift = 12; unsigned int __page_shift = 12;
}
// TODO: remove this backward compatibility hack (for jb-mr1 strace binaries). // TODO: remove this backward compatibility hack (for jb-mr1 strace binaries).
pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) { extern "C" pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
return wait4(pid, status, options, rusage); return wait4(pid, status, options, rusage);
} }
// TODO: does anything still need this? // TODO: does anything still need this?
int __open() { extern "C" int __open() {
abort(); abort();
} }
// TODO: does anything still need this? // TODO: does anything still need this?
void** __get_tls() { extern "C" void** __get_tls() {
#include "private/__get_tls.h" #include "private/__get_tls.h"
return __get_tls(); return __get_tls();
} }
// This non-standard function was in our <string.h> for some reason. // This non-standard function was in our <string.h> for some reason.
void memswap(void* m1, void* m2, size_t n) { extern "C" void memswap(void* m1, void* m2, size_t n) {
char* p = reinterpret_cast<char*>(m1); char* p = reinterpret_cast<char*>(m1);
char* p_end = p + n; char* p_end = p + n;
char* q = reinterpret_cast<char*>(m2); char* q = reinterpret_cast<char*>(m2);
@ -87,13 +90,13 @@ void memswap(void* m1, void* m2, size_t n) {
} }
} }
int pthread_attr_setstackaddr(pthread_attr_t*, void*) { extern "C" int pthread_attr_setstackaddr(pthread_attr_t*, void*) {
// This was removed from POSIX.1-2008, and is not implemented on bionic. // This was removed from POSIX.1-2008, and is not implemented on bionic.
// Needed for ABI compatibility with the NDK. // Needed for ABI compatibility with the NDK.
return ENOSYS; return ENOSYS;
} }
int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) { extern "C" int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
// This was removed from POSIX.1-2008. // This was removed from POSIX.1-2008.
// Needed for ABI compatibility with the NDK. // Needed for ABI compatibility with the NDK.
*stack_addr = (char*)attr->stack_base + attr->stack_size; *stack_addr = (char*)attr->stack_base + attr->stack_size;
@ -101,7 +104,7 @@ int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
} }
// Non-standard cruft that should only ever have been in system/core/toolbox. // Non-standard cruft that should only ever have been in system/core/toolbox.
char* strtotimeval(const char* str, struct timeval* ts) { extern "C" char* strtotimeval(const char* str, struct timeval* ts) {
char* s; char* s;
ts->tv_sec = strtoumax(str, &s, 10); ts->tv_sec = strtoumax(str, &s, 10);
@ -143,7 +146,7 @@ static inline int digitval(int ch) {
} }
// This non-standard function was in our <inttypes.h> for some reason. // This non-standard function was in our <inttypes.h> for some reason.
uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) { extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
const unsigned char* p = (const unsigned char *)nptr; const unsigned char* p = (const unsigned char *)nptr;
const unsigned char* end = p + n; const unsigned char* end = p + n;
int minus = 0; int minus = 0;
@ -191,12 +194,12 @@ uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
} }
// This non-standard function was in our <inttypes.h> for some reason. // This non-standard function was in our <inttypes.h> for some reason.
intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) { extern "C" intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
return (intmax_t) strntoumax(nptr, endptr, base, n); return (intmax_t) strntoumax(nptr, endptr, base, n);
} }
// POSIX calls this dprintf, but LP32 Android had fdprintf instead. // POSIX calls this dprintf, but LP32 Android had fdprintf instead.
int fdprintf(int fd, const char* fmt, ...) { extern "C" int fdprintf(int fd, const char* fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
int rc = vdprintf(fd, fmt, ap); int rc = vdprintf(fd, fmt, ap);
@ -205,7 +208,7 @@ int fdprintf(int fd, const char* fmt, ...) {
} }
// POSIX calls this vdprintf, but LP32 Android had fdprintf instead. // POSIX calls this vdprintf, but LP32 Android had fdprintf instead.
int vfdprintf(int fd, const char* fmt, va_list ap) { extern "C" int vfdprintf(int fd, const char* fmt, va_list ap) {
return vdprintf(fd, fmt, ap); return vdprintf(fd, fmt, ap);
} }
@ -216,64 +219,64 @@ int vfdprintf(int fd, const char* fmt, va_list ap) {
#undef __futex_wait #undef __futex_wait
// This used to be in <sys/atomics.h>. // This used to be in <sys/atomics.h>.
int __futex_wake(volatile void* ftx, int count) { extern "C" int __futex_wake(volatile void* ftx, int count) {
return __real_futex_wake(ftx, count); return __real_futex_wake(ftx, count);
} }
// This used to be in <sys/atomics.h>. // This used to be in <sys/atomics.h>.
int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) { extern "C" int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
return __real_futex_wait(ftx, value, timeout); return __real_futex_wait(ftx, value, timeout);
} }
// Unity's libmono uses this. // Unity's libmono uses this.
int tkill(pid_t tid, int sig) { extern "C" int tkill(pid_t tid, int sig) {
return syscall(__NR_tkill, tid, sig); return syscall(__NR_tkill, tid, sig);
} }
// This was removed from POSIX 2008. // This was removed from POSIX 2008.
wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) { extern "C" wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
return wcsstr(haystack, needle); return wcsstr(haystack, needle);
} }
// This was removed from POSIX 2008. // This was removed from POSIX 2008.
sighandler_t bsd_signal(int signum, sighandler_t handler) { extern "C" sighandler_t bsd_signal(int signum, sighandler_t handler) {
return signal(signum, handler); return signal(signum, handler);
} }
#if !defined(__i386__) #if !defined(__i386__)
// This was removed from POSIX 2008. // This was removed from POSIX 2008.
#undef bcopy #undef bcopy
void bcopy(const void* src, void* dst, size_t n) { extern "C" void bcopy(const void* src, void* dst, size_t n) {
memmove(dst, src, n); memcpy(dst, src, n);
} }
#else #else
// x86 has an assembler implementation. // x86 has an assembler implementation.
#endif #endif
// sysv_signal() was never in POSIX. // sysv_signal() was never in POSIX.
extern "C++" sighandler_t _signal(int signum, sighandler_t handler, int flags); extern sighandler_t _signal(int signum, sighandler_t handler, int flags);
sighandler_t sysv_signal(int signum, sighandler_t handler) { extern "C" sighandler_t sysv_signal(int signum, sighandler_t handler) {
return _signal(signum, handler, SA_RESETHAND); return _signal(signum, handler, SA_RESETHAND);
} }
// This is a system call that was never in POSIX. Use readdir(3) instead. // This is a system call that was never in POSIX. Use readdir(3) instead.
int __getdents64(unsigned int, dirent*, unsigned int); extern "C" int __getdents64(unsigned int, dirent*, unsigned int);
int getdents(unsigned int fd, dirent* dirp, unsigned int count) { extern "C" int getdents(unsigned int fd, dirent* dirp, unsigned int count) {
return __getdents64(fd, dirp, count); return __getdents64(fd, dirp, count);
} }
// This is a BSDism that we never implemented correctly. Used by Firefox. // This is a BSDism that we never implemented correctly. Used by Firefox.
int issetugid() { extern "C" int issetugid() {
return 0; return 0;
} }
// This was removed from POSIX 2004. // This was removed from POSIX 2004.
pid_t wait3(int* status, int options, struct rusage* rusage) { extern "C" pid_t wait3(int* status, int options, struct rusage* rusage) {
return wait4(-1, status, options, rusage); return wait4(-1, status, options, rusage);
} }
// This was removed from POSIX 2004. // This was removed from POSIX 2004.
int getdtablesize() { extern "C" int getdtablesize() {
struct rlimit r; struct rlimit r;
if (getrlimit(RLIMIT_NOFILE, &r) < 0) { if (getrlimit(RLIMIT_NOFILE, &r) < 0) {
@ -283,10 +286,6 @@ int getdtablesize() {
return r.rlim_cur; return r.rlim_cur;
} }
// A leaked BSD stdio implementation detail that's now a no-op.
void __sinit() {}
int __sdidinit = 1;
// Only used by ftime, which was removed from POSIX 2008. // Only used by ftime, which was removed from POSIX 2008.
struct timeb { struct timeb {
time_t time; time_t time;
@ -296,7 +295,7 @@ struct timeb {
}; };
// This was removed from POSIX 2008. // This was removed from POSIX 2008.
int ftime(struct timeb* tb) { extern "C" int ftime(struct timeb* tb) {
struct timeval tv; struct timeval tv;
struct timezone tz; struct timezone tz;
@ -318,42 +317,35 @@ int ftime(struct timeb* tb) {
} }
// This was removed from POSIX 2008. // This was removed from POSIX 2008.
char* index(const char* str, int ch) { extern "C" char* index(const char* str, int ch) {
return strchr(str, ch); return strchr(str, ch);
} }
// This was removed from BSD. // This was removed from BSD.
void arc4random_stir(void) { extern "C" void arc4random_stir(void) {
// The current implementation stirs itself as needed. // The current implementation stirs itself as needed.
} }
// This was removed from BSD. // This was removed from BSD.
void arc4random_addrandom(unsigned char*, int) { extern "C" void arc4random_addrandom(unsigned char*, int) {
// The current implementation adds randomness as needed. // The current implementation adds randomness as needed.
} }
// Old versions of the NDK did not export malloc_usable_size, but did // Old versions of the NDK did not export malloc_usable_size, but did
// export dlmalloc_usable_size. We are moving away from dlmalloc in L // export dlmalloc_usable_size. We are moving away from dlmalloc in L
// so make this call malloc_usable_size. // so make this call malloc_usable_size.
size_t dlmalloc_usable_size(void* ptr) { extern "C" size_t dlmalloc_usable_size(void* ptr) {
return malloc_usable_size(ptr); return malloc_usable_size(ptr);
} }
// In L we added a public pthread_gettid_np, but some apps were using the private API. // In L we added a public pthread_gettid_np, but some apps were using the private API.
pid_t __pthread_gettid_libc(pthread_t t) { extern "C" pid_t __pthread_gettid(pthread_t t) {
return pthread_gettid_np(t); return pthread_gettid_np(t);
} }
pid_t __pthread_gettid_libc_private(pthread_t t) {
return pthread_gettid_np(t);
}
__asm__(".symver __pthread_gettid_libc,__pthread_gettid@LIBC");
__asm__(".symver __pthread_gettid_libc_private,__pthread_gettid@@LIBC_PRIVATE");
// Older versions of apportable used dlmalloc directly instead of malloc, // Older versions of apportable used dlmalloc directly instead of malloc,
// so export this compatibility shim that simply calls malloc. // so export this compatibility shim that simply calls malloc.
void* dlmalloc(size_t size) { extern "C" void* dlmalloc(size_t size) {
return malloc(size); return malloc(size);
} }
@ -361,39 +353,39 @@ void* dlmalloc(size_t size) {
#include "pthread_internal.h" #include "pthread_internal.h"
#undef __get_thread #undef __get_thread
// Various third-party apps contain a backport of our pthread_rwlock implementation that uses this. // Various third-party apps contain a backport of our pthread_rwlock implementation that uses this.
pthread_internal_t* __get_thread() { extern "C" pthread_internal_t* __get_thread() {
return __real_get_thread(); return __real_get_thread();
} }
// This one exists only for the LP32 NDK and is not present anywhere else. // This one exists only for the LP32 NDK and is not present anywhere else.
extern long __set_errno_internal(int); extern "C" long __set_errno_internal(int);
long __set_errno(int n) { extern "C" long __set_errno(int n) {
return __set_errno_internal(n); return __set_errno_internal(n);
} }
#endif // !defined(__LP64__)
// This was never implemented in bionic, only needed for ABI compatibility with the NDK. // This was never implemented in bionic, only needed for ABI compatibility with the NDK.
// In the M time frame, over 1000 apps have a reference to this! // In the M time frame, over 1000 apps have a reference to this!
void endpwent() { } extern "C" void endpwent() { }
// Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems // Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems
// that use dlmalloc, be consistent and export them everywhere. // that use dlmalloc, be consistent and export them everywhere.
#if defined(USE_JEMALLOC) #if defined(USE_JEMALLOC)
void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) { extern "C" void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
} }
int dlmalloc_trim(size_t) { extern "C" int dlmalloc_trim(size_t) {
return 0; return 0;
} }
#else #else
void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*); extern "C" void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) { extern "C" void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
dlmalloc_inspect_all_real(handler, arg); dlmalloc_inspect_all_real(handler, arg);
} }
int dlmalloc_trim_real(size_t); extern "C" int dlmalloc_trim_real(size_t);
int dlmalloc_trim(size_t pad) { extern "C" int dlmalloc_trim(size_t pad) {
return dlmalloc_trim_real(pad); return dlmalloc_trim_real(pad);
} }
#endif #endif
#endif // !defined(__BRILLO__) && !defined (__LP64__) #endif // !defined(__BRILLO__)
} // extern "C"

View File

@ -45,7 +45,7 @@ struct atfork_t {
class atfork_list_t { class atfork_list_t {
public: public:
constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {} atfork_list_t() : first_(nullptr), last_(nullptr) {}
template<typename F> template<typename F>
void walk_forward(F f) { void walk_forward(F f) {

View File

@ -1,183 +0,0 @@
/*
* 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 <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
#include "private/bionic_futex.h"
int pthread_barrierattr_init(pthread_barrierattr_t* attr) {
*attr = 0;
return 0;
}
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) {
*attr = 0;
return 0;
}
int pthread_barrierattr_getpshared(pthread_barrierattr_t* attr, int* pshared) {
*pshared = (*attr & 1) ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
return 0;
}
int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) {
if (pshared == PTHREAD_PROCESS_SHARED) {
*attr |= 1;
} else {
*attr &= ~1;
}
return 0;
}
enum BarrierState {
WAIT,
RELEASE,
};
struct pthread_barrier_internal_t {
// One barrier can be used for unlimited number of cycles. In each cycle, [init_count]
// threads must call pthread_barrier_wait() before any of them successfully return from
// the call. It is undefined behavior if there are more than [init_count] threads call
// pthread_barrier_wait() in one cycle.
uint32_t init_count;
// Barrier state. It is WAIT if waiting for more threads to enter the barrier in this cycle,
// otherwise threads are leaving the barrier.
_Atomic(BarrierState) state;
// Number of threads having entered but not left the barrier in this cycle.
atomic_uint wait_count;
// Whether the barrier is shared across processes.
bool pshared;
uint32_t __reserved[4];
};
static_assert(sizeof(pthread_barrier_t) == sizeof(pthread_barrier_internal_t),
"pthread_barrier_t should actually be pthread_barrier_internal_t in implementation."
);
static_assert(alignof(pthread_barrier_t) >= 4,
"pthread_barrier_t should fulfill the alignment of pthread_barrier_internal_t.");
static inline pthread_barrier_internal_t* __get_internal_barrier(pthread_barrier_t* barrier) {
return reinterpret_cast<pthread_barrier_internal_t*>(barrier);
}
int pthread_barrier_init(pthread_barrier_t* barrier_interface, const pthread_barrierattr_t* attr,
unsigned count) {
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
if (count == 0) {
return EINVAL;
}
barrier->init_count = count;
atomic_init(&barrier->state, WAIT);
atomic_init(&barrier->wait_count, 0);
barrier->pshared = false;
if (attr != nullptr && (*attr & 1)) {
barrier->pshared = true;
}
return 0;
}
// According to POSIX standard, pthread_barrier_wait() synchronizes memory between participating
// threads. It means all memory operations made by participating threads before calling
// pthread_barrier_wait() can be seen by all participating threads after the function call.
// We establish this by making a happens-before relation between all threads entering the barrier
// with the last thread entering the barrier, and a happens-before relation between the last
// thread entering the barrier with all threads leaving the barrier.
int pthread_barrier_wait(pthread_barrier_t* barrier_interface) {
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
// Wait until all threads for the previous cycle have left the barrier. This is needed
// as a participating thread can call pthread_barrier_wait() again before other
// threads have left the barrier. Use acquire operation here to synchronize with
// the last thread leaving the previous cycle, so we can read correct wait_count below.
while(atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
__futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
}
uint32_t prev_wait_count = atomic_load_explicit(&barrier->wait_count, memory_order_relaxed);
while (true) {
// It happens when there are more than [init_count] threads trying to enter the barrier
// at one cycle. We read the POSIX standard as disallowing this, since additional arriving
// threads are not synchronized with respect to the barrier reset. We also don't know of
// any reasonable cases in which this would be intentional.
if (prev_wait_count >= barrier->init_count) {
return EINVAL;
}
// Use memory_order_acq_rel operation here to synchronize between all threads entering
// the barrier with the last thread entering the barrier.
if (atomic_compare_exchange_weak_explicit(&barrier->wait_count, &prev_wait_count,
prev_wait_count + 1u, memory_order_acq_rel,
memory_order_relaxed)) {
break;
}
}
int result = 0;
if (prev_wait_count + 1 == barrier->init_count) {
result = PTHREAD_BARRIER_SERIAL_THREAD;
if (prev_wait_count != 0) {
// Use release operation here to synchronize between the last thread entering the
// barrier with all threads leaving the barrier.
atomic_store_explicit(&barrier->state, RELEASE, memory_order_release);
__futex_wake_ex(&barrier->state, barrier->pshared, prev_wait_count);
}
} else {
// Use acquire operation here to synchronize between the last thread entering the
// barrier with all threads leaving the barrier.
while (atomic_load_explicit(&barrier->state, memory_order_acquire) == WAIT) {
__futex_wait_ex(&barrier->state, barrier->pshared, WAIT, false, nullptr);
}
}
// Use release operation here to make it not reordered with previous operations.
if (atomic_fetch_sub_explicit(&barrier->wait_count, 1, memory_order_release) == 1) {
// Use release operation here to synchronize with threads entering the barrier for
// the next cycle, or the thread calling pthread_barrier_destroy().
atomic_store_explicit(&barrier->state, WAIT, memory_order_release);
__futex_wake_ex(&barrier->state, barrier->pshared, barrier->init_count);
}
return result;
}
int pthread_barrier_destroy(pthread_barrier_t* barrier_interface) {
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
if (barrier->init_count == 0) {
return EINVAL;
}
// Use acquire operation here to synchronize with the last thread leaving the barrier.
// So we can read correct wait_count below.
while (atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
__futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
}
if (atomic_load_explicit(&barrier->wait_count, memory_order_relaxed) != 0) {
return EBUSY;
}
barrier->init_count = 0;
return 0;
}

View File

@ -111,8 +111,8 @@ struct pthread_cond_internal_t {
return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed)); return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed));
} }
bool use_realtime_clock() { int get_clock() {
return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)) == CLOCK_REALTIME; return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed));
} }
#if defined(__LP64__) #if defined(__LP64__)
@ -170,17 +170,12 @@ static int __pthread_cond_pulse(pthread_cond_internal_t* cond, int thread_count)
return 0; return 0;
} }
static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex, static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
bool use_realtime_clock, const timespec* abs_timeout_or_null) { const timespec* rel_timeout_or_null) {
int result = check_timespec(abs_timeout_or_null, true);
if (result != 0) {
return result;
}
unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed); unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
pthread_mutex_unlock(mutex); pthread_mutex_unlock(mutex);
int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, rel_timeout_or_null);
use_realtime_clock, abs_timeout_or_null);
pthread_mutex_lock(mutex); pthread_mutex_lock(mutex);
if (status == -ETIMEDOUT) { if (status == -ETIMEDOUT) {
@ -189,6 +184,21 @@ static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex
return 0; return 0;
} }
static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
const timespec* abs_timeout_or_null, clockid_t clock) {
timespec ts;
timespec* rel_timeout = NULL;
if (abs_timeout_or_null != NULL) {
rel_timeout = &ts;
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
return ETIMEDOUT;
}
}
return __pthread_cond_timedwait_relative(cond, mutex, rel_timeout);
}
int pthread_cond_broadcast(pthread_cond_t* cond_interface) { int pthread_cond_broadcast(pthread_cond_t* cond_interface) {
return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX); return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX);
} }
@ -199,14 +209,14 @@ int pthread_cond_signal(pthread_cond_t* cond_interface) {
int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) { int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface); pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
return __pthread_cond_timedwait(cond, mutex, false, nullptr); return __pthread_cond_timedwait(cond, mutex, NULL, cond->get_clock());
} }
int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex, int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex,
const timespec *abstime) { const timespec *abstime) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface); pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
return __pthread_cond_timedwait(cond, mutex, cond->use_realtime_clock(), abstime); return __pthread_cond_timedwait(cond, mutex, abstime, cond->get_clock());
} }
#if !defined(__LP64__) #if !defined(__LP64__)
@ -215,7 +225,8 @@ extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond_interface,
pthread_mutex_t* mutex, pthread_mutex_t* mutex,
const timespec* abs_timeout) { const timespec* abs_timeout) {
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout); return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, abs_timeout,
CLOCK_MONOTONIC);
} }
extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface, extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface,
@ -227,13 +238,8 @@ extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interfac
extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface, extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface,
pthread_mutex_t* mutex, pthread_mutex_t* mutex,
const timespec* rel_timeout) { const timespec* rel_timeout) {
timespec ts;
timespec* abs_timeout = nullptr; return __pthread_cond_timedwait_relative(__get_internal_cond(cond_interface), mutex, rel_timeout);
if (rel_timeout != nullptr) {
absolute_timespec_from_timespec(ts, *rel_timeout, CLOCK_REALTIME);
abs_timeout = &ts;
}
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, true, abs_timeout);
} }
extern "C" int pthread_cond_timeout_np(pthread_cond_t* cond_interface, extern "C" int pthread_cond_timeout_np(pthread_cond_t* cond_interface,

View File

@ -53,6 +53,13 @@ extern "C" int __isthreaded;
// This code is used both by each new pthread and the code that initializes the main thread. // This code is used both by each new pthread and the code that initializes the main thread.
void __init_tls(pthread_internal_t* thread) { void __init_tls(pthread_internal_t* thread) {
if (thread->mmap_size == 0) {
// If the TLS area was not allocated by mmap(), it may not have been cleared to zero.
// So assume the worst and zero the TLS area.
memset(thread->tls, 0, sizeof(thread->tls));
memset(thread->key_data, 0, sizeof(thread->key_data));
}
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0. // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
thread->tls[TLS_SLOT_SELF] = thread->tls; thread->tls[TLS_SLOT_SELF] = thread->tls;
thread->tls[TLS_SLOT_THREAD_ID] = thread; thread->tls[TLS_SLOT_THREAD_ID] = thread;
@ -168,11 +175,6 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp,
(reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf); (reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top); pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
if (mmap_size == 0) {
// If thread was not allocated by mmap(), it may not have been cleared to zero.
// So assume the worst and zero it.
memset(thread, 0, sizeof(pthread_internal_t));
}
attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base); attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
thread->mmap_size = mmap_size; thread->mmap_size = mmap_size;

View File

@ -40,8 +40,7 @@
/* Has the thread been joined by another thread? */ /* Has the thread been joined by another thread? */
#define PTHREAD_ATTR_FLAG_JOINED 0x00000002 #define PTHREAD_ATTR_FLAG_JOINED 0x00000002
class pthread_key_data_t { struct pthread_key_data_t {
public:
uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below. uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below.
void* data; void* data;
}; };
@ -53,12 +52,9 @@ enum ThreadJoinState {
THREAD_DETACHED THREAD_DETACHED
}; };
class thread_local_dtor; struct pthread_internal_t {
struct pthread_internal_t* next;
class pthread_internal_t { struct pthread_internal_t* prev;
public:
class pthread_internal_t* next;
class pthread_internal_t* prev;
pid_t tid; pid_t tid;
@ -98,8 +94,6 @@ class pthread_internal_t {
size_t mmap_size; size_t mmap_size;
thread_local_dtor* thread_local_dtors;
void* tls[BIONIC_TLS_SLOTS]; void* tls[BIONIC_TLS_SLOTS];
pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT]; pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];

View File

@ -166,13 +166,10 @@ int pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr, int* pshared)
#define MUTEX_STATE_BITS_LOCKED_UNCONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_UNCONTENDED) #define MUTEX_STATE_BITS_LOCKED_UNCONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_UNCONTENDED)
#define MUTEX_STATE_BITS_LOCKED_CONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_CONTENDED) #define MUTEX_STATE_BITS_LOCKED_CONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_CONTENDED)
// Return true iff the mutex is unlocked. /* return true iff the mutex if locked with no waiters */
#define MUTEX_STATE_BITS_IS_UNLOCKED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_UNLOCKED)
// Return true iff the mutex is locked with no waiters.
#define MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED) #define MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
// return true iff the mutex is locked with maybe waiters. /* return true iff the mutex if locked with maybe waiters */
#define MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED) #define MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED)
/* used to flip from LOCKED_UNCONTENDED to LOCKED_CONTENDED */ /* used to flip from LOCKED_UNCONTENDED to LOCKED_CONTENDED */
@ -299,15 +296,11 @@ static inline __always_inline int __pthread_normal_mutex_trylock(pthread_mutex_i
*/ */
static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_internal_t* mutex, static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_internal_t* mutex,
uint16_t shared, uint16_t shared,
bool use_realtime_clock, const timespec* abs_timeout_or_null,
const timespec* abs_timeout_or_null) { clockid_t clock) {
if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) { if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {
return 0; return 0;
} }
int result = check_timespec(abs_timeout_or_null, true);
if (result != 0) {
return result;
}
ScopedTrace trace("Contending for pthread mutex"); ScopedTrace trace("Contending for pthread mutex");
@ -324,8 +317,15 @@ static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_inte
// made by other threads visible to the current CPU. // made by other threads visible to the current CPU.
while (atomic_exchange_explicit(&mutex->state, locked_contended, while (atomic_exchange_explicit(&mutex->state, locked_contended,
memory_order_acquire) != unlocked) { memory_order_acquire) != unlocked) {
if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock, timespec ts;
abs_timeout_or_null) == -ETIMEDOUT) { timespec* rel_timeout = NULL;
if (abs_timeout_or_null != NULL) {
rel_timeout = &ts;
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
return ETIMEDOUT;
}
}
if (__futex_wait_ex(&mutex->state, shared, locked_contended, rel_timeout) == -ETIMEDOUT) {
return ETIMEDOUT; return ETIMEDOUT;
} }
} }
@ -396,15 +396,14 @@ static inline __always_inline int __recursive_or_errorcheck_mutex_wait(
pthread_mutex_internal_t* mutex, pthread_mutex_internal_t* mutex,
uint16_t shared, uint16_t shared,
uint16_t old_state, uint16_t old_state,
bool use_realtime_clock, const timespec* rel_timeout) {
const timespec* abs_timeout) {
// __futex_wait always waits on a 32-bit value. But state is 16-bit. For a normal mutex, the owner_tid // __futex_wait always waits on a 32-bit value. But state is 16-bit. For a normal mutex, the owner_tid
// field in mutex is not used. On 64-bit devices, the __pad field in mutex is not used. // field in mutex is not used. On 64-bit devices, the __pad field in mutex is not used.
// But when a recursive or errorcheck mutex is used on 32-bit devices, we need to add the // But when a recursive or errorcheck mutex is used on 32-bit devices, we need to add the
// owner_tid value in the value argument for __futex_wait, otherwise we may always get EAGAIN error. // owner_tid value in the value argument for __futex_wait, otherwise we may always get EAGAIN error.
#if defined(__LP64__) #if defined(__LP64__)
return __futex_wait_ex(&mutex->state, shared, old_state, use_realtime_clock, abs_timeout); return __futex_wait_ex(&mutex->state, shared, old_state, rel_timeout);
#else #else
// This implementation works only when the layout of pthread_mutex_internal_t matches below expectation. // This implementation works only when the layout of pthread_mutex_internal_t matches below expectation.
@ -413,21 +412,19 @@ static inline __always_inline int __recursive_or_errorcheck_mutex_wait(
static_assert(offsetof(pthread_mutex_internal_t, owner_tid) == 2, ""); static_assert(offsetof(pthread_mutex_internal_t, owner_tid) == 2, "");
uint32_t owner_tid = atomic_load_explicit(&mutex->owner_tid, memory_order_relaxed); uint32_t owner_tid = atomic_load_explicit(&mutex->owner_tid, memory_order_relaxed);
return __futex_wait_ex(&mutex->state, shared, (owner_tid << 16) | old_state, return __futex_wait_ex(&mutex->state, shared, (owner_tid << 16) | old_state, rel_timeout);
use_realtime_clock, abs_timeout);
#endif #endif
} }
static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex, static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
bool use_realtime_clock, const timespec* abs_timeout_or_null, clockid_t clock) {
const timespec* abs_timeout_or_null) {
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
uint16_t mtype = (old_state & MUTEX_TYPE_MASK); uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
uint16_t shared = (old_state & MUTEX_SHARED_MASK); uint16_t shared = (old_state & MUTEX_SHARED_MASK);
// Handle common case first. // Handle common case first.
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) { if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
return __pthread_normal_mutex_lock(mutex, shared, use_realtime_clock, abs_timeout_or_null); return __pthread_normal_mutex_lock(mutex, shared, abs_timeout_or_null, clock);
} }
// Do we already own this recursive or error-check mutex? // Do we already own this recursive or error-check mutex?
@ -487,13 +484,16 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
old_state = new_state; old_state = new_state;
} }
int result = check_timespec(abs_timeout_or_null, true);
if (result != 0) {
return result;
}
// We are in locked_contended state, sleep until someone wakes us up. // We are in locked_contended state, sleep until someone wakes us up.
if (__recursive_or_errorcheck_mutex_wait(mutex, shared, old_state, use_realtime_clock, timespec ts;
abs_timeout_or_null) == -ETIMEDOUT) { timespec* rel_timeout = NULL;
if (abs_timeout_or_null != NULL) {
rel_timeout = &ts;
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
return ETIMEDOUT;
}
}
if (__recursive_or_errorcheck_mutex_wait(mutex, shared, old_state, rel_timeout) == -ETIMEDOUT) {
return ETIMEDOUT; return ETIMEDOUT;
} }
old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
@ -518,7 +518,7 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
return 0; return 0;
} }
} }
return __pthread_mutex_lock_with_timeout(mutex, false, nullptr); return __pthread_mutex_lock_with_timeout(mutex, NULL, 0);
} }
int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) { int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
@ -613,12 +613,17 @@ int pthread_mutex_trylock(pthread_mutex_t* mutex_interface) {
#if !defined(__LP64__) #if !defined(__LP64__)
extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex_interface, unsigned ms) { extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex_interface, unsigned ms) {
timespec ts;
timespec_from_ms(ts, ms);
timespec abs_timeout; timespec abs_timeout;
absolute_timespec_from_timespec(abs_timeout, ts, CLOCK_MONOTONIC); clock_gettime(CLOCK_MONOTONIC, &abs_timeout);
abs_timeout.tv_sec += ms / 1000;
abs_timeout.tv_nsec += (ms % 1000) * 1000000;
if (abs_timeout.tv_nsec >= NS_PER_S) {
abs_timeout.tv_sec++;
abs_timeout.tv_nsec -= NS_PER_S;
}
int error = __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface), int error = __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
false, &abs_timeout); &abs_timeout, CLOCK_MONOTONIC);
if (error == ETIMEDOUT) { if (error == ETIMEDOUT) {
error = EBUSY; error = EBUSY;
} }
@ -628,18 +633,14 @@ extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex_interface, u
int pthread_mutex_timedlock(pthread_mutex_t* mutex_interface, const timespec* abs_timeout) { int pthread_mutex_timedlock(pthread_mutex_t* mutex_interface, const timespec* abs_timeout) {
return __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface), return __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
true, abs_timeout); abs_timeout, CLOCK_REALTIME);
} }
int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) { int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface); // Use trylock to ensure that the mutex is valid and not already locked.
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed); int error = pthread_mutex_trylock(mutex_interface);
// Store 0xffff to make the mutex unusable. Although POSIX standard says it is undefined if (error != 0) {
// behavior to destroy a locked mutex, we prefer not to change mutex->state in that situation. return error;
if (MUTEX_STATE_BITS_IS_UNLOCKED(old_state) && }
atomic_compare_exchange_strong_explicit(&mutex->state, &old_state, 0xffff,
memory_order_relaxed, memory_order_relaxed)) {
return 0; return 0;
} }
return EBUSY;
}

View File

@ -79,7 +79,7 @@ int pthread_once(pthread_once_t* once_control, void (*init_routine)(void)) {
} }
// The initialization is underway, wait for its finish. // The initialization is underway, wait for its finish.
__futex_wait_ex(once_control_ptr, 0, old_value, false, nullptr); __futex_wait_ex(once_control_ptr, 0, old_value, NULL);
old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire); old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire);
} }
} }

View File

@ -294,13 +294,9 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
} }
while (true) { while (true) {
int result = __pthread_rwlock_tryrdlock(rwlock); int ret = __pthread_rwlock_tryrdlock(rwlock);
if (result == 0 || result == EAGAIN) { if (ret == 0 || ret == EAGAIN) {
return result; return ret;
}
result = check_timespec(abs_timeout_or_null, true);
if (result != 0) {
return result;
} }
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed); int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
@ -308,6 +304,16 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
continue; continue;
} }
timespec ts;
timespec* rel_timeout = NULL;
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_lock.lock();
rwlock->pending_reader_count++; rwlock->pending_reader_count++;
@ -321,10 +327,10 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
int old_serial = rwlock->pending_reader_wakeup_serial; int old_serial = rwlock->pending_reader_wakeup_serial;
rwlock->pending_lock.unlock(); rwlock->pending_lock.unlock();
int futex_result = 0; int futex_ret = 0;
if (!__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) { if (!__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) {
futex_result = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared, futex_ret = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
old_serial, true, abs_timeout_or_null); old_serial, rel_timeout);
} }
rwlock->pending_lock.lock(); rwlock->pending_lock.lock();
@ -335,7 +341,7 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
} }
rwlock->pending_lock.unlock(); rwlock->pending_lock.unlock();
if (futex_result == -ETIMEDOUT) { if (futex_ret == -ETIMEDOUT) {
return ETIMEDOUT; return ETIMEDOUT;
} }
} }
@ -366,13 +372,9 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
return EDEADLK; return EDEADLK;
} }
while (true) { while (true) {
int result = __pthread_rwlock_trywrlock(rwlock); int ret = __pthread_rwlock_trywrlock(rwlock);
if (result == 0) { if (ret == 0) {
return result; return ret;
}
result = check_timespec(abs_timeout_or_null, true);
if (result != 0) {
return result;
} }
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed); int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
@ -380,6 +382,16 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
continue; continue;
} }
timespec ts;
timespec* rel_timeout = NULL;
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_lock.lock();
rwlock->pending_writer_count++; rwlock->pending_writer_count++;
@ -389,10 +401,10 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
int old_serial = rwlock->pending_writer_wakeup_serial; int old_serial = rwlock->pending_writer_wakeup_serial;
rwlock->pending_lock.unlock(); rwlock->pending_lock.unlock();
int futex_result = 0; int futex_ret = 0;
if (!__can_acquire_write_lock(old_state)) { if (!__can_acquire_write_lock(old_state)) {
futex_result = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared, futex_ret = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
old_serial, true, abs_timeout_or_null); old_serial, rel_timeout);
} }
rwlock->pending_lock.lock(); rwlock->pending_lock.lock();
@ -403,7 +415,7 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
} }
rwlock->pending_lock.unlock(); rwlock->pending_lock.unlock();
if (futex_result == -ETIMEDOUT) { if (futex_ret == -ETIMEDOUT) {
return ETIMEDOUT; return ETIMEDOUT;
} }
} }
@ -415,7 +427,7 @@ int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock_interface) {
if (__predict_true(__pthread_rwlock_tryrdlock(rwlock) == 0)) { if (__predict_true(__pthread_rwlock_tryrdlock(rwlock) == 0)) {
return 0; return 0;
} }
return __pthread_rwlock_timedrdlock(rwlock, nullptr); return __pthread_rwlock_timedrdlock(rwlock, NULL);
} }
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) { int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {
@ -434,7 +446,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock_interface) {
if (__predict_true(__pthread_rwlock_trywrlock(rwlock) == 0)) { if (__predict_true(__pthread_rwlock_trywrlock(rwlock) == 0)) {
return 0; return 0;
} }
return __pthread_rwlock_timedwrlock(rwlock, nullptr); return __pthread_rwlock_timedwrlock(rwlock, NULL);
} }
int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) { int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {

View File

@ -1,81 +0,0 @@
/*
* 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 <pthread.h>
#include "private/bionic_lock.h"
// User-level spinlocks can be hazardous to battery life on Android.
// We implement a simple compromise that behaves mostly like a spinlock,
// but prevents excessively long spinning.
struct pthread_spinlock_internal_t {
Lock lock;
};
static_assert(sizeof(pthread_spinlock_t) == sizeof(pthread_spinlock_internal_t),
"pthread_spinlock_t should actually be pthread_spinlock_internal_t.");
static_assert(alignof(pthread_spinlock_t) >= 4,
"pthread_spinlock_t should fulfill the alignment of pthread_spinlock_internal_t.");
static inline pthread_spinlock_internal_t* __get_internal_spinlock(pthread_spinlock_t* lock) {
return reinterpret_cast<pthread_spinlock_internal_t*>(lock);
}
int pthread_spin_init(pthread_spinlock_t* lock_interface, int pshared) {
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
lock->lock.init(pshared);
return 0;
}
int pthread_spin_destroy(pthread_spinlock_t* lock_interface) {
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
return lock->lock.trylock() ? 0 : EBUSY;
}
int pthread_spin_trylock(pthread_spinlock_t* lock_interface) {
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
return lock->lock.trylock() ? 0 : EBUSY;
}
int pthread_spin_lock(pthread_spinlock_t* lock_interface) {
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
for (int i = 0; i < 10000; ++i) {
if (lock->lock.trylock()) {
return 0;
}
}
lock->lock.lock();
return 0;
}
int pthread_spin_unlock(pthread_spinlock_t* lock_interface) {
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
lock->lock.unlock();
return 0;
}

View File

@ -220,7 +220,7 @@ int sem_wait(sem_t* sem) {
return 0; return 0;
} }
__futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, false, nullptr); __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, NULL);
} }
} }
@ -235,29 +235,36 @@ int sem_timedwait(sem_t* sem, const timespec* abs_timeout) {
} }
// Check it as per POSIX. // Check it as per POSIX.
int result = check_timespec(abs_timeout, false); if (abs_timeout == NULL || abs_timeout->tv_sec < 0 || abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= NS_PER_S) {
if (result != 0) { errno = EINVAL;
errno = result;
return -1; return -1;
} }
unsigned int shared = SEM_GET_SHARED(sem_count_ptr); unsigned int shared = SEM_GET_SHARED(sem_count_ptr);
while (true) { while (true) {
// POSIX mandates CLOCK_REALTIME here.
timespec ts;
if (!timespec_from_absolute_timespec(ts, *abs_timeout, CLOCK_REALTIME)) {
errno = ETIMEDOUT;
return -1;
}
// Try to grab the semaphore. If the value was 0, this will also change it to -1. // Try to grab the semaphore. If the value was 0, this will also change it to -1.
if (__sem_dec(sem_count_ptr) > 0) { if (__sem_dec(sem_count_ptr) > 0) {
return 0; break;
} }
// Contention detected. Wait for a wakeup event. // Contention detected. Wait for a wakeup event.
int result = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, true, abs_timeout); int ret = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, &ts);
// Return in case of timeout or interrupt. // Return in case of timeout or interrupt.
if (result == -ETIMEDOUT || result == -EINTR) { if (ret == -ETIMEDOUT || ret == -EINTR) {
errno = -result; errno = -ret;
return -1; return -1;
} }
} }
return 0;
} }
int sem_post(sem_t* sem) { int sem_post(sem_t* sem) {

View File

@ -25,38 +25,34 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <new> #include <new>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <errno.h>
#include <poll.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <linux/xattr.h>
#include <netinet/in.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/un.h> #include <netinet/in.h>
#include <sys/xattr.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h> #include <sys/_system_properties.h>
#include <sys/system_properties.h> #include <sys/system_properties.h>
#include "private/bionic_futex.h" #include "private/bionic_futex.h"
#include "private/bionic_lock.h"
#include "private/bionic_macros.h" #include "private/bionic_macros.h"
#include "private/libc_logging.h"
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME; static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
@ -116,57 +112,23 @@ private:
DISALLOW_COPY_AND_ASSIGN(prop_bt); DISALLOW_COPY_AND_ASSIGN(prop_bt);
}; };
class prop_area { struct prop_area {
public: uint32_t bytes_used;
atomic_uint_least32_t serial;
uint32_t magic;
uint32_t version;
uint32_t reserved[28];
char data[0];
prop_area(const uint32_t magic, const uint32_t version) : prop_area(const uint32_t magic, const uint32_t version) :
magic_(magic), version_(version) { magic(magic), version(version) {
atomic_init(&serial_, 0); atomic_init(&serial, 0);
memset(reserved_, 0, sizeof(reserved_)); memset(reserved, 0, sizeof(reserved));
// Allocate enough space for the root node. // Allocate enough space for the root node.
bytes_used_ = sizeof(prop_bt); bytes_used = sizeof(prop_bt);
} }
const prop_info *find(const char *name);
bool add(const char *name, unsigned int namelen,
const char *value, unsigned int valuelen);
bool foreach(void (*propfn)(const prop_info *pi, void *cookie), void *cookie);
atomic_uint_least32_t *serial() { return &serial_; }
uint32_t magic() const { return magic_; }
uint32_t version() const { return version_; }
private: private:
void *allocate_obj(const size_t size, uint_least32_t *const off);
prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off);
prop_info *new_prop_info(const char *name, uint8_t namelen,
const char *value, uint8_t valuelen,
uint_least32_t *const off);
void *to_prop_obj(uint_least32_t off);
prop_bt *to_prop_bt(atomic_uint_least32_t *off_p);
prop_info *to_prop_info(atomic_uint_least32_t *off_p);
prop_bt *root_node();
prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
uint8_t namelen, bool alloc_if_needed);
const prop_info *find_property(prop_bt *const trie, const char *name,
uint8_t namelen, const char *value,
uint8_t valuelen, bool alloc_if_needed);
bool foreach_property(prop_bt *const trie,
void (*propfn)(const prop_info *pi, void *cookie),
void *cookie);
uint32_t bytes_used_;
atomic_uint_least32_t serial_;
uint32_t magic_;
uint32_t version_;
uint32_t reserved_[28];
char data_[0];
DISALLOW_COPY_AND_ASSIGN(prop_area); DISALLOW_COPY_AND_ASSIGN(prop_area);
}; };
@ -196,11 +158,10 @@ struct find_nth_cookie {
} }
}; };
static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME; static char property_filename[PATH_MAX] = PROP_FILENAME;
static bool compat_mode = false; static bool compat_mode = false;
static size_t pa_data_size; static size_t pa_data_size;
static size_t pa_size; static size_t pa_size;
static bool initialized = false;
// NOTE: This isn't static because system_properties_compat.c // NOTE: This isn't static because system_properties_compat.c
// requires it. // requires it.
@ -221,12 +182,13 @@ static int get_fd_from_env(void)
return atoi(env); return atoi(env);
} }
static prop_area* map_prop_area_rw(const char* filename, const char* context, static int map_prop_area_rw()
bool* fsetxattr_failed) { {
/* dev is a tmpfs that we can use to carve a shared workspace /* dev is a tmpfs that we can use to carve a shared workspace
* out of, so let's do that... * out of, so let's do that...
*/ */
const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444); const int fd = open(property_filename,
O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
if (fd < 0) { if (fd < 0) {
if (errno == EACCES) { if (errno == EACCES) {
@ -235,31 +197,12 @@ static prop_area* map_prop_area_rw(const char* filename, const char* context,
*/ */
abort(); abort();
} }
return nullptr; return -1;
}
if (context) {
if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
__libc_format_log(ANDROID_LOG_ERROR, "libc",
"fsetxattr failed to set context (%s) for \"%s\"", context, filename);
/*
* fsetxattr() will fail during system properties tests due to selinux policy.
* We do not want to create a custom policy for the tester, so we will continue in
* this function but set a flag that an error has occurred.
* Init, which is the only daemon that should ever call this function will abort
* when this error occurs.
* Otherwise, the tester will ignore it and continue, albeit without any selinux
* property separation.
*/
if (fsetxattr_failed) {
*fsetxattr_failed = true;
}
}
} }
if (ftruncate(fd, PA_SIZE) < 0) { if (ftruncate(fd, PA_SIZE) < 0) {
close(fd); close(fd);
return nullptr; return -1;
} }
pa_size = PA_SIZE; pa_size = PA_SIZE;
@ -269,26 +212,29 @@ static prop_area* map_prop_area_rw(const char* filename, const char* context,
void *const memory_area = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); void *const memory_area = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (memory_area == MAP_FAILED) { if (memory_area == MAP_FAILED) {
close(fd); close(fd);
return nullptr; return -1;
} }
prop_area *pa = new(memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION); prop_area *pa = new(memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
/* plug into the lib property services */
__system_property_area__ = pa;
close(fd); close(fd);
return pa; return 0;
} }
static prop_area* map_fd_ro(const int fd) { static int map_fd_ro(const int fd) {
struct stat fd_stat; struct stat fd_stat;
if (fstat(fd, &fd_stat) < 0) { if (fstat(fd, &fd_stat) < 0) {
return nullptr; return -1;
} }
if ((fd_stat.st_uid != 0) if ((fd_stat.st_uid != 0)
|| (fd_stat.st_gid != 0) || (fd_stat.st_gid != 0)
|| ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) || ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|| (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area))) ) { || (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area))) ) {
return nullptr; return -1;
} }
pa_size = fd_stat.st_size; pa_size = fd_stat.st_size;
@ -296,28 +242,29 @@ static prop_area* map_fd_ro(const int fd) {
void* const map_result = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0); void* const map_result = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
if (map_result == MAP_FAILED) { if (map_result == MAP_FAILED) {
return nullptr; return -1;
} }
prop_area* pa = reinterpret_cast<prop_area*>(map_result); prop_area* pa = reinterpret_cast<prop_area*>(map_result);
if ((pa->magic() != PROP_AREA_MAGIC) || if ((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
(pa->version() != PROP_AREA_VERSION && pa->version != PROP_AREA_VERSION_COMPAT)) {
pa->version() != PROP_AREA_VERSION_COMPAT)) {
munmap(pa, pa_size); munmap(pa, pa_size);
return nullptr; return -1;
} }
if (pa->version() == PROP_AREA_VERSION_COMPAT) { if (pa->version == PROP_AREA_VERSION_COMPAT) {
compat_mode = true; compat_mode = true;
} }
return pa; __system_property_area__ = pa;
return 0;
} }
static prop_area* map_prop_area(const char* filename, bool is_legacy) { static int map_prop_area()
int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY); {
int fd = open(property_filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
bool close_fd = true; bool close_fd = true;
if (fd == -1 && errno == ENOENT && is_legacy) { if (fd == -1 && errno == ENOENT) {
/* /*
* For backwards compatibility, if the file doesn't * For backwards compatibility, if the file doesn't
* exist, we use the environment to get the file descriptor. * exist, we use the environment to get the file descriptor.
@ -326,18 +273,16 @@ static prop_area* map_prop_area(const char* filename, bool is_legacy) {
* returns other errors such as ENOMEM or ENFILE, since it * returns other errors such as ENOMEM or ENFILE, since it
* might be possible for an external program to trigger this * might be possible for an external program to trigger this
* condition. * condition.
* Only do this for the legacy prop file, secured prop files
* do not have a backup
*/ */
fd = get_fd_from_env(); fd = get_fd_from_env();
close_fd = false; close_fd = false;
} }
if (fd < 0) { if (fd < 0) {
return nullptr; return -1;
} }
prop_area* map_result = map_fd_ro(fd); const int map_result = map_fd_ro(fd);
if (close_fd) { if (close_fd) {
close(fd); close(fd);
} }
@ -345,19 +290,20 @@ static prop_area* map_prop_area(const char* filename, bool is_legacy) {
return map_result; return map_result;
} }
void *prop_area::allocate_obj(const size_t size, uint_least32_t *const off) static void *allocate_obj(const size_t size, uint_least32_t *const off)
{ {
prop_area *pa = __system_property_area__;
const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t)); const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
if (bytes_used_ + aligned > pa_data_size) { if (pa->bytes_used + aligned > pa_data_size) {
return NULL; return NULL;
} }
*off = bytes_used_; *off = pa->bytes_used;
bytes_used_ += aligned; pa->bytes_used += aligned;
return data_ + *off; return pa->data + *off;
} }
prop_bt *prop_area::new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off) static prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
{ {
uint_least32_t new_offset; uint_least32_t new_offset;
void *const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset); void *const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
@ -370,7 +316,7 @@ prop_bt *prop_area::new_prop_bt(const char *name, uint8_t namelen, uint_least32_
return NULL; return NULL;
} }
prop_info *prop_area::new_prop_info(const char *name, uint8_t namelen, static prop_info *new_prop_info(const char *name, uint8_t namelen,
const char *value, uint8_t valuelen, uint_least32_t *const off) const char *value, uint8_t valuelen, uint_least32_t *const off)
{ {
uint_least32_t new_offset; uint_least32_t new_offset;
@ -384,25 +330,27 @@ prop_info *prop_area::new_prop_info(const char *name, uint8_t namelen,
return NULL; return NULL;
} }
void *prop_area::to_prop_obj(uint_least32_t off) static void *to_prop_obj(uint_least32_t off)
{ {
if (off > pa_data_size) if (off > pa_data_size)
return NULL; return NULL;
if (!__system_property_area__)
return NULL;
return (data_ + off); return (__system_property_area__->data + off);
} }
inline prop_bt *prop_area::to_prop_bt(atomic_uint_least32_t* off_p) { static inline prop_bt *to_prop_bt(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume); uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_bt*>(to_prop_obj(off)); return reinterpret_cast<prop_bt*>(to_prop_obj(off));
} }
inline prop_info *prop_area::to_prop_info(atomic_uint_least32_t* off_p) { static inline prop_info *to_prop_info(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume); uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_info*>(to_prop_obj(off)); return reinterpret_cast<prop_info*>(to_prop_obj(off));
} }
inline prop_bt *prop_area::root_node() static inline prop_bt *root_node()
{ {
return reinterpret_cast<prop_bt*>(to_prop_obj(0)); return reinterpret_cast<prop_bt*>(to_prop_obj(0));
} }
@ -418,7 +366,7 @@ static int cmp_prop_name(const char *one, uint8_t one_len, const char *two,
return strncmp(one, two, one_len); return strncmp(one, two, one_len);
} }
prop_bt *prop_area::find_prop_bt(prop_bt *const bt, const char *name, static prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
uint8_t namelen, bool alloc_if_needed) uint8_t namelen, bool alloc_if_needed)
{ {
@ -469,7 +417,7 @@ prop_bt *prop_area::find_prop_bt(prop_bt *const bt, const char *name,
} }
} }
const prop_info *prop_area::find_property(prop_bt *const trie, const char *name, static const prop_info *find_property(prop_bt *const trie, const char *name,
uint8_t namelen, const char *value, uint8_t valuelen, uint8_t namelen, const char *value, uint8_t valuelen,
bool alloc_if_needed) bool alloc_if_needed)
{ {
@ -595,439 +543,44 @@ static void find_nth_fn(const prop_info *pi, void *ptr)
cookie->count++; cookie->count++;
} }
bool prop_area::foreach_property(prop_bt *const trie, static int foreach_property(prop_bt *const trie,
void (*propfn)(const prop_info *pi, void *cookie), void *cookie) void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
{ {
if (!trie) if (!trie)
return false; return -1;
uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed); uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
if (left_offset != 0) { if (left_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie); const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
if (err < 0) if (err < 0)
return false; return -1;
} }
uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed); uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
if (prop_offset != 0) { if (prop_offset != 0) {
prop_info *info = to_prop_info(&trie->prop); prop_info *info = to_prop_info(&trie->prop);
if (!info) if (!info)
return false; return -1;
propfn(info, cookie); propfn(info, cookie);
} }
uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed); uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
if (children_offset != 0) { if (children_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie); const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
if (err < 0) if (err < 0)
return false; return -1;
} }
uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed); uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
if (right_offset != 0) { if (right_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie); const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
if (err < 0) if (err < 0)
return false;
}
return true;
}
const prop_info *prop_area::find(const char *name) {
return find_property(root_node(), name, strlen(name), nullptr, 0, false);
}
bool prop_area::add(const char *name, unsigned int namelen,
const char *value, unsigned int valuelen) {
return find_property(root_node(), name, namelen, value, valuelen, true);
}
bool prop_area::foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
return foreach_property(root_node(), propfn, cookie);
}
class context_node {
public:
context_node(context_node* next, const char* context, prop_area* pa)
: next(next), context_(strdup(context)), pa_(pa), no_access_(false) {
lock_.init(false);
}
~context_node() {
unmap();
free(context_);
}
bool open(bool access_rw, bool* fsetxattr_failed);
bool check_access_and_open();
void reset_access();
const char* context() const { return context_; }
prop_area* pa() { return pa_; }
context_node* next;
private:
bool check_access();
void unmap();
Lock lock_;
char* context_;
prop_area* pa_;
bool no_access_;
};
struct prefix_node {
prefix_node(struct prefix_node* next, const char* prefix, context_node* context)
: prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
}
~prefix_node() {
free(prefix);
}
char* prefix;
const size_t prefix_len;
context_node* context;
struct prefix_node* next;
};
template <typename List, typename... Args>
static inline void list_add(List** list, Args... args) {
*list = new List(*list, args...);
}
static void list_add_after_len(prefix_node** list, const char* prefix, context_node* context) {
size_t prefix_len = strlen(prefix);
auto next_list = list;
while (*next_list) {
if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
list_add(next_list, prefix, context);
return;
}
next_list = &(*next_list)->next;
}
list_add(next_list, prefix, context);
}
template <typename List, typename Func>
static void list_foreach(List* list, Func func) {
while (list) {
func(list);
list = list->next;
}
}
template <typename List, typename Func>
static List* list_find(List* list, Func func) {
while (list) {
if (func(list)) {
return list;
}
list = list->next;
}
return nullptr;
}
template <typename List>
static void list_free(List** list) {
while (*list) {
auto old_list = *list;
*list = old_list->next;
delete old_list;
}
}
static prefix_node* prefixes = nullptr;
static context_node* contexts = nullptr;
/*
* pthread_mutex_lock() calls into system_properties in the case of contention.
* This creates a risk of dead lock if any system_properties functions
* use pthread locks after system_property initialization.
*
* For this reason, the below three functions use a bionic Lock and static
* allocation of memory for each filename.
*/
bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
lock_.lock();
if (pa_) {
lock_.unlock();
return true;
}
char filename[PROP_FILENAME_MAX];
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, context_);
if (len < 0 || len > PROP_FILENAME_MAX) {
lock_.unlock();
return false;
}
if (access_rw) {
pa_ = map_prop_area_rw(filename, context_, fsetxattr_failed);
} else {
pa_ = map_prop_area(filename, false);
}
lock_.unlock();
return pa_;
}
bool context_node::check_access_and_open() {
if (!pa_ && !no_access_) {
if (!check_access() || !open(false, nullptr)) {
no_access_ = true;
}
}
return pa_;
}
void context_node::reset_access() {
if (!check_access()) {
unmap();
no_access_ = true;
} else {
no_access_ = false;
}
}
bool context_node::check_access() {
char filename[PROP_FILENAME_MAX];
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, context_);
if (len < 0 || len > PROP_FILENAME_MAX) {
return false;
}
return access(filename, R_OK) == 0;
}
void context_node::unmap() {
if (!pa_) {
return;
}
munmap(pa_, pa_size);
if (pa_ == __system_property_area__) {
__system_property_area__ = nullptr;
}
pa_ = nullptr;
}
static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
char filename[PROP_FILENAME_MAX];
int len = snprintf(filename, sizeof(filename), "%s/properties_serial", property_filename);
if (len < 0 || len > PROP_FILENAME_MAX) {
__system_property_area__ = nullptr;
return false;
}
if (access_rw) {
__system_property_area__ =
map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
} else {
__system_property_area__ = map_prop_area(filename, false);
}
return __system_property_area__;
}
static prop_area* get_prop_area_for_name(const char* name) {
auto entry = list_find(prefixes, [name](prefix_node* l) {
return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
});
if (!entry) {
return nullptr;
}
auto cnode = entry->context;
if (!cnode->pa()) {
/*
* We explicitly do not check no_access_ in this case because unlike the
* case of foreach(), we want to generate an selinux audit for each
* non-permitted property access in this function.
*/
cnode->open(false, nullptr);
}
return cnode->pa();
}
/*
* The below two functions are duplicated from label_support.c in libselinux.
* TODO: Find a location suitable for these functions such that both libc and
* libselinux can share a common source file.
*/
/*
* The read_spec_entries and read_spec_entry functions may be used to
* replace sscanf to read entries from spec files. The file and
* property services now use these.
*/
/* Read an entry from a spec file (e.g. file_contexts) */
static inline int read_spec_entry(char **entry, char **ptr, int *len)
{
*entry = NULL;
char *tmp_buf = NULL;
while (isspace(**ptr) && **ptr != '\0')
(*ptr)++;
tmp_buf = *ptr;
*len = 0;
while (!isspace(**ptr) && **ptr != '\0') {
(*ptr)++;
(*len)++;
}
if (*len) {
*entry = strndup(tmp_buf, *len);
if (!*entry)
return -1; return -1;
} }
return 0; return 0;
} }
/*
* line_buf - Buffer containing the spec entries .
* num_args - The number of spec parameter entries to process.
* ... - A 'char **spec_entry' for each parameter.
* returns - The number of items processed.
*
* This function calls read_spec_entry() to do the actual string processing.
*/
static int read_spec_entries(char *line_buf, int num_args, ...)
{
char **spec_entry, *buf_p;
int len, rc, items, entry_len = 0;
va_list ap;
len = strlen(line_buf);
if (line_buf[len - 1] == '\n')
line_buf[len - 1] = '\0';
else
/* Handle case if line not \n terminated by bumping
* the len for the check below (as the line is NUL
* terminated by getline(3)) */
len++;
buf_p = line_buf;
while (isspace(*buf_p))
buf_p++;
/* Skip comment lines and empty lines. */
if (*buf_p == '#' || *buf_p == '\0')
return 0;
/* Process the spec file entries */
va_start(ap, num_args);
items = 0;
while (items < num_args) {
spec_entry = va_arg(ap, char **);
if (len - 1 == buf_p - line_buf) {
va_end(ap);
return items;
}
rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
if (rc < 0) {
va_end(ap);
return rc;
}
if (entry_len)
items++;
}
va_end(ap);
return items;
}
static bool initialize_properties() {
FILE* file = fopen("/property_contexts", "re");
if (!file) {
return false;
}
char* buffer = nullptr;
size_t line_len;
char* prop_prefix = nullptr;
char* context = nullptr;
while (getline(&buffer, &line_len, file) > 0) {
int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
if (items <= 0) {
continue;
}
if (items == 1) {
free(prop_prefix);
continue;
}
/*
* init uses ctl.* properties as an IPC mechanism and does not write them
* to a property file, therefore we do not need to create property files
* to store them.
*/
if (!strncmp(prop_prefix, "ctl.", 4)) {
free(prop_prefix);
free(context);
continue;
}
auto old_context = list_find(
contexts, [context](context_node* l) { return !strcmp(l->context(), context); });
if (old_context) {
list_add_after_len(&prefixes, prop_prefix, old_context);
} else {
list_add(&contexts, context, nullptr);
list_add_after_len(&prefixes, prop_prefix, contexts);
}
free(prop_prefix);
free(context);
}
free(buffer);
fclose(file);
return true;
}
static bool is_dir(const char* pathname) {
struct stat info;
if (stat(pathname, &info) == -1) {
return false;
}
return S_ISDIR(info.st_mode);
}
static void free_and_unmap_contexts() {
list_free(&prefixes);
list_free(&contexts);
if (__system_property_area__) {
munmap(__system_property_area__, pa_size);
__system_property_area__ = nullptr;
}
}
int __system_properties_init() int __system_properties_init()
{ {
if (initialized) { return map_prop_area();
list_foreach(contexts, [](context_node* l) { l->reset_access(); });
return 0;
}
if (is_dir(property_filename)) {
if (!initialize_properties()) {
return -1;
}
if (!map_system_property_area(false, nullptr)) {
free_and_unmap_contexts();
return -1;
}
} else {
__system_property_area__ = map_prop_area(property_filename, true);
if (!__system_property_area__) {
return -1;
}
list_add(&contexts, "legacy_system_prop_area", __system_property_area__);
list_add_after_len(&prefixes, "*", contexts);
}
initialized = true;
return 0;
} }
int __system_property_set_filename(const char *filename) int __system_property_set_filename(const char *filename)
@ -1042,24 +595,7 @@ int __system_property_set_filename(const char *filename)
int __system_property_area_init() int __system_property_area_init()
{ {
free_and_unmap_contexts(); return map_prop_area_rw();
mkdir(property_filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (!initialize_properties()) {
return -1;
}
bool open_failed = false;
bool fsetxattr_failed = false;
list_foreach(contexts, [&fsetxattr_failed, &open_failed](context_node* l) {
if (!l->open(true, &fsetxattr_failed)) {
open_failed = true;
}
});
if (open_failed || !map_system_property_area(true, &fsetxattr_failed)) {
free_and_unmap_contexts();
return -1;
}
initialized = true;
return fsetxattr_failed ? -2 : 0;
} }
unsigned int __system_property_area_serial() unsigned int __system_property_area_serial()
@ -1069,26 +605,15 @@ unsigned int __system_property_area_serial()
return -1; return -1;
} }
// Make sure this read fulfilled before __system_property_serial // Make sure this read fulfilled before __system_property_serial
return atomic_load_explicit(pa->serial(), memory_order_acquire); return atomic_load_explicit(&(pa->serial), memory_order_acquire);
} }
const prop_info *__system_property_find(const char *name) const prop_info *__system_property_find(const char *name)
{ {
if (!__system_property_area__) {
return nullptr;
}
if (__predict_false(compat_mode)) { if (__predict_false(compat_mode)) {
return __system_property_find_compat(name); return __system_property_find_compat(name);
} }
return find_property(root_node(), name, strlen(name), NULL, 0, false);
prop_area* pa = get_prop_area_for_name(name);
if (!pa) {
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
return nullptr;
}
return pa->find(name);
} }
// The C11 standard doesn't allow atomic loads from const fields, // The C11 standard doesn't allow atomic loads from const fields,
@ -1163,14 +688,10 @@ int __system_property_set(const char *key, const char *value)
int __system_property_update(prop_info *pi, const char *value, unsigned int len) int __system_property_update(prop_info *pi, const char *value, unsigned int len)
{ {
if (len >= PROP_VALUE_MAX)
return -1;
prop_area *pa = __system_property_area__; prop_area *pa = __system_property_area__;
if (!pa) { if (len >= PROP_VALUE_MAX)
return -1; return -1;
}
uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed); uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
serial |= 1; serial |= 1;
@ -1187,10 +708,10 @@ int __system_property_update(prop_info *pi, const char *value, unsigned int len)
__futex_wake(&pi->serial, INT32_MAX); __futex_wake(&pi->serial, INT32_MAX);
atomic_store_explicit( atomic_store_explicit(
pa->serial(), &pa->serial,
atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1, atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
memory_order_release); memory_order_release);
__futex_wake(pa->serial(), INT32_MAX); __futex_wake(&pa->serial, INT32_MAX);
return 0; return 0;
} }
@ -1198,6 +719,9 @@ int __system_property_update(prop_info *pi, const char *value, unsigned int len)
int __system_property_add(const char *name, unsigned int namelen, int __system_property_add(const char *name, unsigned int namelen,
const char *value, unsigned int valuelen) const char *value, unsigned int valuelen)
{ {
prop_area *pa = __system_property_area__;
const prop_info *pi;
if (namelen >= PROP_NAME_MAX) if (namelen >= PROP_NAME_MAX)
return -1; return -1;
if (valuelen >= PROP_VALUE_MAX) if (valuelen >= PROP_VALUE_MAX)
@ -1205,28 +729,17 @@ int __system_property_add(const char *name, unsigned int namelen,
if (namelen < 1) if (namelen < 1)
return -1; return -1;
if (!__system_property_area__) { pi = find_property(root_node(), name, namelen, value, valuelen, true);
return -1; if (!pi)
}
prop_area* pa = get_prop_area_for_name(name);
if (!pa) {
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
return -1;
}
bool ret = pa->add(name, namelen, value, valuelen);
if (!ret)
return -1; return -1;
// There is only a single mutator, but we want to make sure that // There is only a single mutator, but we want to make sure that
// updates are visible to a reader waiting for the update. // updates are visible to a reader waiting for the update.
atomic_store_explicit( atomic_store_explicit(
__system_property_area__->serial(), &pa->serial,
atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1, atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
memory_order_release); memory_order_release);
__futex_wake(__system_property_area__->serial(), INT32_MAX); __futex_wake(&pa->serial, INT32_MAX);
return 0; return 0;
} }
@ -1248,13 +761,9 @@ unsigned int __system_property_wait_any(unsigned int serial)
prop_area *pa = __system_property_area__; prop_area *pa = __system_property_area__;
uint32_t my_serial; uint32_t my_serial;
if (!pa) {
return 0;
}
do { do {
__futex_wait(pa->serial(), serial, NULL); __futex_wait(&pa->serial, serial, NULL);
my_serial = atomic_load_explicit(pa->serial(), memory_order_acquire); my_serial = atomic_load_explicit(&pa->serial, memory_order_acquire);
} while (my_serial == serial); } while (my_serial == serial);
return my_serial; return my_serial;
@ -1275,18 +784,9 @@ const prop_info *__system_property_find_nth(unsigned n)
int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie), int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
void *cookie) void *cookie)
{ {
if (!__system_property_area__) {
return -1;
}
if (__predict_false(compat_mode)) { if (__predict_false(compat_mode)) {
return __system_property_foreach_compat(propfn, cookie); return __system_property_foreach_compat(propfn, cookie);
} }
list_foreach(contexts, [propfn, cookie](context_node* l) { return foreach_property(root_node(), propfn, cookie);
if (l->check_access_and_open()) {
l->pa()->foreach(propfn, cookie);
}
});
return 0;
} }

View File

@ -98,11 +98,6 @@ enum {
*/ */
ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100, ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100,
/* This flag used to load library in a different namespace. The namespace is
* specified in library_namespace.
*/
ANDROID_DLEXT_USE_NAMESPACE = 0x200,
/* Mask of valid bits */ /* Mask of valid bits */
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
ANDROID_DLEXT_RESERVED_ADDRESS_HINT | ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
@ -112,12 +107,9 @@ enum {
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_FORCE_LOAD |
ANDROID_DLEXT_FORCE_FIXED_VADDR | ANDROID_DLEXT_FORCE_FIXED_VADDR |
ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS | ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS,
ANDROID_DLEXT_USE_NAMESPACE,
}; };
struct android_namespace_t;
typedef struct { typedef struct {
uint64_t flags; uint64_t flags;
void* reserved_addr; void* reserved_addr;
@ -125,75 +117,10 @@ typedef struct {
int relro_fd; int relro_fd;
int library_fd; int library_fd;
off64_t library_fd_offset; off64_t library_fd_offset;
struct android_namespace_t* library_namespace;
} android_dlextinfo; } android_dlextinfo;
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo); extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
/*
* Initializes public and anonymous namespaces. The public_ns_sonames is the list of sonames
* to be included into public namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
* The libraries in this list should be loaded prior to this call.
*
* The anon_ns_library_path is the search path for anonymous namespace. The anonymous namespace
* is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
* for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
*/
extern bool android_init_namespaces(const char* public_ns_sonames,
const char* anon_ns_library_path);
enum {
/* A regular namespace is the namespace with a custom search path that does
* not impose any restrictions on the location of native libraries.
*/
ANDROID_NAMESPACE_TYPE_REGULAR = 0,
/* An isolated namespace requires all the libraries to be on the search path
* or under permitted_when_isolated_path. The search path is the union of
* ld_library_path and default_library_path.
*/
ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
/* The shared namespace clones the list of libraries of the caller namespace upon creation
* which means that they are shared between namespaces - the caller namespace and the new one
* will use the same copy of a library if it was loaded prior to android_create_namespace call.
*
* Note that libraries loaded after the namespace is created will not be shared.
*
* Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
* permitted_path from the caller's namespace.
*/
ANDROID_NAMESPACE_TYPE_SHARED = 2,
ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
ANDROID_NAMESPACE_TYPE_ISOLATED,
};
/*
* Creates new linker namespace.
* ld_library_path and default_library_path represent the search path
* for the libraries in the namespace.
*
* The libraries in the namespace are searched by folowing order:
* 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
* 2. In directories specified by DT_RUNPATH of the "needed by" binary.
* 3. deault_library_path (This of this as namespace-local default library path)
*
* When type is ANDROID_NAMESPACE_TYPE_ISOLATED the resulting namespace requires all of
* the libraries to be on the search path or under the permitted_when_isolated_path;
* the search_path is ld_library_path:default_library_path. Note that the
* permitted_when_isolated_path path is not part of the search_path and
* does not affect the search order. It is a way to allow loading libraries from specific
* locations when using absolute path.
* If a library or any of its dependencies are outside of the permitted_when_isolated_path
* and search_path, and it is not part of the public namespace dlopen will fail.
*/
extern struct android_namespace_t* android_create_namespace(const char* name,
const char* ld_library_path,
const char* default_library_path,
uint64_t type,
const char* permitted_when_isolated_path);
__END_DECLS __END_DECLS
#endif /* __ANDROID_DLEXT_H__ */ #endif /* __ANDROID_DLEXT_H__ */

View File

@ -46,8 +46,7 @@ typedef struct {
extern void* dlopen(const char* filename, int flag); extern void* dlopen(const char* filename, int flag);
extern int dlclose(void* handle); extern int dlclose(void* handle);
extern const char* dlerror(void); extern const char* dlerror(void);
extern void* dlsym(void* handle, const char* symbol) __nonnull((2)); extern void* dlsym(void* handle, const char* symbol);
extern void* dlvsym(void* handle, const char* symbol, const char* version) __nonnull((2, 3));
extern int dladdr(const void* addr, Dl_info *info); extern int dladdr(const void* addr, Dl_info *info);
enum { enum {

View File

@ -32,19 +32,18 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/types.h> #include <sys/types.h>
__BEGIN_DECLS __BEGIN_DECLS
#if !defined(__bionic_using_gnu_basename)
/* /*
* Including <string.h> will get you the GNU basename, unless <libgen.h> is * <string.h> gets you the GNU basename.
* included, either before or after including <string.h>. * <libgen.h> the POSIX one.
* * Note that our "POSIX" one has the wrong argument cv-qualifiers, but doesn't
* Note that this has the wrong argument cv-qualifiers, but doesn't modify its * modify its input and uses thread-local storage for the result if necessary.
* input and uses thread-local storage for the result if necessary.
*/ */
extern char* __posix_basename(const char*) __RENAME(basename); extern char* basename(const char*);
#define __bionic_using_posix_basename
#define basename __posix_basename #endif
/* This has the wrong argument cv-qualifiers, but doesn't modify its input and uses thread-local storage for the result if necessary. */ /* This has the wrong argument cv-qualifiers, but doesn't modify its input and uses thread-local storage for the result if necessary. */
extern char* dirname(const char*); extern char* dirname(const char*);

View File

@ -96,26 +96,6 @@ typedef int pthread_once_t;
#define PTHREAD_ONCE_INIT 0 #define PTHREAD_ONCE_INIT 0
typedef struct {
#if defined(__LP64__)
int64_t __private[4];
#else
int32_t __private[8];
#endif
} pthread_barrier_t;
typedef int pthread_barrierattr_t;
#define PTHREAD_BARRIER_SERIAL_THREAD -1
typedef struct {
#if defined(__LP64__)
int64_t __private;
#else
int32_t __private[2];
#endif
} pthread_spinlock_t;
#if defined(__LP64__) #if defined(__LP64__)
#define PTHREAD_STACK_MIN (4 * PAGE_SIZE) #define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
#else #else
@ -150,7 +130,7 @@ int pthread_attr_setschedparam(pthread_attr_t*, const struct sched_param*) __non
int pthread_attr_setschedpolicy(pthread_attr_t*, int) __nonnull((1)); int pthread_attr_setschedpolicy(pthread_attr_t*, int) __nonnull((1));
int pthread_attr_setscope(pthread_attr_t*, int) __nonnull((1)); int pthread_attr_setscope(pthread_attr_t*, int) __nonnull((1));
int pthread_attr_setstack(pthread_attr_t*, void*, size_t) __nonnull((1)); int pthread_attr_setstack(pthread_attr_t*, void*, size_t) __nonnull((1));
int pthread_attr_setstacksize(pthread_attr_t*, size_t) __nonnull((1)); int pthread_attr_setstacksize(pthread_attr_t*, size_t stack_size) __nonnull((1));
int pthread_condattr_destroy(pthread_condattr_t*) __nonnull((1)); int pthread_condattr_destroy(pthread_condattr_t*) __nonnull((1));
int pthread_condattr_getclock(const pthread_condattr_t*, clockid_t*) __nonnull((1, 2)); int pthread_condattr_getclock(const pthread_condattr_t*, clockid_t*) __nonnull((1, 2));
@ -225,24 +205,9 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const struct timespec*) __nonn
int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const struct timespec*) __nonnull((1, 2)); int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const struct timespec*) __nonnull((1, 2));
int pthread_rwlock_tryrdlock(pthread_rwlock_t*) __nonnull((1)); int pthread_rwlock_tryrdlock(pthread_rwlock_t*) __nonnull((1));
int pthread_rwlock_trywrlock(pthread_rwlock_t*) __nonnull((1)); int pthread_rwlock_trywrlock(pthread_rwlock_t*) __nonnull((1));
int pthread_rwlock_unlock(pthread_rwlock_t *) __nonnull((1)); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) __nonnull((1));
int pthread_rwlock_wrlock(pthread_rwlock_t*) __nonnull((1)); int pthread_rwlock_wrlock(pthread_rwlock_t*) __nonnull((1));
int pthread_barrierattr_init(pthread_barrierattr_t* attr) __nonnull((1));
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) __nonnull((1));
int pthread_barrierattr_getpshared(pthread_barrierattr_t* attr, int* pshared) __nonnull((1, 2));
int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) __nonnull((1));
int pthread_barrier_init(pthread_barrier_t*, const pthread_barrierattr_t*, unsigned) __nonnull((1));
int pthread_barrier_destroy(pthread_barrier_t*) __nonnull((1));
int pthread_barrier_wait(pthread_barrier_t*) __nonnull((1));
int pthread_spin_destroy(pthread_spinlock_t*) __nonnull((1));
int pthread_spin_init(pthread_spinlock_t*, int) __nonnull((1));
int pthread_spin_lock(pthread_spinlock_t*) __nonnull((1));
int pthread_spin_trylock(pthread_spinlock_t*) __nonnull((1));
int pthread_spin_unlock(pthread_spinlock_t*) __nonnull((1));
pthread_t pthread_self(void) __pure2; pthread_t pthread_self(void) __pure2;
int pthread_setname_np(pthread_t, const char*) __nonnull((2)); int pthread_setname_np(pthread_t, const char*) __nonnull((2));

View File

@ -270,7 +270,6 @@ int vasprintf(char ** __restrict, const char * __restrict,
void clearerr_unlocked(FILE*); void clearerr_unlocked(FILE*);
int feof_unlocked(FILE*); int feof_unlocked(FILE*);
int ferror_unlocked(FILE*); int ferror_unlocked(FILE*);
int fileno_unlocked(FILE*);
/* /*
* Stdio function-access interface. * Stdio function-access interface.

View File

@ -115,18 +115,18 @@ extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
extern int strcoll_l(const char *, const char *, locale_t) __purefunc; extern int strcoll_l(const char *, const char *, locale_t) __purefunc;
extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t); extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
#if defined(__USE_GNU) && !defined(basename) #if defined(__USE_GNU) && !defined(__bionic_using_posix_basename)
/* /*
* glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>. * glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>.
* It doesn't modify its argument, and in C++ it's const-correct. * It doesn't modify its argument, and in C++ it's const-correct.
*/ */
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1)); extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1));
extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)); extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
#else #else
extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)); extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
#endif #endif
#define __bionic_using_gnu_basename
#endif #endif
extern void* __memchr_chk(const void*, int, size_t, size_t); extern void* __memchr_chk(const void*, int, size_t, size_t);

View File

@ -41,7 +41,6 @@ typedef struct prop_msg prop_msg;
#define PROP_AREA_VERSION_COMPAT 0x45434f76 #define PROP_AREA_VERSION_COMPAT 0x45434f76
#define PROP_SERVICE_NAME "property_service" #define PROP_SERVICE_NAME "property_service"
#define PROP_FILENAME_MAX 1024
#define PROP_FILENAME "/dev/__properties__" #define PROP_FILENAME "/dev/__properties__"
#define PA_SIZE (128 * 1024) #define PA_SIZE (128 * 1024)

View File

@ -59,7 +59,7 @@ extern void* mmap64(void*, size_t, int, int, int, off64_t);
extern int munmap(void*, size_t); extern int munmap(void*, size_t);
extern int msync(const void*, size_t, int); extern int msync(const void*, size_t, int);
extern int mprotect(const void*, size_t, int); extern int mprotect(const void*, size_t, int);
extern void* mremap(void*, size_t, size_t, int, ...); extern void* mremap(void*, size_t, size_t, unsigned long);
extern int mlockall(int); extern int mlockall(int);
extern int munlockall(void); extern int munlockall(void);

File diff suppressed because it is too large Load Diff

View File

@ -10,25 +10,43 @@ LIBC {
__b64_ntop; __b64_ntop;
__b64_pton; __b64_pton;
__brk; # arm x86 mips __brk; # arm x86 mips
__cmpdf2; # arm
__cmsg_nxthdr; __cmsg_nxthdr;
__connect; # arm x86 mips __connect; # arm x86 mips
__ctype_get_mb_cur_max; __ctype_get_mb_cur_max;
__cxa_atexit; __cxa_atexit;
__cxa_finalize; __cxa_finalize;
__cxa_thread_atexit_impl; __cxa_thread_atexit_impl;
__divdf3; # arm
__divdi3; # arm x86 mips
__divsf3; # arm
__divsi3; # arm
__dn_comp; __dn_comp;
__dn_count_labels; __dn_count_labels;
__dn_skipname; __dn_skipname;
__epoll_pwait; # arm x86 mips __epoll_pwait; # arm x86 mips
__eqdf2; # arm
__errno; __errno;
__exit; # arm x86 mips __exit; # arm x86 mips
__extendsfdf2; # arm
__fbufsize; __fbufsize;
__fcntl64; # arm x86 mips __fcntl64; # arm x86 mips
__FD_CLR_chk; __FD_CLR_chk;
__FD_ISSET_chk; __FD_ISSET_chk;
__FD_SET_chk; __FD_SET_chk;
__fgets_chk; __fgets_chk;
__fixdfsi; # arm
__fixsfsi; # arm
__fixunssfsi; # arm
__flbf; __flbf;
__floatdidf; # arm
__floatdisf; # arm
__floatsidf; # arm
__floatsisf; # arm
__floatundidf; # arm
__floatundisf; # arm
__floatunsidf; # arm
__floatunsisf; # arm
__fp_nquery; __fp_nquery;
__fp_query; __fp_query;
__fpclassify; __fpclassify;
@ -40,14 +58,23 @@ LIBC {
__freadable; __freadable;
__fsetlocking; __fsetlocking;
__fstatfs64; # arm x86 mips __fstatfs64; # arm x86 mips
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable; __fwritable;
__gedf2; # arm
__get_h_errno; __get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
__getcpu; # arm x86 mips __getcpu; # arm x86 mips
__getcwd; # arm x86 mips __getcwd; # arm x86 mips
__getdents64; # arm x86 mips
__getpid; # arm x86 mips __getpid; # arm x86 mips
__getpriority; # arm x86 mips __getpriority; # arm x86 mips
__gnu_basename; __gnu_basename;
__gnu_ldivmod_helper; # arm
__gnu_strerror_r; __gnu_strerror_r;
__gnu_uldivmod_helper; # arm
__gtdf2; # arm
__hostalias; __hostalias;
__ioctl; # arm x86 mips __ioctl; # arm x86 mips
__isfinite; __isfinite;
@ -63,18 +90,25 @@ LIBC {
__isnormalf; __isnormalf;
__isnormall; __isnormall;
__isthreaded; __isthreaded;
__ledf2; # arm
__libc_current_sigrtmax; __libc_current_sigrtmax;
__libc_current_sigrtmin; __libc_current_sigrtmin;
__libc_init; __libc_init;
__llseek; # arm x86 mips __llseek; # arm x86 mips
__loc_aton; __loc_aton;
__loc_ntoa; __loc_ntoa;
__lshrdi3; # arm
__ltdf2; # arm
__memchr_chk; __memchr_chk;
__memcpy_chk; __memcpy_chk;
__memmove_chk; __memmove_chk;
__memrchr_chk; __memrchr_chk;
__memset_chk; __memset_chk;
__mmap2; # arm x86 mips __mmap2; # arm x86 mips
__muldf3; # arm
__muldi3; # arm
__mulsf3; # arm
__nedf2; # arm
__ns_format_ttl; # arm x86 mips __ns_format_ttl; # arm x86 mips
__ns_get16; # arm x86 mips __ns_get16; # arm x86 mips
__ns_get32; # arm x86 mips __ns_get32; # arm x86 mips
@ -97,6 +131,7 @@ LIBC {
__ns_skiprr; # arm x86 mips __ns_skiprr; # arm x86 mips
__ns_sprintrr; # arm x86 mips __ns_sprintrr; # arm x86 mips
__ns_sprintrrf; # arm x86 mips __ns_sprintrrf; # arm x86 mips
__open; # arm x86 mips
__open_2; __open_2;
__openat; # arm x86 mips __openat; # arm x86 mips
__openat_2; __openat_2;
@ -113,7 +148,11 @@ LIBC {
__p_time; __p_time;
__p_type; __p_type;
__p_type_syms; __p_type_syms;
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk; __poll_chk;
__popcount_tab; # arm
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips __ppoll; # arm x86 mips
__ppoll_chk; __ppoll_chk;
__pread64_chk; __pread64_chk;
@ -122,7 +161,7 @@ LIBC {
__pselect6; # arm x86 mips __pselect6; # arm x86 mips
__pthread_cleanup_pop; __pthread_cleanup_pop;
__pthread_cleanup_push; __pthread_cleanup_push;
__pthread_gettid; # arm x86 mips nobrillo __pthread_gettid; # arm x86 mips
__ptrace; # arm x86 mips __ptrace; # arm x86 mips
__putlong; __putlong;
__putshort; __putshort;
@ -152,6 +191,7 @@ LIBC {
__res_send; __res_send;
__res_send_setqhook; __res_send_setqhook;
__res_send_setrhook; __res_send_setrhook;
__restore_core_regs; # arm
__rt_sigaction; # arm x86 mips __rt_sigaction; # arm x86 mips
__rt_sigpending; # arm x86 mips __rt_sigpending; # arm x86 mips
__rt_sigprocmask; # arm x86 mips __rt_sigprocmask; # arm x86 mips
@ -161,14 +201,27 @@ LIBC {
__sched_cpucount; __sched_cpucount;
__sched_cpufree; __sched_cpufree;
__sched_getaffinity; # arm x86 mips __sched_getaffinity; # arm x86 mips
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
__set_tid_address; # arm x86 mips __set_tid_address; # arm x86 mips
__set_tls; # arm mips __set_tls; # arm mips
__sF; __sF;
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sigaction; # arm x86 mips __sigaction; # arm x86 mips
__signalfd4; # arm x86 mips __signalfd4; # arm x86 mips
__sinit; # arm x86 mips
__smakebuf; # arm x86 mips
__snprintf_chk; __snprintf_chk;
__socket; # arm x86 mips __socket; # arm x86 mips
__sprintf_chk; __sprintf_chk;
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__stack_chk_fail; __stack_chk_fail;
__stack_chk_guard; __stack_chk_guard;
__statfs64; # arm x86 mips __statfs64; # arm x86 mips
@ -185,37 +238,49 @@ LIBC {
__strncpy_chk; __strncpy_chk;
__strncpy_chk2; __strncpy_chk2;
__strrchr_chk; __strrchr_chk;
__subdf3; # arm
__subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init; # arm x86 mips __system_properties_init;
__system_property_add; # arm x86 mips __system_property_add;
__system_property_area__; # arm x86 mips __system_property_area__;
__system_property_area_init; # arm x86 mips __system_property_area_init;
__system_property_area_serial; # arm x86 mips __system_property_area_serial;
__system_property_find; # arm x86 mips __system_property_find;
__system_property_find_nth; # arm x86 mips __system_property_find_nth;
__system_property_foreach; # arm x86 mips __system_property_foreach;
__system_property_get; # arm x86 mips __system_property_get;
__system_property_read; # arm x86 mips __system_property_read;
__system_property_serial; # arm x86 mips __system_property_serial;
__system_property_set; # arm x86 mips __system_property_set;
__system_property_set_filename; # arm x86 mips __system_property_set_filename;
__system_property_update; # arm x86 mips __system_property_update;
__system_property_wait_any; # arm x86 mips __system_property_wait_any;
__timer_create; # arm x86 mips __timer_create; # arm x86 mips
__timer_delete; # arm x86 mips __timer_delete; # arm x86 mips
__timer_getoverrun; # arm x86 mips __timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips __timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips __timer_settime; # arm x86 mips
__truncdfsf2; # arm
__udivdi3; # arm x86 mips
__udivsi3; # arm
__umask_chk; __umask_chk;
__unorddf2; # arm
__unordsf2; # arm
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
__wait4; # arm x86 mips
__waitid; # arm x86 mips __waitid; # arm x86 mips
_ctype_; _ctype_;
_Exit; _Exit;
_exit; _exit;
_flushlbf; _flushlbf;
_fwalk; # arm x86 mips
_getlong; _getlong;
_getshort; _getshort;
_longjmp; _longjmp;
@ -242,7 +307,9 @@ LIBC {
android_gethostbynamefornet; android_gethostbynamefornet;
android_set_abort_message; android_set_abort_message;
arc4random; arc4random;
arc4random_addrandom; # arm x86 mips
arc4random_buf; arc4random_buf;
arc4random_stir; # arm x86 mips
arc4random_uniform; arc4random_uniform;
asctime; asctime;
asctime64; # arm x86 mips asctime64; # arm x86 mips
@ -256,11 +323,14 @@ LIBC {
atoll; atoll;
basename; basename;
basename_r; # arm x86 mips basename_r; # arm x86 mips
bcopy; # arm x86 mips
bind; bind;
bindresvport; bindresvport;
brk; brk;
bsd_signal; # arm x86 mips
bsearch; bsearch;
btowc; btowc;
bzero; # arm x86 mips
c16rtomb; c16rtomb;
c32rtomb; c32rtomb;
cacheflush; # arm mips cacheflush; # arm mips
@ -313,6 +383,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -359,6 +430,7 @@ LIBC {
fdatasync; fdatasync;
fdopen; fdopen;
fdopendir; fdopendir;
fdprintf; # arm x86 mips
feof; feof;
feof_unlocked; feof_unlocked;
ferror; ferror;
@ -390,6 +462,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -410,6 +483,7 @@ LIBC {
fsync; fsync;
ftell; ftell;
ftello; ftello;
ftime; # arm x86 mips
ftok; ftok;
ftruncate; ftruncate;
ftruncate64; ftruncate64;
@ -430,6 +504,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -441,6 +516,8 @@ LIBC {
getchar_unlocked; getchar_unlocked;
getcwd; getcwd;
getdelim; getdelim;
getdents; # arm x86 mips
getdtablesize; # arm x86 mips
getegid; getegid;
getenv; getenv;
geteuid; geteuid;
@ -515,6 +592,7 @@ LIBC {
if_nametoindex; if_nametoindex;
imaxabs; imaxabs;
imaxdiv; imaxdiv;
index; # arm x86 mips
inet_addr; inet_addr;
inet_aton; inet_aton;
inet_lnaof; inet_lnaof;
@ -567,6 +645,7 @@ LIBC {
isprint_l; isprint_l;
ispunct; ispunct;
ispunct_l; ispunct_l;
issetugid; # arm x86 mips
isspace; isspace;
isspace_l; isspace_l;
isupper; isupper;
@ -656,6 +735,7 @@ LIBC {
mempcpy; mempcpy;
memrchr; memrchr;
memset; memset;
memswap; # arm x86 mips
mincore; mincore;
mkdir; mkdir;
mkdirat; mkdirat;
@ -675,6 +755,7 @@ LIBC {
mktemp; mktemp;
mktime; mktime;
mktime64; # arm x86 mips mktime64; # arm x86 mips
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -745,6 +826,7 @@ LIBC {
pthread_attr_getschedpolicy; pthread_attr_getschedpolicy;
pthread_attr_getscope; pthread_attr_getscope;
pthread_attr_getstack; pthread_attr_getstack;
pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize; pthread_attr_getstacksize;
pthread_attr_init; pthread_attr_init;
pthread_attr_setdetachstate; pthread_attr_setdetachstate;
@ -753,6 +835,7 @@ LIBC {
pthread_attr_setschedpolicy; pthread_attr_setschedpolicy;
pthread_attr_setscope; pthread_attr_setscope;
pthread_attr_setstack; pthread_attr_setstack;
pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize; pthread_attr_setstacksize;
pthread_cond_broadcast; pthread_cond_broadcast;
pthread_cond_destroy; pthread_cond_destroy;
@ -868,6 +951,7 @@ LIBC {
res_mkquery; res_mkquery;
res_query; res_query;
res_search; res_search;
restore_core_regs; # arm
rewind; rewind;
rewinddir; rewinddir;
rmdir; rmdir;
@ -1010,6 +1094,8 @@ LIBC {
strncpy; strncpy;
strndup; strndup;
strnlen; strnlen;
strntoimax; # arm x86 mips
strntoumax; # arm x86 mips
strpbrk; strpbrk;
strptime; strptime;
strrchr; strrchr;
@ -1028,6 +1114,7 @@ LIBC {
strtoll; strtoll;
strtoll_l; strtoll_l;
strtoq; strtoq;
strtotimeval; # arm x86 mips
strtoul; strtoul;
strtoull; strtoull;
strtoull_l; strtoull_l;
@ -1049,6 +1136,7 @@ LIBC {
sysinfo; sysinfo;
syslog; syslog;
system; system;
sysv_signal; # arm x86 mips
tcdrain; tcdrain;
tcflow; tcflow;
tcflush; tcflush;
@ -1080,6 +1168,7 @@ LIBC {
timerfd_settime; timerfd_settime;
times; times;
timezone; timezone;
tkill; # arm x86 mips
tmpfile; tmpfile;
tmpnam; tmpnam;
toascii; toascii;
@ -1121,6 +1210,7 @@ LIBC {
vdprintf; vdprintf;
verr; verr;
verrx; verrx;
vfdprintf; # arm x86 mips
vfork; vfork;
vfprintf; vfprintf;
vfscanf; vfscanf;
@ -1140,6 +1230,7 @@ LIBC {
vwprintf; vwprintf;
vwscanf; vwscanf;
wait; wait;
wait3; # arm x86 mips
wait4; wait4;
waitid; waitid;
waitpid; waitpid;
@ -1188,6 +1279,7 @@ LIBC {
wcstoull; wcstoull;
wcstoull_l; wcstoull_l;
wcstoumax; wcstoumax;
wcswcs; # arm x86 mips
wcswidth; wcswidth;
wcsxfrm; wcsxfrm;
wcsxfrm_l; wcsxfrm_l;
@ -1212,46 +1304,17 @@ LIBC {
LIBC_N { LIBC_N {
global: global:
__aeabi_atexit; # arm
__aeabi_memclr; # arm
__aeabi_memclr4; # arm
__aeabi_memclr8; # arm
__aeabi_memcpy; # arm
__aeabi_memcpy4; # arm
__aeabi_memcpy8; # arm
__aeabi_memmove; # arm
__aeabi_memmove4; # arm
__aeabi_memmove8; # arm
__aeabi_memset; # arm
__aeabi_memset4; # arm
__aeabi_memset8; # arm
__fread_chk; __fread_chk;
__fwrite_chk; __fwrite_chk;
__getcwd_chk; __getcwd_chk;
__gnu_Unwind_Find_exidx; # arm
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
prlimit; # arm mips x86 prlimit; # arm mips x86
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1335,33 +1398,8 @@ LIBC_PRIVATE {
__ashrdi3; # arm __ashrdi3; # arm
__bionic_brk; # arm x86 mips __bionic_brk; # arm x86 mips
__bionic_libgcc_compat_symbols; # arm x86 __bionic_libgcc_compat_symbols; # arm x86
__cmpdf2; # arm __bionic_libgcc_unwind_symbols; # arm
__divdf3; # arm
__divdi3; # arm x86 mips
__divsf3; # arm
__divsi3; # arm
__dso_handle; # arm __dso_handle; # arm
__eqdf2; # arm
__extendsfdf2; # arm
__fixdfsi; # arm
__fixsfsi; # arm
__fixunssfsi; # arm
__floatdidf; # arm
__floatdisf; # arm
__floatsidf; # arm
__floatsisf; # arm
__floatundidf; # arm
__floatundisf; # arm
__floatunsidf; # arm
__floatunsisf; # arm
__futex_wait; # arm x86 mips nobrillo
__futex_wake; # arm x86 mips nobrillo
__gedf2; # arm
__get_thread; # arm x86 mips nobrillo
__get_tls; # arm x86 mips nobrillo
__getdents64; # arm x86 mips
__gnu_ldivmod_helper; # arm
__gnu_uldivmod_helper; # arm
__gnu_Unwind_Backtrace; # arm __gnu_Unwind_Backtrace; # arm
__gnu_unwind_execute; # arm __gnu_unwind_execute; # arm
__gnu_Unwind_Find_exidx; # arm __gnu_Unwind_Find_exidx; # arm
@ -1380,46 +1418,6 @@ LIBC_PRIVATE {
__gnu_Unwind_Save_VFP_D_16_to_31; # arm __gnu_Unwind_Save_VFP_D_16_to_31; # arm
__gnu_Unwind_Save_WMMXC; # arm __gnu_Unwind_Save_WMMXC; # arm
__gnu_Unwind_Save_WMMXD; # arm __gnu_Unwind_Save_WMMXD; # arm
__gtdf2; # arm
__ledf2; # arm
__lshrdi3; # arm
__ltdf2; # arm
__muldf3; # arm
__muldi3; # arm
__mulsf3; # arm
__nedf2; # arm
__open; # arm x86 mips nobrillo
__page_shift; # arm x86 mips nobrillo
__page_size; # arm x86 mips nobrillo
__popcount_tab; # arm
__popcountsi2; # arm x86 mips
__pthread_gettid; # arm x86 mips nobrillo
__restore_core_regs; # arm
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips nobrillo
__set_errno; # arm x86 mips nobrillo
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sinit; # arm x86 mips nobrillo
__smakebuf; # arm x86 mips
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__subdf3; # arm
__subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__truncdfsf2; # arm
__udivdi3; # arm mips
__udivsi3; # arm
__unorddf2; # arm
__unordsf2; # arm
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
_Unwind_Backtrace; # arm _Unwind_Backtrace; # arm
_Unwind_Complete; # arm _Unwind_Complete; # arm
_Unwind_DeleteException; # arm _Unwind_DeleteException; # arm
@ -1435,40 +1433,14 @@ LIBC_PRIVATE {
_Unwind_VRS_Get; # arm _Unwind_VRS_Get; # arm
_Unwind_VRS_Pop; # arm _Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm _Unwind_VRS_Set; # arm
arc4random_addrandom; # arm x86 mips nobrillo
arc4random_stir; # arm x86 mips nobrillo
atexit; # arm atexit; # arm
bcopy; # arm x86 mips nobrillo dlmalloc; # arm x86 mips
bzero; # arm x86 mips nobrillo dlmalloc_inspect_all;
bsd_signal; # arm x86 mips nobrillo dlmalloc_trim;
dlmalloc; # arm x86 mips nobrillo dlmalloc_usable_size; # arm x86 mips
dlmalloc_inspect_all; # arm x86 mips nobrillo
dlmalloc_trim; # arm x86 mips nobrillo
dlmalloc_usable_size; # arm x86 mips nobrillo
endpwent; # arm x86 mips nobrillo
fdprintf; # arm x86 mips nobrillo
free_malloc_leak_info;
ftime; # arm x86 mips nobrillo
get_malloc_leak_info;
getdents; # arm x86 mips nobrillo
getdtablesize; # arm x86 mips nobrillo
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
index; # arm x86 mips nobrillo
issetugid; # arm x86 mips nobrillo
memswap; # arm x86 mips nobrillo
pthread_attr_getstackaddr; # arm x86 mips nobrillo
pthread_attr_setstackaddr; # arm x86 mips nobrillo
restore_core_regs; # arm
SHA1Final; # arm x86 mips SHA1Final; # arm x86 mips
SHA1Init; # arm x86 mips SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips SHA1Update; # arm x86 mips
strntoimax; # arm x86 mips nobrillo
strntoumax; # arm x86 mips nobrillo
strtotimeval; # arm x86 mips nobrillo
sysv_signal; # arm x86 mips nobrillo
tkill; # arm x86 mips nobrillo
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
} LIBC_N; } LIBC_N;

View File

@ -131,6 +131,21 @@ LIBC {
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init;
__system_property_add;
__system_property_area__;
__system_property_area_init;
__system_property_area_serial;
__system_property_find;
__system_property_find_nth;
__system_property_foreach;
__system_property_get;
__system_property_read;
__system_property_serial;
__system_property_set;
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
__umask_chk; __umask_chk;
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
@ -226,6 +241,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -301,6 +317,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -341,6 +358,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -581,6 +599,7 @@ LIBC {
mkstemps64; mkstemps64;
mktemp; mktemp;
mktime; mktime;
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -1137,25 +1156,10 @@ LIBC_N {
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1165,22 +1169,7 @@ LIBC_N {
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
__system_properties_init; # arm64 x86_64 mips64 dlmalloc_inspect_all;
__system_property_add; # arm64 x86_64 mips64 dlmalloc_trim;
__system_property_area__; # arm64 x86_64 mips64
__system_property_area_init; # arm64 x86_64 mips64
__system_property_area_serial; # arm64 x86_64 mips64
__system_property_find; # arm64 x86_64 mips64
__system_property_find_nth; # arm64 x86_64 mips64
__system_property_foreach; # arm64 x86_64 mips64
__system_property_get; # arm64 x86_64 mips64
__system_property_read; # arm64 x86_64 mips64
__system_property_serial; # arm64 x86_64 mips64
__system_property_set; # arm64 x86_64 mips64
__system_property_set_filename; # arm64 x86_64 mips64
__system_property_update; # arm64 x86_64 mips64
__system_property_wait_any; # arm64 x86_64 mips64
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
} LIBC_N; } LIBC_N;

View File

@ -9,18 +9,25 @@ LIBC {
__b64_ntop; __b64_ntop;
__b64_pton; __b64_pton;
__brk; # arm x86 mips __brk; # arm x86 mips
__cmpdf2; # arm
__cmsg_nxthdr; __cmsg_nxthdr;
__connect; # arm x86 mips __connect; # arm x86 mips
__ctype_get_mb_cur_max; __ctype_get_mb_cur_max;
__cxa_atexit; __cxa_atexit;
__cxa_finalize; __cxa_finalize;
__cxa_thread_atexit_impl; __cxa_thread_atexit_impl;
__divdf3; # arm
__divdi3; # arm x86 mips
__divsf3; # arm
__divsi3; # arm
__dn_comp; __dn_comp;
__dn_count_labels; __dn_count_labels;
__dn_skipname; __dn_skipname;
__epoll_pwait; # arm x86 mips __epoll_pwait; # arm x86 mips
__eqdf2; # arm
__errno; __errno;
__exit; # arm x86 mips __exit; # arm x86 mips
__extendsfdf2; # arm
__fadvise64; # x86 mips __fadvise64; # x86 mips
__fbufsize; __fbufsize;
__fcntl64; # arm x86 mips __fcntl64; # arm x86 mips
@ -28,7 +35,18 @@ LIBC {
__FD_ISSET_chk; __FD_ISSET_chk;
__FD_SET_chk; __FD_SET_chk;
__fgets_chk; __fgets_chk;
__fixdfsi; # arm
__fixsfsi; # arm
__fixunssfsi; # arm
__flbf; __flbf;
__floatdidf; # arm
__floatdisf; # arm
__floatsidf; # arm
__floatsisf; # arm
__floatundidf; # arm
__floatundisf; # arm
__floatunsidf; # arm
__floatunsisf; # arm
__fp_nquery; __fp_nquery;
__fp_query; __fp_query;
__fpclassify; __fpclassify;
@ -40,14 +58,23 @@ LIBC {
__freadable; __freadable;
__fsetlocking; __fsetlocking;
__fstatfs64; # arm x86 mips __fstatfs64; # arm x86 mips
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable; __fwritable;
__gedf2; # arm
__get_h_errno; __get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
__getcpu; # arm x86 mips __getcpu; # arm x86 mips
__getcwd; # arm x86 mips __getcwd; # arm x86 mips
__getdents64; # arm x86 mips
__getpid; # arm x86 mips __getpid; # arm x86 mips
__getpriority; # arm x86 mips __getpriority; # arm x86 mips
__gnu_basename; __gnu_basename;
__gnu_ldivmod_helper; # arm
__gnu_strerror_r; __gnu_strerror_r;
__gnu_uldivmod_helper; # arm
__gtdf2; # arm
__hostalias; __hostalias;
__ioctl; # arm x86 mips __ioctl; # arm x86 mips
__isfinite; __isfinite;
@ -63,12 +90,15 @@ LIBC {
__isnormalf; __isnormalf;
__isnormall; __isnormall;
__isthreaded; __isthreaded;
__ledf2; # arm
__libc_current_sigrtmax; __libc_current_sigrtmax;
__libc_current_sigrtmin; __libc_current_sigrtmin;
__libc_init; __libc_init;
__llseek; # arm x86 mips __llseek; # arm x86 mips
__loc_aton; __loc_aton;
__loc_ntoa; __loc_ntoa;
__lshrdi3; # arm
__ltdf2; # arm
__memchr_chk; __memchr_chk;
__memcpy_chk; __memcpy_chk;
__memmove_chk; __memmove_chk;
@ -76,6 +106,10 @@ LIBC {
__memset_chk; __memset_chk;
__mmap2; # arm x86 mips __mmap2; # arm x86 mips
__moddi3; # x86 mips __moddi3; # x86 mips
__muldf3; # arm
__muldi3; # arm
__mulsf3; # arm
__nedf2; # arm
__ns_format_ttl; # arm x86 mips __ns_format_ttl; # arm x86 mips
__ns_get16; # arm x86 mips __ns_get16; # arm x86 mips
__ns_get32; # arm x86 mips __ns_get32; # arm x86 mips
@ -98,6 +132,7 @@ LIBC {
__ns_skiprr; # arm x86 mips __ns_skiprr; # arm x86 mips
__ns_sprintrr; # arm x86 mips __ns_sprintrr; # arm x86 mips
__ns_sprintrrf; # arm x86 mips __ns_sprintrrf; # arm x86 mips
__open; # arm x86 mips
__open_2; __open_2;
__openat; # arm x86 mips __openat; # arm x86 mips
__openat_2; __openat_2;
@ -114,7 +149,11 @@ LIBC {
__p_time; __p_time;
__p_type; __p_type;
__p_type_syms; __p_type_syms;
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk; __poll_chk;
__popcount_tab; # arm
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips __ppoll; # arm x86 mips
__ppoll_chk; __ppoll_chk;
__pread64_chk; __pread64_chk;
@ -123,7 +162,7 @@ LIBC {
__pselect6; # arm x86 mips __pselect6; # arm x86 mips
__pthread_cleanup_pop; __pthread_cleanup_pop;
__pthread_cleanup_push; __pthread_cleanup_push;
__pthread_gettid; # arm x86 mips nobrillo __pthread_gettid; # arm x86 mips
__ptrace; # arm x86 mips __ptrace; # arm x86 mips
__putlong; __putlong;
__putshort; __putshort;
@ -153,6 +192,7 @@ LIBC {
__res_send; __res_send;
__res_send_setqhook; __res_send_setqhook;
__res_send_setrhook; __res_send_setrhook;
__restore_core_regs; # arm
__rt_sigaction; # arm x86 mips __rt_sigaction; # arm x86 mips
__rt_sigpending; # arm x86 mips __rt_sigpending; # arm x86 mips
__rt_sigprocmask; # arm x86 mips __rt_sigprocmask; # arm x86 mips
@ -162,15 +202,28 @@ LIBC {
__sched_cpucount; __sched_cpucount;
__sched_cpufree; __sched_cpufree;
__sched_getaffinity; # arm x86 mips __sched_getaffinity; # arm x86 mips
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
__set_thread_area; # x86 __set_thread_area; # x86
__set_tid_address; # arm x86 mips __set_tid_address; # arm x86 mips
__set_tls; # arm mips __set_tls; # arm mips
__sF; __sF;
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sigaction; # arm x86 mips __sigaction; # arm x86 mips
__signalfd4; # arm x86 mips __signalfd4; # arm x86 mips
__sinit; # arm x86 mips
__smakebuf; # arm x86 mips
__snprintf_chk; __snprintf_chk;
__socket; # arm x86 mips __socket; # arm x86 mips
__sprintf_chk; __sprintf_chk;
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__stack_chk_fail; __stack_chk_fail;
__stack_chk_guard; __stack_chk_guard;
__statfs64; # arm x86 mips __statfs64; # arm x86 mips
@ -187,39 +240,51 @@ LIBC {
__strncpy_chk; __strncpy_chk;
__strncpy_chk2; __strncpy_chk2;
__strrchr_chk; __strrchr_chk;
__subdf3; # arm
__subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init; # arm x86 mips __system_properties_init;
__system_property_add; # arm x86 mips __system_property_add;
__system_property_area__; # arm x86 mips __system_property_area__;
__system_property_area_init; # arm x86 mips __system_property_area_init;
__system_property_area_serial; # arm x86 mips __system_property_area_serial;
__system_property_find; # arm x86 mips __system_property_find;
__system_property_find_nth; # arm x86 mips __system_property_find_nth;
__system_property_foreach; # arm x86 mips __system_property_foreach;
__system_property_get; # arm x86 mips __system_property_get;
__system_property_read; # arm x86 mips __system_property_read;
__system_property_serial; # arm x86 mips __system_property_serial;
__system_property_set; # arm x86 mips __system_property_set;
__system_property_set_filename; # arm x86 mips __system_property_set_filename;
__system_property_update; # arm x86 mips __system_property_update;
__system_property_wait_any; # arm x86 mips __system_property_wait_any;
__timer_create; # arm x86 mips __timer_create; # arm x86 mips
__timer_delete; # arm x86 mips __timer_delete; # arm x86 mips
__timer_getoverrun; # arm x86 mips __timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips __timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips __timer_settime; # arm x86 mips
__udivdi3; # x86 __truncdfsf2; # arm
__udivdi3; # arm x86 mips
__udivsi3; # arm
__umask_chk; __umask_chk;
__umoddi3; # x86 mips
__unorddf2; # arm
__unordsf2; # arm
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
__wait4; # arm x86 mips
__waitid; # arm x86 mips __waitid; # arm x86 mips
_ctype_; _ctype_;
_Exit; _Exit;
_exit; _exit;
_flush_cache; # mips _flush_cache; # mips
_flushlbf; _flushlbf;
_fwalk; # arm x86 mips
_getlong; _getlong;
_getshort; _getshort;
_longjmp; _longjmp;
@ -246,7 +311,9 @@ LIBC {
android_gethostbynamefornet; android_gethostbynamefornet;
android_set_abort_message; android_set_abort_message;
arc4random; arc4random;
arc4random_addrandom; # arm x86 mips
arc4random_buf; arc4random_buf;
arc4random_stir; # arm x86 mips
arc4random_uniform; arc4random_uniform;
asctime; asctime;
asctime64; # arm x86 mips asctime64; # arm x86 mips
@ -260,11 +327,14 @@ LIBC {
atoll; atoll;
basename; basename;
basename_r; # arm x86 mips basename_r; # arm x86 mips
bcopy; # arm x86 mips
bind; bind;
bindresvport; bindresvport;
brk; brk;
bsd_signal; # arm x86 mips
bsearch; bsearch;
btowc; btowc;
bzero; # arm x86 mips
c16rtomb; c16rtomb;
c32rtomb; c32rtomb;
cacheflush; # arm mips cacheflush; # arm mips
@ -317,6 +387,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -363,6 +434,7 @@ LIBC {
fdatasync; fdatasync;
fdopen; fdopen;
fdopendir; fdopendir;
fdprintf; # arm x86 mips
feof; feof;
feof_unlocked; feof_unlocked;
ferror; ferror;
@ -394,6 +466,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -414,6 +487,7 @@ LIBC {
fsync; fsync;
ftell; ftell;
ftello; ftello;
ftime; # arm x86 mips
ftok; ftok;
ftruncate; ftruncate;
ftruncate64; ftruncate64;
@ -434,6 +508,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -445,6 +520,8 @@ LIBC {
getchar_unlocked; getchar_unlocked;
getcwd; getcwd;
getdelim; getdelim;
getdents; # arm x86 mips
getdtablesize; # arm x86 mips
getegid; getegid;
getenv; getenv;
geteuid; geteuid;
@ -519,6 +596,7 @@ LIBC {
if_nametoindex; if_nametoindex;
imaxabs; imaxabs;
imaxdiv; imaxdiv;
index; # arm x86 mips
inet_addr; inet_addr;
inet_aton; inet_aton;
inet_lnaof; inet_lnaof;
@ -571,6 +649,7 @@ LIBC {
isprint_l; isprint_l;
ispunct; ispunct;
ispunct_l; ispunct_l;
issetugid; # arm x86 mips
isspace; isspace;
isspace_l; isspace_l;
isupper; isupper;
@ -660,6 +739,7 @@ LIBC {
mempcpy; mempcpy;
memrchr; memrchr;
memset; memset;
memswap; # arm x86 mips
mincore; mincore;
mkdir; mkdir;
mkdirat; mkdirat;
@ -679,6 +759,7 @@ LIBC {
mktemp; mktemp;
mktime; mktime;
mktime64; # arm x86 mips mktime64; # arm x86 mips
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -772,6 +853,7 @@ LIBC {
pthread_attr_getschedpolicy; pthread_attr_getschedpolicy;
pthread_attr_getscope; pthread_attr_getscope;
pthread_attr_getstack; pthread_attr_getstack;
pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize; pthread_attr_getstacksize;
pthread_attr_init; pthread_attr_init;
pthread_attr_setdetachstate; pthread_attr_setdetachstate;
@ -780,6 +862,7 @@ LIBC {
pthread_attr_setschedpolicy; pthread_attr_setschedpolicy;
pthread_attr_setscope; pthread_attr_setscope;
pthread_attr_setstack; pthread_attr_setstack;
pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize; pthread_attr_setstacksize;
pthread_cond_broadcast; pthread_cond_broadcast;
pthread_cond_destroy; pthread_cond_destroy;
@ -895,6 +978,7 @@ LIBC {
res_mkquery; res_mkquery;
res_query; res_query;
res_search; res_search;
restore_core_regs; # arm
rewind; rewind;
rewinddir; rewinddir;
rmdir; rmdir;
@ -1037,6 +1121,8 @@ LIBC {
strncpy; strncpy;
strndup; strndup;
strnlen; strnlen;
strntoimax; # arm x86 mips
strntoumax; # arm x86 mips
strpbrk; strpbrk;
strptime; strptime;
strrchr; strrchr;
@ -1055,6 +1141,7 @@ LIBC {
strtoll; strtoll;
strtoll_l; strtoll_l;
strtoq; strtoq;
strtotimeval; # arm x86 mips
strtoul; strtoul;
strtoull; strtoull;
strtoull_l; strtoull_l;
@ -1076,6 +1163,7 @@ LIBC {
sysinfo; sysinfo;
syslog; syslog;
system; system;
sysv_signal; # arm x86 mips
tcdrain; tcdrain;
tcflow; tcflow;
tcflush; tcflush;
@ -1107,6 +1195,7 @@ LIBC {
timerfd_settime; timerfd_settime;
times; times;
timezone; timezone;
tkill; # arm x86 mips
tmpfile; tmpfile;
tmpnam; tmpnam;
toascii; toascii;
@ -1148,6 +1237,7 @@ LIBC {
vdprintf; vdprintf;
verr; verr;
verrx; verrx;
vfdprintf; # arm x86 mips
vfork; vfork;
vfprintf; vfprintf;
vfscanf; vfscanf;
@ -1167,6 +1257,7 @@ LIBC {
vwprintf; vwprintf;
vwscanf; vwscanf;
wait; wait;
wait3; # arm x86 mips
wait4; wait4;
waitid; waitid;
waitpid; waitpid;
@ -1215,6 +1306,7 @@ LIBC {
wcstoull; wcstoull;
wcstoull_l; wcstoull_l;
wcstoumax; wcstoumax;
wcswcs; # arm x86 mips
wcswidth; wcswidth;
wcsxfrm; wcsxfrm;
wcsxfrm_l; wcsxfrm_l;
@ -1239,46 +1331,17 @@ LIBC {
LIBC_N { LIBC_N {
global: global:
__aeabi_atexit; # arm
__aeabi_memclr; # arm
__aeabi_memclr4; # arm
__aeabi_memclr8; # arm
__aeabi_memcpy; # arm
__aeabi_memcpy4; # arm
__aeabi_memcpy8; # arm
__aeabi_memmove; # arm
__aeabi_memmove4; # arm
__aeabi_memmove8; # arm
__aeabi_memset; # arm
__aeabi_memset4; # arm
__aeabi_memset8; # arm
__fread_chk; __fread_chk;
__fwrite_chk; __fwrite_chk;
__getcwd_chk; __getcwd_chk;
__gnu_Unwind_Find_exidx; # arm
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
prlimit; # arm mips x86 prlimit; # arm mips x86
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1362,33 +1425,8 @@ LIBC_PRIVATE {
__ashrdi3; # arm __ashrdi3; # arm
__bionic_brk; # arm x86 mips __bionic_brk; # arm x86 mips
__bionic_libgcc_compat_symbols; # arm x86 __bionic_libgcc_compat_symbols; # arm x86
__cmpdf2; # arm __bionic_libgcc_unwind_symbols; # arm
__divdf3; # arm
__divdi3; # arm x86 mips
__divsf3; # arm
__divsi3; # arm
__dso_handle; # arm __dso_handle; # arm
__eqdf2; # arm
__extendsfdf2; # arm
__fixdfsi; # arm
__fixsfsi; # arm
__fixunssfsi; # arm
__floatdidf; # arm
__floatdisf; # arm
__floatsidf; # arm
__floatsisf; # arm
__floatundidf; # arm
__floatundisf; # arm
__floatunsidf; # arm
__floatunsisf; # arm
__futex_wait; # arm x86 mips nobrillo
__futex_wake; # arm x86 mips nobrillo
__gedf2; # arm
__get_thread; # arm x86 mips nobrillo
__get_tls; # arm x86 mips nobrillo
__getdents64; # arm x86 mips
__gnu_ldivmod_helper; # arm
__gnu_uldivmod_helper; # arm
__gnu_Unwind_Backtrace; # arm __gnu_Unwind_Backtrace; # arm
__gnu_unwind_execute; # arm __gnu_unwind_execute; # arm
__gnu_Unwind_Find_exidx; # arm __gnu_Unwind_Find_exidx; # arm
@ -1407,62 +1445,6 @@ LIBC_PRIVATE {
__gnu_Unwind_Save_VFP_D_16_to_31; # arm __gnu_Unwind_Save_VFP_D_16_to_31; # arm
__gnu_Unwind_Save_WMMXC; # arm __gnu_Unwind_Save_WMMXC; # arm
__gnu_Unwind_Save_WMMXD; # arm __gnu_Unwind_Save_WMMXD; # arm
__gtdf2; # arm
__ledf2; # arm
__lshrdi3; # arm
__ltdf2; # arm
__muldf3; # arm
__muldi3; # arm
__mulsf3; # arm
__nedf2; # arm
__open; # arm x86 mips nobrillo
__page_shift; # arm x86 mips nobrillo
__page_size; # arm x86 mips nobrillo
__popcount_tab; # arm
__popcountsi2; # arm x86 mips
__pthread_gettid; # arm x86 mips nobrillo
__restore_core_regs; # arm
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips nobrillo
__set_errno; # arm x86 mips nobrillo
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sinit; # arm x86 mips nobrillo
__smakebuf; # arm x86 mips
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__subdf3; # arm
__subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__system_properties_init; # arm64 x86_64 mips64
__system_property_add; # arm64 x86_64 mips64
__system_property_area__; # arm64 x86_64 mips64
__system_property_area_init; # arm64 x86_64 mips64
__system_property_area_serial; # arm64 x86_64 mips64
__system_property_find; # arm64 x86_64 mips64
__system_property_find_nth; # arm64 x86_64 mips64
__system_property_foreach; # arm64 x86_64 mips64
__system_property_get; # arm64 x86_64 mips64
__system_property_read; # arm64 x86_64 mips64
__system_property_serial; # arm64 x86_64 mips64
__system_property_set; # arm64 x86_64 mips64
__system_property_set_filename; # arm64 x86_64 mips64
__system_property_update; # arm64 x86_64 mips64
__system_property_wait_any; # arm64 x86_64 mips64
__truncdfsf2; # arm
__udivdi3; # arm mips
__udivsi3; # arm
__umoddi3; # x86 mips
__unorddf2; # arm
__unordsf2; # arm
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
_Unwind_Backtrace; # arm _Unwind_Backtrace; # arm
_Unwind_Complete; # arm _Unwind_Complete; # arm
_Unwind_DeleteException; # arm _Unwind_DeleteException; # arm
@ -1478,40 +1460,14 @@ LIBC_PRIVATE {
_Unwind_VRS_Get; # arm _Unwind_VRS_Get; # arm
_Unwind_VRS_Pop; # arm _Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm _Unwind_VRS_Set; # arm
arc4random_addrandom; # arm x86 mips nobrillo
arc4random_stir; # arm x86 mips nobrillo
atexit; # arm atexit; # arm
bcopy; # arm x86 mips nobrillo dlmalloc; # arm x86 mips
bzero; # arm x86 mips nobrillo dlmalloc_inspect_all;
bsd_signal; # arm x86 mips nobrillo dlmalloc_trim;
dlmalloc; # arm x86 mips nobrillo dlmalloc_usable_size; # arm x86 mips
dlmalloc_inspect_all; # arm x86 mips nobrillo
dlmalloc_trim; # arm x86 mips nobrillo
dlmalloc_usable_size; # arm x86 mips nobrillo
endpwent; # arm x86 mips nobrillo
fdprintf; # arm x86 mips nobrillo
free_malloc_leak_info;
ftime; # arm x86 mips nobrillo
get_malloc_leak_info;
getdents; # arm x86 mips nobrillo
getdtablesize; # arm x86 mips nobrillo
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
index; # arm x86 mips nobrillo
issetugid; # arm x86 mips nobrillo
memswap; # arm x86 mips nobrillo
pthread_attr_getstackaddr; # arm x86 mips nobrillo
pthread_attr_setstackaddr; # arm x86 mips nobrillo
restore_core_regs; # arm
SHA1Final; # arm x86 mips SHA1Final; # arm x86 mips
SHA1Init; # arm x86 mips SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips SHA1Update; # arm x86 mips
strntoimax; # arm x86 mips nobrillo
strntoumax; # arm x86 mips nobrillo
strtotimeval; # arm x86 mips nobrillo
sysv_signal; # arm x86 mips nobrillo
tkill; # arm x86 mips nobrillo
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
} LIBC_N; } LIBC_N;

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ LIBC {
__cxa_atexit; __cxa_atexit;
__cxa_finalize; __cxa_finalize;
__cxa_thread_atexit_impl; __cxa_thread_atexit_impl;
__divdi3; # arm x86 mips
__dn_comp; __dn_comp;
__dn_count_labels; __dn_count_labels;
__dn_skipname; __dn_skipname;
@ -37,10 +38,15 @@ LIBC {
__freadable; __freadable;
__fsetlocking; __fsetlocking;
__fstatfs64; # arm x86 mips __fstatfs64; # arm x86 mips
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable; __fwritable;
__get_h_errno; __get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
__getcpu; # arm x86 mips __getcpu; # arm x86 mips
__getcwd; # arm x86 mips __getcwd; # arm x86 mips
__getdents64; # arm x86 mips
__getpid; # arm x86 mips __getpid; # arm x86 mips
__getpriority; # arm x86 mips __getpriority; # arm x86 mips
__gnu_basename; __gnu_basename;
@ -95,6 +101,7 @@ LIBC {
__ns_skiprr; # arm x86 mips __ns_skiprr; # arm x86 mips
__ns_sprintrr; # arm x86 mips __ns_sprintrr; # arm x86 mips
__ns_sprintrrf; # arm x86 mips __ns_sprintrrf; # arm x86 mips
__open; # arm x86 mips
__open_2; __open_2;
__openat; # arm x86 mips __openat; # arm x86 mips
__openat_2; __openat_2;
@ -111,7 +118,10 @@ LIBC {
__p_time; __p_time;
__p_type; __p_type;
__p_type_syms; __p_type_syms;
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk; __poll_chk;
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips __ppoll; # arm x86 mips
__ppoll_chk; __ppoll_chk;
__pread64_chk; __pread64_chk;
@ -120,7 +130,7 @@ LIBC {
__pselect6; # arm x86 mips __pselect6; # arm x86 mips
__pthread_cleanup_pop; __pthread_cleanup_pop;
__pthread_cleanup_push; __pthread_cleanup_push;
__pthread_gettid; # arm x86 mips nobrillo __pthread_gettid; # arm x86 mips
__ptrace; # arm x86 mips __ptrace; # arm x86 mips
__putlong; __putlong;
__putshort; __putshort;
@ -159,14 +169,27 @@ LIBC {
__sched_cpucount; __sched_cpucount;
__sched_cpufree; __sched_cpufree;
__sched_getaffinity; # arm x86 mips __sched_getaffinity; # arm x86 mips
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
__set_tid_address; # arm x86 mips __set_tid_address; # arm x86 mips
__set_tls; # arm mips __set_tls; # arm mips
__sF; __sF;
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sigaction; # arm x86 mips __sigaction; # arm x86 mips
__signalfd4; # arm x86 mips __signalfd4; # arm x86 mips
__sinit; # arm x86 mips
__smakebuf; # arm x86 mips
__snprintf_chk; __snprintf_chk;
__socket; # arm x86 mips __socket; # arm x86 mips
__sprintf_chk; __sprintf_chk;
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__stack_chk_fail; __stack_chk_fail;
__stack_chk_guard; __stack_chk_guard;
__statfs64; # arm x86 mips __statfs64; # arm x86 mips
@ -183,38 +206,45 @@ LIBC {
__strncpy_chk; __strncpy_chk;
__strncpy_chk2; __strncpy_chk2;
__strrchr_chk; __strrchr_chk;
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init; # arm x86 mips __system_properties_init;
__system_property_add; # arm x86 mips __system_property_add;
__system_property_area__; # arm x86 mips __system_property_area__;
__system_property_area_init; # arm x86 mips __system_property_area_init;
__system_property_area_serial; # arm x86 mips __system_property_area_serial;
__system_property_find; # arm x86 mips __system_property_find;
__system_property_find_nth; # arm x86 mips __system_property_find_nth;
__system_property_foreach; # arm x86 mips __system_property_foreach;
__system_property_get; # arm x86 mips __system_property_get;
__system_property_read; # arm x86 mips __system_property_read;
__system_property_serial; # arm x86 mips __system_property_serial;
__system_property_set; # arm x86 mips __system_property_set;
__system_property_set_filename; # arm x86 mips __system_property_set_filename;
__system_property_update; # arm x86 mips __system_property_update;
__system_property_wait_any; # arm x86 mips __system_property_wait_any;
__timer_create; # arm x86 mips __timer_create; # arm x86 mips
__timer_delete; # arm x86 mips __timer_delete; # arm x86 mips
__timer_getoverrun; # arm x86 mips __timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips __timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips __timer_settime; # arm x86 mips
__udivdi3; # arm x86 mips
__umask_chk; __umask_chk;
__umoddi3; # x86 mips
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
__wait4; # arm x86 mips
__waitid; # arm x86 mips __waitid; # arm x86 mips
_ctype_; _ctype_;
_Exit; _Exit;
_exit; _exit;
_flush_cache; # mips _flush_cache; # mips
_flushlbf; _flushlbf;
_fwalk; # arm x86 mips
_getlong; _getlong;
_getshort; _getshort;
_longjmp; _longjmp;
@ -241,7 +271,9 @@ LIBC {
android_gethostbynamefornet; android_gethostbynamefornet;
android_set_abort_message; android_set_abort_message;
arc4random; arc4random;
arc4random_addrandom; # arm x86 mips
arc4random_buf; arc4random_buf;
arc4random_stir; # arm x86 mips
arc4random_uniform; arc4random_uniform;
asctime; asctime;
asctime64; # arm x86 mips asctime64; # arm x86 mips
@ -255,11 +287,14 @@ LIBC {
atoll; atoll;
basename; basename;
basename_r; # arm x86 mips basename_r; # arm x86 mips
bcopy; # arm x86 mips
bind; bind;
bindresvport; bindresvport;
brk; brk;
bsd_signal; # arm x86 mips
bsearch; bsearch;
btowc; btowc;
bzero; # arm x86 mips
c16rtomb; c16rtomb;
c32rtomb; c32rtomb;
cacheflush; # arm mips cacheflush; # arm mips
@ -312,6 +347,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -358,6 +394,7 @@ LIBC {
fdatasync; fdatasync;
fdopen; fdopen;
fdopendir; fdopendir;
fdprintf; # arm x86 mips
feof; feof;
feof_unlocked; feof_unlocked;
ferror; ferror;
@ -389,6 +426,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -409,6 +447,7 @@ LIBC {
fsync; fsync;
ftell; ftell;
ftello; ftello;
ftime; # arm x86 mips
ftok; ftok;
ftruncate; ftruncate;
ftruncate64; ftruncate64;
@ -429,6 +468,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -440,6 +480,8 @@ LIBC {
getchar_unlocked; getchar_unlocked;
getcwd; getcwd;
getdelim; getdelim;
getdents; # arm x86 mips
getdtablesize; # arm x86 mips
getegid; getegid;
getenv; getenv;
geteuid; geteuid;
@ -514,6 +556,7 @@ LIBC {
if_nametoindex; if_nametoindex;
imaxabs; imaxabs;
imaxdiv; imaxdiv;
index; # arm x86 mips
inet_addr; inet_addr;
inet_aton; inet_aton;
inet_lnaof; inet_lnaof;
@ -566,6 +609,7 @@ LIBC {
isprint_l; isprint_l;
ispunct; ispunct;
ispunct_l; ispunct_l;
issetugid; # arm x86 mips
isspace; isspace;
isspace_l; isspace_l;
isupper; isupper;
@ -655,6 +699,7 @@ LIBC {
mempcpy; mempcpy;
memrchr; memrchr;
memset; memset;
memswap; # arm x86 mips
mincore; mincore;
mkdir; mkdir;
mkdirat; mkdirat;
@ -674,6 +719,7 @@ LIBC {
mktemp; mktemp;
mktime; mktime;
mktime64; # arm x86 mips mktime64; # arm x86 mips
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -744,6 +790,7 @@ LIBC {
pthread_attr_getschedpolicy; pthread_attr_getschedpolicy;
pthread_attr_getscope; pthread_attr_getscope;
pthread_attr_getstack; pthread_attr_getstack;
pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize; pthread_attr_getstacksize;
pthread_attr_init; pthread_attr_init;
pthread_attr_setdetachstate; pthread_attr_setdetachstate;
@ -752,6 +799,7 @@ LIBC {
pthread_attr_setschedpolicy; pthread_attr_setschedpolicy;
pthread_attr_setscope; pthread_attr_setscope;
pthread_attr_setstack; pthread_attr_setstack;
pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize; pthread_attr_setstacksize;
pthread_cond_broadcast; pthread_cond_broadcast;
pthread_cond_destroy; pthread_cond_destroy;
@ -1009,6 +1057,8 @@ LIBC {
strncpy; strncpy;
strndup; strndup;
strnlen; strnlen;
strntoimax; # arm x86 mips
strntoumax; # arm x86 mips
strpbrk; strpbrk;
strptime; strptime;
strrchr; strrchr;
@ -1027,6 +1077,7 @@ LIBC {
strtoll; strtoll;
strtoll_l; strtoll_l;
strtoq; strtoq;
strtotimeval; # arm x86 mips
strtoul; strtoul;
strtoull; strtoull;
strtoull_l; strtoull_l;
@ -1048,6 +1099,7 @@ LIBC {
sysinfo; sysinfo;
syslog; syslog;
system; system;
sysv_signal; # arm x86 mips
tcdrain; tcdrain;
tcflow; tcflow;
tcflush; tcflush;
@ -1079,6 +1131,7 @@ LIBC {
timerfd_settime; timerfd_settime;
times; times;
timezone; timezone;
tkill; # arm x86 mips
tmpfile; tmpfile;
tmpnam; tmpnam;
toascii; toascii;
@ -1120,6 +1173,7 @@ LIBC {
vdprintf; vdprintf;
verr; verr;
verrx; verrx;
vfdprintf; # arm x86 mips
vfork; vfork;
vfprintf; vfprintf;
vfscanf; vfscanf;
@ -1139,6 +1193,7 @@ LIBC {
vwprintf; vwprintf;
vwscanf; vwscanf;
wait; wait;
wait3; # arm x86 mips
wait4; wait4;
waitid; waitid;
waitpid; waitpid;
@ -1187,6 +1242,7 @@ LIBC {
wcstoull; wcstoull;
wcstoull_l; wcstoull_l;
wcstoumax; wcstoumax;
wcswcs; # arm x86 mips
wcswidth; wcswidth;
wcsxfrm; wcsxfrm;
wcsxfrm_l; wcsxfrm_l;
@ -1217,26 +1273,11 @@ LIBC_N {
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
prlimit; # arm mips x86 prlimit; # arm mips x86
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1248,69 +1289,13 @@ LIBC_PRIVATE {
global: global:
__accept4; # arm x86 mips __accept4; # arm x86 mips
__bionic_brk; # arm x86 mips __bionic_brk; # arm x86 mips
__divdi3; # arm x86 mips dlmalloc; # arm x86 mips
__futex_wait; # arm x86 mips nobrillo dlmalloc_inspect_all;
__futex_wake; # arm x86 mips nobrillo dlmalloc_trim;
__get_thread; # arm x86 mips nobrillo dlmalloc_usable_size; # arm x86 mips
__get_tls; # arm x86 mips nobrillo
__getdents64; # arm x86 mips
__open; # arm x86 mips nobrillo
__page_shift; # arm x86 mips nobrillo
__page_size; # arm x86 mips nobrillo
__popcountsi2; # arm x86 mips
__pthread_gettid; # arm x86 mips nobrillo
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips nobrillo
__set_errno; # arm x86 mips nobrillo
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sinit; # arm x86 mips nobrillo
__smakebuf; # arm x86 mips
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__udivdi3; # arm mips
__umoddi3; # x86 mips
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
arc4random_addrandom; # arm x86 mips nobrillo
arc4random_stir; # arm x86 mips nobrillo
bcopy; # arm x86 mips nobrillo
bzero; # arm x86 mips nobrillo
bsd_signal; # arm x86 mips nobrillo
dlmalloc; # arm x86 mips nobrillo
dlmalloc_inspect_all; # arm x86 mips nobrillo
dlmalloc_trim; # arm x86 mips nobrillo
dlmalloc_usable_size; # arm x86 mips nobrillo
endpwent; # arm x86 mips nobrillo
fdprintf; # arm x86 mips nobrillo
free_malloc_leak_info;
ftime; # arm x86 mips nobrillo
get_malloc_leak_info;
getdents; # arm x86 mips nobrillo
getdtablesize; # arm x86 mips nobrillo
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
index; # arm x86 mips nobrillo
issetugid; # arm x86 mips nobrillo
memswap; # arm x86 mips nobrillo
pthread_attr_getstackaddr; # arm x86 mips nobrillo
pthread_attr_setstackaddr; # arm x86 mips nobrillo
SHA1Final; # arm x86 mips SHA1Final; # arm x86 mips
SHA1Init; # arm x86 mips SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips SHA1Update; # arm x86 mips
strntoimax; # arm x86 mips nobrillo
strntoumax; # arm x86 mips nobrillo
strtotimeval; # arm x86 mips nobrillo
sysv_signal; # arm x86 mips nobrillo
tkill; # arm x86 mips nobrillo
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
} LIBC_N; } LIBC_N;

View File

@ -131,6 +131,21 @@ LIBC {
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init;
__system_property_add;
__system_property_area__;
__system_property_area_init;
__system_property_area_serial;
__system_property_find;
__system_property_find_nth;
__system_property_foreach;
__system_property_get;
__system_property_read;
__system_property_serial;
__system_property_set;
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
__umask_chk; __umask_chk;
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
@ -226,6 +241,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -301,6 +317,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -341,6 +358,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -581,6 +599,7 @@ LIBC {
mkstemps64; mkstemps64;
mktemp; mktemp;
mktime; mktime;
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -1137,25 +1156,10 @@ LIBC_N {
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1165,22 +1169,7 @@ LIBC_N {
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
__system_properties_init; # arm64 x86_64 mips64 dlmalloc_inspect_all;
__system_property_add; # arm64 x86_64 mips64 dlmalloc_trim;
__system_property_area__; # arm64 x86_64 mips64
__system_property_area_init; # arm64 x86_64 mips64
__system_property_area_serial; # arm64 x86_64 mips64
__system_property_find; # arm64 x86_64 mips64
__system_property_find_nth; # arm64 x86_64 mips64
__system_property_foreach; # arm64 x86_64 mips64
__system_property_get; # arm64 x86_64 mips64
__system_property_read; # arm64 x86_64 mips64
__system_property_serial; # arm64 x86_64 mips64
__system_property_set; # arm64 x86_64 mips64
__system_property_set_filename; # arm64 x86_64 mips64
__system_property_update; # arm64 x86_64 mips64
__system_property_wait_any; # arm64 x86_64 mips64
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
} LIBC_N; } LIBC_N;

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ LIBC {
__cxa_atexit; __cxa_atexit;
__cxa_finalize; __cxa_finalize;
__cxa_thread_atexit_impl; __cxa_thread_atexit_impl;
__divdi3; # arm x86 mips
__dn_comp; __dn_comp;
__dn_count_labels; __dn_count_labels;
__dn_skipname; __dn_skipname;
@ -37,10 +38,15 @@ LIBC {
__freadable; __freadable;
__fsetlocking; __fsetlocking;
__fstatfs64; # arm x86 mips __fstatfs64; # arm x86 mips
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable; __fwritable;
__get_h_errno; __get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
__getcpu; # arm x86 mips __getcpu; # arm x86 mips
__getcwd; # arm x86 mips __getcwd; # arm x86 mips
__getdents64; # arm x86 mips
__getpid; # arm x86 mips __getpid; # arm x86 mips
__getpriority; # arm x86 mips __getpriority; # arm x86 mips
__gnu_basename; __gnu_basename;
@ -95,6 +101,7 @@ LIBC {
__ns_skiprr; # arm x86 mips __ns_skiprr; # arm x86 mips
__ns_sprintrr; # arm x86 mips __ns_sprintrr; # arm x86 mips
__ns_sprintrrf; # arm x86 mips __ns_sprintrrf; # arm x86 mips
__open; # arm x86 mips
__open_2; __open_2;
__openat; # arm x86 mips __openat; # arm x86 mips
__openat_2; __openat_2;
@ -111,7 +118,10 @@ LIBC {
__p_time; __p_time;
__p_type; __p_type;
__p_type_syms; __p_type_syms;
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk; __poll_chk;
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips __ppoll; # arm x86 mips
__ppoll_chk; __ppoll_chk;
__pread64_chk; __pread64_chk;
@ -120,7 +130,7 @@ LIBC {
__pselect6; # arm x86 mips __pselect6; # arm x86 mips
__pthread_cleanup_pop; __pthread_cleanup_pop;
__pthread_cleanup_push; __pthread_cleanup_push;
__pthread_gettid; # arm x86 mips nobrillo __pthread_gettid; # arm x86 mips
__ptrace; # arm x86 mips __ptrace; # arm x86 mips
__putlong; __putlong;
__putshort; __putshort;
@ -159,14 +169,27 @@ LIBC {
__sched_cpucount; __sched_cpucount;
__sched_cpufree; __sched_cpufree;
__sched_getaffinity; # arm x86 mips __sched_getaffinity; # arm x86 mips
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
__set_thread_area; # x86 __set_thread_area; # x86
__set_tid_address; # arm x86 mips __set_tid_address; # arm x86 mips
__sF; __sF;
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sigaction; # arm x86 mips __sigaction; # arm x86 mips
__signalfd4; # arm x86 mips __signalfd4; # arm x86 mips
__sinit; # arm x86 mips
__smakebuf; # arm x86 mips
__snprintf_chk; __snprintf_chk;
__socket; # arm x86 mips __socket; # arm x86 mips
__sprintf_chk; __sprintf_chk;
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__stack_chk_fail; __stack_chk_fail;
__stack_chk_guard; __stack_chk_guard;
__statfs64; # arm x86 mips __statfs64; # arm x86 mips
@ -183,38 +206,44 @@ LIBC {
__strncpy_chk; __strncpy_chk;
__strncpy_chk2; __strncpy_chk2;
__strrchr_chk; __strrchr_chk;
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init; # arm x86 mips __system_properties_init;
__system_property_add; # arm x86 mips __system_property_add;
__system_property_area__; # arm x86 mips __system_property_area__;
__system_property_area_init; # arm x86 mips __system_property_area_init;
__system_property_area_serial; # arm x86 mips __system_property_area_serial;
__system_property_find; # arm x86 mips __system_property_find;
__system_property_find_nth; # arm x86 mips __system_property_find_nth;
__system_property_foreach; # arm x86 mips __system_property_foreach;
__system_property_get; # arm x86 mips __system_property_get;
__system_property_read; # arm x86 mips __system_property_read;
__system_property_serial; # arm x86 mips __system_property_serial;
__system_property_set; # arm x86 mips __system_property_set;
__system_property_set_filename; # arm x86 mips __system_property_set_filename;
__system_property_update; # arm x86 mips __system_property_update;
__system_property_wait_any; # arm x86 mips __system_property_wait_any;
__timer_create; # arm x86 mips __timer_create; # arm x86 mips
__timer_delete; # arm x86 mips __timer_delete; # arm x86 mips
__timer_getoverrun; # arm x86 mips __timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips __timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips __timer_settime; # arm x86 mips
__udivdi3; # x86 __udivdi3; # arm x86 mips
__umask_chk; __umask_chk;
__umoddi3; # x86 mips
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
__wait4; # arm x86 mips
__waitid; # arm x86 mips __waitid; # arm x86 mips
_ctype_; _ctype_;
_Exit; _Exit;
_exit; _exit;
_flushlbf; _flushlbf;
_fwalk; # arm x86 mips
_getlong; _getlong;
_getshort; _getshort;
_longjmp; _longjmp;
@ -241,7 +270,9 @@ LIBC {
android_gethostbynamefornet; android_gethostbynamefornet;
android_set_abort_message; android_set_abort_message;
arc4random; arc4random;
arc4random_addrandom; # arm x86 mips
arc4random_buf; arc4random_buf;
arc4random_stir; # arm x86 mips
arc4random_uniform; arc4random_uniform;
asctime; asctime;
asctime64; # arm x86 mips asctime64; # arm x86 mips
@ -255,11 +286,14 @@ LIBC {
atoll; atoll;
basename; basename;
basename_r; # arm x86 mips basename_r; # arm x86 mips
bcopy; # arm x86 mips
bind; bind;
bindresvport; bindresvport;
brk; brk;
bsd_signal; # arm x86 mips
bsearch; bsearch;
btowc; btowc;
bzero; # arm x86 mips
c16rtomb; c16rtomb;
c32rtomb; c32rtomb;
calloc; calloc;
@ -311,6 +345,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -357,6 +392,7 @@ LIBC {
fdatasync; fdatasync;
fdopen; fdopen;
fdopendir; fdopendir;
fdprintf; # arm x86 mips
feof; feof;
feof_unlocked; feof_unlocked;
ferror; ferror;
@ -388,6 +424,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -408,6 +445,7 @@ LIBC {
fsync; fsync;
ftell; ftell;
ftello; ftello;
ftime; # arm x86 mips
ftok; ftok;
ftruncate; ftruncate;
ftruncate64; ftruncate64;
@ -428,6 +466,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -439,6 +478,8 @@ LIBC {
getchar_unlocked; getchar_unlocked;
getcwd; getcwd;
getdelim; getdelim;
getdents; # arm x86 mips
getdtablesize; # arm x86 mips
getegid; getegid;
getenv; getenv;
geteuid; geteuid;
@ -513,6 +554,7 @@ LIBC {
if_nametoindex; if_nametoindex;
imaxabs; imaxabs;
imaxdiv; imaxdiv;
index; # arm x86 mips
inet_addr; inet_addr;
inet_aton; inet_aton;
inet_lnaof; inet_lnaof;
@ -565,6 +607,7 @@ LIBC {
isprint_l; isprint_l;
ispunct; ispunct;
ispunct_l; ispunct_l;
issetugid; # arm x86 mips
isspace; isspace;
isspace_l; isspace_l;
isupper; isupper;
@ -654,6 +697,7 @@ LIBC {
mempcpy; mempcpy;
memrchr; memrchr;
memset; memset;
memswap; # arm x86 mips
mincore; mincore;
mkdir; mkdir;
mkdirat; mkdirat;
@ -673,6 +717,7 @@ LIBC {
mktemp; mktemp;
mktime; mktime;
mktime64; # arm x86 mips mktime64; # arm x86 mips
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -743,6 +788,7 @@ LIBC {
pthread_attr_getschedpolicy; pthread_attr_getschedpolicy;
pthread_attr_getscope; pthread_attr_getscope;
pthread_attr_getstack; pthread_attr_getstack;
pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize; pthread_attr_getstacksize;
pthread_attr_init; pthread_attr_init;
pthread_attr_setdetachstate; pthread_attr_setdetachstate;
@ -751,6 +797,7 @@ LIBC {
pthread_attr_setschedpolicy; pthread_attr_setschedpolicy;
pthread_attr_setscope; pthread_attr_setscope;
pthread_attr_setstack; pthread_attr_setstack;
pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize; pthread_attr_setstacksize;
pthread_cond_broadcast; pthread_cond_broadcast;
pthread_cond_destroy; pthread_cond_destroy;
@ -1008,6 +1055,8 @@ LIBC {
strncpy; strncpy;
strndup; strndup;
strnlen; strnlen;
strntoimax; # arm x86 mips
strntoumax; # arm x86 mips
strpbrk; strpbrk;
strptime; strptime;
strrchr; strrchr;
@ -1026,6 +1075,7 @@ LIBC {
strtoll; strtoll;
strtoll_l; strtoll_l;
strtoq; strtoq;
strtotimeval; # arm x86 mips
strtoul; strtoul;
strtoull; strtoull;
strtoull_l; strtoull_l;
@ -1047,6 +1097,7 @@ LIBC {
sysinfo; sysinfo;
syslog; syslog;
system; system;
sysv_signal; # arm x86 mips
tcdrain; tcdrain;
tcflow; tcflow;
tcflush; tcflush;
@ -1078,6 +1129,7 @@ LIBC {
timerfd_settime; timerfd_settime;
times; times;
timezone; timezone;
tkill; # arm x86 mips
tmpfile; tmpfile;
tmpnam; tmpnam;
toascii; toascii;
@ -1119,6 +1171,7 @@ LIBC {
vdprintf; vdprintf;
verr; verr;
verrx; verrx;
vfdprintf; # arm x86 mips
vfork; vfork;
vfprintf; vfprintf;
vfscanf; vfscanf;
@ -1138,6 +1191,7 @@ LIBC {
vwprintf; vwprintf;
vwscanf; vwscanf;
wait; wait;
wait3; # arm x86 mips
wait4; wait4;
waitid; waitid;
waitpid; waitpid;
@ -1186,6 +1240,7 @@ LIBC {
wcstoull; wcstoull;
wcstoull_l; wcstoull_l;
wcstoumax; wcstoumax;
wcswcs; # arm x86 mips
wcswidth; wcswidth;
wcsxfrm; wcsxfrm;
wcsxfrm_l; wcsxfrm_l;
@ -1216,26 +1271,11 @@ LIBC_N {
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
prlimit; # arm mips x86 prlimit; # arm mips x86
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1248,68 +1288,13 @@ LIBC_PRIVATE {
__accept4; # arm x86 mips __accept4; # arm x86 mips
__bionic_brk; # arm x86 mips __bionic_brk; # arm x86 mips
__bionic_libgcc_compat_symbols; # arm x86 __bionic_libgcc_compat_symbols; # arm x86
__divdi3; # arm x86 mips dlmalloc; # arm x86 mips
__futex_wait; # arm x86 mips nobrillo dlmalloc_inspect_all;
__futex_wake; # arm x86 mips nobrillo dlmalloc_trim;
__get_thread; # arm x86 mips nobrillo dlmalloc_usable_size; # arm x86 mips
__get_tls; # arm x86 mips nobrillo
__getdents64; # arm x86 mips
__open; # arm x86 mips nobrillo
__page_shift; # arm x86 mips nobrillo
__page_size; # arm x86 mips nobrillo
__popcountsi2; # arm x86 mips
__pthread_gettid; # arm x86 mips nobrillo
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips nobrillo
__set_errno; # arm x86 mips nobrillo
__sflags; # arm x86 mips
__sflush; # arm x86 mips
__sfp; # arm x86 mips
__sglue; # arm x86 mips
__sinit; # arm x86 mips nobrillo
__smakebuf; # arm x86 mips
__sread; # arm x86 mips
__srefill; # arm x86 mips
__srget; # arm x86 mips
__sseek; # arm x86 mips
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
__umoddi3; # x86 mips
__wait4; # arm x86 mips nobrillo
_fwalk; # arm x86 mips
arc4random_addrandom; # arm x86 mips nobrillo
arc4random_stir; # arm x86 mips nobrillo
bcopy; # arm x86 mips nobrillo
bzero; # arm x86 mips nobrillo
bsd_signal; # arm x86 mips nobrillo
dlmalloc; # arm x86 mips nobrillo
dlmalloc_inspect_all; # arm x86 mips nobrillo
dlmalloc_trim; # arm x86 mips nobrillo
dlmalloc_usable_size; # arm x86 mips nobrillo
endpwent; # arm x86 mips nobrillo
fdprintf; # arm x86 mips nobrillo
free_malloc_leak_info;
ftime; # arm x86 mips nobrillo
get_malloc_leak_info;
getdents; # arm x86 mips nobrillo
getdtablesize; # arm x86 mips nobrillo
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
index; # arm x86 mips nobrillo
issetugid; # arm x86 mips nobrillo
memswap; # arm x86 mips nobrillo
pthread_attr_getstackaddr; # arm x86 mips nobrillo
pthread_attr_setstackaddr; # arm x86 mips nobrillo
SHA1Final; # arm x86 mips SHA1Final; # arm x86 mips
SHA1Init; # arm x86 mips SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips SHA1Update; # arm x86 mips
strntoimax; # arm x86 mips nobrillo
strntoumax; # arm x86 mips nobrillo
strtotimeval; # arm x86 mips nobrillo
sysv_signal; # arm x86 mips nobrillo
tkill; # arm x86 mips nobrillo
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
} LIBC_N; } LIBC_N;

View File

@ -131,6 +131,21 @@ LIBC {
__sym_ntop; __sym_ntop;
__sym_ntos; __sym_ntos;
__sym_ston; __sym_ston;
__system_properties_init;
__system_property_add;
__system_property_area__;
__system_property_area_init;
__system_property_area_serial;
__system_property_find;
__system_property_find_nth;
__system_property_foreach;
__system_property_get;
__system_property_read;
__system_property_serial;
__system_property_set;
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
__umask_chk; __umask_chk;
__vsnprintf_chk; __vsnprintf_chk;
__vsprintf_chk; __vsprintf_chk;
@ -226,6 +241,7 @@ LIBC {
dup3; dup3;
duplocale; duplocale;
endmntent; endmntent;
endpwent;
endservent; endservent;
endutent; endutent;
environ; environ;
@ -301,6 +317,7 @@ LIBC {
fputws; fputws;
fread; fread;
free; free;
free_malloc_leak_info;
freeaddrinfo; freeaddrinfo;
freelocale; freelocale;
fremovexattr; fremovexattr;
@ -341,6 +358,7 @@ LIBC {
fwscanf; fwscanf;
gai_strerror; gai_strerror;
get_avphys_pages; get_avphys_pages;
get_malloc_leak_info;
get_nprocs; get_nprocs;
get_nprocs_conf; get_nprocs_conf;
get_phys_pages; get_phys_pages;
@ -581,6 +599,7 @@ LIBC {
mkstemps64; mkstemps64;
mktemp; mktemp;
mktime; mktime;
mktime_tz;
mlock; mlock;
mlockall; mlockall;
mmap; mmap;
@ -1137,25 +1156,10 @@ LIBC_N {
__pwrite_chk; __pwrite_chk;
__pwrite64_chk; __pwrite64_chk;
__write_chk; __write_chk;
fileno_unlocked;
freeifaddrs;
getgrgid_r; getgrgid_r;
getgrnam_r; getgrnam_r;
getifaddrs;
preadv; preadv;
preadv64; preadv64;
pthread_barrierattr_destroy;
pthread_barrierattr_getpshared;
pthread_barrierattr_init;
pthread_barrierattr_setpshared;
pthread_barrier_destroy;
pthread_barrier_init;
pthread_barrier_wait;
pthread_spin_destroy;
pthread_spin_init;
pthread_spin_lock;
pthread_spin_trylock;
pthread_spin_unlock;
pwritev; pwritev;
pwritev64; pwritev64;
scandirat; scandirat;
@ -1165,22 +1169,7 @@ LIBC_N {
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
__system_properties_init; # arm64 x86_64 mips64 dlmalloc_inspect_all;
__system_property_add; # arm64 x86_64 mips64 dlmalloc_trim;
__system_property_area__; # arm64 x86_64 mips64
__system_property_area_init; # arm64 x86_64 mips64
__system_property_area_serial; # arm64 x86_64 mips64
__system_property_find; # arm64 x86_64 mips64
__system_property_find_nth; # arm64 x86_64 mips64
__system_property_foreach; # arm64 x86_64 mips64
__system_property_get; # arm64 x86_64 mips64
__system_property_read; # arm64 x86_64 mips64
__system_property_serial; # arm64 x86_64 mips64
__system_property_set; # arm64 x86_64 mips64
__system_property_set_filename; # arm64 x86_64 mips64
__system_property_update; # arm64 x86_64 mips64
__system_property_wait_any; # arm64 x86_64 mips64
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild; gMallocLeakZygoteChild;
} LIBC_N; } LIBC_N;

View File

@ -38,25 +38,32 @@ class KernelArgumentBlock {
argv = reinterpret_cast<char**>(args + 1); argv = reinterpret_cast<char**>(args + 1);
envp = argv + argc + 1; envp = argv + argc + 1;
// Skip over all environment variable definitions to find the aux vector. // Skip over all environment variable definitions to find aux vector.
// The end of the environment block is marked by a NULL pointer. // The end of the environment block is marked by two NULL pointers.
char** p = envp; char** p = envp;
while (*p != NULL) { while (*p != NULL) {
++p; ++p;
} }
++p; // Skip the NULL itself. ++p; // Skip second NULL;
auxv = reinterpret_cast<ElfW(auxv_t)*>(p); auxv = reinterpret_cast<ElfW(auxv_t)*>(p);
} }
// Similar to ::getauxval but doesn't require the libc global variables to be set up, // Similar to ::getauxval but doesn't require the libc global variables to be set up,
// so it's safe to call this really early on. // so it's safe to call this really early on. This function also lets you distinguish
unsigned long getauxval(unsigned long type) { // between the inability to find the given type and its value just happening to be 0.
unsigned long getauxval(unsigned long type, bool* found_match = NULL) {
for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) { for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
if (v->a_type == type) { if (v->a_type == type) {
if (found_match != NULL) {
*found_match = true;
}
return v->a_un.a_val; return v->a_un.a_val;
} }
} }
if (found_match != NULL) {
*found_match = false;
}
return 0; return 0;
} }

View File

@ -34,7 +34,7 @@ class ScopedPthreadMutexLocker {
private: private:
pthread_mutex_t* mu_; pthread_mutex_t* mu_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker); DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker);
}; };
#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H #endif // SCOPED_PTHREAD_MUTEX_LOCKER_H

View File

@ -40,12 +40,10 @@ __BEGIN_DECLS
struct timespec; struct timespec;
static inline __always_inline int __futex(volatile void* ftx, int op, int value, static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) {
const struct timespec* timeout,
int bitset) {
// Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to. // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
int saved_errno = errno; int saved_errno = errno;
int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset); int result = syscall(__NR_futex, ftx, op, value, timeout);
if (__predict_false(result == -1)) { if (__predict_false(result == -1)) {
result = -errno; result = -errno;
errno = saved_errno; errno = saved_errno;
@ -54,22 +52,19 @@ static inline __always_inline int __futex(volatile void* ftx, int op, int value,
} }
static inline int __futex_wake(volatile void* ftx, int count) { static inline int __futex_wake(volatile void* ftx, int count) {
return __futex(ftx, FUTEX_WAKE, count, NULL, 0); return __futex(ftx, FUTEX_WAKE, count, NULL);
} }
static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) { static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL, 0); return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL);
} }
static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) { static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
return __futex(ftx, FUTEX_WAIT, value, timeout, 0); return __futex(ftx, FUTEX_WAIT, value, timeout);
} }
static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) {
bool use_realtime_clock, const struct timespec* abs_timeout) { return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout);
return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE) |
(use_realtime_clock ? FUTEX_CLOCK_REALTIME : 0), value, abs_timeout,
FUTEX_BITSET_MATCH_ANY);
} }
__END_DECLS __END_DECLS

View File

@ -30,7 +30,6 @@
#include <stdatomic.h> #include <stdatomic.h>
#include "private/bionic_futex.h" #include "private/bionic_futex.h"
#include "private/bionic_macros.h"
// Lock is used in places like pthread_rwlock_t, which can be initialized without calling // Lock is used in places like pthread_rwlock_t, which can be initialized without calling
// an initialization function. So make sure Lock can be initialized by setting its memory to 0. // an initialization function. So make sure Lock can be initialized by setting its memory to 0.
@ -50,12 +49,6 @@ class Lock {
this->process_shared = process_shared; this->process_shared = process_shared;
} }
bool trylock() {
LockState old_state = Unlocked;
return __predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed));
}
void lock() { void lock() {
LockState old_state = Unlocked; LockState old_state = Unlocked;
if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state, if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
@ -64,7 +57,7 @@ class Lock {
} }
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) { 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. // 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, false, nullptr); __futex_wait_ex(&state, process_shared, LockedWithWaiter, NULL);
} }
return; return;
} }

View File

@ -42,8 +42,8 @@
(((value) + (alignment) - 1) & ~((alignment) - 1)) (((value) + (alignment) - 1) & ~((alignment) - 1))
#define BIONIC_ROUND_UP_POWER_OF_2(value) \ #define BIONIC_ROUND_UP_POWER_OF_2(value) \
((sizeof(value) == 8) \ (sizeof(value) == 8) \
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \ ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))) : (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))
#endif // _BIONIC_MACROS_H_ #endif // _BIONIC_MACROS_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 The Android Open Source Project * Copyright (C) 2011 The Android Open Source Project
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -25,35 +25,17 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#ifndef _BIONIC_TIME_H
#define _BIONIC_TIME_H
#ifndef _IFADDRS_H_ #include <time.h>
#define _IFADDRS_H_
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <netinet/in.h>
#include <sys/socket.h>
__BEGIN_DECLS __BEGIN_DECLS
struct ifaddrs { // We can't remove this (and this file) until we fix MtpUtils.cpp.
struct ifaddrs* ifa_next; time_t mktime_tz(struct tm* const, char const*);
char* ifa_name;
unsigned int ifa_flags;
struct sockaddr* ifa_addr;
struct sockaddr* ifa_netmask;
union {
struct sockaddr* ifu_broadaddr;
struct sockaddr* ifu_dstaddr;
} ifa_ifu;
void* ifa_data;
};
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void freeifaddrs(struct ifaddrs*);
int getifaddrs(struct ifaddrs**);
__END_DECLS __END_DECLS
#endif #endif /* _BIONIC_TIME_H */

View File

@ -29,12 +29,9 @@
#ifndef _BIONIC_TIME_CONVERSIONS_H #ifndef _BIONIC_TIME_CONVERSIONS_H
#define _BIONIC_TIME_CONVERSIONS_H #define _BIONIC_TIME_CONVERSIONS_H
#include <errno.h>
#include <time.h> #include <time.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "private/bionic_constants.h"
__BEGIN_DECLS __BEGIN_DECLS
__LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv); __LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv);
@ -42,24 +39,8 @@ __LIBC_HIDDEN__ void timespec_from_ms(timespec& ts, const int ms);
__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts); __LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
__LIBC_HIDDEN__ void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, __LIBC_HIDDEN__ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock);
clockid_t clock);
__END_DECLS __END_DECLS
static inline int check_timespec(const timespec* ts, bool null_allowed) {
if (null_allowed && ts == nullptr) {
return 0;
}
// glibc just segfaults if you pass a null timespec.
// That seems a lot more likely to catch bad code than returning EINVAL.
if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) {
return EINVAL;
}
if (ts->tv_sec < 0) {
return ETIMEDOUT;
}
return 0;
}
#endif #endif

View File

@ -121,7 +121,7 @@ __END_DECLS
#if defined(__cplusplus) #if defined(__cplusplus)
class KernelArgumentBlock; class KernelArgumentBlock;
extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock&); extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
#endif #endif
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */ #endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */

View File

@ -44,44 +44,37 @@
#define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGNBYTES (sizeof(uintptr_t) - 1)
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
int __sdidinit;
#define NDYNAMIC 10 /* add ten more whenever necessary */ #define NDYNAMIC 10 /* add ten more whenever necessary */
#define std(flags, file) \ #define std(flags, file) \
{0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \ {0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
{(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0,0},0,0} {(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0,0},0,0}
/* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
static struct __sfileext usualext[FOPEN_MAX - 3];
static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
static struct glue *lastglue = &uglue;
_THREAD_PRIVATE_MUTEX(__sfp_mutex); _THREAD_PRIVATE_MUTEX(__sfp_mutex);
// TODO: when we no longer have to support both clang and GCC, we can simplify all this. static struct __sfileext __sFext[3];
#define SBUF_INIT {0,0}
#if defined(__LP64__)
#define MBSTATE_T_INIT {{0},{0}}
#else
#define MBSTATE_T_INIT {{0}}
#endif
#define WCHAR_IO_DATA_INIT {MBSTATE_T_INIT,MBSTATE_T_INIT,{0},0,0}
static struct __sfileext __sFext[3] = {
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
};
// __sF is exported for backwards compatibility. Until M, we didn't have symbols // __sF is exported for backwards compatibility. Until M, we didn't have symbols
// for stdin/stdout/stderr; they were macros accessing __sF. // for stdin/stdout/stderr; they were macros accessing __sF.
FILE __sF[3] = { FILE __sF[3] = {
std(__SRD, STDIN_FILENO), std(__SRD, STDIN_FILENO), /* stdin */
std(__SWR, STDOUT_FILENO), std(__SWR, STDOUT_FILENO), /* stdout */
std(__SWR|__SNBF, STDERR_FILENO), std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
}; };
struct glue __sglue = { &uglue, 3, __sF };
FILE* stdin = &__sF[0]; FILE* stdin = &__sF[0];
FILE* stdout = &__sF[1]; FILE* stdout = &__sF[1];
FILE* stderr = &__sF[2]; FILE* stderr = &__sF[2];
struct glue __sglue = { NULL, 3, __sF };
static struct glue* lastglue = &__sglue;
static struct glue * static struct glue *
moreglue(int n) moreglue(int n)
{ {
@ -121,6 +114,9 @@ __sfp(void)
int n; int n;
struct glue *g; struct glue *g;
if (!__sdidinit)
__sinit();
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
for (g = &__sglue; g != NULL; g = g->next) { for (g = &__sglue; g != NULL; g = g->next) {
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
@ -153,7 +149,48 @@ found:
return (fp); return (fp);
} }
__LIBC_HIDDEN__ void __libc_stdio_cleanup(void) { /*
* exit() and abort() call _cleanup() through the callback registered
* with __atexit_register_cleanup(), set whenever we open or buffer a
* file. This chicanery is done so that programs that do not use stdio
* need not link it all in.
*
* The name `_cleanup' is, alas, fairly well known outside stdio.
*/
void
_cleanup(void)
{
/* (void) _fwalk(fclose); */ /* (void) _fwalk(fclose); */
(void) _fwalk(__sflush); /* `cheating' */ (void) _fwalk(__sflush); /* `cheating' */
} }
/*
* __sinit() is called whenever stdio's internal variables must be set up.
*/
void
__sinit(void)
{
_THREAD_PRIVATE_MUTEX(__sinit_mutex);
_THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
if (__sdidinit) {
/* bail out if caller lost the race */
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
return;
}
/* Initialize stdin/stdout/stderr (for the recursive mutex). http://b/18208568. */
for (size_t i = 0; i < 3; ++i) {
_FILEEXT_SETUP(__sF+i, __sFext+i);
}
/* Initialize the pre-allocated (but initially unused) streams. */
for (size_t i = 0; i < FOPEN_MAX - 3; ++i) {
_FILEEXT_SETUP(usual+i, usualext+i);
}
/* make sure we clean up on exit */
__atexit_register_cleanup(_cleanup); /* conservative */
__sdidinit = 1;
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
}

View File

@ -109,7 +109,7 @@ struct __sfileext {
pthread_mutex_t _lock; pthread_mutex_t _lock;
/* __fsetlocking support */ /* __fsetlocking support */
bool _caller_handles_locking; bool _stdio_handles_locking;
}; };
#if defined(__cplusplus) #if defined(__cplusplus)
@ -131,7 +131,7 @@ do { \
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
pthread_mutex_init(&_FLOCK(fp), &attr); \ pthread_mutex_init(&_FLOCK(fp), &attr); \
pthread_mutexattr_destroy(&attr); \ pthread_mutexattr_destroy(&attr); \
_EXT(fp)->_caller_handles_locking = false; \ _EXT(fp)->_stdio_handles_locking = true; \
} while (0) } while (0)
#define _FILEEXT_SETUP(f, fext) \ #define _FILEEXT_SETUP(f, fext) \
@ -153,8 +153,10 @@ __LIBC32_LEGACY_PUBLIC__ int __srefill(FILE*);
__LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*); __LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*);
/* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */ /* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */
__LIBC32_LEGACY_PUBLIC__ extern int __sdidinit;
__LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*); __LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*);
__LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void); __LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void);
__LIBC32_LEGACY_PUBLIC__ void __sinit(void);
__LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*); __LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
/* These are referenced by the Greed for Glory franchise. */ /* These are referenced by the Greed for Glory franchise. */
@ -168,6 +170,7 @@ __LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE *));
#pragma GCC visibility push(hidden) #pragma GCC visibility push(hidden)
int __sflush_locked(FILE *); int __sflush_locked(FILE *);
void _cleanup(void);
int __swhatbuf(FILE *, size_t *, int *); int __swhatbuf(FILE *, size_t *, int *);
wint_t __fgetwc_unlock(FILE *); wint_t __fgetwc_unlock(FILE *);
wint_t __ungetwc(wint_t, FILE *); wint_t __ungetwc(wint_t, FILE *);
@ -176,6 +179,8 @@ int __svfscanf(FILE * __restrict, const char * __restrict, __va_list);
int __vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list); int __vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list);
int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list); int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
extern void __atexit_register_cleanup(void (*)(void));
/* /*
* Return true if the given FILE cannot be written now. * Return true if the given FILE cannot be written now.
*/ */
@ -203,8 +208,8 @@ int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
(fp)->_lb._base = NULL; \ (fp)->_lb._base = NULL; \
} }
#define FLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) flockfile(fp) #define FLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) flockfile(fp)
#define FUNLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp) #define FUNLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) funlockfile(fp)
#define FLOATING_POINT #define FLOATING_POINT
#define PRINTF_WIDE_CHAR #define PRINTF_WIDE_CHAR
@ -232,10 +237,6 @@ struct __suio;
extern int __sfvwrite(FILE *, struct __suio *); extern int __sfvwrite(FILE *, struct __suio *);
wint_t __fputwc_unlock(wchar_t wc, FILE *fp); wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
/* Remove the if (!__sdidinit) __sinit() idiom from untouched upstream stdio code. */
extern void __sinit(void); // Not actually implemented.
#define __sdidinit 1
#pragma GCC visibility pop #pragma GCC visibility pop
__END_DECLS __END_DECLS

View File

@ -51,6 +51,11 @@ lflush(FILE *fp)
int int
__srefill(FILE *fp) __srefill(FILE *fp)
{ {
/* make sure stdio is set up */
if (!__sdidinit)
__sinit();
fp->_r = 0; /* largely a convenience for callers */ fp->_r = 0; /* largely a convenience for callers */
#if !defined(__ANDROID__) #if !defined(__ANDROID__)

View File

@ -74,7 +74,7 @@ void _flushlbf() {
} }
int __fsetlocking(FILE* fp, int type) { int __fsetlocking(FILE* fp, int type) {
int old_state = _EXT(fp)->_caller_handles_locking ? FSETLOCKING_BYCALLER : FSETLOCKING_INTERNAL; int old_state = _EXT(fp)->_stdio_handles_locking ? FSETLOCKING_INTERNAL : FSETLOCKING_BYCALLER;
if (type == FSETLOCKING_QUERY) { if (type == FSETLOCKING_QUERY) {
return old_state; return old_state;
} }
@ -84,7 +84,7 @@ int __fsetlocking(FILE* fp, int type) {
__libc_fatal("Bad type (%d) passed to __fsetlocking", type); __libc_fatal("Bad type (%d) passed to __fsetlocking", type);
} }
_EXT(fp)->_caller_handles_locking = (type == FSETLOCKING_BYCALLER); _EXT(fp)->_stdio_handles_locking = (type == FSETLOCKING_INTERNAL);
return old_state; return old_state;
} }
@ -99,7 +99,3 @@ int feof_unlocked(FILE* fp) {
int ferror_unlocked(FILE* fp) { int ferror_unlocked(FILE* fp) {
return __sferror(fp); return __sferror(fp);
} }
int fileno_unlocked(FILE* fp) {
return __sfileno(fp);
}

View File

@ -185,12 +185,51 @@ restart:
} }
_ATEXIT_UNLOCK(); _ATEXIT_UNLOCK();
extern void __libc_stdio_cleanup(void);
__libc_stdio_cleanup();
/* BEGIN android-changed: call __unregister_atfork if dso is not null */ /* BEGIN android-changed: call __unregister_atfork if dso is not null */
if (dso != NULL) { if (dso != NULL) {
__unregister_atfork(dso); __unregister_atfork(dso);
} }
/* END android-changed */ /* END android-changed */
} }
/*
* Register the cleanup function
*/
void
__atexit_register_cleanup(void (*func)(void))
{
struct atexit *p;
size_t pgsize = getpagesize();
if (pgsize < sizeof(*p))
return;
_ATEXIT_LOCK();
p = __atexit;
while (p != NULL && p->next != NULL)
p = p->next;
if (p == NULL) {
p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
/* BEGIN android-changed */
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
"atexit handlers");
/* END android-changed */
p->ind = 1;
p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
sizeof(p->fns[0]);
p->next = NULL;
__atexit = p;
} else {
if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
goto unlock;
}
p->fns[0].fn_ptr = (void (*)(void *))func;
p->fns[0].fn_arg = NULL;
p->fns[0].fn_dso = NULL;
mprotect(p, pgsize, PROT_READ);
restartloop = 1;
unlock:
_ATEXIT_UNLOCK();
}

View File

@ -36,9 +36,7 @@ class VersionScriptGenerator(object):
basename = os.path.basename(script) basename = os.path.basename(script)
dirname = os.path.dirname(script) dirname = os.path.dirname(script)
for arch in all_arches: for arch in all_arches:
for brillo in [False, True]: name = basename.split(".")[0] + "." + arch + ".map"
has_nobrillo = False
name = basename.split(".")[0] + "." + arch + (".brillo" if brillo else "") + ".map"
tmp_path = os.path.join(bionic_temp, name) tmp_path = os.path.join(bionic_temp, name)
dest_path = os.path.join(dirname, name) dest_path = os.path.join(dirname, name)
with open(tmp_path, "w") as fout: with open(tmp_path, "w") as fout:
@ -47,14 +45,10 @@ class VersionScriptGenerator(object):
for line in fin: for line in fin:
index = line.find("#") index = line.find("#")
if index != -1: if index != -1:
tags = line[index+1:].split() arches = line[index+1:].split()
if arch not in tags: if arch not in arches:
continue
if brillo and "nobrillo" in tags:
has_nobrillo = True
continue continue
fout.write(line) fout.write(line)
if not brillo or has_nobrillo:
shutil.copyfile(tmp_path, dest_path) shutil.copyfile(tmp_path, dest_path)

View File

@ -1316,10 +1316,9 @@ static void
tzset_unlocked(void) tzset_unlocked(void)
{ {
#if defined(__ANDROID__) #if defined(__ANDROID__)
// The TZ environment variable is meant to override the system-wide setting.
const char * name = getenv("TZ"); const char * name = getenv("TZ");
// If that's not set, look at the "persist.sys.timezone" system property. // Try the "persist.sys.timezone" system property.
if (name == NULL) { if (name == NULL) {
static const prop_info *pi; static const prop_info *pi;
@ -1341,10 +1340,6 @@ tzset_unlocked(void)
} }
} }
// If that's not available (because you're running AOSP on a WiFi-only
// device, say), fall back to GMT.
if (name == NULL) name = gmt;
tzsetlcl(name); tzsetlcl(name);
#else #else
tzsetlcl(getenv("TZ")); tzsetlcl(getenv("TZ"));
@ -2462,4 +2457,50 @@ static int __bionic_open_tzdata(const char* olson_id) {
return fd; return fd;
} }
// Caches the most recent timezone (http://b/8270865).
static int __bionic_tzload_cached(const char* name, struct state* const sp, const int doextend) {
lock();
// Our single-item cache.
static char* g_cached_time_zone_name;
static struct state g_cached_time_zone;
// Do we already have this timezone cached?
if (g_cached_time_zone_name != NULL && strcmp(name, g_cached_time_zone_name) == 0) {
*sp = g_cached_time_zone;
unlock();
return 0;
}
// Can we load it?
int rc = tzload(name, sp, doextend);
if (rc == 0) {
// Update the cache.
free(g_cached_time_zone_name);
g_cached_time_zone_name = strdup(name);
g_cached_time_zone = *sp;
}
unlock();
return rc;
}
// Non-standard API: mktime(3) but with an explicit timezone parameter.
// This can't actually be hidden/removed until we fix MtpUtils.cpp
__attribute__((visibility("default"))) time_t mktime_tz(struct tm* const tmp, const char* tz) {
struct state* st = malloc(sizeof(*st));
time_t return_value;
if (st == NULL)
return 0;
if (__bionic_tzload_cached(tz, st, true) != 0) {
// TODO: not sure what's best here, but for now, we fall back to gmt.
gmtload(st);
}
return_value = time1(tmp, localsub, st, 0L);
free(st);
return return_value;
}
// END android-added // END android-added

View File

@ -502,23 +502,7 @@ label:
continue; continue;
case 'Z': case 'Z':
#ifdef TM_ZONE #ifdef TM_ZONE
// BEGIN: Android-changed. pt = _add(t->TM_ZONE, pt, ptlim, modifier);
{
const char* zone = t->TM_ZONE;
if (!zone || !*zone) {
// "The value of tm_isdst shall be positive if Daylight Savings Time is
// in effect, 0 if Daylight Savings Time is not in effect, and negative
// if the information is not available."
if (t->tm_isdst == 0) zone = tzname[0];
else if (t->tm_isdst > 0) zone = tzname[1];
// "Replaced by the timezone name or abbreviation, or by no bytes if no
// timezone information exists."
if (!zone || !*zone) zone = "";
}
pt = _add(zone, pt, ptlim, modifier);
}
// END: Android-changed.
#else #else
if (t->tm_isdst >= 0) if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0], pt = _add(tzname[t->tm_isdst != 0],

View File

@ -4822,13 +4822,8 @@ void* dlcalloc(size_t n_elements, size_t elem_size) {
req = MAX_SIZE_T; /* force downstream failure on overflow */ req = MAX_SIZE_T; /* force downstream failure on overflow */
} }
mem = dlmalloc(req); mem = dlmalloc(req);
if (mem != 0) { if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
mchunkptr p = mem2chunk(mem); memset(mem, 0, req);
if (calloc_must_clear(p)) {
/* Make sure to clear all of the buffer, not just the requested size. */
memset(mem, 0, chunksize(p) - overhead_for(p));
}
}
return mem; return mem;
} }

View File

@ -32,6 +32,6 @@
#define __unlockenv() 0 #define __unlockenv() 0
#include <stddef.h> #include <stddef.h>
__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t); int reallocarr(void*, size_t, size_t);
#endif #endif

View File

@ -13,28 +13,15 @@ cc_library {
// DO NOT REMOVE --exclude-libs! // DO NOT REMOVE --exclude-libs!
ldflags: ["-Wl,--exclude-libs=libgcc.a"], ldflags: ["-Wl,--exclude-libs=libgcc.a"],
version_script: "libdl.map",
// for x86, exclude libgcc_eh.a for the same reasons as above // for x86, exclude libgcc_eh.a for the same reasons as above
arch: { arch: {
arm: {
version_script: "libdl.arm.map",
},
arm64: {
version_script: "libdl.arm64.map",
},
mips: {
version_script: "libdl.mips.map",
},
mips64: {
version_script: "libdl.mips64.map",
},
x86: { x86: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
version_script: "libdl.x86.map",
}, },
x86_64: { x86_64: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
version_script: "libdl.x86_64.map",
}, },
}, },
srcs: ["libdl.c"], srcs: ["libdl.c"],

View File

@ -33,13 +33,7 @@ LOCAL_CFLAGS := -Wall -Wextra -Wunused -Werror
LOCAL_CXX_STL := none LOCAL_CXX_STL := none
LOCAL_MODULE := libdl LOCAL_MODULE := libdl
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk \ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
$(LOCAL_PATH)/libdl.arm.map \
$(LOCAL_PATH)/libdl.arm64.map \
$(LOCAL_PATH)/libdl.mips.map \
$(LOCAL_PATH)/libdl.mips64.map \
$(LOCAL_PATH)/libdl.x86.map \
$(LOCAL_PATH)/libdl.x86_64.map \
# NOTE: libdl needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a needs a # NOTE: libdl needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a needs a
# few symbols from libc. Using --no-undefined here results in having to link # few symbols from libc. Using --no-undefined here results in having to link

View File

@ -14,17 +14,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -13,17 +13,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -24,48 +24,21 @@
// in the dynamic linker and hijacked at runtime. // in the dynamic linker and hijacked at runtime.
void* dlopen(const char* filename __unused, int flag __unused) { return 0; } void* dlopen(const char* filename __unused, int flag __unused) { return 0; }
const char* dlerror(void) { return 0; } const char* dlerror(void) { return 0; }
void* dlsym(void* handle __unused, const char* symbol __unused) { return 0; } void* dlsym(void* handle __unused, const char* symbol __unused) { return 0; }
void* dlvsym(void* handle __unused, const char* symbol __unused, const char* version __unused) {
return 0;
}
int dladdr(const void* addr __unused, Dl_info* info __unused) { return 0; } int dladdr(const void* addr __unused, Dl_info* info __unused) { return 0; }
int dlclose(void* handle __unused) { return 0; } int dlclose(void* handle __unused) { return 0; }
#if defined(__arm__) #if defined(__arm__)
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) { return 0; } _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) { return 0; }
#endif #endif
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused, int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused, void* data __unused) { return 0; }
void* data __unused) {
return 0;
}
void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unused) { } void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unused) { }
void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { } void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
void* android_dlopen_ext(const char* filename __unused, int flag __unused, void* android_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
const android_dlextinfo* extinfo __unused) {
return 0;
}
void android_set_application_target_sdk_version(uint32_t target __unused) { } void android_set_application_target_sdk_version(uint32_t target __unused) { }
uint32_t android_get_application_target_sdk_version() { return 0; } uint32_t android_get_application_target_sdk_version() { return 0; }
bool android_init_namespaces(const char* public_ns_sonames __unused,
const char* anon_ns_library_path __unused) {
return false;
}
struct android_namespace_t* android_create_namespace(const char* name __unused,
const char* ld_library_path __unused,
const char* default_library_path __unused,
uint64_t type __unused,
const char* permitted_when_isolated_path __unused) {
return 0;
}

View File

@ -28,17 +28,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -13,17 +13,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -13,17 +13,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -13,17 +13,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -13,17 +13,10 @@ LIBC {
*; *;
}; };
LIBC_N {
global:
android_init_namespaces;
android_create_namespace;
dlvsym;
} LIBC;
LIBC_PRIVATE { LIBC_PRIVATE {
global: global:
android_get_application_target_sdk_version; android_get_application_target_sdk_version;
android_set_application_target_sdk_version; android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH; android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH; android_update_LD_LIBRARY_PATH;
} LIBC_N; } LIBC;

View File

@ -3,7 +3,18 @@
bionic_coverage = false bionic_coverage = false
libm_common_src_files = [ // TODO: this comes from from upstream's libc, not libm, but it's an
// implementation detail that should have hidden visibility, so it needs
// to be in whatever library the math code is in.
libm_common_src_files = ["digittoint.c"]
// TODO: this is not in the BSDs.
libm_common_src_files += [
"significandl.c",
"sincos.c",
]
libm_common_src_files += [
"upstream-freebsd/lib/msun/bsdsrc/b_exp.c", "upstream-freebsd/lib/msun/bsdsrc/b_exp.c",
"upstream-freebsd/lib/msun/bsdsrc/b_log.c", "upstream-freebsd/lib/msun/bsdsrc/b_log.c",
"upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c", "upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c",
@ -175,19 +186,8 @@ libm_common_src_files = [
] ]
libm_common_src_files += [ libm_common_src_files += [
// TODO: this comes from from upstream's libc, not libm, but it's an "fake_long_double.c",
// implementation detail that should have hidden visibility, so it needs
// to be in whatever library the math code is in.
"digittoint.c",
// Functionality not in the BSDs.
"significandl.c",
"sincos.c",
// Modified versions of BSD code.
"signbit.c", "signbit.c",
// Home-grown stuff.
"fabs.cpp", "fabs.cpp",
] ]
@ -254,7 +254,6 @@ libm_common_cflags = [
"-D__BIONIC_NO_MATH_INLINES", "-D__BIONIC_NO_MATH_INLINES",
"-DFLT_EVAL_METHOD=0", "-DFLT_EVAL_METHOD=0",
"-include freebsd-compat.h", "-include freebsd-compat.h",
"-Werror",
"-Wno-missing-braces", "-Wno-missing-braces",
"-Wno-parentheses", "-Wno-parentheses",
"-Wno-sign-compare", "-Wno-sign-compare",
@ -291,10 +290,9 @@ cc_library {
native_coverage: bionic_coverage, native_coverage: bionic_coverage,
sanitize: ["never"], sanitize: ["never"],
version_script: "libm.map",
multilib: { multilib: {
lib32: {
srcs: ["fake_long_double.c"],
},
lib64: { lib64: {
srcs: libm_ld128_src_files, srcs: libm_ld128_src_files,
local_include_dirs: libm_ld_local_includes, local_include_dirs: libm_ld_local_includes,
@ -310,27 +308,23 @@ cc_library {
arm: { arm: {
srcs: [ srcs: [
"arm/fenv.c", "arm/fenv.c",
],
armv7_a_neon: {
srcs: [
"arm/sqrt.S", "arm/sqrt.S",
"arm/floor.S", "arm/floor.S",
], ],
exclude_srcs: [ exclude_srcs: [
// TODO: these require neon not available in arm
"upstream-freebsd/lib/msun/src/e_sqrt.c", "upstream-freebsd/lib/msun/src/e_sqrt.c",
"upstream-freebsd/lib/msun/src/e_sqrtf.c", "upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_floor.c", "upstream-freebsd/lib/msun/src/s_floor.c",
], ],
},
instruction_set: "arm", instruction_set: "arm",
ldflags: ["-Wl,--hash-style=both"], ldflags: ["-Wl,--hash-style=both"],
version_script: "libm.arm.map",
}, },
arm64: { arm64: {
srcs: [ srcs: [
"arm64/ceil.S",
"arm64/fenv.c", "arm64/fenv.c",
"arm64/ceil.S",
"arm64/fma.S", "arm64/fma.S",
"arm64/floor.S", "arm64/floor.S",
"arm64/lrint.S", "arm64/lrint.S",
@ -339,8 +333,6 @@ cc_library {
"arm64/trunc.S", "arm64/trunc.S",
], ],
exclude_srcs: [ exclude_srcs: [
"upstream-freebsd/lib/msun/src/e_sqrt.c",
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_ceil.c", "upstream-freebsd/lib/msun/src/s_ceil.c",
"upstream-freebsd/lib/msun/src/s_ceilf.c", "upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_fma.c", "upstream-freebsd/lib/msun/src/s_fma.c",
@ -353,163 +345,33 @@ cc_library {
"upstream-freebsd/lib/msun/src/s_lrintf.c", "upstream-freebsd/lib/msun/src/s_lrintf.c",
"upstream-freebsd/lib/msun/src/s_rint.c", "upstream-freebsd/lib/msun/src/s_rint.c",
"upstream-freebsd/lib/msun/src/s_rintf.c", "upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/e_sqrt.c",
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_trunc.c", "upstream-freebsd/lib/msun/src/s_trunc.c",
"upstream-freebsd/lib/msun/src/s_truncf.c", "upstream-freebsd/lib/msun/src/s_truncf.c",
], ],
version_script: "libm.arm64.map",
}, },
mips: { mips: {
srcs: ["mips/fenv.c"], srcs: ["mips/fenv.c"],
version_script: "libm.mips.map",
}, },
mips64: { mips64: {
srcs: ["mips/fenv.c"], srcs: ["mips/fenv.c"],
version_script: "libm.mips64.map",
}, },
x86: { x86: {
srcs: [
"i387/fenv.c",
"x86/sqrt.S",
"x86/sqrtf.S",
"x86/e_acos.S",
"x86/e_asin.S",
"x86/e_atan2.S",
"x86/e_cosh.S",
"x86/e_exp.S",
"x86/e_hypot.S",
"x86/e_log10.S",
"x86/e_log.S",
"x86/e_pow.S",
"x86/e_sinh.S",
"x86/libm_reduce_pi04l.S",
"x86/libm_sincos_huge.S",
"x86/libm_tancot_huge.S",
"x86/s_atan.S",
"x86/s_cbrt.S",
"x86/s_cos.S",
"x86/s_expm1.S",
"x86/s_log1p.S",
"x86/s_sin.S",
"x86/s_tanh.S",
"x86/s_tan.S",
],
exclude_srcs: [
"upstream-freebsd/lib/msun/src/e_acos.c",
"upstream-freebsd/lib/msun/src/e_asin.c",
"upstream-freebsd/lib/msun/src/e_atan2.c",
"upstream-freebsd/lib/msun/src/e_cosh.c",
"upstream-freebsd/lib/msun/src/e_exp.c",
"upstream-freebsd/lib/msun/src/e_hypot.c",
"upstream-freebsd/lib/msun/src/e_log.c",
"upstream-freebsd/lib/msun/src/e_log10.c",
"upstream-freebsd/lib/msun/src/e_pow.c",
"upstream-freebsd/lib/msun/src/e_sinh.c",
"upstream-freebsd/lib/msun/src/e_sqrt.c",
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
],
sse4_1: {
srcs: [
"x86/ceil.S",
"x86/ceilf.S",
"x86/floor.S",
"x86/floorf.S",
"x86/trunc.S",
"x86/truncf.S",
],
exclude_srcs: [
"upstream-freebsd/lib/msun/src/s_ceil.c",
"upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_floor.c",
"upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_trunc.c",
"upstream-freebsd/lib/msun/src/s_truncf.c",
],
},
local_include_dirs: ["i387"], local_include_dirs: ["i387"],
srcs: ["i387/fenv.c"],
// Clang has wrong long double sizes for x86. // Clang has wrong long double sizes for x86.
clang: false, clang: false,
ldflags: ["-Wl,--hash-style=both"], ldflags: ["-Wl,--hash-style=both"],
version_script: "libm.x86.map",
}, },
x86_64: { x86_64: {
srcs: [ srcs: ["amd64/fenv.c"],
"amd64/fenv.c",
"x86_64/sqrt.S",
"x86_64/sqrtf.S",
"x86_64/e_acos.S",
"x86_64/e_asin.S",
"x86_64/e_atan2.S",
"x86_64/e_cosh.S",
"x86_64/e_exp.S",
"x86_64/e_hypot.S",
"x86_64/e_log10.S",
"x86_64/e_log.S",
"x86_64/e_pow.S",
"x86_64/e_sinh.S",
"x86_64/s_atan.S",
"x86_64/s_cbrt.S",
"x86_64/s_cos.S",
"x86_64/s_expm1.S",
"x86_64/s_log1p.S",
"x86_64/s_sin.S",
"x86_64/s_tanh.S",
"x86_64/s_tan.S",
],
exclude_srcs: [
"upstream-freebsd/lib/msun/src/e_acos.c",
"upstream-freebsd/lib/msun/src/e_asin.c",
"upstream-freebsd/lib/msun/src/e_atan2.c",
"upstream-freebsd/lib/msun/src/e_cosh.c",
"upstream-freebsd/lib/msun/src/e_exp.c",
"upstream-freebsd/lib/msun/src/e_hypot.c",
"upstream-freebsd/lib/msun/src/e_log.c",
"upstream-freebsd/lib/msun/src/e_log10.c",
"upstream-freebsd/lib/msun/src/e_pow.c",
"upstream-freebsd/lib/msun/src/e_sinh.c",
"upstream-freebsd/lib/msun/src/e_sqrt.c",
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
],
sse4_1: {
srcs: [
"x86_64/ceil.S",
"x86_64/ceilf.S",
"x86_64/floor.S",
"x86_64/floorf.S",
"x86_64/trunc.S",
"x86_64/truncf.S",
],
exclude_srcs: [
"upstream-freebsd/lib/msun/src/s_ceil.c",
"upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_floor.c",
"upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_trunc.c",
"upstream-freebsd/lib/msun/src/s_truncf.c",
],
},
// Clang has wrong long double sizes for x86. // Clang has wrong long double sizes for x86.
clang: false, clang: false,
version_script: "libm.x86_64.map",
}, },
}, },

View File

@ -22,19 +22,14 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c \ upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c \
upstream-freebsd/lib/msun/src/catrig.c \ upstream-freebsd/lib/msun/src/catrig.c \
upstream-freebsd/lib/msun/src/catrigf.c \ upstream-freebsd/lib/msun/src/catrigf.c \
upstream-freebsd/lib/msun/src/e_acos.c \
upstream-freebsd/lib/msun/src/e_acosf.c \ upstream-freebsd/lib/msun/src/e_acosf.c \
upstream-freebsd/lib/msun/src/e_acosh.c \ upstream-freebsd/lib/msun/src/e_acosh.c \
upstream-freebsd/lib/msun/src/e_acoshf.c \ upstream-freebsd/lib/msun/src/e_acoshf.c \
upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_asinf.c \ upstream-freebsd/lib/msun/src/e_asinf.c \
upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_atan2f.c \ upstream-freebsd/lib/msun/src/e_atan2f.c \
upstream-freebsd/lib/msun/src/e_atanh.c \ upstream-freebsd/lib/msun/src/e_atanh.c \
upstream-freebsd/lib/msun/src/e_atanhf.c \ upstream-freebsd/lib/msun/src/e_atanhf.c \
upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/e_coshf.c \ upstream-freebsd/lib/msun/src/e_coshf.c \
upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/e_expf.c \ upstream-freebsd/lib/msun/src/e_expf.c \
upstream-freebsd/lib/msun/src/e_fmod.c \ upstream-freebsd/lib/msun/src/e_fmod.c \
upstream-freebsd/lib/msun/src/e_fmodf.c \ upstream-freebsd/lib/msun/src/e_fmodf.c \
@ -42,7 +37,6 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/e_gammaf.c \ upstream-freebsd/lib/msun/src/e_gammaf.c \
upstream-freebsd/lib/msun/src/e_gammaf_r.c \ upstream-freebsd/lib/msun/src/e_gammaf_r.c \
upstream-freebsd/lib/msun/src/e_gamma_r.c \ upstream-freebsd/lib/msun/src/e_gamma_r.c \
upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/e_hypotf.c \ upstream-freebsd/lib/msun/src/e_hypotf.c \
upstream-freebsd/lib/msun/src/e_j0.c \ upstream-freebsd/lib/msun/src/e_j0.c \
upstream-freebsd/lib/msun/src/e_j0f.c \ upstream-freebsd/lib/msun/src/e_j0f.c \
@ -54,13 +48,10 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/e_lgammaf.c \ upstream-freebsd/lib/msun/src/e_lgammaf.c \
upstream-freebsd/lib/msun/src/e_lgammaf_r.c \ upstream-freebsd/lib/msun/src/e_lgammaf_r.c \
upstream-freebsd/lib/msun/src/e_lgamma_r.c \ upstream-freebsd/lib/msun/src/e_lgamma_r.c \
upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/e_log10f.c \ upstream-freebsd/lib/msun/src/e_log10f.c \
upstream-freebsd/lib/msun/src/e_log2.c \ upstream-freebsd/lib/msun/src/e_log2.c \
upstream-freebsd/lib/msun/src/e_log2f.c \ upstream-freebsd/lib/msun/src/e_log2f.c \
upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/e_logf.c \ upstream-freebsd/lib/msun/src/e_logf.c \
upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/e_powf.c \ upstream-freebsd/lib/msun/src/e_powf.c \
upstream-freebsd/lib/msun/src/e_remainder.c \ upstream-freebsd/lib/msun/src/e_remainder.c \
upstream-freebsd/lib/msun/src/e_remainderf.c \ upstream-freebsd/lib/msun/src/e_remainderf.c \
@ -68,10 +59,7 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/e_rem_pio2f.c \ upstream-freebsd/lib/msun/src/e_rem_pio2f.c \
upstream-freebsd/lib/msun/src/e_scalb.c \ upstream-freebsd/lib/msun/src/e_scalb.c \
upstream-freebsd/lib/msun/src/e_scalbf.c \ upstream-freebsd/lib/msun/src/e_scalbf.c \
upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/e_sinhf.c \ upstream-freebsd/lib/msun/src/e_sinhf.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/imprecise.c \ upstream-freebsd/lib/msun/src/imprecise.c \
upstream-freebsd/lib/msun/src/k_cos.c \ upstream-freebsd/lib/msun/src/k_cos.c \
upstream-freebsd/lib/msun/src/k_cosf.c \ upstream-freebsd/lib/msun/src/k_cosf.c \
@ -84,17 +72,13 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/k_tanf.c \ upstream-freebsd/lib/msun/src/k_tanf.c \
upstream-freebsd/lib/msun/src/s_asinh.c \ upstream-freebsd/lib/msun/src/s_asinh.c \
upstream-freebsd/lib/msun/src/s_asinhf.c \ upstream-freebsd/lib/msun/src/s_asinhf.c \
upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_atanf.c \ upstream-freebsd/lib/msun/src/s_atanf.c \
upstream-freebsd/lib/msun/src/s_carg.c \ upstream-freebsd/lib/msun/src/s_carg.c \
upstream-freebsd/lib/msun/src/s_cargf.c \ upstream-freebsd/lib/msun/src/s_cargf.c \
upstream-freebsd/lib/msun/src/s_cargl.c \ upstream-freebsd/lib/msun/src/s_cargl.c \
upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_cbrtf.c \ upstream-freebsd/lib/msun/src/s_cbrtf.c \
upstream-freebsd/lib/msun/src/s_ccosh.c \ upstream-freebsd/lib/msun/src/s_ccosh.c \
upstream-freebsd/lib/msun/src/s_ccoshf.c \ upstream-freebsd/lib/msun/src/s_ccoshf.c \
upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_cexp.c \ upstream-freebsd/lib/msun/src/s_cexp.c \
upstream-freebsd/lib/msun/src/s_cexpf.c \ upstream-freebsd/lib/msun/src/s_cexpf.c \
upstream-freebsd/lib/msun/src/s_cimag.c \ upstream-freebsd/lib/msun/src/s_cimag.c \
@ -105,7 +89,6 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/s_conjl.c \ upstream-freebsd/lib/msun/src/s_conjl.c \
upstream-freebsd/lib/msun/src/s_copysign.c \ upstream-freebsd/lib/msun/src/s_copysign.c \
upstream-freebsd/lib/msun/src/s_copysignf.c \ upstream-freebsd/lib/msun/src/s_copysignf.c \
upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_cosf.c \ upstream-freebsd/lib/msun/src/s_cosf.c \
upstream-freebsd/lib/msun/src/s_cproj.c \ upstream-freebsd/lib/msun/src/s_cproj.c \
upstream-freebsd/lib/msun/src/s_cprojf.c \ upstream-freebsd/lib/msun/src/s_cprojf.c \
@ -124,15 +107,10 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/s_erff.c \ upstream-freebsd/lib/msun/src/s_erff.c \
upstream-freebsd/lib/msun/src/s_exp2.c \ upstream-freebsd/lib/msun/src/s_exp2.c \
upstream-freebsd/lib/msun/src/s_exp2f.c \ upstream-freebsd/lib/msun/src/s_exp2f.c \
upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_expm1f.c \ upstream-freebsd/lib/msun/src/s_expm1f.c \
upstream-freebsd/lib/msun/src/s_fdim.c \ upstream-freebsd/lib/msun/src/s_fdim.c \
upstream-freebsd/lib/msun/src/s_finite.c \ upstream-freebsd/lib/msun/src/s_finite.c \
upstream-freebsd/lib/msun/src/s_finitef.c \ upstream-freebsd/lib/msun/src/s_finitef.c \
upstream-freebsd/lib/msun/src/s_floor.c \
upstream-freebsd/lib/msun/src/s_floorf.c \
upstream-freebsd/lib/msun/src/s_fma.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \
upstream-freebsd/lib/msun/src/s_fmax.c \ upstream-freebsd/lib/msun/src/s_fmax.c \
upstream-freebsd/lib/msun/src/s_fmaxf.c \ upstream-freebsd/lib/msun/src/s_fmaxf.c \
upstream-freebsd/lib/msun/src/s_fmin.c \ upstream-freebsd/lib/msun/src/s_fmin.c \
@ -141,16 +119,11 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/s_frexpf.c \ upstream-freebsd/lib/msun/src/s_frexpf.c \
upstream-freebsd/lib/msun/src/s_ilogb.c \ upstream-freebsd/lib/msun/src/s_ilogb.c \
upstream-freebsd/lib/msun/src/s_ilogbf.c \ upstream-freebsd/lib/msun/src/s_ilogbf.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_llround.c \ upstream-freebsd/lib/msun/src/s_llround.c \
upstream-freebsd/lib/msun/src/s_llroundf.c \ upstream-freebsd/lib/msun/src/s_llroundf.c \
upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_log1pf.c \ upstream-freebsd/lib/msun/src/s_log1pf.c \
upstream-freebsd/lib/msun/src/s_logb.c \ upstream-freebsd/lib/msun/src/s_logb.c \
upstream-freebsd/lib/msun/src/s_logbf.c \ upstream-freebsd/lib/msun/src/s_logbf.c \
upstream-freebsd/lib/msun/src/s_lrint.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \
upstream-freebsd/lib/msun/src/s_lround.c \ upstream-freebsd/lib/msun/src/s_lround.c \
upstream-freebsd/lib/msun/src/s_lroundf.c \ upstream-freebsd/lib/msun/src/s_lroundf.c \
upstream-freebsd/lib/msun/src/s_modf.c \ upstream-freebsd/lib/msun/src/s_modf.c \
@ -161,8 +134,6 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/s_nextafterf.c \ upstream-freebsd/lib/msun/src/s_nextafterf.c \
upstream-freebsd/lib/msun/src/s_remquo.c \ upstream-freebsd/lib/msun/src/s_remquo.c \
upstream-freebsd/lib/msun/src/s_remquof.c \ upstream-freebsd/lib/msun/src/s_remquof.c \
upstream-freebsd/lib/msun/src/s_rint.c \
upstream-freebsd/lib/msun/src/s_rintf.c \
upstream-freebsd/lib/msun/src/s_round.c \ upstream-freebsd/lib/msun/src/s_round.c \
upstream-freebsd/lib/msun/src/s_roundf.c \ upstream-freebsd/lib/msun/src/s_roundf.c \
upstream-freebsd/lib/msun/src/s_scalbln.c \ upstream-freebsd/lib/msun/src/s_scalbln.c \
@ -171,15 +142,10 @@ LOCAL_SRC_FILES := \
upstream-freebsd/lib/msun/src/s_signgam.c \ upstream-freebsd/lib/msun/src/s_signgam.c \
upstream-freebsd/lib/msun/src/s_significand.c \ upstream-freebsd/lib/msun/src/s_significand.c \
upstream-freebsd/lib/msun/src/s_significandf.c \ upstream-freebsd/lib/msun/src/s_significandf.c \
upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_sinf.c \ upstream-freebsd/lib/msun/src/s_sinf.c \
upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_tanf.c \ upstream-freebsd/lib/msun/src/s_tanf.c \
upstream-freebsd/lib/msun/src/s_tanh.c \
upstream-freebsd/lib/msun/src/s_tanhf.c \ upstream-freebsd/lib/msun/src/s_tanhf.c \
upstream-freebsd/lib/msun/src/s_tgammaf.c \ upstream-freebsd/lib/msun/src/s_tgammaf.c \
upstream-freebsd/lib/msun/src/s_trunc.c \
upstream-freebsd/lib/msun/src/s_truncf.c \
upstream-freebsd/lib/msun/src/w_cabs.c \ upstream-freebsd/lib/msun/src/w_cabs.c \
upstream-freebsd/lib/msun/src/w_cabsf.c \ upstream-freebsd/lib/msun/src/w_cabsf.c \
upstream-freebsd/lib/msun/src/w_cabsl.c \ upstream-freebsd/lib/msun/src/w_cabsl.c \
@ -270,6 +236,37 @@ LOCAL_SRC_FILES += \
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
LOCAL_SRC_FILES_arm += \ LOCAL_SRC_FILES_arm += \
arm/fenv.c \ arm/fenv.c \
upstream-freebsd/lib/msun/src/e_acos.c \
upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_fma.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \
upstream-freebsd/lib/msun/src/s_floorf.c \
upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_lrint.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \
upstream-freebsd/lib/msun/src/s_rint.c \
upstream-freebsd/lib/msun/src/s_rintf.c \
upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_tanh.c \
upstream-freebsd/lib/msun/src/s_trunc.c \
upstream-freebsd/lib/msun/src/s_truncf.c \
# s_floor.S requires neon instructions. # s_floor.S requires neon instructions.
ifdef TARGET_2ND_ARCH ifdef TARGET_2ND_ARCH
@ -279,16 +276,17 @@ arch_variant := $(TARGET_ARCH_VARIANT)
endif endif
# Use the C version on armv7-a since it doesn't support neon instructions. # Use the C version on armv7-a since it doesn't support neon instructions.
ifneq ($(arch_variant),armv7-a) ifeq ($(arch_variant),armv7-a)
LOCAL_SRC_FILES_arm += \ LOCAL_SRC_FILES_arm += \
arm/sqrt.S \
arm/floor.S \
LOCAL_SRC_FILES_EXCLUDE_arm += \
upstream-freebsd/lib/msun/src/e_sqrt.c \ upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \ upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/s_floor.c \ upstream-freebsd/lib/msun/src/s_floor.c \
else
LOCAL_SRC_FILES_arm += \
arm/sqrt.S \
arm/floor.S \
endif endif
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@ -303,30 +301,64 @@ LOCAL_SRC_FILES_arm64 += \
arm64/rint.S \ arm64/rint.S \
arm64/sqrt.S \ arm64/sqrt.S \
arm64/trunc.S \ arm64/trunc.S \
upstream-freebsd/lib/msun/src/e_acos.c \
LOCAL_SRC_FILES_EXCLUDE_arm64 += \ upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \ upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \ upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/s_ceil.c \ upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \ upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/s_fma.c \ upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \ upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/s_floor.c \ upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/s_floorf.c \ upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/s_llrint.c \ upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \ upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_lrint.c \ upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \ upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_rint.c \ upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_rintf.c \ upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_trunc.c \ upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_truncf.c \ upstream-freebsd/lib/msun/src/s_tanh.c \
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# mips # mips
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
libm_mips_arch_files := \ libm_mips_arch_files := \
mips/fenv.c \ mips/fenv.c \
upstream-freebsd/lib/msun/src/e_acos.c \
upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_fma.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \
upstream-freebsd/lib/msun/src/s_floor.c \
upstream-freebsd/lib/msun/src/s_floorf.c \
upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_lrint.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \
upstream-freebsd/lib/msun/src/s_rint.c \
upstream-freebsd/lib/msun/src/s_rintf.c \
upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_tanh.c \
upstream-freebsd/lib/msun/src/s_trunc.c \
upstream-freebsd/lib/msun/src/s_truncf.c \
LOCAL_SRC_FILES_mips += $(libm_mips_arch_files) LOCAL_SRC_FILES_mips += $(libm_mips_arch_files)
LOCAL_SRC_FILES_mips64 += $(libm_mips_arch_files) LOCAL_SRC_FILES_mips64 += $(libm_mips_arch_files)
@ -336,6 +368,14 @@ LOCAL_SRC_FILES_mips64 += $(libm_mips_arch_files)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
LOCAL_SRC_FILES_x86 += \ LOCAL_SRC_FILES_x86 += \
i387/fenv.c \ i387/fenv.c \
upstream-freebsd/lib/msun/src/s_fma.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_lrint.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \
upstream-freebsd/lib/msun/src/s_rint.c \
upstream-freebsd/lib/msun/src/s_rintf.c \
x86/sqrt.S \ x86/sqrt.S \
x86/sqrtf.S \ x86/sqrtf.S \
x86/e_acos.S \ x86/e_acos.S \
@ -360,28 +400,6 @@ LOCAL_SRC_FILES_x86 += \
x86/s_tanh.S \ x86/s_tanh.S \
x86/s_tan.S \ x86/s_tan.S \
LOCAL_SRC_FILES_EXCLUDE_x86 += \
upstream-freebsd/lib/msun/src/e_acos.c \
upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_tanh.c \
ifeq ($(ARCH_X86_HAVE_SSE4_1),true) ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
LOCAL_SRC_FILES_x86 += \ LOCAL_SRC_FILES_x86 += \
x86/ceil.S \ x86/ceil.S \
@ -391,7 +409,8 @@ LOCAL_SRC_FILES_x86 += \
x86/trunc.S \ x86/trunc.S \
x86/truncf.S \ x86/truncf.S \
LOCAL_SRC_FILES_EXCLUDE_x86 += \ else
LOCAL_SRC_FILES_x86 += \
upstream-freebsd/lib/msun/src/s_ceil.c \ upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \ upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_floor.c \ upstream-freebsd/lib/msun/src/s_floor.c \
@ -406,6 +425,14 @@ endif
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
LOCAL_SRC_FILES_x86_64 += \ LOCAL_SRC_FILES_x86_64 += \
amd64/fenv.c \ amd64/fenv.c \
upstream-freebsd/lib/msun/src/s_fma.c \
upstream-freebsd/lib/msun/src/s_fmaf.c \
upstream-freebsd/lib/msun/src/s_llrint.c \
upstream-freebsd/lib/msun/src/s_llrintf.c \
upstream-freebsd/lib/msun/src/s_lrint.c \
upstream-freebsd/lib/msun/src/s_lrintf.c \
upstream-freebsd/lib/msun/src/s_rint.c \
upstream-freebsd/lib/msun/src/s_rintf.c \
x86_64/sqrt.S \ x86_64/sqrt.S \
x86_64/sqrtf.S \ x86_64/sqrtf.S \
x86_64/e_acos.S \ x86_64/e_acos.S \
@ -427,28 +454,6 @@ LOCAL_SRC_FILES_x86_64 += \
x86_64/s_tanh.S \ x86_64/s_tanh.S \
x86_64/s_tan.S \ x86_64/s_tan.S \
LOCAL_SRC_FILES_EXCLUDE_x86_64 += \
upstream-freebsd/lib/msun/src/e_acos.c \
upstream-freebsd/lib/msun/src/e_asin.c \
upstream-freebsd/lib/msun/src/e_atan2.c \
upstream-freebsd/lib/msun/src/e_cosh.c \
upstream-freebsd/lib/msun/src/e_exp.c \
upstream-freebsd/lib/msun/src/e_hypot.c \
upstream-freebsd/lib/msun/src/e_log.c \
upstream-freebsd/lib/msun/src/e_log10.c \
upstream-freebsd/lib/msun/src/e_pow.c \
upstream-freebsd/lib/msun/src/e_sinh.c \
upstream-freebsd/lib/msun/src/e_sqrt.c \
upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/s_atan.c \
upstream-freebsd/lib/msun/src/s_cbrt.c \
upstream-freebsd/lib/msun/src/s_cos.c \
upstream-freebsd/lib/msun/src/s_expm1.c \
upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_sin.c \
upstream-freebsd/lib/msun/src/s_tan.c \
upstream-freebsd/lib/msun/src/s_tanh.c \
ifeq ($(ARCH_X86_HAVE_SSE4_1),true) ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
LOCAL_SRC_FILES_x86_64 += \ LOCAL_SRC_FILES_x86_64 += \
x86_64/ceil.S \ x86_64/ceil.S \
@ -458,7 +463,8 @@ LOCAL_SRC_FILES_x86_64 += \
x86_64/trunc.S \ x86_64/trunc.S \
x86_64/truncf.S \ x86_64/truncf.S \
LOCAL_SRC_FILES_EXCLUDE_x86_64 += \ else
LOCAL_SRC_FILES_x86_64 += \
upstream-freebsd/lib/msun/src/s_ceil.c \ upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \ upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_floor.c \ upstream-freebsd/lib/msun/src/s_floor.c \

View File

@ -272,8 +272,8 @@ LIBC {
*; *;
}; };
LIBC_PRIVATE { # arm mips LIBC_PRIVATE { # arm x86 mips
global: # arm mips global: # arm x86 mips
___Unwind_Backtrace; # arm ___Unwind_Backtrace; # arm
___Unwind_ForcedUnwind; # arm ___Unwind_ForcedUnwind; # arm
___Unwind_RaiseException; # arm ___Unwind_RaiseException; # arm
@ -354,6 +354,7 @@ LIBC_PRIVATE { # arm mips
__lesf2; # arm __lesf2; # arm
__ltdf2; # arm __ltdf2; # arm
__ltsf2; # arm __ltsf2; # arm
__muldc3; # arm x86 mips
__muldf3; # arm __muldf3; # arm
__nedf2; # arm __nedf2; # arm
__nesf2; # arm __nesf2; # arm
@ -375,4 +376,4 @@ LIBC_PRIVATE { # arm mips
_Unwind_VRS_Pop; # arm _Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm _Unwind_VRS_Set; # arm
restore_core_regs; # arm restore_core_regs; # arm
} LIBC; # arm mips } LIBC; # arm x86 mips

View File

@ -271,8 +271,8 @@ LIBC {
*; *;
}; };
LIBC_PRIVATE { # arm mips LIBC_PRIVATE { # arm x86 mips
global: # arm mips global: # arm x86 mips
___Unwind_Backtrace; # arm ___Unwind_Backtrace; # arm
___Unwind_ForcedUnwind; # arm ___Unwind_ForcedUnwind; # arm
___Unwind_RaiseException; # arm ___Unwind_RaiseException; # arm
@ -353,6 +353,7 @@ LIBC_PRIVATE { # arm mips
__lesf2; # arm __lesf2; # arm
__ltdf2; # arm __ltdf2; # arm
__ltsf2; # arm __ltsf2; # arm
__muldc3; # arm x86 mips
__muldf3; # arm __muldf3; # arm
__nedf2; # arm __nedf2; # arm
__nesf2; # arm __nesf2; # arm
@ -374,4 +375,4 @@ LIBC_PRIVATE { # arm mips
_Unwind_VRS_Pop; # arm _Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm _Unwind_VRS_Set; # arm
restore_core_regs; # arm restore_core_regs; # arm
} LIBC; # arm mips } LIBC; # arm x86 mips

View File

@ -272,10 +272,11 @@ LIBC {
*; *;
}; };
LIBC_PRIVATE { # arm mips LIBC_PRIVATE { # arm x86 mips
global: # arm mips global: # arm x86 mips
__fixdfdi; # arm mips __fixdfdi; # arm mips
__fixsfdi; # arm mips __fixsfdi; # arm mips
__fixunsdfdi; # arm mips __fixunsdfdi; # arm mips
__fixunssfdi; # arm mips __fixunssfdi; # arm mips
} LIBC; # arm mips __muldc3; # arm x86 mips
} LIBC; # arm x86 mips

View File

@ -272,3 +272,7 @@ LIBC {
*; *;
}; };
LIBC_PRIVATE { # arm x86 mips
global: # arm x86 mips
__muldc3; # arm x86 mips
} LIBC; # arm x86 mips

View File

@ -9,12 +9,12 @@ LOCAL_SRC_FILES := \
dlfcn.cpp \ dlfcn.cpp \
linker.cpp \ linker.cpp \
linker_allocator.cpp \ linker_allocator.cpp \
linker_sdk_versions.cpp \
linker_block_allocator.cpp \ linker_block_allocator.cpp \
linker_libc_support.c \ linker_libc_support.c \
linker_mapped_file_fragment.cpp \ linker_mapped_file_fragment.cpp \
linker_memory.cpp \ linker_memory.cpp \
linker_phdr.cpp \ linker_phdr.cpp \
linker_sdk_versions.cpp \
linker_utils.cpp \ linker_utils.cpp \
rt.cpp \ rt.cpp \

View File

@ -16,10 +16,12 @@
#include "linker.h" #include "linker.h"
#include <dlfcn.h>
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <android/dlext.h>
#include <android/api-level.h> #include <android/api-level.h>
#include <bionic/pthread_internal.h> #include <bionic/pthread_internal.h>
@ -68,7 +70,8 @@ void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
static void* dlopen_ext(const char* filename, int flags, static void* dlopen_ext(const char* filename, int flags,
const android_dlextinfo* extinfo, void* caller_addr) { const android_dlextinfo* extinfo, void* caller_addr) {
ScopedPthreadMutexLocker locker(&g_dl_mutex); ScopedPthreadMutexLocker locker(&g_dl_mutex);
soinfo* result = do_dlopen(filename, flags, extinfo, caller_addr); soinfo* caller = find_containing_library(caller_addr);
soinfo* result = do_dlopen(filename, flags, extinfo, caller);
if (result == nullptr) { if (result == nullptr) {
__bionic_format_dlerror("dlopen failed", linker_get_error_buffer()); __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
return nullptr; return nullptr;
@ -86,32 +89,70 @@ void* dlopen(const char* filename, int flags) {
return dlopen_ext(filename, flags, nullptr, caller_addr); return dlopen_ext(filename, flags, nullptr, caller_addr);
} }
extern android_namespace_t* g_anonymous_namespace; void* dlsym(void* handle, const char* symbol) {
void* dlsym_impl(void* handle, const char* symbol, const char* version, void* caller_addr) {
ScopedPthreadMutexLocker locker(&g_dl_mutex); ScopedPthreadMutexLocker locker(&g_dl_mutex);
void* result;
if (!do_dlsym(handle, symbol, version, caller_addr, &result)) { #if !defined(__LP64__)
__bionic_format_dlerror(linker_get_error_buffer(), nullptr); if (handle == nullptr) {
__bionic_format_dlerror("dlsym library handle is null", nullptr);
return nullptr;
}
#endif
if (symbol == nullptr) {
__bionic_format_dlerror("dlsym symbol name is null", nullptr);
return nullptr; return nullptr;
} }
return result; soinfo* found = nullptr;
const ElfW(Sym)* sym = nullptr;
void* caller_addr = __builtin_return_address(0);
soinfo* caller = find_containing_library(caller_addr);
if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
sym = dlsym_linear_lookup(symbol, &found, caller, handle);
} else {
sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
} }
void* dlsym(void* handle, const char* symbol) { if (sym != nullptr) {
void* caller_addr = __builtin_return_address(0); unsigned bind = ELF_ST_BIND(sym->st_info);
return dlsym_impl(handle, symbol, nullptr, caller_addr);
if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
return reinterpret_cast<void*>(found->resolve_symbol_address(sym));
} }
void* dlvsym(void* handle, const char* symbol, const char* version) { __bionic_format_dlerror("symbol found but not global", symbol);
void* caller_addr = __builtin_return_address(0); return nullptr;
return dlsym_impl(handle, symbol, version, caller_addr); } else {
__bionic_format_dlerror("undefined symbol", symbol);
return nullptr;
}
} }
int dladdr(const void* addr, Dl_info* info) { int dladdr(const void* addr, Dl_info* info) {
ScopedPthreadMutexLocker locker(&g_dl_mutex); ScopedPthreadMutexLocker locker(&g_dl_mutex);
return do_dladdr(addr, info);
// Determine if this address can be found in any library currently mapped.
soinfo* si = find_containing_library(addr);
if (si == nullptr) {
return 0;
}
memset(info, 0, sizeof(Dl_info));
info->dli_fname = si->get_realpath();
// Address at which the shared object is loaded.
info->dli_fbase = reinterpret_cast<void*>(si->base);
// Determine if any symbol in the library contains the specified address.
ElfW(Sym)* sym = si->find_symbol_by_address(addr);
if (sym != nullptr) {
info->dli_sname = si->get_string(sym->st_name);
info->dli_saddr = reinterpret_cast<void*>(si->resolve_symbol_address(sym));
}
return 1;
} }
int dlclose(void* handle) { int dlclose(void* handle) {
@ -136,34 +177,6 @@ uint32_t android_get_application_target_sdk_version() {
return get_application_target_sdk_version(); return get_application_target_sdk_version();
} }
bool android_init_namespaces(const char* public_ns_sonames,
const char* anon_ns_library_path) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
bool success = init_namespaces(public_ns_sonames, anon_ns_library_path);
if (!success) {
__bionic_format_dlerror("android_init_namespaces failed", linker_get_error_buffer());
}
return success;
}
android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
const char* default_library_path, uint64_t type,
const char* permitted_when_isolated_path) {
void* caller_addr = __builtin_return_address(0);
ScopedPthreadMutexLocker locker(&g_dl_mutex);
android_namespace_t* result = create_namespace(caller_addr, name, ld_library_path,
default_library_path, type,
permitted_when_isolated_path);
if (result == nullptr) {
__bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());
}
return result;
}
// name_offset: starting index of the name in libdl_info.strtab // name_offset: starting index of the name in libdl_info.strtab
#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \ #define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
{ name_offset, \ { name_offset, \
@ -190,11 +203,11 @@ static const char ANDROID_LIBDL_STRTAB[] =
// 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999 // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
// 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789 // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
"erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar" "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
// 0000000000111111 111122222222223333333333 4444444444555555555566666 6666677 // 0000000000111111
// 0123456789012345 678901234567890123456789 0123456789012345678901234 5678901 // 0123456789012345
"get_sdk_version\0android_init_namespaces\0android_create_namespace\0dlvsym\0" "get_sdk_version\0"
#if defined(__arm__) #if defined(__arm__)
// 272 // 216
"dl_unwind_find_exidx\0" "dl_unwind_find_exidx\0"
#endif #endif
; ;
@ -216,11 +229,8 @@ static ElfW(Sym) g_libdl_symtab[] = {
ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1), ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1), ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1), ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
ELFW(SYM_INITIALIZER)(216, &android_init_namespaces, 1),
ELFW(SYM_INITIALIZER)(240, &android_create_namespace, 1),
ELFW(SYM_INITIALIZER)(265, &dlvsym, 1),
#if defined(__arm__) #if defined(__arm__)
ELFW(SYM_INITIALIZER)(272, &dl_unwind_find_exidx, 1), ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
#endif #endif
}; };
@ -237,20 +247,18 @@ static ElfW(Sym) g_libdl_symtab[] = {
// Note that adding any new symbols here requires stubbing them out in libdl. // Note that adding any new symbols here requires stubbing them out in libdl.
static unsigned g_libdl_buckets[1] = { 1 }; static unsigned g_libdl_buckets[1] = { 1 };
#if defined(__arm__) #if defined(__arm__)
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 }; static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
#else #else
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 }; static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
#endif #endif
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8))); static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
static soinfo* __libdl_info = nullptr; static soinfo* __libdl_info = nullptr;
extern android_namespace_t g_default_namespace;
// This is used by the dynamic linker. Every process gets these symbols for free. // This is used by the dynamic linker. Every process gets these symbols for free.
soinfo* get_libdl_info() { soinfo* get_libdl_info() {
if (__libdl_info == nullptr) { if (__libdl_info == nullptr) {
__libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, "libdl.so", nullptr, 0, RTLD_GLOBAL); __libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL);
__libdl_info->flags_ |= FLAG_LINKED; __libdl_info->flags_ |= FLAG_LINKED;
__libdl_info->strtab_ = ANDROID_LIBDL_STRTAB; __libdl_info->strtab_ = ANDROID_LIBDL_STRTAB;
__libdl_info->symtab_ = g_libdl_symtab; __libdl_info->symtab_ = g_libdl_symtab;

View File

@ -25,49 +25,12 @@ struct LinkedListEntry {
T* element; T* element;
}; };
// ForwardInputIterator
template<typename T>
class LinkedListIterator {
public:
LinkedListIterator() : entry_(nullptr) {}
LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {}
explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {}
LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) {
entry_ = that.entry_;
return *this;
}
LinkedListIterator<T>& operator++() {
entry_ = entry_->next;
return *this;
}
T* operator*() {
return entry_->element;
}
bool operator==(const LinkedListIterator<T>& that) const {
return entry_ == that.entry_;
}
bool operator!=(const LinkedListIterator<T>& that) const {
return entry_ != that.entry_;
}
private:
LinkedListEntry<T> *entry_;
};
/* /*
* Represents linked list of objects of type T * Represents linked list of objects of type T
*/ */
template<typename T, typename Allocator> template<typename T, typename Allocator>
class LinkedList { class LinkedList {
public: public:
typedef LinkedListIterator<T> iterator;
typedef T* value_type;
LinkedList() : head_(nullptr), tail_(nullptr) {} LinkedList() : head_(nullptr), tail_(nullptr) {}
~LinkedList() { ~LinkedList() {
clear(); clear();
@ -164,13 +127,7 @@ class LinkedList {
} else { } else {
p->next = next; p->next = next;
} }
if (tail_ == e) {
tail_ = p;
}
Allocator::free(e); Allocator::free(e);
e = next; e = next;
} else { } else {
p = e; p = e;
@ -190,24 +147,6 @@ class LinkedList {
return nullptr; return nullptr;
} }
iterator begin() {
return iterator(head_);
}
iterator end() {
return iterator(nullptr);
}
iterator find(T* value) {
for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
if (e->element == value) {
return iterator(e);
}
}
return end();
}
size_t copy_to_array(T* array[], size_t array_length) const { size_t copy_to_array(T* array[], size_t array_length) const {
size_t sz = 0; size_t sz = 0;
for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) { for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) {

Some files were not shown because too many files have changed in this diff Show More