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

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

Merge "Fix potential bad info in eh_frame_hdr."

parents e901d3a3 4ca98e18
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -26,9 +26,9 @@
namespace unwindstack {

template <typename AddressType>
class DwarfDebugFrame : public DwarfSectionImplNoHdr<AddressType> {
class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
 public:
  DwarfDebugFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {
  DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
    this->cie32_value_ = static_cast<uint32_t>(-1);
    this->cie64_value_ = static_cast<uint64_t>(-1);
  }
+2 −2
Original line number Diff line number Diff line
@@ -25,9 +25,9 @@
namespace unwindstack {

template <typename AddressType>
class DwarfEhFrame : public DwarfSectionImplNoHdr<AddressType> {
class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
 public:
  DwarfEhFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {}
  DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
  virtual ~DwarfEhFrame() = default;

  uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
+36 −12
Original line number Diff line number Diff line
@@ -32,14 +32,19 @@ static inline bool IsEncodingRelative(uint8_t encoding) {
}

template <typename AddressType>
bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
  section_bias_ = section_bias;
bool DwarfEhFrameWithHdr<AddressType>::EhFrameInit(uint64_t offset, uint64_t size,
                                                   int64_t section_bias) {
  return DwarfSectionImpl<AddressType>::Init(offset, size, section_bias);
}

template <typename AddressType>
bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t, int64_t section_bias) {
  memory_.clear_func_offset();
  memory_.clear_text_offset();
  memory_.set_data_offset(offset);
  memory_.set_cur_offset(offset);
  pc_offset_ = offset;

  hdr_section_bias_ = section_bias;

  // Read the first four bytes all at once.
  uint8_t data[4];
@@ -56,7 +61,7 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int6
    return false;
  }

  ptr_encoding_ = data[1];
  uint8_t ptr_encoding = data[1];
  uint8_t fde_count_encoding = data[2];
  table_encoding_ = data[3];
  table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_);
@@ -70,7 +75,8 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int6
  }

  memory_.set_pc_offset(memory_.cur_offset());
  if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) {
  uint64_t ptr_offset;
  if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding, &ptr_offset)) {
    last_error_.code = DWARF_ERROR_MEMORY_INVALID;
    last_error_.address = memory_.cur_offset();
    return false;
@@ -88,10 +94,8 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, int6
    return false;
  }

  entries_offset_ = memory_.cur_offset();
  entries_end_ = offset + size;
  entries_data_offset_ = offset;
  cur_entries_offset_ = entries_offset_;
  hdr_entries_offset_ = memory_.cur_offset();
  hdr_entries_data_offset_ = offset;

  return true;
}
@@ -107,6 +111,16 @@ const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
    return nullptr;
  }

  // There is a possibility that this entry points to a zero length FDE
  // due to a bug. If this happens, try and find the non-zero length FDE
  // from eh_frame directly. See b/142483624.
  if (fde->pc_start == fde->pc_end) {
    fde = DwarfSectionImpl<AddressType>::GetFdeFromPc(pc);
    if (fde == nullptr) {
      return nullptr;
    }
  }

  // Guaranteed pc >= pc_start, need to check pc in the fde range.
  if (pc < fde->pc_end) {
    return fde;
@@ -124,8 +138,8 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
  }
  FdeInfo* info = &fde_info_[index];

  memory_.set_data_offset(entries_data_offset_);
  memory_.set_cur_offset(entries_offset_ + 2 * index * table_entry_size_);
  memory_.set_data_offset(hdr_entries_data_offset_);
  memory_.set_cur_offset(hdr_entries_offset_ + 2 * index * table_entry_size_);
  memory_.set_pc_offset(0);
  uint64_t value;
  if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
