Merge "Revert "Hide _tolower_tab_ and _toupper_tab_ on LP64.""
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 625d789..d1fe960 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,13 +14,19 @@
* limitations under the License.
*/
+#include <sys/param.h>
#include <unistd.h>
#include "jemalloc.h"
+#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- return je_memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
+ if (size < bytes) {
+ return NULL;
+ }
+ return je_memalign(pagesize, size);
}
#ifdef je_memalign
@@ -31,11 +37,9 @@
// but this is not true. Both glibc and dlmalloc round up to the next power
// of 2, so we'll do the same.
void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
- unsigned int power_of_2 = static_cast<unsigned int>(boundary);
- if (power_of_2 != 0) {
- power_of_2 = 1UL << (sizeof(unsigned int)*8 - 1 - __builtin_clz(power_of_2));
- if (power_of_2 != boundary) {
- boundary = power_of_2 << 1;
+ if (boundary != 0) {
+ if (!powerof2(boundary)) {
+ boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
}
} else {
boundary = 1;
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index faf61bf..e4e4c2e 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
#include <sys/types.h>
@@ -47,8 +48,9 @@
#include "debug_mapinfo.h"
#include "debug_stacktrace.h"
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
#define MAX_BACKTRACE_DEPTH 16
@@ -350,8 +352,8 @@
}
// Make the alignment a power of two.
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -526,7 +528,7 @@
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -537,7 +539,7 @@
extern "C" void* chk_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 2cc38cc..308d40b 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
@@ -48,6 +49,7 @@
#include "debug_stacktrace.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
@@ -255,7 +257,7 @@
}
extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -266,7 +268,7 @@
extern "C" void* fill_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
@@ -401,8 +403,8 @@
}
// need to make sure it's a power of two
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -464,7 +466,7 @@
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -475,7 +477,7 @@
extern "C" void* leak_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index 9b3bb55..fd5161a 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -47,11 +47,13 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
/* This file should be included into the build only when
* MALLOC_QEMU_INSTRUMENT macro is defined. */
@@ -970,8 +972,8 @@
// size.
if (alignment < DEFAULT_PREFIX_SIZE) {
alignment = DEFAULT_PREFIX_SIZE;
- } else if (alignment & (alignment - 1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ } else if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
desc.prefix_size = alignment;
desc.requested_bytes = bytes;
@@ -1047,7 +1049,7 @@
extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
malloc_pid, getpid(), bytes, size);
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index c4cb262..c83b5a0 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -33,6 +33,7 @@
#include "pthread_internal.h"
+#include "private/bionic_macros.h"
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
#include "private/libc_logging.h"
@@ -183,8 +184,8 @@
}
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
- thread->attr.stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
- thread->attr.guard_size = (thread->attr.guard_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+ thread->attr.stack_size = BIONIC_ALIGN(thread->attr.stack_size, PAGE_SIZE);
+ thread->attr.guard_size = BIONIC_ALIGN(thread->attr.guard_size, PAGE_SIZE);
if (thread->attr.stack_base == NULL) {
// The caller didn't provide a stack, so allocate one.
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 7618586..a564c39 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -55,9 +55,6 @@
#include "private/bionic_futex.h"
#include "private/bionic_macros.h"
-#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
-
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
@@ -301,7 +298,7 @@
static void *allocate_obj(const size_t size, uint32_t *const off)
{
prop_area *pa = __system_property_area__;
- const size_t aligned = ALIGN(size, sizeof(uint32_t));
+ const size_t aligned = BIONIC_ALIGN(size, sizeof(uint32_t));
if (pa->bytes_used + aligned > pa_data_size) {
return NULL;
}
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 34da501..a3a6985 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -33,4 +33,10 @@
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
+#define BIONIC_ALIGN(value, alignment) \
+ (((value) + (alignment) - 1) & ~((alignment) - 1))
+
+#define BIONIC_ROUND_UP_POWER_OF_2(value) \
+ (1UL << (sizeof(value) * 8 - 1 - __builtin_clz(value)))
+
#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index b52013f..56a61be 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/limits.h>
+#include "bionic_macros.h"
#include "__get_tls.h"
__BEGIN_DECLS
@@ -84,8 +85,6 @@
#define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
#endif
-#define BIONIC_ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
/*
* Maximum number of elements in the TLS array.
* This includes space for pthread keys and our own internal slots.
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index c607206..05f2faa 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -37,7 +37,6 @@
#include "atexit.h"
#include "private/thread_private.h"
-int __atexit_invalid = 1;
struct atexit *__atexit;
/*
@@ -131,8 +130,6 @@
sizeof(p->fns[0]);
p->next = __atexit;
__atexit = p;
- if (__atexit_invalid)
- __atexit_invalid = 0;
}
fnp = &p->fns[p->ind++];
fnp->cxa_func = func;
@@ -159,8 +156,6 @@
int n, pgsize = getpagesize(), original_ind;
static int call_depth;
- if (__atexit_invalid)
- return;
_ATEXIT_LOCK();
call_depth++;
diff --git a/libc/stdlib/atexit.h b/libc/stdlib/atexit.h
index 2e88ad6..b530ade 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/stdlib/atexit.h
@@ -45,8 +45,7 @@
__BEGIN_DECLS
-extern int __atexit_invalid;
-extern struct atexit *__atexit; /* points to head of LIFO stack */
+__LIBC_HIDDEN__ extern struct atexit *__atexit; /* points to head of LIFO stack */
int __cxa_atexit(void (*)(void *), void *, void *);
void __cxa_finalize(void *);
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6d63ad6..0b60ef5 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -118,7 +118,7 @@
if (sym != NULL) {
unsigned bind = ELF_ST_BIND(sym->st_info);
- if (bind == STB_GLOBAL && sym->st_shndx != 0) {
+ if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
return reinterpret_cast<void*>(sym->st_value + found->load_bias);
}
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 49cbb7d..8b89183 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -254,6 +254,18 @@
ASSERT_TRUE(addr != NULL);
}
+TEST(dlfcn, dlsym_weak_func) {
+ dlerror();
+ void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW);
+ ASSERT_TRUE(handle != NULL);
+
+ int (*weak_func)();
+ weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
+ ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror();
+ EXPECT_EQ(42, weak_func());
+ dlclose(handle);
+}
+
TEST(dlfcn, dlopen_symlink) {
void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index e75582d..67ea562 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -103,3 +103,15 @@
build_type := host
include $(TEST_PATH)/Android.build.mk
+# -----------------------------------------------------------------------------
+# Library with weak function
+# -----------------------------------------------------------------------------
+libtest_dlsym_weak_func_src_files := \
+ dlsym_weak_function.cpp
+
+module := libtest_dlsym_weak_func
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+build_type := host
+include $(TEST_PATH)/Android.build.mk
diff --git a/tests/libs/dlsym_weak_function.cpp b/tests/libs/dlsym_weak_function.cpp
new file mode 100644
index 0000000..e38f2b8
--- /dev/null
+++ b/tests/libs/dlsym_weak_function.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int __attribute__((weak)) weak_func() {
+ return 42;
+}
+