Use realpath for log and error messages
Bug: http://b/20885931
Change-Id: Ida8ab7982ca75fa73da13c4cb10a6b2e53bc2c8e
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 7d8b266..c3c9029 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -252,7 +252,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) {
@@ -263,7 +263,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;
}
@@ -428,7 +428,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;
}
@@ -498,7 +498,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;
@@ -531,12 +531,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;
}
@@ -546,7 +546,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;
}
@@ -574,7 +574,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;
@@ -582,7 +582,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;
}
@@ -593,7 +593,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;
@@ -614,7 +614,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;
@@ -623,7 +623,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;
@@ -703,7 +703,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;
}
@@ -718,7 +718,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;
@@ -747,7 +747,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;
@@ -769,8 +769,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));
}
@@ -1498,7 +1498,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;
}
@@ -1521,7 +1521,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) {
@@ -1532,19 +1534,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
@@ -1574,7 +1576,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);
}
}
@@ -1691,7 +1694,7 @@
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;
}
@@ -1738,7 +1741,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 {
@@ -1781,7 +1784,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;
}
@@ -1805,7 +1808,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;
}
@@ -2001,7 +2004,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",
@@ -2058,7 +2061,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:
@@ -2090,7 +2093,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;
@@ -2101,7 +2104,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) {
@@ -2109,9 +2112,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() {
@@ -2140,14 +2143,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_);
@@ -2158,7 +2161,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);
@@ -2318,7 +2321,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;
@@ -2439,7 +2442,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 {
@@ -2823,15 +2826,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;
@@ -2856,10 +2859,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;
}
}
@@ -2872,7 +2875,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;
@@ -2895,14 +2898,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;
@@ -2910,14 +2913,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;
@@ -2931,14 +2934,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;
}
}
@@ -2947,7 +2950,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;
}
@@ -2956,14 +2959,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;
}
}
@@ -3238,7 +3241,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;
}
@@ -3254,7 +3257,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++) {