Loading libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ cc_test { "tests/DwarfOpTest.cpp", "tests/DwarfSectionTest.cpp", "tests/DwarfSectionImplTest.cpp", "tests/ElfCacheTest.cpp", "tests/ElfFake.cpp", "tests/ElfInterfaceArmTest.cpp", "tests/ElfInterfaceTest.cpp", Loading libunwindstack/Elf.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ namespace unwindstack { bool Elf::cache_enabled_; std::unordered_map<std::string, std::shared_ptr<Elf>>* Elf::cache_; std::mutex* Elf::cache_lock_; bool Elf::Init(bool init_gnu_debugdata) { load_bias_ = 0; if (!memory_) { Loading Loading @@ -301,4 +305,42 @@ uint64_t Elf::GetLoadBias(Memory* memory) { return 0; } void Elf::SetCachingEnabled(bool enable) { if (!cache_enabled_ && enable) { cache_enabled_ = true; cache_ = new std::unordered_map<std::string, std::shared_ptr<Elf>>; cache_lock_ = new std::mutex; } else if (cache_enabled_ && !enable) { cache_enabled_ = false; delete cache_; delete cache_lock_; } } void Elf::CacheLock() { cache_lock_->lock(); } void Elf::CacheUnlock() { cache_lock_->unlock(); } void Elf::CacheAdd(MapInfo* info) { if (info->offset == 0) { (*cache_)[info->name] = info->elf; } else { std::string name(info->name + ':' + std::to_string(info->offset)); (*cache_)[name] = info->elf; } } bool Elf::CacheGet(const std::string& name, std::shared_ptr<Elf>* elf) { auto entry = cache_->find(name); if (entry != cache_->end()) { *elf = entry->second; return true; } return false; } } // namespace unwindstack libunwindstack/MapInfo.cpp +35 −5 Original line number Diff line number Diff line Loading @@ -109,16 +109,46 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gn // Make sure no other thread is trying to add the elf to this map. std::lock_guard<std::mutex> guard(mutex_); if (elf) { return elf; if (elf.get() != nullptr) { return elf.get(); } elf = new Elf(CreateMemory(process_memory)); elf->Init(init_gnu_debugdata); bool locked = false; if (Elf::CachingEnabled() && !name.empty()) { Elf::CacheLock(); locked = true; if (offset != 0) { std::string hash(name + ':' + std::to_string(offset)); if (Elf::CacheGet(hash, &elf)) { Elf::CacheUnlock(); return elf.get(); } } else if (Elf::CacheGet(name, &elf)) { Elf::CacheUnlock(); return elf.get(); } } Memory* memory = CreateMemory(process_memory); if (locked && offset != 0 && elf_offset != 0) { // In this case, the whole file is the elf, need to see if the elf // data was cached. if (Elf::CacheGet(name, &elf)) { delete memory; Elf::CacheUnlock(); return elf.get(); } } elf.reset(new Elf(memory)); // If the init fails, keep the elf around as an invalid object so we // don't try to reinit the object. return elf; elf->Init(init_gnu_debugdata); if (locked) { Elf::CacheAdd(this); Elf::CacheUnlock(); } return elf.get(); } uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) { Loading libunwindstack/include/unwindstack/Elf.h +13 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <memory> #include <mutex> #include <string> #include <unordered_map> #include <unwindstack/ElfInterface.h> #include <unwindstack/Memory.h> Loading Loading @@ -96,6 +97,14 @@ class Elf { static uint64_t GetLoadBias(Memory* memory); static void SetCachingEnabled(bool enable); static bool CachingEnabled() { return cache_enabled_; } static void CacheLock(); static void CacheUnlock(); static void CacheAdd(MapInfo* info); static bool CacheGet(const std::string& name, std::shared_ptr<Elf>* elf); protected: bool valid_ = false; uint64_t load_bias_ = 0; Loading @@ -109,6 +118,10 @@ class Elf { std::unique_ptr<Memory> gnu_debugdata_memory_; std::unique_ptr<ElfInterface> gnu_debugdata_interface_; static bool cache_enabled_; static std::unordered_map<std::string, std::shared_ptr<Elf>>* cache_; static std::mutex* cache_lock_; }; } // namespace unwindstack Loading libunwindstack/include/unwindstack/MapInfo.h +3 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <stdint.h> #include <atomic> #include <memory> #include <mutex> #include <string> Loading @@ -40,14 +41,14 @@ struct MapInfo { flags(flags), name(name), load_bias(static_cast<uint64_t>(-1)) {} ~MapInfo() { delete elf; } ~MapInfo() = default; uint64_t start = 0; uint64_t end = 0; uint64_t offset = 0; uint16_t flags = 0; std::string name; Elf* elf = nullptr; std::shared_ptr<Elf> elf; // This value is only non-zero if the offset is non-zero but there is // no elf signature found at that offset. This indicates that the // entire file is represented by the Memory object returned by CreateMemory, Loading Loading
libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ cc_test { "tests/DwarfOpTest.cpp", "tests/DwarfSectionTest.cpp", "tests/DwarfSectionImplTest.cpp", "tests/ElfCacheTest.cpp", "tests/ElfFake.cpp", "tests/ElfInterfaceArmTest.cpp", "tests/ElfInterfaceTest.cpp", Loading
libunwindstack/Elf.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ namespace unwindstack { bool Elf::cache_enabled_; std::unordered_map<std::string, std::shared_ptr<Elf>>* Elf::cache_; std::mutex* Elf::cache_lock_; bool Elf::Init(bool init_gnu_debugdata) { load_bias_ = 0; if (!memory_) { Loading Loading @@ -301,4 +305,42 @@ uint64_t Elf::GetLoadBias(Memory* memory) { return 0; } void Elf::SetCachingEnabled(bool enable) { if (!cache_enabled_ && enable) { cache_enabled_ = true; cache_ = new std::unordered_map<std::string, std::shared_ptr<Elf>>; cache_lock_ = new std::mutex; } else if (cache_enabled_ && !enable) { cache_enabled_ = false; delete cache_; delete cache_lock_; } } void Elf::CacheLock() { cache_lock_->lock(); } void Elf::CacheUnlock() { cache_lock_->unlock(); } void Elf::CacheAdd(MapInfo* info) { if (info->offset == 0) { (*cache_)[info->name] = info->elf; } else { std::string name(info->name + ':' + std::to_string(info->offset)); (*cache_)[name] = info->elf; } } bool Elf::CacheGet(const std::string& name, std::shared_ptr<Elf>* elf) { auto entry = cache_->find(name); if (entry != cache_->end()) { *elf = entry->second; return true; } return false; } } // namespace unwindstack
libunwindstack/MapInfo.cpp +35 −5 Original line number Diff line number Diff line Loading @@ -109,16 +109,46 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gn // Make sure no other thread is trying to add the elf to this map. std::lock_guard<std::mutex> guard(mutex_); if (elf) { return elf; if (elf.get() != nullptr) { return elf.get(); } elf = new Elf(CreateMemory(process_memory)); elf->Init(init_gnu_debugdata); bool locked = false; if (Elf::CachingEnabled() && !name.empty()) { Elf::CacheLock(); locked = true; if (offset != 0) { std::string hash(name + ':' + std::to_string(offset)); if (Elf::CacheGet(hash, &elf)) { Elf::CacheUnlock(); return elf.get(); } } else if (Elf::CacheGet(name, &elf)) { Elf::CacheUnlock(); return elf.get(); } } Memory* memory = CreateMemory(process_memory); if (locked && offset != 0 && elf_offset != 0) { // In this case, the whole file is the elf, need to see if the elf // data was cached. if (Elf::CacheGet(name, &elf)) { delete memory; Elf::CacheUnlock(); return elf.get(); } } elf.reset(new Elf(memory)); // If the init fails, keep the elf around as an invalid object so we // don't try to reinit the object. return elf; elf->Init(init_gnu_debugdata); if (locked) { Elf::CacheAdd(this); Elf::CacheUnlock(); } return elf.get(); } uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) { Loading
libunwindstack/include/unwindstack/Elf.h +13 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <memory> #include <mutex> #include <string> #include <unordered_map> #include <unwindstack/ElfInterface.h> #include <unwindstack/Memory.h> Loading Loading @@ -96,6 +97,14 @@ class Elf { static uint64_t GetLoadBias(Memory* memory); static void SetCachingEnabled(bool enable); static bool CachingEnabled() { return cache_enabled_; } static void CacheLock(); static void CacheUnlock(); static void CacheAdd(MapInfo* info); static bool CacheGet(const std::string& name, std::shared_ptr<Elf>* elf); protected: bool valid_ = false; uint64_t load_bias_ = 0; Loading @@ -109,6 +118,10 @@ class Elf { std::unique_ptr<Memory> gnu_debugdata_memory_; std::unique_ptr<ElfInterface> gnu_debugdata_interface_; static bool cache_enabled_; static std::unordered_map<std::string, std::shared_ptr<Elf>>* cache_; static std::mutex* cache_lock_; }; } // namespace unwindstack Loading
libunwindstack/include/unwindstack/MapInfo.h +3 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <stdint.h> #include <atomic> #include <memory> #include <mutex> #include <string> Loading @@ -40,14 +41,14 @@ struct MapInfo { flags(flags), name(name), load_bias(static_cast<uint64_t>(-1)) {} ~MapInfo() { delete elf; } ~MapInfo() = default; uint64_t start = 0; uint64_t end = 0; uint64_t offset = 0; uint16_t flags = 0; std::string name; Elf* elf = nullptr; std::shared_ptr<Elf> elf; // This value is only non-zero if the offset is non-zero but there is // no elf signature found at that offset. This indicates that the // entire file is represented by the Memory object returned by CreateMemory, Loading