am de0fb393: Restore protection flags for ifunc during relocs.

* commit 'de0fb393ae8136a5958fe17eee0c6285e2f7f91a':
  Restore protection flags for ifunc during relocs.
This commit is contained in:
Dmitriy Ivanov 2015-07-27 21:39:11 +00:00 committed by Android Git Automerger
commit ab6ca484bd

View File

@ -1999,9 +1999,32 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
return false;
}
} else {
// We got a definition.
} else { // We got a definition.
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags before resolving
// STT_GNU_IFUNC symbol.
bool protect_segments = has_text_relocations &&
lsi == this &&
ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
if (protect_segments) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
sym_addr = lsi->resolve_symbol_address(s);
#if !defined(__LP64__)
if (protect_segments) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
}
count_relocation(kRelocSymbol);
}
@ -2038,7 +2061,32 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
reinterpret_cast<void*>(reloc),
reinterpret_cast<void*>(load_bias + addend));
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(load_bias + addend);
{
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags for this
// particular call.
if (has_text_relocations) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
#if !defined(__LP64__)
// Unprotect it afterwards...
if (has_text_relocations) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
*reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
}
break;
#if defined(__aarch64__)