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

Commit 299aa7a6 authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Merge "Fix soname reading code."

am: 76eda07f

Change-Id: I659a84ac44940ac38a8d31f9a5c3cb102435da07
parents 67378615 76eda07f
Loading
Loading
Loading
Loading
+27 −44
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <memory>
#include <string>
#include <utility>

#include <7zCrc.h>
#include <Xz.h>
@@ -322,19 +323,13 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
  // Skip the first header, it's always going to be NULL.
  offset += ehdr.e_shentsize;
  for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
    if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
    if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
      last_error_.code = ERROR_MEMORY_INVALID;
      last_error_.address =
          offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr);
      last_error_.address = offset;
      return false;
    }

    if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
      if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
        last_error_.code = ERROR_MEMORY_INVALID;
        last_error_.address = offset;
        return false;
      }
      // Need to go get the information about the section that contains
      // the string terminated names.
      ShdrType str_shdr;
@@ -343,39 +338,19 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
        return false;
      }
      uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
      if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
        last_error_.code = ERROR_MEMORY_INVALID;
        last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) -
                              reinterpret_cast<uintptr_t>(&str_shdr);
        last_error_.address = str_offset;
        return false;
      }
      if (str_shdr.sh_type != SHT_STRTAB) {
        last_error_.code = ERROR_UNWIND_INFO;
        return false;
      }
      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
                              sizeof(str_shdr.sh_offset))) {
        last_error_.code = ERROR_MEMORY_INVALID;
        last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) -
                              reinterpret_cast<uintptr_t>(&str_shdr);
        return false;
      }
      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
        last_error_.code = ERROR_MEMORY_INVALID;
        last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) -
                              reinterpret_cast<uintptr_t>(&str_shdr);
        return false;
      }
      symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
                                     str_shdr.sh_offset, str_shdr.sh_size));
    } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
      // Look for the .debug_frame and .gnu_debugdata.
      if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
        last_error_.code = ERROR_MEMORY_INVALID;
        last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) -
                              reinterpret_cast<uintptr_t>(&shdr);
        return false;
      }
      if (shdr.sh_name < sec_size) {
        std::string name;
        if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
@@ -394,14 +369,16 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
            offset_ptr = &eh_frame_hdr_offset_;
            size_ptr = &eh_frame_hdr_size_;
          }
          if (offset_ptr != nullptr &&
              memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
              memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
          if (offset_ptr != nullptr) {
            *offset_ptr = shdr.sh_offset;
            *size_ptr = shdr.sh_size;
          }
        }
      }
    } else if (shdr.sh_type == SHT_STRTAB) {
      // 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)));
    }
  }
  return true;
@@ -420,7 +397,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
  soname_type_ = SONAME_INVALID;

  uint64_t soname_offset = 0;
  uint64_t strtab_offset = 0;
  uint64_t strtab_addr = 0;
  uint64_t strtab_size = 0;

  // Find the soname location from the dynamic headers section.
