zgu@2364: /* zgu@2364: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. zgu@2364: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. zgu@2364: * zgu@2364: * This code is free software; you can redistribute it and/or modify it zgu@2364: * under the terms of the GNU General Public License version 2 only, as zgu@2364: * published by the Free Software Foundation. zgu@2364: * zgu@2364: * This code is distributed in the hope that it will be useful, but WITHOUT zgu@2364: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or zgu@2364: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License zgu@2364: * version 2 for more details (a copy is included in the LICENSE file that zgu@2364: * accompanied this code). zgu@2364: * zgu@2364: * You should have received a copy of the GNU General Public License version zgu@2364: * 2 along with this work; if not, write to the Free Software Foundation, zgu@2364: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. zgu@2364: * zgu@2364: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA zgu@2364: * or visit www.oracle.com if you need additional information or have any zgu@2364: * questions. zgu@2364: * zgu@2364: */ zgu@2364: zgu@2364: #include "precompiled.hpp" zgu@2364: never@3156: #if !defined(_WINDOWS) && !defined(__APPLE__) zgu@2364: zgu@2364: #include zgu@2364: #include zgu@2364: #include zgu@2834: #include zgu@2364: zgu@2364: #include "memory/allocation.inline.hpp" zgu@2364: #include "utilities/decoder.hpp" zgu@2364: #include "utilities/elfFile.hpp" zgu@2364: #include "utilities/elfStringTable.hpp" zgu@2364: #include "utilities/elfSymbolTable.hpp" zgu@2364: zgu@2364: zgu@2364: ElfFile::ElfFile(const char* filepath) { zgu@2364: assert(filepath, "null file path"); zgu@2364: memset(&m_elfHdr, 0, sizeof(m_elfHdr)); zgu@2364: m_string_tables = NULL; zgu@2364: m_symbol_tables = NULL; zgu@2364: m_next = NULL; zgu@3430: m_status = NullDecoder::no_error; zgu@2364: zgu@2364: int len = strlen(filepath) + 1; zgu@2834: m_filepath = (const char*)os::malloc(len * sizeof(char)); zgu@2364: if (m_filepath != NULL) { zgu@2364: strcpy((char*)m_filepath, filepath); zgu@2364: m_file = fopen(filepath, "r"); zgu@2364: if (m_file != NULL) { zgu@2364: load_tables(); zgu@2364: } else { zgu@3430: m_status = NullDecoder::file_not_found; zgu@2364: } zgu@2364: } else { zgu@3430: m_status = NullDecoder::out_of_memory; zgu@2364: } zgu@2364: } zgu@2364: zgu@2364: ElfFile::~ElfFile() { zgu@2364: if (m_string_tables != NULL) { zgu@2364: delete m_string_tables; zgu@2364: } zgu@2364: zgu@2364: if (m_symbol_tables != NULL) { zgu@2364: delete m_symbol_tables; zgu@2364: } zgu@2364: zgu@2364: if (m_file != NULL) { zgu@2364: fclose(m_file); zgu@2364: } zgu@2364: zgu@2364: if (m_filepath != NULL) { zgu@2834: os::free((void*)m_filepath); zgu@2364: } zgu@2364: zgu@2364: if (m_next != NULL) { zgu@2364: delete m_next; zgu@2364: } zgu@2364: }; zgu@2364: zgu@2364: zgu@2364: //Check elf header to ensure the file is valid. zgu@2364: bool ElfFile::is_elf_file(Elf_Ehdr& hdr) { zgu@2364: return (ELFMAG0 == hdr.e_ident[EI_MAG0] && zgu@2364: ELFMAG1 == hdr.e_ident[EI_MAG1] && zgu@2364: ELFMAG2 == hdr.e_ident[EI_MAG2] && zgu@2364: ELFMAG3 == hdr.e_ident[EI_MAG3] && zgu@2364: ELFCLASSNONE != hdr.e_ident[EI_CLASS] && zgu@2364: ELFDATANONE != hdr.e_ident[EI_DATA]); zgu@2364: } zgu@2364: zgu@2364: bool ElfFile::load_tables() { zgu@2364: assert(m_file, "file not open"); zgu@3430: assert(!NullDecoder::is_error(m_status), "already in error"); zgu@2364: zgu@2364: // read elf file header zgu@2364: if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { zgu@3430: m_status = NullDecoder::file_invalid; zgu@2364: return false; zgu@2364: } zgu@2364: zgu@2364: if (!is_elf_file(m_elfHdr)) { zgu@3430: m_status = NullDecoder::file_invalid; zgu@2364: return false; zgu@2364: } zgu@2364: zgu@2364: // walk elf file's section headers, and load string tables zgu@2364: Elf_Shdr shdr; zgu@2364: if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { zgu@3430: if (NullDecoder::is_error(m_status)) return false; zgu@2364: zgu@2364: for (int index = 0; index < m_elfHdr.e_shnum; index ++) { zgu@2364: if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { zgu@3430: m_status = NullDecoder::file_invalid; zgu@2364: return false; zgu@2364: } zgu@2364: // string table zgu@2364: if (shdr.sh_type == SHT_STRTAB) { zgu@2834: ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); zgu@2364: if (table == NULL) { zgu@3430: m_status = NullDecoder::out_of_memory; zgu@2364: return false; zgu@2364: } zgu@2364: add_string_table(table); zgu@2364: } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { zgu@2834: ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); zgu@2364: if (table == NULL) { zgu@3430: m_status = NullDecoder::out_of_memory; zgu@2364: return false; zgu@2364: } zgu@2364: add_symbol_table(table); zgu@2364: } zgu@2364: } zgu@2364: } zgu@2364: return true; zgu@2364: } zgu@2364: zgu@3430: bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { zgu@2364: // something already went wrong, just give up zgu@3430: if (NullDecoder::is_error(m_status)) { zgu@3430: return false; zgu@2364: } zgu@2364: ElfSymbolTable* symbol_table = m_symbol_tables; zgu@2364: int string_table_index; zgu@2364: int pos_in_string_table; zgu@2364: int off = INT_MAX; zgu@2364: bool found_symbol = false; zgu@2364: while (symbol_table != NULL) { zgu@3430: if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { zgu@2364: found_symbol = true; zgu@2364: } zgu@2364: symbol_table = symbol_table->m_next; zgu@2364: } zgu@3430: if (!found_symbol) return false; zgu@2364: zgu@2364: ElfStringTable* string_table = get_string_table(string_table_index); zgu@3430: zgu@2364: if (string_table == NULL) { zgu@3430: m_status = NullDecoder::file_invalid; zgu@3430: return false; zgu@2364: } zgu@2364: if (offset) *offset = off; zgu@3430: zgu@3430: return string_table->string_at(pos_in_string_table, buf, buflen); zgu@2364: } zgu@2364: zgu@2364: zgu@2364: void ElfFile::add_symbol_table(ElfSymbolTable* table) { zgu@2364: if (m_symbol_tables == NULL) { zgu@2364: m_symbol_tables = table; zgu@2364: } else { zgu@2364: table->m_next = m_symbol_tables; zgu@2364: m_symbol_tables = table; zgu@2364: } zgu@2364: } zgu@2364: zgu@2364: void ElfFile::add_string_table(ElfStringTable* table) { zgu@2364: if (m_string_tables == NULL) { zgu@2364: m_string_tables = table; zgu@2364: } else { zgu@2364: table->m_next = m_string_tables; zgu@2364: m_string_tables = table; zgu@2364: } zgu@2364: } zgu@2364: zgu@2364: ElfStringTable* ElfFile::get_string_table(int index) { zgu@2364: ElfStringTable* p = m_string_tables; zgu@2364: while (p != NULL) { zgu@2364: if (p->index() == index) return p; zgu@2364: p = p->m_next; zgu@2364: } zgu@2364: return NULL; zgu@2364: } zgu@2364: zgu@2364: #endif // _WINDOWS