Merge "Update kernel headers to v3.14."
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 0b0c47f..f330d7e 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -183,3 +183,29 @@
delete[] pinfo;
}
BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
+
+static void BM_property_serial(int iters, int nprops)
+{
+ StopBenchmarkTiming();
+
+ LocalPropertyTestState pa(nprops);
+
+ if (!pa.valid)
+ return;
+
+ srandom(iters * nprops);
+ const prop_info** pinfo = new const prop_info*[iters];
+
+ for (int i = 0; i < iters; i++) {
+ pinfo[i] = __system_property_find(pa.names[random() % nprops]);
+ }
+
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ __system_property_serial(pinfo[i]);
+ }
+ StopBenchmarkTiming();
+
+ delete[] pinfo;
+}
+BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
diff --git a/libc/Android.mk b/libc/Android.mk
index 078be59..5acdd6b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -107,8 +107,9 @@
bionic/clearenv.cpp \
bionic/clock.cpp \
bionic/clone.cpp \
- bionic/cmsg_nxthdr.cpp \
+ bionic/__cmsg_nxthdr.cpp \
bionic/connect.cpp \
+ bionic/ctype.cpp \
bionic/__cxa_guard.cpp \
bionic/__cxa_pure_virtual.cpp \
bionic/dirent.cpp \
@@ -205,10 +206,16 @@
bionic/socket.cpp \
bionic/stat.cpp \
bionic/statvfs.cpp \
+ bionic/strcoll_l.cpp \
bionic/strerror.cpp \
bionic/strerror_r.cpp \
+ bionic/strftime_l.cpp \
bionic/strsignal.cpp \
bionic/strtold.cpp \
+ bionic/strtold_l.cpp \
+ bionic/strtoll_l.cpp \
+ bionic/strtoull_l.cpp \
+ bionic/strxfrm_l.cpp \
bionic/stubs.cpp \
bionic/symlink.cpp \
bionic/sysconf.cpp \
@@ -491,6 +498,12 @@
-D_LIBC=1 \
-Wall -Wextra -Wunused \
+ifneq ($(TARGET_USES_LOGD),false)
+libc_common_cflags += -DTARGET_USES_LOGD
+endif
+
+use_clang := false
+
# Try to catch typical 32-bit assumptions that break with 64-bit pointers.
libc_common_cflags += \
-Werror=pointer-to-int-cast \
@@ -571,6 +584,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_stack_protector
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -608,6 +622,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes) $(LOCAL_PATH)/tzcode/
LOCAL_MODULE := libc_tzcode
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -642,6 +657,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_dns
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -670,6 +686,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_freebsd
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -699,6 +716,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_netbsd
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -729,6 +747,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_openbsd
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -759,6 +778,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_gdtoa
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -780,13 +800,10 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_bionic
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
-ifneq ($(TARGET_USES_LOGD),false)
-LOCAL_CFLAGS += -DTARGET_USES_LOGD
-endif
-
$(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))
include $(BUILD_STATIC_LIBRARY)
@@ -803,6 +820,7 @@
LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) := $(call all-S-files-under,arch-$(TARGET_2ND_ARCH)/syscalls)
endif
LOCAL_MODULE := libc_syscalls
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -810,6 +828,24 @@
# ========================================================
+# libc_aeabi.a
+# This is an LP32 ARM-only library that needs to be built with -fno-builtin
+# to avoid infinite recursion. For the other architectures we just build an
+# empty library to keep this makefile simple.
+# ========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES_arm := arch-arm/bionic/__aeabi.c
+LOCAL_MODULE := libc_aeabi
+LOCAL_CLANG := $(use_clang)
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-builtin
+LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+
+include $(BUILD_STATIC_LIBRARY)
+
+# ========================================================
# libc_common.a
# ========================================================
@@ -821,6 +857,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_common
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_WHOLE_STATIC_LIBRARIES := \
libc_bionic \
@@ -834,6 +871,8 @@
libc_syscalls \
libc_tzcode \
+LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
+
ifeq ($(MALLOC_IMPL),jemalloc)
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
endif
@@ -874,6 +913,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_MODULE := libc_nomalloc
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -896,6 +936,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_malloc
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
include $(BUILD_STATIC_LIBRARY)
@@ -918,6 +959,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
@@ -946,6 +988,7 @@
bionic/NetdClient.cpp \
LOCAL_MODULE := libc
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_REQUIRED_MODULES := tzdata
@@ -1011,14 +1054,15 @@
LOCAL_SRC_FILES := \
bionic/debug_mapinfo.cpp \
bionic/debug_stacktrace.cpp \
+ bionic/libc_logging.cpp \
bionic/malloc_debug_leak.cpp \
bionic/malloc_debug_check.cpp \
LOCAL_MODULE := libc_malloc_debug_leak
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SHARED_LIBRARIES := libc libdl
-LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
@@ -1044,13 +1088,14 @@
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_SRC_FILES := \
- bionic/malloc_debug_qemu.cpp
+ bionic/libc_logging.cpp \
+ bionic/malloc_debug_qemu.cpp \
LOCAL_MODULE := libc_malloc_debug_qemu
+LOCAL_CLANG := $(use_clang)
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
LOCAL_SHARED_LIBRARIES := libc libdl
-LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
# Don't install on release build
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 47e436c..00be4ae 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -52,7 +52,6 @@
arch-arm/bionic/abort_arm.S \
arch-arm/bionic/atomics_arm.c \
arch-arm/bionic/__bionic_clone.S \
- arch-arm/bionic/eabi.c \
arch-arm/bionic/_exit_with_stack_teardown.S \
arch-arm/bionic/__get_sp.S \
arch-arm/bionic/libgcc_compat.c \
diff --git a/libc/arch-arm/bionic/eabi.c b/libc/arch-arm/bionic/__aeabi.c
similarity index 84%
rename from libc/arch-arm/bionic/eabi.c
rename to libc/arch-arm/bionic/__aeabi.c
index 5511ddd..3254f64 100644
--- a/libc/arch-arm/bionic/eabi.c
+++ b/libc/arch-arm/bionic/__aeabi.c
@@ -25,10 +25,19 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
+#if defined(__clang__)
+// clang interprets -fno-builtin more loosely than you might expect,
+// and thinks it's okay to still substitute builtins as long as they're
+// named __aeabi_* rather than __builtin_*, which causes infinite
+// recursion if we have the fortified memcpy visible in this file.
+#undef _FORTIFY_SOURCE
+#endif
+
#include <stddef.h>
#include <string.h>
-extern int __cxa_atexit(void (*)(void*), void*, void* );
+extern int __cxa_atexit(void (*)(void*), void*, void*);
/* The "C++ ABI for ARM" document states that static C++ constructors,
* which are called from the .init_array, should manually call
@@ -38,11 +47,9 @@
* variable from the shared object that contains the constructor/destructor
*/
-/* Make this a weak symbol to avoid a multiple definition error when linking
- * with libstdc++-v3. */
+// Make this a weak symbol to avoid a multiple definition error when linking with libstdc++-v3.
int __attribute__((weak))
-__aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle)
-{
+__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
return __cxa_atexit(destructor, object, dso_handle);
}
@@ -73,10 +80,10 @@
}
/*
- * __aeabi_memset has the order of its second and third arguments reversed.
+ * __aeabi_memset has the order of its second and third arguments reversed.
* This allows __aeabi_memclr to tail-call __aeabi_memset
*/
-
+
void __aeabi_memset8(void *dest, size_t n, int c) {
memset(dest, c, n);
}
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/__cmsg_nxthdr.cpp
similarity index 95%
rename from libc/bionic/cmsg_nxthdr.cpp
rename to libc/bionic/__cmsg_nxthdr.cpp
index 8a2b33e..f962788 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/__cmsg_nxthdr.cpp
@@ -37,6 +37,3 @@
}
return ptr;
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/ctype.cpp
similarity index 61%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/ctype.cpp
index 8a2b33e..3960d9d 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/ctype.cpp
@@ -26,17 +26,64 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <ctype.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+int isalnum_l(int c, locale_t) {
+ return isalnum(c);
}
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
+int isalpha_l(int c, locale_t) {
+ return isalpha(c);
+}
+
+int isascii_l(int c, locale_t) {
+ return isascii(c);
+}
+
+int isblank_l(int c, locale_t) {
+ return isblank(c);
+}
+
+int iscntrl_l(int c, locale_t) {
+ return iscntrl(c);
+}
+
+int isdigit_l(int c, locale_t) {
+ return isdigit(c);
+}
+
+int isgraph_l(int c, locale_t) {
+ return isgraph(c);
+}
+
+int islower_l(int c, locale_t) {
+ return islower(c);
+}
+
+int isprint_l(int c, locale_t) {
+ return isprint(c);
+}
+
+int ispunct_l(int c, locale_t) {
+ return ispunct(c);
+}
+
+int isspace_l(int c, locale_t) {
+ return isspace(c);
+}
+
+int isupper_l(int c, locale_t) {
+ return isupper(c);
+}
+
+int isxdigit_l(int c, locale_t) {
+ return isxdigit(c);
+}
+
+int toupper_l(int c, locale_t) {
+ return toupper(c);
+}
+
+int tolower_l(int c, locale_t) {
+ return tolower(c);
+}
diff --git a/libc/bionic/dlmalloc.h b/libc/bionic/dlmalloc.h
index e065687..46efa91 100644
--- a/libc/bionic/dlmalloc.h
+++ b/libc/bionic/dlmalloc.h
@@ -32,6 +32,8 @@
#define USE_SPIN_LOCKS 0
#define DEFAULT_MMAP_THRESHOLD (64U * 1024U)
+#define malloc_getpagesize getpagesize()
+
/* Export two symbols used by the VM. */
__BEGIN_DECLS
int dlmalloc_trim(size_t) __LIBC_ABI_PUBLIC__;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index d1fe960..e33d560 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -21,7 +21,7 @@
#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) {
return NULL;
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index e4e4c2e..1c63d4d 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -123,6 +123,7 @@
static unsigned g_malloc_debug_backlog = 100;
__LIBC_HIDDEN__ HashTable* g_hash_table;
+__LIBC_HIDDEN__ const MallocDebug* g_malloc_dispatch;
static inline void init_front_guard(hdr_t* hdr) {
memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
@@ -324,7 +325,7 @@
while (backlog_num > g_malloc_debug_backlog) {
hdr_t* gone = backlog_tail;
del_from_backlog_locked(gone);
- Malloc(free)(gone->base);
+ g_malloc_dispatch->free(gone->base);
}
}
@@ -336,7 +337,7 @@
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(malloc)(size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->malloc(size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -364,7 +365,7 @@
return NULL;
}
- void* base = Malloc(malloc)(sizeof(hdr_t) + size + sizeof(ftr_t));
+ void* base = g_malloc_dispatch->malloc(sizeof(hdr_t) + size + sizeof(ftr_t));
if (base != NULL) {
// Check that the actual pointer that will be returned is aligned
// properly.
@@ -461,7 +462,7 @@
user(hdr), bytes);
log_backtrace(bt, depth);
// just get a whole new allocation and leak the old one
- return Malloc(realloc)(0, bytes);
+ return g_malloc_dispatch->realloc(0, bytes);
// return realloc(user(hdr), bytes); // assuming it was allocated externally
}
}
@@ -474,15 +475,15 @@
if (hdr->base != hdr) {
// An allocation from memalign, so create another allocation and
// copy the data out.
- void* newMem = Malloc(malloc)(size);
+ void* newMem = g_malloc_dispatch->malloc(size);
if (newMem == NULL) {
return NULL;
}
memcpy(newMem, hdr, sizeof(hdr_t) + hdr->size);
- Malloc(free)(hdr->base);
+ g_malloc_dispatch->free(hdr->base);
hdr = static_cast<hdr_t*>(newMem);
} else {
- hdr = static_cast<hdr_t*>(Malloc(realloc)(hdr, size));
+ hdr = static_cast<hdr_t*>(g_malloc_dispatch->realloc(hdr, size));
}
if (hdr) {
hdr->base = hdr;
@@ -501,7 +502,7 @@
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(calloc)(1, size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->calloc(1, size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -524,7 +525,7 @@
}
extern "C" struct mallinfo chk_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -538,7 +539,7 @@
}
extern "C" void* chk_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -547,7 +548,7 @@
}
extern "C" void* chk_valloc(size_t size) {
- return chk_memalign(sysconf(_SC_PAGESIZE), size);
+ return chk_memalign(getpagesize(), size);
}
static void ReportMemoryLeaks() {
@@ -584,8 +585,9 @@
}
}
-extern "C" bool malloc_debug_initialize(HashTable* hash_table) {
+extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
g_hash_table = hash_table;
+ g_malloc_dispatch = malloc_dispatch;
char debug_backlog[PROP_VALUE_MAX];
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 9399237..be16625 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -46,6 +46,16 @@
#include "private/ScopedPthreadMutexLocker.h"
+#if defined(USE_JEMALLOC)
+#include "jemalloc.h"
+#define Malloc(function) je_ ## function
+#elif defined(USE_DLMALLOC)
+#include "dlmalloc.h"
+#define Malloc(function) dl ## function
+#else
+#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
+#endif
+
// In a VM process, this is set to 1 after fork()ing out of zygote.
int gMallocLeakZygoteChild = 0;
@@ -408,7 +418,7 @@
dlclose(malloc_impl_handle);
return;
}
- if (!malloc_debug_initialize(&g_hash_table)) {
+ if (!malloc_debug_initialize(&g_hash_table, &__libc_malloc_default_dispatch)) {
dlclose(malloc_impl_handle);
return;
}
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index fb2f03d..5c73da3 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -51,17 +51,6 @@
#define MALLOC_ALIGNMENT ((size_t)(2 * sizeof(void *)))
#endif
-#ifdef USE_JEMALLOC
-#include "jemalloc.h"
-#define Malloc(function) je_ ## function
-#else
-#ifndef USE_DLMALLOC
-#error "Either one of USE_DLMALLOC or USE_JEMALLOC must be defined."
-#endif
-#include "dlmalloc.h"
-#define Malloc(function) dl ## function
-#endif
-
// =============================================================================
// Structures
// =============================================================================
@@ -116,7 +105,7 @@
#endif
};
-typedef bool (*MallocDebugInit)(HashTable*);
+typedef bool (*MallocDebugInit)(HashTable*, const MallocDebug*);
typedef void (*MallocDebugFini)(int);
// =============================================================================
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 308d40b..d9824f0 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -62,6 +62,7 @@
extern int gMallocLeakZygoteChild;
extern HashTable* g_hash_table;
+extern const MallocDebug* g_malloc_dispatch;
// =============================================================================
// stack trace functions
@@ -143,7 +144,7 @@
entry->allocations++;
} else {
// create a new entry
- entry = static_cast<HashEntry*>(Malloc(malloc)(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
+ entry = static_cast<HashEntry*>(g_malloc_dispatch->malloc(sizeof(HashEntry) + numEntries*sizeof(uintptr_t)));
if (!entry) {
return NULL;
}
@@ -208,11 +209,11 @@
#define CHK_SENTINEL_VALUE 0xeb
extern "C" void* fill_calloc(size_t n_elements, size_t elem_size) {
- return Malloc(calloc)(n_elements, elem_size);
+ return g_malloc_dispatch->calloc(n_elements, elem_size);
}
extern "C" void* fill_malloc(size_t bytes) {
- void* buffer = Malloc(malloc)(bytes);
+ void* buffer = g_malloc_dispatch->malloc(bytes);
if (buffer) {
memset(buffer, CHK_SENTINEL_VALUE, bytes);
}
@@ -220,17 +221,17 @@
}
extern "C" void fill_free(void* mem) {
- size_t bytes = Malloc(malloc_usable_size)(mem);
+ size_t bytes = g_malloc_dispatch->malloc_usable_size(mem);
memset(mem, CHK_FILL_FREE, bytes);
- Malloc(free)(mem);
+ g_malloc_dispatch->free(mem);
}
extern "C" void* fill_realloc(void* mem, size_t bytes) {
- size_t oldSize = Malloc(malloc_usable_size)(mem);
- void* newMem = Malloc(realloc)(mem, bytes);
+ size_t oldSize = g_malloc_dispatch->malloc_usable_size(mem);
+ void* newMem = g_malloc_dispatch->realloc(mem, bytes);
if (newMem) {
// If this is larger than before, fill the extra with our pattern.
- size_t newSize = Malloc(malloc_usable_size)(newMem);
+ size_t newSize = g_malloc_dispatch->malloc_usable_size(newMem);
if (newSize > oldSize) {
memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(newMem)+oldSize), CHK_FILL_FREE, newSize-oldSize);
}
@@ -239,7 +240,7 @@
}
extern "C" void* fill_memalign(size_t alignment, size_t bytes) {
- void* buffer = Malloc(memalign)(alignment, bytes);
+ void* buffer = g_malloc_dispatch->memalign(alignment, bytes);
if (buffer) {
memset(buffer, CHK_SENTINEL_VALUE, bytes);
}
@@ -249,11 +250,11 @@
extern "C" size_t fill_malloc_usable_size(const void* mem) {
// Since we didn't allocate extra bytes before or after, we can
// report the normal usable size here.
- return Malloc(malloc_usable_size)(mem);
+ return g_malloc_dispatch->malloc_usable_size(mem);
}
extern "C" struct mallinfo fill_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -267,7 +268,7 @@
}
extern "C" void* fill_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -276,7 +277,7 @@
}
extern "C" void* fill_valloc(size_t size) {
- return fill_memalign(sysconf(_SC_PAGESIZE), size);
+ return fill_memalign(getpagesize(), size);
}
// =============================================================================
@@ -298,7 +299,7 @@
return NULL;
}
- void* base = Malloc(malloc)(size);
+ void* base = g_malloc_dispatch->malloc(size);
if (base != NULL) {
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
@@ -342,11 +343,11 @@
entry->allocations--;
if (entry->allocations <= 0) {
remove_entry(entry);
- Malloc(free)(entry);
+ g_malloc_dispatch->free(entry);
}
// now free the memory!
- Malloc(free)(header);
+ g_malloc_dispatch->free(header);
} else {
debug_log("WARNING bad header guard: '0x%x'! and invalid entry: %p\n",
header->guard, header->entry);
@@ -452,7 +453,7 @@
return 0;
}
- size_t ret = Malloc(malloc_usable_size)(header);
+ size_t ret = g_malloc_dispatch->malloc_usable_size(header);
if (ret != 0) {
// The usable area starts at 'mem' and stops at 'header+ret'.
return reinterpret_cast<uintptr_t>(header) + ret - reinterpret_cast<uintptr_t>(mem);
@@ -462,7 +463,7 @@
}
extern "C" struct mallinfo leak_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -476,7 +477,7 @@
}
extern "C" void* leak_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
@@ -485,5 +486,5 @@
}
extern "C" void* leak_valloc(size_t size) {
- return leak_memalign(sysconf(_SC_PAGESIZE), size);
+ return leak_memalign(getpagesize(), size);
}
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index fd5161a..b3b604d 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -336,6 +336,9 @@
// Static data
// =============================================================================
+// The underlying malloc implementation to use to get memory.
+static const MallocDebug* g_malloc_dispatch = NULL;
+
/* Emulator's magic page address.
* This page (mapped on /dev/qemu_trace device) is used to fire up events
* in the emulator. */
@@ -595,7 +598,9 @@
* Return:
* 0 on success, or -1 on failure.
*/
-extern "C" bool malloc_debug_initialize(HashTable*) {
+extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_dispatch) {
+ g_malloc_dispatch = malloc_dispatch;
+
/* We will be using emulator's magic page to report memory allocation
* activities. In essence, what magic page does, it translates writes to
* the memory mapped spaces into writes to an I/O port that emulator
@@ -693,7 +698,7 @@
errno = ENOMEM;
return NULL;
}
- desc.ptr = Malloc(malloc)(size);
+ desc.ptr = g_malloc_dispatch->malloc(size);
if (desc.ptr == NULL) {
qemu_error_log("<libc_pid=%03u, pid=%03u> malloc(%zu): malloc(%zu) failed.",
malloc_pid, getpid(), bytes, size);
@@ -704,7 +709,7 @@
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
malloc_pid, getpid());
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
errno = ENOMEM;
return NULL;
} else {
@@ -726,7 +731,7 @@
if (mem == NULL) {
// Just let go NULL free
- Malloc(free)(mem);
+ g_malloc_dispatch->free(mem);
return;
}
@@ -757,7 +762,7 @@
} else {
log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
malloc_pid, getpid(), mem);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
}
}
@@ -816,7 +821,7 @@
total_elements++;
desc.suffix_size += (elem_size - total_size);
}
- desc.ptr = Malloc(calloc)(total_elements, elem_size);
+ desc.ptr = g_malloc_dispatch->calloc(total_elements, elem_size);
if (desc.ptr == NULL) {
error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu(%zu), %zu) (prx=%u, sfx=%u) failed.",
malloc_pid, getpid(), n_elements, total_elements, elem_size,
@@ -827,7 +832,7 @@
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%zu(%zu), %zu): notify_malloc failed for ",
malloc_pid, getpid(), n_elements, total_elements, elem_size);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
errno = ENOMEM;
return NULL;
} else {
@@ -905,7 +910,7 @@
errno = ENOMEM;
return NULL;
}
- new_desc.ptr = Malloc(malloc)(new_size);
+ new_desc.ptr = g_malloc_dispatch->malloc(new_size);
if (new_desc.ptr == NULL) {
log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): malloc(%zu) failed on ",
malloc_pid, getpid(), mem, bytes, new_size);
@@ -924,7 +929,7 @@
log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) notify_malloc failed -> ",
malloc_pid, getpid(), mem, bytes);
log_mdesc(error, &cur_desc, " <- ");
- Malloc(free)(new_desc.ptr);
+ g_malloc_dispatch->free(new_desc.ptr);
errno = ENOMEM;
return NULL;
}
@@ -940,11 +945,11 @@
/* Since we registered new decriptor with the emulator, we need
* to unregister it before freeing newly allocated block. */
notify_qemu_free(mallocdesc_user_ptr(&new_desc));
- Malloc(free)(new_desc.ptr);
+ g_malloc_dispatch->free(new_desc.ptr);
errno = ENOMEM;
return NULL;
}
- Malloc(free)(cur_desc.ptr);
+ g_malloc_dispatch->free(cur_desc.ptr);
log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) -> ",
malloc_pid, getpid(), mem, bytes);
@@ -985,7 +990,7 @@
return NULL;
}
- desc.ptr = Malloc(memalign)(desc.prefix_size, size);
+ desc.ptr = g_malloc_dispatch->memalign(desc.prefix_size, size);
if (desc.ptr == NULL) {
error_log("<libc_pid=%03u, pid=%03u> memalign(%zx, %zu): malloc(%zu) failed.",
malloc_pid, getpid(), alignment, bytes, size);
@@ -994,7 +999,7 @@
if (notify_qemu_malloc(&desc)) {
log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%zx, %zu): notify_malloc failed for ",
malloc_pid, getpid(), alignment, bytes);
- Malloc(free)(desc.ptr);
+ g_malloc_dispatch->free(desc.ptr);
return NULL;
}
@@ -1032,7 +1037,7 @@
}
extern "C" struct mallinfo qemu_instrumented_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -1048,7 +1053,7 @@
}
extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
- size_t pagesize = sysconf(_SC_PAGESIZE);
+ size_t pagesize = getpagesize();
size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
@@ -1059,5 +1064,5 @@
}
extern "C" void* qemu_instrumented_valloc(size_t size) {
- return qemu_instrumented_memalign(sysconf(_SC_PAGESIZE), size);
+ return qemu_instrumented_memalign(getpagesize(), size);
}
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 2ded22b..174e308 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -41,23 +41,12 @@
#include "private/ErrnoRestorer.h"
#include "private/ScopedPthreadMutexLocker.h"
-// Used by gdb to track thread creation. See libthread_db.
-#ifdef __i386__
-extern "C" __attribute__((noinline)) __attribute__((fastcall)) void _thread_created_hook(pid_t) {}
-#else
-extern "C" __attribute__((noinline)) void _thread_created_hook(pid_t) {}
-#endif
-
// x86 uses segment descriptors rather than a direct pointer to TLS.
#if __i386__
#include <asm/ldt.h>
extern "C" __LIBC_HIDDEN__ void __init_user_desc(struct user_desc*, int, void*);
#endif
-static pthread_mutex_t g_pthread_stack_creation_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static pthread_mutex_t g_debugger_notification_lock = PTHREAD_MUTEX_INITIALIZER;
-
extern "C" int __isthreaded;
// This code is used both by each new pthread and the code that initializes the main thread.
@@ -113,8 +102,6 @@
}
static void* __create_thread_stack(pthread_internal_t* thread) {
- ScopedPthreadMutexLocker lock(&g_pthread_stack_creation_lock);
-
// Create a new private anonymous map.
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
@@ -258,12 +245,6 @@
return init_errno;
}
- // Notify any debuggers about the new thread.
- {
- ScopedPthreadMutexLocker debugger_locker(&g_debugger_notification_lock);
- _thread_created_hook(thread->tid);
- }
-
// Publish the pthread_t and unlock the mutex to let the new thread start running.
*thread_out = reinterpret_cast<pthread_t>(thread);
pthread_mutex_unlock(&thread->startup_handshake_mutex);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strcoll_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strcoll_l.cpp
index 8a2b33e..7d7c28b 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strcoll_l.cpp
@@ -26,17 +26,8 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <string.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+int strcoll_l(const char *s1, const char *s2, locale_t) {
+ return strcoll(s1, s2);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index 5f2d362..1e57cc0 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -8,6 +8,7 @@
#include <string.h>
#include "private/ErrnoRestorer.h"
+#include "private/libc_logging.h"
struct Pair {
int code;
@@ -49,9 +50,9 @@
const char* error_name = __strerror_lookup(error_number);
if (error_name != NULL) {
- length = snprintf(buf, buf_len, "%s", error_name);
+ length = strlcpy(buf, error_name, buf_len);
} else {
- length = snprintf(buf, buf_len, "Unknown error %d", error_number);
+ length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number);
}
if (length >= buf_len) {
errno_restorer.override(ERANGE);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strftime_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strftime_l.cpp
index 8a2b33e..fb01da5 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strftime_l.cpp
@@ -26,17 +26,9 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <time.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+size_t strftime_l(char *s, size_t max, const char *format, const struct tm *tm,
+ locale_t) {
+ return strftime(s, max, format, tm);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtold_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtold_l.cpp
index 8a2b33e..4b230b9 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtold_l.cpp
@@ -26,17 +26,8 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <stdlib.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+long double strtold_l(const char *nptr, char **endptr, locale_t) {
+ return strtold(nptr, endptr);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtoll_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtoll_l.cpp
index 8a2b33e..05fb760 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtoll_l.cpp
@@ -26,17 +26,8 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <stdlib.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+long long strtoll_l(const char *nptr, char **endptr, size_t base, locale_t) {
+ return strtoll(nptr, endptr, base);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strtoull_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strtoull_l.cpp
index 8a2b33e..ba0bc6a 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strtoull_l.cpp
@@ -26,17 +26,9 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <stdlib.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+unsigned long long strtoull_l(const char *nptr, char **endptr, size_t base,
+ locale_t) {
+ return strtoull(nptr, endptr, base);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/strxfrm_l.cpp
similarity index 76%
copy from libc/bionic/cmsg_nxthdr.cpp
copy to libc/bionic/strxfrm_l.cpp
index 8a2b33e..afe3b96 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/strxfrm_l.cpp
@@ -26,17 +26,8 @@
* SUCH DAMAGE.
*/
-#include <sys/socket.h>
+#include <string.h>
-cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
- cmsghdr* ptr;
- ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
- size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
- if (len > msg->msg_controllen) {
- return NULL;
- }
- return ptr;
+size_t strxfrm_l(char *dest, const char *src, size_t n, locale_t) {
+ return strxfrm(dest, src, n);
}
-
-// TODO: remove after NDK refresh.
-__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 9b025df..0937e9c 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -469,5 +469,6 @@
// Portable code should use sysconf(_SC_PAGE_SIZE) directly instead.
int getpagesize() {
- return sysconf(_SC_PAGE_SIZE);
+ // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat.
+ return PAGE_SIZE;
}
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index acb2761..ecb8b33 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -219,3 +219,25 @@
size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
}
+
+int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
+ return wcscoll(ws1, ws2);
+}
+
+size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
+ return wcsxfrm(dest, src, n);
+}
+
+long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
+ locale_t) {
+ return wcstoll(nptr, endptr, base);
+}
+
+unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
+ size_t base, locale_t) {
+ return wcstoull(nptr, endptr, base);
+}
+
+long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
+ return wcstold(nptr, endptr);
+}
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index 673402d..f2d7861 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#include <wctype.h>
// TODO: these only work for the ASCII range; rewrite to dlsym icu4c? http://b/14499654
@@ -46,6 +47,19 @@
int iswupper(wint_t wc) { return isupper(wc); }
int iswxdigit(wint_t wc) { return isxdigit(wc); }
+int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
+int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
+int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
+int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
+int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
+int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
+int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
+int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
+int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
+int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
+int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
+int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
+
int iswctype(wint_t wc, wctype_t char_class) {
switch (char_class) {
case WC_TYPE_ALNUM: return iswalnum(wc);
@@ -64,9 +78,16 @@
}
}
+int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
+ return iswctype(wc, char_class);
+}
+
wint_t towlower(wint_t wc) { return tolower(wc); }
wint_t towupper(wint_t wc) { return toupper(wc); }
+int towupper_l(int c, locale_t) { return towupper(c); }
+int towlower_l(int c, locale_t) { return towlower(c); }
+
wctype_t wctype(const char* property) {
static const char* const properties[WC_TYPE_MAX] = {
"<invalid>",
@@ -81,6 +102,10 @@
return static_cast<wctype_t>(0);
}
+wctype_t wctype_l(const char* property, locale_t) {
+ return wctype(property);
+}
+
int wcwidth(wchar_t wc) {
return (wc > 0);
}
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 6e97326..19b1adf 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -41,6 +41,7 @@
#define _CTYPE_H_
#include <sys/cdefs.h>
+#include <xlocale.h>
#define _CTYPE_U 0x01
#define _CTYPE_L 0x02
@@ -72,6 +73,22 @@
int tolower(int);
int toupper(int);
+int isalnum_l(int, locale_t);
+int isalpha_l(int, locale_t);
+int isascii_l(int, locale_t);
+int isblank_l(int, locale_t);
+int iscntrl_l(int, locale_t);
+int isdigit_l(int, locale_t);
+int isgraph_l(int, locale_t);
+int islower_l(int, locale_t);
+int isprint_l(int, locale_t);
+int ispunct_l(int, locale_t);
+int isspace_l(int, locale_t);
+int isupper_l(int, locale_t);
+int isxdigit_l(int, locale_t);
+int tolower_l(int, locale_t);
+int toupper_l(int, locale_t);
+
#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE > 200112 \
|| __XPG_VISIBLE > 600
int isblank(int);
diff --git a/libc/include/err.h b/libc/include/err.h
index aad1f59..ca62c9e 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -33,50 +33,25 @@
*/
#ifndef _ERR_H_
-#define _ERR_H_
+#define _ERR_H_
#include <sys/cdefs.h>
#include <sys/types.h>
__BEGIN_DECLS
-__noreturn void err(int, const char *, ...)
- __printflike(2, 3);
-__noreturn void verr(int, const char *, __va_list)
- __printflike(2, 0);
-__noreturn void errx(int, const char *, ...)
- __printflike(2, 3);
-__noreturn void verrx(int, const char *, __va_list)
- __printflike(2, 0);
-void warn(const char *, ...)
- __printflike(1, 2);
-void vwarn(const char *, __va_list)
- __printflike(1, 0);
-void warnx(const char *, ...)
- __printflike(1, 2);
-void vwarnx(const char *, __va_list)
- __printflike(1, 0);
+/* printf's format string isn't nullable; the err family's one is,
+ * so we can't use __errlike here. */
+#define __errlike(x, y) __attribute__((__format__(printf, x, y)))
-/*
- * The _* versions are for use in library functions so user-defined
- * versions of err*,warn* do not get used.
- */
-__noreturn void _err(int, const char *, ...)
- __printflike(2, 3);
-__noreturn void _verr(int, const char *, __va_list)
- __printflike(2, 0);
-__noreturn void _errx(int, const char *, ...)
- __printflike(2, 3);
-__noreturn void _verrx(int, const char *, __va_list)
- __printflike(2, 0);
-void _warn(const char *, ...)
- __printflike(1, 2);
-void _vwarn(const char *, __va_list)
- __printflike(1, 0);
-void _warnx(const char *, ...)
- __printflike(1, 2);
-void _vwarnx(const char *, __va_list)
- __printflike(1, 0);
+__noreturn void err(int, const char *, ...) __errlike(2, 3);
+__noreturn void verr(int, const char *, __va_list) __errlike(2, 0);
+__noreturn void errx(int, const char *, ...) __errlike(2, 3);
+__noreturn void verrx(int, const char *, __va_list) __errlike(2, 0);
+void warn(const char *, ...) __errlike(1, 2);
+void vwarn(const char *, __va_list) __errlike(1, 0);
+void warnx(const char *, ...) __errlike(1, 2);
+void vwarnx(const char *, __va_list) __errlike(1, 0);
__END_DECLS
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 62b7a67..0dac650 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -75,6 +75,10 @@
extern float strtof(const char*, char**) __LIBC_ABI_PUBLIC__;
extern long double strtold(const char*, char**) __LIBC_ABI_PUBLIC__;
+extern long double strtold_l(const char *, char **, locale_t) __LIBC_ABI_PUBLIC__;
+extern long long strtoll_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+extern unsigned long long strtoull_l(const char *, char **, size_t, locale_t) __LIBC_ABI_PUBLIC__;
+
extern int atoi(const char*) __purefunc;
extern long atol(const char*) __purefunc;
extern long long atoll(const char*) __purefunc;
diff --git a/libc/include/string.h b/libc/include/string.h
index 7727c0e..af1c0c1 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <stddef.h>
#include <malloc.h>
+#include <xlocale.h>
__BEGIN_DECLS
@@ -88,6 +89,9 @@
extern int strcoll(const char *, const char *) __purefunc;
extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
+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(__BIONIC_FORTIFY)
__errordecl(__memcpy_dest_size_error, "memcpy: prevented write past end of buffer");
diff --git a/libc/include/time.h b/libc/include/time.h
index 0587a2d..34a53b2 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/time.h>
+#include <xlocale.h>
__BEGIN_DECLS
@@ -75,6 +76,7 @@
extern char* strptime(const char*, const char*, struct tm*) __LIBC_ABI_PUBLIC__;
extern size_t strftime(char*, size_t, const char*, const struct tm*) __LIBC_ABI_PUBLIC__;
+extern size_t strftime_l(char *, size_t, const char *, const struct tm *, locale_t) __LIBC_ABI_PUBLIC__;
extern char* ctime(const time_t*) __LIBC_ABI_PUBLIC__;
extern char* ctime_r(const time_t*, char*) __LIBC_ABI_PUBLIC__;
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 014fed3..1898c7e 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -151,6 +151,13 @@
extern int wprintf(const wchar_t *, ...);
extern int wscanf(const wchar_t *, ...);
+extern long long wcstoll_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern unsigned long long wcstoull_l(const wchar_t *, wchar_t **, size_t, locale_t);
+extern long double wcstold_l(const wchar_t *, wchar_t **, locale_t );
+
+extern int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
+extern size_t wcsxfrm_l(wchar_t *, const wchar_t *, size_t, locale_t);
+
extern size_t wcslcat(wchar_t*, const wchar_t*, size_t);
extern size_t wcslcpy(wchar_t*, const wchar_t*, size_t);
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index b5f18a0..1a4a05e 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -1 +1,56 @@
+/*
+ * 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 _WCTYPE_H_
+#define _WCTYPE_H_
+
#include <wchar.h>
+
+__BEGIN_DECLS
+
+extern int iswalnum_l(wint_t, locale_t);
+extern int iswalpha_l(wint_t, locale_t);
+extern int iswblank_l(wint_t, locale_t);
+extern int iswcntrl_l(wint_t, locale_t);
+extern int iswdigit_l(wint_t, locale_t);
+extern int iswgraph_l(wint_t, locale_t);
+extern int iswlower_l(wint_t, locale_t);
+extern int iswprint_l(wint_t, locale_t);
+extern int iswpunct_l(wint_t, locale_t);
+extern int iswspace_l(wint_t, locale_t);
+extern int iswupper_l(wint_t, locale_t);
+extern int iswxdigit_l(wint_t, locale_t);
+extern int towlower_l(int, locale_t);
+extern int towupper_l(int, locale_t);
+
+extern int iswctype_l(wint_t, wctype_t, locale_t);
+extern wctype_t wctype_l(const char*, locale_t);
+
+__END_DECLS
+
+#endif /* _WCTYPE_H_ */
diff --git a/libc/private/libc_logging.h b/libc/private/libc_logging.h
index 7dd97a4..35c756b 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -88,7 +88,7 @@
//
// Formatting routines for the C library's internal debugging.
-// Unlike the usual alternatives, these don't allocate.
+// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio.
//
__LIBC_HIDDEN__ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...)
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 05f2faa..e10238b 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -103,7 +103,7 @@
{
struct atexit *p = __atexit;
struct atexit_fn *fnp;
- size_t pgsize = sysconf(_SC_PAGESIZE);
+ size_t pgsize = getpagesize();
int ret = -1;
if (pgsize < sizeof(*p))
@@ -219,7 +219,7 @@
__atexit_register_cleanup(void (*func)(void))
{
struct atexit *p;
- size_t pgsize = sysconf(_SC_PAGESIZE);
+ size_t pgsize = getpagesize();
if (pgsize < sizeof(*p))
return;
@@ -248,4 +248,3 @@
unlock:
_ATEXIT_UNLOCK();
}
-
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
index 3dcb210..6b69a5a 100755
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -31,8 +31,8 @@
print 'Found bionic in %s ...' % bionic_dir
# Find the icu4c directory.
-icu_dir = os.path.realpath('%s/../external/icu4c' % bionic_dir)
-CheckDirExists(icu_dir, 'external/icu4c')
+icu_dir = os.path.realpath('%s/../external/icu/icu4c/source' % bionic_dir)
+CheckDirExists(icu_dir, 'external/icu/icu4c/source')
print 'Found icu in %s ...' % icu_dir