@@ -435,7 +412,7 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
    }

    if (dyn.d_tag == DT_STRTAB) {
      strtab_offset = dyn.d_un.d_ptr;
      strtab_addr = dyn.d_un.d_ptr;
    } else if (dyn.d_tag == DT_STRSZ) {
      strtab_size = dyn.d_un.d_val;
    } else if (dyn.d_tag == DT_SONAME) {
@@ -445,8 +422,11 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
    }
  }

  soname_offset += strtab_offset;
  if (soname_offset >= strtab_offset + strtab_size) {
  // Need to map the strtab address to the real offset.
  for (const auto& entry : strtabs_) {
    if (entry.first == strtab_addr) {
      soname_offset = entry.second + soname_offset;
      if (soname_offset >= entry.second + strtab_size) {
        return false;
      }
      if (!memory_->ReadString(soname_offset, &soname_)) {
@@ -456,6 +436,9 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
      *soname = soname_;
      return true;
    }
  }
  return false;
}

template <typename SymType>
bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name,
+1 −0
Original line number Diff line number Diff line
@@ -157,6 +157,7 @@ class ElfInterface {
  ElfInterface* gnu_debugdata_interface_ = nullptr;

  std::vector<Symbols*> symbols_;
  std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
};

class ElfInterface32 : public ElfInterface {
+84 −89
Original line number Diff line number Diff line
@@ -63,15 +63,28 @@ class ElfInterfaceTest : public ::testing::Test {
  template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
  void ManyPhdrs();

  template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
  enum SonameTestEnum : uint8_t {
    SONAME_NORMAL,
    SONAME_DTNULL_AFTER,
    SONAME_DTSIZE_SMALL,
    SONAME_MISSING_MAP,
  };

  template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
  void SonameInit(SonameTestEnum test_type = SONAME_NORMAL);

  template <typename ElfInterfaceType>
  void Soname();

  template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
  template <typename ElfInterfaceType>
  void SonameAfterDtNull();

  template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
  template <typename ElfInterfaceType>
  void SonameSize();

  template <typename ElfInterfaceType>
  void SonameMissingMap();

  template <typename ElfType>
  void InitHeadersEhFrameTest();

@@ -465,17 +478,29 @@ TEST_F(ElfInterfaceTest, elf32_arm) {
  ASSERT_EQ(2U, elf_arm.total_entries());
}

template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
void ElfInterfaceTest::Soname() {
  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));

template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) {
  Ehdr ehdr;
  memset(&ehdr, 0, sizeof(ehdr));
  ehdr.e_shoff = 0x200;
  ehdr.e_shnum = 2;
  ehdr.e_shentsize = sizeof(Shdr);
  ehdr.e_phoff = 0x100;
  ehdr.e_phnum = 1;
  ehdr.e_phentsize = sizeof(Phdr);
  memory_.SetMemory(0, &ehdr, sizeof(ehdr));

  Shdr shdr;
  memset(&shdr, 0, sizeof(shdr));
  shdr.sh_type = SHT_STRTAB;
  if (test_type == SONAME_MISSING_MAP) {
    shdr.sh_addr = 0x20100;
  } else {
    shdr.sh_addr = 0x10100;
  }
  shdr.sh_offset = 0x10000;
  memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr));

  Phdr phdr;
  memset(&phdr, 0, sizeof(phdr));
  phdr.p_type = PT_DYNAMIC;
@@ -487,14 +512,24 @@ void ElfInterfaceTest::Soname() {
  Dyn dyn;

  dyn.d_tag = DT_STRTAB;
  dyn.d_un.d_ptr = 0x10000;
  dyn.d_un.d_ptr = 0x10100;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  dyn.d_tag = DT_STRSZ;
  if (test_type == SONAME_DTSIZE_SMALL) {
    dyn.d_un.d_val = 0x10;
  } else {
    dyn.d_un.d_val = 0x1000;
  }
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  if (test_type == SONAME_DTNULL_AFTER) {
    dyn.d_tag = DT_NULL;
    memory_.SetMemory(offset, &dyn, sizeof(dyn));
    offset += sizeof(dyn);
  }

  dyn.d_tag = DT_SONAME;
  dyn.d_un.d_val = 0x10;
@@ -505,6 +540,11 @@ void ElfInterfaceTest::Soname() {
  memory_.SetMemory(offset, &dyn, sizeof(dyn));

  SetStringMemory(0x10010, "fake_soname.so");
}

template <typename ElfInterfaceType>
void ElfInterfaceTest::Soname() {
  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));

  uint64_t load_bias = 0;
  ASSERT_TRUE(elf->Init(&load_bias));
@@ -516,55 +556,19 @@ void ElfInterfaceTest::Soname() {
}

TEST_F(ElfInterfaceTest, elf32_soname) {
  Soname<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
  SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>();
  Soname<ElfInterface32>();
}

TEST_F(ElfInterfaceTest, elf64_soname) {
  Soname<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
  SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>();
  Soname<ElfInterface64>();
}

template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
template <typename ElfInterfaceType>
void ElfInterfaceTest::SonameAfterDtNull() {
  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));

  Ehdr ehdr;
  memset(&ehdr, 0, sizeof(ehdr));
  ehdr.e_phoff = 0x100;
  ehdr.e_phnum = 1;
  ehdr.e_phentsize = sizeof(Phdr);
  memory_.SetMemory(0, &ehdr, sizeof(ehdr));

  Phdr phdr;
  memset(&phdr, 0, sizeof(phdr));
  phdr.p_type = PT_DYNAMIC;
  phdr.p_offset = 0x2000;
  phdr.p_memsz = sizeof(Dyn) * 3;
  memory_.SetMemory(0x100, &phdr, sizeof(phdr));

  Dyn dyn;
  uint64_t offset = 0x2000;

  dyn.d_tag = DT_STRTAB;
  dyn.d_un.d_ptr = 0x10000;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  dyn.d_tag = DT_STRSZ;
  dyn.d_un.d_val = 0x1000;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  dyn.d_tag = DT_NULL;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  dyn.d_tag = DT_SONAME;
  dyn.d_un.d_val = 0x10;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);

  SetStringMemory(0x10010, "fake_soname.so");

  uint64_t load_bias = 0;
  ASSERT_TRUE(elf->Init(&load_bias));
  EXPECT_EQ(0U, load_bias);