@@ -138,7 +152,7 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {

  // Relative encodings require adding in the load bias.
  if (IsEncodingRelative(table_encoding_)) {
    value += section_bias_;
    value += hdr_section_bias_;
  }
  info->pc = value;
  return info;
@@ -190,6 +204,16 @@ void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fde
    if (fde == nullptr) {
      break;
    }

    // There is a possibility that this entry points to a zero length FDE
    // due to a bug. If this happens, try and find the non-zero length FDE
    // from eh_frame directly. See b/142483624.
    if (fde->pc_start == fde->pc_end) {
      const DwarfFde* fde_real = DwarfSectionImpl<AddressType>::GetFdeFromPc(fde->pc_start);
      if (fde_real != nullptr) {
        fde = fde_real;
      }
    }
    fdes->push_back(fde);
  }
}
+11 −16
Original line number Diff line number Diff line
@@ -34,11 +34,7 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
  // Add these so that the protected members of DwarfSectionImpl
  // can be accessed without needing a this->.
  using DwarfSectionImpl<AddressType>::memory_;
  using DwarfSectionImpl<AddressType>::pc_offset_;
  using DwarfSectionImpl<AddressType>::entries_offset_;
  using DwarfSectionImpl<AddressType>::entries_end_;
  using DwarfSectionImpl<AddressType>::last_error_;
  using DwarfSectionImpl<AddressType>::section_bias_;

  struct FdeInfo {
    AddressType pc;
@@ -49,18 +45,19 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
  virtual ~DwarfEhFrameWithHdr() = default;

  uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
    return this->memory_.cur_offset() - pointer - 4;
    return memory_.cur_offset() - pointer - 4;
  }

  uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
    return this->memory_.cur_offset() - pointer - 8;
    return memory_.cur_offset() - pointer - 8;
  }

  uint64_t AdjustPcFromFde(uint64_t pc) override {
    // The eh_frame uses relative pcs.
    return pc + this->memory_.cur_offset() - 4;
    return pc + memory_.cur_offset() - 4;
  }

  bool EhFrameInit(uint64_t offset, uint64_t size, int64_t section_bias);
  bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;

  const DwarfFde* GetFdeFromPc(uint64_t pc) override;
@@ -72,17 +69,15 @@ class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
  void GetFdes(std::vector<const DwarfFde*>* fdes) override;

 protected:
  uint8_t version_;
  uint8_t ptr_encoding_;
  uint8_t table_encoding_;
  size_t table_entry_size_;
  uint8_t version_ = 0;
  uint8_t table_encoding_ = 0;
  size_t table_entry_size_ = 0;

  uint64_t ptr_offset_;
  uint64_t hdr_entries_offset_ = 0;
  uint64_t hdr_entries_data_offset_ = 0;
  uint64_t hdr_section_bias_ = 0;

  uint64_t entries_data_offset_;
  uint64_t cur_entries_offset_ = 0;

  uint64_t fde_count_;
  uint64_t fde_count_ = 0;
  std::unordered_map<uint64_t, FdeInfo> fde_info_;
};

+35 −30
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset)
    return &cie_entry->second;
  }
  DwarfCie* cie = &cie_entries_[offset];
  memory_.set_data_offset(entries_offset_);
  memory_.set_cur_offset(offset);
  if (!FillInCieHeader(cie) || !FillInCie(cie)) {
    // Erase the cached entry.
@@ -251,6 +252,7 @@ const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset)
    return &fde_entry->second;
  }
  DwarfFde* fde = &fde_entries_[offset];
  memory_.set_data_offset(entries_offset_);
  memory_.set_cur_offset(offset);
  if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
    fde_entries_.erase(offset);
@@ -591,8 +593,7 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const Dwarf
}

