Loading libunwindstack/Elf.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,28 @@ bool Elf::IsValidElf(Memory* memory) { return true; } void Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) { if (!IsValidElf(memory)) { *valid = false; return; } *size = 0; *valid = true; // Now read the section header information. uint8_t class_type; if (!memory->Read(EI_CLASS, &class_type, 1)) { return; } if (class_type == ELFCLASS32) { ElfInterface32::GetMaxSize(memory, size); } else if (class_type == ELFCLASS64) { ElfInterface64::GetMaxSize(memory, size); } else { *valid = false; } } ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { if (!IsValidElf(memory)) { return nullptr; Loading libunwindstack/ElfInterface.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,22 @@ bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) { return false; } // This is an estimation of the size of the elf file using the location // of the section headers and size. This assumes that the section headers // are at the end of the elf file. If the elf has a load bias, the size // will be too large, but this is acceptable. template <typename EhdrType> void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) { EhdrType ehdr; if (!memory->Read(0, &ehdr, sizeof(ehdr))) { return; } if (ehdr.e_shnum == 0) { return; } *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; } // Instantiate all of the needed template functions. template void ElfInterface::InitHeadersWithTemplate<uint32_t>(); template void ElfInterface::InitHeadersWithTemplate<uint64_t>(); Loading @@ -391,4 +407,7 @@ template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*, uint64_t*); template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*); template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*); } // namespace unwindstack libunwindstack/MapInfo.cpp +53 −24 Original line number Diff line number Diff line Loading @@ -27,6 +27,55 @@ namespace unwindstack { Memory* MapInfo::GetFileMemory() { std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset); if (offset == 0) { if (memory->Init(name, 0)) { return memory.release(); } return nullptr; } // There are two possibilities when the offset is non-zero. // - There is an elf file embedded in a file. // - The whole file is an elf file, and the offset needs to be saved. // // Map in just the part of the file for the map. If this is not // a valid elf, then reinit as if the whole file is an elf file. // If the offset is a valid elf, then determine the size of the map // and reinit to that size. This is needed because the dynamic linker // only maps in a portion of the original elf, and never the symbol // file data. uint64_t map_size = end - start; if (!memory->Init(name, offset, map_size)) { return nullptr; } bool valid; uint64_t max_size; Elf::GetInfo(memory.get(), &valid, &max_size); if (!valid) { // Init as if the whole file is an elf. if (memory->Init(name, 0)) { elf_offset = offset; return memory.release(); } return nullptr; } if (max_size > map_size) { if (memory->Init(name, offset, max_size)) { return memory.release(); } // Try to reinit using the default map_size. if (memory->Init(name, offset, map_size)) { return memory.release(); } return nullptr; } return memory.release(); } Memory* MapInfo::CreateMemory(pid_t pid) { if (end <= start) { return nullptr; Loading @@ -40,33 +89,13 @@ Memory* MapInfo::CreateMemory(pid_t pid) { if (flags & MAPS_FLAGS_DEVICE_MAP) { return nullptr; } std::unique_ptr<MemoryFileAtOffset> file_memory(new MemoryFileAtOffset); uint64_t map_size; if (offset != 0) { // Only map in a piece of the file. map_size = end - start; } else { map_size = UINT64_MAX; } if (file_memory->Init(name, offset, map_size)) { // It's possible that a non-zero offset might not be pointing to // valid elf data. Check if this is a valid elf, and if not assume // that this was meant to incorporate the entire file. if (offset != 0 && !Elf::IsValidElf(file_memory.get())) { // Don't bother checking the validity that will happen on the elf init. if (file_memory->Init(name, 0)) { elf_offset = offset; return file_memory.release(); } // Fall through if the init fails. } else { return file_memory.release(); } Memory* memory = GetFileMemory(); if (memory != nullptr) { return memory; } } Memory* memory = nullptr; Memory* memory; if (pid == getpid()) { memory = new MemoryLocal(); } else { Loading libunwindstack/include/unwindstack/Elf.h +2 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ class Elf { static bool IsValidElf(Memory* memory); static void GetInfo(Memory* memory, bool* valid, uint64_t* size); protected: bool valid_ = false; std::unique_ptr<ElfInterface> interface_; Loading libunwindstack/include/unwindstack/ElfInterface.h +11 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ class ElfInterface { virtual bool HandleType(uint64_t, uint32_t) { return false; } template <typename EhdrType> static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size); Memory* memory_; std::unordered_map<uint64_t, LoadInfo> pt_loads_; uint64_t load_bias_ = 0; Loading Loading @@ -146,6 +149,10 @@ class ElfInterface32 : public ElfInterface { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size); } }; class ElfInterface64 : public ElfInterface { Loading @@ -166,6 +173,10 @@ class ElfInterface64 : public ElfInterface { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size); } }; } // namespace unwindstack Loading Loading
libunwindstack/Elf.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,28 @@ bool Elf::IsValidElf(Memory* memory) { return true; } void Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) { if (!IsValidElf(memory)) { *valid = false; return; } *size = 0; *valid = true; // Now read the section header information. uint8_t class_type; if (!memory->Read(EI_CLASS, &class_type, 1)) { return; } if (class_type == ELFCLASS32) { ElfInterface32::GetMaxSize(memory, size); } else if (class_type == ELFCLASS64) { ElfInterface64::GetMaxSize(memory, size); } else { *valid = false; } } ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { if (!IsValidElf(memory)) { return nullptr; Loading
libunwindstack/ElfInterface.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,22 @@ bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) { return false; } // This is an estimation of the size of the elf file using the location // of the section headers and size. This assumes that the section headers // are at the end of the elf file. If the elf has a load bias, the size // will be too large, but this is acceptable. template <typename EhdrType> void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) { EhdrType ehdr; if (!memory->Read(0, &ehdr, sizeof(ehdr))) { return; } if (ehdr.e_shnum == 0) { return; } *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; } // Instantiate all of the needed template functions. template void ElfInterface::InitHeadersWithTemplate<uint32_t>(); template void ElfInterface::InitHeadersWithTemplate<uint64_t>(); Loading @@ -391,4 +407,7 @@ template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*, uint64_t*); template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*); template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*); } // namespace unwindstack
libunwindstack/MapInfo.cpp +53 −24 Original line number Diff line number Diff line Loading @@ -27,6 +27,55 @@ namespace unwindstack { Memory* MapInfo::GetFileMemory() { std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset); if (offset == 0) { if (memory->Init(name, 0)) { return memory.release(); } return nullptr; } // There are two possibilities when the offset is non-zero. // - There is an elf file embedded in a file. // - The whole file is an elf file, and the offset needs to be saved. // // Map in just the part of the file for the map. If this is not // a valid elf, then reinit as if the whole file is an elf file. // If the offset is a valid elf, then determine the size of the map // and reinit to that size. This is needed because the dynamic linker // only maps in a portion of the original elf, and never the symbol // file data. uint64_t map_size = end - start; if (!memory->Init(name, offset, map_size)) { return nullptr; } bool valid; uint64_t max_size; Elf::GetInfo(memory.get(), &valid, &max_size); if (!valid) { // Init as if the whole file is an elf. if (memory->Init(name, 0)) { elf_offset = offset; return memory.release(); } return nullptr; } if (max_size > map_size) { if (memory->Init(name, offset, max_size)) { return memory.release(); } // Try to reinit using the default map_size. if (memory->Init(name, offset, map_size)) { return memory.release(); } return nullptr; } return memory.release(); } Memory* MapInfo::CreateMemory(pid_t pid) { if (end <= start) { return nullptr; Loading @@ -40,33 +89,13 @@ Memory* MapInfo::CreateMemory(pid_t pid) { if (flags & MAPS_FLAGS_DEVICE_MAP) { return nullptr; } std::unique_ptr<MemoryFileAtOffset> file_memory(new MemoryFileAtOffset); uint64_t map_size; if (offset != 0) { // Only map in a piece of the file. map_size = end - start; } else { map_size = UINT64_MAX; } if (file_memory->Init(name, offset, map_size)) { // It's possible that a non-zero offset might not be pointing to // valid elf data. Check if this is a valid elf, and if not assume // that this was meant to incorporate the entire file. if (offset != 0 && !Elf::IsValidElf(file_memory.get())) { // Don't bother checking the validity that will happen on the elf init. if (file_memory->Init(name, 0)) { elf_offset = offset; return file_memory.release(); } // Fall through if the init fails. } else { return file_memory.release(); } Memory* memory = GetFileMemory(); if (memory != nullptr) { return memory; } } Memory* memory = nullptr; Memory* memory; if (pid == getpid()) { memory = new MemoryLocal(); } else { Loading
libunwindstack/include/unwindstack/Elf.h +2 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ class Elf { static bool IsValidElf(Memory* memory); static void GetInfo(Memory* memory, bool* valid, uint64_t* size); protected: bool valid_ = false; std::unique_ptr<ElfInterface> interface_; Loading
libunwindstack/include/unwindstack/ElfInterface.h +11 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ class ElfInterface { virtual bool HandleType(uint64_t, uint32_t) { return false; } template <typename EhdrType> static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size); Memory* memory_; std::unordered_map<uint64_t, LoadInfo> pt_loads_; uint64_t load_bias_ = 0; Loading Loading @@ -146,6 +149,10 @@ class ElfInterface32 : public ElfInterface { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size); } }; class ElfInterface64 : public ElfInterface { Loading @@ -166,6 +173,10 @@ class ElfInterface64 : public ElfInterface { bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset); } static void GetMaxSize(Memory* memory, uint64_t* size) { GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size); } }; } // namespace unwindstack Loading