elfSymbolTable.cpp revision 9659:31e68e7d4bf2
155714Skris/*
255714Skris * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
355714Skris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
455714Skris *
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
1155714Skris * 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
1355714Skris * accompanied this code).
1455714Skris *
1555714Skris * You should have received a copy of the GNU General Public License version
1655714Skris * 2 along with this work; if not, write to the Free Software Foundation,
1755714Skris * 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 *
2355714Skris */
2455714Skris
2555714Skris#include "precompiled.hpp"
2655714Skris
2755714Skris#if !defined(_WINDOWS) && !defined(__APPLE__)
2855714Skris
2955714Skris#include "memory/allocation.inline.hpp"
3055714Skris#include "utilities/elfFuncDescTable.hpp"
3155714Skris#include "utilities/elfSymbolTable.hpp"
3255714Skris
3355714SkrisElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
3455714Skris  assert(file, "null file handle");
3555714Skris  m_symbols = NULL;
3655714Skris  m_next = NULL;
3755714Skris  m_file = file;
3855714Skris  m_status = NullDecoder::no_error;
3955714Skris
4055714Skris  // try to load the string table
4155714Skris  long cur_offset = ftell(file);
4255714Skris  if (cur_offset != -1) {
4355714Skris    // call malloc so we can back up if memory allocation fails.
4455714Skris    m_symbols = (Elf_Sym*)os::malloc(shdr.sh_size, mtInternal);
4555714Skris    if (m_symbols) {
4655714Skris      if (fseek(file, shdr.sh_offset, SEEK_SET) ||
4755714Skris        fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
4855714Skris        fseek(file, cur_offset, SEEK_SET)) {
4955714Skris        m_status = NullDecoder::file_invalid;
5055714Skris        os::free(m_symbols);
5155714Skris        m_symbols = NULL;
5255714Skris      }
5355714Skris    }
5455714Skris    if (!NullDecoder::is_error(m_status)) {
5555714Skris      memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
5655714Skris    }
5755714Skris  } else {
5855714Skris    m_status = NullDecoder::file_invalid;
5955714Skris  }
6055714Skris}
61160814Ssimon
62238405SjkimElfSymbolTable::~ElfSymbolTable() {
63238405Sjkim  if (m_symbols != NULL) {
64160814Ssimon    os::free(m_symbols);
65160814Ssimon  }
6655714Skris
6755714Skris  if (m_next != NULL) {
68246772Sjkim    delete m_next;
69160814Ssimon  }
70160814Ssimon}
71160814Ssimon
7255714Skrisbool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
73194206Ssimon  if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
74109998Smarkm    Elf_Word st_size = sym->st_size;
75109998Smarkm    address sym_addr;
76109998Smarkm    if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) {
77160814Ssimon      // We need to go another step trough the function descriptor table (currently PPC64 only)
78109998Smarkm      sym_addr = funcDescTable->lookup(sym->st_value);
79109998Smarkm    } else {
80109998Smarkm      sym_addr = (address)sym->st_value;
81109998Smarkm    }
82109998Smarkm    if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
83109998Smarkm      *offset = (int)(addr - sym_addr);
8455714Skris      *posIndex = sym->st_name;
8555714Skris      *stringtableIndex = m_shdr.sh_link;
8655714Skris      return true;
8755714Skris    }
88238405Sjkim  }
89109998Smarkm  return false;
90109998Smarkm}
91109998Smarkm
92109998Smarkmbool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
93109998Smarkm  assert(stringtableIndex, "null string table index pointer");
9455714Skris  assert(posIndex, "null string table offset pointer");
9555714Skris  assert(offset, "null offset pointer");
9655714Skris
9755714Skris  if (NullDecoder::is_error(m_status)) {
9855714Skris    return false;
99109998Smarkm  }
10055714Skris
10155714Skris  size_t  sym_size = sizeof(Elf_Sym);
10255714Skris  assert((m_shdr.sh_size % sym_size) == 0, "check size");
103238405Sjkim  int count = m_shdr.sh_size / sym_size;
104160814Ssimon  if (m_symbols != NULL) {
105160814Ssimon    for (int index = 0; index < count; index ++) {
106160814Ssimon      if (compare(&m_symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
107160814Ssimon        return true;
108160814Ssimon      }
109160814Ssimon    }
110160814Ssimon  } else {
111160814Ssimon    long cur_pos;
112160814Ssimon    if ((cur_pos = ftell(m_file)) == -1 ||
113160814Ssimon      fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
114160814Ssimon      m_status = NullDecoder::file_invalid;
115160814Ssimon      return false;
116160814Ssimon    }
117160814Ssimon
118160814Ssimon    Elf_Sym sym;
119160814Ssimon    for (int index = 0; index < count; index ++) {
120160814Ssimon      if (fread(&sym, sym_size, 1, m_file) == 1) {
121160814Ssimon        if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
122160814Ssimon          return true;
123160814Ssimon        }
124160814Ssimon      } else {
125238405Sjkim        m_status = NullDecoder::file_invalid;
126160814Ssimon        return false;
127160814Ssimon      }
128160814Ssimon    }
129160814Ssimon    fseek(m_file, cur_pos, SEEK_SET);
130160814Ssimon  }
131160814Ssimon  return false;
132160814Ssimon}
133160814Ssimon
134160814Ssimon#endif // !_WINDOWS && !__APPLE__
135160814Ssimon