Merge "Revert "Ensure that readlink has access to /proc/self/fd""
diff --git a/.clang-format b/.clang-format
index ea19538..9b7478c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,6 +2,7 @@
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
+ColumnLimit: 100
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
IndentWidth: 2
diff --git a/benchmarks/Benchmark.cpp b/benchmarks/Benchmark.cpp
index ea6000f..a7ab682 100644
--- a/benchmarks/Benchmark.cpp
+++ b/benchmarks/Benchmark.cpp
@@ -24,7 +24,7 @@
#include <string>
#include <vector>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
#include <benchmark/Benchmark.h>
diff --git a/benchmarks/utils.cpp b/benchmarks/utils.cpp
index cf17edb..8bbd20a 100644
--- a/benchmarks/utils.cpp
+++ b/benchmarks/utils.cpp
@@ -23,7 +23,7 @@
#include <string>
-#include <base/stringprintf.h>
+#include <android-base/stringprintf.h>
int Round(int n) {
int base = 1;
diff --git a/libc/Android.bp b/libc/Android.bp
index 2429634..74fd22b 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1,5 +1,3 @@
-bionic_coverage = false
-
// Define the common source files for all the libc instances
// =========================================================
libc_common_src_files = [
@@ -11,7 +9,6 @@
"bionic/if_indextoname.c",
"bionic/if_nametoindex.c",
"bionic/initgroups.c",
- "bionic/ioctl.c",
"bionic/isatty.c",
"bionic/memmem.c",
"bionic/pututline.c",
@@ -23,6 +20,7 @@
"bionic/system_properties_compat.c",
"stdio/findfp.c",
"stdio/fread.c",
+ "stdio/refill.c",
"stdio/snprintf.c",
"stdio/sprintf.c",
"stdio/stdio.c",
@@ -76,51 +74,70 @@
// Define some common cflags
// ========================================================
-libc_common_cflags = [
- "-D_LIBC=1",
- "-Wall",
- "-Wextra",
- "-Wunused",
+cc_defaults {
+ name: "libc_defaults",
+ cflags: [
+ "-D_LIBC=1",
+ "-Wall",
+ "-Wextra",
+ "-Wunused",
-// Try to catch typical 32-bit assumptions that break with 64-bit pointers.
- "-Werror=pointer-to-int-cast",
- "-Werror=int-to-pointer-cast",
- "-Werror=type-limits",
- "-Werror",
-]
+ // Try to catch typical 32-bit assumptions that break with 64-bit pointers.
+ "-Werror=pointer-to-int-cast",
+ "-Werror=int-to-pointer-cast",
+ "-Werror=type-limits",
+ "-Werror",
+ ],
+ // TODO: split out the asflags.
+ asflags: [
+ "-D_LIBC=1",
+ "-Wall",
+ "-Wextra",
+ "-Wunused",
-libc_common_product_variables = {
- device_uses_jemalloc: {
- cflags: ["-DUSE_JEMALLOC"],
- include_dirs: ["external/jemalloc/include"],
+ // Try to catch typical 32-bit assumptions that break with 64-bit pointers.
+ "-Werror=pointer-to-int-cast",
+ "-Werror=int-to-pointer-cast",
+ "-Werror=type-limits",
+ "-Werror",
+ ],
+ conlyflags: ["-std=gnu99"],
+ cppflags: [],
+
+ product_variables: {
+ device_uses_jemalloc: {
+ cflags: ["-DUSE_JEMALLOC"],
+ include_dirs: ["external/jemalloc/include"],
+ },
+ device_uses_dlmalloc: {
+ cflags: ["-DUSE_DLMALLOC"],
+ },
+ // To customize dlmalloc's alignment, set BOARD_MALLOC_ALIGNMENT in
+ // the appropriate BoardConfig.mk file.
+ dlmalloc_alignment: {
+ cflags: ["-DMALLOC_ALIGNMENT=%d"],
+ },
},
- device_uses_dlmalloc: {
- cflags: ["-DUSE_DLMALLOC"],
+ // Clang/llvm has incompatible long double (fp128) for x86_64.
+ // https://llvm.org/bugs/show_bug.cgi?id=23897
+ arch: {
+ x86_64: {
+ clang: false,
+ },
},
- // To customize dlmalloc's alignment, set BOARD_MALLOC_ALIGNMENT in
- // the appropriate BoardConfig.mk file.
- dlmalloc_alignment: {
- cflags: ["-DMALLOC_ALIGNMENT=%d"],
- },
+
+ stl: "none",
+ system_shared_libs: [],
+ sanitize: ["never"],
+ native_coverage: false,
}
-// Clang/llvm has incompatible long double (fp128) for x86_64.
-// https://llvm.org/bugs/show_bug.cgi?id=23897
-use_clang_x86_64 = false
-
// ANDROIDMK TRANSLATION ERROR: unsupported directive
// ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
//libc_common_cflags += ["-DDEBUG"]
// ANDROIDMK TRANSLATION ERROR: unsupported directive
// endif
-//
-// Define some common conlyflags
-libc_common_conlyflags = ["-std=gnu99"]
-
-// Define some common cppflags
-libc_common_cppflags = []
-
// ========================================================
// libc_stack_protector.a - stack protector code
// ========================================================
@@ -132,23 +149,9 @@
cc_library_static {
srcs: ["bionic/__stack_chk_fail.cpp"],
- cflags: libc_common_cflags + ["-fno-stack-protector"],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
+ defaults: ["libc_defaults"],
+ cflags: ["-fno-stack-protector"],
name: "libc_stack_protector",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
-
}
// ========================================================
@@ -157,6 +160,7 @@
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"tzcode/asctime.c",
"tzcode/difftime.c",
@@ -166,38 +170,30 @@
"upstream-openbsd/lib/libc/time/wcsftime.c", // tzcode doesn't include wcsftime, so we use the OpenBSD one.
],
- cflags: libc_common_cflags + [
+ cflags: [
"-fvisibility=hidden",
+ "-Wno-unused-parameter",
// Don't use ridiculous amounts of stack.
"-DALL_STATE",
// Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
"-DSTD_INSPIRED",
+ // Obviously, we want to be thread-safe.
+ "-DTHREAD_SAFE",
// The name of the tm_gmtoff field in our struct tm.
"-DTM_GMTOFF=tm_gmtoff",
// Where we store our tzdata.
"-DTZDIR=\\\"/system/usr/share/zoneinfo\\\"",
// Include timezone and daylight globals.
"-DUSG_COMPAT=1",
+ // Use the empty string (instead of " ") as the timezone abbreviation
+ // fallback.
+ "-DWILDABBR=\\\"\\\"",
"-DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU",
"-Dlint",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: ["tzcode/"],
name: "libc_tzcode",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
@@ -206,6 +202,7 @@
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"dns/net/gethnamaddr.c",
"dns/net/getservbyname.c",
@@ -240,8 +237,8 @@
"upstream-openbsd/lib/libc/net/res_random.c",
],
- cflags: ["-Dres_randomid=__res_randomid"] +
- libc_common_cflags + [
+ cflags: [
+ "-Dres_randomid=__res_randomid",
"-DANDROID_CHANGES",
"-DINET6",
"-fvisibility=hidden",
@@ -249,9 +246,6 @@
"-include netbsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"dns/include",
"private",
@@ -260,17 +254,6 @@
],
name: "libc_dns",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
@@ -281,6 +264,7 @@
// automatically included.
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"upstream-freebsd/lib/libc/gen/ldexp.c",
"upstream-freebsd/lib/libc/gen/sleep.c",
@@ -292,28 +276,26 @@
"upstream-freebsd/lib/libc/string/wcpcpy.c",
"upstream-freebsd/lib/libc/string/wcpncpy.c",
"upstream-freebsd/lib/libc/string/wcscasecmp.c",
+ "upstream-freebsd/lib/libc/string/wcscat.c",
+ "upstream-freebsd/lib/libc/string/wcschr.c",
+ "upstream-freebsd/lib/libc/string/wcscmp.c",
+ "upstream-freebsd/lib/libc/string/wcscpy.c",
"upstream-freebsd/lib/libc/string/wcscspn.c",
"upstream-freebsd/lib/libc/string/wcsdup.c",
"upstream-freebsd/lib/libc/string/wcslcat.c",
+ "upstream-freebsd/lib/libc/string/wcslen.c",
"upstream-freebsd/lib/libc/string/wcsncasecmp.c",
"upstream-freebsd/lib/libc/string/wcsncat.c",
"upstream-freebsd/lib/libc/string/wcsncmp.c",
"upstream-freebsd/lib/libc/string/wcsncpy.c",
"upstream-freebsd/lib/libc/string/wcsnlen.c",
"upstream-freebsd/lib/libc/string/wcspbrk.c",
+ "upstream-freebsd/lib/libc/string/wcsrchr.c",
"upstream-freebsd/lib/libc/string/wcsspn.c",
"upstream-freebsd/lib/libc/string/wcstok.c",
"upstream-freebsd/lib/libc/string/wmemchr.c",
- "upstream-freebsd/lib/libc/string/wmemset.c",
-
- // May be overriden by per-arch optimized versions
- "upstream-freebsd/lib/libc/string/wcscat.c",
- "upstream-freebsd/lib/libc/string/wcschr.c",
- "upstream-freebsd/lib/libc/string/wcscmp.c",
- "upstream-freebsd/lib/libc/string/wcscpy.c",
- "upstream-freebsd/lib/libc/string/wcslen.c",
- "upstream-freebsd/lib/libc/string/wcsrchr.c",
"upstream-freebsd/lib/libc/string/wmemcmp.c",
+ "upstream-freebsd/lib/libc/string/wmemset.c",
"upstream-freebsd/lib/libc/string/wmemmove.c",
],
arch: {
@@ -329,43 +311,36 @@
"upstream-freebsd/lib/libc/string/wcslen.c",
"upstream-freebsd/lib/libc/string/wcsrchr.c",
],
- },
- x86_sse3: {
- exclude_srcs: [
- "upstream-freebsd/lib/libc/string/wcscpy.c",
- "upstream-freebsd/lib/libc/string/wcscat.c",
- ],
- },
- x86_sse4: {
- exclude_srcs: [
- "upstream-freebsd/lib/libc/string/wmemcmp.c",
- ],
- },
- x86_64: {
- clang: use_clang_x86_64,
+ atom: {
+ exclude_srcs: [
+ "upstream-freebsd/lib/libc/string/wmemcmp.c",
+ ],
+ },
+ ssse3: {
+ exclude_srcs: [
+ "upstream-freebsd/lib/libc/string/wcscat.c",
+ "upstream-freebsd/lib/libc/string/wcscpy.c",
+ ],
+ },
+ sse4: {
+ exclude_srcs: [
+ "upstream-freebsd/lib/libc/string/wmemcmp.c",
+ ],
+ },
},
},
- cflags: libc_common_cflags + [
+ cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
"-include freebsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"upstream-freebsd/android/include",
],
name: "libc_freebsd",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
}
// ========================================================
@@ -377,6 +352,7 @@
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"upstream-netbsd/common/lib/libc/stdlib/random.c",
"upstream-netbsd/lib/libc/gen/ftw.c",
@@ -418,33 +394,19 @@
srcs: ["upstream-netbsd/common/lib/libc/hash/sha1/sha1.c"],
},
},
- cflags: libc_common_cflags + [
+ cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
"-DPOSIX_MISTAKE",
"-include netbsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"upstream-netbsd/android/include",
"upstream-netbsd/lib/libc/include",
],
name: "libc_netbsd",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
@@ -458,6 +420,7 @@
cc_library_static {
name: "libc_openbsd_ndk",
+ defaults: ["libc_defaults"],
srcs: [
"upstream-openbsd/lib/libc/compat-43/killpg.c",
"upstream-openbsd/lib/libc/gen/alarm.c",
@@ -500,11 +463,9 @@
"upstream-openbsd/lib/libc/locale/wctomb.c",
"upstream-openbsd/lib/libc/net/htonl.c",
"upstream-openbsd/lib/libc/net/htons.c",
- "upstream-openbsd/lib/libc/net/inet_addr.c",
"upstream-openbsd/lib/libc/net/inet_lnaof.c",
"upstream-openbsd/lib/libc/net/inet_makeaddr.c",
"upstream-openbsd/lib/libc/net/inet_netof.c",
- "upstream-openbsd/lib/libc/net/inet_network.c",
"upstream-openbsd/lib/libc/net/inet_ntoa.c",
"upstream-openbsd/lib/libc/net/inet_ntop.c",
"upstream-openbsd/lib/libc/net/inet_pton.c",
@@ -564,7 +525,6 @@
"upstream-openbsd/lib/libc/stdio/puts.c",
"upstream-openbsd/lib/libc/stdio/putwc.c",
"upstream-openbsd/lib/libc/stdio/putwchar.c",
- "upstream-openbsd/lib/libc/stdio/refill.c",
"upstream-openbsd/lib/libc/stdio/remove.c",
"upstream-openbsd/lib/libc/stdio/rewind.c",
"upstream-openbsd/lib/libc/stdio/rget.c",
@@ -636,16 +596,13 @@
"upstream-openbsd/lib/libc/string/wcswidth.c",
],
- cflags: libc_common_cflags + [
+ cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
"-Wno-unused-parameter",
"-include openbsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"private",
"stdio",
@@ -653,17 +610,6 @@
"upstream-openbsd/lib/libc/include",
"upstream-openbsd/lib/libc/gdtoa/",
],
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
@@ -673,6 +619,7 @@
// These files are built with the openbsd-compat.h header file
// automatically included.
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
// These two depend on getentropy_linux.c, which isn't in libc_ndk.a.
"upstream-openbsd/lib/libc/crypt/arc4random.c",
@@ -685,7 +632,6 @@
"upstream-openbsd/lib/libc/string/stpcpy.c",
"upstream-openbsd/lib/libc/string/stpncpy.c",
"upstream-openbsd/lib/libc/string/strcat.c",
- "upstream-openbsd/lib/libc/string/strcmp.c",
"upstream-openbsd/lib/libc/string/strcpy.c",
"upstream-openbsd/lib/libc/string/strlcat.c",
"upstream-openbsd/lib/libc/string/strlcpy.c",
@@ -703,133 +649,119 @@
arch: {
arm: {
exclude_srcs: [
- "upstream-openbsd/lib/libc/string/strcmp.c",
"upstream-openbsd/lib/libc/string/strcpy.c",
],
+ cortex_a7: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ cortex_a53: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ cortex_a53_a57: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ cortex_a8: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ cortex_a9: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ cortex_a15: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ denver: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
+ krait: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ ],
+ },
},
- cortex_a7: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- cortex_a53: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- cortex_a8: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- cortex_a9: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- cortex_a15: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- denver: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
- krait: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- ],
- },
-
arm64: {
exclude_srcs: [
"upstream-openbsd/lib/libc/string/memchr.c",
"upstream-openbsd/lib/libc/string/memmove.c",
"upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/strcmp.c",
"upstream-openbsd/lib/libc/string/strcpy.c",
"upstream-openbsd/lib/libc/string/strncmp.c",
],
},
- mips: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/strcmp.c",
- ],
- },
-
- mips64: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/strcmp.c",
- ],
- },
-
x86: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memchr.c",
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/memrchr.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/stpncpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- "upstream-openbsd/lib/libc/string/strcmp.c",
- "upstream-openbsd/lib/libc/string/strcpy.c",
- "upstream-openbsd/lib/libc/string/strncmp.c",
- "upstream-openbsd/lib/libc/string/strncpy.c",
- ],
- },
- x86_sse3: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/strlcat.c",
- "upstream-openbsd/lib/libc/string/strlcpy.c",
- "upstream-openbsd/lib/libc/string/strncat.c",
- ],
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memchr.c",
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/memrchr.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/stpncpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ "upstream-openbsd/lib/libc/string/strcpy.c",
+ "upstream-openbsd/lib/libc/string/strncmp.c",
+ "upstream-openbsd/lib/libc/string/strncpy.c",
+ ],
+ ssse3: {
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/strlcat.c",
+ "upstream-openbsd/lib/libc/string/strlcpy.c",
+ "upstream-openbsd/lib/libc/string/strncat.c",
+ ],
+ },
},
x86_64: {
- exclude_srcs: [
- "upstream-openbsd/lib/libc/string/memmove.c",
- "upstream-openbsd/lib/libc/string/stpcpy.c",
- "upstream-openbsd/lib/libc/string/stpncpy.c",
- "upstream-openbsd/lib/libc/string/strcat.c",
- "upstream-openbsd/lib/libc/string/strcmp.c",
- "upstream-openbsd/lib/libc/string/strcpy.c",
- "upstream-openbsd/lib/libc/string/strlcat.c",
- "upstream-openbsd/lib/libc/string/strlcpy.c",
- "upstream-openbsd/lib/libc/string/strncat.c",
- "upstream-openbsd/lib/libc/string/strncmp.c",
- "upstream-openbsd/lib/libc/string/strncpy.c",
- ],
- clang: use_clang_x86_64,
+ exclude_srcs: [
+ "upstream-openbsd/lib/libc/string/memmove.c",
+ "upstream-openbsd/lib/libc/string/stpcpy.c",
+ "upstream-openbsd/lib/libc/string/stpncpy.c",
+ "upstream-openbsd/lib/libc/string/strcat.c",
+ "upstream-openbsd/lib/libc/string/strcpy.c",
+ "upstream-openbsd/lib/libc/string/strlcat.c",
+ "upstream-openbsd/lib/libc/string/strlcpy.c",
+ "upstream-openbsd/lib/libc/string/strncat.c",
+ "upstream-openbsd/lib/libc/string/strncmp.c",
+ "upstream-openbsd/lib/libc/string/strncpy.c",
+ ],
},
},
- cflags: libc_common_cflags + [
+ cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
"-Wno-unused-parameter",
"-include openbsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"private",
"stdio",
@@ -839,12 +771,6 @@
],
name: "libc_openbsd",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
}
// ========================================================
@@ -855,6 +781,7 @@
// automatically included.
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"upstream-openbsd/android/gdtoa_support.cpp",
"upstream-openbsd/lib/libc/gdtoa/dmisc.c",
@@ -877,20 +804,17 @@
],
multilib: {
lib64: {
- srcs: ["upstream-openbsd/lib/libc/gdtoa/strtorQ.c"]
+ srcs: ["upstream-openbsd/lib/libc/gdtoa/strtorQ.c"],
},
},
- cflags: libc_common_cflags + [
+ cflags: [
"-Wno-sign-compare",
"-Wno-uninitialized",
"-fvisibility=hidden",
"-include openbsd-compat.h",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
local_include_dirs: [
"private",
"upstream-openbsd/android/include",
@@ -898,17 +822,6 @@
],
name: "libc_gdtoa",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
@@ -916,9 +829,11 @@
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
- // The fork implementation depends on pthread data, so we can't include
- // it in libc_ndk.a.
+ // The following implementations depend on pthread data, so we can't
+ // include them in libc_ndk.a.
+ "bionic/__cxa_thread_atexit_impl.cpp",
"bionic/fork.cpp",
// The data that backs getauxval is initialized in the libc init
@@ -933,26 +848,447 @@
"bionic/sysconf.cpp",
"bionic/vdso.cpp",
"bionic/setjmp_cookie.cpp",
+
+ "bionic/__memcpy_chk.cpp",
+ "bionic/__memset_chk.cpp",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ "bionic/strchr.cpp",
+ "bionic/strnlen.c",
+ "bionic/strrchr.cpp",
],
- cflags: libc_common_cflags + ["-Wframe-larger-than=2048"],
+ cflags: ["-Wframe-larger-than=2048"],
arch: {
+ arm: {
+ srcs: [
+ "arch-arm/bionic/abort_arm.S",
+ "arch-arm/bionic/atomics_arm.c",
+ "arch-arm/bionic/__bionic_clone.S",
+ "arch-arm/bionic/_exit_with_stack_teardown.S",
+ "arch-arm/bionic/libgcc_compat.c",
+ "arch-arm/bionic/popcount_tab.c",
+ "arch-arm/bionic/__restore.S",
+ "arch-arm/bionic/setjmp.S",
+ "arch-arm/bionic/syscall.S",
+ "arch-arm/bionic/vfork.S",
+
+ "arch-arm/generic/bionic/memcmp.S",
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ ],
+ exclude_srcs: [
+ "bionic/__memcpy_chk.cpp",
+ "bionic/__memset_chk.cpp",
+ ],
+ cortex_a7: {
+ srcs: [
+ "arch-arm/cortex-a7/bionic/memset.S",
+
+ "arch-arm/cortex-a15/bionic/memcpy.S",
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ cortex_a53: {
+ srcs: [
+ "arch-arm/cortex-a53/bionic/memcpy.S",
+ "arch-arm/cortex-a53/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a53/bionic/__strcpy_chk.S",
+
+ "arch-arm/cortex-a7/bionic/memset.S",
+
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ cortex_a53_a57: {
+ srcs: [
+ "arch-arm/cortex-a15/bionic/memcpy.S",
+ "arch-arm/cortex-a15/bionic/memset.S",
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ cortex_a8: {
+ srcs: [
+ "arch-arm/cortex-a15/bionic/memcpy.S",
+ "arch-arm/cortex-a15/bionic/memset.S",
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ cortex_a9: {
+ srcs: [
+ "arch-arm/cortex-a9/bionic/memcpy.S",
+ "arch-arm/cortex-a9/bionic/memset.S",
+ "arch-arm/cortex-a9/bionic/stpcpy.S",
+ "arch-arm/cortex-a9/bionic/strcat.S",
+ "arch-arm/cortex-a9/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a9/bionic/strcmp.S",
+ "arch-arm/cortex-a9/bionic/strcpy.S",
+ "arch-arm/cortex-a9/bionic/__strcpy_chk.S",
+ "arch-arm/cortex-a9/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ cortex_a15: {
+ srcs: [
+ "arch-arm/cortex-a15/bionic/memcpy.S",
+ "arch-arm/cortex-a15/bionic/memset.S",
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/__strcat_chk.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ denver: {
+ srcs: [
+ "arch-arm/denver/bionic/memcpy.S",
+ "arch-arm/denver/bionic/memmove.S",
+ "arch-arm/denver/bionic/memset.S",
+ "arch-arm/denver/bionic/__strcat_chk.S",
+ "arch-arm/denver/bionic/__strcpy_chk.S",
+
+ // Use cortex-a15 versions of strcat/strcpy/strlen.
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/strcmp.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+ krait: {
+ srcs: [
+ "arch-arm/krait/bionic/memcpy.S",
+ "arch-arm/krait/bionic/memset.S",
+ "arch-arm/krait/bionic/strcmp.S",
+ "arch-arm/krait/bionic/__strcat_chk.S",
+ "arch-arm/krait/bionic/__strcpy_chk.S",
+
+ // Use cortex-a15 versions of strcat/strcpy/strlen.
+ "arch-arm/cortex-a15/bionic/stpcpy.S",
+ "arch-arm/cortex-a15/bionic/strcat.S",
+ "arch-arm/cortex-a15/bionic/strcpy.S",
+ "arch-arm/cortex-a15/bionic/strlen.S",
+
+ "arch-arm/denver/bionic/memmove.S",
+ ],
+ exclude_srcs: [
+ "arch-arm/generic/bionic/memcpy.S",
+ "arch-arm/generic/bionic/memset.S",
+ "arch-arm/generic/bionic/strcmp.S",
+ "arch-arm/generic/bionic/strcpy.S",
+ "arch-arm/generic/bionic/strlen.c",
+ "bionic/__strcat_chk.cpp",
+ "bionic/__strcpy_chk.cpp",
+ ],
+ },
+
+ },
+ arm64: {
+ srcs: [
+ "arch-arm64/bionic/__bionic_clone.S",
+ "arch-arm64/bionic/_exit_with_stack_teardown.S",
+ "arch-arm64/bionic/setjmp.S",
+ "arch-arm64/bionic/__set_tls.c",
+ "arch-arm64/bionic/syscall.S",
+ "arch-arm64/bionic/vfork.S",
+
+ "arch-arm64/generic/bionic/memchr.S",
+ "arch-arm64/generic/bionic/memcmp.S",
+ "arch-arm64/generic/bionic/memcpy.S",
+ "arch-arm64/generic/bionic/memmove.S",
+ "arch-arm64/generic/bionic/memset.S",
+ "arch-arm64/generic/bionic/stpcpy.S",
+ "arch-arm64/generic/bionic/strchr.S",
+ "arch-arm64/generic/bionic/strcmp.S",
+ "arch-arm64/generic/bionic/strcpy.S",
+ "arch-arm64/generic/bionic/strlen.S",
+ "arch-arm64/generic/bionic/strncmp.S",
+ "arch-arm64/generic/bionic/strnlen.S",
+ "arch-arm64/generic/bionic/wmemmove.S",
+ ],
+ exclude_srcs: [
+ "bionic/__memcpy_chk.cpp",
+ "bionic/strchr.cpp",
+ "bionic/strnlen.c",
+ ],
+ denver64: {
+ srcs: [
+ "arch-arm64/denver64/bionic/memcpy.S",
+ "arch-arm64/denver64/bionic/memset.S",
+ ],
+ exclude_srcs: [
+ "arch-arm64/generic/bionic/memcpy.S",
+ "arch-arm64/generic/bionic/memset.S",
+ ],
+ },
+ },
+
+ mips: {
+ srcs: [
+ "arch-mips/bionic/__bionic_clone.S",
+ "arch-mips/bionic/bzero.S",
+ "arch-mips/bionic/cacheflush.cpp",
+ "arch-mips/bionic/_exit_with_stack_teardown.S",
+ "arch-mips/bionic/setjmp.S",
+ "arch-mips/bionic/syscall.S",
+ "arch-mips/bionic/vfork.S",
+
+ "arch-mips/string/memcmp.c",
+ "arch-mips/string/memcpy.S",
+ "arch-mips/string/memset.S",
+ "arch-mips/string/strcmp.S",
+ "arch-mips/string/strlen.c",
+ ],
+ rev6: {
+ srcs: [
+ "arch-mips/string/mips_strlen.c",
+ ],
+ exclude_srcs: [
+ "arch-mips/string/strlen.c",
+ ],
+ },
+ },
+ mips64: {
+ srcs: [
+ "arch-mips64/bionic/__bionic_clone.S",
+ "arch-mips64/bionic/_exit_with_stack_teardown.S",
+ "arch-mips64/bionic/setjmp.S",
+ "arch-mips64/bionic/syscall.S",
+ "arch-mips64/bionic/vfork.S",
+ "arch-mips64/bionic/stat.cpp",
+
+ "arch-mips/string/memcmp.c",
+ "arch-mips/string/memcpy.S",
+ "arch-mips/string/memset.S",
+ "arch-mips/string/strcmp.S",
+ "arch-mips/string/strlen.c",
+ ],
+ },
+
+ x86: {
+ srcs: [
+ "arch-x86/bionic/__bionic_clone.S",
+ "arch-x86/bionic/_exit_with_stack_teardown.S",
+ "arch-x86/bionic/libgcc_compat.c",
+ "arch-x86/bionic/__restore.S",
+ "arch-x86/bionic/setjmp.S",
+ "arch-x86/bionic/__set_tls.c",
+ "arch-x86/bionic/syscall.S",
+ "arch-x86/bionic/vfork.S",
+
+ "arch-x86/generic/string/memcmp.S",
+ "arch-x86/generic/string/strcmp.S",
+ "arch-x86/generic/string/strncmp.S",
+ "arch-x86/generic/string/strcat.S",
+ "arch-x86/atom/string/sse2-memchr-atom.S",
+ "arch-x86/atom/string/sse2-memrchr-atom.S",
+ "arch-x86/atom/string/sse2-strchr-atom.S",
+ "arch-x86/atom/string/sse2-strnlen-atom.S",
+ "arch-x86/atom/string/sse2-strrchr-atom.S",
+ "arch-x86/atom/string/sse2-wcschr-atom.S",
+ "arch-x86/atom/string/sse2-wcsrchr-atom.S",
+ "arch-x86/atom/string/sse2-wcslen-atom.S",
+ "arch-x86/atom/string/sse2-wcscmp-atom.S",
+ "arch-x86/silvermont/string/sse2-bcopy-slm.S",
+ "arch-x86/silvermont/string/sse2-bzero-slm.S",
+ "arch-x86/silvermont/string/sse2-memcpy-slm.S",
+ "arch-x86/silvermont/string/sse2-memmove-slm.S",
+ "arch-x86/silvermont/string/sse2-memset-slm.S",
+ "arch-x86/silvermont/string/sse2-stpcpy-slm.S",
+ "arch-x86/silvermont/string/sse2-stpncpy-slm.S",
+ "arch-x86/silvermont/string/sse2-strcpy-slm.S",
+ "arch-x86/silvermont/string/sse2-strlen-slm.S",
+ "arch-x86/silvermont/string/sse2-strncpy-slm.S",
+ ],
+
+ exclude_srcs: [
+ "bionic/strchr.cpp",
+ "bionic/strnlen.c",
+ "bionic/strrchr.cpp",
+ ],
+ atom: {
+ srcs: [
+ "arch-x86/atom/string/sse2-bzero-atom.S",
+ "arch-x86/atom/string/sse2-memset-atom.S",
+ "arch-x86/atom/string/sse2-strlen-atom.S",
+ "arch-x86/atom/string/ssse3-bcopy-atom.S",
+ "arch-x86/atom/string/ssse3-memcmp-atom.S",
+ "arch-x86/atom/string/ssse3-memmove-atom.S",
+ "arch-x86/atom/string/ssse3-strncpy-atom.S",
+ "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
+ ],
+ exclude_srcs: [
+ "arch-x86/generic/string/memcmp.S",
+ "arch-x86/silvermont/string/sse2-bcopy-slm.S",
+ "arch-x86/silvermont/string/sse2-bzero-slm.S",
+ "arch-x86/silvermont/string/sse2-memcpy-slm.S",
+ "arch-x86/silvermont/string/sse2-memmove-slm.S",
+ "arch-x86/silvermont/string/sse2-memset-slm.S",
+ "arch-x86/silvermont/string/sse2-strcpy-slm.S",
+ "arch-x86/silvermont/string/sse2-strlen-slm.S",
+ "arch-x86/silvermont/string/sse2-strncpy-slm.S",
+ ],
+ },
+ ssse3: {
+ srcs: [
+ "arch-x86/atom/string/ssse3-strncat-atom.S",
+ "arch-x86/atom/string/ssse3-strlcat-atom.S",
+ "arch-x86/atom/string/ssse3-strlcpy-atom.S",
+ "arch-x86/atom/string/ssse3-strcat-atom.S",
+ "arch-x86/atom/string/ssse3-strcmp-atom.S",
+ "arch-x86/atom/string/ssse3-strncmp-atom.S",
+ "arch-x86/atom/string/ssse3-wcscat-atom.S",
+ "arch-x86/atom/string/ssse3-wcscpy-atom.S",
+ ],
+ exclude_srcs: [
+ "arch-x86/generic/string/strcmp.S",
+ "arch-x86/generic/string/strncmp.S",
+ "arch-x86/generic/string/strcat.S",
+ ],
+ },
+ sse4: {
+ srcs: [
+ "arch-x86/silvermont/string/sse4-memcmp-slm.S",
+ "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
+ ],
+ exclude_srcs: [
+ "arch-x86/generic/string/memcmp.S",
+ ],
+ },
+ },
x86_64: {
- clang: use_clang_x86_64,
+ srcs: [
+ "arch-x86_64/bionic/__bionic_clone.S",
+ "arch-x86_64/bionic/_exit_with_stack_teardown.S",
+ "arch-x86_64/bionic/__restore_rt.S",
+ "arch-x86_64/bionic/setjmp.S",
+ "arch-x86_64/bionic/__set_tls.c",
+ "arch-x86_64/bionic/syscall.S",
+ "arch-x86_64/bionic/vfork.S",
+
+ "arch-x86_64/string/sse2-memcpy-slm.S",
+ "arch-x86_64/string/sse2-memmove-slm.S",
+ "arch-x86_64/string/sse2-memset-slm.S",
+ "arch-x86_64/string/sse2-stpcpy-slm.S",
+ "arch-x86_64/string/sse2-stpncpy-slm.S",
+ "arch-x86_64/string/sse2-strcat-slm.S",
+ "arch-x86_64/string/sse2-strcpy-slm.S",
+ "arch-x86_64/string/sse2-strlcat-slm.S",
+ "arch-x86_64/string/sse2-strlcpy-slm.S",
+ "arch-x86_64/string/sse2-strlen-slm.S",
+ "arch-x86_64/string/sse2-strncat-slm.S",
+ "arch-x86_64/string/sse2-strncpy-slm.S",
+ "arch-x86_64/string/sse4-memcmp-slm.S",
+ "arch-x86_64/string/ssse3-strcmp-slm.S",
+ "arch-x86_64/string/ssse3-strncmp-slm.S",
+ ],
},
},
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags + ["-Wold-style-cast"],
- product_variables: libc_common_product_variables,
+ cppflags: ["-Wold-style-cast"],
include_dirs: ["bionic/libstdc++/include"],
name: "libc_bionic",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
}
// ========================================================
@@ -961,11 +1297,13 @@
// or constructors).
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"bionic/abort.cpp",
"bionic/accept.cpp",
"bionic/accept4.cpp",
"bionic/access.cpp",
+ "bionic/arpa_inet.cpp",
"bionic/assert.cpp",
"bionic/atof.cpp",
"bionic/bionic_systrace.cpp",
@@ -1011,6 +1349,7 @@
"bionic/gettid.cpp",
"bionic/__gnu_basename.cpp",
"bionic/inotify_init.cpp",
+ "bionic/ioctl.cpp",
"bionic/lchown.cpp",
"bionic/lfs64_support.cpp",
"bionic/__libc_current_sigrtmax.cpp",
@@ -1030,6 +1369,7 @@
"bionic/mkfifo.cpp",
"bionic/mknod.cpp",
"bionic/mntent.cpp",
+ "bionic/mremap.cpp",
"bionic/NetdClientDispatch.cpp",
"bionic/open.cpp",
"bionic/pathconf.cpp",
@@ -1099,433 +1439,20 @@
"bionic/wchar.cpp",
"bionic/wctype.cpp",
"bionic/wmempcpy.cpp",
-
- // May be overriden by per-arch optimized versions
- "bionic/__memcpy_chk.cpp",
- "bionic/__memset_chk.cpp",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- "bionic/strchr.cpp",
- "bionic/strnlen.c",
- "bionic/strrchr.cpp",
],
- cflags: libc_common_cflags + ["-Wframe-larger-than=2048"],
+ cflags: ["-Wframe-larger-than=2048"],
- arch: {
-
- arm: {
- srcs: [
- "arch-arm/bionic/abort_arm.S",
- "arch-arm/bionic/atomics_arm.c",
- "arch-arm/bionic/__bionic_clone.S",
- "arch-arm/bionic/_exit_with_stack_teardown.S",
- "arch-arm/bionic/libgcc_compat.c",
- "arch-arm/bionic/popcount_tab.c",
- "arch-arm/bionic/__restore.S",
- "arch-arm/bionic/setjmp.S",
- "arch-arm/bionic/syscall.S",
- "arch-arm/bionic/vfork.S",
-
- "arch-arm/generic/bionic/memcmp.S",
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- ],
- exclude_srcs: [
- "bionic/__memcpy_chk.cpp",
- "bionic/__memset_chk.cpp",
- ],
- },
- cortex_a7: {
- srcs: [
- "arch-arm/cortex-a7/bionic/memset.S",
-
- "arch-arm/cortex-a15/bionic/memcpy.S",
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/__strcat_chk.S",
- "arch-arm/cortex-a15/bionic/strcmp.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- cortex_a53: {
- srcs: [
- "arch-arm/cortex-a53/bionic/memcpy.S",
- "arch-arm/cortex-a53/bionic/__strcat_chk.S",
- "arch-arm/cortex-a53/bionic/__strcpy_chk.S",
-
- "arch-arm/cortex-a7/bionic/memset.S",
-
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/strcmp.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- cortex_a8: {
- srcs: [
- "arch-arm/cortex-a15/bionic/memcpy.S",
- "arch-arm/cortex-a15/bionic/memset.S",
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/__strcat_chk.S",
- "arch-arm/cortex-a15/bionic/strcmp.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- cortex_a9: {
- srcs: [
- "arch-arm/cortex-a9/bionic/memcpy.S",
- "arch-arm/cortex-a9/bionic/memset.S",
- "arch-arm/cortex-a9/bionic/stpcpy.S",
- "arch-arm/cortex-a9/bionic/strcat.S",
- "arch-arm/cortex-a9/bionic/__strcat_chk.S",
- "arch-arm/cortex-a9/bionic/strcmp.S",
- "arch-arm/cortex-a9/bionic/strcpy.S",
- "arch-arm/cortex-a9/bionic/__strcpy_chk.S",
- "arch-arm/cortex-a9/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- cortex_a15: {
- srcs: [
- "arch-arm/cortex-a15/bionic/memcpy.S",
- "arch-arm/cortex-a15/bionic/memset.S",
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/__strcat_chk.S",
- "arch-arm/cortex-a15/bionic/strcmp.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- denver: {
- srcs: [
- "arch-arm/denver/bionic/memcpy.S",
- "arch-arm/denver/bionic/memmove.S",
- "arch-arm/denver/bionic/memset.S",
- "arch-arm/denver/bionic/__strcat_chk.S",
- "arch-arm/denver/bionic/__strcpy_chk.S",
-
- // Use cortex-a15 versions of strcat/strcpy/strlen.
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/strcmp.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
- krait: {
- srcs: [
- "arch-arm/krait/bionic/memcpy.S",
- "arch-arm/krait/bionic/memset.S",
- "arch-arm/krait/bionic/strcmp.S",
- "arch-arm/krait/bionic/__strcat_chk.S",
- "arch-arm/krait/bionic/__strcpy_chk.S",
-
- // Use cortex-a15 versions of strcat/strcpy/strlen.
- "arch-arm/cortex-a15/bionic/stpcpy.S",
- "arch-arm/cortex-a15/bionic/strcat.S",
- "arch-arm/cortex-a15/bionic/strcpy.S",
- "arch-arm/cortex-a15/bionic/strlen.S",
-
- "arch-arm/denver/bionic/memmove.S",
- ],
- exclude_srcs: [
- "arch-arm/generic/bionic/memcpy.S",
- "arch-arm/generic/bionic/memset.S",
- "arch-arm/generic/bionic/strcmp.S",
- "arch-arm/generic/bionic/strcpy.S",
- "arch-arm/generic/bionic/strlen.c",
- "bionic/__strcat_chk.cpp",
- "bionic/__strcpy_chk.cpp",
- ],
- },
-
- arm64: {
- srcs: [
- "arch-arm64/bionic/__bionic_clone.S",
- "arch-arm64/bionic/_exit_with_stack_teardown.S",
- "arch-arm64/bionic/setjmp.S",
- "arch-arm64/bionic/__set_tls.c",
- "arch-arm64/bionic/syscall.S",
- "arch-arm64/bionic/vfork.S",
-
- "arch-arm64/generic/bionic/memchr.S",
- "arch-arm64/generic/bionic/memcmp.S",
- "arch-arm64/generic/bionic/memcpy.S",
- "arch-arm64/generic/bionic/memmove.S",
- "arch-arm64/generic/bionic/memset.S",
- "arch-arm64/generic/bionic/stpcpy.S",
- "arch-arm64/generic/bionic/strchr.S",
- "arch-arm64/generic/bionic/strcmp.S",
- "arch-arm64/generic/bionic/strcpy.S",
- "arch-arm64/generic/bionic/strlen.S",
- "arch-arm64/generic/bionic/strncmp.S",
- "arch-arm64/generic/bionic/strnlen.S",
- "arch-arm64/generic/bionic/wmemmove.S",
- ],
- exclude_srcs: [
- "bionic/__memcpy_chk.cpp",
- "bionic/strchr.cpp",
- "bionic/strnlen.c",
- ],
- },
- denver64: {
- srcs: [
- "arch-arm64/denver64/bionic/memcpy.S",
- "arch-arm64/denver64/bionic/memset.S",
- ],
- exclude_srcs: [
- "arch-arm64/generic/bionic/memcpy.S",
- "arch-arm64/generic/bionic/memset.S",
- ],
- },
-
- mips: {
- srcs: [
- "arch-mips/bionic/__bionic_clone.S",
- "arch-mips/bionic/bzero.S",
- "arch-mips/bionic/cacheflush.cpp",
- "arch-mips/bionic/_exit_with_stack_teardown.S",
- "arch-mips/bionic/setjmp.S",
- "arch-mips/bionic/syscall.S",
- "arch-mips/bionic/vfork.S",
-
- "arch-mips/string/memcmp.c",
- "arch-mips/string/memcpy.S",
- "arch-mips/string/memset.S",
- "arch-mips/string/strcmp.S",
- "arch-mips/string/strlen.c",
- ],
- },
- mips_rev6: {
- srcs: [
- "arch-mips/string/mips_strlen.c"
- ],
- exclude_srcs: [
- "arch-mips/string/strlen.c"
- ],
- },
-
- mips64: {
- srcs: [
- "arch-mips64/bionic/__bionic_clone.S",
- "arch-mips64/bionic/_exit_with_stack_teardown.S",
- "arch-mips64/bionic/setjmp.S",
- "arch-mips64/bionic/syscall.S",
- "arch-mips64/bionic/vfork.S",
- "arch-mips64/bionic/stat.cpp",
-
- "arch-mips/string/memcmp.c",
- "arch-mips/string/memcpy.S",
- "arch-mips/string/memset.S",
- "arch-mips/string/strcmp.S",
- "arch-mips/string/strlen.c",
- ],
- },
-
- x86: {
- srcs: [
- "arch-x86/bionic/__bionic_clone.S",
- "arch-x86/bionic/_exit_with_stack_teardown.S",
- "arch-x86/bionic/libgcc_compat.c",
- "arch-x86/bionic/__restore.S",
- "arch-x86/bionic/setjmp.S",
- "arch-x86/bionic/__set_tls.c",
- "arch-x86/bionic/syscall.S",
- "arch-x86/bionic/vfork.S",
-
- "arch-x86/generic/string/memcmp.S",
- "arch-x86/generic/string/strcmp.S",
- "arch-x86/generic/string/strncmp.S",
- "arch-x86/generic/string/strcat.S",
- "arch-x86/atom/string/sse2-memchr-atom.S",
- "arch-x86/atom/string/sse2-memrchr-atom.S",
- "arch-x86/atom/string/sse2-strchr-atom.S",
- "arch-x86/atom/string/sse2-strnlen-atom.S",
- "arch-x86/atom/string/sse2-strrchr-atom.S",
- "arch-x86/atom/string/sse2-wcschr-atom.S",
- "arch-x86/atom/string/sse2-wcsrchr-atom.S",
- "arch-x86/atom/string/sse2-wcslen-atom.S",
- "arch-x86/atom/string/sse2-wcscmp-atom.S",
- "arch-x86/silvermont/string/sse2-bcopy-slm.S",
- "arch-x86/silvermont/string/sse2-bzero-slm.S",
- "arch-x86/silvermont/string/sse2-memcpy-slm.S",
- "arch-x86/silvermont/string/sse2-memmove-slm.S",
- "arch-x86/silvermont/string/sse2-memset-slm.S",
- "arch-x86/silvermont/string/sse2-stpcpy-slm.S",
- "arch-x86/silvermont/string/sse2-stpncpy-slm.S",
- "arch-x86/silvermont/string/sse2-strcpy-slm.S",
- "arch-x86/silvermont/string/sse2-strlen-slm.S",
- "arch-x86/silvermont/string/sse2-strncpy-slm.S",
- ],
- },
- x86_sse3: {
- srcs: [
- "arch-x86/atom/string/ssse3-strncat-atom.S",
- "arch-x86/atom/string/ssse3-strlcat-atom.S",
- "arch-x86/atom/string/ssse3-strlcpy-atom.S",
- "arch-x86/atom/string/ssse3-strcmp-atom.S",
- "arch-x86/atom/string/ssse3-strncmp-atom.S",
- "arch-x86/atom/string/ssse3-strcat-atom.S",
- "arch-x86/atom/string/ssse3-wcscat-atom.S",
- "arch-x86/atom/string/ssse3-wcscpy-atom.S",
- ],
- exclude_srcs: [
- "arch-x86/generic/string/strcmp.S",
- "arch-x86/generic/string/strncmp.S",
- "arch-x86/generic/string/strcat.S",
- ],
- },
- x86_sse4: {
- srcs: [
- "arch-x86/silvermont/string/sse4-memcmp-slm.S",
- "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
- ],
- exclude_srcs: [
- "arch-x86/generic/string/memcmp.S",
- ],
- },
-
-
- x86_64: {
- clang: use_clang_x86_64,
- srcs: [
- "arch-x86_64/bionic/__bionic_clone.S",
- "arch-x86_64/bionic/_exit_with_stack_teardown.S",
- "arch-x86_64/bionic/__restore_rt.S",
- "arch-x86_64/bionic/setjmp.S",
- "arch-x86_64/bionic/__set_tls.c",
- "arch-x86_64/bionic/syscall.S",
- "arch-x86_64/bionic/vfork.S",
-
- "arch-x86_64/string/sse2-memcpy-slm.S",
- "arch-x86_64/string/sse2-memmove-slm.S",
- "arch-x86_64/string/sse2-memset-slm.S",
- "arch-x86_64/string/sse2-stpcpy-slm.S",
- "arch-x86_64/string/sse2-stpncpy-slm.S",
- "arch-x86_64/string/sse2-strcat-slm.S",
- "arch-x86_64/string/sse2-strcpy-slm.S",
- "arch-x86_64/string/sse2-strlcat-slm.S",
- "arch-x86_64/string/sse2-strlcpy-slm.S",
- "arch-x86_64/string/sse2-strlen-slm.S",
- "arch-x86_64/string/sse2-strncat-slm.S",
- "arch-x86_64/string/sse2-strncpy-slm.S",
- "arch-x86_64/string/sse4-memcmp-slm.S",
- "arch-x86_64/string/ssse3-strcmp-slm.S",
- "arch-x86_64/string/ssse3-strncmp-slm.S",
- ],
- },
-
- },
multilib: {
lib32: {
// LP32 cruft
- srcs: ["bionic/mmap.cpp"]
+ srcs: ["bionic/mmap.cpp"],
},
},
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags + ["-Wold-style-cast"],
- product_variables: libc_common_product_variables,
+ cppflags: ["-Wold-style-cast"],
local_include_dirs: ["stdio"],
include_dirs: ["bionic/libstdc++/include"],
name: "libc_bionic_ndk",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
-}
-
-cc_library_static {
- name: "libc_thread_atexit_impl",
- srcs: ["bionic/__cxa_thread_atexit_impl.cpp"],
- cflags: libc_common_cflags + ["-Wframe-larger-than=2048"],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags + ["-Wold-style-cast"],
- product_variables: libc_common_product_variables,
- include_dirs: ["bionic/libstdc++/include"],
- // TODO: Clang tries to use __tls_get_addr which is not supported yet
- // remove after it is implemented.
- clang: false,
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
@@ -1537,9 +1464,11 @@
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"bionic/pthread_atfork.cpp",
"bionic/pthread_attr.cpp",
+ "bionic/pthread_barrier.cpp",
"bionic/pthread_cond.cpp",
"bionic/pthread_create.cpp",
"bionic/pthread_detach.cpp",
@@ -1559,25 +1488,13 @@
"bionic/pthread_setname_np.cpp",
"bionic/pthread_setschedparam.cpp",
"bionic/pthread_sigmask.cpp",
+ "bionic/pthread_spinlock.cpp",
],
- cflags: libc_common_cflags + ["-Wframe-larger-than=2048"],
+ cflags: ["-Wframe-larger-than=2048"],
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
-
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags + ["-Wold-style-cast"],
- product_variables: libc_common_product_variables,
+ cppflags: ["-Wold-style-cast"],
include_dirs: ["bionic/libstdc++/include"],
name: "libc_pthread",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
@@ -1585,21 +1502,17 @@
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"bionic/__cxa_guard.cpp",
"bionic/__cxa_pure_virtual.cpp",
"bionic/new.cpp",
],
- cflags: libc_common_cflags + ["-fvisibility=hidden"],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
+ cflags: ["-fvisibility=hidden"],
include_dirs: ["bionic/libstdc++/include"],
name: "libc_cxa",
clang: true, // GCC refuses to hide new/delete
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
// b/17574078: Need to disable coverage until we have a prebuilt libprofile_rt.
// Since this is a static library built with clang, it needs to link
// libprofile_rt when it is linked into the final binary. Since the final binary
@@ -1632,16 +1545,10 @@
srcs: ["arch-x86/syscalls/**/*.S"],
},
x86_64: {
- clang: use_clang_x86_64,
srcs: ["arch-x86_64/syscalls/**/*.S"],
},
},
name: "libc_syscalls",
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
@@ -1652,22 +1559,14 @@
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
arch: {
arm: {
srcs: ["arch-arm/bionic/__aeabi.c"],
},
- x86_64: {
- clang: use_clang_x86_64,
- },
},
name: "libc_aeabi",
- cflags: libc_common_cflags + ["-fno-builtin"],
- product_variables: libc_common_product_variables,
-
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
+ cflags: ["-fno-builtin"],
}
// ========================================================
@@ -1684,6 +1583,7 @@
cc_library_static {
name: "libc_ndk",
+ defaults: ["libc_defaults"],
srcs: libc_common_src_files + ["bionic/malloc_debug_common.cpp"],
multilib: {
lib32: {
@@ -1700,18 +1600,12 @@
],
whole_static_libs: ["libc_aeabi"],
},
- x86_64: {
- clang: use_clang_x86_64,
- },
},
- cflags: libc_common_cflags + [
+ cflags: [
"-fvisibility=hidden",
"-DLIBC_STATIC",
],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
whole_static_libs: [
"libc_bionic_ndk",
@@ -1726,14 +1620,6 @@
"libc_tzcode",
"libm",
],
-
- stl: "none",
- system_shared_libs: [],
-
- // TODO: split out the asflags.
- asflags: libc_common_cflags,
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
@@ -1741,16 +1627,13 @@
// ========================================================
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: libc_common_src_files,
multilib: {
lib32: {
srcs: libc_common_src_files_32,
},
},
- cflags: libc_common_cflags,
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
name: "libc_common",
whole_static_libs: [
@@ -1767,7 +1650,6 @@
"libc_pthread",
"libc_stack_protector",
"libc_syscalls",
- "libc_thread_atexit_impl",
"libc_tzcode",
],
@@ -1775,18 +1657,7 @@
arm: {
whole_static_libs: ["libc_aeabi"],
},
- x86_64: {
- clang: use_clang_x86_64,
- },
},
-
- stl: "none",
- system_shared_libs: [],
-
- // TODO: split out the asflags.
- asflags: libc_common_cflags,
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
@@ -1800,6 +1671,7 @@
// dynamic linker.
cc_library_static {
+ defaults: ["libc_defaults"],
srcs: [
"bionic/dl_iterate_phdr_static.cpp",
"bionic/libc_init_static.cpp",
@@ -1809,32 +1681,21 @@
arm: {
srcs: ["arch-arm/bionic/exidx_static.c"],
},
- x86_64: {
- clang: use_clang_x86_64,
- },
},
- cflags: libc_common_cflags + ["-DLIBC_STATIC"],
-
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
+ cflags: ["-DLIBC_STATIC"],
name: "libc_nomalloc",
whole_static_libs: ["libc_common"],
- stl: "none",
- system_shared_libs: [],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
}
// ========================================================
// libc_malloc.a: the _prefixed_ malloc functions (like dlcalloc).
// ========================================================
cc_library_static {
- product_variables: libc_common_product_variables + {
+ defaults: ["libc_defaults"],
+ product_variables: {
device_uses_jemalloc: {
srcs: ["bionic/jemalloc_wrapper.cpp"],
whole_static_libs: ["libjemalloc"],
@@ -1843,31 +1704,18 @@
srcs: ["bionic/dlmalloc.c"],
},
},
- cflags: libc_common_cflags + ["-fvisibility=hidden"],
+ cflags: ["-fvisibility=hidden"],
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
name: "libc_malloc",
- stl: "none",
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ========================================================
// libc.a + libc.so
// ========================================================
cc_library {
+ defaults: ["libc_defaults"],
name: "libc",
- cflags: libc_common_cflags,
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables + {
+ product_variables: {
platform_sdk_version: {
asflags: ["-DPLATFORM_SDK_VERSION=%d"],
},
@@ -1906,11 +1754,6 @@
shared_libs: ["libdl"],
whole_static_libs: ["libc_common"],
- stl: "none",
- system_shared_libs: [],
-
- // Don't re-export new/delete and friends, even if the compiler really wants to.
- version_script: "libc.map",
// We'd really like to do this for all architectures, but since this wasn't done
// before, these symbols must continue to be exported on LP32 for binary
@@ -1929,6 +1772,9 @@
//TODO: This is to work around b/24465209. Remove after root cause is fixed
ldflags: ["-Wl,--hash-style=both"],
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.arm.map",
+
shared: {
srcs: ["arch-arm/bionic/exidx_dynamic.c"],
},
@@ -1940,16 +1786,30 @@
"arch-arm/bionic/atexit_legacy.c",
],
},
+ arm64: {
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.arm64.map",
+ },
+ mips: {
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.mips.map",
+ },
+ mips64: {
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.mips64.map",
+ },
x86: {
//TODO: This is to work around b/24465209. Remove after root cause is fixed
ldflags: ["-Wl,--hash-style=both"],
+
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.x86.map",
},
x86_64: {
- clang: use_clang_x86_64,
+ // Don't re-export new/delete and friends, even if the compiler really wants to.
+ version_script: "libc.x86_64.map",
},
},
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// For all builds, except for the -user build we will enable memory
@@ -1964,10 +1824,7 @@
// libc_malloc_debug_leak.so
// ========================================================
cc_library_shared {
- cflags: libc_common_cflags,
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
+ defaults: ["libc_defaults"],
srcs: [
"bionic/debug_backtrace.cpp",
@@ -1983,8 +1840,6 @@
"libc",
"libdl",
],
- stl: "none",
- system_shared_libs: [],
// Only need this for arm since libc++ uses its own unwind code that
// doesn't mix with the other default unwind code.
arch: {
@@ -1995,9 +1850,6 @@
],
ldflags: ["-Wl,--exclude-libs,libunwind_llvm.a"],
},
- x86_64: {
- clang: use_clang_x86_64,
- },
},
allow_undefined_symbols: true,
@@ -2009,19 +1861,14 @@
"eng",
"debug",
],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
}
// ========================================================
// libc_malloc_debug_qemu.so
// ========================================================
cc_library_shared {
- cflags: libc_common_cflags + ["-DMALLOC_QEMU_INSTRUMENT"],
-
- conlyflags: libc_common_conlyflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
+ defaults: ["libc_defaults"],
+ cflags: ["-DMALLOC_QEMU_INSTRUMENT"],
srcs: [
"bionic/libc_logging.cpp",
@@ -2034,8 +1881,6 @@
"libc",
"libdl",
],
- stl: "none",
- system_shared_libs: [],
// Don't re-export new/delete and friends, even if the compiler really wants to.
version_script: "version_script.txt",
@@ -2045,14 +1890,6 @@
"eng",
"debug",
],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
-
- arch: {
- x86_64: {
- clang: use_clang_x86_64,
- },
- },
}
// ANDROIDMK TRANSLATION ERROR: unsupported directive
@@ -2063,10 +1900,8 @@
// libstdc++.so + libstdc++.a
// ========================================================
cc_library {
+ defaults: ["libc_defaults"],
include_dirs: ["bionic/libstdc++/include"],
- cflags: libc_common_cflags,
- cppflags: libc_common_cppflags,
- product_variables: libc_common_product_variables,
srcs: [
"bionic/__cxa_guard.cpp",
"bionic/__cxa_pure_virtual.cpp",
@@ -2074,11 +1909,7 @@
"bionic/libc_logging.cpp",
],
name: "libstdc++",
-
- stl: "none",
system_shared_libs: ["libc"],
- sanitize: ["never"],
- native_coverage: bionic_coverage,
//TODO: This is to work around b/24465209. Remove after root cause is fixed
arch: {
@@ -2091,46 +1922,50 @@
},
}
-crt_arch_flags = {
- arm: {
- local_include_dirs: ["arch-arm/include"],
- cflags: ["-mthumb-interwork"],
+cc_defaults {
+ name: "crt_defaults",
+
+ no_default_compiler_flags: true,
+
+ arch: {
+ arm: {
+ local_include_dirs: ["arch-arm/include"],
+ },
+ arm64: {
+ local_include_dirs: ["arch-arm64/include"],
+ },
+ mips: {
+ local_include_dirs: ["arch-mips/include"],
+ },
+ mips64: {
+ local_include_dirs: ["arch-mips64/include"],
+ },
+ x86: {
+ local_include_dirs: ["arch-x86/include"],
+ },
+ x86_64: {
+ local_include_dirs: ["arch-x86_64/include"],
+ },
},
- arm64: {
- local_include_dirs: ["arch-arm64/include"],
- },
- mips: {
- local_include_dirs: ["arch-mips/include"],
- ldflags: ["-melf32ltsmip"],
- },
- mips64: {
- local_include_dirs: ["arch-mips64/include"],
- ldflags: ["-melf64ltsmip"],
- },
- x86: {
- cflags: ["-m32"],
- ldflags: ["-melf_i386"],
- local_include_dirs: ["arch-x86/include"],
- },
- x86_64: {
- cflags: ["-m64"],
- ldflags: ["-melf_x86_64"],
- local_include_dirs: ["arch-x86_64/include"],
- },
+ clang: false,
}
-crt_arch_so_flags = crt_arch_flags + {
- mips: {
- cflags: ["-fPIC"],
- },
- mips64: {
- cflags: ["-fPIC"],
- },
- x86: {
- cflags: ["-fPIC"],
- },
- x86_64: {
- cflags: ["-fPIC"],
+cc_defaults {
+ name: "crt_so_defaults",
+
+ arch: {
+ mips: {
+ cflags: ["-fPIC"],
+ },
+ mips64: {
+ cflags: ["-fPIC"],
+ },
+ x86: {
+ cflags: ["-fPIC"],
+ },
+ x86_64: {
+ cflags: ["-fPIC"],
+ },
},
}
@@ -2163,9 +1998,11 @@
},
},
srcs: ["arch-common/bionic/crtbrand.S"],
- no_default_compiler_flags: true,
- arch: crt_arch_so_flags,
+ defaults: [
+ "crt_defaults",
+ "crt_so_defaults",
+ ],
}
// Android.mk:ignore
@@ -2173,17 +2010,21 @@
name: "crtbegin_so1",
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtbegin_so.c"],
- no_default_compiler_flags: true,
- arch: crt_arch_so_flags,
+ defaults: [
+ "crt_defaults",
+ "crt_so_defaults",
+ ],
}
// Android.mk:ignore
cc_object {
name: "crtbegin_so",
- no_default_compiler_flags: true,
- arch: crt_arch_so_flags,
+ defaults: [
+ "crt_defaults",
+ "crt_so_defaults",
+ ],
deps: [
"crtbegin_so1",
"crtbrand",
@@ -2195,9 +2036,11 @@
name: "crtend_so",
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtend_so.S"],
- no_default_compiler_flags: true,
- arch: crt_arch_so_flags,
+ defaults: [
+ "crt_defaults",
+ "crt_so_defaults",
+ ],
}
// Android.mk:ignore
@@ -2205,9 +2048,8 @@
name: "crtbegin_static1",
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtbegin.c"],
- no_default_compiler_flags: true,
- arch: crt_arch_flags + {
+ arch: {
arm64: {
srcs: [
"arch-arm64/bionic/crtbegin.c",
@@ -2233,18 +2075,19 @@
],
},
},
+
+ defaults: ["crt_defaults"],
}
// Android.mk:ignore
cc_object {
name: "crtbegin_static",
- no_default_compiler_flags: true,
- arch: crt_arch_flags,
deps: [
"crtbegin_static1",
"crtbrand",
],
+ defaults: ["crt_defaults"],
}
// Android.mk:ignore
@@ -2252,9 +2095,8 @@
name: "crtbegin_dynamic1",
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtbegin.c"],
- no_default_compiler_flags: true,
- arch: crt_arch_flags + {
+ arch: {
arm64: {
srcs: [
"arch-arm64/bionic/crtbegin.c",
@@ -2280,18 +2122,18 @@
],
},
},
+ defaults: ["crt_defaults"],
}
// Android.mk:ignore
cc_object {
name: "crtbegin_dynamic",
- no_default_compiler_flags: true,
- arch: crt_arch_flags,
deps: [
"crtbegin_dynamic1",
"crtbrand",
],
+ defaults: ["crt_defaults"],
}
// Android.mk:ignore
@@ -2301,7 +2143,6 @@
name: "crtend_android",
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtend.S"],
- no_default_compiler_flags: true,
- arch: crt_arch_flags,
+ defaults: ["crt_defaults"],
}
diff --git a/libc/Android.mk b/libc/Android.mk
index 140ec82..ba3e5aa 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -47,7 +47,6 @@
bionic/if_indextoname.c \
bionic/if_nametoindex.c \
bionic/initgroups.c \
- bionic/ioctl.c \
bionic/isatty.c \
bionic/memmem.c \
bionic/pututline.c \
@@ -151,6 +150,7 @@
bionic/gettid.cpp \
bionic/__gnu_basename.cpp \
bionic/inotify_init.cpp \
+ bionic/ioctl.cpp \
bionic/lchown.cpp \
bionic/lfs64_support.cpp \
bionic/__libc_current_sigrtmax.cpp \
@@ -170,6 +170,7 @@
bionic/mkfifo.cpp \
bionic/mknod.cpp \
bionic/mntent.cpp \
+ bionic/mremap.cpp \
bionic/NetdClientDispatch.cpp \
bionic/open.cpp \
bionic/pathconf.cpp \
@@ -242,9 +243,11 @@
libc_bionic_src_files :=
-# The fork implementation depends on pthread data, so we can't include it in
-# libc_ndk.a.
-libc_bionic_src_files += bionic/fork.cpp
+# The following implementations depend on pthread data, so we can't include
+# them in libc_ndk.a.
+libc_bionic_src_files += \
+ bionic/__cxa_thread_atexit_impl.cpp \
+ bionic/fork.cpp \
# 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
@@ -258,6 +261,15 @@
libc_bionic_src_files += bionic/vdso.cpp
libc_bionic_src_files += bionic/setjmp_cookie.cpp
+libc_bionic_src_files += \
+ bionic/__memcpy_chk.cpp \
+ bionic/__memset_chk.cpp \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+ bionic/strchr.cpp \
+ bionic/strnlen.c \
+ bionic/strrchr.cpp \
+
libc_cxa_src_files := \
bionic/__cxa_guard.cpp \
bionic/__cxa_pure_virtual.cpp \
@@ -274,18 +286,26 @@
upstream-freebsd/lib/libc/string/wcpcpy.c \
upstream-freebsd/lib/libc/string/wcpncpy.c \
upstream-freebsd/lib/libc/string/wcscasecmp.c \
+ upstream-freebsd/lib/libc/string/wcscat.c \
+ upstream-freebsd/lib/libc/string/wcschr.c \
+ upstream-freebsd/lib/libc/string/wcscmp.c \
+ upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wcscspn.c \
upstream-freebsd/lib/libc/string/wcsdup.c \
upstream-freebsd/lib/libc/string/wcslcat.c \
+ upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcsncasecmp.c \
upstream-freebsd/lib/libc/string/wcsncat.c \
upstream-freebsd/lib/libc/string/wcsncmp.c \
upstream-freebsd/lib/libc/string/wcsncpy.c \
upstream-freebsd/lib/libc/string/wcsnlen.c \
upstream-freebsd/lib/libc/string/wcspbrk.c \
+ upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wcsspn.c \
upstream-freebsd/lib/libc/string/wcstok.c \
upstream-freebsd/lib/libc/string/wmemchr.c \
+ upstream-freebsd/lib/libc/string/wmemcmp.c \
+ upstream-freebsd/lib/libc/string/wmemmove.c \
upstream-freebsd/lib/libc/string/wmemset.c \
libc_upstream_netbsd_src_files := \
@@ -355,6 +375,20 @@
upstream-openbsd/lib/libc/crypt/arc4random.c \
upstream-openbsd/lib/libc/crypt/arc4random_uniform.c \
+libc_upstream_openbsd_src_files += \
+ upstream-openbsd/lib/libc/string/memchr.c \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/memrchr.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/stpncpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+ upstream-openbsd/lib/libc/string/strcpy.c \
+ upstream-openbsd/lib/libc/string/strlcat.c \
+ upstream-openbsd/lib/libc/string/strlcpy.c \
+ upstream-openbsd/lib/libc/string/strncat.c \
+ upstream-openbsd/lib/libc/string/strncmp.c \
+ upstream-openbsd/lib/libc/string/strncpy.c \
+
libc_upstream_openbsd_ndk_src_files := \
upstream-openbsd/lib/libc/compat-43/killpg.c \
upstream-openbsd/lib/libc/gen/alarm.c \
@@ -532,6 +566,7 @@
libc_pthread_src_files := \
bionic/pthread_atfork.cpp \
bionic/pthread_attr.cpp \
+ bionic/pthread_barrier.cpp \
bionic/pthread_cond.cpp \
bionic/pthread_create.cpp \
bionic/pthread_detach.cpp \
@@ -551,9 +586,7 @@
bionic/pthread_setname_np.cpp \
bionic/pthread_setschedparam.cpp \
bionic/pthread_sigmask.cpp \
-
-libc_thread_atexit_impl_src_files := \
- bionic/__cxa_thread_atexit_impl.cpp \
+ bionic/pthread_spinlock.cpp \
libc_arch_static_src_files := \
bionic/dl_iterate_phdr_static.cpp \
@@ -591,6 +624,11 @@
use_clang := false
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),)
use_clang := false
endif
@@ -693,6 +731,7 @@
LOCAL_CFLAGS += -DALL_STATE
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
LOCAL_CFLAGS += -DSTD_INSPIRED
+# Obviously, we want to be thread-safe.
LOCAL_CFLAGS += -DTHREAD_SAFE
# The name of the tm_gmtoff field in our struct tm.
LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
@@ -700,6 +739,8 @@
LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
# Include timezone and daylight globals.
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 += -Dlint
@@ -794,7 +835,7 @@
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_SRC_FILES,libc_freebsd_src_files))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES_EXCLUDE,libc_freebsd_src_files_exclude))
include $(BUILD_STATIC_LIBRARY)
@@ -909,6 +950,7 @@
$(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))
include $(BUILD_STATIC_LIBRARY)
@@ -972,6 +1014,7 @@
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES_EXCLUDE,libc_bionic_src_files_exclude))
include $(BUILD_STATIC_LIBRARY)
@@ -1002,24 +1045,6 @@
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files))
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
@@ -1217,7 +1242,6 @@
libc_pthread \
libc_stack_protector \
libc_syscalls \
- libc_thread_atexit_impl \
libc_tzcode \
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
@@ -1353,7 +1377,12 @@
LOCAL_REQUIRED_MODULES := tzdata
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(libc_common_additional_dependencies) \
- $(LOCAL_PATH)/libc.map \
+ $(LOCAL_PATH)/libc.arm.map \
+ $(LOCAL_PATH)/libc.arm64.map \
+ $(LOCAL_PATH)/libc.mips.map \
+ $(LOCAL_PATH)/libc.mips64.map \
+ $(LOCAL_PATH)/libc.x86.map \
+ $(LOCAL_PATH)/libc.x86_64.map \
# Leave the symbols in the shared library so that stack unwinders can produce
# meaningful name resolution.
@@ -1380,8 +1409,17 @@
LOCAL_CXX_STL := none
LOCAL_SYSTEM_SHARED_LIBRARIES :=
+# TODO: This is to work around b/24465209. Remove after root cause is fixed
+LOCAL_LDFLAGS_arm := -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.
-LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libc.map
+LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.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_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.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
# before, these symbols must continue to be exported on LP32 for binary
@@ -1392,10 +1430,6 @@
# prevent the build system from using this flag.
LOCAL_NO_EXCLUDE_LIBS := true
-# TODO: This is to work around b/24465209. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
-LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
-
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 4188c15..526b6d0 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -107,7 +107,7 @@
int ___close:close(int) all
pid_t __getpid:getpid() all
int munmap(void*, size_t) all
-void* mremap(void*, size_t, size_t, unsigned long) all
+void* ___mremap:mremap(void*, size_t, size_t, int, void*) all
int msync(const void*, size_t, int) all
int mprotect(const void*, size_t, int) all
int madvise(void*, size_t, int) all
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 58c5eb6..76f465e 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -1,33 +1,19 @@
# 32-bit arm.
-#
-# Default implementations of functions that are commonly optimized.
-#
-
libc_bionic_src_files_arm += \
- bionic/strchr.cpp \
- bionic/strnlen.c \
- bionic/strrchr.cpp \
+ arch-arm/generic/bionic/memcmp.S \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
-libc_freebsd_src_files_arm += \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-freebsd/lib/libc/string/wcschr.c \
- upstream-freebsd/lib/libc/string/wcscmp.c \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcslen.c \
- upstream-freebsd/lib/libc/string/wcsrchr.c \
- upstream-freebsd/lib/libc/string/wmemcmp.c \
- upstream-freebsd/lib/libc/string/wmemmove.c \
+libc_bionic_src_files_exclude_arm += \
+ bionic/__memcpy_chk.cpp \
+ bionic/__memset_chk.cpp \
-libc_openbsd_src_files_arm += \
- upstream-openbsd/lib/libc/string/memchr.c \
- upstream-openbsd/lib/libc/string/memrchr.c \
- upstream-openbsd/lib/libc/string/stpncpy.c \
- upstream-openbsd/lib/libc/string/strlcat.c \
- upstream-openbsd/lib/libc/string/strlcpy.c \
- upstream-openbsd/lib/libc/string/strncat.c \
- upstream-openbsd/lib/libc/string/strncmp.c \
- upstream-openbsd/lib/libc/string/strncpy.c \
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/strcpy.c \
#
# Inherently architecture-specific code.
@@ -52,6 +38,7 @@
ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
$(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
endif
+ifneq ($(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT),generic)
cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
@@ -60,6 +47,7 @@
libc_common_additional_dependencies += $(cpu_variant_mk)
cpu_variant_mk :=
+endif
libc_crt_target_cflags_arm := \
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index a119529..464f7d8 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -151,7 +151,10 @@
// Save core registers.
add r1, r0, #(_JB_CORE_BASE * 4)
m_mangle_registers r2
- stmia r1, {r4-r14}
+
+ // ARM deprecates using sp in the register list for stmia.
+ stmia r1, {r4-r12, lr}
+ str sp, [r1, #(10 * 4)]
m_unmangle_registers r2
// Save floating-point registers.
@@ -204,7 +207,10 @@
ldr r3, [r0, #(_JB_SIGFLAG * 4)]
bic r3, r3, #1
add r2, r0, #(_JB_CORE_BASE * 4)
- ldmia r2, {r4-r14}
+
+ // ARM deprecates using sp in the register list for ldmia.
+ ldmia r2, {r4-r12, lr}
+ ldr sp, [r2, #(10 * 4)]
m_unmangle_registers r3
// Save the return value/address and check the setjmp cookie.
diff --git a/libc/arch-arm/cortex-a15/cortex-a15.mk b/libc/arch-arm/cortex-a15/cortex-a15.mk
index 6fa3270..20202a7 100644
--- a/libc/arch-arm/cortex-a15/cortex-a15.mk
+++ b/libc/arch-arm/cortex-a15/cortex-a15.mk
@@ -1,3 +1,17 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/memset.S \
@@ -10,7 +24,4 @@
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a53.a57/cortex-a53.a57.mk b/libc/arch-arm/cortex-a53.a57/cortex-a53.a57.mk
index 0eec165..6455d04 100644
--- a/libc/arch-arm/cortex-a53.a57/cortex-a53.a57.mk
+++ b/libc/arch-arm/cortex-a53.a57/cortex-a53.a57.mk
@@ -3,6 +3,20 @@
# The cortex-a7 optimized routines, and the cortex-a53 optimized routines
# decrease performance on cortex-a57 processors by as much as 20%.
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/memset.S \
@@ -15,7 +29,4 @@
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a53/cortex-a53.mk b/libc/arch-arm/cortex-a53/cortex-a53.mk
index bb00433..9b431ae 100644
--- a/libc/arch-arm/cortex-a53/cortex-a53.mk
+++ b/libc/arch-arm/cortex-a53/cortex-a53.mk
@@ -1,3 +1,17 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/cortex-a53/bionic/memcpy.S \
arch-arm/cortex-a53/bionic/__strcat_chk.S \
@@ -14,7 +28,4 @@
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a7/cortex-a7.mk b/libc/arch-arm/cortex-a7/cortex-a7.mk
index b6af4da..f570d0f 100644
--- a/libc/arch-arm/cortex-a7/cortex-a7.mk
+++ b/libc/arch-arm/cortex-a7/cortex-a7.mk
@@ -1,3 +1,17 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/cortex-a7/bionic/memset.S \
@@ -12,7 +26,4 @@
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a9/cortex-a9.mk b/libc/arch-arm/cortex-a9/cortex-a9.mk
index 7b38de1..8a26d6b 100644
--- a/libc/arch-arm/cortex-a9/cortex-a9.mk
+++ b/libc/arch-arm/cortex-a9/cortex-a9.mk
@@ -1,3 +1,18 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+ upstream-openbsd/lib/libc/string/strcpy.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/cortex-a9/bionic/memcpy.S \
arch-arm/cortex-a9/bionic/memset.S \
@@ -10,7 +25,4 @@
arch-arm/cortex-a9/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/denver/denver.mk b/libc/arch-arm/denver/denver.mk
index 5fddf95..f167991 100644
--- a/libc/arch-arm/denver/denver.mk
+++ b/libc/arch-arm/denver/denver.mk
@@ -1,5 +1,18 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
arch-arm/denver/bionic/memcpy.S \
arch-arm/denver/bionic/memmove.S \
arch-arm/denver/bionic/memset.S \
diff --git a/libc/arch-arm/generic/generic.mk b/libc/arch-arm/generic/generic.mk
deleted file mode 100644
index e49d6d2..0000000
--- a/libc/arch-arm/generic/generic.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
- arch-arm/generic/bionic/memcpy.S \
- arch-arm/generic/bionic/memset.S \
- arch-arm/generic/bionic/strcmp.S \
- arch-arm/generic/bionic/strcpy.S \
- arch-arm/generic/bionic/strlen.c \
- bionic/__strcat_chk.cpp \
- bionic/__strcpy_chk.cpp \
-
-libc_openbsd_src_files_arm += \
- upstream-openbsd/lib/libc/string/memmove.c \
- upstream-openbsd/lib/libc/string/stpcpy.c \
- upstream-openbsd/lib/libc/string/strcat.c \
diff --git a/libc/arch-arm/krait/krait.mk b/libc/arch-arm/krait/krait.mk
index 88b4d66..f8e3452 100644
--- a/libc/arch-arm/krait/krait.mk
+++ b/libc/arch-arm/krait/krait.mk
@@ -1,3 +1,18 @@
+libc_openbsd_src_files_exclude_arm += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+
+libc_bionic_src_files_exclude_arm += \
+ arch-arm/generic/bionic/memcpy.S \
+ arch-arm/generic/bionic/memset.S \
+ arch-arm/generic/bionic/strcmp.S \
+ arch-arm/generic/bionic/strcpy.S \
+ arch-arm/generic/bionic/strlen.c \
+ bionic/__strcat_chk.cpp \
+ bionic/__strcpy_chk.cpp \
+
libc_bionic_src_files_arm += \
arch-arm/krait/bionic/memcpy.S \
arch-arm/krait/bionic/memset.S \
@@ -13,7 +28,4 @@
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
- arch-arm/generic/bionic/memcmp.S \
-
-libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/syscalls/___mremap.S b/libc/arch-arm/syscalls/___mremap.S
new file mode 100644
index 0000000..ade8d78
--- /dev/null
+++ b/libc/arch-arm/syscalls/___mremap.S
@@ -0,0 +1,23 @@
+/* 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
diff --git a/libc/arch-arm/syscalls/mremap.S b/libc/arch-arm/syscalls/mremap.S
deleted file mode 100644
index 505ea3c..0000000
--- a/libc/arch-arm/syscalls/mremap.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 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)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 470a038..0811c96 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -1,32 +1,38 @@
# 64-bit arm.
#
-# Default implementations of functions that are commonly optimized.
+# Generic arm64 optimizations, may be overriden by CPU variants.
#
libc_bionic_src_files_arm64 += \
- bionic/__memset_chk.cpp \
- bionic/__strcpy_chk.cpp \
- bionic/__strcat_chk.cpp \
- bionic/strrchr.cpp \
+ arch-arm64/generic/bionic/memchr.S \
+ arch-arm64/generic/bionic/memcmp.S \
+ arch-arm64/generic/bionic/memcpy.S \
+ arch-arm64/generic/bionic/memmove.S \
+ arch-arm64/generic/bionic/memset.S \
+ arch-arm64/generic/bionic/stpcpy.S \
+ arch-arm64/generic/bionic/strchr.S \
+ arch-arm64/generic/bionic/strcmp.S \
+ arch-arm64/generic/bionic/strcpy.S \
+ arch-arm64/generic/bionic/strlen.S \
+ arch-arm64/generic/bionic/strncmp.S \
+ arch-arm64/generic/bionic/strnlen.S \
+ arch-arm64/generic/bionic/wmemmove.S \
-libc_freebsd_src_files_arm64 += \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-freebsd/lib/libc/string/wcschr.c \
- upstream-freebsd/lib/libc/string/wcscmp.c \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcslen.c \
- upstream-freebsd/lib/libc/string/wcsrchr.c \
- upstream-freebsd/lib/libc/string/wmemcmp.c \
+libc_bionic_src_files_exclude_arm64 += \
+ bionic/__memcpy_chk.cpp \
+ bionic/strchr.cpp \
+ bionic/strnlen.c \
-libc_openbsd_src_files_arm64 += \
- upstream-openbsd/lib/libc/string/memrchr.c \
- upstream-openbsd/lib/libc/string/stpncpy.c \
- upstream-openbsd/lib/libc/string/strcat.c \
- upstream-openbsd/lib/libc/string/strlcat.c \
- upstream-openbsd/lib/libc/string/strlcpy.c \
- upstream-openbsd/lib/libc/string/strncat.c \
- upstream-openbsd/lib/libc/string/strncpy.c \
+libc_freebsd_src_files_exclude_arm64 += \
+ upstream-freebsd/lib/libc/string/wmemmove.c \
+
+libc_openbsd_src_files_exclude_arm64 += \
+ upstream-openbsd/lib/libc/string/memchr.c \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/strcpy.c \
+ upstream-openbsd/lib/libc/string/strncmp.c \
#
# Inherently architecture-specific code.
@@ -54,6 +60,7 @@
ifeq ($(strip $(TARGET_CPU_VARIANT)),)
$(warning TARGET_ARCH is arm64, but TARGET_CPU_VARIANT is not defined)
endif
+ifneq ($(TARGET_CPU_VARIANT),generic)
cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
@@ -62,3 +69,4 @@
libc_common_additional_dependencies += $(cpu_variant_mk)
cpu_variant_mk :=
+endif
diff --git a/libc/arch-arm64/cortex-a53/cortex-a53.mk b/libc/arch-arm64/cortex-a53/cortex-a53.mk
index 676e886..e69de29 100644
--- a/libc/arch-arm64/cortex-a53/cortex-a53.mk
+++ b/libc/arch-arm64/cortex-a53/cortex-a53.mk
@@ -1 +0,0 @@
-include bionic/libc/arch-arm64/generic/generic.mk
diff --git a/libc/arch-arm64/denver64/denver64.mk b/libc/arch-arm64/denver64/denver64.mk
index d619c11..703af45 100644
--- a/libc/arch-arm64/denver64/denver64.mk
+++ b/libc/arch-arm64/denver64/denver64.mk
@@ -1,14 +1,7 @@
libc_bionic_src_files_arm64 += \
- arch-arm64/generic/bionic/memchr.S \
- arch-arm64/generic/bionic/memcmp.S \
arch-arm64/denver64/bionic/memcpy.S \
- arch-arm64/generic/bionic/memmove.S \
arch-arm64/denver64/bionic/memset.S \
- arch-arm64/generic/bionic/stpcpy.S \
- arch-arm64/generic/bionic/strchr.S \
- arch-arm64/generic/bionic/strcmp.S \
- arch-arm64/generic/bionic/strcpy.S \
- arch-arm64/generic/bionic/strlen.S \
- arch-arm64/generic/bionic/strncmp.S \
- arch-arm64/generic/bionic/strnlen.S \
- arch-arm64/generic/bionic/wmemmove.S
+
+libc_bionic_src_files_exclude_arm64 += \
+ arch-arm64/generic/bionic/memcpy.S \
+ arch-arm64/generic/bionic/memset.S \
diff --git a/libc/arch-arm64/generic/generic.mk b/libc/arch-arm64/generic/generic.mk
deleted file mode 100644
index 1b595aa..0000000
--- a/libc/arch-arm64/generic/generic.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-libc_bionic_src_files_arm64 += \
- arch-arm64/generic/bionic/memchr.S \
- arch-arm64/generic/bionic/memcmp.S \
- arch-arm64/generic/bionic/memcpy.S \
- arch-arm64/generic/bionic/memmove.S \
- arch-arm64/generic/bionic/memset.S \
- arch-arm64/generic/bionic/stpcpy.S \
- arch-arm64/generic/bionic/strchr.S \
- arch-arm64/generic/bionic/strcmp.S \
- arch-arm64/generic/bionic/strcpy.S \
- arch-arm64/generic/bionic/strlen.S \
- arch-arm64/generic/bionic/strncmp.S \
- arch-arm64/generic/bionic/strnlen.S \
- arch-arm64/generic/bionic/wmemmove.S
diff --git a/libc/arch-arm64/syscalls/mremap.S b/libc/arch-arm64/syscalls/___mremap.S
similarity index 81%
rename from libc/arch-arm64/syscalls/mremap.S
rename to libc/arch-arm64/syscalls/___mremap.S
index 69b91d6..aeb93bc 100644
--- a/libc/arch-arm64/syscalls/mremap.S
+++ b/libc/arch-arm64/syscalls/___mremap.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(mremap)
+ENTRY(___mremap)
mov x8, __NR_mremap
svc #0
@@ -11,4 +11,5 @@
b.hi __set_errno_internal
ret
-END(mremap)
+END(___mremap)
+.hidden ___mremap
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 05e7198..b184abb 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -1,45 +1,10 @@
# 32-bit mips.
-#
-# Default implementations of functions that are commonly optimized.
-#
-
libc_bionic_src_files_mips += \
arch-mips/string/memcmp.c \
arch-mips/string/memcpy.S \
arch-mips/string/memset.S \
arch-mips/string/strcmp.S \
- bionic/__memcpy_chk.cpp \
- bionic/__memset_chk.cpp \
- bionic/__strcpy_chk.cpp \
- bionic/__strcat_chk.cpp \
- bionic/strchr.cpp \
- bionic/strnlen.c \
- bionic/strrchr.cpp \
-
-libc_freebsd_src_files_mips += \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-freebsd/lib/libc/string/wcschr.c \
- upstream-freebsd/lib/libc/string/wcscmp.c \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcslen.c \
- upstream-freebsd/lib/libc/string/wcsrchr.c \
- upstream-freebsd/lib/libc/string/wmemcmp.c \
- upstream-freebsd/lib/libc/string/wmemmove.c \
-
-libc_openbsd_src_files_mips += \
- upstream-openbsd/lib/libc/string/memchr.c \
- upstream-openbsd/lib/libc/string/memmove.c \
- upstream-openbsd/lib/libc/string/memrchr.c \
- upstream-openbsd/lib/libc/string/stpcpy.c \
- upstream-openbsd/lib/libc/string/stpncpy.c \
- upstream-openbsd/lib/libc/string/strcat.c \
- upstream-openbsd/lib/libc/string/strcpy.c \
- upstream-openbsd/lib/libc/string/strlcat.c \
- upstream-openbsd/lib/libc/string/strlcpy.c \
- upstream-openbsd/lib/libc/string/strncat.c \
- upstream-openbsd/lib/libc/string/strncmp.c \
- upstream-openbsd/lib/libc/string/strncpy.c \
#
# Inherently architecture-specific code.
diff --git a/libc/arch-mips/syscalls/mremap.S b/libc/arch-mips/syscalls/___mremap.S
similarity index 84%
rename from libc/arch-mips/syscalls/mremap.S
rename to libc/arch-mips/syscalls/___mremap.S
index 7cbb94e..82e2eb3 100644
--- a/libc/arch-mips/syscalls/mremap.S
+++ b/libc/arch-mips/syscalls/___mremap.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(mremap)
+ENTRY(___mremap)
.set noreorder
.cpload t9
li v0, __NR_mremap
@@ -16,4 +16,5 @@
j t9
nop
.set reorder
-END(mremap)
+END(___mremap)
+.hidden ___mremap
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 7757385..20ee639 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -1,46 +1,11 @@
# 64-bit mips.
-#
-# Default implementations of functions that are commonly optimized.
-#
-
libc_bionic_src_files_mips64 += \
arch-mips/string/memcmp.c \
arch-mips/string/memcpy.S \
arch-mips/string/memset.S \
arch-mips/string/strcmp.S \
arch-mips/string/strlen.c \
- bionic/__memcpy_chk.cpp \
- bionic/__memset_chk.cpp \
- bionic/__strcpy_chk.cpp \
- bionic/__strcat_chk.cpp \
- bionic/strchr.cpp \
- bionic/strnlen.c \
- bionic/strrchr.cpp \
-
-libc_freebsd_src_files_mips64 += \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-freebsd/lib/libc/string/wcschr.c \
- upstream-freebsd/lib/libc/string/wcscmp.c \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcslen.c \
- upstream-freebsd/lib/libc/string/wcsrchr.c \
- upstream-freebsd/lib/libc/string/wmemcmp.c \
- upstream-freebsd/lib/libc/string/wmemmove.c \
-
-libc_openbsd_src_files_mips64 += \
- upstream-openbsd/lib/libc/string/memchr.c \
- upstream-openbsd/lib/libc/string/memmove.c \
- upstream-openbsd/lib/libc/string/memrchr.c \
- upstream-openbsd/lib/libc/string/stpcpy.c \
- upstream-openbsd/lib/libc/string/stpncpy.c \
- upstream-openbsd/lib/libc/string/strcat.c \
- upstream-openbsd/lib/libc/string/strcpy.c \
- upstream-openbsd/lib/libc/string/strlcat.c \
- upstream-openbsd/lib/libc/string/strlcpy.c \
- upstream-openbsd/lib/libc/string/strncat.c \
- upstream-openbsd/lib/libc/string/strncmp.c \
- upstream-openbsd/lib/libc/string/strncpy.c \
#
# Inherently architecture-specific code.
diff --git a/libc/arch-mips64/syscalls/mremap.S b/libc/arch-mips64/syscalls/___mremap.S
similarity index 87%
rename from libc/arch-mips64/syscalls/mremap.S
rename to libc/arch-mips64/syscalls/___mremap.S
index cf7f1de..5004d50 100644
--- a/libc/arch-mips64/syscalls/mremap.S
+++ b/libc/arch-mips64/syscalls/___mremap.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(mremap)
+ENTRY(___mremap)
.set push
.set noreorder
li v0, __NR_mremap
@@ -22,4 +22,5 @@
j t9
move ra, t0
.set pop
-END(mremap)
+END(___mremap)
+.hidden ___mremap
diff --git a/libc/arch-x86/atom/atom.mk b/libc/arch-x86/atom/atom.mk
index 3f28fb2..1afabac 100644
--- a/libc/arch-x86/atom/atom.mk
+++ b/libc/arch-x86/atom/atom.mk
@@ -1,32 +1,27 @@
libc_bionic_src_files_x86 += \
arch-x86/atom/string/sse2-bzero-atom.S \
- arch-x86/atom/string/sse2-memchr-atom.S \
- arch-x86/atom/string/sse2-memrchr-atom.S \
arch-x86/atom/string/sse2-memset-atom.S \
- arch-x86/atom/string/sse2-strchr-atom.S \
arch-x86/atom/string/sse2-strlen-atom.S \
- arch-x86/atom/string/sse2-strnlen-atom.S \
- arch-x86/atom/string/sse2-strrchr-atom.S \
- arch-x86/atom/string/sse2-wcschr-atom.S \
- arch-x86/atom/string/sse2-wcsrchr-atom.S \
- arch-x86/atom/string/sse2-wcslen-atom.S \
- arch-x86/atom/string/sse2-wcscmp-atom.S \
arch-x86/atom/string/ssse3-bcopy-atom.S \
arch-x86/atom/string/ssse3-memcmp-atom.S \
arch-x86/atom/string/ssse3-memcpy-atom.S \
arch-x86/atom/string/ssse3-memmove-atom.S \
- arch-x86/atom/string/ssse3-strcat-atom.S \
- arch-x86/atom/string/ssse3-strcmp-atom.S \
arch-x86/atom/string/ssse3-strcpy-atom.S \
- arch-x86/atom/string/ssse3-strlcat-atom.S \
- arch-x86/atom/string/ssse3-strlcpy-atom.S \
- arch-x86/atom/string/ssse3-strncat-atom.S \
- arch-x86/atom/string/ssse3-strncmp-atom.S \
arch-x86/atom/string/ssse3-strncpy-atom.S \
- arch-x86/atom/string/ssse3-wcscat-atom.S \
- arch-x86/atom/string/ssse3-wcscpy-atom.S \
arch-x86/atom/string/ssse3-wmemcmp-atom.S
-libc_bionic_src_files_x86 += \
- arch-x86/silvermont/string/sse2-stpcpy-slm.S \
- arch-x86/silvermont/string/sse2-stpncpy-slm.S
+libc_bionic_src_files_exclude_x86 += \
+ arch-x86/generic/string/memcmp.S \
+
+libc_bionic_src_files_exclude_x86 += \
+ arch-x86/silvermont/string/sse2-bcopy-slm.S \
+ arch-x86/silvermont/string/sse2-bzero-slm.S \
+ arch-x86/silvermont/string/sse2-memcpy-slm.S \
+ arch-x86/silvermont/string/sse2-memmove-slm.S \
+ arch-x86/silvermont/string/sse2-memset-slm.S \
+ arch-x86/silvermont/string/sse2-strcpy-slm.S \
+ arch-x86/silvermont/string/sse2-strlen-slm.S \
+ arch-x86/silvermont/string/sse2-strncpy-slm.S \
+
+libc_freebsd_src_files_exclude_x86 += \
+ upstream-freebsd/lib/libc/string/wmemcmp.c \
diff --git a/libc/arch-x86/generic/generic.mk b/libc/arch-x86/generic/generic.mk
deleted file mode 100644
index 4aee5dc..0000000
--- a/libc/arch-x86/generic/generic.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-libc_bionic_src_files_x86 += \
- arch-x86/atom/string/sse2-memchr-atom.S \
- arch-x86/atom/string/sse2-memrchr-atom.S \
- arch-x86/atom/string/sse2-strchr-atom.S \
- arch-x86/atom/string/sse2-strnlen-atom.S \
- arch-x86/atom/string/sse2-strrchr-atom.S \
- arch-x86/atom/string/sse2-wcschr-atom.S \
- arch-x86/atom/string/sse2-wcsrchr-atom.S \
- arch-x86/atom/string/sse2-wcslen-atom.S \
- arch-x86/atom/string/sse2-wcscmp-atom.S \
- arch-x86/silvermont/string/sse2-bcopy-slm.S \
- arch-x86/silvermont/string/sse2-bzero-slm.S \
- arch-x86/silvermont/string/sse2-memcpy-slm.S \
- arch-x86/silvermont/string/sse2-memmove-slm.S \
- arch-x86/silvermont/string/sse2-memset-slm.S \
- arch-x86/silvermont/string/sse2-stpcpy-slm.S \
- arch-x86/silvermont/string/sse2-stpncpy-slm.S \
- arch-x86/silvermont/string/sse2-strcpy-slm.S \
- arch-x86/silvermont/string/sse2-strlen-slm.S \
- arch-x86/silvermont/string/sse2-strncpy-slm.S
-
-ifeq ($(ARCH_X86_HAVE_SSSE3),true)
-libc_bionic_src_files_x86 += \
- arch-x86/atom/string/ssse3-strncat-atom.S \
- arch-x86/atom/string/ssse3-strlcat-atom.S \
- arch-x86/atom/string/ssse3-strlcpy-atom.S \
- arch-x86/atom/string/ssse3-strcmp-atom.S \
- arch-x86/atom/string/ssse3-strncmp-atom.S \
- arch-x86/atom/string/ssse3-strcat-atom.S \
- arch-x86/atom/string/ssse3-wcscat-atom.S \
- arch-x86/atom/string/ssse3-wcscpy-atom.S
-else
-libc_bionic_src_files_x86 += \
- arch-x86/generic/string/strcmp.S \
- arch-x86/generic/string/strncmp.S \
- arch-x86/generic/string/strcat.S \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-openbsd/lib/libc/string/strlcat.c \
- upstream-openbsd/lib/libc/string/strlcpy.c \
- upstream-openbsd/lib/libc/string/strncat.c
-endif
-
-ifeq ($(ARCH_X86_HAVE_SSE4),true)
- libc_bionic_src_files_x86 += \
- arch-x86/silvermont/string/sse4-memcmp-slm.S \
- arch-x86/silvermont/string/sse4-wmemcmp-slm.S
-else
-libc_bionic_src_files_x86 += \
- arch-x86/generic/string/memcmp.S \
- upstream-freebsd/lib/libc/string/wmemcmp.c
-endif
diff --git a/libc/arch-x86/silvermont/silvermont.mk b/libc/arch-x86/silvermont/silvermont.mk
index 176bee3..e69de29 100644
--- a/libc/arch-x86/silvermont/silvermont.mk
+++ b/libc/arch-x86/silvermont/silvermont.mk
@@ -1,32 +0,0 @@
-libc_bionic_src_files_x86 += \
- arch-x86/silvermont/string/sse2-bcopy-slm.S \
- arch-x86/silvermont/string/sse2-bzero-slm.S \
- arch-x86/silvermont/string/sse2-memcpy-slm.S \
- arch-x86/silvermont/string/sse2-memmove-slm.S \
- arch-x86/silvermont/string/sse2-memset-slm.S \
- arch-x86/silvermont/string/sse2-stpcpy-slm.S \
- arch-x86/silvermont/string/sse2-stpncpy-slm.S \
- arch-x86/silvermont/string/sse2-strcpy-slm.S \
- arch-x86/silvermont/string/sse2-strlen-slm.S \
- arch-x86/silvermont/string/sse2-strncpy-slm.S \
- arch-x86/silvermont/string/sse4-memcmp-slm.S \
- arch-x86/silvermont/string/sse4-wmemcmp-slm.S
-
-libc_bionic_src_files_x86 += \
- arch-x86/atom/string/sse2-memchr-atom.S \
- arch-x86/atom/string/sse2-memrchr-atom.S \
- arch-x86/atom/string/sse2-strchr-atom.S \
- arch-x86/atom/string/sse2-strrchr-atom.S \
- arch-x86/atom/string/sse2-strnlen-atom.S \
- arch-x86/atom/string/sse2-wcschr-atom.S \
- arch-x86/atom/string/sse2-wcsrchr-atom.S \
- arch-x86/atom/string/sse2-wcslen-atom.S \
- arch-x86/atom/string/sse2-wcscmp-atom.S \
- arch-x86/atom/string/ssse3-strncat-atom.S \
- arch-x86/atom/string/ssse3-strlcat-atom.S \
- arch-x86/atom/string/ssse3-strlcpy-atom.S \
- arch-x86/atom/string/ssse3-strcmp-atom.S \
- arch-x86/atom/string/ssse3-strncmp-atom.S \
- arch-x86/atom/string/ssse3-strcat-atom.S \
- arch-x86/atom/string/ssse3-wcscat-atom.S \
- arch-x86/atom/string/ssse3-wcscpy-atom.S
diff --git a/libc/arch-x86/syscalls/mremap.S b/libc/arch-x86/syscalls/___mremap.S
similarity index 69%
rename from libc/arch-x86/syscalls/mremap.S
rename to libc/arch-x86/syscalls/___mremap.S
index 869ef5d..e5e9c54 100644
--- a/libc/arch-x86/syscalls/mremap.S
+++ b/libc/arch-x86/syscalls/___mremap.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(mremap)
+ENTRY(___mremap)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -15,10 +15,14 @@
pushl %esi
.cfi_adjust_cfa_offset 4
.cfi_rel_offset esi, 0
- mov 20(%esp), %ebx
- mov 24(%esp), %ecx
- mov 28(%esp), %edx
- mov 32(%esp), %esi
+ pushl %edi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edi, 0
+ mov 24(%esp), %ebx
+ mov 28(%esp), %ecx
+ mov 32(%esp), %edx
+ mov 36(%esp), %esi
+ mov 40(%esp), %edi
movl $__NR_mremap, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
@@ -28,9 +32,11 @@
call __set_errno_internal
addl $4, %esp
1:
+ popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
ret
-END(mremap)
+END(___mremap)
+.hidden ___mremap
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index e5d70a9..b4056bb 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -1,17 +1,103 @@
# 32-bit x86.
#
-# Default implementations of functions that are commonly optimized.
+# Generic x86 optimizations, may be overriden by CPU variants.
#
-libc_common_src_files_x86 += \
- bionic/__memcpy_chk.cpp \
- bionic/__memset_chk.cpp \
- bionic/__strcpy_chk.cpp \
- bionic/__strcat_chk.cpp \
+libc_bionic_src_files_x86 += \
+ arch-x86/atom/string/sse2-memchr-atom.S \
+ arch-x86/atom/string/sse2-memrchr-atom.S \
+ arch-x86/atom/string/sse2-strchr-atom.S \
+ arch-x86/atom/string/sse2-strnlen-atom.S \
+ arch-x86/atom/string/sse2-strrchr-atom.S \
+ arch-x86/atom/string/sse2-wcschr-atom.S \
+ arch-x86/atom/string/sse2-wcsrchr-atom.S \
+ arch-x86/atom/string/sse2-wcslen-atom.S \
+ arch-x86/atom/string/sse2-wcscmp-atom.S \
+ arch-x86/silvermont/string/sse2-bcopy-slm.S \
+ arch-x86/silvermont/string/sse2-bzero-slm.S \
+ arch-x86/silvermont/string/sse2-memcpy-slm.S \
+ arch-x86/silvermont/string/sse2-memmove-slm.S \
+ arch-x86/silvermont/string/sse2-memset-slm.S \
+ arch-x86/silvermont/string/sse2-stpcpy-slm.S \
+ arch-x86/silvermont/string/sse2-stpncpy-slm.S \
+ arch-x86/silvermont/string/sse2-strcpy-slm.S \
+ arch-x86/silvermont/string/sse2-strlen-slm.S \
+ arch-x86/silvermont/string/sse2-strncpy-slm.S
-libc_freebsd_src_files_x86 += \
- upstream-freebsd/lib/libc/string/wmemmove.c \
+libc_bionic_src_files_x86 += \
+ arch-x86/generic/string/memcmp.S \
+ arch-x86/generic/string/strcmp.S \
+ arch-x86/generic/string/strncmp.S \
+ arch-x86/generic/string/strcat.S
+
+ifeq ($(ARCH_X86_HAVE_SSSE3),true)
+libc_bionic_src_files_x86 += \
+ arch-x86/atom/string/ssse3-strncat-atom.S \
+ arch-x86/atom/string/ssse3-strlcat-atom.S \
+ arch-x86/atom/string/ssse3-strlcpy-atom.S \
+ arch-x86/atom/string/ssse3-strcmp-atom.S \
+ arch-x86/atom/string/ssse3-strncmp-atom.S \
+ arch-x86/atom/string/ssse3-strcat-atom.S \
+ arch-x86/atom/string/ssse3-wcscat-atom.S \
+ arch-x86/atom/string/ssse3-wcscpy-atom.S
+libc_bionic_src_files_exclude_x86 += \
+ arch-x86/generic/string/strcmp.S \
+ arch-x86/generic/string/strncmp.S \
+ arch-x86/generic/string/strcat.S
+endif
+
+ifeq ($(ARCH_X86_HAVE_SSE4),true)
+libc_bionic_src_files_x86 += \
+ arch-x86/silvermont/string/sse4-memcmp-slm.S \
+ arch-x86/silvermont/string/sse4-wmemcmp-slm.S
+libc_bionic_src_files_exclude_x86 += \
+ arch-x86/generic/string/memcmp.S
+endif
+
+#
+# Remove default implementations that we have optimized versions of.
+#
+
+libc_freebsd_src_files_exclude_x86 += \
+ upstream-freebsd/lib/libc/string/wcschr.c \
+ upstream-freebsd/lib/libc/string/wcscmp.c \
+ upstream-freebsd/lib/libc/string/wcslen.c \
+ upstream-freebsd/lib/libc/string/wcsrchr.c \
+
+ifeq ($(ARCH_X86_HAVE_SSSE3),true)
+libc_freebsd_src_files_exclude_x86 += \
+ upstream-freebsd/lib/libc/string/wcscat.c \
+ upstream-freebsd/lib/libc/string/wcscpy.c
+endif
+
+ifeq ($(ARCH_X86_HAVE_SSE4),true)
+libc_freebsd_src_files_exclude_x86 += \
+ upstream-freebsd/lib/libc/string/wmemcmp.c
+endif
+
+libc_openbsd_src_files_exclude_x86 += \
+ upstream-openbsd/lib/libc/string/memchr.c \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/memrchr.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/stpncpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+ upstream-openbsd/lib/libc/string/strcpy.c \
+ upstream-openbsd/lib/libc/string/strncmp.c \
+ upstream-openbsd/lib/libc/string/strncpy.c \
+
+ifeq ($(ARCH_X86_HAVE_SSSE3),true)
+libc_openbsd_src_files_exclude_x86 += \
+ upstream-openbsd/lib/libc/string/strlcat.c \
+ upstream-openbsd/lib/libc/string/strlcpy.c \
+ upstream-openbsd/lib/libc/string/strncat.c
+endif
+
+libc_bionic_src_files_exclude_x86 += \
+ bionic/strchr.cpp \
+ bionic/strnlen.c \
+ bionic/strrchr.cpp \
#
# Inherently architecture-specific functions.
@@ -30,12 +116,14 @@
## ARCH variant specific source files
arch_variant_mk := $(LOCAL_PATH)/arch-x86/$(TARGET_ARCH_VARIANT)/$(TARGET_ARCH_VARIANT).mk
ifeq ($(wildcard $(arch_variant_mk)),)
- arch_variant_mk := $(LOCAL_PATH)/arch-x86/generic/generic.mk
+ arch_variant_mk :=
endif
+ifneq ($(arch_variant_mk),)
include $(arch_variant_mk)
libc_common_additional_dependencies += $(arch_variant_mk)
arch_variant_mk :=
+endif
libc_crt_target_cflags_x86 := \
-m32 \
diff --git a/libc/arch-x86_64/syscalls/mremap.S b/libc/arch-x86_64/syscalls/___mremap.S
similarity index 84%
rename from libc/arch-x86_64/syscalls/mremap.S
rename to libc/arch-x86_64/syscalls/___mremap.S
index a6042cb..cc6dee9 100644
--- a/libc/arch-x86_64/syscalls/mremap.S
+++ b/libc/arch-x86_64/syscalls/___mremap.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(mremap)
+ENTRY(___mremap)
movq %rcx, %r10
movl $__NR_mremap, %eax
syscall
@@ -13,4 +13,5 @@
call __set_errno_internal
1:
ret
-END(mremap)
+END(___mremap)
+.hidden ___mremap
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 06d3185..bbf5c8c 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -1,31 +1,20 @@
# 64-bit x86.
#
-# Default implementations of functions that are commonly optimized.
+# Remove default implementations that we have optimized versions of.
#
-libc_bionic_src_files_x86_64 += \
- bionic/__memcpy_chk.cpp \
- bionic/__memset_chk.cpp \
- bionic/__strcpy_chk.cpp \
- bionic/__strcat_chk.cpp \
- bionic/strchr.cpp \
- bionic/strnlen.c \
- bionic/strrchr.cpp \
-
-libc_freebsd_src_files_x86_64 += \
- upstream-freebsd/lib/libc/string/wcscat.c \
- upstream-freebsd/lib/libc/string/wcschr.c \
- upstream-freebsd/lib/libc/string/wcscmp.c \
- upstream-freebsd/lib/libc/string/wcscpy.c \
- upstream-freebsd/lib/libc/string/wcslen.c \
- upstream-freebsd/lib/libc/string/wcsrchr.c \
- upstream-freebsd/lib/libc/string/wmemcmp.c \
- upstream-freebsd/lib/libc/string/wmemmove.c \
-
-libc_openbsd_src_files_x86_64 += \
- upstream-openbsd/lib/libc/string/memchr.c \
- upstream-openbsd/lib/libc/string/memrchr.c \
+libc_openbsd_src_files_exclude_x86_64 += \
+ upstream-openbsd/lib/libc/string/memmove.c \
+ upstream-openbsd/lib/libc/string/stpcpy.c \
+ upstream-openbsd/lib/libc/string/stpncpy.c \
+ upstream-openbsd/lib/libc/string/strcat.c \
+ upstream-openbsd/lib/libc/string/strcpy.c \
+ upstream-openbsd/lib/libc/string/strlcat.c \
+ upstream-openbsd/lib/libc/string/strlcpy.c \
+ upstream-openbsd/lib/libc/string/strncat.c \
+ upstream-openbsd/lib/libc/string/strncmp.c \
+ upstream-openbsd/lib/libc/string/strncpy.c \
#
# Inherently architecture-specific code.
diff --git a/libc/bionic/__cxa_guard.cpp b/libc/bionic/__cxa_guard.cpp
index 5b34b58..97284d5 100644
--- a/libc/bionic/__cxa_guard.cpp
+++ b/libc/bionic/__cxa_guard.cpp
@@ -109,7 +109,7 @@
}
}
- __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, NULL);
+ __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, false, nullptr);
old_value = atomic_load_explicit(&gv->state, memory_order_relaxed);
}
}
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
index 0e427d3..0e903b9 100644
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
@@ -15,6 +15,8 @@
*/
#include <sys/cdefs.h>
+#include "pthread_internal.h"
+
struct thread_local_dtor {
void (*func) (void *);
void *arg;
@@ -22,25 +24,24 @@
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) {
thread_local_dtor* dtor = new thread_local_dtor();
dtor->func = func;
dtor->arg = arg;
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;
}
extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
- while (thread_local_dtors != nullptr) {
- thread_local_dtor* current = thread_local_dtors;
- thread_local_dtors = current->next;
+ pthread_internal_t* thread = __get_thread();
+ while (thread->thread_local_dtors != nullptr) {
+ thread_local_dtor* current = thread->thread_local_dtors;
+ thread->thread_local_dtors = current->next;
current->func(current->arg);
delete current;
diff --git a/libc/bionic/__set_errno.cpp b/libc/bionic/__set_errno.cpp
index 30df350..9ef0047 100644
--- a/libc/bionic/__set_errno.cpp
+++ b/libc/bionic/__set_errno.cpp
@@ -36,20 +36,13 @@
// system these are the same size, but on a 64-bit system they're not.
// 'long' gives us 32-bit on 32-bit systems, 64-bit on 64-bit systems.
-// __set_errno was mistakenly exposed in <errno.h> in the 32-bit NDK.
-// We need the extra level of indirection so that the .hidden directives
-// in the system call stubs don't cause __set_errno to be hidden, breaking
-// old NDK apps.
+// Since __set_errno was mistakenly exposed in <errno.h> in the 32-bit
+// NDK, use a differently named internal function for the system call
+// stubs. This avoids having the stubs .hidden directives accidentally
+// hide __set_errno for old NDK apps.
// This one is for internal use only and used by both LP32 and LP64 assembler.
extern "C" __LIBC_HIDDEN__ long __set_errno_internal(int n) {
errno = n;
return -1;
}
-
-// This one exists for the LP32 NDK and is not present at all in LP64.
-#if !defined(__LP64__)
-extern "C" long __set_errno(int n) {
- return __set_errno_internal(n);
-}
-#endif
diff --git a/libc/bionic/bionic_time_conversions.cpp b/libc/bionic/bionic_time_conversions.cpp
index 75e8d49..f3ca46a 100644
--- a/libc/bionic/bionic_time_conversions.cpp
+++ b/libc/bionic/bionic_time_conversions.cpp
@@ -52,18 +52,12 @@
tv.tv_usec = ts.tv_nsec / 1000;
}
-// Initializes 'ts' with the difference between 'abs_ts' and the current time
-// according to 'clock'. Returns false if abstime already expired, true otherwise.
-bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) {
- clock_gettime(clock, &ts);
- ts.tv_sec = abs_ts.tv_sec - ts.tv_sec;
- ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec;
- if (ts.tv_nsec < 0) {
- ts.tv_sec--;
- ts.tv_nsec += NS_PER_S;
+void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, clockid_t clock) {
+ clock_gettime(clock, &abs_ts);
+ abs_ts.tv_sec += ts.tv_sec;
+ abs_ts.tv_nsec += ts.tv_nsec;
+ if (abs_ts.tv_nsec >= NS_PER_S) {
+ abs_ts.tv_nsec -= NS_PER_S;
+ abs_ts.tv_sec++;
}
- if (ts.tv_nsec < 0 || ts.tv_sec < 0) {
- return false;
- }
- return true;
}
diff --git a/libc/bionic/flockfile.cpp b/libc/bionic/flockfile.cpp
index b73907cb..db53828 100644
--- a/libc/bionic/flockfile.cpp
+++ b/libc/bionic/flockfile.cpp
@@ -36,23 +36,15 @@
// struct __sfileext (see fileext.h).
void flockfile(FILE* fp) {
- if (!__sdidinit) {
- __sinit();
- }
-
- if (fp != NULL) {
+ if (fp != nullptr) {
pthread_mutex_lock(&_FLOCK(fp));
}
}
int ftrylockfile(FILE* fp) {
- if (!__sdidinit) {
- __sinit();
- }
-
// The specification for ftrylockfile() says it returns 0 on success,
// or non-zero on error. So return an errno code directly on error.
- if (fp == NULL) {
+ if (fp == nullptr) {
return EINVAL;
}
@@ -60,11 +52,7 @@
}
void funlockfile(FILE* fp) {
- if (!__sdidinit) {
- __sinit();
- }
-
- if (fp != NULL) {
+ if (fp != nullptr) {
pthread_mutex_unlock(&_FLOCK(fp));
}
}
diff --git a/libc/bionic/ioctl.c b/libc/bionic/ioctl.cpp
similarity index 85%
rename from libc/bionic/ioctl.c
rename to libc/bionic/ioctl.cpp
index 6dd95d0..db85132 100644
--- a/libc/bionic/ioctl.c
+++ b/libc/bionic/ioctl.cpp
@@ -25,19 +25,16 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
+#include <sys/ioctl.h>
#include <stdarg.h>
-extern int __ioctl(int, int, void *);
+extern "C" int __ioctl(int, int, void *);
-int ioctl(int fd, int request, ...)
-{
- va_list ap;
- void * arg;
-
- va_start(ap, request);
- arg = va_arg(ap, void *);
- va_end(ap);
-
- return __ioctl(fd, request, arg);
+int ioctl(int fd, int request, ...) {
+ va_list ap;
+ va_start(ap, request);
+ void* arg = va_arg(ap, void*);
+ va_end(ap);
+ return __ioctl(fd, request, arg);
}
-
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 20d258d..f2bb37d 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -111,3 +111,22 @@
int setrlimit64(int resource, const rlimit64* limits64) {
return prlimit64(0, resource, limits64, NULL);
}
+
+// There is no prlimit system call, so we need to use prlimit64.
+int prlimit(pid_t pid, int resource, const rlimit* n32, rlimit* o32) {
+ rlimit64 n64;
+ if (n32 != nullptr) {
+ n64.rlim_cur = (n32->rlim_cur == RLIM_INFINITY) ? RLIM64_INFINITY : n32->rlim_cur;
+ n64.rlim_max = (n32->rlim_max == RLIM_INFINITY) ? RLIM64_INFINITY : n32->rlim_max;
+ }
+
+ rlimit64 o64;
+ int result = prlimit64(pid, resource,
+ (n32 != nullptr) ? &n64 : nullptr,
+ (o32 != nullptr) ? &o64 : nullptr);
+ if (result != -1 && o32 != nullptr) {
+ o32->rlim_cur = (o64.rlim_cur == RLIM64_INFINITY) ? RLIM_INFINITY : o64.rlim_cur;
+ o32->rlim_max = (o64.rlim_max == RLIM64_INFINITY) ? RLIM_INFINITY : o64.rlim_max;
+ }
+ return result;
+}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 4995414..8f1ee95 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -110,6 +110,7 @@
// 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
// globals, once for the linker's copy and once for the one in libc.so.
+ __libc_auxv = args.auxv;
__libc_globals.initialize();
__libc_globals.mutate([&args](libc_globals* globals) {
__libc_init_vdso(globals, args);
@@ -121,7 +122,6 @@
// Initialize various globals.
environ = args.envp;
errno = 0;
- __libc_auxv = args.auxv;
__progname = args.argv[0] ? args.argv[0] : "<unknown>";
__abort_message_ptr = args.abort_message_ptr;
@@ -245,7 +245,11 @@
}
static bool __is_unsafe_environment_variable(const char* name) {
- // None of these should be allowed in setuid programs.
+ // None of these should be allowed when the AT_SECURE auxv
+ // 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[] = {
"GCONV_PATH",
"GETCONF_DIR",
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 3bb6e89..edf6a44 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -50,11 +50,11 @@
#include <elf.h>
#include "libc_init_common.h"
+#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
extern "C" {
- extern void malloc_debug_init(void);
extern void malloc_debug_fini(void);
extern void netdClientInit(void);
extern int __cxa_atexit(void (*)(void *), void *, void *);
@@ -78,7 +78,7 @@
__libc_init_common(*args);
// Hooks for various libraries to let them know that we're starting up.
- malloc_debug_init();
+ __libc_globals.mutate(__libc_init_malloc);
netdClientInit();
}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index 2a987b9..67bb052 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -31,6 +31,7 @@
#include <android/set_abort_message.h>
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
@@ -46,6 +47,9 @@
#include <time.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;
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
@@ -481,6 +485,64 @@
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
uint32_t tv_sec;
uint32_t tv_nsec;
@@ -501,7 +563,7 @@
vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid);
timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
+ clock_gettime(__android_log_clockid(), &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
@@ -544,7 +606,7 @@
vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid);
timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
+ clock_gettime(__android_log_clockid(), &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
diff --git a/libc/bionic/libgen.cpp b/libc/bionic/libgen.cpp
index 5c27bb5..c415c0f 100644
--- a/libc/bionic/libgen.cpp
+++ b/libc/bionic/libgen.cpp
@@ -92,7 +92,7 @@
}
// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
-__LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
+__LIBC32_LEGACY_PUBLIC__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
return __basename_r(path, buffer, buffer_size);
}
@@ -156,7 +156,7 @@
}
// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
-__LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
+__LIBC32_LEGACY_PUBLIC__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
return __dirname_r(path, buffer, buffer_size);
}
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 5b7c42c..9f7f3ba 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -44,6 +44,7 @@
#include <string.h>
#include <unistd.h>
+#include "private/bionic_globals.h"
#include "private/ScopedPthreadMutexLocker.h"
#if defined(USE_JEMALLOC)
@@ -56,33 +57,29 @@
#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
#endif
+static constexpr MallocDebug __libc_malloc_default_dispatch
+ __attribute__((unused)) = {
+ Malloc(calloc),
+ Malloc(free),
+ Malloc(mallinfo),
+ Malloc(malloc),
+ Malloc(malloc_usable_size),
+ Malloc(memalign),
+ Malloc(posix_memalign),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ Malloc(pvalloc),
+#endif
+ Malloc(realloc),
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ Malloc(valloc),
+#endif
+ };
+
// In a VM process, this is set to 1 after fork()ing out of zygote.
int gMallocLeakZygoteChild = 0;
static HashTable g_hash_table;
-// Support for malloc debugging.
-// Table for dispatching malloc calls, initialized with default dispatchers.
-static const MallocDebug __libc_malloc_default_dispatch __attribute__((aligned(32))) = {
- Malloc(calloc),
- Malloc(free),
- Malloc(mallinfo),
- Malloc(malloc),
- Malloc(malloc_usable_size),
- Malloc(memalign),
- Malloc(posix_memalign),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
- Malloc(pvalloc),
-#endif
- Malloc(realloc),
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
- Malloc(valloc),
-#endif
-};
-
-// Selector of dispatch table to use for dispatching malloc calls.
-static const MallocDebug* __libc_malloc_dispatch = &__libc_malloc_default_dispatch;
-
// Handle to shared library where actual memory allocation is implemented.
// This library is loaded and memory allocation calls are redirected there
// when libc.debug.malloc environment variable contains value other than
@@ -244,46 +241,87 @@
// Allocation functions
// =============================================================================
extern "C" void* calloc(size_t n_elements, size_t elem_size) {
- return __libc_malloc_dispatch->calloc(n_elements, elem_size);
+ auto _calloc = __libc_globals->malloc_dispatch.calloc;
+ if (__predict_false(_calloc != nullptr)) {
+ return _calloc(n_elements, elem_size);
+ }
+ return Malloc(calloc)(n_elements, elem_size);
}
extern "C" void free(void* mem) {
- __libc_malloc_dispatch->free(mem);
+ auto _free = __libc_globals->malloc_dispatch.free;
+ if (__predict_false(_free != nullptr)) {
+ _free(mem);
+ } else {
+ Malloc(free)(mem);
+ }
}
extern "C" struct mallinfo mallinfo() {
- return __libc_malloc_dispatch->mallinfo();
+ auto _mallinfo = __libc_globals->malloc_dispatch.mallinfo;
+ if (__predict_false(_mallinfo != nullptr)) {
+ return _mallinfo();
+ }
+ return Malloc(mallinfo)();
}
extern "C" void* malloc(size_t bytes) {
- return __libc_malloc_dispatch->malloc(bytes);
+ auto _malloc = __libc_globals->malloc_dispatch.malloc;
+ if (__predict_false(_malloc != nullptr)) {
+ return _malloc(bytes);
+ }
+ return Malloc(malloc)(bytes);
}
extern "C" size_t malloc_usable_size(const void* mem) {
- return __libc_malloc_dispatch->malloc_usable_size(mem);
+ auto _malloc_usable_size = __libc_globals->malloc_dispatch.malloc_usable_size;
+ if (__predict_false(_malloc_usable_size != nullptr)) {
+ return _malloc_usable_size(mem);
+ }
+ return Malloc(malloc_usable_size)(mem);
}
extern "C" void* memalign(size_t alignment, size_t bytes) {
- return __libc_malloc_dispatch->memalign(alignment, bytes);
+ auto _memalign = __libc_globals->malloc_dispatch.memalign;
+ if (__predict_false(_memalign != nullptr)) {
+ return _memalign(alignment, bytes);
+ }
+ return Malloc(memalign)(alignment, bytes);
}
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size) {
- return __libc_malloc_dispatch->posix_memalign(memptr, alignment, size);
+ auto _posix_memalign = __libc_globals->malloc_dispatch.posix_memalign;
+ if (__predict_false(_posix_memalign != nullptr)) {
+ return _posix_memalign(memptr, alignment, size);
+ }
+ return Malloc(posix_memalign)(memptr, alignment, size);
}
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* pvalloc(size_t bytes) {
- return __libc_malloc_dispatch->pvalloc(bytes);
+ auto _pvalloc = __libc_globals->malloc_dispatch.pvalloc;
+ if (__predict_false(_pvalloc != nullptr)) {
+ return _pvalloc(bytes);
+ }
+ return Malloc(pvalloc)(bytes);
}
#endif
-extern "C" void* realloc(void* oldMem, size_t bytes) {
- return __libc_malloc_dispatch->realloc(oldMem, bytes);
+extern "C" void* realloc(void* old_mem, size_t bytes) {
+ auto _realloc = __libc_globals->malloc_dispatch.realloc;
+ if (__predict_false(_realloc != nullptr)) {
+ return _realloc(old_mem, bytes);
+ }
+ return Malloc(realloc)(old_mem, bytes);
}
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* valloc(size_t bytes) {
- return __libc_malloc_dispatch->valloc(bytes);
+ auto _valloc = __libc_globals->malloc_dispatch.valloc;
+ if (__predict_false(_valloc != nullptr)) {
+ return _valloc(bytes);
+ }
+ return Malloc(valloc)(bytes);
}
#endif
@@ -326,7 +364,7 @@
}
// Initializes memory allocation framework once per process.
-static void malloc_init_impl() {
+static void malloc_init_impl(libc_globals* globals) {
const char* so_name = NULL;
MallocDebugInit malloc_debug_initialize = NULL;
unsigned int qemu_running = 0;
@@ -442,7 +480,7 @@
// No need to init the dispatch table because we can only get
// here if debug level is 1, 5, 10, or 20.
- static MallocDebug malloc_dispatch_table __attribute__((aligned(32)));
+ MallocDebug malloc_dispatch_table;
switch (g_malloc_debug_level) {
case 1:
InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "leak");
@@ -480,7 +518,7 @@
getprogname(), g_malloc_debug_level);
dlclose(malloc_impl_handle);
} else {
- __libc_malloc_dispatch = &malloc_dispatch_table;
+ globals->malloc_dispatch = malloc_dispatch_table;
libc_malloc_impl_handle = malloc_impl_handle;
}
}
@@ -507,15 +545,12 @@
#endif // !LIBC_STATIC
// Initializes memory allocation framework.
-// This routine is called from __libc_init routines implemented
-// in libc_init_static.c and libc_init_dynamic.c files.
-extern "C" __LIBC_HIDDEN__ void malloc_debug_init() {
+// This routine is called from __libc_init routines in libc_init_dynamic.cpp.
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
+ (void)globals;
#if !defined(LIBC_STATIC)
- static pthread_once_t malloc_init_once_ctl = PTHREAD_ONCE_INIT;
- if (pthread_once(&malloc_init_once_ctl, malloc_init_impl)) {
- error_log("Unable to initialize malloc_debug component.");
- }
-#endif // !LIBC_STATIC
+ malloc_init_impl(globals);
+#endif
}
extern "C" __LIBC_HIDDEN__ void malloc_debug_fini() {
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index 5c73da3..f8745da 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include "private/bionic_config.h"
+#include "private/bionic_malloc_dispatch.h"
#include "private/libc_logging.h"
#define HASHTABLE_SIZE 1543
@@ -72,39 +73,6 @@
HashEntry* slots[HASHTABLE_SIZE];
};
-/* Entry in malloc dispatch table. */
-typedef void* (*MallocDebugCalloc)(size_t, size_t);
-typedef void (*MallocDebugFree)(void*);
-typedef struct mallinfo (*MallocDebugMallinfo)();
-typedef void* (*MallocDebugMalloc)(size_t);
-typedef size_t (*MallocDebugMallocUsableSize)(const void*);
-typedef void* (*MallocDebugMemalign)(size_t, size_t);
-typedef int (*MallocDebugPosixMemalign)(void**, size_t, size_t);
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-typedef void* (*MallocDebugPvalloc)(size_t);
-#endif
-typedef void* (*MallocDebugRealloc)(void*, size_t);
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-typedef void* (*MallocDebugValloc)(size_t);
-#endif
-
-struct MallocDebug {
- MallocDebugCalloc calloc;
- MallocDebugFree free;
- MallocDebugMallinfo mallinfo;
- MallocDebugMalloc malloc;
- MallocDebugMallocUsableSize malloc_usable_size;
- MallocDebugMemalign memalign;
- MallocDebugPosixMemalign posix_memalign;
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
- MallocDebugPvalloc pvalloc;
-#endif
- MallocDebugRealloc realloc;
-#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
- MallocDebugValloc valloc;
-#endif
-};
-
typedef bool (*MallocDebugInit)(HashTable*, const MallocDebug*);
typedef void (*MallocDebugFini)(int);
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index 794f50f..57a8cdf 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -27,6 +27,7 @@
*/
#include <errno.h>
+#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -48,15 +49,19 @@
// prevent allocations large enough for `end - start` to overflow
size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE);
- if (rounded < size || size > PTRDIFF_MAX) {
+ if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
- bool is_private_anonymous = (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0;
+ bool is_private_anonymous =
+ (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);
- if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE && is_private_anonymous) {
+ if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
+ is_private_anonymous && !is_stack_or_grows_down) {
ErrnoRestorer errno_restorer;
int rc = madvise(result, size, MADV_MERGEABLE);
if (rc == -1 && errno == EINVAL) {
diff --git a/libc/bionic/ioctl.c b/libc/bionic/mremap.cpp
similarity index 61%
copy from libc/bionic/ioctl.c
copy to libc/bionic/mremap.cpp
index 6dd95d0..6653d43 100644
--- a/libc/bionic/ioctl.c
+++ b/libc/bionic/mremap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,19 +25,33 @@
* 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>
-extern int __ioctl(int, int, void *);
+#include "private/bionic_macros.h"
-int ioctl(int fd, int request, ...)
-{
+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;
- void * arg;
-
- va_start(ap, request);
- arg = va_arg(ap, void *);
+ va_start(ap, flags);
+ new_address = va_arg(ap, void*);
va_end(ap);
-
- return __ioctl(fd, request, arg);
+ }
+ return ___mremap(old_address, old_size, new_size, flags, new_address);
}
-
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index b299684..0429430 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -47,34 +47,37 @@
#include "private/libc_logging.h"
-// The part is only for 32-bit targets.
+extern "C" {
+
+// Brillo doesn't need to support any legacy cruft.
+#if !defined(__BRILLO__)
+
+// Most of the cruft is only for 32-bit Android targets.
#if !defined(__LP64__)
// These were accidentally declared in <unistd.h> because we stupidly used to inline
// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
-extern "C" {
- unsigned int __page_size = PAGE_SIZE;
- unsigned int __page_shift = 12;
-}
+unsigned int __page_size = PAGE_SIZE;
+unsigned int __page_shift = 12;
// TODO: remove this backward compatibility hack (for jb-mr1 strace binaries).
-extern "C" pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
+pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
return wait4(pid, status, options, rusage);
}
// TODO: does anything still need this?
-extern "C" int __open() {
+int __open() {
abort();
}
// TODO: does anything still need this?
-extern "C" void** __get_tls() {
+void** __get_tls() {
#include "private/__get_tls.h"
return __get_tls();
}
// This non-standard function was in our <string.h> for some reason.
-extern "C" void memswap(void* m1, void* m2, size_t n) {
+void memswap(void* m1, void* m2, size_t n) {
char* p = reinterpret_cast<char*>(m1);
char* p_end = p + n;
char* q = reinterpret_cast<char*>(m2);
@@ -87,13 +90,13 @@
}
}
-extern "C" int pthread_attr_setstackaddr(pthread_attr_t*, void*) {
+int pthread_attr_setstackaddr(pthread_attr_t*, void*) {
// This was removed from POSIX.1-2008, and is not implemented on bionic.
// Needed for ABI compatibility with the NDK.
return ENOSYS;
}
-extern "C" int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
+int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
// This was removed from POSIX.1-2008.
// Needed for ABI compatibility with the NDK.
*stack_addr = (char*)attr->stack_base + attr->stack_size;
@@ -101,7 +104,7 @@
}
// Non-standard cruft that should only ever have been in system/core/toolbox.
-extern "C" char* strtotimeval(const char* str, struct timeval* ts) {
+char* strtotimeval(const char* str, struct timeval* ts) {
char* s;
ts->tv_sec = strtoumax(str, &s, 10);
@@ -143,7 +146,7 @@
}
// This non-standard function was in our <inttypes.h> for some reason.
-extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
+uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
const unsigned char* p = (const unsigned char *)nptr;
const unsigned char* end = p + n;
int minus = 0;
@@ -191,12 +194,12 @@
}
// This non-standard function was in our <inttypes.h> for some reason.
-extern "C" intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
+intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
return (intmax_t) strntoumax(nptr, endptr, base, n);
}
// POSIX calls this dprintf, but LP32 Android had fdprintf instead.
-extern "C" int fdprintf(int fd, const char* fmt, ...) {
+int fdprintf(int fd, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
int rc = vdprintf(fd, fmt, ap);
@@ -205,7 +208,7 @@
}
// POSIX calls this vdprintf, but LP32 Android had fdprintf instead.
-extern "C" int vfdprintf(int fd, const char* fmt, va_list ap) {
+int vfdprintf(int fd, const char* fmt, va_list ap) {
return vdprintf(fd, fmt, ap);
}
@@ -216,64 +219,64 @@
#undef __futex_wait
// This used to be in <sys/atomics.h>.
-extern "C" int __futex_wake(volatile void* ftx, int count) {
+int __futex_wake(volatile void* ftx, int count) {
return __real_futex_wake(ftx, count);
}
// This used to be in <sys/atomics.h>.
-extern "C" int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
+int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
return __real_futex_wait(ftx, value, timeout);
}
// Unity's libmono uses this.
-extern "C" int tkill(pid_t tid, int sig) {
+int tkill(pid_t tid, int sig) {
return syscall(__NR_tkill, tid, sig);
}
// This was removed from POSIX 2008.
-extern "C" wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
+wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
return wcsstr(haystack, needle);
}
// This was removed from POSIX 2008.
-extern "C" sighandler_t bsd_signal(int signum, sighandler_t handler) {
+sighandler_t bsd_signal(int signum, sighandler_t handler) {
return signal(signum, handler);
}
#if !defined(__i386__)
// This was removed from POSIX 2008.
#undef bcopy
-extern "C" void bcopy(const void* src, void* dst, size_t n) {
- memcpy(dst, src, n);
+void bcopy(const void* src, void* dst, size_t n) {
+ memmove(dst, src, n);
}
#else
// x86 has an assembler implementation.
#endif
// sysv_signal() was never in POSIX.
-extern sighandler_t _signal(int signum, sighandler_t handler, int flags);
-extern "C" sighandler_t sysv_signal(int signum, sighandler_t handler) {
+extern "C++" sighandler_t _signal(int signum, sighandler_t handler, int flags);
+sighandler_t sysv_signal(int signum, sighandler_t handler) {
return _signal(signum, handler, SA_RESETHAND);
}
// This is a system call that was never in POSIX. Use readdir(3) instead.
-extern "C" int __getdents64(unsigned int, dirent*, unsigned int);
-extern "C" int getdents(unsigned int fd, dirent* dirp, unsigned int count) {
+int __getdents64(unsigned int, dirent*, unsigned int);
+int getdents(unsigned int fd, dirent* dirp, unsigned int count) {
return __getdents64(fd, dirp, count);
}
// This is a BSDism that we never implemented correctly. Used by Firefox.
-extern "C" int issetugid() {
+int issetugid() {
return 0;
}
// This was removed from POSIX 2004.
-extern "C" pid_t wait3(int* status, int options, struct rusage* rusage) {
+pid_t wait3(int* status, int options, struct rusage* rusage) {
return wait4(-1, status, options, rusage);
}
// This was removed from POSIX 2004.
-extern "C" int getdtablesize() {
+int getdtablesize() {
struct rlimit r;
if (getrlimit(RLIMIT_NOFILE, &r) < 0) {
@@ -283,6 +286,10 @@
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.
struct timeb {
time_t time;
@@ -292,7 +299,7 @@
};
// This was removed from POSIX 2008.
-extern "C" int ftime(struct timeb* tb) {
+int ftime(struct timeb* tb) {
struct timeval tv;
struct timezone tz;
@@ -314,35 +321,35 @@
}
// This was removed from POSIX 2008.
-extern "C" char* index(const char* str, int ch) {
+char* index(const char* str, int ch) {
return strchr(str, ch);
}
// This was removed from BSD.
-extern "C" void arc4random_stir(void) {
+void arc4random_stir(void) {
// The current implementation stirs itself as needed.
}
// This was removed from BSD.
-extern "C" void arc4random_addrandom(unsigned char*, int) {
+void arc4random_addrandom(unsigned char*, int) {
// The current implementation adds randomness as needed.
}
// 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
// so make this call malloc_usable_size.
-extern "C" size_t dlmalloc_usable_size(void* ptr) {
+size_t dlmalloc_usable_size(void* ptr) {
return malloc_usable_size(ptr);
}
// In L we added a public pthread_gettid_np, but some apps were using the private API.
-extern "C" pid_t __pthread_gettid(pthread_t t) {
+pid_t __pthread_gettid(pthread_t t) {
return pthread_gettid_np(t);
}
// Older versions of apportable used dlmalloc directly instead of malloc,
// so export this compatibility shim that simply calls malloc.
-extern "C" void* dlmalloc(size_t size) {
+void* dlmalloc(size_t size) {
return malloc(size);
}
@@ -350,45 +357,41 @@
#include "pthread_internal.h"
#undef __get_thread
// Various third-party apps contain a backport of our pthread_rwlock implementation that uses this.
-extern "C" pthread_internal_t* __get_thread() {
+pthread_internal_t* __get_thread() {
return __real_get_thread();
}
+// This one exists only for the LP32 NDK and is not present anywhere else.
+extern long __set_errno_internal(int);
+long __set_errno(int n) {
+ return __set_errno_internal(n);
+}
+
#endif // !defined(__LP64__)
-// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
-extern "C" char* getusershell() {
- return NULL;
-}
-
-// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
-extern "C" void setusershell() { }
-
-// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
-extern "C" void endusershell() { }
-
-// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
-extern "C" void endpwent() { }
+// 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!
+void endpwent() { }
// Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems
// that use dlmalloc, be consistent and export them everywhere.
#if defined(USE_JEMALLOC)
-extern "C" void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
+void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
+}
+int dlmalloc_trim(size_t) {
+ return 0;
}
#else
-extern "C" void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
-extern "C" void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
+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) {
dlmalloc_inspect_all_real(handler, arg);
}
-#endif
-
-#if defined(USE_JEMALLOC)
-extern "C" int dlmalloc_trim(size_t) {
- return 0;
-}
-#else
-extern "C" int dlmalloc_trim_real(size_t);
-extern "C" int dlmalloc_trim(size_t pad) {
+int dlmalloc_trim_real(size_t);
+int dlmalloc_trim(size_t pad) {
return dlmalloc_trim_real(pad);
}
#endif
+
+#endif // !defined(__BRILLO__)
+
+} // extern "C"
diff --git a/libc/bionic/pthread_barrier.cpp b/libc/bionic/pthread_barrier.cpp
new file mode 100644
index 0000000..1bcd12a
--- /dev/null
+++ b/libc/bionic/pthread_barrier.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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;
+}
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index 4a69da5..adbce07 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -111,8 +111,8 @@
return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed));
}
- int get_clock() {
- return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed));
+ bool use_realtime_clock() {
+ return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)) == CLOCK_REALTIME;
}
#if defined(__LP64__)
@@ -170,12 +170,17 @@
return 0;
}
-static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
- const timespec* rel_timeout_or_null) {
- unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
+static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
+ bool use_realtime_clock, const timespec* abs_timeout_or_null) {
+ int result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
+ }
+ unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
pthread_mutex_unlock(mutex);
- int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, rel_timeout_or_null);
+ int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state,
+ use_realtime_clock, abs_timeout_or_null);
pthread_mutex_lock(mutex);
if (status == -ETIMEDOUT) {
@@ -184,21 +189,6 @@
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) {
return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX);
}
@@ -209,14 +199,14 @@
int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
- return __pthread_cond_timedwait(cond, mutex, NULL, cond->get_clock());
+ return __pthread_cond_timedwait(cond, mutex, false, nullptr);
}
int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex,
const timespec *abstime) {
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
- return __pthread_cond_timedwait(cond, mutex, abstime, cond->get_clock());
+ return __pthread_cond_timedwait(cond, mutex, cond->use_realtime_clock(), abstime);
}
#if !defined(__LP64__)
@@ -225,8 +215,7 @@
pthread_mutex_t* mutex,
const timespec* abs_timeout) {
- return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, abs_timeout,
- CLOCK_MONOTONIC);
+ return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
}
extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface,
@@ -238,8 +227,13 @@
extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface,
pthread_mutex_t* mutex,
const timespec* rel_timeout) {
-
- return __pthread_cond_timedwait_relative(__get_internal_cond(cond_interface), mutex, rel_timeout);
+ timespec ts;
+ timespec* abs_timeout = nullptr;
+ 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,
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index e260e97..34826db 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -53,13 +53,6 @@
// This code is used both by each new pthread and the code that initializes the main 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.
thread->tls[TLS_SLOT_SELF] = thread->tls;
thread->tls[TLS_SLOT_THREAD_ID] = thread;
@@ -175,6 +168,11 @@
(reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
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);
thread->mmap_size = mmap_size;
@@ -193,8 +191,7 @@
// notify gdb about this thread before we start doing anything.
// This also provides the memory barrier needed to ensure that all memory
// accesses previously made by the creating thread are visible to us.
- pthread_mutex_lock(&thread->startup_handshake_mutex);
- pthread_mutex_destroy(&thread->startup_handshake_mutex);
+ thread->startup_handshake_lock.lock();
__init_alternate_signal_stack(thread);
@@ -233,14 +230,14 @@
return result;
}
- // Create a mutex for the thread in TLS to wait on once it starts so we can keep
+ // Create a lock for the thread to wait on once it starts so we can keep
// it from doing anything until after we notify the debugger about it
//
// This also provides the memory barrier we need to ensure that all
// memory accesses previously performed by this thread are visible to
// the new thread.
- pthread_mutex_init(&thread->startup_handshake_mutex, NULL);
- pthread_mutex_lock(&thread->startup_handshake_mutex);
+ thread->startup_handshake_lock.init(false);
+ thread->startup_handshake_lock.lock();
thread->start_routine = start_routine;
thread->start_routine_arg = arg;
@@ -263,7 +260,7 @@
// We don't have to unlock the mutex at all because clone(2) failed so there's no child waiting to
// be unblocked, but we're about to unmap the memory the mutex is stored in, so this serves as a
// reminder that you can't rewrite this function to use a ScopedPthreadMutexLocker.
- pthread_mutex_unlock(&thread->startup_handshake_mutex);
+ thread->startup_handshake_lock.unlock();
if (thread->mmap_size != 0) {
munmap(thread->attr.stack_base, thread->mmap_size);
}
@@ -278,13 +275,13 @@
atomic_store(&thread->join_state, THREAD_DETACHED);
__pthread_internal_add(thread);
thread->start_routine = __do_nothing;
- pthread_mutex_unlock(&thread->startup_handshake_mutex);
+ thread->startup_handshake_lock.unlock();
return init_errno;
}
// Publish the pthread_t and unlock the mutex to let the new thread start running.
*thread_out = __pthread_internal_add(thread);
- pthread_mutex_unlock(&thread->startup_handshake_mutex);
+ thread->startup_handshake_lock.unlock();
return 0;
}
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 6a39a21..f96e9d2 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -31,6 +31,7 @@
#include <pthread.h>
#include <stdatomic.h>
+#include "private/bionic_lock.h"
#include "private/bionic_tls.h"
/* Has the thread been detached by a pthread_join or pthread_detach call? */
@@ -51,6 +52,8 @@
THREAD_DETACHED
};
+struct thread_local_dtor;
+
struct pthread_internal_t {
struct pthread_internal_t* next;
struct pthread_internal_t* prev;
@@ -89,10 +92,12 @@
void* alternate_signal_stack;
- pthread_mutex_t startup_handshake_mutex;
+ Lock startup_handshake_lock;
size_t mmap_size;
+ thread_local_dtor* thread_local_dtors;
+
void* tls[BIONIC_TLS_SLOTS];
pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 851fc3d..cad138c 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -166,11 +166,14 @@
#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)
-/* return true iff the mutex if locked with no waiters */
-#define MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
+// Return true iff the mutex is unlocked.
+#define MUTEX_STATE_BITS_IS_UNLOCKED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_UNLOCKED)
-/* 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)
+// 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)
+
+// return true iff the mutex is locked with maybe waiters.
+#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 */
#define MUTEX_STATE_BITS_FLIP_CONTENTION(v) ((v) ^ (MUTEX_STATE_BITS_LOCKED_CONTENDED ^ MUTEX_STATE_BITS_LOCKED_UNCONTENDED))
@@ -296,11 +299,15 @@
*/
static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_internal_t* mutex,
uint16_t shared,
- const timespec* abs_timeout_or_null,
- clockid_t clock) {
+ bool use_realtime_clock,
+ const timespec* abs_timeout_or_null) {
if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {
return 0;
}
+ int result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
+ }
ScopedTrace trace("Contending for pthread mutex");
@@ -317,15 +324,8 @@
// made by other threads visible to the current CPU.
while (atomic_exchange_explicit(&mutex->state, locked_contended,
memory_order_acquire) != unlocked) {
- 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;
- }
- }
- if (__futex_wait_ex(&mutex->state, shared, locked_contended, rel_timeout) == -ETIMEDOUT) {
+ if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock,
+ abs_timeout_or_null) == -ETIMEDOUT) {
return ETIMEDOUT;
}
}
@@ -396,14 +396,15 @@
pthread_mutex_internal_t* mutex,
uint16_t shared,
uint16_t old_state,
- const timespec* rel_timeout) {
+ bool use_realtime_clock,
+ 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
// 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
// owner_tid value in the value argument for __futex_wait, otherwise we may always get EAGAIN error.
#if defined(__LP64__)
- return __futex_wait_ex(&mutex->state, shared, old_state, rel_timeout);
+ return __futex_wait_ex(&mutex->state, shared, old_state, use_realtime_clock, abs_timeout);
#else
// This implementation works only when the layout of pthread_mutex_internal_t matches below expectation.
@@ -412,19 +413,21 @@
static_assert(offsetof(pthread_mutex_internal_t, owner_tid) == 2, "");
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, rel_timeout);
+ return __futex_wait_ex(&mutex->state, shared, (owner_tid << 16) | old_state,
+ use_realtime_clock, abs_timeout);
#endif
}
static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
- const timespec* abs_timeout_or_null, clockid_t clock) {
+ bool use_realtime_clock,
+ const timespec* abs_timeout_or_null) {
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
uint16_t shared = (old_state & MUTEX_SHARED_MASK);
// Handle common case first.
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
- return __pthread_normal_mutex_lock(mutex, shared, abs_timeout_or_null, clock);
+ return __pthread_normal_mutex_lock(mutex, shared, use_realtime_clock, abs_timeout_or_null);
}
// Do we already own this recursive or error-check mutex?
@@ -484,16 +487,13 @@
old_state = new_state;
}
- // We are in locked_contended state, sleep until someone wakes us up.
- 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;
- }
+ int result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
}
- if (__recursive_or_errorcheck_mutex_wait(mutex, shared, old_state, rel_timeout) == -ETIMEDOUT) {
+ // 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,
+ abs_timeout_or_null) == -ETIMEDOUT) {
return ETIMEDOUT;
}
old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
@@ -518,7 +518,7 @@
return 0;
}
}
- return __pthread_mutex_lock_with_timeout(mutex, NULL, 0);
+ return __pthread_mutex_lock_with_timeout(mutex, false, nullptr);
}
int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
@@ -613,17 +613,12 @@
#if !defined(__LP64__)
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;
- 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;
- }
-
+ absolute_timespec_from_timespec(abs_timeout, ts, CLOCK_MONOTONIC);
int error = __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
- &abs_timeout, CLOCK_MONOTONIC);
+ false, &abs_timeout);
if (error == ETIMEDOUT) {
error = EBUSY;
}
@@ -633,14 +628,18 @@
int pthread_mutex_timedlock(pthread_mutex_t* mutex_interface, const timespec* abs_timeout) {
return __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
- abs_timeout, CLOCK_REALTIME);
+ true, abs_timeout);
}
int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
- // Use trylock to ensure that the mutex is valid and not already locked.
- int error = pthread_mutex_trylock(mutex_interface);
- if (error != 0) {
- return error;
+ pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
+ uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
+ // Store 0xffff to make the mutex unusable. Although POSIX standard says it is undefined
+ // behavior to destroy a locked mutex, we prefer not to change mutex->state in that situation.
+ 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;
}
diff --git a/libc/bionic/pthread_once.cpp b/libc/bionic/pthread_once.cpp
index 7688a23..f48eadc 100644
--- a/libc/bionic/pthread_once.cpp
+++ b/libc/bionic/pthread_once.cpp
@@ -79,7 +79,7 @@
}
// The initialization is underway, wait for its finish.
- __futex_wait_ex(once_control_ptr, 0, old_value, NULL);
+ __futex_wait_ex(once_control_ptr, 0, old_value, false, nullptr);
old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire);
}
}
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 934210e..b1c48c8 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -294,9 +294,13 @@
}
while (true) {
- int ret = __pthread_rwlock_tryrdlock(rwlock);
- if (ret == 0 || ret == EAGAIN) {
- return ret;
+ int result = __pthread_rwlock_tryrdlock(rwlock);
+ if (result == 0 || result == EAGAIN) {
+ return result;
+ }
+ result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
}
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
@@ -304,16 +308,6 @@
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_reader_count++;
@@ -327,10 +321,10 @@
int old_serial = rwlock->pending_reader_wakeup_serial;
rwlock->pending_lock.unlock();
- int futex_ret = 0;
+ int futex_result = 0;
if (!__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) {
- futex_ret = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
- old_serial, rel_timeout);
+ futex_result = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
+ old_serial, true, abs_timeout_or_null);
}
rwlock->pending_lock.lock();
@@ -341,7 +335,7 @@
}
rwlock->pending_lock.unlock();
- if (futex_ret == -ETIMEDOUT) {
+ if (futex_result == -ETIMEDOUT) {
return ETIMEDOUT;
}
}
@@ -372,9 +366,13 @@
return EDEADLK;
}
while (true) {
- int ret = __pthread_rwlock_trywrlock(rwlock);
- if (ret == 0) {
- return ret;
+ int result = __pthread_rwlock_trywrlock(rwlock);
+ if (result == 0) {
+ return result;
+ }
+ result = check_timespec(abs_timeout_or_null);
+ if (result != 0) {
+ return result;
}
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
@@ -382,16 +380,6 @@
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_writer_count++;
@@ -401,10 +389,10 @@
int old_serial = rwlock->pending_writer_wakeup_serial;
rwlock->pending_lock.unlock();
- int futex_ret = 0;
+ int futex_result = 0;
if (!__can_acquire_write_lock(old_state)) {
- futex_ret = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
- old_serial, rel_timeout);
+ futex_result = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
+ old_serial, true, abs_timeout_or_null);
}
rwlock->pending_lock.lock();
@@ -415,7 +403,7 @@
}
rwlock->pending_lock.unlock();
- if (futex_ret == -ETIMEDOUT) {
+ if (futex_result == -ETIMEDOUT) {
return ETIMEDOUT;
}
}
@@ -427,7 +415,7 @@
if (__predict_true(__pthread_rwlock_tryrdlock(rwlock) == 0)) {
return 0;
}
- return __pthread_rwlock_timedrdlock(rwlock, NULL);
+ return __pthread_rwlock_timedrdlock(rwlock, nullptr);
}
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {
@@ -446,7 +434,7 @@
if (__predict_true(__pthread_rwlock_trywrlock(rwlock) == 0)) {
return 0;
}
- return __pthread_rwlock_timedwrlock(rwlock, NULL);
+ return __pthread_rwlock_timedwrlock(rwlock, nullptr);
}
int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {
diff --git a/libc/bionic/pthread_spinlock.cpp b/libc/bionic/pthread_spinlock.cpp
new file mode 100644
index 0000000..f26f283
--- /dev/null
+++ b/libc/bionic/pthread_spinlock.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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;
+}
diff --git a/libc/bionic/scandir.cpp b/libc/bionic/scandir.cpp
index ee62fee..e55be42 100644
--- a/libc/bionic/scandir.cpp
+++ b/libc/bionic/scandir.cpp
@@ -16,9 +16,11 @@
#include <dirent.h>
+#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "private/bionic_macros.h"
#include "private/ScopedReaddir.h"
@@ -26,7 +28,7 @@
// A smart pointer to the scandir dirent**.
class ScandirResult {
public:
- ScandirResult() : names_(NULL), size_(0), capacity_(0) {
+ ScandirResult() : names_(nullptr), size_(0), capacity_(0) {
}
~ScandirResult() {
@@ -42,7 +44,7 @@
dirent** release() {
dirent** result = names_;
- names_ = NULL;
+ names_ = nullptr;
size_ = capacity_ = 0;
return result;
}
@@ -52,7 +54,7 @@
size_t new_capacity = capacity_ + 32;
dirent** new_names =
reinterpret_cast<dirent**>(realloc(names_, new_capacity * sizeof(dirent*)));
- if (new_names == NULL) {
+ if (new_names == nullptr) {
return false;
}
names_ = new_names;
@@ -60,7 +62,7 @@
}
dirent* copy = CopyDirent(entry);
- if (copy == NULL) {
+ if (copy == nullptr) {
return false;
}
names_[size_++] = copy;
@@ -69,7 +71,7 @@
void Sort(int (*comparator)(const dirent**, const dirent**)) {
// If we have entries and a comparator, sort them.
- if (size_ > 0 && comparator != NULL) {
+ if (size_ > 0 && comparator != nullptr) {
qsort(names_, size_, sizeof(dirent*),
reinterpret_cast<int (*)(const void*, const void*)>(comparator));
}
@@ -91,19 +93,29 @@
DISALLOW_COPY_AND_ASSIGN(ScandirResult);
};
-int scandir(const char* dirname, dirent*** name_list,
- int (*filter)(const dirent*),
- int (*comparator)(const dirent**, const dirent**)) {
- ScopedReaddir reader(dirname);
+int scandirat(int parent_fd, const char* dir_name, dirent*** name_list,
+ int (*filter)(const dirent*),
+ int (*comparator)(const dirent**, const dirent**)) {
+ DIR* dir = nullptr;
+ if (parent_fd == AT_FDCWD) {
+ dir = opendir(dir_name);
+ } else {
+ int dir_fd = openat(parent_fd, dir_name, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+ if (dir_fd != -1) {
+ dir = fdopendir(dir_fd);
+ }
+ }
+
+ ScopedReaddir reader(dir);
if (reader.IsBad()) {
return -1;
}
ScandirResult names;
dirent* entry;
- while ((entry = reader.ReadEntry()) != NULL) {
+ while ((entry = reader.ReadEntry()) != nullptr) {
// If we have a filter, skip names that don't match.
- if (filter != NULL && !(*filter)(entry)) {
+ if (filter != nullptr && !(*filter)(entry)) {
continue;
}
names.Add(entry);
@@ -115,4 +127,11 @@
*name_list = names.release();
return size;
}
+__strong_alias(scandirat64, scandirat);
+
+int scandir(const char* dir_path, dirent*** name_list,
+ int (*filter)(const dirent*),
+ int (*comparator)(const dirent**, const dirent**)) {
+ return scandirat(AT_FDCWD, dir_path, name_list, filter, comparator);
+}
__strong_alias(scandir64, scandir);
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
index ff84443..79b5d63 100644
--- a/libc/bionic/semaphore.cpp
+++ b/libc/bionic/semaphore.cpp
@@ -220,7 +220,7 @@
return 0;
}
- __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, NULL);
+ __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, false, nullptr);
}
}
@@ -235,36 +235,29 @@
}
// Check it as per POSIX.
- if (abs_timeout == NULL || abs_timeout->tv_sec < 0 || abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= NS_PER_S) {
- errno = EINVAL;
+ int result = check_timespec(abs_timeout);
+ if (result != 0) {
+ errno = result;
return -1;
}
unsigned int shared = SEM_GET_SHARED(sem_count_ptr);
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.
if (__sem_dec(sem_count_ptr) > 0) {
- break;
+ return 0;
}
// Contention detected. Wait for a wakeup event.
- int ret = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, &ts);
+ int result = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, true, abs_timeout);
// Return in case of timeout or interrupt.
- if (ret == -ETIMEDOUT || ret == -EINTR) {
- errno = -ret;
+ if (result == -ETIMEDOUT || result == -EINTR) {
+ errno = -result;
return -1;
}
}
- return 0;
}
int sem_post(sem_t* sem) {
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 74a2f65..13d1882 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -28,12 +28,7 @@
#include <signal.h>
-#ifdef __LP64__
-static
-#else
-__LIBC_HIDDEN__
-#endif
-sighandler_t _signal(int signum, sighandler_t handler, int flags) {
+__LIBC_HIDDEN__ sighandler_t _signal(int signum, sighandler_t handler, int flags) {
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = handler;
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index c436a16..b9a373e 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -25,34 +25,38 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#include <new>
-#include <stdatomic.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stddef.h>
+#include <ctype.h>
#include <errno.h>
-#include <poll.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 <linux/xattr.h>
+#include <netinet/in.h>
#include <sys/mman.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <netinet/in.h>
+#include <sys/un.h>
+#include <sys/xattr.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#include <sys/system_properties.h>
#include "private/bionic_futex.h"
+#include "private/bionic_lock.h"
#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
@@ -112,23 +116,57 @@
DISALLOW_COPY_AND_ASSIGN(prop_bt);
};
-struct prop_area {
- uint32_t bytes_used;
- atomic_uint_least32_t serial;
- uint32_t magic;
- uint32_t version;
- uint32_t reserved[28];
- char data[0];
+class prop_area {
+public:
prop_area(const uint32_t magic, const uint32_t version) :
- magic(magic), version(version) {
- atomic_init(&serial, 0);
- memset(reserved, 0, sizeof(reserved));
+ magic_(magic), version_(version) {
+ atomic_init(&serial_, 0);
+ memset(reserved_, 0, sizeof(reserved_));
// 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:
+ 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);
};
@@ -158,7 +196,7 @@
}
};
-static char property_filename[PATH_MAX] = PROP_FILENAME;
+static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
static bool compat_mode = false;
static size_t pa_data_size;
static size_t pa_size;
@@ -182,13 +220,12 @@
return atoi(env);
}
-static int map_prop_area_rw()
-{
+static prop_area* map_prop_area_rw(const char* filename, const char* context,
+ bool* fsetxattr_failed) {
/* dev is a tmpfs that we can use to carve a shared workspace
* out of, so let's do that...
*/
- const int fd = open(property_filename,
- O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
+ const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
if (fd < 0) {
if (errno == EACCES) {
@@ -197,12 +234,31 @@
*/
abort();
}
- return -1;
+ return nullptr;
+ }
+
+ 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) {
close(fd);
- return -1;
+ return nullptr;
}
pa_size = PA_SIZE;
@@ -212,29 +268,26 @@
void *const memory_area = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (memory_area == MAP_FAILED) {
close(fd);
- return -1;
+ return nullptr;
}
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);
- return 0;
+ return pa;
}
-static int map_fd_ro(const int fd) {
+static prop_area* map_fd_ro(const int fd) {
struct stat fd_stat;
if (fstat(fd, &fd_stat) < 0) {
- return -1;
+ return nullptr;
}
if ((fd_stat.st_uid != 0)
|| (fd_stat.st_gid != 0)
|| ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|| (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area))) ) {
- return -1;
+ return nullptr;
}
pa_size = fd_stat.st_size;
@@ -242,29 +295,28 @@
void* const map_result = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
if (map_result == MAP_FAILED) {
- return -1;
+ return nullptr;
}
prop_area* pa = reinterpret_cast<prop_area*>(map_result);
- if ((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
- pa->version != PROP_AREA_VERSION_COMPAT)) {
+ if ((pa->magic() != PROP_AREA_MAGIC) ||
+ (pa->version() != PROP_AREA_VERSION &&
+ pa->version() != PROP_AREA_VERSION_COMPAT)) {
munmap(pa, pa_size);
- return -1;
+ return nullptr;
}
- if (pa->version == PROP_AREA_VERSION_COMPAT) {
+ if (pa->version() == PROP_AREA_VERSION_COMPAT) {
compat_mode = true;
}
- __system_property_area__ = pa;
- return 0;
+ return pa;
}
-static int map_prop_area()
-{
- int fd = open(property_filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
+static prop_area* map_prop_area(const char* filename, bool is_legacy) {
+ int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
bool close_fd = true;
- if (fd == -1 && errno == ENOENT) {
+ if (fd == -1 && errno == ENOENT && is_legacy) {
/*
* For backwards compatibility, if the file doesn't
* exist, we use the environment to get the file descriptor.
@@ -273,16 +325,18 @@
* returns other errors such as ENOMEM or ENFILE, since it
* might be possible for an external program to trigger this
* condition.
+ * Only do this for the legacy prop file, secured prop files
+ * do not have a backup
*/
fd = get_fd_from_env();
close_fd = false;
}
if (fd < 0) {
- return -1;
+ return nullptr;
}
- const int map_result = map_fd_ro(fd);
+ prop_area* map_result = map_fd_ro(fd);
if (close_fd) {
close(fd);
}
@@ -290,20 +344,19 @@
return map_result;
}
-static void *allocate_obj(const size_t size, uint_least32_t *const off)
+void *prop_area::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));
- if (pa->bytes_used + aligned > pa_data_size) {
+ if (bytes_used_ + aligned > pa_data_size) {
return NULL;
}
- *off = pa->bytes_used;
- pa->bytes_used += aligned;
- return pa->data + *off;
+ *off = bytes_used_;
+ bytes_used_ += aligned;
+ return data_ + *off;
}
-static prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
+prop_bt *prop_area::new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
{
uint_least32_t new_offset;
void *const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
@@ -316,7 +369,7 @@
return NULL;
}
-static prop_info *new_prop_info(const char *name, uint8_t namelen,
+prop_info *prop_area::new_prop_info(const char *name, uint8_t namelen,
const char *value, uint8_t valuelen, uint_least32_t *const off)
{
uint_least32_t new_offset;
@@ -330,27 +383,25 @@
return NULL;
}
-static void *to_prop_obj(uint_least32_t off)
+void *prop_area::to_prop_obj(uint_least32_t off)
{
if (off > pa_data_size)
return NULL;
- if (!__system_property_area__)
- return NULL;
- return (__system_property_area__->data + off);
+ return (data_ + off);
}
-static inline prop_bt *to_prop_bt(atomic_uint_least32_t* off_p) {
+inline prop_bt *prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_bt*>(to_prop_obj(off));
}
-static inline prop_info *to_prop_info(atomic_uint_least32_t* off_p) {
+inline prop_info *prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
return reinterpret_cast<prop_info*>(to_prop_obj(off));
}
-static inline prop_bt *root_node()
+inline prop_bt *prop_area::root_node()
{
return reinterpret_cast<prop_bt*>(to_prop_obj(0));
}
@@ -366,8 +417,8 @@
return strncmp(one, two, one_len);
}
-static prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
- uint8_t namelen, bool alloc_if_needed)
+prop_bt *prop_area::find_prop_bt(prop_bt *const bt, const char *name,
+ uint8_t namelen, bool alloc_if_needed)
{
prop_bt* current = bt;
@@ -417,7 +468,7 @@
}
}
-static const prop_info *find_property(prop_bt *const trie, const char *name,
+const prop_info *prop_area::find_property(prop_bt *const trie, const char *name,
uint8_t namelen, const char *value, uint8_t valuelen,
bool alloc_if_needed)
{
@@ -543,44 +594,383 @@
cookie->count++;
}
-static int foreach_property(prop_bt *const trie,
+bool prop_area::foreach_property(prop_bt *const trie,
void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
{
if (!trie)
- return -1;
+ return false;
uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
if (left_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
if (err < 0)
- return -1;
+ return false;
}
uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
if (prop_offset != 0) {
prop_info *info = to_prop_info(&trie->prop);
if (!info)
- return -1;
+ return false;
propfn(info, cookie);
}
uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
if (children_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
if (err < 0)
- return -1;
+ return false;
}
uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
if (right_offset != 0) {
const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
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);
+}
+
+struct context_node {
+ context_node(struct context_node* next, const char* context, prop_area* pa)
+ : context(strdup(context)), pa(pa), checked_access(false), next(next) {
+ lock.init(false);
+ }
+ ~context_node() {
+ if (pa) {
+ munmap(pa, pa_size);
+ }
+ free(context);
+ }
+ Lock lock;
+ char* context;
+ prop_area* pa;
+ bool checked_access;
+ struct context_node* next;
+};
+
+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.
+ */
+
+static bool open_prop_file(context_node* cnode, bool access_rw, bool* fsetxattr_failed) {
+ cnode->lock.lock();
+ if (cnode->pa) {
+ cnode->lock.unlock();
+ return true;
+ }
+
+ char filename[PROP_FILENAME_MAX];
+ int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
+ if (len < 0 || len > PROP_FILENAME_MAX) {
+ cnode->lock.unlock();
+ return false;
+ }
+
+ if (access_rw) {
+ cnode->pa = map_prop_area_rw(filename, cnode->context, fsetxattr_failed);
+ } else {
+ cnode->pa = map_prop_area(filename, false);
+ }
+ cnode->lock.unlock();
+ return cnode->pa;
+}
+
+static bool check_access(context_node* cnode) {
+ char filename[PROP_FILENAME_MAX];
+ int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
+ if (len < 0 || len > PROP_FILENAME_MAX) {
+ return false;
+ }
+
+ return access(filename, R_OK) == 0;
+}
+
+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) {
+ open_prop_file(cnode, 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 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() {
+ list_free(&prefixes);
+ list_free(&contexts);
+
+ 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);
+}
+
int __system_properties_init()
{
- return map_prop_area();
+ if (is_dir(property_filename)) {
+ if (!initialize_properties()) {
+ return -1;
+ }
+ if (!map_system_property_area(false, nullptr)) {
+ list_free(&prefixes);
+ list_free(&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);
+ }
+ return 0;
}
int __system_property_set_filename(const char *filename)
@@ -595,7 +985,23 @@
int __system_property_area_init()
{
- 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_prop_file_failed = false;
+ bool fsetxattr_failed = false;
+ list_foreach(contexts, [&fsetxattr_failed, &open_prop_file_failed](context_node* l) {
+ if (!open_prop_file(l, true, &fsetxattr_failed)) {
+ open_prop_file_failed = true;
+ }
+ });
+ if (open_prop_file_failed || !map_system_property_area(true, &fsetxattr_failed)) {
+ list_free(&prefixes);
+ list_free(&contexts);
+ return -1;
+ }
+ return fsetxattr_failed ? -2 : 0;
}
unsigned int __system_property_area_serial()
@@ -605,15 +1011,26 @@
return -1;
}
// 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)
{
+ if (!__system_property_area__) {
+ return nullptr;
+ }
+
if (__predict_false(compat_mode)) {
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,
@@ -688,11 +1105,15 @@
int __system_property_update(prop_info *pi, const char *value, unsigned int len)
{
- prop_area *pa = __system_property_area__;
-
if (len >= PROP_VALUE_MAX)
return -1;
+ prop_area* pa = __system_property_area__;
+
+ if (!pa) {
+ return -1;
+ }
+
uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
serial |= 1;
atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
@@ -708,10 +1129,10 @@
__futex_wake(&pi->serial, INT32_MAX);
atomic_store_explicit(
- &pa->serial,
- atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+ pa->serial(),
+ atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
memory_order_release);
- __futex_wake(&pa->serial, INT32_MAX);
+ __futex_wake(pa->serial(), INT32_MAX);
return 0;
}
@@ -719,9 +1140,6 @@
int __system_property_add(const char *name, unsigned int namelen,
const char *value, unsigned int valuelen)
{
- prop_area *pa = __system_property_area__;
- const prop_info *pi;
-
if (namelen >= PROP_NAME_MAX)
return -1;
if (valuelen >= PROP_VALUE_MAX)
@@ -729,17 +1147,28 @@
if (namelen < 1)
return -1;
- pi = find_property(root_node(), name, namelen, value, valuelen, true);
- if (!pi)
+ if (!__system_property_area__) {
+ return -1;
+ }
+
+ 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;
// There is only a single mutator, but we want to make sure that
// updates are visible to a reader waiting for the update.
atomic_store_explicit(
- &pa->serial,
- atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
+ __system_property_area__->serial(),
+ atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1,
memory_order_release);
- __futex_wake(&pa->serial, INT32_MAX);
+ __futex_wake(__system_property_area__->serial(), INT32_MAX);
return 0;
}
@@ -761,9 +1190,13 @@
prop_area *pa = __system_property_area__;
uint32_t my_serial;
+ if (!pa) {
+ return 0;
+ }
+
do {
- __futex_wait(&pa->serial, serial, NULL);
- my_serial = atomic_load_explicit(&pa->serial, memory_order_acquire);
+ __futex_wait(pa->serial(), serial, NULL);
+ my_serial = atomic_load_explicit(pa->serial(), memory_order_acquire);
} while (my_serial == serial);
return my_serial;
@@ -784,9 +1217,24 @@
int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
void *cookie)
{
+ if (!__system_property_area__) {
+ return -1;
+ }
+
if (__predict_false(compat_mode)) {
return __system_property_foreach_compat(propfn, cookie);
}
- return foreach_property(root_node(), propfn, cookie);
+ list_foreach(contexts, [propfn, cookie](context_node* l) {
+ if (!l->pa && !l->checked_access) {
+ if (check_access(l)) {
+ open_prop_file(l, false, nullptr);
+ }
+ l->checked_access = true;
+ }
+ if (l->pa) {
+ l->pa->foreach(propfn, cookie);
+ }
+ });
+ return 0;
}
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index 40f610f..ed9a3b9 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -80,6 +80,29 @@
*/
ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
+ /* Instructs dlopen to load the library at the address specified by reserved_addr.
+ *
+ * The difference between ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS and ANDROID_DLEXT_RESERVED_ADDRESS
+ * is that for ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS the linker reserves memory at reserved_addr
+ * whereas for ANDROID_DLEXT_RESERVED_ADDRESS the linker relies on the caller to reserve the memory.
+ *
+ * This flag can be used with ANDROID_DLEXT_FORCE_FIXED_VADDR; when ANDROID_DLEXT_FORCE_FIXED_VADDR
+ * is set and load_bias is not 0 (load_bias is min(p_vaddr) of PT_LOAD segments) this flag is ignored.
+ * This is implemented this way because the linker has to pick one address over the other and this
+ * way is more convenient for art. Note that ANDROID_DLEXT_FORCE_FIXED_VADDR does not generate
+ * an error when min(p_vaddr) is 0.
+ *
+ * Cannot be used with ANDROID_DLEXT_RESERVED_ADDRESS or ANDROID_DLEXT_RESERVED_ADDRESS_HINT.
+ *
+ * This flag is for ART internal use only.
+ */
+ 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 */
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
@@ -88,9 +111,13 @@
ANDROID_DLEXT_USE_LIBRARY_FD |
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
ANDROID_DLEXT_FORCE_LOAD |
- ANDROID_DLEXT_FORCE_FIXED_VADDR,
+ ANDROID_DLEXT_FORCE_FIXED_VADDR |
+ ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS |
+ ANDROID_DLEXT_USE_NAMESPACE,
};
+struct android_namespace_t;
+
typedef struct {
uint64_t flags;
void* reserved_addr;
@@ -98,10 +125,44 @@
int relro_fd;
int library_fd;
off64_t library_fd_offset;
+ struct android_namespace_t* library_namespace;
} android_dlextinfo;
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);
+
+/*
+ * 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 is_isolated is true the resulted namespace requires all of the libraries
+ * to be on the search path; the search_path is ld_library_path:default_library_path.
+ *
+ * If a library or any of its dependencies are outside of the search path and 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,
+ bool is_isolated);
+
__END_DECLS
#endif /* __ANDROID_DLEXT_H__ */
diff --git a/libc/include/byteswap.h b/libc/include/byteswap.h
index 74b0e91..628fb7f 100644
--- a/libc/include/byteswap.h
+++ b/libc/include/byteswap.h
@@ -28,11 +28,10 @@
#ifndef _BYTESWAP_H_
#define _BYTESWAP_H_
-/* endian.h rather than sys/endian.h so we get the machine-specific file. */
-#include <endian.h>
+#include <sys/endian.h>
-#define bswap_16(x) swap16(x)
-#define bswap_32(x) swap32(x)
-#define bswap_64(x) swap64(x)
+#define bswap_16(x) __swap16(x)
+#define bswap_32(x) __swap32(x)
+#define bswap_64(x) __swap64(x)
#endif /* _BYTESWAP_H_ */
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index 63716a4..3cdfa68 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -81,8 +81,13 @@
extern int dirfd(DIR*);
extern int alphasort(const struct dirent**, const struct dirent**);
extern int alphasort64(const struct dirent64**, const struct dirent64**);
-extern int scandir(const char*, struct dirent***, int (*)(const struct dirent*), int (*)(const struct dirent**, const struct dirent**));
extern int scandir64(const char*, struct dirent64***, int (*)(const struct dirent64*), int (*)(const struct dirent64**, const struct dirent64**));
+extern int scandir(const char*, struct dirent***, int (*)(const struct dirent*), int (*)(const struct dirent**, const struct dirent**));
+
+#if defined(__USE_GNU)
+int scandirat64(int, const char*, struct dirent64***, int (*)(const struct dirent64*), int (*)(const struct dirent64**, const struct dirent64**));
+int scandirat(int, const char*, struct dirent***, int (*)(const struct dirent*), int (*)(const struct dirent**, const struct dirent**));
+#endif
__END_DECLS
diff --git a/libc/include/libgen.h b/libc/include/libgen.h
index e89328e..4d22d15 100644
--- a/libc/include/libgen.h
+++ b/libc/include/libgen.h
@@ -32,18 +32,19 @@
#include <sys/cdefs.h>
#include <sys/types.h>
+
__BEGIN_DECLS
-#if !defined(__bionic_using_gnu_basename)
/*
- * <string.h> gets you the GNU basename.
- * <libgen.h> the POSIX one.
- * Note that our "POSIX" one has the wrong argument cv-qualifiers, but doesn't
- * modify its input and uses thread-local storage for the result if necessary.
+ * Including <string.h> will get you the GNU basename, unless <libgen.h> is
+ * included, either before or after including <string.h>.
+ *
+ * Note that 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* basename(const char*);
-#define __bionic_using_posix_basename
-#endif
+extern char* __posix_basename(const char*) __RENAME(basename);
+
+#define basename __posix_basename
/* 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*);
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 260ae5b..21d34fb 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -96,6 +96,26 @@
#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__)
#define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
#else
@@ -130,7 +150,7 @@
int pthread_attr_setschedpolicy(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_setstacksize(pthread_attr_t*, size_t stack_size) __nonnull((1));
+int pthread_attr_setstacksize(pthread_attr_t*, size_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));
@@ -205,9 +225,24 @@
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_trywrlock(pthread_rwlock_t*) __nonnull((1));
-int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) __nonnull((1));
+int pthread_rwlock_unlock(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;
int pthread_setname_np(pthread_t, const char*) __nonnull((2));
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 1df4b54..fd653d9 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -270,6 +270,7 @@
void clearerr_unlocked(FILE*);
int feof_unlocked(FILE*);
int ferror_unlocked(FILE*);
+int fileno_unlocked(FILE*);
/*
* Stdio function-access interface.
diff --git a/libc/include/string.h b/libc/include/string.h
index 2c50cfa..32d4a18 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -115,18 +115,18 @@
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);
-#if defined(__USE_GNU) && !defined(__bionic_using_posix_basename)
+#if defined(__USE_GNU) && !defined(basename)
/*
* 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.
*/
+
#if defined(__cplusplus)
extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1));
extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
#else
extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
#endif
-#define __bionic_using_gnu_basename
#endif
extern void* __memchr_chk(const void*, int, size_t, size_t);
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index a0315b5..3b1f7d0 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -41,6 +41,7 @@
#define PROP_AREA_VERSION_COMPAT 0x45434f76
#define PROP_SERVICE_NAME "property_service"
+#define PROP_FILENAME_MAX 1024
#define PROP_FILENAME "/dev/__properties__"
#define PA_SIZE (128 * 1024)
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 58038cd..342cfad 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -432,9 +432,9 @@
/* Like __LIBC_HIDDEN__, but preserves binary compatibility for LP32. */
#ifdef __LP64__
-#define __LIBC64_HIDDEN__ __LIBC_HIDDEN__
+#define __LIBC32_LEGACY_PUBLIC__ __LIBC_HIDDEN__
#else
-#define __LIBC64_HIDDEN__ __LIBC_ABI_PUBLIC__
+#define __LIBC32_LEGACY_PUBLIC__ __LIBC_ABI_PUBLIC__
#endif
/* Used to tag non-static symbols that are public and exposed by the shared library. */
diff --git a/libc/include/sys/endian.h b/libc/include/sys/endian.h
index 2fd480d..60cc030 100644
--- a/libc/include/sys/endian.h
+++ b/libc/include/sys/endian.h
@@ -75,10 +75,6 @@
#define HTONL(x) (x) = htonl((u_int32_t)(x))
#define HTONS(x) (x) = htons((u_int16_t)(x))
-#define swap16 __swap16
-#define swap32 __swap32
-#define swap64 __swap64
-
#define htobe16 __swap16
#define htobe32 __swap32
#define htobe64 __swap64
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 6857f60..a19ceb5 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -59,7 +59,7 @@
extern int munmap(void*, size_t);
extern int msync(const void*, size_t, int);
extern int mprotect(const void*, size_t, int);
-extern void* mremap(void*, size_t, size_t, unsigned long);
+extern void* mremap(void*, size_t, size_t, int, ...);
extern int mlockall(int);
extern int munlockall(void);
diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h
index 3f8dd45..8209dfb 100644
--- a/libc/include/sys/resource.h
+++ b/libc/include/sys/resource.h
@@ -53,10 +53,7 @@
extern int getrusage(int, struct rusage*);
-#if __LP64__
-/* Implementing prlimit for 32-bit isn't worth the effort. */
extern int prlimit(pid_t, int, const struct rlimit*, struct rlimit*);
-#endif
extern int prlimit64(pid_t, int, const struct rlimit64*, struct rlimit64*);
__END_DECLS
diff --git a/libc/include/sys/shm.h b/libc/include/sys/shm.h
deleted file mode 100644
index c691c29..0000000
--- a/libc/include/sys/shm.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _SYS_SHM_H_
-#define _SYS_SHM_H_
-
-#include <linux/shm.h>
-
-#endif /* _SYS_SHM_H_ */
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index 7eeea41..c6f22a5 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -97,8 +97,9 @@
__BEGIN_DECLS
int utmpname(const char*);
-void setutent();
-struct utmp* getutent();
+void setutent(void);
+struct utmp* getutent(void);
+void endutent(void);
int login_tty(int);
diff --git a/libc/libc.map b/libc/libc.arm.map
similarity index 95%
copy from libc/libc.map
copy to libc/libc.arm.map
index fbceb83..69aa272 100644
--- a/libc/libc.map
+++ b/libc/libc.arm.map
@@ -1,3 +1,4 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
@@ -28,7 +29,6 @@
__errno;
__exit; # arm x86 mips
__extendsfdf2; # arm
- __fadvise64; # x86 mips
__fbufsize;
__fcntl64; # arm x86 mips
__FD_CLR_chk;
@@ -105,7 +105,6 @@
__memrchr_chk;
__memset_chk;
__mmap2; # arm x86 mips
- __moddi3; # x86 mips
__muldf3; # arm
__muldi3; # arm
__mulsf3; # arm
@@ -205,7 +204,6 @@
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
- __set_thread_area; # x86
__set_tid_address; # arm x86 mips
__set_tls; # arm mips
__sF;
@@ -272,7 +270,6 @@
__udivdi3; # arm x86 mips
__udivsi3; # arm
__umask_chk;
- __umoddi3; # x86 mips
__unorddf2; # arm
__unordsf2; # arm
__vsnprintf_chk;
@@ -282,7 +279,6 @@
_ctype_;
_Exit;
_exit;
- _flush_cache; # mips
_flushlbf;
_fwalk; # arm x86 mips
_getlong;
@@ -389,7 +385,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -580,7 +575,6 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
@@ -780,28 +774,6 @@
nftw64;
nice;
nrand48;
- ns_format_ttl; # arm64 x86_64 mips64
- ns_get16; # arm64 x86_64 mips64
- ns_get32; # arm64 x86_64 mips64
- ns_initparse; # arm64 x86_64 mips64
- ns_makecanon; # arm64 x86_64 mips64
- ns_msg_getflag; # arm64 x86_64 mips64
- ns_name_compress; # arm64 x86_64 mips64
- ns_name_ntol; # arm64 x86_64 mips64
- ns_name_ntop; # arm64 x86_64 mips64
- ns_name_pack; # arm64 x86_64 mips64
- ns_name_pton; # arm64 x86_64 mips64
- ns_name_rollback; # arm64 x86_64 mips64
- ns_name_skip; # arm64 x86_64 mips64
- ns_name_uncompress; # arm64 x86_64 mips64
- ns_name_unpack; # arm64 x86_64 mips64
- ns_parserr; # arm64 x86_64 mips64
- ns_put16; # arm64 x86_64 mips64
- ns_put32; # arm64 x86_64 mips64
- ns_samename; # arm64 x86_64 mips64
- ns_skiprr; # arm64 x86_64 mips64
- ns_sprintrr; # arm64 x86_64 mips64
- ns_sprintrrf; # arm64 x86_64 mips64
nsdispatch;
ntohl;
ntohs;
@@ -840,7 +812,6 @@
pread;
pread64;
printf;
- prlimit; # arm64 x86_64 mips64
prlimit64;
process_vm_readv;
process_vm_writev;
@@ -1051,7 +1022,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1340,12 +1310,28 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
preadv64;
+ 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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
diff --git a/libc/libc.map b/libc/libc.arm64.map
similarity index 68%
copy from libc/libc.map
copy to libc/libc.arm64.map
index fbceb83..763f77e 100644
--- a/libc/libc.map
+++ b/libc/libc.arm64.map
@@ -1,52 +1,25 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
__assert2;
- __atomic_cmpxchg; # arm
- __atomic_dec; # arm
- __atomic_inc; # arm
- __atomic_swap; # arm
__b64_ntop;
__b64_pton;
- __brk; # arm x86 mips
- __cmpdf2; # arm
__cmsg_nxthdr;
- __connect; # arm x86 mips
__ctype_get_mb_cur_max;
__cxa_atexit;
__cxa_finalize;
__cxa_thread_atexit_impl;
- __divdf3; # arm
- __divdi3; # arm x86 mips
- __divsf3; # arm
- __divsi3; # arm
__dn_comp;
__dn_count_labels;
__dn_skipname;
- __epoll_pwait; # arm x86 mips
- __eqdf2; # arm
__errno;
- __exit; # arm x86 mips
- __extendsfdf2; # arm
- __fadvise64; # x86 mips
__fbufsize;
- __fcntl64; # arm x86 mips
__FD_CLR_chk;
__FD_ISSET_chk;
__FD_SET_chk;
__fgets_chk;
- __fixdfsi; # arm
- __fixsfsi; # arm
- __fixunssfsi; # arm
__flbf;
- __floatdidf; # arm
- __floatdisf; # arm
- __floatsidf; # arm
- __floatsisf; # arm
- __floatundidf; # arm
- __floatundisf; # arm
- __floatunsidf; # arm
- __floatunsisf; # arm
__fp_nquery;
__fp_query;
__fpclassify;
@@ -57,26 +30,11 @@
__fpurge;
__freadable;
__fsetlocking;
- __fstatfs64; # arm x86 mips
- __futex_wait; # arm x86 mips
- __futex_wake; # arm x86 mips
__fwritable;
- __gedf2; # arm
__get_h_errno;
- __get_thread; # arm x86 mips
- __get_tls; # arm x86 mips
- __getcpu; # arm x86 mips
- __getcwd; # arm x86 mips
- __getdents64; # arm x86 mips
- __getpid; # arm x86 mips
- __getpriority; # arm x86 mips
__gnu_basename;
- __gnu_ldivmod_helper; # arm
__gnu_strerror_r;
- __gnu_uldivmod_helper; # arm
- __gtdf2; # arm
__hostalias;
- __ioctl; # arm x86 mips
__isfinite;
__isfinitef;
__isfinitel;
@@ -90,51 +48,17 @@
__isnormalf;
__isnormall;
__isthreaded;
- __ledf2; # arm
__libc_current_sigrtmax;
__libc_current_sigrtmin;
__libc_init;
- __llseek; # arm x86 mips
__loc_aton;
__loc_ntoa;
- __lshrdi3; # arm
- __ltdf2; # arm
__memchr_chk;
__memcpy_chk;
__memmove_chk;
__memrchr_chk;
__memset_chk;
- __mmap2; # arm x86 mips
- __moddi3; # x86 mips
- __muldf3; # arm
- __muldi3; # arm
- __mulsf3; # arm
- __nedf2; # arm
- __ns_format_ttl; # arm x86 mips
- __ns_get16; # arm x86 mips
- __ns_get32; # arm x86 mips
- __ns_initparse; # arm x86 mips
- __ns_makecanon; # arm x86 mips
- __ns_msg_getflag; # arm x86 mips
- __ns_name_compress; # arm x86 mips
- __ns_name_ntol; # arm x86 mips
- __ns_name_ntop; # arm x86 mips
- __ns_name_pack; # arm x86 mips
- __ns_name_pton; # arm x86 mips
- __ns_name_rollback; # arm x86 mips
- __ns_name_skip; # arm x86 mips
- __ns_name_uncompress; # arm x86 mips
- __ns_name_unpack; # arm x86 mips
- __ns_parserr; # arm x86 mips
- __ns_put16; # arm x86 mips
- __ns_put32; # arm x86 mips
- __ns_samename; # arm x86 mips
- __ns_skiprr; # arm x86 mips
- __ns_sprintrr; # arm x86 mips
- __ns_sprintrrf; # arm x86 mips
- __open; # arm x86 mips
__open_2;
- __openat; # arm x86 mips
__openat_2;
__p_cdname;
__p_cdnname;
@@ -149,27 +73,18 @@
__p_time;
__p_type;
__p_type_syms;
- __page_shift; # arm x86 mips
- __page_size; # arm x86 mips
__poll_chk;
- __popcount_tab; # arm
- __popcountsi2; # arm x86 mips
- __ppoll; # arm x86 mips
__ppoll_chk;
__pread64_chk;
__pread_chk;
__progname;
- __pselect6; # arm x86 mips
__pthread_cleanup_pop;
__pthread_cleanup_push;
- __pthread_gettid; # arm x86 mips
- __ptrace; # arm x86 mips
__putlong;
__putshort;
__read_chk;
__readlink_chk;
__readlinkat_chk;
- __reboot; # arm x86 mips
__recvfrom_chk;
__register_atfork;
__res_close;
@@ -192,41 +107,14 @@
__res_send;
__res_send_setqhook;
__res_send_setrhook;
- __restore_core_regs; # arm
- __rt_sigaction; # arm x86 mips
- __rt_sigpending; # arm x86 mips
- __rt_sigprocmask; # arm x86 mips
- __rt_sigsuspend; # arm x86 mips
- __rt_sigtimedwait; # arm x86 mips
__sched_cpualloc;
__sched_cpucount;
__sched_cpufree;
- __sched_getaffinity; # arm x86 mips
- __sclose; # arm x86 mips
- __sdidinit; # arm x86 mips
- __set_errno; # arm x86 mips
- __set_thread_area; # x86
- __set_tid_address; # arm x86 mips
- __set_tls; # arm mips
__sF;
- __sflags; # arm x86 mips
- __sflush; # arm x86 mips
- __sfp; # arm x86 mips
- __sglue; # arm x86 mips
- __sigaction; # arm x86 mips
- __signalfd4; # arm x86 mips
- __sinit; # arm x86 mips
- __smakebuf; # arm x86 mips
__snprintf_chk;
- __socket; # arm x86 mips
__sprintf_chk;
- __sread; # arm x86 mips
- __srefill; # arm x86 mips
- __srget; # arm x86 mips
- __sseek; # arm x86 mips
__stack_chk_fail;
__stack_chk_guard;
- __statfs64; # arm x86 mips
__stpcpy_chk;
__stpncpy_chk;
__stpncpy_chk2;
@@ -240,11 +128,6 @@
__strncpy_chk;
__strncpy_chk2;
__strrchr_chk;
- __subdf3; # arm
- __subsf3; # arm
- __swbuf; # arm x86 mips
- __swrite; # arm x86 mips
- __swsetup; # arm x86 mips
__sym_ntop;
__sym_ntos;
__sym_ston;
@@ -263,28 +146,13 @@
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
- __timer_create; # arm x86 mips
- __timer_delete; # arm x86 mips
- __timer_getoverrun; # arm x86 mips
- __timer_gettime; # arm x86 mips
- __timer_settime; # arm x86 mips
- __truncdfsf2; # arm
- __udivdi3; # arm x86 mips
- __udivsi3; # arm
__umask_chk;
- __umoddi3; # x86 mips
- __unorddf2; # arm
- __unordsf2; # arm
__vsnprintf_chk;
__vsprintf_chk;
- __wait4; # arm x86 mips
- __waitid; # arm x86 mips
_ctype_;
_Exit;
_exit;
- _flush_cache; # mips
_flushlbf;
- _fwalk; # arm x86 mips
_getlong;
_getshort;
_longjmp;
@@ -293,9 +161,7 @@
_resolv_set_nameservers_for_net;
_setjmp;
_tolower;
- _tolower_tab_; # arm x86 mips
_toupper;
- _toupper_tab_; # arm x86 mips
abort;
abs;
accept;
@@ -311,13 +177,9 @@
android_gethostbynamefornet;
android_set_abort_message;
arc4random;
- arc4random_addrandom; # arm x86 mips
arc4random_buf;
- arc4random_stir; # arm x86 mips
arc4random_uniform;
asctime;
- asctime64; # arm x86 mips
- asctime64_r; # arm x86 mips
asctime_r;
asprintf;
at_quick_exit;
@@ -326,18 +188,13 @@
atol;
atoll;
basename;
- basename_r; # arm x86 mips
- bcopy; # arm x86 mips
bind;
bindresvport;
brk;
- bsd_signal; # arm x86 mips
bsearch;
btowc;
- bzero; # arm x86 mips
c16rtomb;
c32rtomb;
- cacheflush; # arm mips
calloc;
capget;
capset;
@@ -368,8 +225,6 @@
creat;
creat64;
ctime;
- ctime64; # arm x86 mips
- ctime64_r; # arm x86 mips
ctime_r;
daemon;
daylight;
@@ -377,7 +232,6 @@
difftime;
dirfd;
dirname;
- dirname_r; # arm x86 mips
div;
dn_expand;
dprintf;
@@ -389,7 +243,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -421,8 +274,6 @@
execvpe;
exit;
faccessat;
- fake_gmtime_r; # arm x86 mips
- fake_localtime_r; # arm x86 mips
fallocate;
fallocate64;
fchdir;
@@ -435,7 +286,6 @@
fdatasync;
fdopen;
fdopendir;
- fdprintf; # arm x86 mips
feof;
feof_unlocked;
ferror;
@@ -488,7 +338,6 @@
fsync;
ftell;
ftello;
- ftime; # arm x86 mips
ftok;
ftruncate;
ftruncate64;
@@ -521,8 +370,6 @@
getchar_unlocked;
getcwd;
getdelim;
- getdents; # arm x86 mips
- getdtablesize; # arm x86 mips
getegid;
getenv;
geteuid;
@@ -580,14 +427,11 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
getxattr;
gmtime;
- gmtime64; # arm x86 mips
- gmtime64_r; # arm x86 mips
gmtime_r;
grantpt;
herror;
@@ -598,7 +442,6 @@
if_nametoindex;
imaxabs;
imaxdiv;
- index; # arm x86 mips
inet_addr;
inet_aton;
inet_lnaof;
@@ -651,7 +494,6 @@
isprint_l;
ispunct;
ispunct_l;
- issetugid; # arm x86 mips
isspace;
isspace_l;
isupper;
@@ -704,8 +546,6 @@
llistxattr;
localeconv;
localtime;
- localtime64; # arm x86 mips
- localtime64_r; # arm x86 mips
localtime_r;
login_tty;
longjmp;
@@ -741,7 +581,6 @@
mempcpy;
memrchr;
memset;
- memswap; # arm x86 mips
mincore;
mkdir;
mkdirat;
@@ -760,7 +599,6 @@
mkstemps64;
mktemp;
mktime;
- mktime64; # arm x86 mips
mktime_tz;
mlock;
mlockall;
@@ -855,7 +693,6 @@
pthread_attr_getschedpolicy;
pthread_attr_getscope;
pthread_attr_getstack;
- pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize;
pthread_attr_init;
pthread_attr_setdetachstate;
@@ -864,17 +701,12 @@
pthread_attr_setschedpolicy;
pthread_attr_setscope;
pthread_attr_setstack;
- pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize;
pthread_cond_broadcast;
pthread_cond_destroy;
pthread_cond_init;
pthread_cond_signal;
pthread_cond_timedwait;
- pthread_cond_timedwait_monotonic; # arm x86 mips
- pthread_cond_timedwait_monotonic_np; # arm x86 mips
- pthread_cond_timedwait_relative_np; # arm x86 mips
- pthread_cond_timeout_np; # arm x86 mips
pthread_cond_wait;
pthread_condattr_destroy;
pthread_condattr_getclock;
@@ -898,7 +730,6 @@
pthread_mutex_destroy;
pthread_mutex_init;
pthread_mutex_lock;
- pthread_mutex_lock_timeout_np; # arm x86 mips
pthread_mutex_timedlock;
pthread_mutex_trylock;
pthread_mutex_unlock;
@@ -939,10 +770,8 @@
putenv;
puts;
pututline;
- putw; # arm x86 mips
putwc;
putwchar;
- pvalloc; # arm x86 mips
pwrite;
pwrite64;
qsort;
@@ -980,7 +809,6 @@
res_mkquery;
res_query;
res_search;
- restore_core_regs; # arm
rewind;
rewinddir;
rmdir;
@@ -1051,7 +879,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1124,8 +951,6 @@
strncpy;
strndup;
strnlen;
- strntoimax; # arm x86 mips
- strntoumax; # arm x86 mips
strpbrk;
strptime;
strrchr;
@@ -1144,7 +969,6 @@
strtoll;
strtoll_l;
strtoq;
- strtotimeval; # arm x86 mips
strtoul;
strtoull;
strtoull_l;
@@ -1166,7 +990,6 @@
sysinfo;
syslog;
system;
- sysv_signal; # arm x86 mips
tcdrain;
tcflow;
tcflush;
@@ -1185,9 +1008,7 @@
tgkill;
time;
timegm;
- timegm64; # arm x86 mips
timelocal;
- timelocal64; # arm x86 mips
timer_create;
timer_delete;
timer_getoverrun;
@@ -1198,7 +1019,6 @@
timerfd_settime;
times;
timezone;
- tkill; # arm x86 mips
tmpfile;
tmpnam;
toascii;
@@ -1235,12 +1055,10 @@
utimensat;
utimes;
utmpname;
- valloc; # arm x86 mips
vasprintf;
vdprintf;
verr;
verrx;
- vfdprintf; # arm x86 mips
vfork;
vfprintf;
vfscanf;
@@ -1260,7 +1078,6 @@
vwprintf;
vwscanf;
wait;
- wait3; # arm x86 mips
wait4;
waitid;
waitpid;
@@ -1309,7 +1126,6 @@
wcstoull;
wcstoull_l;
wcstoumax;
- wcswcs; # arm x86 mips
wcswidth;
wcsxfrm;
wcsxfrm_l;
@@ -1340,134 +1156,33 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
LIBC_PRIVATE {
global:
- ___Unwind_Backtrace; # arm
- ___Unwind_ForcedUnwind; # arm
- ___Unwind_RaiseException; # arm
- ___Unwind_Resume; # arm
- ___Unwind_Resume_or_Rethrow; # arm
- __accept4; # arm x86 mips
- __adddf3; # arm
- __addsf3; # arm
- __aeabi_atexit; # arm
- __aeabi_cdcmpeq; # arm
- __aeabi_cdcmple; # arm
- __aeabi_cdrcmple; # arm
- __aeabi_d2f; # arm
- __aeabi_d2iz; # arm
- __aeabi_dadd; # arm
- __aeabi_dcmpeq; # arm
- __aeabi_dcmpge; # arm
- __aeabi_dcmpgt; # arm
- __aeabi_dcmple; # arm
- __aeabi_dcmplt; # arm
- __aeabi_dcmpun; # arm
- __aeabi_ddiv; # arm
- __aeabi_dmul; # arm
- __aeabi_drsub; # arm
- __aeabi_dsub; # arm
- __aeabi_f2d; # arm
- __aeabi_f2iz; # arm
- __aeabi_f2uiz; # arm
- __aeabi_fadd; # arm
- __aeabi_fcmpun; # arm
- __aeabi_fdiv; # arm
- __aeabi_fmul; # arm
- __aeabi_frsub; # arm
- __aeabi_fsub; # arm
- __aeabi_i2d; # arm
- __aeabi_i2f; # arm
- __aeabi_idiv; # arm
- __aeabi_idiv0; # arm
- __aeabi_idivmod; # arm
- __aeabi_l2d; # arm
- __aeabi_l2f; # arm
- __aeabi_lasr; # arm
- __aeabi_ldiv0; # arm
- __aeabi_ldivmod; # arm
- __aeabi_llsl; # arm
- __aeabi_llsr; # arm
- __aeabi_lmul; # 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
- __aeabi_ui2d; # arm
- __aeabi_ui2f; # arm
- __aeabi_uidiv; # arm
- __aeabi_uidivmod; # arm
- __aeabi_ul2d; # arm
- __aeabi_ul2f; # arm
- __aeabi_uldivmod; # arm
- __aeabi_unwind_cpp_pr0; # arm
- __aeabi_unwind_cpp_pr1; # arm
- __aeabi_unwind_cpp_pr2; # arm
- __arm_fadvise64_64; # arm
- __ashldi3; # arm
- __ashrdi3; # arm
- __bionic_brk; # arm x86 mips
- __bionic_libgcc_compat_symbols; # arm x86
- __bionic_libgcc_unwind_symbols; # arm
- __dso_handle; # arm
- __gnu_Unwind_Backtrace; # arm
- __gnu_unwind_execute; # arm
- __gnu_Unwind_Find_exidx; # arm
- __gnu_Unwind_ForcedUnwind; # arm
- __gnu_unwind_frame; # arm
- __gnu_Unwind_RaiseException; # arm
- __gnu_Unwind_Restore_VFP; # arm
- __gnu_Unwind_Restore_VFP_D; # arm
- __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
- __gnu_Unwind_Restore_WMMXC; # arm
- __gnu_Unwind_Restore_WMMXD; # arm
- __gnu_Unwind_Resume; # arm
- __gnu_Unwind_Resume_or_Rethrow; # arm
- __gnu_Unwind_Save_VFP; # arm
- __gnu_Unwind_Save_VFP_D; # arm
- __gnu_Unwind_Save_VFP_D_16_to_31; # arm
- __gnu_Unwind_Save_WMMXC; # arm
- __gnu_Unwind_Save_WMMXD; # arm
- _Unwind_Backtrace; # arm
- _Unwind_Complete; # arm
- _Unwind_DeleteException; # arm
- _Unwind_ForcedUnwind; # arm
- _Unwind_GetCFA; # arm
- _Unwind_GetDataRelBase; # arm
- _Unwind_GetLanguageSpecificData; # arm
- _Unwind_GetRegionStart; # arm
- _Unwind_GetTextRelBase; # arm
- _Unwind_RaiseException; # arm
- _Unwind_Resume; # arm
- _Unwind_Resume_or_Rethrow; # arm
- _Unwind_VRS_Get; # arm
- _Unwind_VRS_Pop; # arm
- _Unwind_VRS_Set; # arm
- atexit; # arm
- dlmalloc; # arm x86 mips
dlmalloc_inspect_all;
dlmalloc_trim;
- dlmalloc_usable_size; # arm x86 mips
gMallocLeakZygoteChild;
- SHA1Final; # arm x86 mips
- SHA1Init; # arm x86 mips
- SHA1Transform; # arm x86 mips
- SHA1Update; # arm x86 mips
} LIBC_N;
diff --git a/libc/libc.map b/libc/libc.map.txt
similarity index 98%
rename from libc/libc.map
rename to libc/libc.map.txt
index fbceb83..76cb168 100644
--- a/libc/libc.map
+++ b/libc/libc.map.txt
@@ -389,7 +389,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -580,7 +579,6 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
@@ -1051,7 +1049,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1340,12 +1337,28 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
preadv64;
+ 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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
diff --git a/libc/libc.map b/libc/libc.mips.map
similarity index 81%
copy from libc/libc.map
copy to libc/libc.mips.map
index fbceb83..e268bad 100644
--- a/libc/libc.map
+++ b/libc/libc.mips.map
@@ -1,33 +1,24 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
__assert2;
- __atomic_cmpxchg; # arm
- __atomic_dec; # arm
- __atomic_inc; # arm
- __atomic_swap; # arm
__b64_ntop;
__b64_pton;
__brk; # arm x86 mips
- __cmpdf2; # arm
__cmsg_nxthdr;
__connect; # arm x86 mips
__ctype_get_mb_cur_max;
__cxa_atexit;
__cxa_finalize;
__cxa_thread_atexit_impl;
- __divdf3; # arm
__divdi3; # arm x86 mips
- __divsf3; # arm
- __divsi3; # arm
__dn_comp;
__dn_count_labels;
__dn_skipname;
__epoll_pwait; # arm x86 mips
- __eqdf2; # arm
__errno;
__exit; # arm x86 mips
- __extendsfdf2; # arm
__fadvise64; # x86 mips
__fbufsize;
__fcntl64; # arm x86 mips
@@ -35,18 +26,7 @@
__FD_ISSET_chk;
__FD_SET_chk;
__fgets_chk;
- __fixdfsi; # arm
- __fixsfsi; # arm
- __fixunssfsi; # arm
__flbf;
- __floatdidf; # arm
- __floatdisf; # arm
- __floatsidf; # arm
- __floatsisf; # arm
- __floatundidf; # arm
- __floatundisf; # arm
- __floatunsidf; # arm
- __floatunsisf; # arm
__fp_nquery;
__fp_query;
__fpclassify;
@@ -61,7 +41,6 @@
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable;
- __gedf2; # arm
__get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
@@ -71,10 +50,7 @@
__getpid; # arm x86 mips
__getpriority; # arm x86 mips
__gnu_basename;
- __gnu_ldivmod_helper; # arm
__gnu_strerror_r;
- __gnu_uldivmod_helper; # arm
- __gtdf2; # arm
__hostalias;
__ioctl; # arm x86 mips
__isfinite;
@@ -90,15 +66,12 @@
__isnormalf;
__isnormall;
__isthreaded;
- __ledf2; # arm
__libc_current_sigrtmax;
__libc_current_sigrtmin;
__libc_init;
__llseek; # arm x86 mips
__loc_aton;
__loc_ntoa;
- __lshrdi3; # arm
- __ltdf2; # arm
__memchr_chk;
__memcpy_chk;
__memmove_chk;
@@ -106,10 +79,6 @@
__memset_chk;
__mmap2; # arm x86 mips
__moddi3; # x86 mips
- __muldf3; # arm
- __muldi3; # arm
- __mulsf3; # arm
- __nedf2; # arm
__ns_format_ttl; # arm x86 mips
__ns_get16; # arm x86 mips
__ns_get32; # arm x86 mips
@@ -152,7 +121,6 @@
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk;
- __popcount_tab; # arm
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips
__ppoll_chk;
@@ -192,7 +160,6 @@
__res_send;
__res_send_setqhook;
__res_send_setrhook;
- __restore_core_regs; # arm
__rt_sigaction; # arm x86 mips
__rt_sigpending; # arm x86 mips
__rt_sigprocmask; # arm x86 mips
@@ -205,7 +172,6 @@
__sclose; # arm x86 mips
__sdidinit; # arm x86 mips
__set_errno; # arm x86 mips
- __set_thread_area; # x86
__set_tid_address; # arm x86 mips
__set_tls; # arm mips
__sF;
@@ -240,8 +206,6 @@
__strncpy_chk;
__strncpy_chk2;
__strrchr_chk;
- __subdf3; # arm
- __subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
@@ -268,13 +232,9 @@
__timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips
- __truncdfsf2; # arm
__udivdi3; # arm x86 mips
- __udivsi3; # arm
__umask_chk;
__umoddi3; # x86 mips
- __unorddf2; # arm
- __unordsf2; # arm
__vsnprintf_chk;
__vsprintf_chk;
__wait4; # arm x86 mips
@@ -389,7 +349,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -580,7 +539,6 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
@@ -780,28 +738,6 @@
nftw64;
nice;
nrand48;
- ns_format_ttl; # arm64 x86_64 mips64
- ns_get16; # arm64 x86_64 mips64
- ns_get32; # arm64 x86_64 mips64
- ns_initparse; # arm64 x86_64 mips64
- ns_makecanon; # arm64 x86_64 mips64
- ns_msg_getflag; # arm64 x86_64 mips64
- ns_name_compress; # arm64 x86_64 mips64
- ns_name_ntol; # arm64 x86_64 mips64
- ns_name_ntop; # arm64 x86_64 mips64
- ns_name_pack; # arm64 x86_64 mips64
- ns_name_pton; # arm64 x86_64 mips64
- ns_name_rollback; # arm64 x86_64 mips64
- ns_name_skip; # arm64 x86_64 mips64
- ns_name_uncompress; # arm64 x86_64 mips64
- ns_name_unpack; # arm64 x86_64 mips64
- ns_parserr; # arm64 x86_64 mips64
- ns_put16; # arm64 x86_64 mips64
- ns_put32; # arm64 x86_64 mips64
- ns_samename; # arm64 x86_64 mips64
- ns_skiprr; # arm64 x86_64 mips64
- ns_sprintrr; # arm64 x86_64 mips64
- ns_sprintrrf; # arm64 x86_64 mips64
nsdispatch;
ntohl;
ntohs;
@@ -840,7 +776,6 @@
pread;
pread64;
printf;
- prlimit; # arm64 x86_64 mips64
prlimit64;
process_vm_readv;
process_vm_writev;
@@ -980,7 +915,6 @@
res_mkquery;
res_query;
res_search;
- restore_core_regs; # arm
rewind;
rewinddir;
rmdir;
@@ -1051,7 +985,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1340,127 +1273,35 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
preadv64;
+ 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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
LIBC_PRIVATE {
global:
- ___Unwind_Backtrace; # arm
- ___Unwind_ForcedUnwind; # arm
- ___Unwind_RaiseException; # arm
- ___Unwind_Resume; # arm
- ___Unwind_Resume_or_Rethrow; # arm
__accept4; # arm x86 mips
- __adddf3; # arm
- __addsf3; # arm
- __aeabi_atexit; # arm
- __aeabi_cdcmpeq; # arm
- __aeabi_cdcmple; # arm
- __aeabi_cdrcmple; # arm
- __aeabi_d2f; # arm
- __aeabi_d2iz; # arm
- __aeabi_dadd; # arm
- __aeabi_dcmpeq; # arm
- __aeabi_dcmpge; # arm
- __aeabi_dcmpgt; # arm
- __aeabi_dcmple; # arm
- __aeabi_dcmplt; # arm
- __aeabi_dcmpun; # arm
- __aeabi_ddiv; # arm
- __aeabi_dmul; # arm
- __aeabi_drsub; # arm
- __aeabi_dsub; # arm
- __aeabi_f2d; # arm
- __aeabi_f2iz; # arm
- __aeabi_f2uiz; # arm
- __aeabi_fadd; # arm
- __aeabi_fcmpun; # arm
- __aeabi_fdiv; # arm
- __aeabi_fmul; # arm
- __aeabi_frsub; # arm
- __aeabi_fsub; # arm
- __aeabi_i2d; # arm
- __aeabi_i2f; # arm
- __aeabi_idiv; # arm
- __aeabi_idiv0; # arm
- __aeabi_idivmod; # arm
- __aeabi_l2d; # arm
- __aeabi_l2f; # arm
- __aeabi_lasr; # arm
- __aeabi_ldiv0; # arm
- __aeabi_ldivmod; # arm
- __aeabi_llsl; # arm
- __aeabi_llsr; # arm
- __aeabi_lmul; # 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
- __aeabi_ui2d; # arm
- __aeabi_ui2f; # arm
- __aeabi_uidiv; # arm
- __aeabi_uidivmod; # arm
- __aeabi_ul2d; # arm
- __aeabi_ul2f; # arm
- __aeabi_uldivmod; # arm
- __aeabi_unwind_cpp_pr0; # arm
- __aeabi_unwind_cpp_pr1; # arm
- __aeabi_unwind_cpp_pr2; # arm
- __arm_fadvise64_64; # arm
- __ashldi3; # arm
- __ashrdi3; # arm
__bionic_brk; # arm x86 mips
- __bionic_libgcc_compat_symbols; # arm x86
- __bionic_libgcc_unwind_symbols; # arm
- __dso_handle; # arm
- __gnu_Unwind_Backtrace; # arm
- __gnu_unwind_execute; # arm
- __gnu_Unwind_Find_exidx; # arm
- __gnu_Unwind_ForcedUnwind; # arm
- __gnu_unwind_frame; # arm
- __gnu_Unwind_RaiseException; # arm
- __gnu_Unwind_Restore_VFP; # arm
- __gnu_Unwind_Restore_VFP_D; # arm
- __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
- __gnu_Unwind_Restore_WMMXC; # arm
- __gnu_Unwind_Restore_WMMXD; # arm
- __gnu_Unwind_Resume; # arm
- __gnu_Unwind_Resume_or_Rethrow; # arm
- __gnu_Unwind_Save_VFP; # arm
- __gnu_Unwind_Save_VFP_D; # arm
- __gnu_Unwind_Save_VFP_D_16_to_31; # arm
- __gnu_Unwind_Save_WMMXC; # arm
- __gnu_Unwind_Save_WMMXD; # arm
- _Unwind_Backtrace; # arm
- _Unwind_Complete; # arm
- _Unwind_DeleteException; # arm
- _Unwind_ForcedUnwind; # arm
- _Unwind_GetCFA; # arm
- _Unwind_GetDataRelBase; # arm
- _Unwind_GetLanguageSpecificData; # arm
- _Unwind_GetRegionStart; # arm
- _Unwind_GetTextRelBase; # arm
- _Unwind_RaiseException; # arm
- _Unwind_Resume; # arm
- _Unwind_Resume_or_Rethrow; # arm
- _Unwind_VRS_Get; # arm
- _Unwind_VRS_Pop; # arm
- _Unwind_VRS_Set; # arm
- atexit; # arm
dlmalloc; # arm x86 mips
dlmalloc_inspect_all;
dlmalloc_trim;
diff --git a/libc/libc.map b/libc/libc.mips64.map
similarity index 68%
copy from libc/libc.map
copy to libc/libc.mips64.map
index fbceb83..763f77e 100644
--- a/libc/libc.map
+++ b/libc/libc.mips64.map
@@ -1,52 +1,25 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
__assert2;
- __atomic_cmpxchg; # arm
- __atomic_dec; # arm
- __atomic_inc; # arm
- __atomic_swap; # arm
__b64_ntop;
__b64_pton;
- __brk; # arm x86 mips
- __cmpdf2; # arm
__cmsg_nxthdr;
- __connect; # arm x86 mips
__ctype_get_mb_cur_max;
__cxa_atexit;
__cxa_finalize;
__cxa_thread_atexit_impl;
- __divdf3; # arm
- __divdi3; # arm x86 mips
- __divsf3; # arm
- __divsi3; # arm
__dn_comp;
__dn_count_labels;
__dn_skipname;
- __epoll_pwait; # arm x86 mips
- __eqdf2; # arm
__errno;
- __exit; # arm x86 mips
- __extendsfdf2; # arm
- __fadvise64; # x86 mips
__fbufsize;
- __fcntl64; # arm x86 mips
__FD_CLR_chk;
__FD_ISSET_chk;
__FD_SET_chk;
__fgets_chk;
- __fixdfsi; # arm
- __fixsfsi; # arm
- __fixunssfsi; # arm
__flbf;
- __floatdidf; # arm
- __floatdisf; # arm
- __floatsidf; # arm
- __floatsisf; # arm
- __floatundidf; # arm
- __floatundisf; # arm
- __floatunsidf; # arm
- __floatunsisf; # arm
__fp_nquery;
__fp_query;
__fpclassify;
@@ -57,26 +30,11 @@
__fpurge;
__freadable;
__fsetlocking;
- __fstatfs64; # arm x86 mips
- __futex_wait; # arm x86 mips
- __futex_wake; # arm x86 mips
__fwritable;
- __gedf2; # arm
__get_h_errno;
- __get_thread; # arm x86 mips
- __get_tls; # arm x86 mips
- __getcpu; # arm x86 mips
- __getcwd; # arm x86 mips
- __getdents64; # arm x86 mips
- __getpid; # arm x86 mips
- __getpriority; # arm x86 mips
__gnu_basename;
- __gnu_ldivmod_helper; # arm
__gnu_strerror_r;
- __gnu_uldivmod_helper; # arm
- __gtdf2; # arm
__hostalias;
- __ioctl; # arm x86 mips
__isfinite;
__isfinitef;
__isfinitel;
@@ -90,51 +48,17 @@
__isnormalf;
__isnormall;
__isthreaded;
- __ledf2; # arm
__libc_current_sigrtmax;
__libc_current_sigrtmin;
__libc_init;
- __llseek; # arm x86 mips
__loc_aton;
__loc_ntoa;
- __lshrdi3; # arm
- __ltdf2; # arm
__memchr_chk;
__memcpy_chk;
__memmove_chk;
__memrchr_chk;
__memset_chk;
- __mmap2; # arm x86 mips
- __moddi3; # x86 mips
- __muldf3; # arm
- __muldi3; # arm
- __mulsf3; # arm
- __nedf2; # arm
- __ns_format_ttl; # arm x86 mips
- __ns_get16; # arm x86 mips
- __ns_get32; # arm x86 mips
- __ns_initparse; # arm x86 mips
- __ns_makecanon; # arm x86 mips
- __ns_msg_getflag; # arm x86 mips
- __ns_name_compress; # arm x86 mips
- __ns_name_ntol; # arm x86 mips
- __ns_name_ntop; # arm x86 mips
- __ns_name_pack; # arm x86 mips
- __ns_name_pton; # arm x86 mips
- __ns_name_rollback; # arm x86 mips
- __ns_name_skip; # arm x86 mips
- __ns_name_uncompress; # arm x86 mips
- __ns_name_unpack; # arm x86 mips
- __ns_parserr; # arm x86 mips
- __ns_put16; # arm x86 mips
- __ns_put32; # arm x86 mips
- __ns_samename; # arm x86 mips
- __ns_skiprr; # arm x86 mips
- __ns_sprintrr; # arm x86 mips
- __ns_sprintrrf; # arm x86 mips
- __open; # arm x86 mips
__open_2;
- __openat; # arm x86 mips
__openat_2;
__p_cdname;
__p_cdnname;
@@ -149,27 +73,18 @@
__p_time;
__p_type;
__p_type_syms;
- __page_shift; # arm x86 mips
- __page_size; # arm x86 mips
__poll_chk;
- __popcount_tab; # arm
- __popcountsi2; # arm x86 mips
- __ppoll; # arm x86 mips
__ppoll_chk;
__pread64_chk;
__pread_chk;
__progname;
- __pselect6; # arm x86 mips
__pthread_cleanup_pop;
__pthread_cleanup_push;
- __pthread_gettid; # arm x86 mips
- __ptrace; # arm x86 mips
__putlong;
__putshort;
__read_chk;
__readlink_chk;
__readlinkat_chk;
- __reboot; # arm x86 mips
__recvfrom_chk;
__register_atfork;
__res_close;
@@ -192,41 +107,14 @@
__res_send;
__res_send_setqhook;
__res_send_setrhook;
- __restore_core_regs; # arm
- __rt_sigaction; # arm x86 mips
- __rt_sigpending; # arm x86 mips
- __rt_sigprocmask; # arm x86 mips
- __rt_sigsuspend; # arm x86 mips
- __rt_sigtimedwait; # arm x86 mips
__sched_cpualloc;
__sched_cpucount;
__sched_cpufree;
- __sched_getaffinity; # arm x86 mips
- __sclose; # arm x86 mips
- __sdidinit; # arm x86 mips
- __set_errno; # arm x86 mips
- __set_thread_area; # x86
- __set_tid_address; # arm x86 mips
- __set_tls; # arm mips
__sF;
- __sflags; # arm x86 mips
- __sflush; # arm x86 mips
- __sfp; # arm x86 mips
- __sglue; # arm x86 mips
- __sigaction; # arm x86 mips
- __signalfd4; # arm x86 mips
- __sinit; # arm x86 mips
- __smakebuf; # arm x86 mips
__snprintf_chk;
- __socket; # arm x86 mips
__sprintf_chk;
- __sread; # arm x86 mips
- __srefill; # arm x86 mips
- __srget; # arm x86 mips
- __sseek; # arm x86 mips
__stack_chk_fail;
__stack_chk_guard;
- __statfs64; # arm x86 mips
__stpcpy_chk;
__stpncpy_chk;
__stpncpy_chk2;
@@ -240,11 +128,6 @@
__strncpy_chk;
__strncpy_chk2;
__strrchr_chk;
- __subdf3; # arm
- __subsf3; # arm
- __swbuf; # arm x86 mips
- __swrite; # arm x86 mips
- __swsetup; # arm x86 mips
__sym_ntop;
__sym_ntos;
__sym_ston;
@@ -263,28 +146,13 @@
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
- __timer_create; # arm x86 mips
- __timer_delete; # arm x86 mips
- __timer_getoverrun; # arm x86 mips
- __timer_gettime; # arm x86 mips
- __timer_settime; # arm x86 mips
- __truncdfsf2; # arm
- __udivdi3; # arm x86 mips
- __udivsi3; # arm
__umask_chk;
- __umoddi3; # x86 mips
- __unorddf2; # arm
- __unordsf2; # arm
__vsnprintf_chk;
__vsprintf_chk;
- __wait4; # arm x86 mips
- __waitid; # arm x86 mips
_ctype_;
_Exit;
_exit;
- _flush_cache; # mips
_flushlbf;
- _fwalk; # arm x86 mips
_getlong;
_getshort;
_longjmp;
@@ -293,9 +161,7 @@
_resolv_set_nameservers_for_net;
_setjmp;
_tolower;
- _tolower_tab_; # arm x86 mips
_toupper;
- _toupper_tab_; # arm x86 mips
abort;
abs;
accept;
@@ -311,13 +177,9 @@
android_gethostbynamefornet;
android_set_abort_message;
arc4random;
- arc4random_addrandom; # arm x86 mips
arc4random_buf;
- arc4random_stir; # arm x86 mips
arc4random_uniform;
asctime;
- asctime64; # arm x86 mips
- asctime64_r; # arm x86 mips
asctime_r;
asprintf;
at_quick_exit;
@@ -326,18 +188,13 @@
atol;
atoll;
basename;
- basename_r; # arm x86 mips
- bcopy; # arm x86 mips
bind;
bindresvport;
brk;
- bsd_signal; # arm x86 mips
bsearch;
btowc;
- bzero; # arm x86 mips
c16rtomb;
c32rtomb;
- cacheflush; # arm mips
calloc;
capget;
capset;
@@ -368,8 +225,6 @@
creat;
creat64;
ctime;
- ctime64; # arm x86 mips
- ctime64_r; # arm x86 mips
ctime_r;
daemon;
daylight;
@@ -377,7 +232,6 @@
difftime;
dirfd;
dirname;
- dirname_r; # arm x86 mips
div;
dn_expand;
dprintf;
@@ -389,7 +243,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -421,8 +274,6 @@
execvpe;
exit;
faccessat;
- fake_gmtime_r; # arm x86 mips
- fake_localtime_r; # arm x86 mips
fallocate;
fallocate64;
fchdir;
@@ -435,7 +286,6 @@
fdatasync;
fdopen;
fdopendir;
- fdprintf; # arm x86 mips
feof;
feof_unlocked;
ferror;
@@ -488,7 +338,6 @@
fsync;
ftell;
ftello;
- ftime; # arm x86 mips
ftok;
ftruncate;
ftruncate64;
@@ -521,8 +370,6 @@
getchar_unlocked;
getcwd;
getdelim;
- getdents; # arm x86 mips
- getdtablesize; # arm x86 mips
getegid;
getenv;
geteuid;
@@ -580,14 +427,11 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
getxattr;
gmtime;
- gmtime64; # arm x86 mips
- gmtime64_r; # arm x86 mips
gmtime_r;
grantpt;
herror;
@@ -598,7 +442,6 @@
if_nametoindex;
imaxabs;
imaxdiv;
- index; # arm x86 mips
inet_addr;
inet_aton;
inet_lnaof;
@@ -651,7 +494,6 @@
isprint_l;
ispunct;
ispunct_l;
- issetugid; # arm x86 mips
isspace;
isspace_l;
isupper;
@@ -704,8 +546,6 @@
llistxattr;
localeconv;
localtime;
- localtime64; # arm x86 mips
- localtime64_r; # arm x86 mips
localtime_r;
login_tty;
longjmp;
@@ -741,7 +581,6 @@
mempcpy;
memrchr;
memset;
- memswap; # arm x86 mips
mincore;
mkdir;
mkdirat;
@@ -760,7 +599,6 @@
mkstemps64;
mktemp;
mktime;
- mktime64; # arm x86 mips
mktime_tz;
mlock;
mlockall;
@@ -855,7 +693,6 @@
pthread_attr_getschedpolicy;
pthread_attr_getscope;
pthread_attr_getstack;
- pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize;
pthread_attr_init;
pthread_attr_setdetachstate;
@@ -864,17 +701,12 @@
pthread_attr_setschedpolicy;
pthread_attr_setscope;
pthread_attr_setstack;
- pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize;
pthread_cond_broadcast;
pthread_cond_destroy;
pthread_cond_init;
pthread_cond_signal;
pthread_cond_timedwait;
- pthread_cond_timedwait_monotonic; # arm x86 mips
- pthread_cond_timedwait_monotonic_np; # arm x86 mips
- pthread_cond_timedwait_relative_np; # arm x86 mips
- pthread_cond_timeout_np; # arm x86 mips
pthread_cond_wait;
pthread_condattr_destroy;
pthread_condattr_getclock;
@@ -898,7 +730,6 @@
pthread_mutex_destroy;
pthread_mutex_init;
pthread_mutex_lock;
- pthread_mutex_lock_timeout_np; # arm x86 mips
pthread_mutex_timedlock;
pthread_mutex_trylock;
pthread_mutex_unlock;
@@ -939,10 +770,8 @@
putenv;
puts;
pututline;
- putw; # arm x86 mips
putwc;
putwchar;
- pvalloc; # arm x86 mips
pwrite;
pwrite64;
qsort;
@@ -980,7 +809,6 @@
res_mkquery;
res_query;
res_search;
- restore_core_regs; # arm
rewind;
rewinddir;
rmdir;
@@ -1051,7 +879,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1124,8 +951,6 @@
strncpy;
strndup;
strnlen;
- strntoimax; # arm x86 mips
- strntoumax; # arm x86 mips
strpbrk;
strptime;
strrchr;
@@ -1144,7 +969,6 @@
strtoll;
strtoll_l;
strtoq;
- strtotimeval; # arm x86 mips
strtoul;
strtoull;
strtoull_l;
@@ -1166,7 +990,6 @@
sysinfo;
syslog;
system;
- sysv_signal; # arm x86 mips
tcdrain;
tcflow;
tcflush;
@@ -1185,9 +1008,7 @@
tgkill;
time;
timegm;
- timegm64; # arm x86 mips
timelocal;
- timelocal64; # arm x86 mips
timer_create;
timer_delete;
timer_getoverrun;
@@ -1198,7 +1019,6 @@
timerfd_settime;
times;
timezone;
- tkill; # arm x86 mips
tmpfile;
tmpnam;
toascii;
@@ -1235,12 +1055,10 @@
utimensat;
utimes;
utmpname;
- valloc; # arm x86 mips
vasprintf;
vdprintf;
verr;
verrx;
- vfdprintf; # arm x86 mips
vfork;
vfprintf;
vfscanf;
@@ -1260,7 +1078,6 @@
vwprintf;
vwscanf;
wait;
- wait3; # arm x86 mips
wait4;
waitid;
waitpid;
@@ -1309,7 +1126,6 @@
wcstoull;
wcstoull_l;
wcstoumax;
- wcswcs; # arm x86 mips
wcswidth;
wcsxfrm;
wcsxfrm_l;
@@ -1340,134 +1156,33 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
LIBC_PRIVATE {
global:
- ___Unwind_Backtrace; # arm
- ___Unwind_ForcedUnwind; # arm
- ___Unwind_RaiseException; # arm
- ___Unwind_Resume; # arm
- ___Unwind_Resume_or_Rethrow; # arm
- __accept4; # arm x86 mips
- __adddf3; # arm
- __addsf3; # arm
- __aeabi_atexit; # arm
- __aeabi_cdcmpeq; # arm
- __aeabi_cdcmple; # arm
- __aeabi_cdrcmple; # arm
- __aeabi_d2f; # arm
- __aeabi_d2iz; # arm
- __aeabi_dadd; # arm
- __aeabi_dcmpeq; # arm
- __aeabi_dcmpge; # arm
- __aeabi_dcmpgt; # arm
- __aeabi_dcmple; # arm
- __aeabi_dcmplt; # arm
- __aeabi_dcmpun; # arm
- __aeabi_ddiv; # arm
- __aeabi_dmul; # arm
- __aeabi_drsub; # arm
- __aeabi_dsub; # arm
- __aeabi_f2d; # arm
- __aeabi_f2iz; # arm
- __aeabi_f2uiz; # arm
- __aeabi_fadd; # arm
- __aeabi_fcmpun; # arm
- __aeabi_fdiv; # arm
- __aeabi_fmul; # arm
- __aeabi_frsub; # arm
- __aeabi_fsub; # arm
- __aeabi_i2d; # arm
- __aeabi_i2f; # arm
- __aeabi_idiv; # arm
- __aeabi_idiv0; # arm
- __aeabi_idivmod; # arm
- __aeabi_l2d; # arm
- __aeabi_l2f; # arm
- __aeabi_lasr; # arm
- __aeabi_ldiv0; # arm
- __aeabi_ldivmod; # arm
- __aeabi_llsl; # arm
- __aeabi_llsr; # arm
- __aeabi_lmul; # 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
- __aeabi_ui2d; # arm
- __aeabi_ui2f; # arm
- __aeabi_uidiv; # arm
- __aeabi_uidivmod; # arm
- __aeabi_ul2d; # arm
- __aeabi_ul2f; # arm
- __aeabi_uldivmod; # arm
- __aeabi_unwind_cpp_pr0; # arm
- __aeabi_unwind_cpp_pr1; # arm
- __aeabi_unwind_cpp_pr2; # arm
- __arm_fadvise64_64; # arm
- __ashldi3; # arm
- __ashrdi3; # arm
- __bionic_brk; # arm x86 mips
- __bionic_libgcc_compat_symbols; # arm x86
- __bionic_libgcc_unwind_symbols; # arm
- __dso_handle; # arm
- __gnu_Unwind_Backtrace; # arm
- __gnu_unwind_execute; # arm
- __gnu_Unwind_Find_exidx; # arm
- __gnu_Unwind_ForcedUnwind; # arm
- __gnu_unwind_frame; # arm
- __gnu_Unwind_RaiseException; # arm
- __gnu_Unwind_Restore_VFP; # arm
- __gnu_Unwind_Restore_VFP_D; # arm
- __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
- __gnu_Unwind_Restore_WMMXC; # arm
- __gnu_Unwind_Restore_WMMXD; # arm
- __gnu_Unwind_Resume; # arm
- __gnu_Unwind_Resume_or_Rethrow; # arm
- __gnu_Unwind_Save_VFP; # arm
- __gnu_Unwind_Save_VFP_D; # arm
- __gnu_Unwind_Save_VFP_D_16_to_31; # arm
- __gnu_Unwind_Save_WMMXC; # arm
- __gnu_Unwind_Save_WMMXD; # arm
- _Unwind_Backtrace; # arm
- _Unwind_Complete; # arm
- _Unwind_DeleteException; # arm
- _Unwind_ForcedUnwind; # arm
- _Unwind_GetCFA; # arm
- _Unwind_GetDataRelBase; # arm
- _Unwind_GetLanguageSpecificData; # arm
- _Unwind_GetRegionStart; # arm
- _Unwind_GetTextRelBase; # arm
- _Unwind_RaiseException; # arm
- _Unwind_Resume; # arm
- _Unwind_Resume_or_Rethrow; # arm
- _Unwind_VRS_Get; # arm
- _Unwind_VRS_Pop; # arm
- _Unwind_VRS_Set; # arm
- atexit; # arm
- dlmalloc; # arm x86 mips
dlmalloc_inspect_all;
dlmalloc_trim;
- dlmalloc_usable_size; # arm x86 mips
gMallocLeakZygoteChild;
- SHA1Final; # arm x86 mips
- SHA1Init; # arm x86 mips
- SHA1Transform; # arm x86 mips
- SHA1Update; # arm x86 mips
} LIBC_N;
diff --git a/libc/libc.map b/libc/libc.x86.map
similarity index 81%
copy from libc/libc.map
copy to libc/libc.x86.map
index fbceb83..6578370 100644
--- a/libc/libc.map
+++ b/libc/libc.x86.map
@@ -1,33 +1,24 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
__assert2;
- __atomic_cmpxchg; # arm
- __atomic_dec; # arm
- __atomic_inc; # arm
- __atomic_swap; # arm
__b64_ntop;
__b64_pton;
__brk; # arm x86 mips
- __cmpdf2; # arm
__cmsg_nxthdr;
__connect; # arm x86 mips
__ctype_get_mb_cur_max;
__cxa_atexit;
__cxa_finalize;
__cxa_thread_atexit_impl;
- __divdf3; # arm
__divdi3; # arm x86 mips
- __divsf3; # arm
- __divsi3; # arm
__dn_comp;
__dn_count_labels;
__dn_skipname;
__epoll_pwait; # arm x86 mips
- __eqdf2; # arm
__errno;
__exit; # arm x86 mips
- __extendsfdf2; # arm
__fadvise64; # x86 mips
__fbufsize;
__fcntl64; # arm x86 mips
@@ -35,18 +26,7 @@
__FD_ISSET_chk;
__FD_SET_chk;
__fgets_chk;
- __fixdfsi; # arm
- __fixsfsi; # arm
- __fixunssfsi; # arm
__flbf;
- __floatdidf; # arm
- __floatdisf; # arm
- __floatsidf; # arm
- __floatsisf; # arm
- __floatundidf; # arm
- __floatundisf; # arm
- __floatunsidf; # arm
- __floatunsisf; # arm
__fp_nquery;
__fp_query;
__fpclassify;
@@ -61,7 +41,6 @@
__futex_wait; # arm x86 mips
__futex_wake; # arm x86 mips
__fwritable;
- __gedf2; # arm
__get_h_errno;
__get_thread; # arm x86 mips
__get_tls; # arm x86 mips
@@ -71,10 +50,7 @@
__getpid; # arm x86 mips
__getpriority; # arm x86 mips
__gnu_basename;
- __gnu_ldivmod_helper; # arm
__gnu_strerror_r;
- __gnu_uldivmod_helper; # arm
- __gtdf2; # arm
__hostalias;
__ioctl; # arm x86 mips
__isfinite;
@@ -90,15 +66,12 @@
__isnormalf;
__isnormall;
__isthreaded;
- __ledf2; # arm
__libc_current_sigrtmax;
__libc_current_sigrtmin;
__libc_init;
__llseek; # arm x86 mips
__loc_aton;
__loc_ntoa;
- __lshrdi3; # arm
- __ltdf2; # arm
__memchr_chk;
__memcpy_chk;
__memmove_chk;
@@ -106,10 +79,6 @@
__memset_chk;
__mmap2; # arm x86 mips
__moddi3; # x86 mips
- __muldf3; # arm
- __muldi3; # arm
- __mulsf3; # arm
- __nedf2; # arm
__ns_format_ttl; # arm x86 mips
__ns_get16; # arm x86 mips
__ns_get32; # arm x86 mips
@@ -152,7 +121,6 @@
__page_shift; # arm x86 mips
__page_size; # arm x86 mips
__poll_chk;
- __popcount_tab; # arm
__popcountsi2; # arm x86 mips
__ppoll; # arm x86 mips
__ppoll_chk;
@@ -192,7 +160,6 @@
__res_send;
__res_send_setqhook;
__res_send_setrhook;
- __restore_core_regs; # arm
__rt_sigaction; # arm x86 mips
__rt_sigpending; # arm x86 mips
__rt_sigprocmask; # arm x86 mips
@@ -207,7 +174,6 @@
__set_errno; # arm x86 mips
__set_thread_area; # x86
__set_tid_address; # arm x86 mips
- __set_tls; # arm mips
__sF;
__sflags; # arm x86 mips
__sflush; # arm x86 mips
@@ -240,8 +206,6 @@
__strncpy_chk;
__strncpy_chk2;
__strrchr_chk;
- __subdf3; # arm
- __subsf3; # arm
__swbuf; # arm x86 mips
__swrite; # arm x86 mips
__swsetup; # arm x86 mips
@@ -268,13 +232,9 @@
__timer_getoverrun; # arm x86 mips
__timer_gettime; # arm x86 mips
__timer_settime; # arm x86 mips
- __truncdfsf2; # arm
__udivdi3; # arm x86 mips
- __udivsi3; # arm
__umask_chk;
__umoddi3; # x86 mips
- __unorddf2; # arm
- __unordsf2; # arm
__vsnprintf_chk;
__vsprintf_chk;
__wait4; # arm x86 mips
@@ -282,7 +242,6 @@
_ctype_;
_Exit;
_exit;
- _flush_cache; # mips
_flushlbf;
_fwalk; # arm x86 mips
_getlong;
@@ -337,7 +296,6 @@
bzero; # arm x86 mips
c16rtomb;
c32rtomb;
- cacheflush; # arm mips
calloc;
capget;
capset;
@@ -389,7 +347,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -580,7 +537,6 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
@@ -780,28 +736,6 @@
nftw64;
nice;
nrand48;
- ns_format_ttl; # arm64 x86_64 mips64
- ns_get16; # arm64 x86_64 mips64
- ns_get32; # arm64 x86_64 mips64
- ns_initparse; # arm64 x86_64 mips64
- ns_makecanon; # arm64 x86_64 mips64
- ns_msg_getflag; # arm64 x86_64 mips64
- ns_name_compress; # arm64 x86_64 mips64
- ns_name_ntol; # arm64 x86_64 mips64
- ns_name_ntop; # arm64 x86_64 mips64
- ns_name_pack; # arm64 x86_64 mips64
- ns_name_pton; # arm64 x86_64 mips64
- ns_name_rollback; # arm64 x86_64 mips64
- ns_name_skip; # arm64 x86_64 mips64
- ns_name_uncompress; # arm64 x86_64 mips64
- ns_name_unpack; # arm64 x86_64 mips64
- ns_parserr; # arm64 x86_64 mips64
- ns_put16; # arm64 x86_64 mips64
- ns_put32; # arm64 x86_64 mips64
- ns_samename; # arm64 x86_64 mips64
- ns_skiprr; # arm64 x86_64 mips64
- ns_sprintrr; # arm64 x86_64 mips64
- ns_sprintrrf; # arm64 x86_64 mips64
nsdispatch;
ntohl;
ntohs;
@@ -840,7 +774,6 @@
pread;
pread64;
printf;
- prlimit; # arm64 x86_64 mips64
prlimit64;
process_vm_readv;
process_vm_writev;
@@ -980,7 +913,6 @@
res_mkquery;
res_query;
res_search;
- restore_core_regs; # arm
rewind;
rewinddir;
rmdir;
@@ -1051,7 +983,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1340,127 +1271,36 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
preadv64;
+ 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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
LIBC_PRIVATE {
global:
- ___Unwind_Backtrace; # arm
- ___Unwind_ForcedUnwind; # arm
- ___Unwind_RaiseException; # arm
- ___Unwind_Resume; # arm
- ___Unwind_Resume_or_Rethrow; # arm
__accept4; # arm x86 mips
- __adddf3; # arm
- __addsf3; # arm
- __aeabi_atexit; # arm
- __aeabi_cdcmpeq; # arm
- __aeabi_cdcmple; # arm
- __aeabi_cdrcmple; # arm
- __aeabi_d2f; # arm
- __aeabi_d2iz; # arm
- __aeabi_dadd; # arm
- __aeabi_dcmpeq; # arm
- __aeabi_dcmpge; # arm
- __aeabi_dcmpgt; # arm
- __aeabi_dcmple; # arm
- __aeabi_dcmplt; # arm
- __aeabi_dcmpun; # arm
- __aeabi_ddiv; # arm
- __aeabi_dmul; # arm
- __aeabi_drsub; # arm
- __aeabi_dsub; # arm
- __aeabi_f2d; # arm
- __aeabi_f2iz; # arm
- __aeabi_f2uiz; # arm
- __aeabi_fadd; # arm
- __aeabi_fcmpun; # arm
- __aeabi_fdiv; # arm
- __aeabi_fmul; # arm
- __aeabi_frsub; # arm
- __aeabi_fsub; # arm
- __aeabi_i2d; # arm
- __aeabi_i2f; # arm
- __aeabi_idiv; # arm
- __aeabi_idiv0; # arm
- __aeabi_idivmod; # arm
- __aeabi_l2d; # arm
- __aeabi_l2f; # arm
- __aeabi_lasr; # arm
- __aeabi_ldiv0; # arm
- __aeabi_ldivmod; # arm
- __aeabi_llsl; # arm
- __aeabi_llsr; # arm
- __aeabi_lmul; # 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
- __aeabi_ui2d; # arm
- __aeabi_ui2f; # arm
- __aeabi_uidiv; # arm
- __aeabi_uidivmod; # arm
- __aeabi_ul2d; # arm
- __aeabi_ul2f; # arm
- __aeabi_uldivmod; # arm
- __aeabi_unwind_cpp_pr0; # arm
- __aeabi_unwind_cpp_pr1; # arm
- __aeabi_unwind_cpp_pr2; # arm
- __arm_fadvise64_64; # arm
- __ashldi3; # arm
- __ashrdi3; # arm
__bionic_brk; # arm x86 mips
__bionic_libgcc_compat_symbols; # arm x86
- __bionic_libgcc_unwind_symbols; # arm
- __dso_handle; # arm
- __gnu_Unwind_Backtrace; # arm
- __gnu_unwind_execute; # arm
- __gnu_Unwind_Find_exidx; # arm
- __gnu_Unwind_ForcedUnwind; # arm
- __gnu_unwind_frame; # arm
- __gnu_Unwind_RaiseException; # arm
- __gnu_Unwind_Restore_VFP; # arm
- __gnu_Unwind_Restore_VFP_D; # arm
- __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
- __gnu_Unwind_Restore_WMMXC; # arm
- __gnu_Unwind_Restore_WMMXD; # arm
- __gnu_Unwind_Resume; # arm
- __gnu_Unwind_Resume_or_Rethrow; # arm
- __gnu_Unwind_Save_VFP; # arm
- __gnu_Unwind_Save_VFP_D; # arm
- __gnu_Unwind_Save_VFP_D_16_to_31; # arm
- __gnu_Unwind_Save_WMMXC; # arm
- __gnu_Unwind_Save_WMMXD; # arm
- _Unwind_Backtrace; # arm
- _Unwind_Complete; # arm
- _Unwind_DeleteException; # arm
- _Unwind_ForcedUnwind; # arm
- _Unwind_GetCFA; # arm
- _Unwind_GetDataRelBase; # arm
- _Unwind_GetLanguageSpecificData; # arm
- _Unwind_GetRegionStart; # arm
- _Unwind_GetTextRelBase; # arm
- _Unwind_RaiseException; # arm
- _Unwind_Resume; # arm
- _Unwind_Resume_or_Rethrow; # arm
- _Unwind_VRS_Get; # arm
- _Unwind_VRS_Pop; # arm
- _Unwind_VRS_Set; # arm
- atexit; # arm
dlmalloc; # arm x86 mips
dlmalloc_inspect_all;
dlmalloc_trim;
diff --git a/libc/libc.map b/libc/libc.x86_64.map
similarity index 68%
copy from libc/libc.map
copy to libc/libc.x86_64.map
index fbceb83..763f77e 100644
--- a/libc/libc.map
+++ b/libc/libc.x86_64.map
@@ -1,52 +1,25 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__assert;
__assert2;
- __atomic_cmpxchg; # arm
- __atomic_dec; # arm
- __atomic_inc; # arm
- __atomic_swap; # arm
__b64_ntop;
__b64_pton;
- __brk; # arm x86 mips
- __cmpdf2; # arm
__cmsg_nxthdr;
- __connect; # arm x86 mips
__ctype_get_mb_cur_max;
__cxa_atexit;
__cxa_finalize;
__cxa_thread_atexit_impl;
- __divdf3; # arm
- __divdi3; # arm x86 mips
- __divsf3; # arm
- __divsi3; # arm
__dn_comp;
__dn_count_labels;
__dn_skipname;
- __epoll_pwait; # arm x86 mips
- __eqdf2; # arm
__errno;
- __exit; # arm x86 mips
- __extendsfdf2; # arm
- __fadvise64; # x86 mips
__fbufsize;
- __fcntl64; # arm x86 mips
__FD_CLR_chk;
__FD_ISSET_chk;
__FD_SET_chk;
__fgets_chk;
- __fixdfsi; # arm
- __fixsfsi; # arm
- __fixunssfsi; # arm
__flbf;
- __floatdidf; # arm
- __floatdisf; # arm
- __floatsidf; # arm
- __floatsisf; # arm
- __floatundidf; # arm
- __floatundisf; # arm
- __floatunsidf; # arm
- __floatunsisf; # arm
__fp_nquery;
__fp_query;
__fpclassify;
@@ -57,26 +30,11 @@
__fpurge;
__freadable;
__fsetlocking;
- __fstatfs64; # arm x86 mips
- __futex_wait; # arm x86 mips
- __futex_wake; # arm x86 mips
__fwritable;
- __gedf2; # arm
__get_h_errno;
- __get_thread; # arm x86 mips
- __get_tls; # arm x86 mips
- __getcpu; # arm x86 mips
- __getcwd; # arm x86 mips
- __getdents64; # arm x86 mips
- __getpid; # arm x86 mips
- __getpriority; # arm x86 mips
__gnu_basename;
- __gnu_ldivmod_helper; # arm
__gnu_strerror_r;
- __gnu_uldivmod_helper; # arm
- __gtdf2; # arm
__hostalias;
- __ioctl; # arm x86 mips
__isfinite;
__isfinitef;
__isfinitel;
@@ -90,51 +48,17 @@
__isnormalf;
__isnormall;
__isthreaded;
- __ledf2; # arm
__libc_current_sigrtmax;
__libc_current_sigrtmin;
__libc_init;
- __llseek; # arm x86 mips
__loc_aton;
__loc_ntoa;
- __lshrdi3; # arm
- __ltdf2; # arm
__memchr_chk;
__memcpy_chk;
__memmove_chk;
__memrchr_chk;
__memset_chk;
- __mmap2; # arm x86 mips
- __moddi3; # x86 mips
- __muldf3; # arm
- __muldi3; # arm
- __mulsf3; # arm
- __nedf2; # arm
- __ns_format_ttl; # arm x86 mips
- __ns_get16; # arm x86 mips
- __ns_get32; # arm x86 mips
- __ns_initparse; # arm x86 mips
- __ns_makecanon; # arm x86 mips
- __ns_msg_getflag; # arm x86 mips
- __ns_name_compress; # arm x86 mips
- __ns_name_ntol; # arm x86 mips
- __ns_name_ntop; # arm x86 mips
- __ns_name_pack; # arm x86 mips
- __ns_name_pton; # arm x86 mips
- __ns_name_rollback; # arm x86 mips
- __ns_name_skip; # arm x86 mips
- __ns_name_uncompress; # arm x86 mips
- __ns_name_unpack; # arm x86 mips
- __ns_parserr; # arm x86 mips
- __ns_put16; # arm x86 mips
- __ns_put32; # arm x86 mips
- __ns_samename; # arm x86 mips
- __ns_skiprr; # arm x86 mips
- __ns_sprintrr; # arm x86 mips
- __ns_sprintrrf; # arm x86 mips
- __open; # arm x86 mips
__open_2;
- __openat; # arm x86 mips
__openat_2;
__p_cdname;
__p_cdnname;
@@ -149,27 +73,18 @@
__p_time;
__p_type;
__p_type_syms;
- __page_shift; # arm x86 mips
- __page_size; # arm x86 mips
__poll_chk;
- __popcount_tab; # arm
- __popcountsi2; # arm x86 mips
- __ppoll; # arm x86 mips
__ppoll_chk;
__pread64_chk;
__pread_chk;
__progname;
- __pselect6; # arm x86 mips
__pthread_cleanup_pop;
__pthread_cleanup_push;
- __pthread_gettid; # arm x86 mips
- __ptrace; # arm x86 mips
__putlong;
__putshort;
__read_chk;
__readlink_chk;
__readlinkat_chk;
- __reboot; # arm x86 mips
__recvfrom_chk;
__register_atfork;
__res_close;
@@ -192,41 +107,14 @@
__res_send;
__res_send_setqhook;
__res_send_setrhook;
- __restore_core_regs; # arm
- __rt_sigaction; # arm x86 mips
- __rt_sigpending; # arm x86 mips
- __rt_sigprocmask; # arm x86 mips
- __rt_sigsuspend; # arm x86 mips
- __rt_sigtimedwait; # arm x86 mips
__sched_cpualloc;
__sched_cpucount;
__sched_cpufree;
- __sched_getaffinity; # arm x86 mips
- __sclose; # arm x86 mips
- __sdidinit; # arm x86 mips
- __set_errno; # arm x86 mips
- __set_thread_area; # x86
- __set_tid_address; # arm x86 mips
- __set_tls; # arm mips
__sF;
- __sflags; # arm x86 mips
- __sflush; # arm x86 mips
- __sfp; # arm x86 mips
- __sglue; # arm x86 mips
- __sigaction; # arm x86 mips
- __signalfd4; # arm x86 mips
- __sinit; # arm x86 mips
- __smakebuf; # arm x86 mips
__snprintf_chk;
- __socket; # arm x86 mips
__sprintf_chk;
- __sread; # arm x86 mips
- __srefill; # arm x86 mips
- __srget; # arm x86 mips
- __sseek; # arm x86 mips
__stack_chk_fail;
__stack_chk_guard;
- __statfs64; # arm x86 mips
__stpcpy_chk;
__stpncpy_chk;
__stpncpy_chk2;
@@ -240,11 +128,6 @@
__strncpy_chk;
__strncpy_chk2;
__strrchr_chk;
- __subdf3; # arm
- __subsf3; # arm
- __swbuf; # arm x86 mips
- __swrite; # arm x86 mips
- __swsetup; # arm x86 mips
__sym_ntop;
__sym_ntos;
__sym_ston;
@@ -263,28 +146,13 @@
__system_property_set_filename;
__system_property_update;
__system_property_wait_any;
- __timer_create; # arm x86 mips
- __timer_delete; # arm x86 mips
- __timer_getoverrun; # arm x86 mips
- __timer_gettime; # arm x86 mips
- __timer_settime; # arm x86 mips
- __truncdfsf2; # arm
- __udivdi3; # arm x86 mips
- __udivsi3; # arm
__umask_chk;
- __umoddi3; # x86 mips
- __unorddf2; # arm
- __unordsf2; # arm
__vsnprintf_chk;
__vsprintf_chk;
- __wait4; # arm x86 mips
- __waitid; # arm x86 mips
_ctype_;
_Exit;
_exit;
- _flush_cache; # mips
_flushlbf;
- _fwalk; # arm x86 mips
_getlong;
_getshort;
_longjmp;
@@ -293,9 +161,7 @@
_resolv_set_nameservers_for_net;
_setjmp;
_tolower;
- _tolower_tab_; # arm x86 mips
_toupper;
- _toupper_tab_; # arm x86 mips
abort;
abs;
accept;
@@ -311,13 +177,9 @@
android_gethostbynamefornet;
android_set_abort_message;
arc4random;
- arc4random_addrandom; # arm x86 mips
arc4random_buf;
- arc4random_stir; # arm x86 mips
arc4random_uniform;
asctime;
- asctime64; # arm x86 mips
- asctime64_r; # arm x86 mips
asctime_r;
asprintf;
at_quick_exit;
@@ -326,18 +188,13 @@
atol;
atoll;
basename;
- basename_r; # arm x86 mips
- bcopy; # arm x86 mips
bind;
bindresvport;
brk;
- bsd_signal; # arm x86 mips
bsearch;
btowc;
- bzero; # arm x86 mips
c16rtomb;
c32rtomb;
- cacheflush; # arm mips
calloc;
capget;
capset;
@@ -368,8 +225,6 @@
creat;
creat64;
ctime;
- ctime64; # arm x86 mips
- ctime64_r; # arm x86 mips
ctime_r;
daemon;
daylight;
@@ -377,7 +232,6 @@
difftime;
dirfd;
dirname;
- dirname_r; # arm x86 mips
div;
dn_expand;
dprintf;
@@ -389,7 +243,6 @@
endmntent;
endpwent;
endservent;
- endusershell;
endutent;
environ;
epoll_create;
@@ -421,8 +274,6 @@
execvpe;
exit;
faccessat;
- fake_gmtime_r; # arm x86 mips
- fake_localtime_r; # arm x86 mips
fallocate;
fallocate64;
fchdir;
@@ -435,7 +286,6 @@
fdatasync;
fdopen;
fdopendir;
- fdprintf; # arm x86 mips
feof;
feof_unlocked;
ferror;
@@ -488,7 +338,6 @@
fsync;
ftell;
ftello;
- ftime; # arm x86 mips
ftok;
ftruncate;
ftruncate64;
@@ -521,8 +370,6 @@
getchar_unlocked;
getcwd;
getdelim;
- getdents; # arm x86 mips
- getdtablesize; # arm x86 mips
getegid;
getenv;
geteuid;
@@ -580,14 +427,11 @@
gettid;
gettimeofday;
getuid;
- getusershell;
getutent;
getwc;
getwchar;
getxattr;
gmtime;
- gmtime64; # arm x86 mips
- gmtime64_r; # arm x86 mips
gmtime_r;
grantpt;
herror;
@@ -598,7 +442,6 @@
if_nametoindex;
imaxabs;
imaxdiv;
- index; # arm x86 mips
inet_addr;
inet_aton;
inet_lnaof;
@@ -651,7 +494,6 @@
isprint_l;
ispunct;
ispunct_l;
- issetugid; # arm x86 mips
isspace;
isspace_l;
isupper;
@@ -704,8 +546,6 @@
llistxattr;
localeconv;
localtime;
- localtime64; # arm x86 mips
- localtime64_r; # arm x86 mips
localtime_r;
login_tty;
longjmp;
@@ -741,7 +581,6 @@
mempcpy;
memrchr;
memset;
- memswap; # arm x86 mips
mincore;
mkdir;
mkdirat;
@@ -760,7 +599,6 @@
mkstemps64;
mktemp;
mktime;
- mktime64; # arm x86 mips
mktime_tz;
mlock;
mlockall;
@@ -855,7 +693,6 @@
pthread_attr_getschedpolicy;
pthread_attr_getscope;
pthread_attr_getstack;
- pthread_attr_getstackaddr; # arm x86 mips
pthread_attr_getstacksize;
pthread_attr_init;
pthread_attr_setdetachstate;
@@ -864,17 +701,12 @@
pthread_attr_setschedpolicy;
pthread_attr_setscope;
pthread_attr_setstack;
- pthread_attr_setstackaddr; # arm x86 mips
pthread_attr_setstacksize;
pthread_cond_broadcast;
pthread_cond_destroy;
pthread_cond_init;
pthread_cond_signal;
pthread_cond_timedwait;
- pthread_cond_timedwait_monotonic; # arm x86 mips
- pthread_cond_timedwait_monotonic_np; # arm x86 mips
- pthread_cond_timedwait_relative_np; # arm x86 mips
- pthread_cond_timeout_np; # arm x86 mips
pthread_cond_wait;
pthread_condattr_destroy;
pthread_condattr_getclock;
@@ -898,7 +730,6 @@
pthread_mutex_destroy;
pthread_mutex_init;
pthread_mutex_lock;
- pthread_mutex_lock_timeout_np; # arm x86 mips
pthread_mutex_timedlock;
pthread_mutex_trylock;
pthread_mutex_unlock;
@@ -939,10 +770,8 @@
putenv;
puts;
pututline;
- putw; # arm x86 mips
putwc;
putwchar;
- pvalloc; # arm x86 mips
pwrite;
pwrite64;
qsort;
@@ -980,7 +809,6 @@
res_mkquery;
res_query;
res_search;
- restore_core_regs; # arm
rewind;
rewinddir;
rmdir;
@@ -1051,7 +879,6 @@
setstate;
settimeofday;
setuid;
- setusershell;
setutent;
setvbuf;
setxattr;
@@ -1124,8 +951,6 @@
strncpy;
strndup;
strnlen;
- strntoimax; # arm x86 mips
- strntoumax; # arm x86 mips
strpbrk;
strptime;
strrchr;
@@ -1144,7 +969,6 @@
strtoll;
strtoll_l;
strtoq;
- strtotimeval; # arm x86 mips
strtoul;
strtoull;
strtoull_l;
@@ -1166,7 +990,6 @@
sysinfo;
syslog;
system;
- sysv_signal; # arm x86 mips
tcdrain;
tcflow;
tcflush;
@@ -1185,9 +1008,7 @@
tgkill;
time;
timegm;
- timegm64; # arm x86 mips
timelocal;
- timelocal64; # arm x86 mips
timer_create;
timer_delete;
timer_getoverrun;
@@ -1198,7 +1019,6 @@
timerfd_settime;
times;
timezone;
- tkill; # arm x86 mips
tmpfile;
tmpnam;
toascii;
@@ -1235,12 +1055,10 @@
utimensat;
utimes;
utmpname;
- valloc; # arm x86 mips
vasprintf;
vdprintf;
verr;
verrx;
- vfdprintf; # arm x86 mips
vfork;
vfprintf;
vfscanf;
@@ -1260,7 +1078,6 @@
vwprintf;
vwscanf;
wait;
- wait3; # arm x86 mips
wait4;
waitid;
waitpid;
@@ -1309,7 +1126,6 @@
wcstoull;
wcstoull_l;
wcstoumax;
- wcswcs; # arm x86 mips
wcswidth;
wcsxfrm;
wcsxfrm_l;
@@ -1340,134 +1156,33 @@
__pwrite_chk;
__pwrite64_chk;
__write_chk;
+ fileno_unlocked;
getgrgid_r;
getgrnam_r;
preadv;
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;
pwritev64;
+ scandirat;
+ scandirat64;
strchrnul;
} LIBC;
LIBC_PRIVATE {
global:
- ___Unwind_Backtrace; # arm
- ___Unwind_ForcedUnwind; # arm
- ___Unwind_RaiseException; # arm
- ___Unwind_Resume; # arm
- ___Unwind_Resume_or_Rethrow; # arm
- __accept4; # arm x86 mips
- __adddf3; # arm
- __addsf3; # arm
- __aeabi_atexit; # arm
- __aeabi_cdcmpeq; # arm
- __aeabi_cdcmple; # arm
- __aeabi_cdrcmple; # arm
- __aeabi_d2f; # arm
- __aeabi_d2iz; # arm
- __aeabi_dadd; # arm
- __aeabi_dcmpeq; # arm
- __aeabi_dcmpge; # arm
- __aeabi_dcmpgt; # arm
- __aeabi_dcmple; # arm
- __aeabi_dcmplt; # arm
- __aeabi_dcmpun; # arm
- __aeabi_ddiv; # arm
- __aeabi_dmul; # arm
- __aeabi_drsub; # arm
- __aeabi_dsub; # arm
- __aeabi_f2d; # arm
- __aeabi_f2iz; # arm
- __aeabi_f2uiz; # arm
- __aeabi_fadd; # arm
- __aeabi_fcmpun; # arm
- __aeabi_fdiv; # arm
- __aeabi_fmul; # arm
- __aeabi_frsub; # arm
- __aeabi_fsub; # arm
- __aeabi_i2d; # arm
- __aeabi_i2f; # arm
- __aeabi_idiv; # arm
- __aeabi_idiv0; # arm
- __aeabi_idivmod; # arm
- __aeabi_l2d; # arm
- __aeabi_l2f; # arm
- __aeabi_lasr; # arm
- __aeabi_ldiv0; # arm
- __aeabi_ldivmod; # arm
- __aeabi_llsl; # arm
- __aeabi_llsr; # arm
- __aeabi_lmul; # 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
- __aeabi_ui2d; # arm
- __aeabi_ui2f; # arm
- __aeabi_uidiv; # arm
- __aeabi_uidivmod; # arm
- __aeabi_ul2d; # arm
- __aeabi_ul2f; # arm
- __aeabi_uldivmod; # arm
- __aeabi_unwind_cpp_pr0; # arm
- __aeabi_unwind_cpp_pr1; # arm
- __aeabi_unwind_cpp_pr2; # arm
- __arm_fadvise64_64; # arm
- __ashldi3; # arm
- __ashrdi3; # arm
- __bionic_brk; # arm x86 mips
- __bionic_libgcc_compat_symbols; # arm x86
- __bionic_libgcc_unwind_symbols; # arm
- __dso_handle; # arm
- __gnu_Unwind_Backtrace; # arm
- __gnu_unwind_execute; # arm
- __gnu_Unwind_Find_exidx; # arm
- __gnu_Unwind_ForcedUnwind; # arm
- __gnu_unwind_frame; # arm
- __gnu_Unwind_RaiseException; # arm
- __gnu_Unwind_Restore_VFP; # arm
- __gnu_Unwind_Restore_VFP_D; # arm
- __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
- __gnu_Unwind_Restore_WMMXC; # arm
- __gnu_Unwind_Restore_WMMXD; # arm
- __gnu_Unwind_Resume; # arm
- __gnu_Unwind_Resume_or_Rethrow; # arm
- __gnu_Unwind_Save_VFP; # arm
- __gnu_Unwind_Save_VFP_D; # arm
- __gnu_Unwind_Save_VFP_D_16_to_31; # arm
- __gnu_Unwind_Save_WMMXC; # arm
- __gnu_Unwind_Save_WMMXD; # arm
- _Unwind_Backtrace; # arm
- _Unwind_Complete; # arm
- _Unwind_DeleteException; # arm
- _Unwind_ForcedUnwind; # arm
- _Unwind_GetCFA; # arm
- _Unwind_GetDataRelBase; # arm
- _Unwind_GetLanguageSpecificData; # arm
- _Unwind_GetRegionStart; # arm
- _Unwind_GetTextRelBase; # arm
- _Unwind_RaiseException; # arm
- _Unwind_Resume; # arm
- _Unwind_Resume_or_Rethrow; # arm
- _Unwind_VRS_Get; # arm
- _Unwind_VRS_Pop; # arm
- _Unwind_VRS_Set; # arm
- atexit; # arm
- dlmalloc; # arm x86 mips
dlmalloc_inspect_all;
dlmalloc_trim;
- dlmalloc_usable_size; # arm x86 mips
gMallocLeakZygoteChild;
- SHA1Final; # arm x86 mips
- SHA1Init; # arm x86 mips
- SHA1Transform; # arm x86 mips
- SHA1Update; # arm x86 mips
} LIBC_N;
diff --git a/libc/private/ScopedPthreadMutexLocker.h b/libc/private/ScopedPthreadMutexLocker.h
index 43dbdc1..58462e3 100644
--- a/libc/private/ScopedPthreadMutexLocker.h
+++ b/libc/private/ScopedPthreadMutexLocker.h
@@ -34,7 +34,7 @@
private:
pthread_mutex_t* mu_;
- DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker);
};
#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H
diff --git a/libc/private/ScopedReaddir.h b/libc/private/ScopedReaddir.h
index 84c1b93..3d77a40 100644
--- a/libc/private/ScopedReaddir.h
+++ b/libc/private/ScopedReaddir.h
@@ -23,8 +23,11 @@
class ScopedReaddir {
public:
- ScopedReaddir(const char* path) {
- dir_ = opendir(path);
+ ScopedReaddir(const char* path) : ScopedReaddir(opendir(path)) {
+ }
+
+ ScopedReaddir(DIR* dir) {
+ dir_ = dir;
}
~ScopedReaddir() {
diff --git a/libc/private/bionic_futex.h b/libc/private/bionic_futex.h
index 401577a..946d9dd 100644
--- a/libc/private/bionic_futex.h
+++ b/libc/private/bionic_futex.h
@@ -40,10 +40,12 @@
struct timespec;
-static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) {
+static inline __always_inline int __futex(volatile void* ftx, int op, int value,
+ const struct timespec* timeout,
+ int bitset) {
// Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
int saved_errno = errno;
- int result = syscall(__NR_futex, ftx, op, value, timeout);
+ int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
if (__predict_false(result == -1)) {
result = -errno;
errno = saved_errno;
@@ -52,19 +54,22 @@
}
static inline int __futex_wake(volatile void* ftx, int count) {
- return __futex(ftx, FUTEX_WAKE, count, NULL);
+ return __futex(ftx, FUTEX_WAKE, count, NULL, 0);
}
static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
- return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL);
+ return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL, 0);
}
static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
- return __futex(ftx, FUTEX_WAIT, value, timeout);
+ return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
}
-static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) {
- return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout);
+static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value,
+ bool use_realtime_clock, const struct timespec* abs_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
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 644b5a4..a671d77 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -29,12 +29,14 @@
#define _PRIVATE_BIONIC_GLOBALS_H
#include <sys/cdefs.h>
+#include "private/bionic_malloc_dispatch.h"
#include "private/bionic_vdso.h"
#include "private/WriteProtected.h"
struct libc_globals {
vdso_entry vdso[VDSO_END];
long setjmp_cookie;
+ MallocDebug malloc_dispatch;
};
__LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals;
@@ -44,5 +46,5 @@
KernelArgumentBlock& args);
__LIBC_HIDDEN__ void __libc_init_setjmp_cookie(libc_globals* globals,
KernelArgumentBlock& args);
-
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals);
#endif
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index 6a0fd06..3dbafe0 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -30,7 +30,10 @@
#include <stdatomic.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
+// an initialization function. So make sure Lock can be initialized by setting its memory to 0.
class Lock {
private:
enum LockState {
@@ -42,15 +45,17 @@
bool process_shared;
public:
- Lock(bool process_shared = false) {
- init(process_shared);
- }
-
void init(bool process_shared) {
atomic_init(&state, Unlocked);
this->process_shared = process_shared;
}
+ 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() {
LockState old_state = Unlocked;
if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
@@ -59,7 +64,7 @@
}
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
// TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
- __futex_wait_ex(&state, process_shared, LockedWithWaiter, NULL);
+ __futex_wait_ex(&state, process_shared, LockedWithWaiter, false, nullptr);
}
return;
}
diff --git a/libc/private/bionic_malloc_dispatch.h b/libc/private/bionic_malloc_dispatch.h
new file mode 100644
index 0000000..34fb898
--- /dev/null
+++ b/libc/private/bionic_malloc_dispatch.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PRIVATE_BIONIC_MALLOC_DISPATCH_H
+#define _PRIVATE_BIONIC_MALLOC_DISPATCH_H
+
+#include <stddef.h>
+#include "private/bionic_config.h"
+
+/* Entry in malloc dispatch table. */
+typedef void* (*MallocDebugCalloc)(size_t, size_t);
+typedef void (*MallocDebugFree)(void*);
+typedef struct mallinfo (*MallocDebugMallinfo)();
+typedef void* (*MallocDebugMalloc)(size_t);
+typedef size_t (*MallocDebugMallocUsableSize)(const void*);
+typedef void* (*MallocDebugMemalign)(size_t, size_t);
+typedef int (*MallocDebugPosixMemalign)(void**, size_t, size_t);
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+typedef void* (*MallocDebugPvalloc)(size_t);
+#endif
+typedef void* (*MallocDebugRealloc)(void*, size_t);
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+typedef void* (*MallocDebugValloc)(size_t);
+#endif
+
+struct MallocDebug {
+ MallocDebugCalloc calloc;
+ MallocDebugFree free;
+ MallocDebugMallinfo mallinfo;
+ MallocDebugMalloc malloc;
+ MallocDebugMallocUsableSize malloc_usable_size;
+ MallocDebugMemalign memalign;
+ MallocDebugPosixMemalign posix_memalign;
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ MallocDebugPvalloc pvalloc;
+#endif
+ MallocDebugRealloc realloc;
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+ MallocDebugValloc valloc;
+#endif
+} __attribute__((aligned(32)));
+
+#endif
diff --git a/libc/private/bionic_time_conversions.h b/libc/private/bionic_time_conversions.h
index cf0046a..294c29a 100644
--- a/libc/private/bionic_time_conversions.h
+++ b/libc/private/bionic_time_conversions.h
@@ -29,9 +29,12 @@
#ifndef _BIONIC_TIME_CONVERSIONS_H
#define _BIONIC_TIME_CONVERSIONS_H
+#include <errno.h>
#include <time.h>
#include <sys/cdefs.h>
+#include "private/bionic_constants.h"
+
__BEGIN_DECLS
__LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv);
@@ -39,8 +42,21 @@
__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
-__LIBC_HIDDEN__ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock);
+__LIBC_HIDDEN__ void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts,
+ clockid_t clock);
__END_DECLS
+static inline int check_timespec(const timespec* ts) {
+ if (ts != nullptr) {
+ if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) {
+ return EINVAL;
+ }
+ if (ts->tv_sec < 0) {
+ return ETIMEDOUT;
+ }
+ }
+ return 0;
+}
+
#endif
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 2696cfd..6e20562 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -44,37 +44,44 @@
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-int __sdidinit;
-
#define NDYNAMIC 10 /* add ten more whenever necessary */
#define std(flags, file) \
{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}
- /* 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);
-static struct __sfileext __sFext[3];
+// TODO: when we no longer have to support both clang and GCC, we can simplify all this.
+#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
// for stdin/stdout/stderr; they were macros accessing __sF.
FILE __sF[3] = {
- std(__SRD, STDIN_FILENO), /* stdin */
- std(__SWR, STDOUT_FILENO), /* stdout */
- std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
+ std(__SRD, STDIN_FILENO),
+ std(__SWR, STDOUT_FILENO),
+ std(__SWR|__SNBF, STDERR_FILENO),
};
-struct glue __sglue = { &uglue, 3, __sF };
-
FILE* stdin = &__sF[0];
FILE* stdout = &__sF[1];
FILE* stderr = &__sF[2];
+struct glue __sglue = { NULL, 3, __sF };
+static struct glue* lastglue = &__sglue;
+
static struct glue *
moreglue(int n)
{
@@ -114,9 +121,6 @@
int n;
struct glue *g;
- if (!__sdidinit)
- __sinit();
-
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
for (g = &__sglue; g != NULL; g = g->next) {
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
@@ -149,48 +153,7 @@
return (fp);
}
-/*
- * 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)
-{
+__LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
/* (void) _fwalk(fclose); */
(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);
-}
diff --git a/libc/stdio/glue.h b/libc/stdio/glue.h
index a9e5d10..cb1d182 100644
--- a/libc/stdio/glue.h
+++ b/libc/stdio/glue.h
@@ -47,6 +47,6 @@
};
/* This was referenced by a couple of different pieces of middleware and the Crystax NDK. */
-__LIBC64_HIDDEN__ extern struct glue __sglue;
+__LIBC32_LEGACY_PUBLIC__ extern struct glue __sglue;
__END_DECLS
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 749de7b..6dcd3ae 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -109,7 +109,7 @@
pthread_mutex_t _lock;
/* __fsetlocking support */
- bool _stdio_handles_locking;
+ bool _caller_handles_locking;
};
#if defined(__cplusplus)
@@ -131,7 +131,7 @@
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
pthread_mutex_init(&_FLOCK(fp), &attr); \
pthread_mutexattr_destroy(&attr); \
- _EXT(fp)->_stdio_handles_locking = true; \
+ _EXT(fp)->_caller_handles_locking = false; \
} while (0)
#define _FILEEXT_SETUP(f, fext) \
@@ -145,32 +145,29 @@
* to __srget/__swbuf, so those symbols need to be public for LP32
* but can be hidden for LP64.
*/
-__LIBC64_HIDDEN__ int __srget(FILE*);
-__LIBC64_HIDDEN__ int __swbuf(int, FILE*);
-__LIBC64_HIDDEN__ int __srefill(FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __srget(FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __swbuf(int, FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __srefill(FILE*);
/* This was referenced by the apportable middleware for LP32. */
-__LIBC64_HIDDEN__ int __swsetup(FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*);
/* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */
-__LIBC64_HIDDEN__ extern int __sdidinit;
-__LIBC64_HIDDEN__ int __sflags(const char*, int*);
-__LIBC64_HIDDEN__ FILE* __sfp(void);
-__LIBC64_HIDDEN__ void __sinit(void);
-__LIBC64_HIDDEN__ void __smakebuf(FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*);
+__LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void);
+__LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
/* These are referenced by the Greed for Glory franchise. */
-__LIBC64_HIDDEN__ int __sflush(FILE *);
-__LIBC64_HIDDEN__ int __sread(void *, char *, int);
-__LIBC64_HIDDEN__ int __swrite(void *, const char *, int);
-__LIBC64_HIDDEN__ fpos_t __sseek(void *, fpos_t, int);
-__LIBC64_HIDDEN__ int __sclose(void *);
-__LIBC64_HIDDEN__ int _fwalk(int (*)(FILE *));
+__LIBC32_LEGACY_PUBLIC__ int __sflush(FILE *);
+__LIBC32_LEGACY_PUBLIC__ int __sread(void *, char *, int);
+__LIBC32_LEGACY_PUBLIC__ int __swrite(void *, const char *, int);
+__LIBC32_LEGACY_PUBLIC__ fpos_t __sseek(void *, fpos_t, int);
+__LIBC32_LEGACY_PUBLIC__ int __sclose(void *);
+__LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE *));
#pragma GCC visibility push(hidden)
int __sflush_locked(FILE *);
-void _cleanup(void);
int __swhatbuf(FILE *, size_t *, int *);
wint_t __fgetwc_unlock(FILE *);
wint_t __ungetwc(wint_t, FILE *);
@@ -179,8 +176,6 @@
int __vfwprintf(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.
*/
@@ -208,8 +203,8 @@
(fp)->_lb._base = NULL; \
}
-#define FLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) flockfile(fp)
-#define FUNLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) funlockfile(fp)
+#define FLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) flockfile(fp)
+#define FUNLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp)
#define FLOATING_POINT
#define PRINTF_WIDE_CHAR
@@ -237,6 +232,10 @@
extern int __sfvwrite(FILE *, struct __suio *);
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
__END_DECLS
diff --git a/libc/stdio/refill.c b/libc/stdio/refill.c
index e87c7b9..5b0811f 100644
--- a/libc/stdio/refill.c
+++ b/libc/stdio/refill.c
@@ -51,11 +51,6 @@
int
__srefill(FILE *fp)
{
-
- /* make sure stdio is set up */
- if (!__sdidinit)
- __sinit();
-
fp->_r = 0; /* largely a convenience for callers */
#if !defined(__ANDROID__)
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index fea44f6..f273d45 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -74,7 +74,7 @@
}
int __fsetlocking(FILE* fp, int type) {
- int old_state = _EXT(fp)->_stdio_handles_locking ? FSETLOCKING_INTERNAL : FSETLOCKING_BYCALLER;
+ int old_state = _EXT(fp)->_caller_handles_locking ? FSETLOCKING_BYCALLER : FSETLOCKING_INTERNAL;
if (type == FSETLOCKING_QUERY) {
return old_state;
}
@@ -84,7 +84,7 @@
__libc_fatal("Bad type (%d) passed to __fsetlocking", type);
}
- _EXT(fp)->_stdio_handles_locking = (type == FSETLOCKING_INTERNAL);
+ _EXT(fp)->_caller_handles_locking = (type == FSETLOCKING_BYCALLER);
return old_state;
}
@@ -99,3 +99,7 @@
int ferror_unlocked(FILE* fp) {
return __sferror(fp);
}
+
+int fileno_unlocked(FILE* fp) {
+ return __sfileno(fp);
+}
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 34a4db1..c817b63 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -185,51 +185,12 @@
}
_ATEXIT_UNLOCK();
+ extern void __libc_stdio_cleanup(void);
+ __libc_stdio_cleanup();
+
/* BEGIN android-changed: call __unregister_atfork if dso is not null */
if (dso != NULL) {
__unregister_atfork(dso);
}
/* 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();
-}
diff --git a/libc/tools/genversion-scripts.py b/libc/tools/genversion-scripts.py
new file mode 100755
index 0000000..37fb5e9
--- /dev/null
+++ b/libc/tools/genversion-scripts.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+
+# This tool is used to generate the version scripts for libc and libm
+# for every architecture.
+
+import atexit
+import os.path
+import shutil
+import tempfile
+
+
+all_arches = ["arm", "arm64", "mips", "mips64", "x86", "x86_64"]
+bionic_libc_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc")
+bionic_libm_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libm")
+bionic_libdl_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libdl")
+libc_script = os.path.join(bionic_libc_root, "libc.map.txt")
+libm_script = os.path.join(bionic_libm_root, "libm.map.txt")
+libdl_script = os.path.join(bionic_libdl_root, "libdl.map.txt")
+
+# TODO (dimity): generate architecture-specific version scripts as part of build
+
+# temp directory where we store all intermediate files
+bionic_temp = tempfile.mkdtemp(prefix="bionic_genversionscripts")
+# Make sure the directory is deleted when the script exits.
+atexit.register(shutil.rmtree, bionic_temp)
+
+bionic_libc_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc")
+
+warning = "Generated by genversionscripts.py. Do not edit."
+
+
+class VersionScriptGenerator(object):
+
+ def run(self):
+ for script in [libc_script, libm_script, libdl_script]:
+ basename = os.path.basename(script)
+ dirname = os.path.dirname(script)
+ for arch in all_arches:
+ name = basename.split(".")[0] + "." + arch + ".map"
+ tmp_path = os.path.join(bionic_temp, name)
+ dest_path = os.path.join(dirname, name)
+ with open(tmp_path, "w") as fout:
+ with open(script, "r") as fin:
+ fout.write("# %s\n" % warning)
+ for line in fin:
+ index = line.find("#")
+ if index != -1:
+ arches = line[index+1:].split()
+ if arch not in arches:
+ continue
+ fout.write(line)
+ shutil.copyfile(tmp_path, dest_path)
+
+
+generator = VersionScriptGenerator()
+generator.run()
+
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 79c4a9a..b1ebb24 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -338,7 +338,7 @@
{
if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
return 0;
-#if defined(__LP64__) // 32-bit Android only has a signed 32-bit time_t; 64-bit Android is fixed.
+#if defined(__LP64__) // 32-bit Android/glibc has a signed 32-bit time_t; 64-bit doesn't.
return t1 - t0 == SECSPERREPEAT;
#endif
}
@@ -1316,9 +1316,10 @@
tzset_unlocked(void)
{
#if defined(__ANDROID__)
+ // The TZ environment variable is meant to override the system-wide setting.
const char * name = getenv("TZ");
- // Try the "persist.sys.timezone" system property.
+ // If that's not set, look at the "persist.sys.timezone" system property.
if (name == NULL) {
static const prop_info *pi;
@@ -1340,6 +1341,10 @@
}
}
+ // 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);
#else
tzsetlcl(getenv("TZ"));
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 10dfb4b..4349cf6 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -502,7 +502,23 @@
continue;
case 'Z':
#ifdef TM_ZONE
- pt = _add(t->TM_ZONE, pt, ptlim, modifier);
+ // BEGIN: Android-changed.
+ {
+ 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
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
diff --git a/libc/upstream-netbsd/android/include/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h
index 0212d16..8d1c46b 100644
--- a/libc/upstream-netbsd/android/include/netbsd-compat.h
+++ b/libc/upstream-netbsd/android/include/netbsd-compat.h
@@ -32,6 +32,6 @@
#define __unlockenv() 0
#include <stddef.h>
-int reallocarr(void*, size_t, size_t);
+__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t);
#endif
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 47bacc3..b07f55d 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -71,8 +71,8 @@
__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
/* LP32 NDK ctype.h contained references to these. */
-__LIBC64_HIDDEN__ extern const short* _tolower_tab_;
-__LIBC64_HIDDEN__ extern const short* _toupper_tab_;
+__LIBC32_LEGACY_PUBLIC__ extern const short* _tolower_tab_;
+__LIBC32_LEGACY_PUBLIC__ extern const short* _toupper_tab_;
__LIBC_HIDDEN__ extern const char _C_ctype_[];
__LIBC_HIDDEN__ extern const short _C_toupper_[];
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 46dd0eb..2aa9b68 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -13,15 +13,28 @@
// DO NOT REMOVE --exclude-libs!
ldflags: ["-Wl,--exclude-libs=libgcc.a"],
- version_script: "libdl.map",
// for x86, exclude libgcc_eh.a for the same reasons as above
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: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
+ version_script: "libdl.x86.map",
},
x86_64: {
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
+ version_script: "libdl.x86_64.map",
},
},
srcs: ["libdl.c"],
diff --git a/libdl/Android.mk b/libdl/Android.mk
index 4ab32e0..1ea5dc7 100644
--- a/libdl/Android.mk
+++ b/libdl/Android.mk
@@ -15,18 +15,31 @@
#
# DO NOT REMOVE --exclude-libs!
-LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a -Wl,--version-script=$(LOCAL_PATH)/libdl.map
+LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a
# for x86, exclude libgcc_eh.a for the same reasons as above
LOCAL_LDFLAGS_x86 := -Wl,--exclude-libs=libgcc_eh.a
LOCAL_LDFLAGS_x86_64 := $(LOCAL_LDFLAGS_x86)
+LOCAL_LDFLAGS_arm += -Wl,--version-script=$(LOCAL_PATH)/libdl.arm.map
+LOCAL_LDFLAGS_arm64 += -Wl,--version-script=$(LOCAL_PATH)/libdl.arm64.map
+LOCAL_LDFLAGS_mips += -Wl,--version-script=$(LOCAL_PATH)/libdl.mips.map
+LOCAL_LDFLAGS_mips64 += -Wl,--version-script=$(LOCAL_PATH)/libdl.mips64.map
+LOCAL_LDFLAGS_x86 += -Wl,--version-script=$(LOCAL_PATH)/libdl.x86.map
+LOCAL_LDFLAGS_x86_64 += -Wl,--version-script=$(LOCAL_PATH)/libdl.x86_64.map
+
LOCAL_SRC_FILES:= libdl.c
LOCAL_CFLAGS := -Wall -Wextra -Wunused -Werror
LOCAL_CXX_STL := none
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
# few symbols from libc. Using --no-undefined here results in having to link
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
new file mode 100644
index 0000000..5ad9f9d
--- /dev/null
+++ b/libdl/libdl.arm.map
@@ -0,0 +1,29 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dl_unwind_find_exidx; # arm
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
new file mode 100644
index 0000000..3535774
--- /dev/null
+++ b/libdl/libdl.arm64.map
@@ -0,0 +1,28 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 9a858a3..3928ba2 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -33,12 +33,30 @@
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) { return 0; }
#endif
-int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused, void* data __unused) { return 0; }
+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused,
+ void* data __unused) {
+ return 0;
+}
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_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
+void* android_dlopen_ext(const char* filename __unused, int flag __unused,
+ const android_dlextinfo* extinfo __unused) {
+ return 0;
+}
void android_set_application_target_sdk_version(uint32_t target __unused) { }
uint32_t android_get_application_target_sdk_version() { return 0; }
+
+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,
+ bool isolated __unused) {
+ return 0;
+}
diff --git a/libdl/libdl.map b/libdl/libdl.map.txt
similarity index 88%
rename from libdl/libdl.map
rename to libdl/libdl.map.txt
index a911cb6..8d123fe 100644
--- a/libdl/libdl.map
+++ b/libdl/libdl.map.txt
@@ -18,9 +18,7 @@
global:
android_dlopen_ext;
dl_iterate_phdr;
-# begin arm-only
- dl_unwind_find_exidx;
-# end arm-only
+ dl_unwind_find_exidx; # arm
dladdr;
dlclose;
dlerror;
@@ -30,10 +28,16 @@
*;
};
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
LIBC_PRIVATE {
global:
android_get_application_target_sdk_version;
android_set_application_target_sdk_version;
android_get_LD_LIBRARY_PATH;
android_update_LD_LIBRARY_PATH;
-} LIBC;
+} LIBC_N;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
new file mode 100644
index 0000000..3535774
--- /dev/null
+++ b/libdl/libdl.mips.map
@@ -0,0 +1,28 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
new file mode 100644
index 0000000..3535774
--- /dev/null
+++ b/libdl/libdl.mips64.map
@@ -0,0 +1,28 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
new file mode 100644
index 0000000..3535774
--- /dev/null
+++ b/libdl/libdl.x86.map
@@ -0,0 +1,28 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
new file mode 100644
index 0000000..3535774
--- /dev/null
+++ b/libdl/libdl.x86_64.map
@@ -0,0 +1,28 @@
+# Generated by genversionscripts.py. Do not edit.
+
+LIBC {
+ global:
+ android_dlopen_ext;
+ dl_iterate_phdr;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlopen;
+ dlsym;
+ local:
+ *;
+};
+
+LIBC_N {
+ global:
+ android_init_namespaces;
+ android_create_namespace;
+} LIBC;
+
+LIBC_PRIVATE {
+ global:
+ android_get_application_target_sdk_version;
+ android_set_application_target_sdk_version;
+ android_get_LD_LIBRARY_PATH;
+ android_update_LD_LIBRARY_PATH;
+} LIBC_N;
diff --git a/libm/Android.bp b/libm/Android.bp
index 3ae086f..081a139 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -3,18 +3,7 @@
bionic_coverage = false
-// 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 += [
+libm_common_src_files = [
"upstream-freebsd/lib/msun/bsdsrc/b_exp.c",
"upstream-freebsd/lib/msun/bsdsrc/b_log.c",
"upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c",
@@ -186,8 +175,19 @@
]
libm_common_src_files += [
- "fake_long_double.c",
+ // 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.
+ "digittoint.c",
+
+ // Functionality not in the BSDs.
+ "significandl.c",
+ "sincos.c",
+
+ // Modified versions of BSD code.
"signbit.c",
+
+ // Home-grown stuff.
"fabs.cpp",
]
@@ -254,6 +254,7 @@
"-D__BIONIC_NO_MATH_INLINES",
"-DFLT_EVAL_METHOD=0",
"-include freebsd-compat.h",
+ "-Werror",
"-Wno-missing-braces",
"-Wno-parentheses",
"-Wno-sign-compare",
@@ -290,9 +291,10 @@
native_coverage: bionic_coverage,
sanitize: ["never"],
- version_script: "libm.map",
-
multilib: {
+ lib32: {
+ srcs: ["fake_long_double.c"],
+ },
lib64: {
srcs: libm_ld128_src_files,
local_include_dirs: libm_ld_local_includes,
@@ -308,23 +310,27 @@
arm: {
srcs: [
"arm/fenv.c",
- "arm/sqrt.S",
- "arm/floor.S",
],
- exclude_srcs: [
- // TODO: these require neon not available in arm
- "upstream-freebsd/lib/msun/src/e_sqrt.c",
- "upstream-freebsd/lib/msun/src/e_sqrtf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- ],
+ armv7_a_neon: {
+ srcs: [
+ "arm/sqrt.S",
+ "arm/floor.S",
+ ],
+ exclude_srcs: [
+ "upstream-freebsd/lib/msun/src/e_sqrt.c",
+ "upstream-freebsd/lib/msun/src/e_sqrtf.c",
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ ],
+ },
instruction_set: "arm",
ldflags: ["-Wl,--hash-style=both"],
+ version_script: "libm.arm.map",
},
arm64: {
srcs: [
- "arm64/fenv.c",
"arm64/ceil.S",
+ "arm64/fenv.c",
"arm64/fma.S",
"arm64/floor.S",
"arm64/lrint.S",
@@ -333,6 +339,8 @@
"arm64/trunc.S",
],
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_ceilf.c",
"upstream-freebsd/lib/msun/src/s_fma.c",
@@ -345,33 +353,163 @@
"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/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_truncf.c",
],
+ version_script: "libm.arm64.map",
},
mips: {
srcs: ["mips/fenv.c"],
+ version_script: "libm.mips.map",
},
mips64: {
srcs: ["mips/fenv.c"],
+ version_script: "libm.mips64.map",
},
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"],
- srcs: ["i387/fenv.c"],
// Clang has wrong long double sizes for x86.
clang: false,
ldflags: ["-Wl,--hash-style=both"],
+ version_script: "libm.x86.map",
},
x86_64: {
- srcs: ["amd64/fenv.c"],
+ srcs: [
+ "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: false,
+ version_script: "libm.x86_64.map",
},
},
diff --git a/libm/Android.mk b/libm/Android.mk
index fb8df07..faf3c50 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -22,14 +22,19 @@
upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c \
upstream-freebsd/lib/msun/src/catrig.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_acosh.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_atan2.c \
upstream-freebsd/lib/msun/src/e_atan2f.c \
upstream-freebsd/lib/msun/src/e_atanh.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_exp.c \
upstream-freebsd/lib/msun/src/e_expf.c \
upstream-freebsd/lib/msun/src/e_fmod.c \
upstream-freebsd/lib/msun/src/e_fmodf.c \
@@ -37,6 +42,7 @@
upstream-freebsd/lib/msun/src/e_gammaf.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_hypot.c \
upstream-freebsd/lib/msun/src/e_hypotf.c \
upstream-freebsd/lib/msun/src/e_j0.c \
upstream-freebsd/lib/msun/src/e_j0f.c \
@@ -48,10 +54,13 @@
upstream-freebsd/lib/msun/src/e_lgammaf.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_log10.c \
upstream-freebsd/lib/msun/src/e_log10f.c \
upstream-freebsd/lib/msun/src/e_log2.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_pow.c \
upstream-freebsd/lib/msun/src/e_powf.c \
upstream-freebsd/lib/msun/src/e_remainder.c \
upstream-freebsd/lib/msun/src/e_remainderf.c \
@@ -59,7 +68,10 @@
upstream-freebsd/lib/msun/src/e_rem_pio2f.c \
upstream-freebsd/lib/msun/src/e_scalb.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_sqrt.c \
+ upstream-freebsd/lib/msun/src/e_sqrtf.c \
upstream-freebsd/lib/msun/src/imprecise.c \
upstream-freebsd/lib/msun/src/k_cos.c \
upstream-freebsd/lib/msun/src/k_cosf.c \
@@ -72,13 +84,17 @@
upstream-freebsd/lib/msun/src/k_tanf.c \
upstream-freebsd/lib/msun/src/s_asinh.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_carg.c \
upstream-freebsd/lib/msun/src/s_cargf.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_ccosh.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_cexpf.c \
upstream-freebsd/lib/msun/src/s_cimag.c \
@@ -89,6 +105,7 @@
upstream-freebsd/lib/msun/src/s_conjl.c \
upstream-freebsd/lib/msun/src/s_copysign.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_cproj.c \
upstream-freebsd/lib/msun/src/s_cprojf.c \
@@ -107,10 +124,15 @@
upstream-freebsd/lib/msun/src/s_erff.c \
upstream-freebsd/lib/msun/src/s_exp2.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_fdim.c \
upstream-freebsd/lib/msun/src/s_finite.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_fmaxf.c \
upstream-freebsd/lib/msun/src/s_fmin.c \
@@ -119,11 +141,16 @@
upstream-freebsd/lib/msun/src/s_frexpf.c \
upstream-freebsd/lib/msun/src/s_ilogb.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_llroundf.c \
+ upstream-freebsd/lib/msun/src/s_log1p.c \
upstream-freebsd/lib/msun/src/s_log1pf.c \
upstream-freebsd/lib/msun/src/s_logb.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_lroundf.c \
upstream-freebsd/lib/msun/src/s_modf.c \
@@ -134,6 +161,8 @@
upstream-freebsd/lib/msun/src/s_nextafterf.c \
upstream-freebsd/lib/msun/src/s_remquo.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_roundf.c \
upstream-freebsd/lib/msun/src/s_scalbln.c \
@@ -142,10 +171,15 @@
upstream-freebsd/lib/msun/src/s_signgam.c \
upstream-freebsd/lib/msun/src/s_significand.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_tan.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_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_cabsf.c \
upstream-freebsd/lib/msun/src/w_cabsl.c \
@@ -236,37 +270,6 @@
# -----------------------------------------------------------------------------
LOCAL_SRC_FILES_arm += \
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.
ifdef TARGET_2ND_ARCH
@@ -276,17 +279,16 @@
endif
# Use the C version on armv7-a since it doesn't support neon instructions.
-ifeq ($(arch_variant),armv7-a)
-LOCAL_SRC_FILES_arm += \
- upstream-freebsd/lib/msun/src/e_sqrt.c \
- upstream-freebsd/lib/msun/src/e_sqrtf.c \
- upstream-freebsd/lib/msun/src/s_floor.c \
-
-else
+ifneq ($(arch_variant),armv7-a)
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_sqrtf.c \
+ upstream-freebsd/lib/msun/src/s_floor.c \
+
endif
# -----------------------------------------------------------------------------
@@ -301,64 +303,30 @@
arm64/rint.S \
arm64/sqrt.S \
arm64/trunc.S \
- 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_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 \
+
+LOCAL_SRC_FILES_EXCLUDE_arm64 += \
+ 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_ceilf.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_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 \
+ upstream-freebsd/lib/msun/src/s_trunc.c \
+ upstream-freebsd/lib/msun/src/s_truncf.c \
# -----------------------------------------------------------------------------
# mips
# -----------------------------------------------------------------------------
libm_mips_arch_files := \
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_mips64 += $(libm_mips_arch_files)
@@ -368,14 +336,6 @@
# -----------------------------------------------------------------------------
LOCAL_SRC_FILES_x86 += \
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/sqrtf.S \
x86/e_acos.S \
@@ -400,6 +360,28 @@
x86/s_tanh.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)
LOCAL_SRC_FILES_x86 += \
x86/ceil.S \
@@ -409,8 +391,7 @@
x86/trunc.S \
x86/truncf.S \
-else
-LOCAL_SRC_FILES_x86 += \
+LOCAL_SRC_FILES_EXCLUDE_x86 += \
upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_floor.c \
@@ -425,14 +406,6 @@
# -----------------------------------------------------------------------------
LOCAL_SRC_FILES_x86_64 += \
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/sqrtf.S \
x86_64/e_acos.S \
@@ -454,6 +427,28 @@
x86_64/s_tanh.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)
LOCAL_SRC_FILES_x86_64 += \
x86_64/ceil.S \
@@ -463,8 +458,7 @@
x86_64/trunc.S \
x86_64/truncf.S \
-else
-LOCAL_SRC_FILES_x86_64 += \
+LOCAL_SRC_FILES_EXCLUDE_x86_64 += \
upstream-freebsd/lib/msun/src/s_ceil.c \
upstream-freebsd/lib/msun/src/s_ceilf.c \
upstream-freebsd/lib/msun/src/s_floor.c \
@@ -485,6 +479,7 @@
-D__BIONIC_NO_MATH_INLINES \
-DFLT_EVAL_METHOD=0 \
-include $(LOCAL_PATH)/freebsd-compat.h \
+ -Werror \
-Wno-missing-braces \
-Wno-parentheses \
-Wno-sign-compare \
@@ -512,13 +507,25 @@
# -----------------------------------------------------------------------------
include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/libm.map
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(LOCAL_PATH)/libm.arm.map \
+ $(LOCAL_PATH)/libm.arm64.map \
+ $(LOCAL_PATH)/libm.mips.map \
+ $(LOCAL_PATH)/libm.mips64.map \
+ $(LOCAL_PATH)/libm.x86.map \
+ $(LOCAL_PATH)/libm.x86_64.map \
# TODO: This is to work around b/24465209. Remove after root cause is fixed
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
-LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libm.map
+LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libm.arm.map
+LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libm.arm64.map
+LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libm.mips.map
+LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libm.mips64.map
+LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libm.x86.map
+LOCAL_LDFLAGS_x86_64 += -Wl,--version-script,$(LOCAL_PATH)/libm.x86_64.map
+
LOCAL_MODULE := libm
LOCAL_CLANG := $(libm_clang)
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index ce560a7..19a2393 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -26,6 +26,7 @@
* $FreeBSD: libm/aarch64/fenv.c $
*/
+#include <stdint.h>
#include <fenv.h>
#define FPCR_EXCEPT_SHIFT 8
@@ -38,10 +39,20 @@
typedef __uint32_t fpu_control_t; // FPCR, Floating-point Control Register.
typedef __uint32_t fpu_status_t; // FPSR, Floating-point Status Register.
-#define __get_fpcr(__fpcr) __asm__ __volatile__("mrs %0,fpcr" : "=r" (__fpcr))
-#define __get_fpsr(__fpsr) __asm__ __volatile__("mrs %0,fpsr" : "=r" (__fpsr))
-#define __set_fpcr(__fpcr) __asm__ __volatile__("msr fpcr,%0" : :"ri" (__fpcr))
-#define __set_fpsr(__fpsr) __asm__ __volatile__("msr fpsr,%0" : :"ri" (__fpsr))
+#define __get(REGISTER, __value) { \
+ uint64_t __value64; \
+ __asm__ __volatile__("mrs %0," REGISTER : "=r" (__value64)); \
+ __value = (__uint32_t) __value64; \
+}
+#define __get_fpcr(__fpcr) __get("fpcr", __fpcr)
+#define __get_fpsr(__fpsr) __get("fpsr", __fpsr)
+
+#define __set(REGISTER, __value) { \
+ uint64_t __value64 = __value; \
+ __asm__ __volatile__("msr " REGISTER ",%0" : : "ri" (__value64)); \
+}
+#define __set_fpcr(__fpcr) __set("fpcr", __fpcr)
+#define __set_fpsr(__fpsr) __set("fpsr", __fpsr)
int fegetenv(fenv_t* envp) {
__get_fpcr(envp->__control);
diff --git a/libm/libm.map b/libm/libm.arm.map
similarity index 97%
copy from libm/libm.map
copy to libm/libm.arm.map
index 7f02f42..e781f2d 100644
--- a/libm/libm.map
+++ b/libm/libm.arm.map
@@ -1,3 +1,4 @@
+# Generated by genversionscripts.py. Do not edit.
LIBC {
global:
__fe_dfl_env;
@@ -271,8 +272,8 @@
*;
};
-LIBC_PRIVATE {
- global:
+LIBC_PRIVATE { # arm mips
+ global: # arm mips
___Unwind_Backtrace; # arm
___Unwind_ForcedUnwind; # arm
___Unwind_RaiseException; # arm
@@ -353,7 +354,6 @@
__lesf2; # arm
__ltdf2; # arm
__ltsf2; # arm
- __muldc3; # arm x86 mips
__muldf3; # arm
__nedf2; # arm
__nesf2; # arm
@@ -375,4 +375,4 @@
_Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm
restore_core_regs; # arm
-} LIBC;
+} LIBC; # arm mips
diff --git a/libm/libm.arm64.map b/libm/libm.arm64.map
new file mode 100644
index 0000000..1623ea0
--- /dev/null
+++ b/libm/libm.arm64.map
@@ -0,0 +1,274 @@
+# Generated by genversionscripts.py. Do not edit.
+LIBC {
+ global:
+ __fe_dfl_env;
+ __signbit;
+ __signbitf;
+ __signbitl;
+ acos;
+ acosf;
+ acosh;
+ acoshf;
+ acoshl;
+ acosl;
+ asin;
+ asinf;
+ asinh;
+ asinhf;
+ asinhl;
+ asinl;
+ atan;
+ atan2;
+ atan2f;
+ atan2l;
+ atanf;
+ atanh;
+ atanhf;
+ atanhl;
+ atanl;
+ cabs;
+ cabsf;
+ cabsl;
+ cacos;
+ cacosf;
+ cacosh;
+ cacoshf;
+ carg;
+ cargf;
+ cargl;
+ casin;
+ casinf;
+ casinh;
+ casinhf;
+ catan;
+ catanf;
+ catanh;
+ catanhf;
+ cbrt;
+ cbrtf;
+ cbrtl;
+ ccos;
+ ccosf;
+ ccosh;
+ ccoshf;
+ ceil;
+ ceilf;
+ ceill;
+ cexp;
+ cexpf;
+ cimag;
+ cimagf;
+ cimagl;
+ conj;
+ conjf;
+ conjl;
+ copysign;
+ copysignf;
+ copysignl;
+ cos;
+ cosf;
+ cosh;
+ coshf;
+ coshl;
+ cosl;
+ cproj;
+ cprojf;
+ cprojl;
+ creal;
+ crealf;
+ creall;
+ csin;
+ csinf;
+ csinh;
+ csinhf;
+ csqrt;
+ csqrtf;
+ csqrtl;
+ ctan;
+ ctanf;
+ ctanh;
+ ctanhf;
+ drem;
+ dremf;
+ erf;
+ erfc;
+ erfcf;
+ erfcl;
+ erff;
+ erfl;
+ exp;
+ exp2;
+ exp2f;
+ exp2l;
+ expf;
+ expl;
+ expm1;
+ expm1f;
+ expm1l;
+ fabs;
+ fabsf;
+ fabsl;
+ fdim;
+ fdimf;
+ fdiml;
+ feclearexcept;
+ fedisableexcept;
+ feenableexcept;
+ fegetenv;
+ fegetexcept;
+ fegetexceptflag;
+ fegetround;
+ feholdexcept;
+ feraiseexcept;
+ fesetenv;
+ fesetexceptflag;
+ fesetround;
+ fetestexcept;
+ feupdateenv;
+ finite;
+ finitef;
+ floor;
+ floorf;
+ floorl;
+ fma;
+ fmaf;
+ fmal;
+ fmax;
+ fmaxf;
+ fmaxl;
+ fmin;
+ fminf;
+ fminl;
+ fmod;
+ fmodf;
+ fmodl;
+ frexp;
+ frexpf;
+ frexpl;
+ gamma;
+ gamma_r;
+ gammaf;
+ gammaf_r;
+ hypot;
+ hypotf;
+ hypotl;
+ ilogb;
+ ilogbf;
+ ilogbl;
+ j0;
+ j0f;
+ j1;
+ j1f;
+ jn;
+ jnf;
+ ldexpf;
+ ldexpl;
+ lgamma;
+ lgamma_r;
+ lgammaf;
+ lgammaf_r;
+ lgammal;
+ lgammal_r;
+ llrint;
+ llrintf;
+ llrintl;
+ llround;
+ llroundf;
+ llroundl;
+ log;
+ log10;
+ log10f;
+ log10l;
+ log1p;
+ log1pf;
+ log1pl;
+ log2;
+ log2f;
+ log2l;
+ logb;
+ logbf;
+ logbl;
+ logf;
+ logl;
+ lrint;
+ lrintf;
+ lrintl;
+ lround;
+ lroundf;
+ lroundl;
+ modf;
+ modff;
+ modfl;
+ nan;
+ nanf;
+ nanl;
+ nearbyint;
+ nearbyintf;
+ nearbyintl;
+ nextafter;
+ nextafterf;
+ nextafterl;
+ nexttoward;
+ nexttowardf;
+ nexttowardl;
+ pow;
+ powf;
+ powl;
+ remainder;
+ remainderf;
+ remainderl;
+ remquo;
+ remquof;
+ remquol;
+ rint;
+ rintf;
+ rintl;
+ round;
+ roundf;
+ roundl;
+ scalb;
+ scalbf;
+ scalbln;
+ scalblnf;
+ scalblnl;
+ scalbn;
+ scalbnf;
+ scalbnl;
+ signgam;
+ significand;
+ significandf;
+ significandl;
+ sin;
+ sincos;
+ sincosf;
+ sincosl;
+ sinf;
+ sinh;
+ sinhf;
+ sinhl;
+ sinl;
+ sqrt;
+ sqrtf;
+ sqrtl;
+ tan;
+ tanf;
+ tanh;
+ tanhf;
+ tanhl;
+ tanl;
+ tgamma;
+ tgammaf;
+ tgammal;
+ trunc;
+ truncf;
+ truncl;
+ y0;
+ y0f;
+ y1;
+ y1f;
+ yn;
+ ynf;
+ local:
+ *;
+};
+
diff --git a/libm/libm.map b/libm/libm.map.txt
similarity index 98%
rename from libm/libm.map
rename to libm/libm.map.txt
index 7f02f42..075ebd5 100644
--- a/libm/libm.map
+++ b/libm/libm.map.txt
@@ -271,8 +271,8 @@
*;
};
-LIBC_PRIVATE {
- global:
+LIBC_PRIVATE { # arm mips
+ global: # arm mips
___Unwind_Backtrace; # arm
___Unwind_ForcedUnwind; # arm
___Unwind_RaiseException; # arm
@@ -353,7 +353,6 @@
__lesf2; # arm
__ltdf2; # arm
__ltsf2; # arm
- __muldc3; # arm x86 mips
__muldf3; # arm
__nedf2; # arm
__nesf2; # arm
@@ -375,4 +374,4 @@
_Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm
restore_core_regs; # arm
-} LIBC;
+} LIBC; # arm mips
diff --git a/libm/libm.mips.map b/libm/libm.mips.map
new file mode 100644
index 0000000..476c6ad
--- /dev/null
+++ b/libm/libm.mips.map
@@ -0,0 +1,281 @@
+# Generated by genversionscripts.py. Do not edit.
+LIBC {
+ global:
+ __fe_dfl_env;
+ __signbit;
+ __signbitf;
+ __signbitl;
+ acos;
+ acosf;
+ acosh;
+ acoshf;
+ acoshl;
+ acosl;
+ asin;
+ asinf;
+ asinh;
+ asinhf;
+ asinhl;
+ asinl;
+ atan;
+ atan2;
+ atan2f;
+ atan2l;
+ atanf;
+ atanh;
+ atanhf;
+ atanhl;
+ atanl;
+ cabs;
+ cabsf;
+ cabsl;
+ cacos;
+ cacosf;
+ cacosh;
+ cacoshf;
+ carg;
+ cargf;
+ cargl;
+ casin;
+ casinf;
+ casinh;
+ casinhf;
+ catan;
+ catanf;
+ catanh;
+ catanhf;
+ cbrt;
+ cbrtf;
+ cbrtl;
+ ccos;
+ ccosf;
+ ccosh;
+ ccoshf;
+ ceil;
+ ceilf;
+ ceill;
+ cexp;
+ cexpf;
+ cimag;
+ cimagf;
+ cimagl;
+ conj;
+ conjf;
+ conjl;
+ copysign;
+ copysignf;
+ copysignl;
+ cos;
+ cosf;
+ cosh;
+ coshf;
+ coshl;
+ cosl;
+ cproj;
+ cprojf;
+ cprojl;
+ creal;
+ crealf;
+ creall;
+ csin;
+ csinf;
+ csinh;
+ csinhf;
+ csqrt;
+ csqrtf;
+ csqrtl;
+ ctan;
+ ctanf;
+ ctanh;
+ ctanhf;
+ drem;
+ dremf;
+ erf;
+ erfc;
+ erfcf;
+ erfcl;
+ erff;
+ erfl;
+ exp;
+ exp2;
+ exp2f;
+ exp2l;
+ expf;
+ expl;
+ expm1;
+ expm1f;
+ expm1l;
+ fabs;
+ fabsf;
+ fabsl;
+ fdim;
+ fdimf;
+ fdiml;
+ feclearexcept;
+ fedisableexcept;
+ feenableexcept;
+ fegetenv;
+ fegetexcept;
+ fegetexceptflag;
+ fegetround;
+ feholdexcept;
+ feraiseexcept;
+ fesetenv;
+ fesetexceptflag;
+ fesetround;
+ fetestexcept;
+ feupdateenv;
+ finite;
+ finitef;
+ floor;
+ floorf;
+ floorl;
+ fma;
+ fmaf;
+ fmal;
+ fmax;
+ fmaxf;
+ fmaxl;
+ fmin;
+ fminf;
+ fminl;
+ fmod;
+ fmodf;
+ fmodl;
+ frexp;
+ frexpf;
+ frexpl;
+ gamma;
+ gamma_r;
+ gammaf;
+ gammaf_r;
+ hypot;
+ hypotf;
+ hypotl;
+ ilogb;
+ ilogbf;
+ ilogbl;
+ j0;
+ j0f;
+ j1;
+ j1f;
+ jn;
+ jnf;
+ ldexpf;
+ ldexpl;
+ lgamma;
+ lgamma_r;
+ lgammaf;
+ lgammaf_r;
+ lgammal;
+ lgammal_r;
+ llrint;
+ llrintf;
+ llrintl;
+ llround;
+ llroundf;
+ llroundl;
+ log;
+ log10;
+ log10f;
+ log10l;
+ log1p;
+ log1pf;
+ log1pl;
+ log2;
+ log2f;
+ log2l;
+ logb;
+ logbf;
+ logbl;
+ logf;
+ logl;
+ lrint;
+ lrintf;
+ lrintl;
+ lround;
+ lroundf;
+ lroundl;
+ modf;
+ modff;
+ modfl;
+ nan;
+ nanf;
+ nanl;
+ nearbyint;
+ nearbyintf;
+ nearbyintl;
+ nextafter;
+ nextafterf;
+ nextafterl;
+ nexttoward;
+ nexttowardf;
+ nexttowardl;
+ pow;
+ powf;
+ powl;
+ remainder;
+ remainderf;
+ remainderl;
+ remquo;
+ remquof;
+ remquol;
+ rint;
+ rintf;
+ rintl;
+ round;
+ roundf;
+ roundl;
+ scalb;
+ scalbf;
+ scalbln;
+ scalblnf;
+ scalblnl;
+ scalbn;
+ scalbnf;
+ scalbnl;
+ signgam;
+ significand;
+ significandf;
+ significandl;
+ sin;
+ sincos;
+ sincosf;
+ sincosl;
+ sinf;
+ sinh;
+ sinhf;
+ sinhl;
+ sinl;
+ sqrt;
+ sqrtf;
+ sqrtl;
+ tan;
+ tanf;
+ tanh;
+ tanhf;
+ tanhl;
+ tanl;
+ tgamma;
+ tgammaf;
+ tgammal;
+ trunc;
+ truncf;
+ truncl;
+ y0;
+ y0f;
+ y1;
+ y1f;
+ yn;
+ ynf;
+ local:
+ *;
+};
+
+LIBC_PRIVATE { # arm mips
+ global: # arm mips
+ __fixdfdi; # arm mips
+ __fixsfdi; # arm mips
+ __fixunsdfdi; # arm mips
+ __fixunssfdi; # arm mips
+} LIBC; # arm mips
diff --git a/libm/libm.mips64.map b/libm/libm.mips64.map
new file mode 100644
index 0000000..1623ea0
--- /dev/null
+++ b/libm/libm.mips64.map
@@ -0,0 +1,274 @@
+# Generated by genversionscripts.py. Do not edit.
+LIBC {
+ global:
+ __fe_dfl_env;
+ __signbit;
+ __signbitf;
+ __signbitl;
+ acos;
+ acosf;
+ acosh;
+ acoshf;
+ acoshl;
+ acosl;
+ asin;
+ asinf;
+ asinh;
+ asinhf;
+ asinhl;
+ asinl;
+ atan;
+ atan2;
+ atan2f;
+ atan2l;
+ atanf;
+ atanh;
+ atanhf;
+ atanhl;
+ atanl;
+ cabs;
+ cabsf;
+ cabsl;
+ cacos;
+ cacosf;
+ cacosh;
+ cacoshf;
+ carg;
+ cargf;
+ cargl;
+ casin;
+ casinf;
+ casinh;
+ casinhf;
+ catan;
+ catanf;
+ catanh;
+ catanhf;
+ cbrt;
+ cbrtf;
+ cbrtl;
+ ccos;
+ ccosf;
+ ccosh;
+ ccoshf;
+ ceil;
+ ceilf;
+ ceill;
+ cexp;
+ cexpf;
+ cimag;
+ cimagf;
+ cimagl;
+ conj;
+ conjf;
+ conjl;
+ copysign;
+ copysignf;
+ copysignl;
+ cos;
+ cosf;
+ cosh;
+ coshf;
+ coshl;
+ cosl;
+ cproj;
+ cprojf;
+ cprojl;
+ creal;
+ crealf;
+ creall;
+ csin;
+ csinf;
+ csinh;
+ csinhf;
+ csqrt;
+ csqrtf;
+ csqrtl;
+ ctan;
+ ctanf;
+ ctanh;
+ ctanhf;
+ drem;
+ dremf;
+ erf;
+ erfc;
+ erfcf;
+ erfcl;
+ erff;
+ erfl;
+ exp;
+ exp2;
+ exp2f;
+ exp2l;
+ expf;
+ expl;
+ expm1;
+ expm1f;
+ expm1l;
+ fabs;
+ fabsf;
+ fabsl;
+ fdim;
+ fdimf;
+ fdiml;
+ feclearexcept;
+ fedisableexcept;
+ feenableexcept;
+ fegetenv;
+ fegetexcept;
+ fegetexceptflag;
+ fegetround;
+ feholdexcept;
+ feraiseexcept;
+ fesetenv;
+ fesetexceptflag;
+ fesetround;
+ fetestexcept;
+ feupdateenv;
+ finite;
+ finitef;
+ floor;
+ floorf;
+ floorl;
+ fma;
+ fmaf;
+ fmal;
+ fmax;
+ fmaxf;
+ fmaxl;
+ fmin;
+ fminf;
+ fminl;
+ fmod;
+ fmodf;
+ fmodl;
+ frexp;
+ frexpf;
+ frexpl;
+ gamma;
+ gamma_r;
+ gammaf;
+ gammaf_r;
+ hypot;
+ hypotf;
+ hypotl;
+ ilogb;
+ ilogbf;
+ ilogbl;
+ j0;
+ j0f;
+ j1;
+ j1f;
+ jn;
+ jnf;
+ ldexpf;
+ ldexpl;
+ lgamma;
+ lgamma_r;
+ lgammaf;
+ lgammaf_r;
+ lgammal;
+ lgammal_r;
+ llrint;
+ llrintf;
+ llrintl;
+ llround;
+ llroundf;
+ llroundl;
+ log;
+ log10;
+ log10f;
+ log10l;
+ log1p;
+ log1pf;
+ log1pl;
+ log2;
+ log2f;
+ log2l;
+ logb;
+ logbf;
+ logbl;
+ logf;
+ logl;
+ lrint;
+ lrintf;
+ lrintl;
+ lround;
+ lroundf;
+ lroundl;
+ modf;
+ modff;
+ modfl;
+ nan;
+ nanf;
+ nanl;
+ nearbyint;
+ nearbyintf;
+ nearbyintl;
+ nextafter;
+ nextafterf;
+ nextafterl;
+ nexttoward;
+ nexttowardf;
+ nexttowardl;
+ pow;
+ powf;
+ powl;
+ remainder;
+ remainderf;
+ remainderl;
+ remquo;
+ remquof;
+ remquol;
+ rint;
+ rintf;
+ rintl;
+ round;
+ roundf;
+ roundl;
+ scalb;
+ scalbf;
+ scalbln;
+ scalblnf;
+ scalblnl;
+ scalbn;
+ scalbnf;
+ scalbnl;
+ signgam;
+ significand;
+ significandf;
+ significandl;
+ sin;
+ sincos;
+ sincosf;
+ sincosl;
+ sinf;
+ sinh;
+ sinhf;
+ sinhl;
+ sinl;
+ sqrt;
+ sqrtf;
+ sqrtl;
+ tan;
+ tanf;
+ tanh;
+ tanhf;
+ tanhl;
+ tanl;
+ tgamma;
+ tgammaf;
+ tgammal;
+ trunc;
+ truncf;
+ truncl;
+ y0;
+ y0f;
+ y1;
+ y1f;
+ yn;
+ ynf;
+ local:
+ *;
+};
+
diff --git a/libm/libm.x86.map b/libm/libm.x86.map
new file mode 100644
index 0000000..1623ea0
--- /dev/null
+++ b/libm/libm.x86.map
@@ -0,0 +1,274 @@
+# Generated by genversionscripts.py. Do not edit.
+LIBC {
+ global:
+ __fe_dfl_env;
+ __signbit;
+ __signbitf;
+ __signbitl;
+ acos;
+ acosf;
+ acosh;
+ acoshf;
+ acoshl;
+ acosl;
+ asin;
+ asinf;
+ asinh;
+ asinhf;
+ asinhl;
+ asinl;
+ atan;
+ atan2;
+ atan2f;
+ atan2l;
+ atanf;
+ atanh;
+ atanhf;
+ atanhl;
+ atanl;
+ cabs;
+ cabsf;
+ cabsl;
+ cacos;
+ cacosf;
+ cacosh;
+ cacoshf;
+ carg;
+ cargf;
+ cargl;
+ casin;
+ casinf;
+ casinh;
+ casinhf;
+ catan;
+ catanf;
+ catanh;
+ catanhf;
+ cbrt;
+ cbrtf;
+ cbrtl;
+ ccos;
+ ccosf;
+ ccosh;
+ ccoshf;
+ ceil;
+ ceilf;
+ ceill;
+ cexp;
+ cexpf;
+ cimag;
+ cimagf;
+ cimagl;
+ conj;
+ conjf;
+ conjl;
+ copysign;
+ copysignf;
+ copysignl;
+ cos;
+ cosf;
+ cosh;
+ coshf;
+ coshl;
+ cosl;
+ cproj;
+ cprojf;
+ cprojl;
+ creal;
+ crealf;
+ creall;
+ csin;
+ csinf;
+ csinh;
+ csinhf;
+ csqrt;
+ csqrtf;
+ csqrtl;
+ ctan;
+ ctanf;
+ ctanh;
+ ctanhf;
+ drem;
+ dremf;
+ erf;
+ erfc;
+ erfcf;
+ erfcl;
+ erff;
+ erfl;
+ exp;
+ exp2;
+ exp2f;
+ exp2l;
+ expf;
+ expl;
+ expm1;
+ expm1f;
+ expm1l;
+ fabs;
+ fabsf;
+ fabsl;
+ fdim;
+ fdimf;
+ fdiml;
+ feclearexcept;
+ fedisableexcept;
+ feenableexcept;
+ fegetenv;
+ fegetexcept;
+ fegetexceptflag;
+ fegetround;
+ feholdexcept;
+ feraiseexcept;
+ fesetenv;
+ fesetexceptflag;
+ fesetround;
+ fetestexcept;
+ feupdateenv;
+ finite;
+ finitef;
+ floor;
+ floorf;
+ floorl;
+ fma;
+ fmaf;
+ fmal;
+ fmax;
+ fmaxf;
+ fmaxl;
+ fmin;
+ fminf;
+ fminl;
+ fmod;
+ fmodf;
+ fmodl;
+ frexp;
+ frexpf;
+ frexpl;
+ gamma;
+ gamma_r;
+ gammaf;
+ gammaf_r;
+ hypot;
+ hypotf;
+ hypotl;
+ ilogb;
+ ilogbf;
+ ilogbl;
+ j0;
+ j0f;
+ j1;
+ j1f;
+ jn;
+ jnf;
+ ldexpf;
+ ldexpl;
+ lgamma;
+ lgamma_r;
+ lgammaf;
+ lgammaf_r;
+ lgammal;
+ lgammal_r;
+ llrint;
+ llrintf;
+ llrintl;
+ llround;
+ llroundf;
+ llroundl;
+ log;
+ log10;
+ log10f;
+ log10l;
+ log1p;
+ log1pf;
+ log1pl;
+ log2;
+ log2f;
+ log2l;
+ logb;
+ logbf;
+ logbl;
+ logf;
+ logl;
+ lrint;
+ lrintf;
+ lrintl;
+ lround;
+ lroundf;
+ lroundl;
+ modf;
+ modff;
+ modfl;
+ nan;
+ nanf;
+ nanl;
+ nearbyint;
+ nearbyintf;
+ nearbyintl;
+ nextafter;
+ nextafterf;
+ nextafterl;
+ nexttoward;
+ nexttowardf;
+ nexttowardl;
+ pow;
+ powf;
+ powl;
+ remainder;
+ remainderf;
+ remainderl;
+ remquo;
+ remquof;
+ remquol;
+ rint;
+ rintf;
+ rintl;
+ round;
+ roundf;
+ roundl;
+ scalb;
+ scalbf;
+ scalbln;
+ scalblnf;
+ scalblnl;
+ scalbn;
+ scalbnf;
+ scalbnl;
+ signgam;
+ significand;
+ significandf;
+ significandl;
+ sin;
+ sincos;
+ sincosf;
+ sincosl;
+ sinf;
+ sinh;
+ sinhf;
+ sinhl;
+ sinl;
+ sqrt;
+ sqrtf;
+ sqrtl;
+ tan;
+ tanf;
+ tanh;
+ tanhf;
+ tanhl;
+ tanl;
+ tgamma;
+ tgammaf;
+ tgammal;
+ trunc;
+ truncf;
+ truncl;
+ y0;
+ y0f;
+ y1;
+ y1f;
+ yn;
+ ynf;
+ local:
+ *;
+};
+
diff --git a/libm/libm.x86_64.map b/libm/libm.x86_64.map
new file mode 100644
index 0000000..1623ea0
--- /dev/null
+++ b/libm/libm.x86_64.map
@@ -0,0 +1,274 @@
+# Generated by genversionscripts.py. Do not edit.
+LIBC {
+ global:
+ __fe_dfl_env;
+ __signbit;
+ __signbitf;
+ __signbitl;
+ acos;
+ acosf;
+ acosh;
+ acoshf;
+ acoshl;
+ acosl;
+ asin;
+ asinf;
+ asinh;
+ asinhf;
+ asinhl;
+ asinl;
+ atan;
+ atan2;
+ atan2f;
+ atan2l;
+ atanf;
+ atanh;
+ atanhf;
+ atanhl;
+ atanl;
+ cabs;
+ cabsf;
+ cabsl;
+ cacos;
+ cacosf;
+ cacosh;
+ cacoshf;
+ carg;
+ cargf;
+ cargl;
+ casin;
+ casinf;
+ casinh;
+ casinhf;
+ catan;
+ catanf;
+ catanh;
+ catanhf;
+ cbrt;
+ cbrtf;
+ cbrtl;
+ ccos;
+ ccosf;
+ ccosh;
+ ccoshf;
+ ceil;
+ ceilf;
+ ceill;
+ cexp;
+ cexpf;
+ cimag;
+ cimagf;
+ cimagl;
+ conj;
+ conjf;
+ conjl;
+ copysign;
+ copysignf;
+ copysignl;
+ cos;
+ cosf;
+ cosh;
+ coshf;
+ coshl;
+ cosl;
+ cproj;
+ cprojf;
+ cprojl;
+ creal;
+ crealf;
+ creall;
+ csin;
+ csinf;
+ csinh;
+ csinhf;
+ csqrt;
+ csqrtf;
+ csqrtl;
+ ctan;
+ ctanf;
+ ctanh;
+ ctanhf;
+ drem;
+ dremf;
+ erf;
+ erfc;
+ erfcf;
+ erfcl;
+ erff;
+ erfl;
+ exp;
+ exp2;
+ exp2f;
+ exp2l;
+ expf;
+ expl;
+ expm1;
+ expm1f;
+ expm1l;
+ fabs;
+ fabsf;
+ fabsl;
+ fdim;
+ fdimf;
+ fdiml;
+ feclearexcept;
+ fedisableexcept;
+ feenableexcept;
+ fegetenv;
+ fegetexcept;
+ fegetexceptflag;
+ fegetround;
+ feholdexcept;
+ feraiseexcept;
+ fesetenv;
+ fesetexceptflag;
+ fesetround;
+ fetestexcept;
+ feupdateenv;
+ finite;
+ finitef;
+ floor;
+ floorf;
+ floorl;
+ fma;
+ fmaf;
+ fmal;
+ fmax;
+ fmaxf;
+ fmaxl;
+ fmin;
+ fminf;
+ fminl;
+ fmod;
+ fmodf;
+ fmodl;
+ frexp;
+ frexpf;
+ frexpl;
+ gamma;
+ gamma_r;
+ gammaf;
+ gammaf_r;
+ hypot;
+ hypotf;
+ hypotl;
+ ilogb;
+ ilogbf;
+ ilogbl;
+ j0;
+ j0f;
+ j1;
+ j1f;
+ jn;
+ jnf;
+ ldexpf;
+ ldexpl;
+ lgamma;
+ lgamma_r;
+ lgammaf;
+ lgammaf_r;
+ lgammal;
+ lgammal_r;
+ llrint;
+ llrintf;
+ llrintl;
+ llround;
+ llroundf;
+ llroundl;
+ log;
+ log10;
+ log10f;
+ log10l;
+ log1p;
+ log1pf;
+ log1pl;
+ log2;
+ log2f;
+ log2l;
+ logb;
+ logbf;
+ logbl;
+ logf;
+ logl;
+ lrint;
+ lrintf;
+ lrintl;
+ lround;
+ lroundf;
+ lroundl;
+ modf;
+ modff;
+ modfl;
+ nan;
+ nanf;
+ nanl;
+ nearbyint;
+ nearbyintf;
+ nearbyintl;
+ nextafter;
+ nextafterf;
+ nextafterl;
+ nexttoward;
+ nexttowardf;
+ nexttowardl;
+ pow;
+ powf;
+ powl;
+ remainder;
+ remainderf;
+ remainderl;
+ remquo;
+ remquof;
+ remquol;
+ rint;
+ rintf;
+ rintl;
+ round;
+ roundf;
+ roundl;
+ scalb;
+ scalbf;
+ scalbln;
+ scalblnf;
+ scalblnl;
+ scalbn;
+ scalbnf;
+ scalbnl;
+ signgam;
+ significand;
+ significandf;
+ significandl;
+ sin;
+ sincos;
+ sincosf;
+ sincosl;
+ sinf;
+ sinh;
+ sinhf;
+ sinhl;
+ sinl;
+ sqrt;
+ sqrtf;
+ sqrtl;
+ tan;
+ tanf;
+ tanh;
+ tanhf;
+ tanhl;
+ tanl;
+ tgamma;
+ tgammaf;
+ tgammal;
+ trunc;
+ truncf;
+ truncl;
+ y0;
+ y0f;
+ y1;
+ y1f;
+ yn;
+ ynf;
+ local:
+ *;
+};
+
diff --git a/linker/Android.mk b/linker/Android.mk
index 8be53a1..85ac0ca 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -9,11 +9,12 @@
dlfcn.cpp \
linker.cpp \
linker_allocator.cpp \
- linker_sdk_versions.cpp \
linker_block_allocator.cpp \
linker_libc_support.c \
+ linker_mapped_file_fragment.cpp \
linker_memory.cpp \
linker_phdr.cpp \
+ linker_sdk_versions.cpp \
linker_utils.cpp \
rt.cpp \
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index f1b26c9..d07ec86 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -89,9 +89,12 @@
return dlopen_ext(filename, flags, nullptr, caller_addr);
}
+extern android_namespace_t* g_anonymous_namespace;
+
void* dlsym(void* handle, const char* symbol) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ // TODO(dimitry): move (most of) the code below to linker.cpp
#if !defined(__LP64__)
if (handle == nullptr) {
__bionic_format_dlerror("dlsym library handle is null", nullptr);
@@ -108,9 +111,10 @@
const ElfW(Sym)* sym = nullptr;
void* caller_addr = __builtin_return_address(0);
soinfo* caller = find_containing_library(caller_addr);
+ android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
- sym = dlsym_linear_lookup(symbol, &found, caller, handle);
+ sym = dlsym_linear_lookup(ns, symbol, &found, caller, handle);
} else {
sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
}
@@ -177,6 +181,31 @@
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, bool is_isolated) {
+ ScopedPthreadMutexLocker locker(&g_dl_mutex);
+
+ android_namespace_t* result = create_namespace(name, ld_library_path,
+ default_library_path, is_isolated);
+
+ 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
#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
{ name_offset, \
@@ -203,11 +232,11 @@
// 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
// 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
"erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
- // 0000000000111111
- // 0123456789012345
- "get_sdk_version\0"
+ // 0000000000111111 111122222222223333333333 4444444444555555555566666
+ // 0123456789012345 678901234567890123456789 0123456789012345678901234
+ "get_sdk_version\0android_init_namespaces\0android_create_namespace\0"
#if defined(__arm__)
- // 216
+ // 265
"dl_unwind_find_exidx\0"
#endif
;
@@ -229,8 +258,10 @@
ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
+ ELFW(SYM_INITIALIZER)(216, &android_init_namespaces, 1),
+ ELFW(SYM_INITIALIZER)(240, &android_create_namespace, 1),
#if defined(__arm__)
- ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
+ ELFW(SYM_INITIALIZER)(265, &dl_unwind_find_exidx, 1),
#endif
};
@@ -247,18 +278,20 @@
// Note that adding any new symbols here requires stubbing them out in libdl.
static unsigned g_libdl_buckets[1] = { 1 };
#if defined(__arm__)
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 };
#else
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 };
#endif
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
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.
soinfo* get_libdl_info() {
if (__libdl_info == nullptr) {
- __libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL);
+ __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, "libdl.so", nullptr, 0, RTLD_GLOBAL);
__libdl_info->flags_ |= FLAG_LINKED;
__libdl_info->strtab_ = ANDROID_LIBDL_STRTAB;
__libdl_info->symtab_ = g_libdl_symtab;
@@ -271,7 +304,7 @@
__libdl_info->local_group_root_ = __libdl_info;
__libdl_info->soname_ = "libdl.so";
__libdl_info->target_sdk_version_ = __ANDROID_API__;
-#if defined(__arm__)
+#if defined(__work_around_b_24465209__)
strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
#endif
}
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 8003dbf..88386b0 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -25,12 +25,49 @@
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
*/
template<typename T, typename Allocator>
class LinkedList {
public:
+ typedef LinkedListIterator<T> iterator;
+ typedef T* value_type;
+
LinkedList() : head_(nullptr), tail_(nullptr) {}
~LinkedList() {
clear();
@@ -127,7 +164,13 @@
} else {
p->next = next;
}
+
+ if (tail_ == e) {
+ tail_ = p;
+ }
+
Allocator::free(e);
+
e = next;
} else {
p = e;
@@ -147,6 +190,24 @@
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 sz = 0;
for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) {
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 406cdee..028e490 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -49,7 +49,6 @@
#include "private/KernelArgumentBlock.h"
#include "private/ScopedPthreadMutexLocker.h"
#include "private/ScopeGuard.h"
-#include "private/UniquePtr.h"
#include "linker.h"
#include "linker_block_allocator.h"
@@ -60,7 +59,7 @@
#include "linker_reloc_iterators.h"
#include "linker_utils.h"
-#include "base/strings.h"
+#include "android-base/strings.h"
#include "ziparchive/zip_archive.h"
extern void __libc_init_globals(KernelArgumentBlock&);
@@ -70,20 +69,67 @@
#undef ELF_ST_TYPE
#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
+struct android_namespace_t {
+ public:
+ android_namespace_t() : name_(nullptr), is_isolated_(false) {}
+
+ const char* get_name() const { return name_; }
+ void set_name(const char* name) { name_ = name; }
+
+ bool is_isolated() const { return is_isolated_; }
+ void set_isolated(bool isolated) { is_isolated_ = isolated; }
+
+ const std::vector<std::string>& get_ld_library_paths() const {
+ return ld_library_paths_;
+ }
+ void set_ld_library_paths(std::vector<std::string>&& library_paths) {
+ ld_library_paths_ = library_paths;
+ }
+
+ const std::vector<std::string>& get_default_library_paths() const {
+ return default_library_paths_;
+ }
+ void set_default_library_paths(std::vector<std::string>&& library_paths) {
+ default_library_paths_ = library_paths;
+ }
+
+ soinfo::soinfo_list_t& soinfo_list() { return soinfo_list_; }
+
+ // For isolated namespaces - checks if the file is on the search path;
+ // always returns true for not isolated namespace.
+ bool is_accessible(const std::string& path);
+
+ private:
+ const char* name_;
+ bool is_isolated_;
+ std::vector<std::string> ld_library_paths_;
+ std::vector<std::string> default_library_paths_;
+ soinfo::soinfo_list_t soinfo_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(android_namespace_t);
+};
+
+android_namespace_t g_default_namespace;
+android_namespace_t* g_anonymous_namespace = &g_default_namespace;
+
static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
static LinkerTypeAllocator<soinfo> g_soinfo_allocator;
static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
+static LinkerTypeAllocator<android_namespace_t> g_namespace_allocator;
+
static soinfo* solist;
static soinfo* sonext;
static soinfo* somain; // main process, always the one after libdl_info
static const char* const kDefaultLdPaths[] = {
#if defined(__LP64__)
+ "/odm/lib64",
"/vendor/lib64",
"/system/lib64",
#else
+ "/odm/lib",
"/vendor/lib",
"/system/lib",
#endif
@@ -92,11 +138,15 @@
static const char* const kAsanDefaultLdPaths[] = {
#if defined(__LP64__)
+ "/data/odm/lib64",
+ "/odm/lib64",
"/data/vendor/lib64",
"/vendor/lib64",
"/data/lib64",
"/system/lib64",
#else
+ "/data/odm/lib",
+ "/odm/lib",
"/data/vendor/lib",
"/vendor/lib",
"/data/lib",
@@ -107,14 +157,15 @@
static const ElfW(Versym) kVersymNotNeeded = 0;
static const ElfW(Versym) kVersymGlobal = 1;
-static const char* const kZipFileSeparator = "!/";
static const char* const* g_default_ld_paths;
-static std::vector<std::string> g_ld_library_paths;
static std::vector<std::string> g_ld_preload_names;
static std::vector<soinfo*> g_ld_preloads;
+static bool g_public_namespace_initialized;
+static soinfo::soinfo_list_t g_public_namespace;
+
__LIBC_HIDDEN__ int g_ld_debug_verbosity;
__LIBC_HIDDEN__ abort_msg_t* g_abort_message = nullptr; // For debuggerd.
@@ -247,6 +298,26 @@
rtld_db_dlactivity();
}
+bool android_namespace_t::is_accessible(const std::string& file) {
+ if (!is_isolated_) {
+ return true;
+ }
+
+ for (const auto& dir : ld_library_paths_) {
+ if (file_is_in_dir(file, dir)) {
+ return true;
+ }
+ }
+
+ for (const auto& dir : default_library_paths_) {
+ if (file_is_in_dir(file, dir)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
LinkedListEntry<soinfo>* SoinfoListAllocator::alloc() {
return g_soinfo_links_allocator.alloc();
}
@@ -255,18 +326,22 @@
g_soinfo_links_allocator.free(entry);
}
-static soinfo* soinfo_alloc(const char* name, struct stat* file_stat,
- off64_t file_offset, uint32_t rtld_flags) {
+static soinfo* soinfo_alloc(android_namespace_t* ns, const char* name,
+ struct stat* file_stat, off64_t file_offset,
+ uint32_t rtld_flags) {
if (strlen(name) >= PATH_MAX) {
DL_ERR("library name \"%s\" too long", name);
return nullptr;
}
- soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat, file_offset, rtld_flags);
+ soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
+ file_offset, rtld_flags);
sonext->next = si;
sonext = si;
+ ns->soinfo_list().push_back(si);
+
TRACE("name %s: allocated soinfo @ %p", name, si);
return si;
}
@@ -307,30 +382,130 @@
sonext = prev;
}
+ // remove from the namespace
+ si->get_namespace()->soinfo_list().remove_if([&](soinfo* candidate) {
+ return si == candidate;
+ });
+
si->~soinfo();
g_soinfo_allocator.free(si);
}
-static void parse_path(const char* path, const char* delimiters,
+// For every path element this function checks of it exists, and is a directory,
+// and normalizes it:
+// 1. For regular path it converts it to realpath()
+// 2. For path in a zip file it uses realpath on the zipfile
+// normalizes entry name by calling normalize_path function.
+static void resolve_paths(std::vector<std::string>& paths,
+ std::vector<std::string>* resolved_paths) {
+ resolved_paths->clear();
+ for (const auto& path : paths) {
+ char resolved_path[PATH_MAX];
+ const char* original_path = path.c_str();
+ if (realpath(original_path, resolved_path) != nullptr) {
+ struct stat s;
+ if (stat(resolved_path, &s) == 0) {
+ if (S_ISDIR(s.st_mode)) {
+ resolved_paths->push_back(resolved_path);
+ } else {
+ DL_WARN("Warning: \"%s\" is not a directory (excluding from path)", resolved_path);
+ continue;
+ }
+ } else {
+ DL_WARN("Warning: cannot stat file \"%s\": %s", resolved_path, strerror(errno));
+ continue;
+ }
+ } else {
+ std::string zip_path;
+ std::string entry_path;
+
+ std::string normalized_path;
+
+ if (!normalize_path(original_path, &normalized_path)) {
+ DL_WARN("Warning: unable to normalize \"%s\"", original_path);
+ continue;
+ }
+
+ if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) {
+ if (realpath(zip_path.c_str(), resolved_path) == nullptr) {
+ DL_WARN("Warning: unable to resolve \"%s\": %s", zip_path.c_str(), strerror(errno));
+ continue;
+ }
+
+ ZipArchiveHandle handle = nullptr;
+ if (OpenArchive(resolved_path, &handle) != 0) {
+ DL_WARN("Warning: unable to open zip archive: %s", resolved_path);
+ continue;
+ }
+
+ // Check if zip-file has a dir with entry_path name
+ void* cookie = nullptr;
+ std::string prefix_str = entry_path + "/";
+ ZipString prefix(prefix_str.c_str());
+
+ ZipEntry out_data;
+ ZipString out_name;
+
+ int32_t error_code;
+
+ if ((error_code = StartIteration(handle, &cookie, &prefix, nullptr)) != 0) {
+ DL_WARN("Unable to iterate over zip-archive entries \"%s\";"
+ " error code: %d", zip_path.c_str(), error_code);
+ continue;
+ }
+
+ if (Next(cookie, &out_data, &out_name) != 0) {
+ DL_WARN("Unable to find entries starting with \"%s\" in \"%s\"",
+ prefix_str.c_str(), zip_path.c_str());
+ continue;
+ }
+
+ auto zip_guard = make_scope_guard([&]() {
+ if (cookie != nullptr) {
+ EndIteration(cookie);
+ }
+ CloseArchive(handle);
+ });
+
+ resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path);
+ }
+ }
+ }
+}
+
+static void split_path(const char* path, const char* delimiters,
std::vector<std::string>* paths) {
- paths->clear();
- if (path != nullptr) {
+ if (path != nullptr && path[0] != 0) {
*paths = android::base::Split(path, delimiters);
}
}
+static void parse_path(const char* path, const char* delimiters,
+ std::vector<std::string>* resolved_paths) {
+ std::vector<std::string> paths;
+ split_path(path, delimiters, &paths);
+ resolve_paths(paths, resolved_paths);
+}
+
static void parse_LD_LIBRARY_PATH(const char* path) {
- parse_path(path, ":", &g_ld_library_paths);
+ std::vector<std::string> ld_libary_paths;
+ parse_path(path, ":", &ld_libary_paths);
+ g_default_namespace.set_ld_library_paths(std::move(ld_libary_paths));
}
void soinfo::set_dt_runpath(const char* path) {
- if (!has_min_version(2)) return;
- parse_path(path, ":", &dt_runpath_);
+ if (!has_min_version(3)) {
+ return;
+ }
+
+ std::vector<std::string> runpaths;
+
+ split_path(path, ":", &runpaths);
std::string origin = dirname(get_realpath());
// FIXME: add $LIB and $PLATFORM.
std::pair<std::string, std::string> substs[] = {{"ORIGIN", origin}};
- for (std::string& s : dt_runpath_) {
+ for (auto&& s : runpaths) {
size_t pos = 0;
while (pos < s.size()) {
pos = s.find("$", pos);
@@ -353,11 +528,16 @@
++pos;
}
}
+
+ resolve_paths(runpaths, &dt_runpath_);
}
static void parse_LD_PRELOAD(const char* path) {
- // We have historically supported ':' as well as ' ' in LD_PRELOAD.
- parse_path(path, " :", &g_ld_preload_names);
+ g_ld_preload_names.clear();
+ if (path != nullptr) {
+ // We have historically supported ':' as well as ' ' in LD_PRELOAD.
+ g_ld_preload_names = android::base::Split(path, " :");
+ }
}
static bool realpath_fd(int fd, std::string* realpath) {
@@ -678,8 +858,9 @@
return true;
}
-soinfo::soinfo(const char* realpath, const struct stat* file_stat,
- off64_t file_offset, int rtld_flags) {
+soinfo::soinfo(android_namespace_t* ns, const char* realpath,
+ const struct stat* file_stat, off64_t file_offset,
+ int rtld_flags) {
memset(this, 0, sizeof(*this));
if (realpath != nullptr) {
@@ -696,6 +877,7 @@
}
this->rtld_flags_ = rtld_flags;
+ this->namespace_ = ns;
}
@@ -847,6 +1029,7 @@
void protect_data(int protection) {
g_soinfo_allocator.protect_all(protection);
g_soinfo_links_allocator.protect_all(protection);
+ g_namespace_allocator.protect_all(protection);
}
static size_t ref_count_;
@@ -889,17 +1072,17 @@
public:
struct deleter_t {
void operator()(LoadTask* t) {
+ t->~LoadTask();
TypeBasedAllocator<LoadTask>::free(t);
}
};
- typedef UniquePtr<LoadTask, deleter_t> unique_ptr;
-
static deleter_t deleter;
- static LoadTask* create(const char* name, soinfo* needed_by) {
+ static LoadTask* create(const char* name, soinfo* needed_by,
+ std::unordered_map<const soinfo*, ElfReader>* readers_map) {
LoadTask* ptr = TypeBasedAllocator<LoadTask>::alloc();
- return new (ptr) LoadTask(name, needed_by);
+ return new (ptr) LoadTask(name, needed_by, readers_map);
}
const char* get_name() const {
@@ -909,12 +1092,94 @@
soinfo* get_needed_by() const {
return needed_by_;
}
+
+ soinfo* get_soinfo() const {
+ return si_;
+ }
+
+ void set_soinfo(soinfo* si) {
+ si_ = si;
+ }
+
+ off64_t get_file_offset() const {
+ return file_offset_;
+ }
+
+ void set_file_offset(off64_t offset) {
+ file_offset_ = offset;
+ }
+
+ int get_fd() const {
+ return fd_;
+ }
+
+ void set_fd(int fd, bool assume_ownership) {
+ fd_ = fd;
+ close_fd_ = assume_ownership;
+ }
+
+ const android_dlextinfo* get_extinfo() const {
+ return extinfo_;
+ }
+
+ void set_extinfo(const android_dlextinfo* extinfo) {
+ extinfo_ = extinfo;
+ }
+
+ const ElfReader& get_elf_reader() const {
+ CHECK(si_ != nullptr);
+ return (*elf_readers_map_)[si_];
+ }
+
+ ElfReader& get_elf_reader() {
+ CHECK(si_ != nullptr);
+ return (*elf_readers_map_)[si_];
+ }
+
+ std::unordered_map<const soinfo*, ElfReader>* get_readers_map() {
+ return elf_readers_map_;
+ }
+
+ bool read(const char* realpath, off64_t file_size) {
+ ElfReader& elf_reader = get_elf_reader();
+ return elf_reader.Read(realpath, fd_, file_offset_, file_size);
+ }
+
+ bool load() {
+ ElfReader& elf_reader = get_elf_reader();
+ if (!elf_reader.Load(extinfo_)) {
+ return false;
+ }
+
+ si_->base = elf_reader.load_start();
+ si_->size = elf_reader.load_size();
+ si_->load_bias = elf_reader.load_bias();
+ si_->phnum = elf_reader.phdr_count();
+ si_->phdr = elf_reader.loaded_phdr();
+
+ return true;
+ }
+
private:
- LoadTask(const char* name, soinfo* needed_by)
- : name_(name), needed_by_(needed_by) {}
+ LoadTask(const char* name, soinfo* needed_by,
+ std::unordered_map<const soinfo*, ElfReader>* readers_map)
+ : name_(name), needed_by_(needed_by), si_(nullptr),
+ fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map) {}
+
+ ~LoadTask() {
+ if (fd_ != -1 && close_fd_) {
+ close(fd_);
+ }
+ }
const char* name_;
soinfo* needed_by_;
+ soinfo* si_;
+ const android_dlextinfo* extinfo_;
+ int fd_;
+ bool close_fd_;
+ off64_t file_offset_;
+ std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask);
};
@@ -926,7 +1191,7 @@
typedef linked_list_t<soinfo> SoinfoLinkedList;
typedef linked_list_t<const char> StringLinkedList;
-typedef linked_list_t<LoadTask> LoadTaskList;
+typedef std::vector<LoadTask*> LoadTaskList;
// This function walks down the tree of soinfo dependencies
@@ -1004,7 +1269,7 @@
// libraries and they are loaded in breath-first (correct) order we can just execute
// dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup.
if (si == somain) {
- return dlsym_linear_lookup(name, found, nullptr, RTLD_DEFAULT);
+ return dlsym_linear_lookup(&g_default_namespace, name, found, nullptr, RTLD_DEFAULT);
}
SymbolName symbol_name(name);
@@ -1016,24 +1281,29 @@
beginning of the global solist. Otherwise the search starts at the
specified soinfo (for RTLD_NEXT).
*/
-const ElfW(Sym)* dlsym_linear_lookup(const char* name,
+const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
+ const char* name,
soinfo** found,
soinfo* caller,
void* handle) {
SymbolName symbol_name(name);
- soinfo* start = solist;
+ soinfo::soinfo_list_t& soinfo_list = ns->soinfo_list();
+ soinfo::soinfo_list_t::iterator start = soinfo_list.begin();
if (handle == RTLD_NEXT) {
if (caller == nullptr) {
return nullptr;
} else {
- start = caller->next;
+ soinfo::soinfo_list_t::iterator it = soinfo_list.find(caller);
+ CHECK (it != soinfo_list.end());
+ start = ++it;
}
}
const ElfW(Sym)* s = nullptr;
- for (soinfo* si = start; si != nullptr; si = si->next) {
+ for (soinfo::soinfo_list_t::iterator it = start, end = soinfo_list.end(); it != end; ++it) {
+ soinfo* si = *it;
// Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...)
// if the library is opened by application with target api level <= 22
// See http://b/21565766
@@ -1161,7 +1431,7 @@
}
ZipArchiveCache::~ZipArchiveCache() {
- for (auto it : cache_) {
+ for (const auto& it : cache_) {
CloseArchive(it.second);
}
}
@@ -1245,35 +1515,13 @@
return true;
}
-static int open_library_on_default_path(const char* name, off64_t* file_offset, std::string* realpath) {
- for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
- char buf[512];
- if (!format_path(buf, sizeof(buf), g_default_ld_paths[i], name)) {
- continue;
- }
-
- int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
- if (fd != -1) {
- *file_offset = 0;
- if (!realpath_fd(fd, realpath)) {
- PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", buf);
- *realpath = buf;
- }
- return fd;
- }
- }
-
- return -1;
-}
-
static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
const char* name, off64_t* file_offset,
const std::vector<std::string>& paths,
std::string* realpath) {
- for (const auto& path_str : paths) {
+ for (const auto& path : paths) {
char buf[512];
- const char* const path = path_str.c_str();
- if (!format_path(buf, sizeof(buf), path, name)) {
+ if (!format_path(buf, sizeof(buf), path.c_str(), name)) {
continue;
}
@@ -1301,39 +1549,46 @@
return -1;
}
-static int open_library(ZipArchiveCache* zip_archive_cache,
+static int open_library(android_namespace_t* ns,
+ ZipArchiveCache* zip_archive_cache,
const char* name, soinfo *needed_by,
off64_t* file_offset, std::string* realpath) {
TRACE("[ opening %s ]", name);
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
+ int fd = -1;
+
if (strstr(name, kZipFileSeparator) != nullptr) {
- int fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
+ fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
+ }
+
+ if (fd == -1) {
+ fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC));
if (fd != -1) {
- return fd;
+ *file_offset = 0;
+ if (!realpath_fd(fd, realpath)) {
+ PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", name);
+ *realpath = name;
+ }
}
}
- int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC));
- if (fd != -1) {
- *file_offset = 0;
- if (!realpath_fd(fd, realpath)) {
- PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", name);
- *realpath = name;
- }
- }
return fd;
}
- // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
- int fd = open_library_on_paths(zip_archive_cache, name, file_offset, g_ld_library_paths, realpath);
- if (fd == -1 && needed_by) {
+ // Otherwise we try LD_LIBRARY_PATH first, and fall back to the default library path
+ int fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_ld_library_paths(), realpath);
+ if (fd == -1 && needed_by != nullptr) {
fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
+ // Check if the library is accessible
+ if (fd != -1 && !ns->is_accessible(*realpath)) {
+ fd = -1;
+ }
}
if (fd == -1) {
- fd = open_library_on_default_path(name, file_offset, realpath);
+ fd = open_library_on_paths(zip_archive_cache, name, file_offset, ns->get_default_library_paths(), realpath);
}
return fd;
@@ -1356,91 +1611,137 @@
template<typename F>
static void for_each_dt_needed(const soinfo* si, F action) {
- for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
+ for (const ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_NEEDED) {
action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
}
}
}
-static soinfo* load_library(int fd, off64_t file_offset,
- LoadTaskList& load_tasks,
- const char* name, int rtld_flags,
- const android_dlextinfo* extinfo,
- const std::string& realpath) {
+template<typename F>
+static void for_each_dt_needed(const ElfReader& elf_reader, F action) {
+ for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_NEEDED) {
+ action(fix_dt_needed(elf_reader.get_string(d->d_un.d_val), elf_reader.name()));
+ }
+ }
+}
+
+static bool load_library(android_namespace_t* ns,
+ LoadTask* task,
+ LoadTaskList* load_tasks,
+ int rtld_flags,
+ const std::string& realpath) {
+ off64_t file_offset = task->get_file_offset();
+ const char* name = task->get_name();
+ const android_dlextinfo* extinfo = task->get_extinfo();
+
if ((file_offset % PAGE_SIZE) != 0) {
DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
- return nullptr;
+ return false;
}
if (file_offset < 0) {
DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset);
- return nullptr;
+ return false;
}
struct stat file_stat;
- if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
+ if (TEMP_FAILURE_RETRY(fstat(task->get_fd(), &file_stat)) != 0) {
DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno));
- return nullptr;
+ return false;
}
if (file_offset >= file_stat.st_size) {
DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64,
name, file_offset, file_stat.st_size);
- return nullptr;
+ return false;
}
// Check for symlink and other situations where
// file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
- for (soinfo* si = solist; si != nullptr; si = si->next) {
- if (si->get_st_dev() != 0 &&
- si->get_st_ino() != 0 &&
- si->get_st_dev() == file_stat.st_dev &&
- si->get_st_ino() == file_stat.st_ino &&
- si->get_file_offset() == file_offset) {
- TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
- "will return existing soinfo", name, si->get_realpath());
- return si;
+ auto predicate = [&](soinfo* si) {
+ return si->get_st_dev() != 0 &&
+ si->get_st_ino() != 0 &&
+ si->get_st_dev() == file_stat.st_dev &&
+ si->get_st_ino() == file_stat.st_ino &&
+ si->get_file_offset() == file_offset;
+ };
+
+ soinfo* si = ns->soinfo_list().find_if(predicate);
+
+ // check public namespace
+ if (si == nullptr) {
+ si = g_public_namespace.find_if(predicate);
+ if (si != nullptr) {
+ ns->soinfo_list().push_back(si);
}
}
+
+ if (si != nullptr) {
+ TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
+ "will return existing soinfo", name, si->get_realpath());
+ task->set_soinfo(si);
+ return true;
+ }
}
if ((rtld_flags & RTLD_NOLOAD) != 0) {
DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name);
- return nullptr;
+ return false;
}
- // Read the ELF header and load the segments.
- ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size);
- if (!elf_reader.Load(extinfo)) {
- return nullptr;
+ if (!ns->is_accessible(realpath)) {
+ // do not load libraries if they are not accessible for the specified namespace.
+ DL_ERR("library \"%s\" is not accessible for the namespace \"%s\"",
+ name, ns->get_name());
+ return false;
}
- soinfo* si = soinfo_alloc(realpath.c_str(), &file_stat, file_offset, rtld_flags);
+ soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
if (si == nullptr) {
- return nullptr;
+ return false;
}
- si->base = elf_reader.load_start();
- si->size = elf_reader.load_size();
- si->load_bias = elf_reader.load_bias();
- si->phnum = elf_reader.phdr_count();
- si->phdr = elf_reader.loaded_phdr();
- if (!si->prelink_image()) {
+ task->set_soinfo(si);
+
+ // Read the ELF header and some of the segments.
+ if (!task->read(realpath.c_str(), file_stat.st_size)) {
soinfo_free(si);
- return nullptr;
+ task->set_soinfo(nullptr);
+ return false;
}
- for_each_dt_needed(si, [&] (const char* name) {
- load_tasks.push_back(LoadTask::create(name, si));
+ // find and set DT_RUNPATH and dt_soname
+ // Note that these field values are temporary and are
+ // going to be overwritten on soinfo::prelink_image
+ // with values from PT_LOAD segments.
+ const ElfReader& elf_reader = task->get_elf_reader();
+ for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_RUNPATH) {
+ si->set_dt_runpath(elf_reader.get_string(d->d_un.d_val));
+ }
+ if (d->d_tag == DT_SONAME) {
+ si->set_soname(elf_reader.get_string(d->d_un.d_val));
+ }
+ }
+
+ for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
+ load_tasks->push_back(LoadTask::create(name, si, task->get_readers_map()));
});
- return si;
+ return true;
+
}
-static soinfo* load_library(ZipArchiveCache* zip_archive_cache,
- LoadTaskList& load_tasks, const char* name,
- soinfo* needed_by, int rtld_flags,
- const android_dlextinfo* extinfo) {
+static bool load_library(android_namespace_t* ns,
+ LoadTask* task,
+ ZipArchiveCache* zip_archive_cache,
+ LoadTaskList* load_tasks,
+ int rtld_flags) {
+ const char* name = task->get_name();
+ soinfo* needed_by = task->get_needed_by();
+ const android_dlextinfo* extinfo = task->get_extinfo();
+
off64_t file_offset;
std::string realpath;
if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
@@ -1454,25 +1755,31 @@
"Will use given name.", name);
realpath = name;
}
- return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo, realpath);
+
+ task->set_fd(extinfo->library_fd, false);
+ task->set_file_offset(file_offset);
+ return load_library(ns, task, load_tasks, rtld_flags, realpath);
}
// Open the file.
- int fd = open_library(zip_archive_cache, name, needed_by, &file_offset, &realpath);
+ int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath);
if (fd == -1) {
DL_ERR("library \"%s\" not found", name);
- return nullptr;
+ return false;
}
- soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo, realpath);
- close(fd);
- return result;
+
+ task->set_fd(fd, true);
+ task->set_file_offset(file_offset);
+
+ return load_library(ns, task, load_tasks, rtld_flags, realpath);
}
// Returns true if library was found and false in 2 cases
-// 1. The library was found but loaded under different target_sdk_version
-// (*candidate != nullptr)
+// 1. (for default namespace only) The library was found but loaded under different
+// target_sdk_version (*candidate != nullptr)
// 2. The library was not found by soname (*candidate is nullptr)
-static bool find_loaded_library_by_soname(const char* name, soinfo** candidate) {
+static bool find_loaded_library_by_soname(android_namespace_t* ns,
+ const char* name, soinfo** candidate) {
*candidate = nullptr;
// Ignore filename with path.
@@ -1482,7 +1789,7 @@
uint32_t target_sdk_version = get_application_target_sdk_version();
- for (soinfo* si = solist; si != nullptr; si = si->next) {
+ return !ns->soinfo_list().visit([&](soinfo* si) {
const char* soname = si->get_soname();
if (soname != nullptr && (strcmp(name, soname) == 0)) {
// If the library was opened under different target sdk version
@@ -1492,44 +1799,64 @@
// in any case.
bool is_libdl = si == solist;
if (is_libdl || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0 ||
- !si->is_linked() || si->get_target_sdk_version() == target_sdk_version) {
+ !si->is_linked() || si->get_target_sdk_version() == target_sdk_version ||
+ ns != &g_default_namespace) {
*candidate = si;
- return true;
+ return false;
} else if (*candidate == nullptr) {
- // for the different sdk version - remember the first library.
+ // for the different sdk version in the default namespace
+ // remember the first library.
*candidate = si;
}
}
- }
- return false;
+ return true;
+ });
}
-static soinfo* find_library_internal(ZipArchiveCache* zip_archive_cache,
- LoadTaskList& load_tasks, const char* name,
- soinfo* needed_by, int rtld_flags,
- const android_dlextinfo* extinfo) {
+static bool find_library_internal(android_namespace_t* ns,
+ LoadTask* task,
+ ZipArchiveCache* zip_archive_cache,
+ LoadTaskList* load_tasks,
+ int rtld_flags) {
soinfo* candidate;
- if (find_loaded_library_by_soname(name, &candidate)) {
- return candidate;
+ if (find_loaded_library_by_soname(ns, task->get_name(), &candidate)) {
+ task->set_soinfo(candidate);
+ return true;
+ }
+
+ if (ns != &g_default_namespace) {
+ // check public namespace
+ candidate = g_public_namespace.find_if([&](soinfo* si) {
+ return strcmp(task->get_name(), si->get_soname()) == 0;
+ });
+
+ if (candidate != nullptr) {
+ ns->soinfo_list().push_back(candidate);
+ task->set_soinfo(candidate);
+ return true;
+ }
}
// Library might still be loaded, the accurate detection
// of this fact is done by load_library.
TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
- name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+ task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
- soinfo* si = load_library(zip_archive_cache, load_tasks, name, needed_by, rtld_flags, extinfo);
-
- // In case we were unable to load the library but there
- // is a candidate loaded under the same soname but different
- // sdk level - return it anyways.
- if (si == nullptr && candidate != nullptr) {
- si = candidate;
+ if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) {
+ return true;
+ } else {
+ // In case we were unable to load the library but there
+ // is a candidate loaded under the same soname but different
+ // sdk level - return it anyways.
+ if (candidate != nullptr) {
+ task->set_soinfo(candidate);
+ return true;
+ }
}
- return si;
+ return false;
}
static void soinfo_unload(soinfo* si);
@@ -1541,22 +1868,31 @@
//
// This group consists of the main executable, LD_PRELOADs
// and libraries with the DF_1_GLOBAL flag set.
-static soinfo::soinfo_list_t make_global_group() {
+static soinfo::soinfo_list_t make_global_group(android_namespace_t* ns) {
soinfo::soinfo_list_t global_group;
- for (soinfo* si = somain; si != nullptr; si = si->next) {
+ ns->soinfo_list().for_each([&](soinfo* si) {
if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
global_group.push_back(si);
}
- }
+ });
return global_group;
}
+static void shuffle(std::vector<LoadTask*>* v) {
+ for (size_t i = 0, size = v->size(); i < size; ++i) {
+ size_t n = size - i;
+ size_t r = arc4random_uniform(n);
+ std::swap((*v)[n-1], (*v)[r]);
+ }
+}
+
// add_as_children - add first-level loaded libraries (i.e. library_names[], but
// not their transitive dependencies) as children of the start_with library.
// This is false when find_libraries is called for dlopen(), when newly loaded
// libraries must form a disjoint tree.
-static bool find_libraries(soinfo* start_with,
+static bool find_libraries(android_namespace_t* ns,
+ soinfo* start_with,
const char* const library_names[],
size_t library_names_count, soinfo* soinfos[],
std::vector<soinfo*>* ld_preloads,
@@ -1565,13 +1901,15 @@
bool add_as_children) {
// Step 0: prepare.
LoadTaskList load_tasks;
+ std::unordered_map<const soinfo*, ElfReader> readers_map;
+
for (size_t i = 0; i < library_names_count; ++i) {
const char* name = library_names[i];
- load_tasks.push_back(LoadTask::create(name, start_with));
+ load_tasks.push_back(LoadTask::create(name, start_with, &readers_map));
}
// Construct global_group.
- soinfo::soinfo_list_t global_group = make_global_group();
+ soinfo::soinfo_list_t global_group = make_global_group(ns);
// If soinfos array is null allocate one on stack.
// The array is needed in case of failure; for example
@@ -1589,12 +1927,14 @@
// list of libraries to link - see step 2.
size_t soinfos_count = 0;
+ auto scope_guard = make_scope_guard([&]() {
+ for (LoadTask* t : load_tasks) {
+ LoadTask::deleter(t);
+ }
+ });
+
auto failure_guard = make_scope_guard([&]() {
// Housekeeping
- load_tasks.for_each([] (LoadTask* t) {
- LoadTask::deleter(t);
- });
-
for (size_t i = 0; i<soinfos_count; ++i) {
soinfo_unload(soinfos[i]);
}
@@ -1602,20 +1942,21 @@
ZipArchiveCache zip_archive_cache;
- // Step 1: load and pre-link all DT_NEEDED libraries in breadth first order.
- for (LoadTask::unique_ptr task(load_tasks.pop_front());
- task.get() != nullptr; task.reset(load_tasks.pop_front())) {
+ // Step 1: expand the list of load_tasks to include
+ // all DT_NEEDED libraries (do not load them just yet)
+ for (size_t i = 0; i<load_tasks.size(); ++i) {
+ LoadTask* task = load_tasks[i];
soinfo* needed_by = task->get_needed_by();
+
bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
+ task->set_extinfo(is_dt_needed ? nullptr : extinfo);
- soinfo* si = find_library_internal(&zip_archive_cache, load_tasks,
- task->get_name(), needed_by, rtld_flags,
- is_dt_needed ? nullptr : extinfo);
-
- if (si == nullptr) {
+ if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) {
return false;
}
+ soinfo* si = task->get_soinfo();
+
if (is_dt_needed) {
needed_by->add_child(si);
}
@@ -1627,11 +1968,6 @@
// When ld_preloads is not null, the first
// ld_preloads_count libs are in fact ld_preloads.
if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
- // Add LD_PRELOADed libraries to the global group for future runs.
- // There is no need to explicitly add them to the global group
- // for this run because they are going to appear in the local
- // group in the correct order.
- si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
ld_preloads->push_back(si);
}
@@ -1640,7 +1976,47 @@
}
}
- // Step 2: link libraries.
+ // Step 2: Load libraries in random order (see b/24047022)
+ LoadTaskList load_list;
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ auto pred = [&](const LoadTask* t) {
+ return t->get_soinfo() == si;
+ };
+
+ if (!si->is_linked() &&
+ std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) {
+ load_list.push_back(task);
+ }
+ }
+ shuffle(&load_list);
+
+ for (auto&& task : load_list) {
+ if (!task->load()) {
+ return false;
+ }
+ }
+
+ // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
+ for (auto&& task : load_tasks) {
+ soinfo* si = task->get_soinfo();
+ if (!si->is_linked() && !si->prelink_image()) {
+ return false;
+ }
+ }
+
+ // Step 4: Add LD_PRELOADed libraries to the global group for
+ // future runs. There is no need to explicitly add them to
+ // the global group for this run because they are going to
+ // appear in the local group in the correct order.
+ if (ld_preloads != nullptr) {
+ for (auto&& si : *ld_preloads) {
+ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
+ }
+ }
+
+
+ // Step 5: link libraries.
soinfo::soinfo_list_t local_group;
walk_dependencies_tree(
(start_with != nullptr && add_as_children) ? &start_with : soinfos,
@@ -1676,14 +2052,15 @@
return linked;
}
-static soinfo* find_library(const char* name, int rtld_flags,
+static soinfo* find_library(android_namespace_t* ns,
+ const char* name, int rtld_flags,
const android_dlextinfo* extinfo,
soinfo* needed_by) {
soinfo* si;
if (name == nullptr) {
si = somain;
- } else if (!find_libraries(needed_by, &name, 1, &si, nullptr, 0, rtld_flags,
+ } else if (!find_libraries(ns, needed_by, &name, 1, &si, nullptr, 0, rtld_flags,
extinfo, /* add_as_children */ false)) {
return nullptr;
}
@@ -1746,7 +2123,9 @@
TRACE("deprecated (old format of soinfo): %s needs to unload %s",
si->get_realpath(), library_name);
- soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr, nullptr);
+ soinfo* needed = find_library(si->get_namespace(),
+ library_name, RTLD_NOLOAD, nullptr, nullptr);
+
if (needed != nullptr) {
// Not found: for example if symlink was deleted between dlopen and dlclose
// Since we cannot really handle errors at this point - print and continue.
@@ -1818,24 +2197,44 @@
DL_ERR("invalid flags to dlopen: %x", flags);
return nullptr;
}
+
+ android_namespace_t* ns = caller != nullptr ? caller->get_namespace() : g_anonymous_namespace;
+
if (extinfo != nullptr) {
if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
return nullptr;
}
+
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
(extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
"ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
return nullptr;
}
+
+ if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&
+ (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {
+ DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "
+ "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");
+ return nullptr;
+ }
+
+ if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
+ if (extinfo->library_namespace == nullptr) {
+ DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
+ return nullptr;
+ }
+ ns = extinfo->library_namespace;
+ }
}
ProtectedDataGuard guard;
- soinfo* si = find_library(name, flags, extinfo, caller);
+ soinfo* si = find_library(ns, name, flags, extinfo, caller);
if (si != nullptr) {
si->call_constructors();
}
+
return si;
}
@@ -1844,6 +2243,80 @@
soinfo_unload(si);
}
+bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path) {
+ CHECK(public_ns_sonames != nullptr);
+ if (g_public_namespace_initialized) {
+ DL_ERR("public namespace has already been initialized.");
+ return false;
+ }
+
+ std::vector<std::string> sonames = android::base::Split(public_ns_sonames, ":");
+
+ ProtectedDataGuard guard;
+
+ auto failure_guard = make_scope_guard([&]() {
+ g_public_namespace.clear();
+ });
+
+ for (const auto& soname : sonames) {
+ soinfo* candidate = nullptr;
+
+ find_loaded_library_by_soname(&g_default_namespace, soname.c_str(), &candidate);
+
+ if (candidate == nullptr) {
+ DL_ERR("error initializing public namespace: \"%s\" was not found"
+ " in the default namespace", soname.c_str());
+ return false;
+ }
+
+ candidate->set_nodelete();
+ g_public_namespace.push_back(candidate);
+ }
+
+ g_public_namespace_initialized = true;
+
+ // create anonymous namespace
+ android_namespace_t* anon_ns =
+ create_namespace("(anonymous)", nullptr, anon_ns_library_path, false);
+
+ if (anon_ns == nullptr) {
+ g_public_namespace_initialized = false;
+ return false;
+ }
+ g_anonymous_namespace = anon_ns;
+ failure_guard.disable();
+ return true;
+}
+
+android_namespace_t* create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ bool is_isolated) {
+ if (!g_public_namespace_initialized) {
+ DL_ERR("cannot create namespace: public namespace is not initialized.");
+ return nullptr;
+ }
+
+ ProtectedDataGuard guard;
+ std::vector<std::string> ld_library_paths;
+ std::vector<std::string> default_library_paths;
+
+ parse_path(ld_library_path, ":", &ld_library_paths);
+ parse_path(default_library_path, ":", &default_library_paths);
+
+ android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
+ ns->set_name(name);
+ ns->set_isolated(is_isolated);
+ ns->set_ld_library_paths(std::move(ld_library_paths));
+ ns->set_default_library_paths(std::move(default_library_paths));
+
+ // TODO(dimtiry): Should this be global group of caller's namespace?
+ auto global_group = make_global_group(&g_default_namespace);
+ std::copy(global_group.begin(), global_group.end(), std::back_inserter(ns->soinfo_list()));
+
+ return ns;
+}
+
static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
@@ -2165,24 +2638,23 @@
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n",
- reloc, (sym_addr + addend), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
+ reloc, sym_addr + addend, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
break;
case R_AARCH64_ABS32:
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n",
- reloc, (sym_addr + addend), sym_name);
+ reloc, sym_addr + addend, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
- if ((min_value <= (reloc_value + (sym_addr + addend))) &&
- ((reloc_value + (sym_addr + addend)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
+ if ((min_value <= (sym_addr + addend)) &&
+ ((sym_addr + addend) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
} else {
DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
- (reloc_value + (sym_addr + addend)), min_value, max_value);
+ sym_addr + addend, min_value, max_value);
return false;
}
}
@@ -2191,17 +2663,16 @@
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n",
- reloc, (sym_addr + addend), sym_name);
+ reloc, sym_addr + addend, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
- if ((min_value <= (reloc_value + (sym_addr + addend))) &&
- ((reloc_value + (sym_addr + addend)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend);
+ if ((min_value <= (sym_addr + addend)) &&
+ ((sym_addr + addend) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = (sym_addr + addend);
} else {
DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
- reloc_value + (sym_addr + addend), min_value, max_value);
+ sym_addr + addend, min_value, max_value);
return false;
}
}
@@ -2210,24 +2681,23 @@
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n",
- reloc, (sym_addr + addend), rel->r_offset, sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr + addend) - rel->r_offset;
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
break;
case R_AARCH64_PREL32:
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n",
- reloc, (sym_addr + addend), rel->r_offset, sym_name);
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT32_MIN);
const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT32_MAX);
- if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
- ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
+ if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
+ ((sym_addr + addend - rel->r_offset) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
} else {
DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
- reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
+ sym_addr + addend - rel->r_offset, min_value, max_value);
return false;
}
}
@@ -2236,17 +2706,16 @@
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n",
- reloc, (sym_addr + addend), rel->r_offset, sym_name);
+ reloc, sym_addr + addend, rel->r_offset, sym_name);
{
- const ElfW(Addr) reloc_value = *reinterpret_cast<ElfW(Addr)*>(reloc);
const ElfW(Addr) min_value = static_cast<ElfW(Addr)>(INT16_MIN);
const ElfW(Addr) max_value = static_cast<ElfW(Addr)>(UINT16_MAX);
- if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) &&
- ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) {
- *reinterpret_cast<ElfW(Addr)*>(reloc) += ((sym_addr + addend) - rel->r_offset);
+ if ((min_value <= (sym_addr + addend - rel->r_offset)) &&
+ ((sym_addr + addend - rel->r_offset) <= max_value)) {
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - rel->r_offset;
} else {
DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx",
- reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value);
+ sym_addr + addend - rel->r_offset, min_value, max_value);
return false;
}
}
@@ -2278,14 +2747,14 @@
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
static_cast<size_t>(sym_addr), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
+ *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend;
break;
case R_X86_64_64:
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast<size_t>(reloc),
static_cast<size_t>(sym_addr), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
+ *reinterpret_cast<Elf64_Addr*>(reloc) = sym_addr + addend;
break;
case R_X86_64_PC32:
count_relocation(kRelocRelative);
@@ -2293,7 +2762,7 @@
TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s",
static_cast<size_t>(reloc), static_cast<size_t>(sym_addr - reloc),
static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name);
- *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend - reloc;
+ *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend - reloc;
break;
#elif defined(__arm__)
case R_ARM_ABS32:
@@ -2516,6 +2985,10 @@
}
}
+void soinfo::set_nodelete() {
+ rtld_flags_ |= RTLD_NODELETE;
+}
+
const char* soinfo::get_realpath() const {
#if defined(__work_around_b_24465209__)
if (has_min_version(2)) {
@@ -2528,6 +3001,17 @@
#endif
}
+void soinfo::set_soname(const char* soname) {
+#if defined(__work_around_b_24465209__)
+ if (has_min_version(2)) {
+ soname_ = soname;
+ }
+ strlcpy(old_name_, soname_, sizeof(old_name_));
+#else
+ soname_ = soname;
+#endif
+}
+
const char* soinfo::get_soname() const {
#if defined(__work_around_b_24465209__)
if (has_min_version(2)) {
@@ -2571,13 +3055,21 @@
static std::vector<std::string> g_empty_runpath;
const std::vector<std::string>& soinfo::get_dt_runpath() const {
- if (has_min_version(2)) {
+ if (has_min_version(3)) {
return dt_runpath_;
}
return g_empty_runpath;
}
+android_namespace_t* soinfo::get_namespace() {
+ if (has_min_version(3)) {
+ return namespace_;
+ }
+
+ return &g_default_namespace;
+}
+
ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
return call_ifunc_resolver(s->st_value + load_bias);
@@ -3059,13 +3551,9 @@
for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
switch (d->d_tag) {
case DT_SONAME:
- soname_ = get_string(d->d_un.d_val);
-#if defined(__work_around_b_24465209__)
- strlcpy(old_name_, soname_, sizeof(old_name_));
-#endif
+ set_soname(get_string(d->d_un.d_val));
break;
case DT_RUNPATH:
- // FIXME: $LIB, $PLATFORM unsupported.
set_dt_runpath(get_string(d->d_un.d_val));
break;
}
@@ -3243,7 +3731,7 @@
return;
}
- soinfo* si = soinfo_alloc("[vdso]", nullptr, 0, 0);
+ soinfo* si = soinfo_alloc(&g_default_namespace, "[vdso]", nullptr, 0, 0);
si->phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(ehdr_vdso) + ehdr_vdso->e_phoff);
si->phnum = ehdr_vdso->e_phnum;
@@ -3279,7 +3767,8 @@
* be on the soinfo list.
*/
static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
- linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(LINKER_PATH, nullptr, 0, 0);
+ linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(nullptr, LINKER_PATH,
+ nullptr, 0, 0);
linker_soinfo_for_gdb->load_bias = linker_base;
@@ -3296,14 +3785,25 @@
insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
}
-static void init_default_ld_library_path() {
+static void init_default_namespace() {
+ g_default_namespace.set_name("(default)");
+ g_default_namespace.set_isolated(false);
+
const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
somain->load_bias);
const char* bname = basename(interp);
- if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0))
+ if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0)) {
g_default_ld_paths = kAsanDefaultLdPaths;
- else
+ } else {
g_default_ld_paths = kDefaultLdPaths;
+ }
+
+ std::vector<std::string> ld_default_paths;
+ for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
+ ld_default_paths.push_back(g_default_ld_paths[i]);
+ }
+
+ g_default_namespace.set_default_library_paths(std::move(ld_default_paths));
};
extern "C" int __system_properties_init(void);
@@ -3344,7 +3844,7 @@
INFO("[ android linker & debugger ]");
- soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL);
+ soinfo* si = soinfo_alloc(&g_default_namespace, args.argv[0], nullptr, 0, RTLD_GLOBAL);
if (si == nullptr) {
exit(EXIT_FAILURE);
}
@@ -3396,11 +3896,10 @@
somain = si;
- init_default_ld_library_path();
+ init_default_namespace();
if (!si->prelink_image()) {
- __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
- exit(EXIT_FAILURE);
+ __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
}
// add somain to global group
@@ -3428,15 +3927,13 @@
needed_library_name_list.copy_to_array(needed_library_names, needed_libraries_count);
if (needed_libraries_count > 0 &&
- !find_libraries(si, needed_library_names, needed_libraries_count, nullptr,
- &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr,
+ !find_libraries(&g_default_namespace, si, needed_library_names, needed_libraries_count,
+ nullptr, &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr,
/* add_as_children */ true)) {
- __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
- exit(EXIT_FAILURE);
+ __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
} else if (needed_libraries_count == 0) {
if (!si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr)) {
- __libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
- exit(EXIT_FAILURE);
+ __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
}
si->increment_ref_count();
}
@@ -3545,7 +4042,7 @@
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
- soinfo linker_so(nullptr, nullptr, 0, 0);
+ soinfo linker_so(nullptr, nullptr, nullptr, 0, 0);
// If the linker is not acting as PT_INTERP entry_point is equal to
// _start. Which means that the linker is running as an executable and
@@ -3554,7 +4051,7 @@
// This happens when user tries to run 'adb shell /system/bin/linker'
// see also https://code.google.com/p/android/issues/detail?id=63174
if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
- __libc_fatal("This is %s, the helper program for shared library executables.\n", args.argv[0]);
+ __libc_fatal("This is %s, the helper program for shared library executables.", args.argv[0]);
}
linker_so.base = linker_addr;
@@ -3572,15 +4069,7 @@
// are not yet initialized, and therefore we cannot use linked_list.push_*
// functions at this point.
if (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) {
- // It would be nice to print an error message, but if the linker
- // can't link itself, there's no guarantee that we'll be able to
- // call write() (because it involves a GOT reference). We may as
- // well try though...
- const char* msg = "CANNOT LINK EXECUTABLE: ";
- write(2, msg, strlen(msg));
- write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf));
- write(2, "\n", 1);
- _exit(EXIT_FAILURE);
+ __libc_fatal("CANNOT LINK EXECUTABLE: %s", linker_get_error_buffer());
}
__libc_init_main_thread(args);
@@ -3596,6 +4085,7 @@
// before get_libdl_info().
solist = get_libdl_info();
sonext = get_libdl_info();
+ g_default_namespace.soinfo_list().push_back(get_libdl_info());
// We have successfully fixed our own relocations. It's safe to run
// the main part of the linker now.
diff --git a/linker/linker.h b/linker/linker.h
index 39d3ff1..b391fc3 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -86,7 +86,7 @@
#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)
-#define SOINFO_VERSION 2
+#define SOINFO_VERSION 3
#if defined(__work_around_b_24465209__)
#define SOINFO_NAME_LEN 128
@@ -261,7 +261,8 @@
bool has_DT_SYMBOLIC;
public:
- soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
+ soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
+ off64_t file_offset, int rtld_flags);
void call_constructors();
void call_destructors();
@@ -311,12 +312,14 @@
void set_linked();
void set_linker_flag();
void set_main_executable();
+ void set_nodelete();
void increment_ref_count();
size_t decrement_ref_count();
soinfo* get_local_group_root() const;
+ void set_soname(const char* soname);
const char* get_soname() const;
const char* get_realpath() const;
const ElfW(Versym)* get_versym(size_t n) const;
@@ -329,7 +332,9 @@
uint32_t get_target_sdk_version() const;
+ void set_dt_runpath(const char *);
const std::vector<std::string>& get_dt_runpath() const;
+ android_namespace_t* get_namespace();
private:
bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
@@ -392,8 +397,9 @@
uint32_t target_sdk_version_;
- void set_dt_runpath(const char *);
+ // version >= 3
std::vector<std::string> dt_runpath_;
+ android_namespace_t* namespace_;
friend soinfo* get_libdl_info();
};
@@ -421,7 +427,9 @@
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
-const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
+const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns, const char* name, soinfo** found,
+ soinfo* caller, void* handle);
+
soinfo* find_containing_library(const void* addr);
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
@@ -436,4 +444,8 @@
void set_application_target_sdk_version(uint32_t target);
uint32_t get_application_target_sdk_version();
+bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path);
+android_namespace_t* create_namespace(const char* name, const char* ld_library_path,
+ const char* default_library_path, bool is_isolated);
+
#endif
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 51f8d4c..17c6986 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -58,6 +58,13 @@
__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
+#define CHECK(predicate) { \
+ if (!(predicate)) { \
+ __libc_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ }
+
#if LINKER_DEBUG_TO_LOG
#define _PRINTVF(v, x...) \
do { \
diff --git a/linker/linker_libc_support.c b/linker/linker_libc_support.c
index 4c49384..77a0252 100644
--- a/linker/linker_libc_support.c
+++ b/linker/linker_libc_support.c
@@ -15,7 +15,9 @@
*/
#include "../libc/arch-common/bionic/__dso_handle.h"
+#include "../libc/arch-common/bionic/pthread_atfork.h"
int atexit(void (*function)(void) __attribute__((__unused__))) {
return -1;
}
+
diff --git a/linker/linker_mapped_file_fragment.cpp b/linker/linker_mapped_file_fragment.cpp
new file mode 100644
index 0000000..27c1c69
--- /dev/null
+++ b/linker/linker_mapped_file_fragment.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "linker_mapped_file_fragment.h"
+#include "linker_debug.h"
+#include "linker_utils.h"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+MappedFileFragment::MappedFileFragment() : map_start_(nullptr), map_size_(0),
+ data_(nullptr), size_ (0)
+{ }
+
+MappedFileFragment::~MappedFileFragment() {
+ if (map_start_ != nullptr) {
+ munmap(map_start_, map_size_);
+ }
+}
+
+bool MappedFileFragment::Map(int fd, off64_t base_offset, size_t elf_offset, size_t size) {
+ off64_t offset;
+ CHECK(safe_add(&offset, base_offset, elf_offset));
+
+ off64_t page_min = page_start(offset);
+ off64_t end_offset;
+
+ CHECK(safe_add(&end_offset, offset, size));
+ CHECK(safe_add(&end_offset, end_offset, page_offset(offset)));
+
+ size_t map_size = static_cast<size_t>(end_offset - page_min);
+ CHECK(map_size >= size);
+
+ uint8_t* map_start = static_cast<uint8_t*>(
+ mmap64(nullptr, map_size, PROT_READ, MAP_PRIVATE, fd, page_min));
+
+ if (map_start == MAP_FAILED) {
+ return false;
+ }
+
+ map_start_ = map_start;
+ map_size_ = map_size;
+
+ data_ = map_start + page_offset(offset);
+ size_ = size;
+
+ return true;
+}
diff --git a/linker/linker_mapped_file_fragment.h b/linker/linker_mapped_file_fragment.h
new file mode 100644
index 0000000..91bd077
--- /dev/null
+++ b/linker/linker_mapped_file_fragment.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LINKER_MAPPED_FILE_FRAGMENT_H
+#define LINKER_MAPPED_FILE_FRAGMENT_H
+
+#include <unistd.h>
+
+#include "private/bionic_macros.h"
+
+class MappedFileFragment {
+ public:
+ MappedFileFragment();
+ ~MappedFileFragment();
+
+ bool Map(int fd, off64_t base_offset, size_t elf_offset, size_t size);
+
+ void* data() const { return data_; }
+ size_t size() const { return size_; }
+ private:
+ void* map_start_;
+ size_t map_size_;
+ void* data_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(MappedFileFragment);
+};
+
+#endif /* LINKER_MAPPED_FILE_FRAGMENT_H */
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 30bc6fa..4c4ce17 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -37,6 +37,7 @@
#include "linker.h"
#include "linker_debug.h"
+#include "linker_utils.h"
static int GetTargetElfMachine() {
#if defined(__arm__)
@@ -133,37 +134,59 @@
MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
-ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
- : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size),
- phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
- load_start_(nullptr), load_size_(0), load_bias_(0),
- loaded_phdr_(nullptr) {
+ElfReader::ElfReader()
+ : did_read_(false), did_load_(false), fd_(-1), file_offset_(0), file_size_(0), phdr_num_(0),
+ phdr_table_(nullptr), shdr_table_(nullptr), shdr_num_(0), dynamic_(nullptr), strtab_(nullptr),
+ strtab_size_(0), load_start_(nullptr), load_size_(0), load_bias_(0), loaded_phdr_(nullptr) {
}
-ElfReader::~ElfReader() {
- if (phdr_mmap_ != nullptr) {
- munmap(phdr_mmap_, phdr_size_);
+bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file_size) {
+ CHECK(!did_read_);
+ CHECK(!did_load_);
+ name_ = name;
+ fd_ = fd;
+ file_offset_ = file_offset;
+ file_size_ = file_size;
+
+ if (ReadElfHeader() &&
+ VerifyElfHeader() &&
+ ReadProgramHeaders() &&
+ ReadSectionHeaders() &&
+ ReadDynamicSection()) {
+ did_read_ = true;
}
+
+ return did_read_;
}
bool ElfReader::Load(const android_dlextinfo* extinfo) {
- return ReadElfHeader() &&
- VerifyElfHeader() &&
- ReadProgramHeader() &&
- ReserveAddressSpace(extinfo) &&
- LoadSegments() &&
- FindPhdr();
+ CHECK(did_read_);
+ CHECK(!did_load_);
+ if (ReserveAddressSpace(extinfo) &&
+ LoadSegments() &&
+ FindPhdr()) {
+ did_load_ = true;
+ }
+
+ return did_load_;
+}
+
+const char* ElfReader::get_string(ElfW(Word) index) const {
+ CHECK(strtab_ != nullptr);
+ CHECK(index < strtab_size_);
+
+ return strtab_ + index;
}
bool ElfReader::ReadElfHeader() {
ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
if (rc < 0) {
- DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
+ DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
return false;
}
if (rc != sizeof(header_)) {
- DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
+ DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
static_cast<size_t>(rc));
return false;
}
@@ -172,7 +195,7 @@
bool ElfReader::VerifyElfHeader() {
if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
- DL_ERR("\"%s\" has bad ELF magic", name_);
+ DL_ERR("\"%s\" has bad ELF magic", name_.c_str());
return false;
}
@@ -182,73 +205,161 @@
#if defined(__LP64__)
if (elf_class != ELFCLASS64) {
if (elf_class == ELFCLASS32) {
- DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
+ DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_.c_str());
} else {
- DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
+ DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
}
return false;
}
#else
if (elf_class != ELFCLASS32) {
if (elf_class == ELFCLASS64) {
- DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_);
+ DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_.c_str());
} else {
- DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
+ DL_ERR("\"%s\" has unknown ELF class: %d", name_.c_str(), elf_class);
}
return false;
}
#endif
if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
- DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]);
+ DL_ERR("\"%s\" not little-endian: %d", name_.c_str(), header_.e_ident[EI_DATA]);
return false;
}
if (header_.e_type != ET_DYN) {
- DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
+ DL_ERR("\"%s\" has unexpected e_type: %d", name_.c_str(), header_.e_type);
return false;
}
if (header_.e_version != EV_CURRENT) {
- DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
+ DL_ERR("\"%s\" has unexpected e_version: %d", name_.c_str(), header_.e_version);
return false;
}
if (header_.e_machine != GetTargetElfMachine()) {
- DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine);
+ DL_ERR("\"%s\" has unexpected e_machine: %d", name_.c_str(), header_.e_machine);
return false;
}
return true;
}
+bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size) {
+ off64_t range_start;
+ off64_t range_end;
+
+ return safe_add(&range_start, file_offset_, offset) &&
+ safe_add(&range_end, range_start, size) &&
+ range_start < file_size_ &&
+ range_end <= file_size_;
+}
+
// Loads the program header table from an ELF file into a read-only private
// anonymous mmap-ed block.
-bool ElfReader::ReadProgramHeader() {
+bool ElfReader::ReadProgramHeaders() {
phdr_num_ = header_.e_phnum;
// Like the kernel, we only accept program header tables that
// are smaller than 64KiB.
if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
- DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_);
+ DL_ERR("\"%s\" has invalid e_phnum: %zd", name_.c_str(), phdr_num_);
return false;
}
- ElfW(Addr) page_min = PAGE_START(header_.e_phoff);
- ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
- ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
-
- phdr_size_ = page_max - page_min;
-
- void* mmap_result =
- mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
- if (mmap_result == MAP_FAILED) {
- DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
+ // Boundary checks
+ size_t size = phdr_num_ * sizeof(ElfW(Phdr));
+ if (!CheckFileRange(header_.e_phoff, size)) {
+ DL_ERR("\"%s\" has invalid phdr offset/size", name_.c_str());
return false;
}
- phdr_mmap_ = mmap_result;
- phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
+ if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
+ DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
+ return true;
+}
+
+bool ElfReader::ReadSectionHeaders() {
+ shdr_num_ = header_.e_shnum;
+
+ if (shdr_num_ == 0) {
+ DL_ERR("\"%s\" has no section headers", name_.c_str());
+ return false;
+ }
+
+ size_t size = shdr_num_ * sizeof(ElfW(Shdr));
+ if (!CheckFileRange(header_.e_shoff, size)) {
+ DL_ERR("\"%s\" has invalid shdr offset/size", name_.c_str());
+ return false;
+ }
+
+ if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
+ DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
+ return true;
+}
+
+bool ElfReader::ReadDynamicSection() {
+ // 1. Find .dynamic section (in section headers)
+ const ElfW(Shdr)* dynamic_shdr = nullptr;
+ for (size_t i = 0; i < shdr_num_; ++i) {
+ if (shdr_table_[i].sh_type == SHT_DYNAMIC) {
+ dynamic_shdr = &shdr_table_ [i];
+ break;
+ }
+ }
+
+ if (dynamic_shdr == nullptr) {
+ DL_ERR("\"%s\" .dynamic section header was not found", name_.c_str());
+ return false;
+ }
+
+ if (dynamic_shdr->sh_link >= shdr_num_) {
+ DL_ERR("\"%s\" .dynamic section has invalid sh_link: %d", name_.c_str(), dynamic_shdr->sh_link);
+ return false;
+ }
+
+ const ElfW(Shdr)* strtab_shdr = &shdr_table_[dynamic_shdr->sh_link];
+
+ if (strtab_shdr->sh_type != SHT_STRTAB) {
+ DL_ERR("\"%s\" .dynamic section has invalid link(%d) sh_type: %d (expected SHT_STRTAB)",
+ name_.c_str(), dynamic_shdr->sh_link, strtab_shdr->sh_type);
+ return false;
+ }
+
+ if (!CheckFileRange(dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
+ DL_ERR("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
+ PRINT("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
+ return false;
+ }
+
+ if (!dynamic_fragment_.Map(fd_, file_offset_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
+ DL_ERR("\"%s\" dynamic section mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
+
+ if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
+ DL_ERR("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
+ name_.c_str());
+ return false;
+ }
+
+ if (!strtab_fragment_.Map(fd_, file_offset_, strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
+ DL_ERR("\"%s\" strtab section mmap failed: %s", name_.c_str(), strerror(errno));
+ return false;
+ }
+
+ strtab_ = static_cast<const char*>(strtab_fragment_.data());
+ strtab_size_ = strtab_fragment_.size();
return true;
}
@@ -308,7 +419,7 @@
ElfW(Addr) min_vaddr;
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
if (load_size_ == 0) {
- DL_ERR("\"%s\" has no loadable segments", name_);
+ DL_ERR("\"%s\" has no loadable segments", name_.c_str());
return false;
}
@@ -316,8 +427,9 @@
void* start;
size_t reserved_size = 0;
bool reserved_hint = true;
+ bool strict_hint = false;
// Assume position independent executable by default.
- uint8_t* mmap_hint = nullptr;
+ void* mmap_hint = nullptr;
if (extinfo != nullptr) {
if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
@@ -327,21 +439,30 @@
reserved_size = extinfo->reserved_size;
}
- if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
+ if (addr != nullptr && (extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
mmap_hint = addr;
+ } else if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0) {
+ mmap_hint = extinfo->reserved_addr;
+ strict_hint = true;
}
}
if (load_size_ > reserved_size) {
if (!reserved_hint) {
DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
- reserved_size - load_size_, load_size_, name_);
+ reserved_size - load_size_, load_size_, name_.c_str());
return false;
}
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0);
if (start == MAP_FAILED) {
- DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
+ DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_.c_str());
+ return false;
+ }
+ if (strict_hint && (start != mmap_hint)) {
+ munmap(start, load_size_);
+ DL_ERR("couldn't reserve %zd bytes of address space at %p for \"%s\"",
+ load_size_, mmap_hint, name_.c_str());
return false;
}
} else {
@@ -378,14 +499,14 @@
ElfW(Addr) file_length = file_end - file_page_start;
if (file_size_ <= 0) {
- DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_);
+ DL_ERR("\"%s\" invalid file size: %" PRId64, name_.c_str(), file_size_);
return false;
}
if (file_end > static_cast<size_t>(file_size_)) {
DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
" p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
- name_, i, reinterpret_cast<void*>(phdr->p_offset),
+ name_.c_str(), i, reinterpret_cast<void*>(phdr->p_offset),
reinterpret_cast<void*>(phdr->p_filesz),
reinterpret_cast<void*>(file_end), file_size_);
return false;
@@ -399,7 +520,7 @@
fd_,
file_offset_ + file_page_start);
if (seg_addr == MAP_FAILED) {
- DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
+ DL_ERR("couldn't map \"%s\" segment %zd: %s", name_.c_str(), i, strerror(errno));
return false;
}
}
@@ -424,7 +545,7 @@
-1,
0);
if (zeromap == MAP_FAILED) {
- DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno));
+ DL_ERR("couldn't zero fill \"%s\" gap: %s", name_.c_str(), strerror(errno));
return false;
}
}
@@ -819,7 +940,7 @@
}
}
- DL_ERR("can't find loaded phdr for \"%s\"", name_);
+ DL_ERR("can't find loaded phdr for \"%s\"", name_.c_str());
return false;
}
@@ -829,7 +950,7 @@
bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
- for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
+ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
if (phdr->p_type != PT_LOAD) {
continue;
}
@@ -840,6 +961,7 @@
return true;
}
}
- DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
+ DL_ERR("\"%s\" loaded phdr %p not in loadable segment",
+ name_.c_str(), reinterpret_cast<void*>(loaded));
return false;
}
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 55196fd..c359cca 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -36,30 +36,39 @@
*/
#include "linker.h"
+#include "linker_mapped_file_fragment.h"
class ElfReader {
public:
- ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size);
- ~ElfReader();
+ ElfReader();
+ bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
bool Load(const android_dlextinfo* extinfo);
- size_t phdr_count() { return phdr_num_; }
- ElfW(Addr) load_start() { return reinterpret_cast<ElfW(Addr)>(load_start_); }
- size_t load_size() { return load_size_; }
- ElfW(Addr) load_bias() { return load_bias_; }
- const ElfW(Phdr)* loaded_phdr() { return loaded_phdr_; }
+ const char* name() const { return name_.c_str(); }
+ size_t phdr_count() const { return phdr_num_; }
+ ElfW(Addr) load_start() const { return reinterpret_cast<ElfW(Addr)>(load_start_); }
+ size_t load_size() const { return load_size_; }
+ ElfW(Addr) load_bias() const { return load_bias_; }
+ const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; }
+ const ElfW(Dyn)* dynamic() const { return dynamic_; }
+ const char* get_string(ElfW(Word) index) const;
private:
bool ReadElfHeader();
bool VerifyElfHeader();
- bool ReadProgramHeader();
+ bool ReadProgramHeaders();
+ bool ReadSectionHeaders();
+ bool ReadDynamicSection();
bool ReserveAddressSpace(const android_dlextinfo* extinfo);
bool LoadSegments();
bool FindPhdr();
bool CheckPhdr(ElfW(Addr));
+ bool CheckFileRange(ElfW(Addr) offset, size_t size);
- const char* name_;
+ bool did_read_;
+ bool did_load_;
+ std::string name_;
int fd_;
off64_t file_offset_;
off64_t file_size_;
@@ -67,9 +76,19 @@
ElfW(Ehdr) header_;
size_t phdr_num_;
- void* phdr_mmap_;
- ElfW(Phdr)* phdr_table_;
- ElfW(Addr) phdr_size_;
+ MappedFileFragment phdr_fragment_;
+ const ElfW(Phdr)* phdr_table_;
+
+ MappedFileFragment shdr_fragment_;
+ const ElfW(Shdr)* shdr_table_;
+ size_t shdr_num_;
+
+ MappedFileFragment dynamic_fragment_;
+ const ElfW(Dyn)* dynamic_;
+
+ MappedFileFragment strtab_fragment_;
+ const char* strtab_;
+ size_t strtab_size_;
// First page of reserved address space.
void* load_start_;
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 5d39d83..db43d38 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -20,7 +20,7 @@
bool normalize_path(const char* path, std::string* normalized_path) {
// Input should be an absolute path
if (path[0] != '/') {
- PRINT("canonize_path - invalid input: '%s', the input path should be absolute", path);
+ PRINT("normalize_path - invalid input: '%s', the input path should be absolute", path);
return false;
}
@@ -61,3 +61,67 @@
return true;
}
+bool file_is_in_dir(const std::string& file, const std::string& dir) {
+ const char* needle = dir.c_str();
+ const char* haystack = file.c_str();
+ size_t needle_len = strlen(needle);
+
+ return (strncmp(haystack, needle, needle_len) == 0 &&
+ haystack[needle_len] == '/' &&
+ strchr(haystack + needle_len + 1, '/') == nullptr);
+}
+
+const char* const kZipFileSeparator = "!/";
+
+bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path) {
+ std::string normalized_path;
+ if (!normalize_path(input_path, &normalized_path)) {
+ return false;
+ }
+
+ const char* const path = normalized_path.c_str();
+ TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path);
+
+ // Treat an '!/' separator inside a path as the separator between the name
+ // of the zip file on disk and the subdirectory to search within it.
+ // For example, if path is "foo.zip!/bar/bas/x.so", then we search for
+ // "bar/bas/x.so" within "foo.zip".
+ const char* const separator = strstr(path, kZipFileSeparator);
+ if (separator == nullptr) {
+ return false;
+ }
+
+ char buf[512];
+ if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
+ PRINT("Warning: ignoring very long library path: %s", path);
+ return false;
+ }
+
+ buf[separator - path] = '\0';
+
+ *zip_path = buf;
+ *entry_path = &buf[separator - path + 2];
+
+ return true;
+}
+
+constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1);
+
+off64_t page_start(off64_t offset) {
+ return offset & kPageMask;
+}
+
+bool safe_add(off64_t* out, off64_t a, size_t b) {
+ CHECK(a >= 0);
+ if (static_cast<uint64_t>(INT64_MAX - a) < b) {
+ return false;
+ }
+
+ *out = a + b;
+ return true;
+}
+
+size_t page_offset(off64_t offset) {
+ return static_cast<size_t>(offset & (PAGE_SIZE-1));
+}
+
diff --git a/linker/linker_utils.h b/linker/linker_utils.h
index fc79fd1..65ffbdc5 100644
--- a/linker/linker_utils.h
+++ b/linker/linker_utils.h
@@ -18,6 +18,14 @@
#include <string>
+extern const char* const kZipFileSeparator;
+
bool normalize_path(const char* path, std::string* normalized_path);
+bool file_is_in_dir(const std::string& file, const std::string& dir);
+bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path);
+
+off64_t page_start(off64_t offset);
+size_t page_offset(off64_t offset);
+bool safe_add(off64_t* out, off64_t a, size_t b);
#endif
diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp
index 09ad687..12348d9 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/tests/linked_list_test.cpp
@@ -133,6 +133,23 @@
ASSERT_TRUE(list.pop_front() == nullptr);
}
+TEST(linked_list, remove_if_last_then_push_back) {
+ test_list_t list;
+
+ list.push_back("a");
+ list.push_back("b");
+ list.push_back("c");
+ list.push_back("d");
+
+ list.remove_if([](const char* c) {
+ return *c == 'c' || *c == 'd';
+ });
+
+ ASSERT_EQ("ab", test_list_to_string(list));
+ list.push_back("d");
+ ASSERT_EQ("abd", test_list_to_string(list));
+}
+
TEST(linked_list, copy_to_array) {
test_list_t list;
const size_t max_size = 128;
diff --git a/linker/tests/linker_utils_test.cpp b/linker/tests/linker_utils_test.cpp
index 458474e..3be9b3f 100644
--- a/linker/tests/linker_utils_test.cpp
+++ b/linker/tests/linker_utils_test.cpp
@@ -43,3 +43,50 @@
ASSERT_FALSE(normalize_path("root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
ASSERT_EQ("unchanged", output);
}
+
+TEST(linker_utils, file_is_in_dir_smoke) {
+ ASSERT_TRUE(file_is_in_dir("/foo/bar/file", "/foo/bar"));
+ ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/foo"));
+
+ ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/bar/foo"));
+
+ ASSERT_TRUE(file_is_in_dir("/file", ""));
+ ASSERT_FALSE(file_is_in_dir("/file", "/"));
+}
+
+TEST(linker_utils, parse_zip_path_smoke) {
+ std::string zip_path;
+ std::string entry_path;
+
+ ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip", &zip_path, &entry_path));
+ ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip!path/in/zip", &zip_path, &entry_path));
+ ASSERT_TRUE(parse_zip_path("/zip/path/file.zip!/path/in/zip", &zip_path, &entry_path));
+ ASSERT_EQ("/zip/path/file.zip", zip_path);
+ ASSERT_EQ("path/in/zip", entry_path);
+
+ ASSERT_TRUE(parse_zip_path("/zip/path/file2.zip!/", &zip_path, &entry_path));
+ ASSERT_EQ("/zip/path/file2.zip", zip_path);
+ ASSERT_EQ("", entry_path);
+}
+
+TEST(linker_utils, page_start) {
+ ASSERT_EQ(0x0001000, page_start(0x0001000));
+ ASSERT_EQ(0x3002000, page_start(0x300222f));
+ ASSERT_EQ(0x6001000, page_start(0x6001fff));
+}
+
+TEST(linker_utils, page_offset) {
+ ASSERT_EQ(0x0U, page_offset(0x0001000));
+ ASSERT_EQ(0x22fU, page_offset(0x300222f));
+ ASSERT_EQ(0xfffU, page_offset(0x6001fff));
+}
+
+TEST(linker_utils, safe_add) {
+ int64_t val = 42;
+ ASSERT_FALSE(safe_add(&val, INT64_MAX-20, 21U));
+ ASSERT_EQ(42, val);
+ ASSERT_TRUE(safe_add(&val, INT64_MAX-42, 42U));
+ ASSERT_EQ(INT64_MAX, val);
+ ASSERT_TRUE(safe_add(&val, 2000, 42U));
+ ASSERT_EQ(2042, val);
+}
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 7cac349..740c2f4 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -28,9 +28,17 @@
LOCAL_MODULE_STEM_32 := $(module)32
LOCAL_MODULE_STEM_64 := $(module)64
else
+
+ifneq ($($(module)_install_to_out_data_dir),)
+ $(module)_install_to_out_data := true
+endif
+
ifeq ($($(module)_install_to_out_data),true)
- LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
- LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
+ ifeq ($($(module)_install_to_out_data_dir),)
+ $(module)_install_to_out_data_dir := $(module)
+ endif
+ LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$($(module)_install_to_out_data_dir)
+ LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$($(module)_install_to_out_data_dir)
endif
endif
diff --git a/tests/Android.mk b/tests/Android.mk
index e2c4fb4..86c141a 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -63,6 +63,7 @@
getcwd_test.cpp \
inttypes_test.cpp \
libc_logging_test.cpp \
+ libgen_basename_test.cpp \
libgen_test.cpp \
locale_test.cpp \
malloc_test.cpp \
@@ -141,7 +142,9 @@
# Clang/llvm has incompatible long double (fp128) for x86_64.
# https://llvm.org/bugs/show_bug.cgi?id=23897
# This affects most of math_test.cpp.
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64))
libBionicStandardTests_clang_target := false
+endif
module := libBionicStandardTests
module_tag := optional
@@ -168,6 +171,7 @@
) \
)
+fortify1-tests-gcc_clang_target := false
module := fortify1-tests-gcc
module_tag := optional
build_type := target
@@ -176,6 +180,7 @@
build_type := host
include $(LOCAL_PATH)/Android.build.mk
+fortify2-tests-gcc_clang_target := false
module := fortify2-tests-gcc
module_tag := optional
build_type := target
@@ -267,18 +272,20 @@
# Tests for the device using bionic's .so. Run with:
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
+# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc32
+# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc64
# -----------------------------------------------------------------------------
-bionic-unit-tests_whole_static_libraries := \
+common_bionic-unit-tests_whole_static_libraries := \
libBionicTests \
libBionicGtestMain \
-bionic-unit-tests_static_libraries := \
+common_bionic-unit-tests_static_libraries := \
libtinyxml2 \
liblog \
libbase \
# TODO: Include __cxa_thread_atexit_test.cpp to glibc tests once it is upgraded (glibc 2.18+)
-bionic-unit-tests_src_files := \
+common_bionic-unit-tests_src_files := \
atexit_test.cpp \
dl_test.cpp \
dlext_test.cpp \
@@ -288,36 +295,56 @@
pthread_dlfcn_test.cpp \
thread_local_test.cpp \
-bionic-unit-tests_cflags := $(test_cflags)
+common_bionic-unit-tests_cflags := $(test_cflags)
-bionic-unit-tests_conlyflags := \
+common_bionic-unit-tests_conlyflags := \
-fexceptions \
-fnon-call-exceptions \
-bionic-unit-tests_cppflags := $(test_cppflags)
+common_bionic-unit-tests_cppflags := $(test_cppflags)
-bionic-unit-tests_ldflags := \
+common_bionic-unit-tests_ldflags := \
-Wl,--export-dynamic
-bionic-unit-tests_c_includes := \
+common_bionic-unit-tests_c_includes := \
bionic/libc \
-bionic-unit-tests_shared_libraries_target := \
+common_bionic-unit-tests_shared_libraries_target := \
libdl \
libpagemap \
libdl_preempt_test_1 \
libdl_preempt_test_2
-# TODO: clang support for thread_local on arm is done via __aeabi_read_tp()
-# which bionic does not support. Reenable this once this question is resolved.
-bionic-unit-tests_clang_target := false
+common_bionic-unit-tests_shared_libraries_target += libdl_test_df_1_global
-bionic-unit-tests_shared_libraries_target += libdl_test_df_1_global
-
-module := bionic-unit-tests
module_tag := optional
build_type := target
build_target := NATIVE_TEST
+
+module := bionic-unit-tests
+bionic-unit-tests_clang_target := true
+bionic-unit-tests_whole_static_libraries := $(common_bionic-unit-tests_whole_static_libraries)
+bionic-unit-tests_static_libraries := $(common_bionic-unit-tests_static_libraries)
+bionic-unit-tests_src_files := $(common_bionic-unit-tests_src_files)
+bionic-unit-tests_cflags := $(common_bionic-unit-tests_cflags)
+bionic-unit-tests_conlyflags := $(common_bionic-unit-tests_conlyflags)
+bionic-unit-tests_cppflags := $(common_bionic-unit-tests_cppflags)
+bionic-unit-tests_ldflags := $(common_bionic-unit-tests_ldflags)
+bionic-unit-tests_c_includes := $(common_bionic-unit-tests_c_includes)
+bionic-unit-tests_shared_libraries_target := $(common_bionic-unit-tests_shared_libraries_target)
+include $(LOCAL_PATH)/Android.build.mk
+
+module := bionic-unit-tests-gcc
+bionic-unit-tests-gcc_clang_target := false
+bionic-unit-tests-gcc_whole_static_libraries := $(common_bionic-unit-tests_whole_static_libraries)
+bionic-unit-tests-gcc_static_libraries := $(common_bionic-unit-tests_static_libraries)
+bionic-unit-tests-gcc_src_files := $(common_bionic-unit-tests_src_files)
+bionic-unit-tests-gcc_cflags := $(common_bionic-unit-tests_cflags)
+bionic-unit-tests-gcc_conlyflags := $(common_bionic-unit-tests_conlyflags)
+bionic-unit-tests-gcc_cppflags := $(common_bionic-unit-tests_cppflags)
+bionic-unit-tests-gcc_ldflags := $(common_bionic-unit-tests_ldflags)
+bionic-unit-tests-gcc_c_includes := $(common_bionic-unit-tests_c_includes)
+bionic-unit-tests-gcc_shared_libraries_target := $(common_bionic-unit-tests_shared_libraries_target)
include $(LOCAL_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
diff --git a/tests/__cxa_thread_atexit_test.cpp b/tests/__cxa_thread_atexit_test.cpp
index e388f3b..1432968 100644
--- a/tests/__cxa_thread_atexit_test.cpp
+++ b/tests/__cxa_thread_atexit_test.cpp
@@ -35,7 +35,12 @@
std::string message;
};
+#if defined(__clang__) && defined(__aarch64__)
+// b/25642296, aarch64 clang compiled "thread_local" does not link.
+static ClassWithDtor class_with_dtor;
+#else
static thread_local ClassWithDtor class_with_dtor;
+#endif
static void* thread_nop(void* arg) {
class_with_dtor.set_message(*static_cast<std::string*>(arg));
@@ -47,7 +52,12 @@
pthread_t t;
ASSERT_EQ(0, pthread_create(&t, nullptr, thread_nop, &msg));
ASSERT_EQ(0, pthread_join(t, nullptr));
+#if defined(__clang__) && defined(__aarch64__)
+ GTEST_LOG_(INFO) << "Skipping test, b/25642296, "
+ << "thread_local does not work with aarch64 clang/llvm.\n";
+#else
ASSERT_EQ("dtor called.", class_with_dtor_output);
+#endif
}
class ClassWithDtorForMainThread {
@@ -64,7 +74,13 @@
};
static void thread_atexit_main() {
+#if defined(__clang__) && defined(__aarch64__)
+ static ClassWithDtorForMainThread class_with_dtor_for_main_thread;
+ GTEST_LOG_(INFO) << "Skipping test, b/25642296, "
+ << "thread_local does not work with aarch64 clang/llvm.\n";
+#else
static thread_local ClassWithDtorForMainThread class_with_dtor_for_main_thread;
+#endif
class_with_dtor_for_main_thread.set_message("d-tor for main thread called.");
exit(0);
}
diff --git a/tests/atexit_test.cpp b/tests/atexit_test.cpp
index e92889d..67fbfd2 100644
--- a/tests/atexit_test.cpp
+++ b/tests/atexit_test.cpp
@@ -14,7 +14,17 @@
* limitations under the License.
*/
+// To work around b/25643775, we disable clang optimization so that
+// VTT for std::__1::basic_stringstream<char, std::__1::char_traits<char>,
+// std::__1::allocator<char> >
+// will be correctly kept for other module's references.
+#if defined(__clang__) && (defined(__arm__) || defined(__aarch64__))
+#pragma clang optimize off
+#endif
#include <gtest/gtest.h>
+#if defined(__clang__) && (defined(__arm__) || defined(__aarch64__))
+#pragma clang optimize on
+#endif
#include <dlfcn.h>
#include <libgen.h>
diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp
index 214dd78..fa05ca1 100644
--- a/tests/dirent_test.cpp
+++ b/tests/dirent_test.cpp
@@ -81,6 +81,72 @@
CheckProcSelf(name_set);
}
+TEST(dirent, scandirat_scandirat64) {
+ // Get everything from /proc/self...
+ dirent** entries;
+ int entry_count = scandir("/proc/self", &entries, NULL, alphasort);
+ ASSERT_GE(entry_count, 0);
+
+ int proc_fd = open("/proc", O_DIRECTORY);
+ ASSERT_NE(-1, proc_fd);
+
+ dirent** entries_at;
+ int entry_count_at = scandirat(proc_fd, "self", &entries_at, NULL, alphasort);
+ ASSERT_EQ(entry_count, entry_count_at);
+
+ dirent64** entries_at64;
+ int entry_count_at64 = scandirat64(proc_fd, "self", &entries_at64, NULL, alphasort64);
+ ASSERT_EQ(entry_count, entry_count_at64);
+
+ close(proc_fd);
+
+ // scandirat and scandirat64 should return the same results as scandir.
+ std::set<std::string> name_set, name_set_at, name_set_at64;
+ std::vector<std::string> unsorted_name_list, unsorted_name_list_at, unsorted_name_list_at64;
+ ScanEntries(entries, entry_count, name_set, unsorted_name_list);
+ ScanEntries(entries_at, entry_count_at, name_set_at, unsorted_name_list_at);
+ ScanEntries(entries_at64, entry_count_at64, name_set_at64, unsorted_name_list_at64);
+
+ ASSERT_EQ(name_set, name_set_at);
+ ASSERT_EQ(name_set, name_set_at64);
+ ASSERT_EQ(unsorted_name_list, unsorted_name_list_at);
+ ASSERT_EQ(unsorted_name_list, unsorted_name_list_at64);
+}
+
+TEST(dirent, scandir_ENOENT) {
+ dirent** entries;
+ errno = 0;
+ ASSERT_EQ(-1, scandir("/does-not-exist", &entries, nullptr, nullptr));
+ ASSERT_EQ(ENOENT, errno);
+}
+
+TEST(dirent, scandir64_ENOENT) {
+ dirent64** entries;
+ errno = 0;
+ ASSERT_EQ(-1, scandir64("/does-not-exist", &entries, nullptr, nullptr));
+ ASSERT_EQ(ENOENT, errno);
+}
+
+TEST(dirent, scandirat_ENOENT) {
+ int root_fd = open("/", O_DIRECTORY | O_RDONLY);
+ ASSERT_NE(-1, root_fd);
+ dirent** entries;
+ errno = 0;
+ ASSERT_EQ(-1, scandirat(root_fd, "does-not-exist", &entries, nullptr, nullptr));
+ ASSERT_EQ(ENOENT, errno);
+ close(root_fd);
+}
+
+TEST(dirent, scandirat64_ENOENT) {
+ int root_fd = open("/", O_DIRECTORY | O_RDONLY);
+ ASSERT_NE(-1, root_fd);
+ dirent64** entries;
+ errno = 0;
+ ASSERT_EQ(-1, scandirat64(root_fd, "does-not-exist", &entries, nullptr, nullptr));
+ ASSERT_EQ(ENOENT, errno);
+ close(root_fd);
+}
+
TEST(dirent, fdopendir_invalid) {
ASSERT_TRUE(fdopendir(-1) == NULL);
ASSERT_EQ(EBADF, errno);
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index d5a5e56..97b5208 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -32,6 +32,7 @@
#include <pagemap/pagemap.h>
#include "TemporaryFile.h"
+#include "utils.h"
#define ASSERT_DL_NOTNULL(ptr) \
ASSERT_TRUE(ptr != nullptr) << "dlerror: " << dlerror()
@@ -52,14 +53,14 @@
#define LIBSIZE 1024*1024 // how much address space to reserve for it
#if defined(__LP64__)
-#define LIBPATH_PREFIX "/nativetest64/"
+#define NATIVE_TESTS_PATH "/nativetest64"
#else
-#define LIBPATH_PREFIX "/nativetest/"
+#define NATIVE_TESTS_PATH "/nativetest"
#endif
-#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd/libdlext_test_fd.so"
-#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_zip/libdlext_test_zip_zipaligned.zip"
-#define LIBZIPPATH_WITH_RUNPATH LIBPATH_PREFIX "libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip"
+#define LIBPATH NATIVE_TESTS_PATH "/libdlext_test_fd/libdlext_test_fd.so"
+#define LIBZIPPATH NATIVE_TESTS_PATH "/libdlext_test_zip/libdlext_test_zip_zipaligned.zip"
+#define LIBZIPPATH_WITH_RUNPATH NATIVE_TESTS_PATH "/libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip"
#define LIBZIP_OFFSET PAGE_SIZE
@@ -169,6 +170,11 @@
ASSERT_TRUE(handle_ == nullptr);
ASSERT_EQ("dlopen failed: \"" + lib_realpath + "\" has bad ELF magic", dlerror());
+ // Check if dlsym works after unsuccessful dlopen().
+ // Supply non-exiting one to make linker visit every soinfo.
+ void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
+ ASSERT_TRUE(sym == nullptr);
+
close(extinfo.library_fd);
}
@@ -343,6 +349,43 @@
EXPECT_EQ(4, f());
}
+TEST_F(DlExtTest, LoadAtFixedAddress) {
+ void* start = mmap(nullptr, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ munmap(start, LIBSIZE);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
+ extinfo.reserved_addr = start;
+
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_GE(reinterpret_cast<void*>(f), start);
+ EXPECT_LT(reinterpret_cast<void*>(f), reinterpret_cast<char*>(start) + LIBSIZE);
+
+ EXPECT_EQ(4, f());
+}
+
+TEST_F(DlExtTest, LoadAtFixedAddressTooSmall) {
+ void* start = mmap(nullptr, LIBSIZE + PAGE_SIZE, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_TRUE(start != MAP_FAILED);
+ munmap(start, LIBSIZE + PAGE_SIZE);
+ void* new_addr = mmap(reinterpret_cast<uint8_t*>(start) + PAGE_SIZE, LIBSIZE, PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_TRUE(new_addr != MAP_FAILED);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
+ extinfo.reserved_addr = start;
+
+ handle_ = android_dlopen_ext(LIBNAME, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle_ == nullptr);
+}
+
class DlExtRelroSharingTest : public DlExtTest {
protected:
virtual void SetUp() {
@@ -560,3 +603,298 @@
ASSERT_EQ(0, WEXITSTATUS(status));
}
}
+
+// Testing namespaces
+static const char* g_public_lib = "libnstest_public.so";
+
+TEST(dlext, ns_smoke) {
+ static const char* root_lib = "libnstest_root.so";
+ std::string path = std::string("libc.so:libc++.so:libdl.so:libm.so:") + g_public_lib;
+
+ ASSERT_FALSE(android_init_namespaces(path.c_str(), nullptr));
+ ASSERT_STREQ("android_init_namespaces failed: error initializing public namespace: "
+ "\"libnstest_public.so\" was not found in the default namespace", dlerror());
+
+ const std::string lib_path = std::string(getenv("ANDROID_DATA")) + NATIVE_TESTS_PATH;
+
+ const std::string lib_public_path = lib_path + "/public_namespace_libs/" + g_public_lib;
+ void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+ ASSERT_TRUE(android_init_namespaces(path.c_str(), nullptr)) << dlerror();
+
+ // Check that libraries added to public namespace are NODELETE
+ dlclose(handle_public);
+ handle_public = dlopen((lib_path + "/public_namespace_libs/" + g_public_lib).c_str(), RTLD_NOW | RTLD_NOLOAD);
+ ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+ android_namespace_t* ns1 = android_create_namespace("private", nullptr, (lib_path + "/private_namespace_libs").c_str(), false);
+ ASSERT_TRUE(ns1 != nullptr) << dlerror();
+
+ android_namespace_t* ns2 = android_create_namespace("private_isolated", nullptr, (lib_path + "/private_namespace_libs").c_str(), true);
+ ASSERT_TRUE(ns2 != nullptr) << dlerror();
+
+ // This should not have affect search path for default namespace:
+ ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
+ void* handle = dlopen(g_public_lib, RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ dlclose(handle);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns1;
+
+ void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle1 != nullptr) << dlerror();
+
+ extinfo.library_namespace = ns2;
+ void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle2 != nullptr) << dlerror();
+
+ ASSERT_TRUE(handle1 != handle2);
+
+ // dlopen for a public library using an absolute path should work for isolated namespaces
+ extinfo.library_namespace = ns2;
+ handle = android_dlopen_ext(lib_public_path.c_str(), RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ ASSERT_TRUE(handle == handle_public);
+
+ dlclose(handle);
+
+ typedef const char* (*fn_t)();
+
+ fn_t ns_get_local_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
+ ASSERT_TRUE(ns_get_local_string1 != nullptr) << dlerror();
+ fn_t ns_get_local_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_local_string"));
+ ASSERT_TRUE(ns_get_local_string2 != nullptr) << dlerror();
+
+ EXPECT_STREQ("This string is local to root library", ns_get_local_string1());
+ EXPECT_STREQ("This string is local to root library", ns_get_local_string2());
+
+ ASSERT_TRUE(ns_get_local_string1() != ns_get_local_string2());
+
+ fn_t ns_get_private_extern_string1 =
+ reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
+ ASSERT_TRUE(ns_get_private_extern_string1 != nullptr) << dlerror();
+ fn_t ns_get_private_extern_string2 =
+ reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_private_extern_string"));
+ ASSERT_TRUE(ns_get_private_extern_string2 != nullptr) << dlerror();
+
+ EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string1());
+ EXPECT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
+
+ ASSERT_TRUE(ns_get_private_extern_string1() != ns_get_private_extern_string2());
+
+ fn_t ns_get_public_extern_string1 =
+ reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
+ ASSERT_TRUE(ns_get_public_extern_string1 != nullptr) << dlerror();
+ fn_t ns_get_public_extern_string2 =
+ reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_public_extern_string"));
+ ASSERT_TRUE(ns_get_public_extern_string2 != nullptr) << dlerror();
+
+ EXPECT_STREQ("This string is from public namespace", ns_get_public_extern_string1());
+ ASSERT_TRUE(ns_get_public_extern_string1() == ns_get_public_extern_string2());
+
+ // and now check that dlopen() does the right thing in terms of preserving namespace
+ fn_t ns_get_dlopened_string1 = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
+ ASSERT_TRUE(ns_get_dlopened_string1 != nullptr) << dlerror();
+ fn_t ns_get_dlopened_string2 = reinterpret_cast<fn_t>(dlsym(handle2, "ns_get_dlopened_string"));
+ ASSERT_TRUE(ns_get_dlopened_string2 != nullptr) << dlerror();
+
+ EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string1());
+ EXPECT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
+
+ ASSERT_TRUE(ns_get_dlopened_string1() != ns_get_dlopened_string2());
+
+ dlclose(handle1);
+
+ // Check if handle2 is still alive (and well)
+ ASSERT_STREQ("This string is local to root library", ns_get_local_string2());
+ ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string2());
+ ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string2());
+ ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string2());
+
+ dlclose(handle2);
+}
+
+extern "C" void android_set_application_target_sdk_version(uint32_t target);
+
+TEST(dlext, ns_isolated) {
+ static const char* root_lib = "libnstest_root_not_isolated.so";
+ std::string path = std::string("libc.so:libc++.so:libdl.so:libm.so:") + g_public_lib;
+
+ const std::string lib_path = std::string(getenv("ANDROID_DATA")) + NATIVE_TESTS_PATH;
+ const std::string lib_public_path = lib_path + "/public_namespace_libs/" + g_public_lib;
+ void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+ android_set_application_target_sdk_version(42U); // something > 23
+
+ ASSERT_TRUE(android_init_namespaces(path.c_str(), nullptr)) << dlerror();
+
+ android_namespace_t* ns_not_isolated = android_create_namespace("private", nullptr, (lib_path + "/private_namespace_libs").c_str(), false);
+ ASSERT_TRUE(ns_not_isolated != nullptr) << dlerror();
+
+ android_namespace_t* ns_isolated = android_create_namespace("private_isolated1", nullptr, (lib_path + "/private_namespace_libs").c_str(), true);
+ ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
+
+ android_namespace_t* ns_isolated2 = android_create_namespace("private_isolated2", (lib_path + "/private_namespace_libs").c_str(), nullptr, true);
+ ASSERT_TRUE(ns_isolated2 != nullptr) << dlerror();
+
+ ASSERT_TRUE(dlopen(root_lib, RTLD_NOW) == nullptr);
+ ASSERT_STREQ("dlopen failed: library \"libnstest_root_not_isolated.so\" not found", dlerror());
+
+ std::string lib_private_external_path =
+ lib_path + "/private_namespace_libs_external/libnstest_private_external.so";
+
+ // Load lib_private_external_path to default namespace
+ // (it should remain invisible for the isolated namespaces after this)
+ void* handle = dlopen(lib_private_external_path.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns_not_isolated;
+
+ void* handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle1 != nullptr) << dlerror();
+
+ extinfo.library_namespace = ns_isolated;
+
+ void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle2 == nullptr);
+ ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
+
+ // Check dlopen by absolute path
+ handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle2 == nullptr);
+ ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" is not accessible for the namespace \"private_isolated1\"", dlerror());
+
+ extinfo.library_namespace = ns_isolated2;
+
+ handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle2 == nullptr);
+ ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror());
+
+ // Check dlopen by absolute path
+ handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle2 == nullptr);
+ ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" is not accessible for the namespace \"private_isolated2\"", dlerror());
+
+ typedef const char* (*fn_t)();
+ fn_t ns_get_local_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_local_string"));
+ ASSERT_TRUE(ns_get_local_string != nullptr) << dlerror();
+
+ ASSERT_STREQ("This string is local to root library", ns_get_local_string());
+
+ fn_t ns_get_private_extern_string =
+ reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_private_extern_string"));
+ ASSERT_TRUE(ns_get_private_extern_string != nullptr) << dlerror();
+
+ ASSERT_STREQ("This string is from private namespace", ns_get_private_extern_string());
+
+ fn_t ns_get_public_extern_string =
+ reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_public_extern_string"));
+ ASSERT_TRUE(ns_get_public_extern_string != nullptr) << dlerror();
+
+ ASSERT_STREQ("This string is from public namespace", ns_get_public_extern_string());
+
+ fn_t ns_get_dlopened_string = reinterpret_cast<fn_t>(dlsym(handle1, "ns_get_dlopened_string"));
+ ASSERT_TRUE(ns_get_dlopened_string != nullptr) << dlerror();
+
+ ASSERT_STREQ("This string is from private namespace (dlopened library)", ns_get_dlopened_string());
+
+ dlclose(handle1);
+}
+
+TEST(dlext, ns_anonymous) {
+ static const char* root_lib = "libnstest_root.so";
+ std::string path = std::string("libc.so:libc++.so:libdl.so:libm.so:") + g_public_lib;
+
+ const std::string lib_path = std::string(getenv("ANDROID_DATA")) + NATIVE_TESTS_PATH;
+
+ const std::string lib_public_path = lib_path + "/public_namespace_libs/" + g_public_lib;
+ void* handle_public = dlopen(lib_public_path.c_str(), RTLD_NOW);
+
+ ASSERT_TRUE(handle_public != nullptr) << dlerror();
+
+ ASSERT_TRUE(android_init_namespaces(path.c_str(), (lib_path + "/private_namespace_libs").c_str()))
+ << dlerror();
+
+ android_namespace_t* ns = android_create_namespace(
+ "private", nullptr,
+ (lib_path + "/private_namespace_libs").c_str(),
+ false);
+
+ ASSERT_TRUE(ns != nullptr) << dlerror();
+
+ std::string private_library_absolute_path = lib_path + "/private_namespace_libs/" + root_lib;
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_namespace = ns;
+
+ // we are going to copy this library to anonymous mmap and call the copy of ns_get_dlopened_string
+ void* handle = android_dlopen_ext(private_library_absolute_path.c_str(), RTLD_NOW, &extinfo);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+
+ uintptr_t ns_get_dlopened_string_addr =
+ reinterpret_cast<uintptr_t>(dlsym(handle, "ns_get_dlopened_string"));
+ ASSERT_TRUE(ns_get_dlopened_string_addr != 0) << dlerror();
+ typedef const char* (*fn_t)();
+ fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
+
+ std::vector<map_record> maps;
+ Maps::parse_maps(&maps);
+
+ uintptr_t addr_start = 0;
+ uintptr_t addr_end = 0;
+ std::vector<map_record> maps_to_copy;
+
+ for (const auto& rec : maps) {
+ if (rec.pathname == private_library_absolute_path) {
+ if (addr_start == 0) {
+ addr_start = rec.addr_start;
+ }
+ addr_end = rec.addr_end;
+
+ maps_to_copy.push_back(rec);
+ }
+ }
+
+ // some sanity checks..
+ ASSERT_TRUE(addr_start > 0);
+ ASSERT_TRUE(addr_end > 0);
+ ASSERT_EQ(3U, maps_to_copy.size());
+ ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
+ ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
+
+ // copy
+ uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
+ PROT_NONE, MAP_ANON | MAP_PRIVATE,
+ -1, 0));
+ ASSERT_TRUE(reinterpret_cast<void*>(reserved_addr) != MAP_FAILED);
+
+ for (const auto& rec : maps_to_copy) {
+ uintptr_t offset = rec.addr_start - addr_start;
+ size_t size = rec.addr_end - rec.addr_start;
+ void* addr = reinterpret_cast<void*>(reserved_addr + offset);
+ void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+ ASSERT_TRUE(map != MAP_FAILED);
+ memcpy(map, reinterpret_cast<void*>(rec.addr_start), size);
+ mprotect(map, size, rec.perms);
+ }
+
+ // call the function copy
+ uintptr_t ns_get_dlopened_string_offset = ns_get_dlopened_string_addr - addr_start;
+ fn_t ns_get_dlopened_string_anon = reinterpret_cast<fn_t>(reserved_addr + ns_get_dlopened_string_offset);
+ ASSERT_STREQ("This string is from private namespace (dlopened library)",
+ ns_get_dlopened_string_anon());
+
+ // They should belong to different namespaces (private and anonymous)
+ ASSERT_STREQ("This string is from private namespace (dlopened library)",
+ ns_get_dlopened_string_private());
+
+ ASSERT_TRUE(ns_get_dlopened_string_anon() != ns_get_dlopened_string_private());
+}
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 3b9f6b9..a662c73 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -575,27 +575,15 @@
exit(result);
}
-#if defined(__APPLE__)
-
-static int pipe2(int pipefd[2], int flags) {
- int ret = pipe(pipefd);
- if (ret != -1) {
- ret = fcntl(pipefd[0], F_SETFL, flags);
- }
- if (ret != -1) {
- ret = fcntl(pipefd[1], F_SETFL, flags);
- }
- return ret;
-}
-
-#endif
-
static ChildProcInfo RunChildProcess(const std::string& test_name, int testcase_id, int test_id,
int argc, char** argv) {
int pipefd[2];
- int ret = pipe2(pipefd, O_NONBLOCK);
- if (ret == -1) {
- perror("pipe2 in RunTestInSeparateProc");
+ if (pipe(pipefd) == -1) {
+ perror("pipe in RunTestInSeparateProc");
+ exit(1);
+ }
+ if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) {
+ perror("fcntl in RunTestInSeparateProc");
exit(1);
}
pid_t pid = fork();
@@ -685,6 +673,30 @@
return timeout_child_count;
}
+static void ReadChildProcOutput(std::vector<TestCase>& testcase_list,
+ std::vector<ChildProcInfo>& child_proc_list) {
+ for (const auto& child_proc : child_proc_list) {
+ TestCase& testcase = testcase_list[child_proc.testcase_id];
+ int test_id = child_proc.test_id;
+ while (true) {
+ char buf[1024];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(child_proc.child_read_fd, buf, sizeof(buf) - 1));
+ if (bytes_read > 0) {
+ buf[bytes_read] = '\0';
+ testcase.GetTest(test_id).AppendTestOutput(buf);
+ } else if (bytes_read == 0) {
+ break; // Read end.
+ } else {
+ if (errno == EAGAIN) {
+ break;
+ }
+ perror("failed to read child_read_fd");
+ exit(1);
+ }
+ }
+ }
+}
+
static void WaitChildProcs(std::vector<TestCase>& testcase_list,
std::vector<ChildProcInfo>& child_proc_list) {
size_t finished_child_count = 0;
@@ -709,6 +721,7 @@
finished_child_count += CheckChildProcTimeout(child_proc_list);
}
+ ReadChildProcOutput(testcase_list, child_proc_list);
if (finished_child_count > 0) {
return;
}
@@ -742,26 +755,6 @@
kill(child_proc.pid, SIGKILL);
WaitForOneChild(child_proc.pid);
}
-
- while (true) {
- char buf[1024];
- ssize_t bytes_read = TEMP_FAILURE_RETRY(read(child_proc.child_read_fd, buf, sizeof(buf) - 1));
- if (bytes_read > 0) {
- buf[bytes_read] = '\0';
- testcase.GetTest(test_id).AppendTestOutput(buf);
- } else if (bytes_read == 0) {
- break; // Read end.
- } else {
- if (errno == EAGAIN) {
- // No data is available. This rarely happens, only when the child process created other
- // processes which have not exited so far. But the child process has already exited or
- // been killed, so the test has finished, and we shouldn't wait further.
- break;
- }
- perror("read child_read_fd in RunTestInSeparateProc");
- exit(1);
- }
- }
close(child_proc.child_read_fd);
if (child_proc.timed_out) {
@@ -780,8 +773,14 @@
testcase.GetTest(test_id).AppendTestOutput(buf);
} else {
- testcase.SetTestResult(test_id, WEXITSTATUS(child_proc.exit_status) == 0 ?
- TEST_SUCCESS : TEST_FAILED);
+ int exitcode = WEXITSTATUS(child_proc.exit_status);
+ testcase.SetTestResult(test_id, exitcode == 0 ? TEST_SUCCESS : TEST_FAILED);
+ if (exitcode != 0) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s exited with exitcode %d.\n",
+ testcase.GetTestName(test_id).c_str(), exitcode);
+ testcase.GetTest(test_id).AppendTestOutput(buf);
+ }
}
}
diff --git a/tests/libgen_basename_test.cpp b/tests/libgen_basename_test.cpp
new file mode 100644
index 0000000..d97e0da
--- /dev/null
+++ b/tests/libgen_basename_test.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+#endif
+
+#include <string.h>
+
+#if defined(basename)
+ #error basename should not be defined at this point
+#endif
+
+static const char* gnu_basename(const char* in) {
+ return basename(in);
+}
+
+#include <libgen.h>
+
+#if !defined(basename)
+ #error basename should be defined at this point
+#endif
+
+static char* posix_basename(char* in) {
+ return basename(in);
+}
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+static void __TestGnuBasename(const char* in, const char* expected_out, int line) {
+ errno = 0;
+ const char* out = gnu_basename(in);
+ ASSERT_STREQ(expected_out, out) << "(" << line << "): " << in << std::endl;
+ ASSERT_EQ(0, errno) << "(" << line << "): " << in << std::endl;
+}
+
+static void __TestPosixBasename(const char* in, const char* expected_out, int line) {
+ char* writable_in = (in != NULL) ? strdup(in) : NULL;
+ errno = 0;
+ const char* out = posix_basename(&writable_in[0]);
+ ASSERT_STREQ(expected_out, out) << "(" << line << "): " << in << std::endl;
+ ASSERT_EQ(0, errno) << "(" << line << "): " << in << std::endl;
+ free(writable_in);
+}
+
+#define TestGnuBasename(in, expected) __TestGnuBasename(in, expected, __LINE__)
+#define TestPosixBasename(in, expected) __TestPosixBasename(in, expected, __LINE__)
+
+TEST(libgen_basename, gnu_basename) {
+ // GNU's basename doesn't accept NULL
+ // TestGnuBasename(NULL, ".");
+ TestGnuBasename("", "");
+ TestGnuBasename("/usr/lib", "lib");
+ TestGnuBasename("/system/bin/sh/", "");
+ TestGnuBasename("/usr/", "");
+ TestGnuBasename("usr", "usr");
+ TestGnuBasename("/", "");
+ TestGnuBasename(".", ".");
+ TestGnuBasename("..", "..");
+ TestGnuBasename("///", "");
+ TestGnuBasename("//usr//lib//", "");
+}
+
+TEST(libgen_basename, posix_basename) {
+ TestPosixBasename(NULL, ".");
+ TestPosixBasename("", ".");
+ TestPosixBasename("/usr/lib", "lib");
+ TestPosixBasename("/system/bin/sh/", "sh");
+ TestPosixBasename("/usr/", "usr");
+ TestPosixBasename("usr", "usr");
+ TestPosixBasename("/", "/");
+ TestPosixBasename(".", ".");
+ TestPosixBasename("..", "..");
+ TestPosixBasename("///", "/");
+ TestPosixBasename("//usr//lib//", "lib");
+}
diff --git a/tests/libgen_test.cpp b/tests/libgen_test.cpp
index e9a5d5c..8a37a3f 100644
--- a/tests/libgen_test.cpp
+++ b/tests/libgen_test.cpp
@@ -19,15 +19,6 @@
#include <errno.h>
#include <gtest/gtest.h>
-static void TestBasename(const char* in, const char* expected_out) {
- char* writable_in = (in != NULL) ? strdup(in) : NULL;
- errno = 0;
- const char* out = basename(&writable_in[0]);
- ASSERT_STREQ(expected_out, out) << in;
- ASSERT_EQ(0, errno) << in;
- free(writable_in);
-}
-
static void TestDirname(const char* in, const char* expected_out) {
char* writable_in = (in != NULL) ? strdup(in) : NULL;
errno = 0;
@@ -37,21 +28,6 @@
free(writable_in);
}
-// Do not use basename as the test name, it's defined to another value in glibc
-// so leads to a differently named test on host versus target architectures.
-TEST(libgen, posix_basename) {
- TestBasename(NULL, ".");
- TestBasename("", ".");
- TestBasename("/usr/lib", "lib");
- TestBasename("/usr/", "usr");
- TestBasename("usr", "usr");
- TestBasename("/", "/");
- TestBasename(".", ".");
- TestBasename("..", "..");
- TestBasename("///", "/");
- TestBasename("//usr//lib//", "lib");
-}
-
TEST(libgen, dirname) {
TestDirname(NULL, ".");
TestDirname("", ".");
diff --git a/tests/libs/Android.build.linker_namespaces.mk b/tests/libs/Android.build.linker_namespaces.mk
new file mode 100644
index 0000000..f913780
--- /dev/null
+++ b/tests/libs/Android.build.linker_namespaces.mk
@@ -0,0 +1,84 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# -----------------------------------------------------------------------------
+# This set of libraries are used to verify linker namespaces.
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# Test cases
+# 1. Check that private libraries loaded in different namespaces are
+# different. Check that dlsym does not confuse them.
+# 2. Check that public libraries loaded in different namespaces are shared
+# between them.
+# 3. Check that namespace sticks on dlopen
+#
+# Dependency tree (visibility)
+# libnstest_root.so (this should be local to the namespace)
+# +-> libnstest_public.so
+# +-> libnstest_private.so
+#
+# libnstest_dlopened.so (library in private namespace dlopened from libnstest_root.so)
+# -----------------------------------------------------------------------------
+libnstest_root_src_files := namespaces_root.cpp
+libnstest_root_shared_libraries := libnstest_public libnstest_private
+libnstest_root_install_to_out_data_dir := private_namespace_libs
+module := libnstest_root
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
+
+libnstest_public_src_files := namespaces_public.cpp
+module := libnstest_public
+libnstest_public_install_to_out_data_dir := public_namespace_libs
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
+
+libnstest_private_src_files := namespaces_private.cpp
+libnstest_private_install_to_out_data_dir := private_namespace_libs
+module := libnstest_private
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
+
+libnstest_dlopened_src_files := namespaces_dlopened.cpp
+libnstest_dlopened_install_to_out_data_dir := private_namespace_libs
+module := libnstest_dlopened
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
+
+# -----------------------------------------------------------------------------
+# This set of libraries is to test isolated namespaces
+#
+# Isolated namespaces do not allow loading of the library outside of
+# the search paths.
+#
+# This library cannot be loaded in isolated namespace because one of DT_NEEDED
+# libraries is outside of the search paths.
+#
+# libnstest_root_not_isolated.so (DT_RUNPATH = $ORIGIN/../private_namespace_libs_external/)
+# +-> libnstest_public.so
+# +-> libnstest_private_external.so (located in $ORIGIN/../private_namespace_libs_external/)
+#
+# Search path: $NATIVE_TESTS/private_namespace_libs/
+# -----------------------------------------------------------------------------
+libnstest_root_not_isolated_src_files := namespaces_root.cpp
+libnstest_root_not_isolated_shared_libraries := libnstest_public libnstest_private_external
+libnstest_root_not_isolated_install_to_out_data_dir := private_namespace_libs
+libnstest_root_not_isolated_ldflags := -Wl,--rpath,\$$ORIGIN/../private_namespace_libs_external \
+ -Wl,--enable-new-dtags
+
+module := libnstest_root_not_isolated
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
+
+libnstest_private_external_src_files := namespaces_private.cpp
+libnstest_private_external_install_to_out_data_dir := private_namespace_libs_external
+module := libnstest_private_external
+include $(LOCAL_PATH)/Android.build.target.testlib.mk
diff --git a/tests/libs/Android.build.target.testlib.mk b/tests/libs/Android.build.target.testlib.mk
new file mode 100644
index 0000000..1e767c2
--- /dev/null
+++ b/tests/libs/Android.build.target.testlib.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index 3391d79..93d95ee 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -26,6 +26,7 @@
$(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
$(LOCAL_PATH)/Android.build.dlopen_check_order_reloc_siblings.mk \
$(LOCAL_PATH)/Android.build.dlopen_check_order_reloc_main_executable.mk \
+ $(LOCAL_PATH)/Android.build.linker_namespaces.mk \
$(LOCAL_PATH)/Android.build.pthread_atfork.mk \
$(LOCAL_PATH)/Android.build.testlib.mk \
$(LOCAL_PATH)/Android.build.versioned_lib.mk \
@@ -213,6 +214,11 @@
include $(LOCAL_PATH)/Android.build.testlib.mk
# -----------------------------------------------------------------------------
+# Build test helper libraries for linker namespaces
+# -----------------------------------------------------------------------------
+include $(LOCAL_PATH)/Android.build.linker_namespaces.mk
+
+# -----------------------------------------------------------------------------
# Build DT_RUNPATH test helper libraries
# -----------------------------------------------------------------------------
include $(LOCAL_PATH)/Android.build.dt_runpath.mk
diff --git a/tests/libs/namespaces_dlopened.cpp b/tests/libs/namespaces_dlopened.cpp
new file mode 100644
index 0000000..9d11689
--- /dev/null
+++ b/tests/libs/namespaces_dlopened.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* g_private_dlopened_string = "This string is from private namespace "
+ "(dlopened library)";
+
diff --git a/tests/libs/namespaces_private.cpp b/tests/libs/namespaces_private.cpp
new file mode 100644
index 0000000..07cab70
--- /dev/null
+++ b/tests/libs/namespaces_private.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* g_private_extern_string = "This string is from private namespace";
+
diff --git a/tests/libs/namespaces_public.cpp b/tests/libs/namespaces_public.cpp
new file mode 100644
index 0000000..bb2a8de
--- /dev/null
+++ b/tests/libs/namespaces_public.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const char* g_public_extern_string = "This string is from public namespace";
+
diff --git a/tests/libs/namespaces_root.cpp b/tests/libs/namespaces_root.cpp
new file mode 100644
index 0000000..b0006c7
--- /dev/null
+++ b/tests/libs/namespaces_root.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+
+static const char* g_local_string = "This string is local to root library";
+extern "C" const char* g_private_extern_string;
+extern "C" const char* g_public_extern_string;
+
+bool g_dlopened = false;
+
+extern "C" const char* ns_get_local_string() {
+ return g_local_string;
+}
+
+extern "C" const char* ns_get_private_extern_string() {
+ return g_private_extern_string;
+}
+
+extern "C" const char* ns_get_public_extern_string() {
+ return g_public_extern_string;
+}
+
+extern "C" const char* ns_get_dlopened_string() {
+ void* handle = dlopen("libnstest_dlopened.so", RTLD_NOW | RTLD_GLOBAL);
+ if (handle == nullptr) {
+ return nullptr;
+ }
+
+ const char** result = static_cast<const char**>(dlsym(handle, "g_private_dlopened_string"));
+ if (result == nullptr) {
+ return nullptr;
+ } else {
+ g_dlopened = true;
+ }
+
+ return *result;
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
old mode 100644
new mode 100755
index 9f887e3..27d992b
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -30,12 +30,9 @@
#include <unwind.h>
#include <atomic>
-#include <regex>
#include <vector>
-#include <base/file.h>
-#include <base/stringprintf.h>
-
+#include "private/bionic_constants.h"
#include "private/bionic_macros.h"
#include "private/ScopeGuard.h"
#include "BionicDeathTest.h"
@@ -43,8 +40,6 @@
#include "utils.h"
-extern "C" pid_t gettid();
-
TEST(pthread, pthread_key_create) {
pthread_key_t key;
ASSERT_EQ(0, pthread_key_create(&key, NULL));
@@ -164,7 +159,7 @@
pthread_key_t key;
ASSERT_EQ(0, pthread_key_create(&key, NULL));
- size_t stack_size = 128 * 1024;
+ size_t stack_size = 640 * 1024;
void* stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
ASSERT_NE(MAP_FAILED, stack);
memset(stack, 0xff, stack_size);
@@ -222,13 +217,13 @@
while (spin_flag_) {}
return NULL;
}
- static volatile bool spin_flag_;
+ static std::atomic<bool> spin_flag_;
};
// It doesn't matter if spin_flag_ is used in several tests,
// because it is always set to false after each test. Each thread
// loops on spin_flag_ can find it becomes false at some time.
-volatile bool SpinFunctionHelper::spin_flag_ = false;
+std::atomic<bool> SpinFunctionHelper::spin_flag_;
static void* JoinFn(void* arg) {
return reinterpret_cast<void*>(pthread_join(reinterpret_cast<pthread_t>(arg), NULL));
@@ -421,6 +416,8 @@
pthread_t t1;
ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL));
ASSERT_EQ(0, pthread_setname_np(t1, "short 2"));
+ spinhelper.UnSpin();
+ ASSERT_EQ(0, pthread_join(t1, nullptr));
}
TEST(pthread, pthread_setname_np__no_such_thread) {
@@ -471,6 +468,8 @@
ASSERT_EQ(0, pthread_getcpuclockid(t, &c));
timespec ts;
ASSERT_EQ(0, clock_gettime(c, &ts));
+ spinhelper.UnSpin();
+ ASSERT_EQ(0, pthread_join(t, nullptr));
}
TEST(pthread, pthread_getcpuclockid__no_such_thread) {
@@ -539,7 +538,7 @@
// http://b/11693195 --- pthread_join could return before the thread had actually exited.
// If the joiner unmapped the thread's stack, that could lead to SIGSEGV in the thread.
for (size_t i = 0; i < 1024; ++i) {
- size_t stack_size = 64*1024;
+ size_t stack_size = 640*1024;
void* stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
pthread_attr_t a;
@@ -721,58 +720,47 @@
ASSERT_EQ(0, pthread_rwlock_destroy(&l));
}
-static void WaitUntilThreadSleep(std::atomic<pid_t>& pid) {
- while (pid == 0) {
- usleep(1000);
- }
- std::string filename = android::base::StringPrintf("/proc/%d/stat", pid.load());
- std::regex regex {R"(\s+S\s+)"};
-
- while (true) {
- std::string content;
- ASSERT_TRUE(android::base::ReadFileToString(filename, &content));
- if (std::regex_search(content, regex)) {
- break;
- }
- usleep(1000);
- }
-}
-
struct RwlockWakeupHelperArg {
pthread_rwlock_t lock;
enum Progress {
LOCK_INITIALIZED,
LOCK_WAITING,
LOCK_RELEASED,
- LOCK_ACCESSED
+ LOCK_ACCESSED,
+ LOCK_TIMEDOUT,
};
std::atomic<Progress> progress;
std::atomic<pid_t> tid;
+ std::function<int (pthread_rwlock_t*)> trylock_function;
+ std::function<int (pthread_rwlock_t*)> lock_function;
+ std::function<int (pthread_rwlock_t*, const timespec*)> timed_lock_function;
};
-static void pthread_rwlock_reader_wakeup_writer_helper(RwlockWakeupHelperArg* arg) {
+static void pthread_rwlock_wakeup_helper(RwlockWakeupHelperArg* arg) {
arg->tid = gettid();
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
arg->progress = RwlockWakeupHelperArg::LOCK_WAITING;
- ASSERT_EQ(EBUSY, pthread_rwlock_trywrlock(&arg->lock));
- ASSERT_EQ(0, pthread_rwlock_wrlock(&arg->lock));
+ ASSERT_EQ(EBUSY, arg->trylock_function(&arg->lock));
+ ASSERT_EQ(0, arg->lock_function(&arg->lock));
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress);
ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock));
arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED;
}
-TEST(pthread, pthread_rwlock_reader_wakeup_writer) {
+static void test_pthread_rwlock_reader_wakeup_writer(std::function<int (pthread_rwlock_t*)> lock_function) {
RwlockWakeupHelperArg wakeup_arg;
ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL));
ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock));
wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
wakeup_arg.tid = 0;
+ wakeup_arg.trylock_function = pthread_rwlock_trywrlock;
+ wakeup_arg.lock_function = lock_function;
pthread_t thread;
ASSERT_EQ(0, pthread_create(&thread, NULL,
- reinterpret_cast<void* (*)(void*)>(pthread_rwlock_reader_wakeup_writer_helper), &wakeup_arg));
+ reinterpret_cast<void* (*)(void*)>(pthread_rwlock_wakeup_helper), &wakeup_arg));
WaitUntilThreadSleep(wakeup_arg.tid);
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
@@ -784,29 +772,31 @@
ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
}
-static void pthread_rwlock_writer_wakeup_reader_helper(RwlockWakeupHelperArg* arg) {
- arg->tid = gettid();
- ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
- arg->progress = RwlockWakeupHelperArg::LOCK_WAITING;
-
- ASSERT_EQ(EBUSY, pthread_rwlock_tryrdlock(&arg->lock));
- ASSERT_EQ(0, pthread_rwlock_rdlock(&arg->lock));
- ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress);
- ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock));
-
- arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED;
+TEST(pthread, pthread_rwlock_reader_wakeup_writer) {
+ test_pthread_rwlock_reader_wakeup_writer(pthread_rwlock_wrlock);
}
-TEST(pthread, pthread_rwlock_writer_wakeup_reader) {
+TEST(pthread, pthread_rwlock_reader_wakeup_writer_timedwait) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_reader_wakeup_writer([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_timedwrlock(lock, &ts);
+ });
+}
+
+static void test_pthread_rwlock_writer_wakeup_reader(std::function<int (pthread_rwlock_t*)> lock_function) {
RwlockWakeupHelperArg wakeup_arg;
ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL));
ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock));
wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
wakeup_arg.tid = 0;
+ wakeup_arg.trylock_function = pthread_rwlock_tryrdlock;
+ wakeup_arg.lock_function = lock_function;
pthread_t thread;
ASSERT_EQ(0, pthread_create(&thread, NULL,
- reinterpret_cast<void* (*)(void*)>(pthread_rwlock_writer_wakeup_reader_helper), &wakeup_arg));
+ reinterpret_cast<void* (*)(void*)>(pthread_rwlock_wakeup_helper), &wakeup_arg));
WaitUntilThreadSleep(wakeup_arg.tid);
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
@@ -818,6 +808,85 @@
ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
}
+TEST(pthread, pthread_rwlock_writer_wakeup_reader) {
+ test_pthread_rwlock_writer_wakeup_reader(pthread_rwlock_rdlock);
+}
+
+TEST(pthread, pthread_rwlock_writer_wakeup_reader_timedwait) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_writer_wakeup_reader([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_timedrdlock(lock, &ts);
+ });
+}
+
+static void pthread_rwlock_wakeup_timeout_helper(RwlockWakeupHelperArg* arg) {
+ arg->tid = gettid();
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
+ arg->progress = RwlockWakeupHelperArg::LOCK_WAITING;
+
+ ASSERT_EQ(EBUSY, arg->trylock_function(&arg->lock));
+
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ASSERT_EQ(ETIMEDOUT, arg->timed_lock_function(&arg->lock, &ts));
+ ts.tv_nsec = -1;
+ ASSERT_EQ(EINVAL, arg->timed_lock_function(&arg->lock, &ts));
+ ts.tv_nsec = NS_PER_S;
+ ASSERT_EQ(EINVAL, arg->timed_lock_function(&arg->lock, &ts));
+ ts.tv_nsec = NS_PER_S - 1;
+ ts.tv_sec = -1;
+ ASSERT_EQ(ETIMEDOUT, arg->timed_lock_function(&arg->lock, &ts));
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ ASSERT_EQ(ETIMEDOUT, arg->timed_lock_function(&arg->lock, &ts));
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, arg->progress);
+ arg->progress = RwlockWakeupHelperArg::LOCK_TIMEDOUT;
+}
+
+TEST(pthread, pthread_rwlock_timedrdlock_timeout) {
+ RwlockWakeupHelperArg wakeup_arg;
+ ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, nullptr));
+ ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock));
+ wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
+ wakeup_arg.tid = 0;
+ wakeup_arg.trylock_function = pthread_rwlock_tryrdlock;
+ wakeup_arg.timed_lock_function = pthread_rwlock_timedrdlock;
+
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(pthread_rwlock_wakeup_timeout_helper), &wakeup_arg));
+ WaitUntilThreadSleep(wakeup_arg.tid);
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
+
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_TIMEDOUT, wakeup_arg.progress);
+ ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));
+ ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
+}
+
+TEST(pthread, pthread_rwlock_timedwrlock_timeout) {
+ RwlockWakeupHelperArg wakeup_arg;
+ ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, nullptr));
+ ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock));
+ wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
+ wakeup_arg.tid = 0;
+ wakeup_arg.trylock_function = pthread_rwlock_trywrlock;
+ wakeup_arg.timed_lock_function = pthread_rwlock_timedwrlock;
+
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(pthread_rwlock_wakeup_timeout_helper), &wakeup_arg));
+ WaitUntilThreadSleep(wakeup_arg.tid);
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
+
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+ ASSERT_EQ(RwlockWakeupHelperArg::LOCK_TIMEDOUT, wakeup_arg.progress);
+ ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));
+ ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
+}
+
class RwlockKindTestHelper {
private:
struct ThreadArg {
@@ -1062,36 +1131,44 @@
};
std::atomic<Progress> progress;
pthread_t thread;
+ std::function<int (pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function;
protected:
- virtual void SetUp() {
- ASSERT_EQ(0, pthread_mutex_init(&mutex, NULL));
- ASSERT_EQ(0, pthread_cond_init(&cond, NULL));
+ void SetUp() override {
+ ASSERT_EQ(0, pthread_mutex_init(&mutex, nullptr));
+ }
+
+ void InitCond(clockid_t clock=CLOCK_REALTIME) {
+ pthread_condattr_t attr;
+ ASSERT_EQ(0, pthread_condattr_init(&attr));
+ ASSERT_EQ(0, pthread_condattr_setclock(&attr, clock));
+ ASSERT_EQ(0, pthread_cond_init(&cond, &attr));
+ ASSERT_EQ(0, pthread_condattr_destroy(&attr));
+ }
+
+ void StartWaitingThread(std::function<int (pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function) {
progress = INITIALIZED;
- ASSERT_EQ(0,
- pthread_create(&thread, NULL, reinterpret_cast<void* (*)(void*)>(WaitThreadFn), this));
- }
-
- virtual void TearDown() {
- ASSERT_EQ(0, pthread_join(thread, NULL));
- ASSERT_EQ(FINISHED, progress);
- ASSERT_EQ(0, pthread_cond_destroy(&cond));
- ASSERT_EQ(0, pthread_mutex_destroy(&mutex));
- }
-
- void SleepUntilProgress(Progress expected_progress) {
- while (progress != expected_progress) {
+ this->wait_function = wait_function;
+ ASSERT_EQ(0, pthread_create(&thread, NULL, reinterpret_cast<void* (*)(void*)>(WaitThreadFn), this));
+ while (progress != WAITING) {
usleep(5000);
}
usleep(5000);
}
+ void TearDown() override {
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+ ASSERT_EQ(FINISHED, progress);
+ ASSERT_EQ(0, pthread_cond_destroy(&cond));
+ ASSERT_EQ(0, pthread_mutex_destroy(&mutex));
+ }
+
private:
static void WaitThreadFn(pthread_CondWakeupTest* test) {
ASSERT_EQ(0, pthread_mutex_lock(&test->mutex));
test->progress = WAITING;
while (test->progress == WAITING) {
- ASSERT_EQ(0, pthread_cond_wait(&test->cond, &test->mutex));
+ ASSERT_EQ(0, test->wait_function(&test->cond, &test->mutex));
}
ASSERT_EQ(SIGNALED, test->progress);
test->progress = FINISHED;
@@ -1099,39 +1176,65 @@
}
};
-TEST_F(pthread_CondWakeupTest, signal) {
- SleepUntilProgress(WAITING);
+TEST_F(pthread_CondWakeupTest, signal_wait) {
+ InitCond();
+ StartWaitingThread([](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return pthread_cond_wait(cond, mutex);
+ });
progress = SIGNALED;
- pthread_cond_signal(&cond);
+ ASSERT_EQ(0, pthread_cond_signal(&cond));
}
-TEST_F(pthread_CondWakeupTest, broadcast) {
- SleepUntilProgress(WAITING);
+TEST_F(pthread_CondWakeupTest, broadcast_wait) {
+ InitCond();
+ StartWaitingThread([](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return pthread_cond_wait(cond, mutex);
+ });
progress = SIGNALED;
- pthread_cond_broadcast(&cond);
+ ASSERT_EQ(0, pthread_cond_broadcast(&cond));
}
-TEST(pthread, pthread_mutex_timedlock) {
- pthread_mutex_t m;
- ASSERT_EQ(0, pthread_mutex_init(&m, NULL));
-
- // If the mutex is already locked, pthread_mutex_timedlock should time out.
- ASSERT_EQ(0, pthread_mutex_lock(&m));
-
+TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_REALTIME) {
+ InitCond(CLOCK_REALTIME);
timespec ts;
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
- ts.tv_nsec += 1;
- ASSERT_EQ(ETIMEDOUT, pthread_mutex_timedlock(&m, &ts));
+ ts.tv_sec += 1;
+ StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return pthread_cond_timedwait(cond, mutex, &ts);
+ });
+ progress = SIGNALED;
+ ASSERT_EQ(0, pthread_cond_signal(&cond));
+}
- // If the mutex is unlocked, pthread_mutex_timedlock should succeed.
- ASSERT_EQ(0, pthread_mutex_unlock(&m));
+TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_MONOTONIC) {
+ InitCond(CLOCK_MONOTONIC);
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_sec += 1;
+ StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return pthread_cond_timedwait(cond, mutex, &ts);
+ });
+ progress = SIGNALED;
+ ASSERT_EQ(0, pthread_cond_signal(&cond));
+}
+TEST(pthread, pthread_cond_timedwait_timeout) {
+ pthread_mutex_t mutex;
+ ASSERT_EQ(0, pthread_mutex_init(&mutex, nullptr));
+ pthread_cond_t cond;
+ ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+ ASSERT_EQ(0, pthread_mutex_lock(&mutex));
+ timespec ts;
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
- ts.tv_nsec += 1;
- ASSERT_EQ(0, pthread_mutex_timedlock(&m, &ts));
-
- ASSERT_EQ(0, pthread_mutex_unlock(&m));
- ASSERT_EQ(0, pthread_mutex_destroy(&m));
+ ASSERT_EQ(ETIMEDOUT, pthread_cond_timedwait(&cond, &mutex, &ts));
+ ts.tv_nsec = -1;
+ ASSERT_EQ(EINVAL, pthread_cond_timedwait(&cond, &mutex, &ts));
+ ts.tv_nsec = NS_PER_S;
+ ASSERT_EQ(EINVAL, pthread_cond_timedwait(&cond, &mutex, &ts));
+ ts.tv_nsec = NS_PER_S - 1;
+ ts.tv_sec = -1;
+ ASSERT_EQ(ETIMEDOUT, pthread_cond_timedwait(&cond, &mutex, &ts));
+ ASSERT_EQ(0, pthread_mutex_unlock(&mutex));
}
TEST(pthread, pthread_attr_getstack__main_thread) {
@@ -1303,8 +1406,14 @@
}
#if defined(__BIONIC__)
+static pthread_mutex_t pthread_gettid_np_mutex = PTHREAD_MUTEX_INITIALIZER;
+
static void* pthread_gettid_np_helper(void* arg) {
*reinterpret_cast<pid_t*>(arg) = gettid();
+
+ // Wait for our parent to call pthread_gettid_np on us before exiting.
+ pthread_mutex_lock(&pthread_gettid_np_mutex);
+ pthread_mutex_unlock(&pthread_gettid_np_mutex);
return NULL;
}
#endif
@@ -1313,12 +1422,18 @@
#if defined(__BIONIC__)
ASSERT_EQ(gettid(), pthread_gettid_np(pthread_self()));
+ // Ensure the other thread doesn't exit until after we've called
+ // pthread_gettid_np on it.
+ pthread_mutex_lock(&pthread_gettid_np_mutex);
+
pid_t t_gettid_result;
pthread_t t;
pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result);
pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
+ // Release the other thread and wait for it to exit.
+ pthread_mutex_unlock(&pthread_gettid_np_mutex);
pthread_join(t, NULL);
ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
@@ -1540,6 +1655,35 @@
#endif
}
+TEST(pthread, pthread_mutex_timedlock) {
+ pthread_mutex_t m;
+ ASSERT_EQ(0, pthread_mutex_init(&m, nullptr));
+
+ // If the mutex is already locked, pthread_mutex_timedlock should time out.
+ ASSERT_EQ(0, pthread_mutex_lock(&m));
+
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ASSERT_EQ(ETIMEDOUT, pthread_mutex_timedlock(&m, &ts));
+ ts.tv_nsec = -1;
+ ASSERT_EQ(EINVAL, pthread_mutex_timedlock(&m, &ts));
+ ts.tv_nsec = NS_PER_S;
+ ASSERT_EQ(EINVAL, pthread_mutex_timedlock(&m, &ts));
+ ts.tv_nsec = NS_PER_S - 1;
+ ts.tv_sec = -1;
+ ASSERT_EQ(ETIMEDOUT, pthread_mutex_timedlock(&m, &ts));
+
+ // If the mutex is unlocked, pthread_mutex_timedlock should succeed.
+ ASSERT_EQ(0, pthread_mutex_unlock(&m));
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ ASSERT_EQ(0, pthread_mutex_timedlock(&m, &ts));
+
+ ASSERT_EQ(0, pthread_mutex_unlock(&m));
+ ASSERT_EQ(0, pthread_mutex_destroy(&m));
+}
+
class StrictAlignmentAllocator {
public:
void* allocate(size_t size, size_t alignment) {
@@ -1653,3 +1797,128 @@
kill(getpid(), SIGUSR1);
ASSERT_TRUE(signal_handler_on_altstack_done);
}
+
+TEST(pthread, pthread_barrierattr_smoke) {
+ pthread_barrierattr_t attr;
+ ASSERT_EQ(0, pthread_barrierattr_init(&attr));
+ int pshared;
+ ASSERT_EQ(0, pthread_barrierattr_getpshared(&attr, &pshared));
+ ASSERT_EQ(PTHREAD_PROCESS_PRIVATE, pshared);
+ ASSERT_EQ(0, pthread_barrierattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));
+ ASSERT_EQ(0, pthread_barrierattr_getpshared(&attr, &pshared));
+ ASSERT_EQ(PTHREAD_PROCESS_SHARED, pshared);
+ ASSERT_EQ(0, pthread_barrierattr_destroy(&attr));
+}
+
+struct BarrierTestHelperArg {
+ std::atomic<pid_t> tid;
+ pthread_barrier_t* barrier;
+ size_t iteration_count;
+};
+
+static void BarrierTestHelper(BarrierTestHelperArg* arg) {
+ arg->tid = gettid();
+ for (size_t i = 0; i < arg->iteration_count; ++i) {
+ ASSERT_EQ(0, pthread_barrier_wait(arg->barrier));
+ }
+}
+
+TEST(pthread, pthread_barrier_smoke) {
+ const size_t BARRIER_ITERATION_COUNT = 10;
+ const size_t BARRIER_THREAD_COUNT = 10;
+ pthread_barrier_t barrier;
+ ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, BARRIER_THREAD_COUNT + 1));
+ std::vector<pthread_t> threads(BARRIER_THREAD_COUNT);
+ std::vector<BarrierTestHelperArg> args(threads.size());
+ for (size_t i = 0; i < threads.size(); ++i) {
+ args[i].tid = 0;
+ args[i].barrier = &barrier;
+ args[i].iteration_count = BARRIER_ITERATION_COUNT;
+ ASSERT_EQ(0, pthread_create(&threads[i], nullptr,
+ reinterpret_cast<void* (*)(void*)>(BarrierTestHelper), &args[i]));
+ }
+ for (size_t iteration = 0; iteration < BARRIER_ITERATION_COUNT; ++iteration) {
+ for (size_t i = 0; i < threads.size(); ++i) {
+ WaitUntilThreadSleep(args[i].tid);
+ }
+ ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier));
+ }
+ for (size_t i = 0; i < threads.size(); ++i) {
+ ASSERT_EQ(0, pthread_join(threads[i], nullptr));
+ }
+ ASSERT_EQ(0, pthread_barrier_destroy(&barrier));
+}
+
+TEST(pthread, pthread_barrier_destroy) {
+ pthread_barrier_t barrier;
+ ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, 2));
+ pthread_t thread;
+ BarrierTestHelperArg arg;
+ arg.tid = 0;
+ arg.barrier = &barrier;
+ arg.iteration_count = 1;
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(BarrierTestHelper), &arg));
+ WaitUntilThreadSleep(arg.tid);
+ ASSERT_EQ(EBUSY, pthread_barrier_destroy(&barrier));
+ ASSERT_EQ(PTHREAD_BARRIER_SERIAL_THREAD, pthread_barrier_wait(&barrier));
+ // Verify if the barrier can be destroyed directly after pthread_barrier_wait().
+ ASSERT_EQ(0, pthread_barrier_destroy(&barrier));
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+#if defined(__BIONIC__)
+ ASSERT_EQ(EINVAL, pthread_barrier_destroy(&barrier));
+#endif
+}
+
+struct BarrierOrderingTestHelperArg {
+ pthread_barrier_t* barrier;
+ size_t* array;
+ size_t array_length;
+ size_t id;
+};
+
+void BarrierOrderingTestHelper(BarrierOrderingTestHelperArg* arg) {
+ const size_t ITERATION_COUNT = 10000;
+ for (size_t i = 1; i <= ITERATION_COUNT; ++i) {
+ arg->array[arg->id] = i;
+ int result = pthread_barrier_wait(arg->barrier);
+ ASSERT_TRUE(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD);
+ for (size_t j = 0; j < arg->array_length; ++j) {
+ ASSERT_EQ(i, arg->array[j]);
+ }
+ result = pthread_barrier_wait(arg->barrier);
+ ASSERT_TRUE(result == 0 || result == PTHREAD_BARRIER_SERIAL_THREAD);
+ }
+}
+
+TEST(pthread, pthread_barrier_check_ordering) {
+ const size_t THREAD_COUNT = 4;
+ pthread_barrier_t barrier;
+ ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, THREAD_COUNT));
+ size_t array[THREAD_COUNT];
+ std::vector<pthread_t> threads(THREAD_COUNT);
+ std::vector<BarrierOrderingTestHelperArg> args(THREAD_COUNT);
+ for (size_t i = 0; i < THREAD_COUNT; ++i) {
+ args[i].barrier = &barrier;
+ args[i].array = array;
+ args[i].array_length = THREAD_COUNT;
+ args[i].id = i;
+ ASSERT_EQ(0, pthread_create(&threads[i], nullptr,
+ reinterpret_cast<void* (*)(void*)>(BarrierOrderingTestHelper),
+ &args[i]));
+ }
+ for (size_t i = 0; i < THREAD_COUNT; ++i) {
+ ASSERT_EQ(0, pthread_join(threads[i], nullptr));
+ }
+}
+
+TEST(pthread, pthread_spinlock_smoke) {
+ pthread_spinlock_t lock;
+ ASSERT_EQ(0, pthread_spin_init(&lock, 0));
+ ASSERT_EQ(0, pthread_spin_trylock(&lock));
+ ASSERT_EQ(0, pthread_spin_unlock(&lock));
+ ASSERT_EQ(0, pthread_spin_lock(&lock));
+ ASSERT_EQ(EBUSY, pthread_spin_trylock(&lock));
+ ASSERT_EQ(0, pthread_spin_unlock(&lock));
+ ASSERT_EQ(0, pthread_spin_destroy(&lock));
+}
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
index e517f81..b65bfb8 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -117,6 +117,16 @@
ts.tv_nsec = -1;
ASSERT_EQ(-1, sem_timedwait(&s, &ts));
ASSERT_EQ(EINVAL, errno);
+ errno = 0;
+ ts.tv_nsec = NS_PER_S;
+ ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+ ASSERT_EQ(EINVAL, errno);
+
+ errno = 0;
+ ts.tv_nsec = NS_PER_S - 1;
+ ts.tv_sec = -1;
+ ASSERT_EQ(-1, sem_timedwait(&s, &ts));
+ ASSERT_EQ(ETIMEDOUT, errno);
ASSERT_EQ(0, sem_destroy(&s));
}
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index c95cbbd..7872567 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -30,6 +30,7 @@
#include <locale.h>
#include "TemporaryFile.h"
+#include "utils.h"
TEST(stdio_ext, __fbufsize) {
FILE* fp = fopen("/proc/version", "r");
@@ -140,3 +141,24 @@
ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
fclose(fp);
}
+
+static void LockingByCallerHelper(std::atomic<pid_t>* pid) {
+ *pid = gettid();
+ flockfile(stdout);
+ funlockfile(stdout);
+}
+
+TEST(stdio_ext, __fsetlocking_BYCALLER) {
+ // Check if users can use flockfile/funlockfile to protect stdio operations.
+ int old_state = __fsetlocking(stdout, FSETLOCKING_BYCALLER);
+ flockfile(stdout);
+ pthread_t thread;
+ std::atomic<pid_t> pid(0);
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(LockingByCallerHelper), &pid));
+ WaitUntilThreadSleep(pid);
+ funlockfile(stdout);
+
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+ __fsetlocking(stdout, old_state);
+}
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index b0e40fd..ddb6c77 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <sys/mman.h>
+#include <sys/user.h>
#include <sys/types.h>
#include <unistd.h>
@@ -215,3 +216,19 @@
ASSERT_EQ(0, munmap(map, pagesize));
}
+
+TEST(sys_mman, mremap) {
+ ASSERT_EQ(MAP_FAILED, mremap(nullptr, 0, 0, 0));
+}
+
+const size_t huge = size_t(PTRDIFF_MAX) + 1;
+
+TEST(sys_mman, mmap_PTRDIFF_MAX) {
+ ASSERT_EQ(MAP_FAILED, mmap(nullptr, huge, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+}
+
+TEST(sys_mman, mremap_PTRDIFF_MAX) {
+ void* map = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(MAP_FAILED, map);
+ ASSERT_EQ(MAP_FAILED, mremap(map, PAGE_SIZE, huge, MREMAP_MAYMOVE));
+}
diff --git a/tests/sys_resource_test.cpp b/tests/sys_resource_test.cpp
index 8cefc65..0b6b6ef 100644
--- a/tests/sys_resource_test.cpp
+++ b/tests/sys_resource_test.cpp
@@ -33,7 +33,8 @@
virtual void SetUp() {
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_));
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_));
- ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_));
+ ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, nullptr, &pr_l32_));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, nullptr, &pr_l64_));
}
void CheckResourceLimits();
@@ -41,21 +42,28 @@
protected:
rlimit l32_;
rlimit64 l64_;
+ rlimit pr_l32_;
rlimit64 pr_l64_;
};
void SysResourceTest::CheckResourceLimits() {
ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_));
ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_));
- ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_));
+ ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, nullptr, &pr_l32_));
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, nullptr, &pr_l64_));
+
+ ASSERT_EQ(l32_.rlim_cur, pr_l32_.rlim_cur);
ASSERT_EQ(l64_.rlim_cur, pr_l64_.rlim_cur);
+
if (l64_.rlim_cur == RLIM64_INFINITY) {
ASSERT_EQ(RLIM_INFINITY, l32_.rlim_cur);
} else {
ASSERT_EQ(l64_.rlim_cur, l32_.rlim_cur);
}
+ ASSERT_EQ(l32_.rlim_max, pr_l32_.rlim_max);
ASSERT_EQ(l64_.rlim_max, pr_l64_.rlim_max);
+
if (l64_.rlim_max == RLIM64_INFINITY) {
ASSERT_EQ(RLIM_INFINITY, l32_.rlim_max);
} else {
@@ -88,13 +96,16 @@
ASSERT_EQ(456U, l64_.rlim_cur);
}
-TEST_F(SysResourceTest, prlimit64) {
- pr_l64_.rlim_cur = pr_l64_.rlim_max;
- ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &pr_l64_, NULL));
+TEST_F(SysResourceTest, prlimit) {
+ pr_l32_.rlim_cur = pr_l32_.rlim_max;
+ ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, &pr_l32_, nullptr));
CheckResourceLimits();
- ASSERT_EQ(pr_l64_.rlim_max, pr_l64_.rlim_cur);
+ ASSERT_EQ(pr_l32_.rlim_max, pr_l32_.rlim_cur);
}
-TEST_F(SysResourceTest, prlimit) {
- // prlimit is prlimit64 on LP64 and unimplemented on 32-bit. So we only test prlimit64.
+TEST_F(SysResourceTest, prlimit64) {
+ pr_l64_.rlim_cur = pr_l64_.rlim_max;
+ ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &pr_l64_, nullptr));
+ CheckResourceLimits();
+ ASSERT_EQ(pr_l64_.rlim_max, pr_l64_.rlim_cur);
}
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index c7bfee6..09eac3f 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -41,9 +41,6 @@
return;
}
- old_pa = __system_property_area__;
- __system_property_area__ = NULL;
-
pa_dirname = dirname;
pa_filename = pa_dirname + "/__properties__";
@@ -57,9 +54,8 @@
return;
}
- __system_property_area__ = old_pa;
-
__system_property_set_filename(PROP_FILENAME);
+ __system_properties_init();
unlink(pa_filename.c_str());
rmdir(pa_dirname.c_str());
}
@@ -68,7 +64,6 @@
private:
std::string pa_dirname;
std::string pa_filename;
- void *old_pa;
};
static void foreach_test_callback(const prop_info *pi, void* cookie) {
diff --git a/tests/thread_local_test.cpp b/tests/thread_local_test.cpp
index aeba2ba..1422ed2 100644
--- a/tests/thread_local_test.cpp
+++ b/tests/thread_local_test.cpp
@@ -18,7 +18,8 @@
#include <stdint.h>
#include <string.h>
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__clang__) && \
+ (defined(__arm__) || defined(__aarch64__))
// Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
// Until that bug is fixed, disable optimization since
// it is not essential for this test.
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c685e94..a04c449 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -143,6 +143,44 @@
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
}
+TEST(time, strftime_null_tm_zone) {
+ // Netflix on Nexus Player wouldn't start (http://b/25170306).
+ struct tm t;
+ memset(&t, 0, sizeof(tm));
+
+ char buf[64];
+
+ setenv("TZ", "America/Los_Angeles", 1);
+ tzset();
+
+ t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
+ EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+ EXPECT_STREQ("<PST>", buf);
+
+#if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
+ t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
+ EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+ EXPECT_STREQ("<PDT>", buf);
+
+ t.tm_isdst = -123; // "and negative if the information is not available".
+ EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
+ EXPECT_STREQ("<>", buf);
+#endif
+
+ setenv("TZ", "UTC", 1);
+ tzset();
+
+ t.tm_isdst = 0;
+ EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
+ EXPECT_STREQ("<UTC>", buf);
+
+#if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
+ t.tm_isdst = 1; // UTC has no DST.
+ EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
+ EXPECT_STREQ("<>", buf);
+#endif
+}
+
TEST(time, strptime) {
setenv("TZ", "UTC", 1);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 0a97abc..5e06b1f 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -30,8 +30,8 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <base/file.h>
-#include <base/strings.h>
+#include <android-base/file.h>
+#include <android-base/strings.h>
#include "private/get_cpu_count_from_string.h"
diff --git a/tests/utils.h b/tests/utils.h
index 53cf6b6..a8f3441 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -18,6 +18,14 @@
#define __TEST_UTILS_H
#include <inttypes.h>
#include <sys/mman.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <string>
+#include <regex>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include "private/ScopeGuard.h"
@@ -82,4 +90,23 @@
}
};
+extern "C" pid_t gettid();
+
+static inline void WaitUntilThreadSleep(std::atomic<pid_t>& tid) {
+ while (tid == 0) {
+ usleep(1000);
+ }
+ std::string filename = android::base::StringPrintf("/proc/%d/stat", tid.load());
+ std::regex regex {R"(\s+S\s+)"};
+
+ while (true) {
+ std::string content;
+ ASSERT_TRUE(android::base::ReadFileToString(filename, &content));
+ if (std::regex_search(content, regex)) {
+ break;
+ }
+ usleep(1000);
+ }
+}
+
#endif
diff --git a/tests/utmp_test.cpp b/tests/utmp_test.cpp
index b61110d..0fa55c7 100644
--- a/tests/utmp_test.cpp
+++ b/tests/utmp_test.cpp
@@ -23,3 +23,9 @@
// This test just checks that we're exporting the symbol independently.
ASSERT_EQ(-1, login_tty(-1));
}
+
+TEST(utmp, setutent_getutent_endutent) {
+ setutent();
+ getutent();
+ endutent();
+}