summaryrefslogtreecommitdiffstats
path: root/runtime/elf_file.cc
diff options
context:
space:
mode:
authorJim_Guo <jim_guo@htc.com>2014-04-28 11:11:57 +0800
committerBrian Carlstrom <bdc@google.com>2014-08-04 22:27:52 -0700
commita62a588a9202f69e53fbeb3045ea8ea5ec2587f8 (patch)
treeafbbcca1eaa59d40fa94db6babeb2ea909777357 /runtime/elf_file.cc
parentb5c5646b5ffd3d451af5e8d52b50743bf61d4c40 (diff)
downloadart-a62a588a9202f69e53fbeb3045ea8ea5ec2587f8.tar.gz
art-a62a588a9202f69e53fbeb3045ea8ea5ec2587f8.tar.bz2
art-a62a588a9202f69e53fbeb3045ea8ea5ec2587f8.zip
ART: Fix memory unmapped twice issue in ElfFile::Load(bool)
Root Cause: The overlapped memory region will be unmapped by (1) ~MemMap() of reservation MemMap (reserve) and (2) ~MemMap() of "reuse" MemMap (segment). Someone takes the memory region after (1) and it will be unmapped in (2). So, SIGSEGV occurs when using the unmapped memory region. Solution: Fixes this issue by skip unmap "reuse" MemMap in destructor. And always create reservation MemMap before "reuse" MemMap. (It also solved the fixupELF case which does not reserve the whole needed memory region). Bug: 16486685 Change-Id: I8f2538861d5c3fa7b9a04d2c3f516319cc060291
Diffstat (limited to 'runtime/elf_file.cc')
-rw-r--r--runtime/elf_file.cc24
1 files changed, 15 insertions, 9 deletions
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 594c65f6e2..6179b5e8d1 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -837,6 +837,7 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
}
}
+ bool reserved = false;
for (Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
Elf32_Phdr& program_header = GetProgramHeader(i);
@@ -853,10 +854,8 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
// Found something to load.
- // If p_vaddr is zero, it must be the first loadable segment,
- // since they must be in order. Since it is zero, there isn't a
- // specific address requested, so first request a contiguous chunk
- // of required size for all segments, but with no
+ // Before load the actual segments, reserve a contiguous chunk
+ // of required size and address for all segments, but with no
// permissions. We'll then carve that up with the proper
// permissions as we load the actual segments. If p_vaddr is
// non-zero, the segments require the specific address specified,
@@ -870,18 +869,24 @@ bool ElfFile::Load(bool executable, std::string* error_msg) {
return false;
}
size_t file_length = static_cast<size_t>(temp_file_length);
- if (program_header.p_vaddr == 0) {
+ if (!reserved) {
+ byte* reserve_base = ((program_header.p_vaddr != 0) ?
+ reinterpret_cast<byte*>(program_header.p_vaddr) : nullptr);
std::string reservation_name("ElfFile reservation for ");
reservation_name += file_->GetPath();
std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
- nullptr, GetLoadedSize(), PROT_NONE, false,
- error_msg));
+ reserve_base,
+ GetLoadedSize(), PROT_NONE, false,
+ error_msg));
if (reserve.get() == nullptr) {
*error_msg = StringPrintf("Failed to allocate %s: %s",
reservation_name.c_str(), error_msg->c_str());
return false;
}
- base_address_ = reserve->Begin();
+ reserved = true;
+ if (reserve_base == nullptr) {
+ base_address_ = reserve->Begin();
+ }
segments_.push_back(reserve.release());
}
// empty segment, nothing to map
@@ -1335,7 +1340,8 @@ void ElfFile::GdbJITSupport() {
const Elf32_Shdr* symtab_sec = all.FindSectionByName(".symtab");
Elf32_Shdr* text_sec = all.FindSectionByName(".text");
if (debug_info == nullptr || debug_abbrev == nullptr || eh_frame == nullptr ||
- debug_str == nullptr || text_sec == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
+ debug_str == nullptr || text_sec == nullptr || strtab_sec == nullptr ||
+ symtab_sec == nullptr) {
return;
}
// We need to add in a strtab and symtab to the image.