Add a global elf cache.

Bug: 65682279

Test: Ran new unit tests.
Change-Id: I19c64614b2b11a27f58204d4cc34913c02e04c36
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index f120da2..dbf772e 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -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_) {
@@ -301,4 +305,42 @@
   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