template <typename AddressType>
bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size,
                                              int64_t section_bias) {
bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
  section_bias_ = section_bias;
  entries_offset_ = offset;
  next_entries_offset_ = offset;
@@ -601,7 +602,6 @@ bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size,
  memory_.clear_func_offset();
  memory_.clear_text_offset();
  memory_.set_cur_offset(offset);
  memory_.set_data_offset(offset);
  pc_offset_ = offset;

  return true;
@@ -617,7 +617,7 @@ bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size,
// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
// will be added: 0x200, 0x100 and 0x500, 0x400.
template <typename AddressType>
void DwarfSectionImplNoHdr<AddressType>::InsertFde(const DwarfFde* fde) {
void DwarfSectionImpl<AddressType>::InsertFde(const DwarfFde* fde) {
  uint64_t start = fde->pc_start;
  uint64_t end = fde->pc_end;
  auto it = fdes_.upper_bound(start);
@@ -654,9 +654,10 @@ void DwarfSectionImplNoHdr<AddressType>::InsertFde(const DwarfFde* fde) {
}

template <typename AddressType>
bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(const DwarfFde** fde_entry) {
  uint64_t start_offset = next_entries_offset_;

  memory_.set_data_offset(entries_offset_);
  memory_.set_cur_offset(next_entries_offset_);
  uint32_t value32;
  if (!memory_.ReadBytes(&value32, sizeof(value32))) {
@@ -689,7 +690,7 @@ bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
      entry_is_cie = true;
      cie_fde_encoding = DW_EH_PE_sdata8;
    } else {
      cie_offset = this->GetCieOffsetFromFde64(value64);
      cie_offset = GetCieOffsetFromFde64(value64);
    }
  } else {
    next_entries_offset_ = memory_.cur_offset() + value32;
@@ -705,37 +706,45 @@ bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
      entry_is_cie = true;
      cie_fde_encoding = DW_EH_PE_sdata4;
    } else {
      cie_offset = this->GetCieOffsetFromFde32(value32);
      cie_offset = GetCieOffsetFromFde32(value32);
    }
  }

  if (entry_is_cie) {
    auto entry = cie_entries_.find(start_offset);
    if (entry == cie_entries_.end()) {
      DwarfCie* cie = &cie_entries_[start_offset];
      cie->lsda_encoding = DW_EH_PE_omit;
      cie->cfa_instructions_end = next_entries_offset_;
      cie->fde_address_encoding = cie_fde_encoding;

    if (!this->FillInCie(cie)) {
      if (!FillInCie(cie)) {
        cie_entries_.erase(start_offset);
        return false;
      }
    }
    *fde_entry = nullptr;
  } else {
    auto entry = fde_entries_.find(start_offset);
    if (entry != fde_entries_.end()) {
      *fde_entry = &entry->second;
    } else {
      DwarfFde* fde = &fde_entries_[start_offset];
      fde->cfa_instructions_end = next_entries_offset_;
      fde->cie_offset = cie_offset;

    if (!this->FillInFde(fde)) {
      if (!FillInFde(fde)) {
        fde_entries_.erase(start_offset);
        return false;
      }
      *fde_entry = fde;
    }
  }
  return true;
}

template <typename AddressType>
void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
  // Loop through the already cached entries.
  uint64_t entry_offset = entries_offset_;
  while (entry_offset < next_entries_offset_) {
@@ -754,7 +763,7 @@ void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* f
  }

  while (next_entries_offset_ < entries_end_) {
    DwarfFde* fde;
    const DwarfFde* fde;
    if (!GetNextCieOrFde(&fde)) {
      break;
    }
@@ -771,7 +780,7 @@ void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* f
}

template <typename AddressType>
const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
  // Search in the list of fdes we already have.
  auto it = fdes_.upper_bound(pc);
  if (it != fdes_.end()) {
@@ -784,7 +793,7 @@ const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
  // to do a linear search of the fdes by pc. As fdes are read, a cached
  // search map is created.
  while (next_entries_offset_ < entries_end_) {
    DwarfFde* fde;
    const DwarfFde* fde;
    if (!GetNextCieOrFde(&fde)) {
      return nullptr;
    }
@@ -807,10 +816,6 @@ const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
template class DwarfSectionImpl<uint32_t>;
template class DwarfSectionImpl<uint64_t>;

// Explicitly instantiate DwarfSectionImplNoHdr
template class DwarfSectionImplNoHdr<uint32_t>;
template class DwarfSectionImplNoHdr<uint64_t>;

// Explicitly instantiate DwarfDebugFrame
template class DwarfDebugFrame<uint32_t>;
template class DwarfDebugFrame<uint64_t>;
Loading