elfFile.cpp revision 2721:f08d439fab8c
1115170Speter/*
299127Sobrien * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
399127Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
499127Sobrien *
599127Sobrien * This code is free software; you can redistribute it and/or modify it
699127Sobrien * under the terms of the GNU General Public License version 2 only, as
799127Sobrien * published by the Free Software Foundation.
899127Sobrien *
999127Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1099127Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1199127Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12115170Speter * version 2 for more details (a copy is included in the LICENSE file that
1399127Sobrien * accompanied this code).
1499127Sobrien *
1599127Sobrien * You should have received a copy of the GNU General Public License version
16115170Speter * 2 along with this work; if not, write to the Free Software Foundation,
1799127Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1899127Sobrien *
1999127Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2099127Sobrien * or visit www.oracle.com if you need additional information or have any
21169612Swkoszek * questions.
2299127Sobrien *
2399127Sobrien */
2499127Sobrien
2599127Sobrien#include "precompiled.hpp"
2699127Sobrien
2799127Sobrien#if !defined(_WINDOWS) && !defined(__APPLE__)
2899127Sobrien
2999127Sobrien#include <string.h>
3099127Sobrien#include <stdio.h>
3199127Sobrien#include <limits.h>
3299127Sobrien#include <new>
3399127Sobrien
34250840Smarcel#include "memory/allocation.inline.hpp"
35250840Smarcel#include "utilities/decoder.hpp"
36179225Sjb#include "utilities/elfFile.hpp"
37115405Speter#include "utilities/elfStringTable.hpp"
38115405Speter#include "utilities/elfSymbolTable.hpp"
39115405Speter
40114370Speter
4199127SobrienElfFile::ElfFile(const char* filepath) {
42218893Sdim  assert(filepath, "null file path");
43232263Sdim  memset(&m_elfHdr, 0, sizeof(m_elfHdr));
44232263Sdim  m_string_tables = NULL;
45232263Sdim  m_symbol_tables = NULL;
46232263Sdim  m_next = NULL;
47232263Sdim  m_status = Decoder::no_error;
48218893Sdim
4999127Sobrien  int len = strlen(filepath) + 1;
5099127Sobrien  m_filepath = (const char*)os::malloc(len * sizeof(char));
5199127Sobrien  if (m_filepath != NULL) {
5299127Sobrien    strcpy((char*)m_filepath, filepath);
5399127Sobrien    m_file = fopen(filepath, "r");
5499127Sobrien    if (m_file != NULL) {
5599127Sobrien      load_tables();
5699127Sobrien    } else {
5799127Sobrien      m_status = Decoder::file_not_found;
5899127Sobrien    }
5999127Sobrien  } else {
6099127Sobrien    m_status = Decoder::out_of_memory;
6199127Sobrien  }
6299127Sobrien}
6399127Sobrien
64ElfFile::~ElfFile() {
65  if (m_string_tables != NULL) {
66    delete m_string_tables;
67  }
68
69  if (m_symbol_tables != NULL) {
70    delete m_symbol_tables;
71  }
72
73  if (m_file != NULL) {
74    fclose(m_file);
75  }
76
77  if (m_filepath != NULL) {
78    os::free((void*)m_filepath);
79  }
80
81  if (m_next != NULL) {
82    delete m_next;
83  }
84};
85
86
87//Check elf header to ensure the file is valid.
88bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
89  return (ELFMAG0 == hdr.e_ident[EI_MAG0] &&
90      ELFMAG1 == hdr.e_ident[EI_MAG1] &&
91      ELFMAG2 == hdr.e_ident[EI_MAG2] &&
92      ELFMAG3 == hdr.e_ident[EI_MAG3] &&
93      ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&
94      ELFDATANONE != hdr.e_ident[EI_DATA]);
95}
96
97bool ElfFile::load_tables() {
98  assert(m_file, "file not open");
99  assert(m_status == Decoder::no_error, "already in error");
100
101  // read elf file header
102  if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
103    m_status = Decoder::file_invalid;
104    return false;
105  }
106
107  if (!is_elf_file(m_elfHdr)) {
108    m_status = Decoder::file_invalid;
109    return false;
110  }
111
112  // walk elf file's section headers, and load string tables
113  Elf_Shdr shdr;
114  if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
115    if (m_status != Decoder::no_error) return false;
116
117    for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
118      if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
119        m_status = Decoder::file_invalid;
120        return false;
121      }
122      // string table
123      if (shdr.sh_type == SHT_STRTAB) {
124        ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
125        if (table == NULL) {
126          m_status = Decoder::out_of_memory;
127          return false;
128        }
129        add_string_table(table);
130      } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
131        ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
132        if (table == NULL) {
133          m_status = Decoder::out_of_memory;
134          return false;
135        }
136        add_symbol_table(table);
137      }
138    }
139  }
140  return true;
141}
142
143const char* ElfFile::decode(address addr, int* offset) {
144  // something already went wrong, just give up
145  if (m_status != Decoder::no_error) {
146    return NULL;
147  }
148
149  ElfSymbolTable* symbol_table = m_symbol_tables;
150  int string_table_index;
151  int pos_in_string_table;
152  int off = INT_MAX;
153  bool found_symbol = false;
154  while (symbol_table != NULL) {
155    if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
156      found_symbol = true;
157    }
158    symbol_table = symbol_table->m_next;
159  }
160  if (!found_symbol) return NULL;
161
162  ElfStringTable* string_table = get_string_table(string_table_index);
163  if (string_table == NULL) {
164    m_status = Decoder::file_invalid;
165    return NULL;
166  }
167  if (offset) *offset = off;
168  return string_table->string_at(pos_in_string_table);
169}
170
171
172void ElfFile::add_symbol_table(ElfSymbolTable* table) {
173  if (m_symbol_tables == NULL) {
174    m_symbol_tables = table;
175  } else {
176    table->m_next = m_symbol_tables;
177    m_symbol_tables = table;
178  }
179}
180
181void ElfFile::add_string_table(ElfStringTable* table) {
182  if (m_string_tables == NULL) {
183    m_string_tables = table;
184  } else {
185    table->m_next = m_string_tables;
186    m_string_tables = table;
187  }
188}
189
190ElfStringTable* ElfFile::get_string_table(int index) {
191  ElfStringTable* p = m_string_tables;
192  while (p != NULL) {
193    if (p->index() == index) return p;
194    p = p->m_next;
195  }
196  return NULL;
197}
198
199#endif // _WINDOWS
200