Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb4d172f authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Add a global elf cache."

parents 1e11f5f7 0b79ae15
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+42 −0
Original line number Diff line number Diff line
@@ -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 @@ 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
+35 −5
Original line number Diff line number Diff line
@@ -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) {
+13 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>

#include <unwindstack/ElfInterface.h>
#include <unwindstack/Memory.h>
@@ -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;
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <stdint.h>

#include <atomic>
#include <memory>
#include <mutex>
#include <string>

@@ -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