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; } // string table if (shdr.sh_type == SHT_STRTAB) { 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) { ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); if (table == NULL) { m_status = NullDecoder::out_of_memory; return false; } add_symbol_table(table); } } } return true; }
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) { lib_info* newlib; print_debug("add_lib_info_fd %s\n", libname); if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) { print_debug("can't allocate memory for lib_info\n"); return NULL; } strncpy(newlib->name, libname, sizeof(newlib->name)); newlib->base = base; if (fd == -1) { if ( (newlib->fd = pathmap_open(newlib->name)) < 0) { print_debug("can't open shared object %s\n", newlib->name); free(newlib); return NULL; } } else { newlib->fd = fd; } #ifdef __APPLE__ // check whether we have got an Macho file. if (is_macho_file(newlib->fd) == false) { close(newlib->fd); free(newlib); print_debug("not a mach-o file\n"); return NULL; } #else // check whether we have got an ELF file. /proc/<pid>/map // gives out all file mappings and not just shared objects if (is_elf_file(newlib->fd) == false) { close(newlib->fd); free(newlib); return NULL; } #endif // __APPLE__ newlib->symtab = build_symtab(newlib->fd); if (newlib->symtab == NULL) { print_debug("symbol table build failed for %s\n", newlib->name); } else { print_debug("built symbol table for %s\n", newlib->name); } // even if symbol table building fails, we add the lib_info. // This is because we may need to read from the ELF file or MachO file for core file // address read functionality. lookup_symbol checks for NULL symtab. if (ph->libs) { ph->lib_tail->next = newlib; ph->lib_tail = newlib; } else { ph->libs = ph->lib_tail = newlib; } ph->num_libs++; return newlib; }
BOOL ElfLoader::read_header() { // read ELF header _file->read(&_eh, sizeof(Elf_Ehdr), 0); // check ELF Magic. if (!is_elf_file()) { DPRINTF((TEXT("not a ELF file.\n"))); return FALSE; } // Windows CE is 32bit little-endian only. if (_eh.e_ident[EI_DATA] != ELFDATA2LSB || _eh.e_ident[EI_CLASS] != ELFCLASS32) { DPRINTF((TEXT("invalid class/data(%d/%d)\n"), _eh.e_ident[EI_CLASS], _eh.e_ident[EI_DATA])); return FALSE; } // Is native architecture? switch(_eh.e_machine) { ELF32_MACHDEP_ID_CASES; default: DPRINTF((TEXT("not a native architecture. machine = %d\n"), _eh.e_machine)); return FALSE; } // Check object type if (_eh.e_type != ET_EXEC) { DPRINTF((TEXT("not a executable file. type = %d\n"), _eh.e_type)); return FALSE; } if (_eh.e_phoff == 0 || _eh.e_phnum == 0 || _eh.e_phnum > 16 || _eh.e_phentsize != sizeof(Elf_Phdr)) { DPRINTF((TEXT("invalid program header information.\n"))); return FALSE; } return TRUE; }
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; }