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

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

Merge "Cache DWARF location rules for a given pc."

parents 85d9e673 3386ebad
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -50,7 +50,17 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
  memory_->set_cur_offset(start_offset);
  uint64_t cfa_offset;
  cur_pc_ = fde_->pc_start;
  while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc_ <= pc) {
  loc_regs->pc_start = cur_pc_;
  while (true) {
    if (cur_pc_ > pc) {
      loc_regs->pc_end = cur_pc_;
      return true;
    }
    if ((cfa_offset = memory_->cur_offset()) >= end_offset) {
      loc_regs->pc_end = fde_->pc_end;
      return true;
    }
    loc_regs->pc_start = cur_pc_;
    operands_.clear();
    // Read the cfa information.
    uint8_t cfa_value;
@@ -129,7 +139,6 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
      }
    }
  }
  return true;
}

template <typename AddressType>
+19 −11
Original line number Diff line number Diff line
@@ -55,6 +55,9 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
}

bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
  // Lookup the pc in the cache.
  auto it = loc_regs_.upper_bound(pc);
  if (it == loc_regs_.end() || pc < it->second.pc_start) {
    last_error_.code = DWARF_ERROR_NONE;
    const DwarfFde* fde = GetFdeFromPc(pc);
    if (fde == nullptr || fde->cie == nullptr) {
@@ -67,9 +70,14 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f
    if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
      return false;
    }
    loc_regs.cie = fde->cie;

    // Store it in the cache.
    it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
  }

  // Now eval the actual registers.
  return Eval(fde->cie, process_memory, loc_regs, regs, finished);
  return Eval(it->second.cie, process_memory, it->second, regs, finished);
}

template <typename AddressType>
+9 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@

namespace unwindstack {

struct DwarfCie;

enum DwarfLocationEnum : uint8_t {
  DWARF_LOCATION_INVALID = 0,
  DWARF_LOCATION_UNDEFINED,
@@ -38,7 +40,13 @@ struct DwarfLocation {
  uint64_t values[2];
};

typedef std::unordered_map<uint32_t, DwarfLocation> dwarf_loc_regs_t;
struct DwarfLocations : public std::unordered_map<uint32_t, DwarfLocation> {
  const DwarfCie* cie;
  // The range of PCs where the locations are valid (end is exclusive).
  uint64_t pc_start = 0;
  uint64_t pc_end = 0;
};
typedef DwarfLocations dwarf_loc_regs_t;

}  // namespace unwindstack

+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <stdint.h>

#include <iterator>
#include <map>
#include <unordered_map>

#include <unwindstack/DwarfError.h>
@@ -112,6 +113,7 @@ class DwarfSection {
  std::unordered_map<uint64_t, DwarfFde> fde_entries_;
  std::unordered_map<uint64_t, DwarfCie> cie_entries_;
  std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
  std::map<uint64_t, dwarf_loc_regs_t> loc_regs_;  // Single row indexed by pc_end.
};

template <typename AddressType>
+2 −1
Original line number Diff line number Diff line
@@ -853,7 +853,8 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
  fde.cfa_instructions_offset = 0x6000;
  fde.cfa_instructions_end = 0x6002;

  dwarf_loc_regs_t cie_loc_regs{{6, {DWARF_LOCATION_REGISTER, {4, 0}}}};
  dwarf_loc_regs_t cie_loc_regs;
  cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
  this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
  this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});

Loading