Add a global elf cache.
Bug: 65682279
Test: Ran new unit tests.
Change-Id: I19c64614b2b11a27f58204d4cc34913c02e04c36
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 89fe038..0c15335 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -109,16 +109,46 @@
// 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) {