elfFile.cpp revision 2995:d7e3846464d0
155714Skris/* 255714Skris * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 355714Skris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4238405Sjkim * 555714Skris * This code is free software; you can redistribute it and/or modify it 655714Skris * under the terms of the GNU General Public License version 2 only, as 755714Skris * published by the Free Software Foundation. 855714Skris * 955714Skris * This code is distributed in the hope that it will be useful, but WITHOUT 1055714Skris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11109998Smarkm * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1255714Skris * version 2 for more details (a copy is included in the LICENSE file that 13160814Ssimon * accompanied this code). 14160814Ssimon * 15160814Ssimon * You should have received a copy of the GNU General Public License version 16238405Sjkim * 2 along with this work; if not, write to the Free Software Foundation, 17238405Sjkim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1855714Skris * 1955714Skris * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2055714Skris * or visit www.oracle.com if you need additional information or have any 2155714Skris * questions. 2255714Skris * 23238405Sjkim */ 24238405Sjkim 25238405Sjkim#include "precompiled.hpp" 2655714Skris 2755714Skris#if !defined(_WINDOWS) && !defined(__APPLE__) 2855714Skris 2955714Skris#include <string.h> 3055714Skris#include <stdio.h> 3155714Skris#include <limits.h> 3255714Skris#include <new> 3355714Skris 3455714Skris#include "memory/allocation.inline.hpp" 3555714Skris#include "utilities/decoder.hpp" 3655714Skris#include "utilities/elfFile.hpp" 3755714Skris#include "utilities/elfStringTable.hpp" 3855714Skris#include "utilities/elfSymbolTable.hpp" 3955714Skris 4055714Skris 41109998SmarkmElfFile::ElfFile(const char* filepath) { 42109998Smarkm assert(filepath, "null file path"); 43109998Smarkm memset(&m_elfHdr, 0, sizeof(m_elfHdr)); 4455714Skris m_string_tables = NULL; 4555714Skris m_symbol_tables = NULL; 4655714Skris m_next = NULL; 47238405Sjkim m_status = NullDecoder::no_error; 48238405Sjkim 49238405Sjkim int len = strlen(filepath) + 1; 50238405Sjkim m_filepath = (const char*)os::malloc(len * sizeof(char)); 51238405Sjkim if (m_filepath != NULL) { 52238405Sjkim strcpy((char*)m_filepath, filepath); 53238405Sjkim m_file = fopen(filepath, "r"); 54238405Sjkim if (m_file != NULL) { 55238405Sjkim load_tables(); 56238405Sjkim } else { 57238405Sjkim m_status = NullDecoder::file_not_found; 58238405Sjkim } 59238405Sjkim } else { 60238405Sjkim m_status = NullDecoder::out_of_memory; 61238405Sjkim } 62238405Sjkim} 63238405Sjkim 64238405SjkimElfFile::~ElfFile() { 65238405Sjkim if (m_string_tables != NULL) { 66238405Sjkim delete m_string_tables; 67238405Sjkim } 68238405Sjkim 69238405Sjkim if (m_symbol_tables != NULL) { 70238405Sjkim delete m_symbol_tables; 71238405Sjkim } 72238405Sjkim 73238405Sjkim if (m_file != NULL) { 74238405Sjkim fclose(m_file); 75238405Sjkim } 76238405Sjkim 77238405Sjkim if (m_filepath != NULL) { 78238405Sjkim os::free((void*)m_filepath); 79238405Sjkim } 80238405Sjkim 81238405Sjkim if (m_next != NULL) { 82238405Sjkim delete m_next; 83238405Sjkim } 84238405Sjkim}; 85238405Sjkim 86238405Sjkim 87238405Sjkim//Check elf header to ensure the file is valid. 88238405Sjkimbool ElfFile::is_elf_file(Elf_Ehdr& hdr) { 89238405Sjkim return (ELFMAG0 == hdr.e_ident[EI_MAG0] && 90238405Sjkim ELFMAG1 == hdr.e_ident[EI_MAG1] && 91238405Sjkim ELFMAG2 == hdr.e_ident[EI_MAG2] && 92238405Sjkim ELFMAG3 == hdr.e_ident[EI_MAG3] && 93238405Sjkim ELFCLASSNONE != hdr.e_ident[EI_CLASS] && 94238405Sjkim ELFDATANONE != hdr.e_ident[EI_DATA]); 95238405Sjkim} 96238405Sjkim 97238405Sjkimbool ElfFile::load_tables() { 98238405Sjkim assert(m_file, "file not open"); 99238405Sjkim assert(!NullDecoder::is_error(m_status), "already in error"); 100238405Sjkim 101238405Sjkim // read elf file header 102238405Sjkim if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { 103238405Sjkim m_status = NullDecoder::file_invalid; 104238405Sjkim return false; 105238405Sjkim } 106238405Sjkim 107238405Sjkim if (!is_elf_file(m_elfHdr)) { 108238405Sjkim m_status = NullDecoder::file_invalid; 109238405Sjkim return false; 110238405Sjkim } 111238405Sjkim 11255714Skris // walk elf file's section headers, and load string tables 11355714Skris Elf_Shdr shdr; 11455714Skris if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { 11555714Skris if (NullDecoder::is_error(m_status)) return false; 11655714Skris 11755714Skris for (int index = 0; index < m_elfHdr.e_shnum; index ++) { 118238405Sjkim if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { 11955714Skris m_status = NullDecoder::file_invalid; 12055714Skris return false; 12155714Skris } 12255714Skris // string table 12355714Skris if (shdr.sh_type == SHT_STRTAB) { 12455714Skris ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); 12555714Skris if (table == NULL) { 12655714Skris m_status = NullDecoder::out_of_memory; 12755714Skris return false; 12855714Skris } 12955714Skris add_string_table(table); 13055714Skris } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 13155714Skris ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); 13255714Skris if (table == NULL) { 13389837Skris m_status = NullDecoder::out_of_memory; 13455714Skris return false; 13555714Skris } 13655714Skris add_symbol_table(table); 137238405Sjkim } 138238405Sjkim } 139160814Ssimon } 140160814Ssimon return true; 14155714Skris} 14255714Skris 14355714Skrisbool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { 14455714Skris // something already went wrong, just give up 14555714Skris if (NullDecoder::is_error(m_status)) { 14655714Skris return false; 14755714Skris } 14855714Skris ElfSymbolTable* symbol_table = m_symbol_tables; 14955714Skris int string_table_index; 15055714Skris int pos_in_string_table; 15155714Skris int off = INT_MAX; 15255714Skris bool found_symbol = false; 15355714Skris while (symbol_table != NULL) { 15455714Skris if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { 15555714Skris found_symbol = true; 15655714Skris } 15789837Skris symbol_table = symbol_table->m_next; 15855714Skris } 15955714Skris if (!found_symbol) return false; 16055714Skris 161109998Smarkm ElfStringTable* string_table = get_string_table(string_table_index); 162109998Smarkm 163109998Smarkm if (string_table == NULL) { 164109998Smarkm m_status = NullDecoder::file_invalid; 165109998Smarkm return false; 166109998Smarkm } 16768651Skris if (offset) *offset = off; 168109998Smarkm 169109998Smarkm return string_table->string_at(pos_in_string_table, buf, buflen); 170109998Smarkm} 171109998Smarkm 172109998Smarkm 17355714Skrisvoid ElfFile::add_symbol_table(ElfSymbolTable* table) { 174109998Smarkm if (m_symbol_tables == NULL) { 175109998Smarkm m_symbol_tables = table; 176109998Smarkm } else { 177109998Smarkm table->m_next = m_symbol_tables; 17855714Skris m_symbol_tables = table; 179160814Ssimon } 180160814Ssimon} 181160814Ssimon 182160814Ssimonvoid ElfFile::add_string_table(ElfStringTable* table) { 183160814Ssimon if (m_string_tables == NULL) { 184160814Ssimon m_string_tables = table; 185160814Ssimon } else { 186160814Ssimon table->m_next = m_string_tables; 187160814Ssimon m_string_tables = table; 188109998Smarkm } 189160814Ssimon} 190160814Ssimon 191109998SmarkmElfStringTable* ElfFile::get_string_table(int index) { 192109998Smarkm ElfStringTable* p = m_string_tables; 193160814Ssimon while (p != NULL) { 19455714Skris if (p->index() == index) return p; 195109998Smarkm p = p->m_next; 19655714Skris } 197109998Smarkm return NULL; 19855714Skris} 199109998Smarkm 200109998Smarkm#endif // _WINDOWS 201109998Smarkm