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

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

Merge "Fix support finding global variables."

am: 2da8e3c2

Change-Id: Ieec8f9ae7c542487a108c06f66b4292046e4ff4c
parents 080a2d01 2da8e3c2
Loading
Loading
Loading
Loading
+16 −18
Original line number Diff line number Diff line
@@ -112,37 +112,35 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse
                     gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
}

bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) {
  if (!valid_) {
    return false;
  }

  if (!interface_->GetGlobalVariable(name, memory_address) &&
  uint64_t vaddr;
  if (!interface_->GetGlobalVariable(name, &vaddr) &&
      (gnu_debugdata_interface_ == nullptr ||
       !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) {
       !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) {
    return false;
  }

  // Adjust by the load bias.
  if (load_bias_ > 0 && *memory_address < static_cast<uint64_t>(load_bias_)) {
    return false;
  // Check the .data section.
  uint64_t vaddr_start = interface_->data_vaddr_start();
  if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
    *memory_offset = vaddr - vaddr_start + interface_->data_offset();
    return true;
  }

  *memory_address -= load_bias_;

  // If this winds up in the dynamic section, then we might need to adjust
  // the address.
  uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size();
  if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) {
    if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) {
      *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset();
    } else {
      *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr();
    }
  }
  // Check the .dynamic section.
  vaddr_start = interface_->dynamic_vaddr_start();
  if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) {
    *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset();
    return true;
  }

  return false;
}

std::string Elf::GetBuildID() {
  if (!valid_) {
    return "";
+15 −3
Original line number Diff line number Diff line
@@ -236,8 +236,12 @@ void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias)

    case PT_DYNAMIC:
      dynamic_offset_ = phdr.p_offset;
      dynamic_vaddr_ = phdr.p_vaddr;
      dynamic_size_ = phdr.p_memsz;
      dynamic_vaddr_start_ = phdr.p_vaddr;
      if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) {
        dynamic_offset_ = 0;
        dynamic_vaddr_start_ = 0;
        dynamic_vaddr_end_ = 0;
      }
      break;

    default:
@@ -360,6 +364,14 @@ void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
            eh_frame_hdr_offset_ = shdr.sh_offset;
            eh_frame_hdr_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
            eh_frame_hdr_size_ = shdr.sh_size;
          } else if (name == ".data") {
            data_offset_ = shdr.sh_offset;
            data_vaddr_start_ = shdr.sh_addr;
            if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) {
              data_offset_ = 0;
              data_vaddr_start_ = 0;
              data_vaddr_end_ = 0;
            }
          }
        }
      }
@@ -398,7 +410,7 @@ std::string ElfInterface::GetSonameWithTemplate() {
  // Find the soname location from the dynamic headers section.
  DynType dyn;
  uint64_t offset = dynamic_offset_;
  uint64_t max_offset = offset + dynamic_size_;
  uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_;
  for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
    if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
      last_error_.code = ERROR_MEMORY_INVALID;
+28 −31
Original line number Diff line number Diff line
@@ -39,28 +39,22 @@ void Global::SetArch(ArchEnum arch) {
  }
}

uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
  if (!search_libs_.empty()) {
    bool found = false;
    const char* lib = basename(info->name.c_str());
    for (const std::string& name : search_libs_) {
      if (name == lib) {
        found = true;
        break;
      }
    }
    if (!found) {
      return 0;
bool Global::Searchable(const std::string& name) {
  if (search_libs_.empty()) {
    return true;
  }

  if (name.empty()) {
    return false;
  }

  Elf* elf = info->GetElf(memory_, arch());
  uint64_t ptr;
  // Find first non-empty list (libraries might be loaded multiple times).
  if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
    return ptr + info->start;
  const char* base_name = basename(name.c_str());
  for (const std::string& lib : search_libs_) {
    if (base_name == lib) {
      return true;
    }
  }
  return 0;
  return false;
}

void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
@@ -78,24 +72,27 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
  //   f2000-f3000 2000 rw- /system/lib/libc.so
  MapInfo* map_start = nullptr;
  for (const auto& info : *maps) {
    if (map_start != nullptr) {
      if (map_start->name == info->name) {
    if (map_start != nullptr && map_start->name == info->name) {
      if (info->offset != 0 &&
          (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
          uint64_t ptr = GetVariableOffset(map_start, variable);
          if (ptr != 0 && ReadVariableData(ptr)) {
        Elf* elf = map_start->GetElf(memory_, arch());
        uint64_t ptr;
        if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) {
          uint64_t offset_end = info->offset + info->end - info->start;
          if (ptr >= info->offset && ptr < offset_end) {
            ptr = info->start + ptr - info->offset;
            if (ReadVariableData(ptr)) {
              break;
          } else {
            // Failed to find the global variable, do not bother trying again.
            map_start = nullptr;
            }
          }
      } else {
        }
        map_start = nullptr;
      }
    } else {
      map_start = nullptr;
    }
    if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
        !info->name.empty()) {
        Searchable(info->name)) {
      map_start = info.get();
    }
  }
+1 −1
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ class Elf {

  bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);

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

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

+11 −4
Original line number Diff line number Diff line
@@ -77,8 +77,11 @@ class ElfInterface {
  void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }

  uint64_t dynamic_offset() { return dynamic_offset_; }
  uint64_t dynamic_vaddr() { return dynamic_vaddr_; }
  uint64_t dynamic_size() { return dynamic_size_; }
  uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
  uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
  uint64_t data_offset() { return data_offset_; }
  uint64_t data_vaddr_start() { return data_vaddr_start_; }
  uint64_t data_vaddr_end() { return data_vaddr_end_; }
  uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
  int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
  uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
@@ -141,8 +144,12 @@ class ElfInterface {

  // Stored elf data.
  uint64_t dynamic_offset_ = 0;
  uint64_t dynamic_vaddr_ = 0;
  uint64_t dynamic_size_ = 0;
  uint64_t dynamic_vaddr_start_ = 0;
  uint64_t dynamic_vaddr_end_ = 0;

  uint64_t data_offset_ = 0;
  uint64_t data_vaddr_start_ = 0;
  uint64_t data_vaddr_end_ = 0;

  uint64_t eh_frame_hdr_offset_ = 0;
  int64_t eh_frame_hdr_section_bias_ = 0;
Loading