Index: base/third_party/symbolize/symbolize.cc |
diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc |
index db82b04d4df254a345107f532c636511cc5e6753..d7678956c87f603eb1b0483bb819a9f401ca2dc2 100644 |
--- a/base/third_party/symbolize/symbolize.cc |
+++ b/base/third_party/symbolize/symbolize.cc |
@@ -327,7 +327,7 @@ FindSymbol(uint64_t pc, const int fd, char *out, int out_size, |
// false. |
static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, |
char *out, int out_size, |
- uint64_t map_start_address) { |
+ uint64_t map_base_address) { |
// Read the ELF header. |
ElfW(Ehdr) elf_header; |
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { |
@@ -336,7 +336,28 @@ static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, |
uint64_t symbol_offset = 0; |
if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment. |
- symbol_offset = map_start_address; |
+ ElfW(Phdr) phdr; |
+ // We need to find the PT_LOAD segment corresponding to the read-execute |
+ // file mapping in order to correctly perform the offset adjustment. |
+ for (unsigned i = 0; i != elf_header.e_phnum; ++i) { |
+ if (!ReadFromOffsetExact(fd, &phdr, sizeof(phdr), |
+ elf_header.e_phoff + i * sizeof(phdr))) |
+ return false; |
+ if (phdr.p_type == PT_LOAD && |
+ (phdr.p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) { |
+ // Find the mapped address corresponding to virtual address zero. We do |
+ // this by first adding p_offset. This gives us the mapped address of |
+ // the start of the segment, or in other words the mapped address |
+ // corresponding to the virtual address of the segment. (Note that this |
+ // is distinct from the start address, as p_offset is not guaranteed to |
+ // be page aligned.) We then subtract p_vaddr, which takes us to virtual |
+ // address zero. |
+ symbol_offset = map_base_address + phdr.p_offset - phdr.p_vaddr; |
+ break; |
+ } |
+ } |
+ if (symbol_offset == 0) |
+ return false; |
} |
ElfW(Shdr) symtab, strtab; |
@@ -783,7 +804,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, |
} |
} |
if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, |
- out, out_size, start_address)) { |
+ out, out_size, base_address)) { |
return false; |
} |