Ejemplo n.º 1
0
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
  // something already went wrong, just give up
  if (NullDecoder::is_error(m_status)) {
    return false;
  }
  ElfSymbolTable* symbol_table = m_symbol_tables;
  int string_table_index;
  int pos_in_string_table;
  int off = INT_MAX;
  bool found_symbol = false;
  while (symbol_table != NULL) {
    if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
      found_symbol = true;
    }
    symbol_table = symbol_table->m_next;
  }
  if (!found_symbol) return false;

  ElfStringTable* string_table = get_string_table(string_table_index);

  if (string_table == NULL) {
    m_status = NullDecoder::file_invalid;
    return false;
  }
  if (offset) *offset = off;

  return string_table->string_at(pos_in_string_table, buf, buflen);
}
Ejemplo n.º 2
0
bool ElfFile::load_tables() {
  assert(m_file, "file not open");
  assert(!NullDecoder::is_error(m_status), "already in error");

  // read elf file header
  if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
    m_status = NullDecoder::file_invalid;
    return false;
  }

  if (!is_elf_file(m_elfHdr)) {
    m_status = NullDecoder::file_invalid;
    return false;
  }

  // walk elf file's section headers, and load string tables
  Elf_Shdr shdr;
  if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
    if (NullDecoder::is_error(m_status)) return false;

    for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
      if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
        m_status = NullDecoder::file_invalid;
        return false;
      }
      if (shdr.sh_type == SHT_STRTAB) {
        // string tables
        ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
        if (table == NULL) {
          m_status = NullDecoder::out_of_memory;
          return false;
        }
        add_string_table(table);
      } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
        // symbol tables
        ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
        if (table == NULL) {
          m_status = NullDecoder::out_of_memory;
          return false;
        }
        add_symbol_table(table);
      }
    }

#if defined(PPC64) && !defined(ABI_ELFv2)
    // Now read the .opd section wich contains the PPC64 function descriptor table.
    // The .opd section is only available on PPC64 (see for example:
    // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
    // so this code should do no harm on other platforms but because of performance reasons we only
    // execute it on PPC64 platforms.
    // Notice that we can only find the .opd section after we have successfully read in the string
    // tables in the previous loop, because we need to query the name of each section which is
    // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).

    // Reset the file pointer
    if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
      m_status = NullDecoder::file_invalid;
      return false;
    }
    for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
      if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
        m_status = NullDecoder::file_invalid;
        return false;
      }
      if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {
        ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);
        if (string_table == NULL) {
          m_status = NullDecoder::file_invalid;
          return false;
        }
        char buf[8]; // '8' is enough because we only want to read ".opd"
        if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) {
          m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index);
          if (m_funcDesc_table == NULL) {
            m_status = NullDecoder::out_of_memory;
            return false;
          }
          break;
        }
      }
    }
#endif

  }
  return true;
}