Loading libunwindstack/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ cc_library { "Elf.cpp", "Elf.cpp", "ElfInterface.cpp", "ElfInterface.cpp", "ElfInterfaceArm.cpp", "ElfInterfaceArm.cpp", "Global.cpp", "JitDebug.cpp", "JitDebug.cpp", "Log.cpp", "Log.cpp", "MapInfo.cpp", "MapInfo.cpp", Loading libunwindstack/DexFiles.cpp +8 −32 Original line number Original line Diff line number Diff line Loading @@ -43,10 +43,10 @@ struct DEXFileEntry64 { uint64_t dex_file; uint64_t dex_file; }; }; DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {} DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {} DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} : Global(memory, search_libs) {} DexFiles::~DexFiles() { DexFiles::~DexFiles() { for (auto& entry : files_) { for (auto& entry : files_) { Loading Loading @@ -117,6 +117,11 @@ bool DexFiles::ReadEntry64() { return true; return true; } } bool DexFiles::ReadVariableData(uint64_t ptr_offset) { entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset); return entry_addr_ != 0; } void DexFiles::Init(Maps* maps) { void DexFiles::Init(Maps* maps) { if (initialized_) { if (initialized_) { return; return; Loading @@ -124,36 +129,7 @@ void DexFiles::Init(Maps* maps) { initialized_ = true; initialized_ = true; entry_addr_ = 0; entry_addr_ = 0; const std::string dex_debug_name("__dex_debug_descriptor"); FindAndReadVariable(maps, "__dex_debug_descriptor"); for (MapInfo* info : *maps) { if (!(info->flags & PROT_READ) || info->offset != 0) { continue; } if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { continue; } } Elf* elf = info->GetElf(memory_, true); uint64_t ptr; // Find first non-empty list (libart might be loaded multiple times). if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) { entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start); if (entry_addr_ != 0) { break; } } } } } DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) { DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) { Loading libunwindstack/Global.cpp 0 → 100644 +96 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <sys/mman.h> #include <string> #include <vector> #include <unwindstack/Global.h> #include <unwindstack/MapInfo.h> #include <unwindstack/Maps.h> #include <unwindstack/Memory.h> namespace unwindstack { Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {} Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { return 0; } } Elf* elf = info->GetElf(memory_, true); uint64_t ptr; // Find first non-empty list (libraries might be loaded multiple times). if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) { return ptr + info->start; } return 0; } void Global::FindAndReadVariable(Maps* maps, const char* var_str) { std::string variable(var_str); // When looking for global variables, do not arbitrarily search every // readable map. Instead look for a specific pattern that must exist. // The pattern should be a readable map, followed by a read-write // map with a non-zero offset. // For example: // f0000-f1000 0 r-- /system/lib/libc.so // f1000-f2000 1000 r-x /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so // This also works: // f0000-f2000 0 r-- /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; for (MapInfo* info : *maps) { if (map_start != nullptr) { if (map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { uint64_t ptr = GetVariableOffset(map_start, variable); if (ptr != 0 && ReadVariableData(ptr)) { break; } else { // Failed to find the global variable, do not bother trying again. map_start = nullptr; } } } else { map_start = nullptr; } } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && !info->name.empty()) { map_start = info; } } } } // namespace unwindstack libunwindstack/JitDebug.cpp +8 −32 Original line number Original line Diff line number Diff line Loading @@ -69,10 +69,10 @@ struct JITDescriptor64 { uint64_t first_entry; uint64_t first_entry; }; }; JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {} JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {} JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} : Global(memory, search_libs) {} JitDebug::~JitDebug() { JitDebug::~JitDebug() { for (auto* elf : elf_list_) { for (auto* elf : elf_list_) { Loading Loading @@ -165,6 +165,11 @@ void JitDebug::SetArch(ArchEnum arch) { } } } } bool JitDebug::ReadVariableData(uint64_t ptr) { entry_addr_ = (this->*read_descriptor_func_)(ptr); return entry_addr_ != 0; } void JitDebug::Init(Maps* maps) { void JitDebug::Init(Maps* maps) { if (initialized_) { if (initialized_) { return; return; Loading @@ -172,36 +177,7 @@ void JitDebug::Init(Maps* maps) { // Regardless of what happens below, consider the init finished. // Regardless of what happens below, consider the init finished. initialized_ = true; initialized_ = true; const std::string descriptor_name("__jit_debug_descriptor"); FindAndReadVariable(maps, "__jit_debug_descriptor"); for (MapInfo* info : *maps) { if (!(info->flags & PROT_READ) || info->offset != 0) { continue; } if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (std::string& name : search_libs_) { if (strcmp(name.c_str(), lib) == 0) { found = true; break; } } if (!found) { continue; } } Elf* elf = info->GetElf(memory_, true); uint64_t descriptor_addr; // Find first non-empty entry (libart might be loaded multiple times). if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) { entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start); if (entry_addr_ != 0) { break; } } } } } Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) { Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) { Loading libunwindstack/include/unwindstack/DexFiles.h +5 −4 Original line number Original line Diff line number Diff line Loading @@ -25,16 +25,18 @@ #include <unordered_map> #include <unordered_map> #include <vector> #include <vector> #include <unwindstack/Global.h> #include <unwindstack/Memory.h> namespace unwindstack { namespace unwindstack { // Forward declarations. // Forward declarations. class DexFile; class DexFile; class Maps; class Maps; struct MapInfo; struct MapInfo; class Memory; enum ArchEnum : uint8_t; enum ArchEnum : uint8_t; class DexFiles { class DexFiles : public Global { public: public: explicit DexFiles(std::shared_ptr<Memory>& memory); explicit DexFiles(std::shared_ptr<Memory>& memory); DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs); DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs); Loading @@ -60,8 +62,7 @@ class DexFiles { bool ReadEntry64(); bool ReadEntry64(); std::shared_ptr<Memory> memory_; bool ReadVariableData(uint64_t ptr_offset) override; std::vector<std::string> search_libs_; std::mutex lock_; std::mutex lock_; bool initialized_ = false; bool initialized_ = false; Loading Loading
libunwindstack/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ cc_library { "Elf.cpp", "Elf.cpp", "ElfInterface.cpp", "ElfInterface.cpp", "ElfInterfaceArm.cpp", "ElfInterfaceArm.cpp", "Global.cpp", "JitDebug.cpp", "JitDebug.cpp", "Log.cpp", "Log.cpp", "MapInfo.cpp", "MapInfo.cpp", Loading
libunwindstack/DexFiles.cpp +8 −32 Original line number Original line Diff line number Diff line Loading @@ -43,10 +43,10 @@ struct DEXFileEntry64 { uint64_t dex_file; uint64_t dex_file; }; }; DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {} DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {} DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} : Global(memory, search_libs) {} DexFiles::~DexFiles() { DexFiles::~DexFiles() { for (auto& entry : files_) { for (auto& entry : files_) { Loading Loading @@ -117,6 +117,11 @@ bool DexFiles::ReadEntry64() { return true; return true; } } bool DexFiles::ReadVariableData(uint64_t ptr_offset) { entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset); return entry_addr_ != 0; } void DexFiles::Init(Maps* maps) { void DexFiles::Init(Maps* maps) { if (initialized_) { if (initialized_) { return; return; Loading @@ -124,36 +129,7 @@ void DexFiles::Init(Maps* maps) { initialized_ = true; initialized_ = true; entry_addr_ = 0; entry_addr_ = 0; const std::string dex_debug_name("__dex_debug_descriptor"); FindAndReadVariable(maps, "__dex_debug_descriptor"); for (MapInfo* info : *maps) { if (!(info->flags & PROT_READ) || info->offset != 0) { continue; } if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { continue; } } Elf* elf = info->GetElf(memory_, true); uint64_t ptr; // Find first non-empty list (libart might be loaded multiple times). if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) { entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start); if (entry_addr_ != 0) { break; } } } } } DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) { DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) { Loading
libunwindstack/Global.cpp 0 → 100644 +96 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdint.h> #include <sys/mman.h> #include <string> #include <vector> #include <unwindstack/Global.h> #include <unwindstack/MapInfo.h> #include <unwindstack/Maps.h> #include <unwindstack/Memory.h> namespace unwindstack { Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {} Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (const std::string& name : search_libs_) { if (name == lib) { found = true; break; } } if (!found) { return 0; } } Elf* elf = info->GetElf(memory_, true); uint64_t ptr; // Find first non-empty list (libraries might be loaded multiple times). if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) { return ptr + info->start; } return 0; } void Global::FindAndReadVariable(Maps* maps, const char* var_str) { std::string variable(var_str); // When looking for global variables, do not arbitrarily search every // readable map. Instead look for a specific pattern that must exist. // The pattern should be a readable map, followed by a read-write // map with a non-zero offset. // For example: // f0000-f1000 0 r-- /system/lib/libc.so // f1000-f2000 1000 r-x /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so // This also works: // f0000-f2000 0 r-- /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; for (MapInfo* info : *maps) { if (map_start != nullptr) { if (map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { uint64_t ptr = GetVariableOffset(map_start, variable); if (ptr != 0 && ReadVariableData(ptr)) { break; } else { // Failed to find the global variable, do not bother trying again. map_start = nullptr; } } } else { map_start = nullptr; } } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && !info->name.empty()) { map_start = info; } } } } // namespace unwindstack
libunwindstack/JitDebug.cpp +8 −32 Original line number Original line Diff line number Diff line Loading @@ -69,10 +69,10 @@ struct JITDescriptor64 { uint64_t first_entry; uint64_t first_entry; }; }; JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {} JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {} JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} : Global(memory, search_libs) {} JitDebug::~JitDebug() { JitDebug::~JitDebug() { for (auto* elf : elf_list_) { for (auto* elf : elf_list_) { Loading Loading @@ -165,6 +165,11 @@ void JitDebug::SetArch(ArchEnum arch) { } } } } bool JitDebug::ReadVariableData(uint64_t ptr) { entry_addr_ = (this->*read_descriptor_func_)(ptr); return entry_addr_ != 0; } void JitDebug::Init(Maps* maps) { void JitDebug::Init(Maps* maps) { if (initialized_) { if (initialized_) { return; return; Loading @@ -172,36 +177,7 @@ void JitDebug::Init(Maps* maps) { // Regardless of what happens below, consider the init finished. // Regardless of what happens below, consider the init finished. initialized_ = true; initialized_ = true; const std::string descriptor_name("__jit_debug_descriptor"); FindAndReadVariable(maps, "__jit_debug_descriptor"); for (MapInfo* info : *maps) { if (!(info->flags & PROT_READ) || info->offset != 0) { continue; } if (!search_libs_.empty()) { bool found = false; const char* lib = basename(info->name.c_str()); for (std::string& name : search_libs_) { if (strcmp(name.c_str(), lib) == 0) { found = true; break; } } if (!found) { continue; } } Elf* elf = info->GetElf(memory_, true); uint64_t descriptor_addr; // Find first non-empty entry (libart might be loaded multiple times). if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) { entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start); if (entry_addr_ != 0) { break; } } } } } Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) { Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) { Loading
libunwindstack/include/unwindstack/DexFiles.h +5 −4 Original line number Original line Diff line number Diff line Loading @@ -25,16 +25,18 @@ #include <unordered_map> #include <unordered_map> #include <vector> #include <vector> #include <unwindstack/Global.h> #include <unwindstack/Memory.h> namespace unwindstack { namespace unwindstack { // Forward declarations. // Forward declarations. class DexFile; class DexFile; class Maps; class Maps; struct MapInfo; struct MapInfo; class Memory; enum ArchEnum : uint8_t; enum ArchEnum : uint8_t; class DexFiles { class DexFiles : public Global { public: public: explicit DexFiles(std::shared_ptr<Memory>& memory); explicit DexFiles(std::shared_ptr<Memory>& memory); DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs); DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs); Loading @@ -60,8 +62,7 @@ class DexFiles { bool ReadEntry64(); bool ReadEntry64(); std::shared_ptr<Memory> memory_; bool ReadVariableData(uint64_t ptr_offset) override; std::vector<std::string> search_libs_; std::mutex lock_; std::mutex lock_; bool initialized_ = false; bool initialized_ = false; Loading