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

Commit a5913bdd authored by Florian Mayer's avatar Florian Mayer Committed by Gerrit Code Review
Browse files

Merge "Read .note.gnu.build-id."

parents 675a70be da459e56
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -140,6 +140,10 @@ bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
  return true;
}

bool Elf::GetBuildID(std::string* build_id) {
  return valid_ && interface_->GetBuildID(build_id);
}

void Elf::GetLastError(ErrorData* data) {
  if (valid_) {
    *data = interface_->last_error();
+62 −0
Original line number Diff line number Diff line
@@ -237,6 +237,56 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
  }
}

template <typename NhdrType>
bool ElfInterface::ReadBuildID(std::string* build_id) {
  // Ensure there is no overflow in any of the calulations below.
  uint64_t tmp;
  if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) {
    return false;
  }

  uint64_t offset = 0;
  while (offset < gnu_build_id_size_) {
    if (gnu_build_id_size_ - offset < sizeof(NhdrType)) {
      return false;
    }
    NhdrType hdr;
    if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) {
      return false;
    }
    offset += sizeof(hdr);

    if (gnu_build_id_size_ - offset < hdr.n_namesz) {
      return false;
    }
    if (hdr.n_namesz > 0) {
      std::string name(hdr.n_namesz, '\0');
      if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) {
        return false;
      }

      // Trim trailing \0 as GNU is stored as a C string in the ELF file.
      if (name.back() == '\0')
        name.resize(name.size() - 1);

      // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
      offset += (hdr.n_namesz + 3) & ~3;

      if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
        if (gnu_build_id_size_ - offset < hdr.n_descsz) {
          return false;
        }
        build_id->resize(hdr.n_descsz);
        return memory_->ReadFully(gnu_build_id_offset_ + offset, &(*build_id)[0],
                                  hdr.n_descsz);
      }
    }
    // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
    offset += (hdr.n_descsz + 3) & ~3;
  }
  return false;
}

template <typename EhdrType, typename ShdrType>
void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
  uint64_t offset = ehdr.e_shoff;
@@ -308,6 +358,15 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
      // In order to read soname, keep track of address to offset mapping.
      strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
                                                            static_cast<uint64_t>(shdr.sh_offset)));
    } else if (shdr.sh_type == SHT_NOTE) {
      if (shdr.sh_name < sec_size) {
        std::string name;
        if (memory_->ReadString(sec_offset + shdr.sh_name, &name) &&
            name == ".note.gnu.build-id") {
          gnu_build_id_offset_ = shdr.sh_offset;
          gnu_build_id_size_ = shdr.sh_size;
        }
      }
    }
  }
}
@@ -492,6 +551,9 @@ template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf
template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);

template bool ElfInterface::ReadBuildID<Elf32_Nhdr>(std::string*);
template bool ElfInterface::ReadBuildID<Elf64_Nhdr>(std::string*);

template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);

+2 −0
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ class Elf {

  bool GetGlobalVariable(const std::string& name, uint64_t* memory_address);

  bool GetBuildID(std::string* build_id);

  uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);

  bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
+18 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ class ElfInterface {

  virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;

  virtual bool GetBuildID(std::string* build_id) = 0;

  virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);

  virtual bool IsValidPc(uint64_t pc);
@@ -85,6 +87,8 @@ class ElfInterface {
  uint64_t debug_frame_size() { return debug_frame_size_; }
  uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
  uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
  uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; }
  uint64_t gnu_build_id_size() { return gnu_build_id_size_; }

  DwarfSection* eh_frame() { return eh_frame_.get(); }
  DwarfSection* debug_frame() { return debug_frame_.get(); }
@@ -123,6 +127,9 @@ class ElfInterface {
  template <typename EhdrType>
  static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);

  template <typename NhdrType>
  bool ReadBuildID(std::string* build_id);

  Memory* memory_;
  std::unordered_map<uint64_t, LoadInfo> pt_loads_;

@@ -143,6 +150,9 @@ class ElfInterface {
  uint64_t gnu_debugdata_offset_ = 0;
  uint64_t gnu_debugdata_size_ = 0;

  uint64_t gnu_build_id_offset_ = 0;
  uint64_t gnu_build_id_size_ = 0;

  uint8_t soname_type_ = SONAME_UNKNOWN;
  std::string soname_;

@@ -182,6 +192,10 @@ class ElfInterface32 : public ElfInterface {
    return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address);
  }

  bool GetBuildID(std::string* build_id) {
    return ElfInterface::ReadBuildID<Elf32_Nhdr>(build_id);
  }

  static void GetMaxSize(Memory* memory, uint64_t* size) {
    GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size);
  }
@@ -212,6 +226,10 @@ class ElfInterface64 : public ElfInterface {
    return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address);
  }

  bool GetBuildID(std::string* build_id) {
    return ElfInterface::ReadBuildID<Elf64_Nhdr>(build_id);
  }

  static void GetMaxSize(Memory* memory, uint64_t* size) {
    GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size);
  }
+3 −0
Original line number Diff line number Diff line
@@ -72,6 +72,9 @@ class ElfInterfaceFake : public ElfInterface {

  bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
  bool GetGlobalVariable(const std::string&, uint64_t*) override;
  bool GetBuildID(std::string*) override {
    return false;
  }

  bool Step(uint64_t, Regs*, Memory*, bool*) override;

Loading