Merge "Update NOTICE files." into mnc-dev
diff --git a/libc/Android.mk b/libc/Android.mk
index 4a20b3f..9679494 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -1388,11 +1388,10 @@
# We'd really like to do this for all architectures, but since this wasn't done
# before, these symbols must continue to be exported on LP32 for binary
# compatibility.
-# TODO: disabled for http://b/20065774.
-#LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
# TODO: This is to work around b/19059885. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
+LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
$(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))
@@ -1522,7 +1521,7 @@
LOCAL_CPPFLAGS := $(libc_common_cppflags)
# TODO: This is to work around b/19059885. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
+LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
LOCAL_MODULE:= libstdc++
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 6a2f313..470a038 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -40,8 +40,6 @@
arch-arm64/bionic/syscall.S \
arch-arm64/bionic/vfork.S \
-# Work around for http://b/20065774.
-libc_bionic_src_files_arm64 += arch-arm64/bionic/libgcc_compat.c
libc_crt_target_cflags_arm64 := \
-I$(LOCAL_PATH)/arch-arm64/include
diff --git a/libc/arch-arm64/bionic/libgcc_compat.c b/libc/arch-arm64/bionic/libgcc_compat.c
deleted file mode 100644
index 2dae3f5..0000000
--- a/libc/arch-arm64/bionic/libgcc_compat.c
+++ /dev/null
@@ -1,15 +0,0 @@
-/* STOPSHIP: remove this once the flounder blobs have been rebuilt (http://b/20065774). */
-
-#if !defined(__clang__)
-
-extern void __clear_cache(char*, char*);
-extern char _Unwind_Backtrace;
-extern char _Unwind_GetIP;
-
-void* __bionic_libgcc_compat_symbols[] = {
- &__clear_cache,
- &_Unwind_Backtrace,
- &_Unwind_GetIP,
-};
-
-#endif
diff --git a/libc/arch-common/bionic/asm_multiarch.h b/libc/arch-common/bionic/asm_multiarch.h
index 85e1b57..91cb8af 100644
--- a/libc/arch-common/bionic/asm_multiarch.h
+++ b/libc/arch-common/bionic/asm_multiarch.h
@@ -28,9 +28,9 @@
#ifdef __LP64__
# define ASM_PTR_SIZE(x) .quad x
-# define ASM_ALIGN(x)
+# define ASM_ALIGN_TO_PTR_SIZE .balign 8
#else
# define ASM_PTR_SIZE(x) .long x
-# define ASM_ALIGN(x) .align x
+# define ASM_ALIGN_TO_PTR_SIZE .balign 4
#endif
diff --git a/libc/arch-common/bionic/crtend.S b/libc/arch-common/bionic/crtend.S
index a4cf8de..87d1120 100644
--- a/libc/arch-common/bionic/crtend.S
+++ b/libc/arch-common/bionic/crtend.S
@@ -29,12 +29,15 @@
#include "asm_multiarch.h"
.section .preinit_array, "aw"
+ ASM_ALIGN_TO_PTR_SIZE
ASM_PTR_SIZE(0)
.section .init_array, "aw"
+ ASM_ALIGN_TO_PTR_SIZE
ASM_PTR_SIZE(0)
.section .fini_array, "aw"
+ ASM_ALIGN_TO_PTR_SIZE
ASM_PTR_SIZE(0)
#if defined(__linux__) && defined(__ELF__)
@@ -42,7 +45,9 @@
#endif
#if defined(__i386__) || defined(__x86_64__)
.section .eh_frame,"a",@progbits
- ASM_ALIGN(4)
+#if defined(__i386__)
+ .balign 4
+#endif
.type __FRAME_END__, @object
.size __FRAME_END__, 4
__FRAME_END__:
diff --git a/libc/arch-common/bionic/crtend_so.S b/libc/arch-common/bionic/crtend_so.S
index f745109..e7b8cac 100644
--- a/libc/arch-common/bionic/crtend_so.S
+++ b/libc/arch-common/bionic/crtend_so.S
@@ -26,22 +26,14 @@
* SUCH DAMAGE.
*/
-#include "asm_multiarch.h"
-
-#ifndef __arm__
- .section .init_array, "aw"
- ASM_PTR_SIZE(0)
-
- .section .fini_array, "aw"
- ASM_PTR_SIZE(0)
-#endif
-
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
#if defined(__i386__) || defined(__x86_64__)
.section .eh_frame,"a",@progbits
- ASM_ALIGN(4)
+#if defined(__i386__)
+ .balign 4
+#endif
.type __FRAME_END__, @object
.size __FRAME_END__, 4
__FRAME_END__:
diff --git a/libc/include/elf.h b/libc/include/elf.h
index df768ba..eaad1d3 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -34,6 +34,11 @@
#include <machine/elf_machdep.h>
+#define ELF32_R_INFO(sym, type) ((((Elf32_Word)sym) << 8) | ((type) & 0xff))
+#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)sym) << 32) | ((type) & 0xffffffff))
+
+typedef __s64 Elf32_Sxword;
+
typedef struct {
__u32 a_type;
union {
@@ -187,6 +192,11 @@
#define STT_LOPROC 13
#define STT_HIPROC 15
+#define STV_DEFAULT 0
+#define STV_INTERNAL 1
+#define STV_HIDDEN 2
+#define STV_PROTECTED 3
+
/* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */
#define NT_FPREGSET NT_PRFPREG
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 8086020..a0315b5 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -81,7 +81,6 @@
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"
#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"
#define PROP_PATH_VENDOR_BUILD "/vendor/build.prop"
-#define PROP_PATH_BOOTIMAGE_BUILD "/build.prop"
#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
#define PROP_PATH_FACTORY "/factory/factory.prop"
diff --git a/libc/version_script.txt b/libc/version_script.txt
index 349a2fc..afc5e5c 100644
--- a/libc/version_script.txt
+++ b/libc/version_script.txt
@@ -1,9 +1,4 @@
LIBC {
- global:
- /* Work-around for http://b/20065774. */
- __clear_cache;
- _Unwind_Backtrace;
- _Unwind_GetIP;
local:
_ZSt7nothrow;
_ZdaPv;
diff --git a/libm/Android.mk b/libm/Android.mk
index 6472a15..529dda8 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -514,7 +514,7 @@
include $(CLEAR_VARS)
# TODO: This is to work around b/19059885. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
+LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
LOCAL_MODULE := libm
LOCAL_CLANG := $(libm_clang)
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 2669a56..c6decee 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -267,7 +267,7 @@
soinfo *prev = nullptr, *trav;
- TRACE("name %s: freeing soinfo @ %p", si->get_soname(), si);
+ TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
for (trav = solist; trav != nullptr; trav = trav->next) {
if (trav == si) {
@@ -278,7 +278,7 @@
if (trav == nullptr) {
// si was not in solist
- DL_ERR("name \"%s\"@%p is not in solist!", si->get_soname(), si);
+ DL_ERR("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
return;
}
@@ -443,7 +443,7 @@
if (verdef->vd_version != 1) {
DL_ERR("unsupported verdef[%zd] vd_version: %d (expected 1) library: %s",
- i, verdef->vd_version, si->get_soname());
+ i, verdef->vd_version, si->get_realpath());
return false;
}
@@ -513,7 +513,7 @@
return s->st_shndx != SHN_UNDEF;
} else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
DL_WARN("unexpected ST_BIND value: %d for '%s' in '%s'",
- ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_soname());
+ ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
}
return false;
@@ -546,12 +546,12 @@
*symbol_index = 0;
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
- symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
// test against bloom filter
if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
- symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
return true;
}
@@ -561,7 +561,7 @@
if (n == 0) {
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
- symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
return true;
}
@@ -589,7 +589,7 @@
strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
is_symbol_global_and_defined(this, s)) {
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
- symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(s->st_value),
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(s->st_value),
static_cast<size_t>(s->st_size));
*symbol_index = n;
return true;
@@ -597,7 +597,7 @@
} while ((gnu_chain_[n++] & 1) == 0);
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
- symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
return true;
}
@@ -608,7 +608,7 @@
uint32_t hash = symbol_name.elf_hash();
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
- symbol_name.get_name(), get_soname(),
+ symbol_name.get_name(), get_realpath(),
reinterpret_cast<void*>(base), hash, hash % nbucket_);
ElfW(Versym) verneed = 0;
@@ -629,7 +629,7 @@
strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
is_symbol_global_and_defined(this, s)) {
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
- symbol_name.get_name(), get_soname(),
+ symbol_name.get_name(), get_realpath(),
reinterpret_cast<void*>(s->st_value),
static_cast<size_t>(s->st_size));
*symbol_index = n;
@@ -638,7 +638,7 @@
}
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
- symbol_name.get_name(), get_soname(),
+ symbol_name.get_name(), get_realpath(),
reinterpret_cast<void*>(base), hash, hash % nbucket_);
*symbol_index = 0;
@@ -718,7 +718,7 @@
* relocations for -Bsymbolic linked dynamic executables.
*/
if (si_from->has_DT_SYMBOLIC) {
- DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_soname(), name);
+ DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name);
if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) {
return false;
}
@@ -733,7 +733,7 @@
bool error = false;
global_group.visit([&](soinfo* global_si) {
DEBUG("%s: looking up %s in %s (from global group)",
- si_from->get_soname(), name, global_si->get_soname());
+ si_from->get_realpath(), name, global_si->get_realpath());
if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) {
error = true;
return false;
@@ -762,7 +762,7 @@
}
DEBUG("%s: looking up %s in %s (from local group)",
- si_from->get_soname(), name, local_si->get_soname());
+ si_from->get_realpath(), name, local_si->get_realpath());
if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) {
error = true;
return false;
@@ -784,8 +784,8 @@
if (s != nullptr) {
TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
"found in %s, base = %p, load bias = %p",
- si_from->get_soname(), name, reinterpret_cast<void*>(s->st_value),
- (*si_found_in)->get_soname(), reinterpret_cast<void*>((*si_found_in)->base),
+ si_from->get_realpath(), name, reinterpret_cast<void*>(s->st_value),
+ (*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
reinterpret_cast<void*>((*si_found_in)->load_bias));
}
@@ -1513,7 +1513,7 @@
}
if (!root->can_unload()) {
- TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_soname());
+ TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath());
return;
}
@@ -1536,7 +1536,9 @@
if (si->has_min_version(0)) {
soinfo* child = nullptr;
while ((child = si->get_children().pop_front()) != nullptr) {
- TRACE("%s@%p needs to unload %s@%p", si->get_soname(), si, child->get_soname(), child);
+ TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
+ child->get_realpath(), child);
+
if (local_unload_list.contains(child)) {
continue;
} else if (child->is_linked() && child->get_local_group_root() != root) {
@@ -1547,19 +1549,19 @@
}
} else {
#if !defined(__arm__)
- __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_soname(), si);
+ __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
#else
- PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_soname(), si);
+ PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
for_each_dt_needed(si, [&] (const char* library_name) {
TRACE("deprecated (old format of soinfo): %s needs to unload %s",
- si->get_soname(), library_name);
+ si->get_realpath(), library_name);
soinfo* needed = find_library(library_name, RTLD_NOLOAD, 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.
PRINT("warning: couldn't find %s needed by %s on unload.",
- library_name, si->get_soname());
+ library_name, si->get_realpath());
return;
} else if (local_unload_list.contains(needed)) {
// already visited
@@ -1589,7 +1591,8 @@
soinfo_unload(si);
}
} else {
- TRACE("not unloading '%s' group, decrementing ref_count to %zd", root->get_soname(), ref_count);
+ TRACE("not unloading '%s' group, decrementing ref_count to %zd",
+ root->get_realpath(), ref_count);
}
}
@@ -1701,12 +1704,12 @@
const char* target_soname = si_from->get_string(verneed->vn_file);
// find it in dependencies
soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
- return strcmp(si->get_soname(), target_soname) == 0;
+ return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
});
if (target_si == nullptr) {
DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
- target_soname, i, si_from->get_soname());
+ target_soname, i, si_from->get_realpath());
return false;
}
@@ -1753,7 +1756,7 @@
if (*vi == nullptr) {
DL_ERR("cannot find verneed/verdef for version index=%d "
- "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_soname());
+ "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_realpath());
return false;
}
} else {
@@ -1796,7 +1799,7 @@
const char* sym_name = nullptr;
ElfW(Addr) addend = get_addend(rel, reloc);
- DEBUG("Processing '%s' relocation at index %zd", get_soname(), idx);
+ DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
if (type == R_GENERIC_NONE) {
continue;
}
@@ -1820,7 +1823,7 @@
// We only allow an undefined symbol if this is a weak reference...
s = &symtab_[sym];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
- DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_soname());
+ DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath());
return false;
}
@@ -2016,7 +2019,7 @@
* R_AARCH64_COPY may only appear in executable objects where e_type is
* set to ET_EXEC.
*/
- DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_soname());
+ DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath());
return false;
case R_AARCH64_TLS_TPREL64:
TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
@@ -2073,7 +2076,7 @@
* R_ARM_COPY may only appear in executable objects where e_type is
* set to ET_EXEC.
*/
- DL_ERR("%s R_ARM_COPY relocations are not supported", get_soname());
+ DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
return false;
#elif defined(__i386__)
case R_386_32:
@@ -2105,7 +2108,7 @@
return;
}
- TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_soname());
+ TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_realpath());
int begin = reverse ? (count - 1) : 0;
int end = reverse ? -1 : count;
@@ -2116,7 +2119,7 @@
call_function("function", functions[i]);
}
- TRACE("[ Done calling %s for '%s' ]", array_name, get_soname());
+ TRACE("[ Done calling %s for '%s' ]", array_name, get_realpath());
}
void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
@@ -2124,9 +2127,9 @@
return;
}
- TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_soname());
+ TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath());
function();
- TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_soname());
+ TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_realpath());
}
void soinfo::call_pre_init_constructors() {
@@ -2155,14 +2158,14 @@
if (!is_main_executable() && preinit_array_ != nullptr) {
// The GNU dynamic linker silently ignores these, but we warn the developer.
PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
- get_soname(), preinit_array_count_);
+ get_realpath(), preinit_array_count_);
}
get_children().for_each([] (soinfo* si) {
si->call_constructors();
});
- TRACE("\"%s\": calling constructors", get_soname());
+ TRACE("\"%s\": calling constructors", get_realpath());
// DT_INIT should be called before DT_INIT_ARRAY if both are present.
call_function("DT_INIT", init_func_);
@@ -2173,7 +2176,7 @@
if (!constructors_called) {
return;
}
- TRACE("\"%s\": calling destructors", get_soname());
+ TRACE("\"%s\": calling destructors", get_realpath());
// DT_FINI_ARRAY must be parsed in reverse order.
call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true);
@@ -2333,7 +2336,7 @@
const char* soinfo::get_string(ElfW(Word) index) const {
if (has_min_version(1) && (index >= strtab_size_)) {
__libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
- get_soname(), strtab_size_, index);
+ get_realpath(), strtab_size_, index);
}
return strtab_ + index;
@@ -2454,7 +2457,7 @@
if (dynamic == nullptr) {
if (!relocating_linker) {
- DL_ERR("missing PT_DYNAMIC in \"%s\"", get_soname());
+ DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath());
}
return false;
} else {
@@ -2838,15 +2841,15 @@
}
if (nbucket_ == 0 && gnu_nbucket_ == 0) {
DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" "
- "(new hash type from the future?)", get_soname());
+ "(new hash type from the future?)", get_realpath());
return false;
}
if (strtab_ == 0) {
- DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_soname());
+ DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());
return false;
}
if (symtab_ == 0) {
- DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_soname());
+ DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
return false;
}
return true;
@@ -2871,10 +2874,10 @@
// Make segments writable to allow text relocations to work properly. We will later call
// phdr_table_protect_segments() after all of them are applied and all constructors are run.
DL_WARN("%s has text relocations. This is wasting memory and prevents "
- "security hardening. Please fix.", get_soname());
+ "security hardening. Please fix.", get_realpath());
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
- get_soname(), strerror(errno));
+ get_realpath(), strerror(errno));
return false;
}
}
@@ -2887,7 +2890,7 @@
android_relocs_[1] == 'P' &&
android_relocs_[2] == 'S' &&
android_relocs_[3] == '2') {
- DEBUG("[ android relocating %s ]", get_soname());
+ DEBUG("[ android relocating %s ]", get_realpath());
bool relocated = false;
const uint8_t* packed_relocs = android_relocs_ + 4;
@@ -2910,14 +2913,14 @@
#if defined(USE_RELA)
if (rela_ != nullptr) {
- DEBUG("[ relocating %s ]", get_soname());
+ DEBUG("[ relocating %s ]", get_realpath());
if (!relocate(version_tracker,
plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
return false;
}
}
if (plt_rela_ != nullptr) {
- DEBUG("[ relocating %s plt ]", get_soname());
+ DEBUG("[ relocating %s plt ]", get_realpath());
if (!relocate(version_tracker,
plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
return false;
@@ -2925,14 +2928,14 @@
}
#else
if (rel_ != nullptr) {
- DEBUG("[ relocating %s ]", get_soname());
+ DEBUG("[ relocating %s ]", get_realpath());
if (!relocate(version_tracker,
plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
return false;
}
}
if (plt_rel_ != nullptr) {
- DEBUG("[ relocating %s plt ]", get_soname());
+ DEBUG("[ relocating %s plt ]", get_realpath());
if (!relocate(version_tracker,
plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
return false;
@@ -2946,14 +2949,14 @@
}
#endif
- DEBUG("[ finished linking %s ]", get_soname());
+ DEBUG("[ finished linking %s ]", get_realpath());
#if !defined(__LP64__)
if (has_text_relocations) {
// All relocations are done, we can protect our segments back to read-only.
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
- get_soname(), strerror(errno));
+ get_realpath(), strerror(errno));
return false;
}
}
@@ -2962,7 +2965,7 @@
/* We can also turn on GNU RELRO protection */
if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
- get_soname(), strerror(errno));
+ get_realpath(), strerror(errno));
return false;
}
@@ -2971,14 +2974,14 @@
if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
extinfo->relro_fd) < 0) {
DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
- get_soname(), strerror(errno));
+ get_realpath(), strerror(errno));
return false;
}
} else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
extinfo->relro_fd) < 0) {
DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
- get_soname(), strerror(errno));
+ get_realpath(), strerror(errno));
return false;
}
}
@@ -3253,7 +3256,7 @@
fflush(stdout);
#endif
- TRACE("[ Ready to execute '%s' @ %p ]", si->get_soname(), reinterpret_cast<void*>(si->entry));
+ TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast<void*>(si->entry));
return si->entry;
}
@@ -3269,7 +3272,8 @@
*/
static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) {
ElfW(Addr) offset = elf->e_phoff;
- const ElfW(Phdr)* phdr_table = reinterpret_cast<const ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(elf) + offset);
+ const ElfW(Phdr)* phdr_table =
+ reinterpret_cast<const ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(elf) + offset);
const ElfW(Phdr)* phdr_end = phdr_table + elf->e_phnum;
for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_end; phdr++) {
diff --git a/linker/linker_mips.cpp b/linker/linker_mips.cpp
index 7436180..a7a4bc0 100644
--- a/linker/linker_mips.cpp
+++ b/linker/linker_mips.cpp
@@ -157,20 +157,34 @@
soinfo* lsi = nullptr;
const ElfW(Sym)* s = nullptr;
- const version_info* vi = nullptr;
+ ElfW(Word) st_visibility = (local_sym->st_other & 0x3);
- if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
- return false;
- }
+ if (st_visibility == STV_DEFAULT) {
+ const version_info* vi = nullptr;
- if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+ } else if (st_visibility == STV_PROTECTED) {
+ if (local_sym->st_value == 0) {
+ DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ", get_soname(), sym_name);
+ return false;
+ }
+ s = local_sym;
+ lsi = this;
+ } else {
+ DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x", get_soname(), sym_name, st_visibility);
return false;
}
if (s == nullptr) {
// We only allow an undefined symbol if this is a weak reference.
if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
- DL_ERR("cannot locate \"%s\"...", sym_name);
+ DL_ERR("%s: cannot locate \"%s\"...", get_soname(), sym_name);
return false;
}
*got = 0;
diff --git a/tests/Android.mk b/tests/Android.mk
index cd65c10..14f0d32 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -269,6 +269,7 @@
dlext_test.cpp \
__cxa_thread_atexit_test.cpp \
dlfcn_test.cpp \
+ pthread_dlfcn_test.cpp \
bionic-unit-tests_cflags := $(test_cflags)
@@ -346,6 +347,7 @@
atexit_test.cpp \
dlfcn_test.cpp \
dl_test.cpp \
+ pthread_dlfcn_test.cpp \
bionic-unit-tests-glibc_shared_libraries := \
libdl_preempt_test_1 \
diff --git a/tests/pthread_dlfcn_test.cpp b/tests/pthread_dlfcn_test.cpp
new file mode 100644
index 0000000..5e8b206
--- /dev/null
+++ b/tests/pthread_dlfcn_test.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <dlfcn.h>
+
+static int g_atfork_prepare_calls = 0;
+static void AtForkPrepare1() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 1; }
+static void AtForkPrepare2() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 2; }
+static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; }
+static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; }
+
+static int g_atfork_parent_calls = 0;
+static void AtForkParent1() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 1; }
+static void AtForkParent2() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 2; }
+static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; }
+static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; }
+
+static int g_atfork_child_calls = 0;
+static void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 1; }
+static void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 2; }
+static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; }
+static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; }
+
+TEST(pthread, pthread_atfork_with_dlclose) {
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
+
+ void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void));
+ fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork"));
+ ASSERT_TRUE(fn != nullptr) << dlerror();
+ // the library registers 2 additional atfork handlers in a constructor
+ ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2));
+ ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3));
+
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4));
+
+ int pid = fork();
+
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ if (pid == 0) {
+ ASSERT_EQ(1234, g_atfork_child_calls);
+ _exit(0);
+ }
+
+ ASSERT_EQ(1234, g_atfork_parent_calls);
+ ASSERT_EQ(4321, g_atfork_prepare_calls);
+
+ EXPECT_EQ(0, dlclose(handle));
+ g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
+
+ int status;
+ ASSERT_EQ(pid, waitpid(pid, &status, 0));
+
+ pid = fork();
+
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ if (pid == 0) {
+ ASSERT_EQ(14, g_atfork_child_calls);
+ _exit(0);
+ }
+
+ ASSERT_EQ(14, g_atfork_parent_calls);
+ ASSERT_EQ(41, g_atfork_prepare_calls);
+
+ ASSERT_EQ(pid, waitpid(pid, &status, 0));
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index cb5e818..cbbcada 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -16,7 +16,6 @@
#include <gtest/gtest.h>
-#include <dlfcn.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
@@ -1019,62 +1018,6 @@
ASSERT_EQ(pid, waitpid(pid, &status, 0));
}
-static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; }
-static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; }
-
-static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; }
-static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; }
-
-static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; }
-static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; }
-
-TEST(pthread, pthread_atfork_with_dlclose) {
- ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
-
- void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL);
- ASSERT_TRUE(handle != nullptr) << dlerror();
- typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void));
- fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork"));
- ASSERT_TRUE(fn != nullptr) << dlerror();
- // the library registers 2 additional atfork handlers in a constructor
- ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2));
- ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3));
-
- ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4));
-
- int pid = fork();
-
- ASSERT_NE(-1, pid) << strerror(errno);
-
- if (pid == 0) {
- ASSERT_EQ(1234, g_atfork_child_calls);
- _exit(0);
- }
-
- ASSERT_EQ(1234, g_atfork_parent_calls);
- ASSERT_EQ(4321, g_atfork_prepare_calls);
-
- EXPECT_EQ(0, dlclose(handle));
- g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
-
- int status;
- ASSERT_EQ(pid, waitpid(pid, &status, 0));
-
- pid = fork();
-
- ASSERT_NE(-1, pid) << strerror(errno);
-
- if (pid == 0) {
- ASSERT_EQ(14, g_atfork_child_calls);
- _exit(0);
- }
-
- ASSERT_EQ(14, g_atfork_parent_calls);
- ASSERT_EQ(41, g_atfork_prepare_calls);
-
- ASSERT_EQ(pid, waitpid(pid, &status, 0));
-}
-
TEST(pthread, pthread_attr_getscope) {
pthread_attr_t attr;
ASSERT_EQ(0, pthread_attr_init(&attr));
diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc
index d06bd63..102d614 100644
--- a/tools/relocation_packer/src/elf_file.cc
+++ b/tools/relocation_packer/src/elf_file.cc
@@ -312,6 +312,13 @@
for (size_t i = 0; i < count; ++i) {
typename ELF::Phdr* program_header = &program_headers[i];
+ // Do not adjust PT_GNU_STACK - it confuses gdb and results
+ // in incorrect unwinding if the executable is stripped after
+ // packing.
+ if (program_header->p_type == PT_GNU_STACK) {
+ continue;
+ }
+
if (program_header->p_offset > hole_start) {
// The hole start is past this segment, so adjust offset.
program_header->p_offset += hole_size;