@@ -574,53 +578,42 @@ void ElfInterfaceTest::SonameAfterDtNull() {
}

TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) {
  SonameAfterDtNull<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
  SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER);
  SonameAfterDtNull<ElfInterface32>();
}

TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) {
  SonameAfterDtNull<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
  SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER);
  SonameAfterDtNull<ElfInterface64>();
}

template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
template <typename ElfInterfaceType>
void ElfInterfaceTest::SonameSize() {
  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));

  Ehdr ehdr;
  memset(&ehdr, 0, sizeof(ehdr));
  ehdr.e_phoff = 0x100;
  ehdr.e_phnum = 1;
  ehdr.e_phentsize = sizeof(Phdr);
  memory_.SetMemory(0, &ehdr, sizeof(ehdr));

  Phdr phdr;
  memset(&phdr, 0, sizeof(phdr));
  phdr.p_type = PT_DYNAMIC;
  phdr.p_offset = 0x2000;
  phdr.p_memsz = sizeof(Dyn);
  memory_.SetMemory(0x100, &phdr, sizeof(phdr));

  Dyn dyn;
  uint64_t offset = 0x2000;

  dyn.d_tag = DT_STRTAB;
  dyn.d_un.d_ptr = 0x10000;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);
  uint64_t load_bias = 0;
  ASSERT_TRUE(elf->Init(&load_bias));
  EXPECT_EQ(0U, load_bias);

  dyn.d_tag = DT_STRSZ;
  dyn.d_un.d_val = 0x10;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);
  std::string name;
  ASSERT_FALSE(elf->GetSoname(&name));
}

  dyn.d_tag = DT_SONAME;
  dyn.d_un.d_val = 0x10;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
  offset += sizeof(dyn);
TEST_F(ElfInterfaceTest, elf32_soname_size) {
  SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
  SonameSize<ElfInterface32>();
}

  dyn.d_tag = DT_NULL;
  memory_.SetMemory(offset, &dyn, sizeof(dyn));
TEST_F(ElfInterfaceTest, elf64_soname_size) {
  SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
  SonameSize<ElfInterface64>();
}

  SetStringMemory(0x10010, "fake_soname.so");
// Verify that there is no map from STRTAB in the dynamic section to a
// STRTAB entry in the section headers.
template <typename ElfInterfaceType>
void ElfInterfaceTest::SonameMissingMap() {
  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));

  uint64_t load_bias = 0;
  ASSERT_TRUE(elf->Init(&load_bias));
@@ -630,12 +623,14 @@ void ElfInterfaceTest::SonameSize() {
  ASSERT_FALSE(elf->GetSoname(&name));
}

TEST_F(ElfInterfaceTest, elf32_soname_size) {
  SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
TEST_F(ElfInterfaceTest, elf32_soname_missing_map) {
  SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP);
  SonameMissingMap<ElfInterface32>();
}

TEST_F(ElfInterfaceTest, elf64_soname_size) {
  SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
TEST_F(ElfInterfaceTest, elf64_soname_missing_map) {
  SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
  SonameMissingMap<ElfInterface64>();
}

template <typename ElfType>
+5 −0
Original line number Diff line number Diff line
@@ -120,6 +120,11 @@ int GetElfInfo(const char* file, uint64_t offset) {
    return 1;
  }

  std::string soname;
  if (elf.GetSoname(&soname)) {
    printf("Soname: %s\n", soname.c_str());
  }

  ElfInterface* interface = elf.interface();
  if (elf.machine_type() == EM_ARM) {
    DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface));
+5 −0
Original line number Diff line number Diff line
@@ -157,6 +157,11 @@ int GetInfo(const char* file, uint64_t pc) {
    return 1;
  }

  std::string soname;
  if (elf.GetSoname(&soname)) {
    printf("Soname: %s\n\n", soname.c_str());
  }

  printf("PC 0x%" PRIx64 ":\n", pc);

  DwarfSection* section = interface->eh_frame();
Loading