diff options
Diffstat (limited to 'libunwindstack/ElfInterface.cpp')
-rw-r--r-- | libunwindstack/ElfInterface.cpp | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp index 20cc1b06c..d5d158f82 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include "DwarfDebugFrame.h" | 33 | #include "DwarfDebugFrame.h" |
34 | #include "DwarfEhFrame.h" | 34 | #include "DwarfEhFrame.h" |
35 | #include "DwarfEhFrameWithHdr.h" | ||
35 | #include "Symbols.h" | 36 | #include "Symbols.h" |
36 | 37 | ||
37 | namespace unwindstack { | 38 | namespace unwindstack { |
@@ -98,7 +99,17 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() { | |||
98 | 99 | ||
99 | template <typename AddressType> | 100 | template <typename AddressType> |
100 | void ElfInterface::InitHeadersWithTemplate() { | 101 | void ElfInterface::InitHeadersWithTemplate() { |
101 | if (eh_frame_offset_ != 0) { | 102 | if (eh_frame_hdr_offset_ != 0) { |
103 | eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_)); | ||
104 | if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) { | ||
105 | // Even if the eh_frame_offset_ is non-zero, do not bother | ||
106 | // trying to read that since something has gone wrong. | ||
107 | eh_frame_.reset(nullptr); | ||
108 | eh_frame_hdr_offset_ = 0; | ||
109 | eh_frame_hdr_size_ = static_cast<uint64_t>(-1); | ||
110 | } | ||
111 | } else if (eh_frame_offset_ != 0) { | ||
112 | // If there is a eh_frame section without a eh_frame_hdr section. | ||
102 | eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); | 113 | eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); |
103 | if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { | 114 | if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { |
104 | eh_frame_.reset(nullptr); | 115 | eh_frame_.reset(nullptr); |
@@ -181,11 +192,12 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) | |||
181 | if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { | 192 | if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { |
182 | return false; | 193 | return false; |
183 | } | 194 | } |
184 | eh_frame_offset_ = phdr.p_offset; | 195 | // This is really the pointer to the .eh_frame_hdr section. |
196 | eh_frame_hdr_offset_ = phdr.p_offset; | ||
185 | if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { | 197 | if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { |
186 | return false; | 198 | return false; |
187 | } | 199 | } |
188 | eh_frame_size_ = phdr.p_memsz; | 200 | eh_frame_hdr_size_ = phdr.p_memsz; |
189 | break; | 201 | break; |
190 | 202 | ||
191 | case PT_DYNAMIC: | 203 | case PT_DYNAMIC: |
@@ -271,6 +283,12 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { | |||
271 | } else if (name == ".gnu_debugdata") { | 283 | } else if (name == ".gnu_debugdata") { |
272 | offset_ptr = &gnu_debugdata_offset_; | 284 | offset_ptr = &gnu_debugdata_offset_; |
273 | size_ptr = &gnu_debugdata_size_; | 285 | size_ptr = &gnu_debugdata_size_; |
286 | } else if (name == ".eh_frame") { | ||
287 | offset_ptr = &eh_frame_offset_; | ||
288 | size_ptr = &eh_frame_size_; | ||
289 | } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") { | ||
290 | offset_ptr = &eh_frame_hdr_offset_; | ||
291 | size_ptr = &eh_frame_hdr_size_; | ||
274 | } | 292 | } |
275 | if (offset_ptr != nullptr && | 293 | if (offset_ptr != nullptr && |
276 | memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && | 294 | memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) && |