mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8019929: PPC64 (part 107): Extend ELF-decoder to support PPC64 function descriptor tables
Extend ELF-decoder to support PPC64 function descriptor tables Reviewed-by: kvn, zgu
This commit is contained in:
parent
ecca1bcc72
commit
d767bd2dfd
12 changed files with 350 additions and 29 deletions
|
@ -202,8 +202,8 @@ Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_
|
|||
|
||||
Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE))
|
||||
|
||||
# Disable 155427 on aix.
|
||||
Src_Files_EXCLUDE += decoder_elf.cpp elfFile.cpp elfStringTable.cpp elfSymbolTable.cpp
|
||||
# Disable ELF decoder on AIX (AIX uses XCOFF).
|
||||
Src_Files_EXCLUDE += decoder_elf.cpp elfFile.cpp elfStringTable.cpp elfSymbolTable.cpp elfFuncDescTable.cpp
|
||||
|
||||
# Special handling of arch model.
|
||||
ifeq ($(Platform_arch_model), x86_32)
|
||||
|
|
|
@ -32,6 +32,12 @@ bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
|||
char* result;
|
||||
size_t size = (size_t)buflen;
|
||||
|
||||
#ifdef PPC64
|
||||
// On PPC64 ElfDecoder::decode() may return a dot (.) prefixed name
|
||||
// (see elfFuncDescTable.hpp for details)
|
||||
if (symbol && *symbol == '.') symbol += 1;
|
||||
#endif
|
||||
|
||||
// Don't pass buf to __cxa_demangle. In case of the 'buf' is too small,
|
||||
// __cxa_demangle will call system "realloc" for additional memory, which
|
||||
// may use different malloc/realloc mechanism that allocates 'buf'.
|
||||
|
|
|
@ -73,4 +73,4 @@ ElfFile* ElfDecoder::get_elf_file(const char* filepath) {
|
|||
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -55,5 +55,5 @@ private:
|
|||
ElfFile* _opened_elf_files;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -34,6 +34,7 @@
|
|||
#include "memory/allocation.inline.hpp"
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "utilities/elfFile.hpp"
|
||||
#include "utilities/elfFuncDescTable.hpp"
|
||||
#include "utilities/elfStringTable.hpp"
|
||||
#include "utilities/elfSymbolTable.hpp"
|
||||
|
||||
|
@ -43,6 +44,7 @@ ElfFile::ElfFile(const char* filepath) {
|
|||
memset(&m_elfHdr, 0, sizeof(m_elfHdr));
|
||||
m_string_tables = NULL;
|
||||
m_symbol_tables = NULL;
|
||||
m_funcDesc_table = NULL;
|
||||
m_next = NULL;
|
||||
m_status = NullDecoder::no_error;
|
||||
|
||||
|
@ -119,8 +121,8 @@ bool ElfFile::load_tables() {
|
|||
m_status = NullDecoder::file_invalid;
|
||||
return false;
|
||||
}
|
||||
// string table
|
||||
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;
|
||||
|
@ -128,6 +130,7 @@ bool ElfFile::load_tables() {
|
|||
}
|
||||
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;
|
||||
|
@ -136,6 +139,46 @@ bool ElfFile::load_tables() {
|
|||
add_symbol_table(table);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PPC64)
|
||||
// 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;
|
||||
}
|
||||
|
@ -151,8 +194,9 @@ bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
|||
int off = INT_MAX;
|
||||
bool found_symbol = false;
|
||||
while (symbol_table != NULL) {
|
||||
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
|
||||
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
|
||||
found_symbol = true;
|
||||
break;
|
||||
}
|
||||
symbol_table = symbol_table->m_next;
|
||||
}
|
||||
|
@ -221,4 +265,4 @@ bool ElfFile::specifies_noexecstack() {
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -75,6 +75,7 @@ typedef Elf32_Sym Elf_Sym;
|
|||
|
||||
class ElfStringTable;
|
||||
class ElfSymbolTable;
|
||||
class ElfFuncDescTable;
|
||||
|
||||
|
||||
// On Solaris/Linux platforms, libjvm.so does contain all private symbols.
|
||||
|
@ -150,9 +151,12 @@ protected:
|
|||
// string tables
|
||||
ElfStringTable* m_string_tables;
|
||||
|
||||
// function descriptors table
|
||||
ElfFuncDescTable* m_funcDesc_table;
|
||||
|
||||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
||||
#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP
|
||||
|
|
104
hotspot/src/share/vm/utilities/elfFuncDescTable.cpp
Normal file
104
hotspot/src/share/vm/utilities/elfFuncDescTable.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2012, 2013 SAP AG. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "utilities/elfFuncDescTable.hpp"
|
||||
|
||||
ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) {
|
||||
assert(file, "null file handle");
|
||||
// The actual function address (i.e. function entry point) is always the
|
||||
// first value in the function descriptor (on IA64 and PPC64 they look as follows):
|
||||
// PPC64: [function entry point, TOC pointer, environment pointer]
|
||||
// IA64 : [function entry point, GP (global pointer) value]
|
||||
// Unfortunately 'shdr.sh_entsize' doesn't always seem to contain this size (it's zero on PPC64) so we can't assert
|
||||
// assert(IA64_ONLY(2) PPC64_ONLY(3) * sizeof(address) == shdr.sh_entsize, "Size mismatch for '.opd' section entries");
|
||||
|
||||
m_funcDescs = NULL;
|
||||
m_file = file;
|
||||
m_index = index;
|
||||
m_status = NullDecoder::no_error;
|
||||
|
||||
// try to load the function descriptor table
|
||||
long cur_offset = ftell(file);
|
||||
if (cur_offset != -1) {
|
||||
// call malloc so we can back up if memory allocation fails.
|
||||
m_funcDescs = (address*)os::malloc(shdr.sh_size, mtInternal);
|
||||
if (m_funcDescs) {
|
||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
||||
fread((void*)m_funcDescs, shdr.sh_size, 1, file) != 1 ||
|
||||
fseek(file, cur_offset, SEEK_SET)) {
|
||||
m_status = NullDecoder::file_invalid;
|
||||
os::free(m_funcDescs);
|
||||
m_funcDescs = NULL;
|
||||
}
|
||||
}
|
||||
if (!NullDecoder::is_error(m_status)) {
|
||||
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
||||
}
|
||||
} else {
|
||||
m_status = NullDecoder::file_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
ElfFuncDescTable::~ElfFuncDescTable() {
|
||||
if (m_funcDescs != NULL) {
|
||||
os::free(m_funcDescs);
|
||||
}
|
||||
}
|
||||
|
||||
address ElfFuncDescTable::lookup(Elf_Word index) {
|
||||
if (NullDecoder::is_error(m_status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (m_funcDescs != NULL) {
|
||||
if (m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size) {
|
||||
// Notice that 'index' is a byte-offset into the function descriptor table.
|
||||
return m_funcDescs[(index - m_shdr.sh_addr) / sizeof(address)];
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
long cur_pos;
|
||||
address addr;
|
||||
if (!(m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size)) {
|
||||
// don't put the whole decoder in error mode if we just tried a wrong index
|
||||
return NULL;
|
||||
}
|
||||
if ((cur_pos = ftell(m_file)) == -1 ||
|
||||
fseek(m_file, m_shdr.sh_offset + index - m_shdr.sh_addr, SEEK_SET) ||
|
||||
fread(&addr, sizeof(addr), 1, m_file) != 1 ||
|
||||
fseek(m_file, cur_pos, SEEK_SET)) {
|
||||
m_status = NullDecoder::file_invalid;
|
||||
return NULL;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !_WINDOWS && !__APPLE__
|
149
hotspot/src/share/vm/utilities/elfFuncDescTable.hpp
Normal file
149
hotspot/src/share/vm/utilities/elfFuncDescTable.hpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2012, 2013 SAP AG. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP
|
||||
#define SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP
|
||||
|
||||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/decoder.hpp"
|
||||
#include "utilities/elfFile.hpp"
|
||||
|
||||
/*
|
||||
|
||||
On PowerPC-64 (and other architectures like for example IA64) a pointer to a
|
||||
function is not just a plain code address, but instead a pointer to a so called
|
||||
function descriptor (which is simply a structure containing 3 pointers).
|
||||
This fact is also reflected in the ELF ABI for PowerPC-64.
|
||||
|
||||
On architectures like x86 or SPARC, the ELF symbol table contains the start
|
||||
address and size of an object. So for example for a function object (i.e. type
|
||||
'STT_FUNC') the symbol table's 'st_value' and 'st_size' fields directly
|
||||
represent the starting address and size of that function. On PPC64 however, the
|
||||
symbol table's 'st_value' field only contains an index into another, PPC64
|
||||
specific '.opd' (official procedure descriptors) section, while the 'st_size'
|
||||
field still holds the size of the corresponding function. In order to get the
|
||||
actual start address of a function, it is necessary to read the corresponding
|
||||
function descriptor entry in the '.opd' section at the corresponding index and
|
||||
extract the start address from there.
|
||||
|
||||
That's exactly what this 'ElfFuncDescTable' class is used for. If the HotSpot
|
||||
runs on a PPC64 machine, and the corresponding ELF files contains an '.opd'
|
||||
section (which is actually mandatory on PPC64) it will be read into an object
|
||||
of type 'ElfFuncDescTable' just like the string and symbol table sections.
|
||||
Later on, during symbol lookup in 'ElfSymbolTable::lookup()' this function
|
||||
descriptor table will be used if available to find the real function address.
|
||||
|
||||
All this is how things work today (2013) on contemporary Linux distributions
|
||||
(i.e. SLES 10) and new version of GCC (i.e. > 4.0). However there is a history,
|
||||
and it goes like this:
|
||||
|
||||
In SLES 9 times (sometimes before GCC 3.4) gcc/ld on PPC64 generated two
|
||||
entries in the symbol table for every function. The value of the symbol with
|
||||
the name of the function was the address of the function descriptor while the
|
||||
dot '.' prefixed name was reserved to hold the actual address of that function
|
||||
(http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES).
|
||||
|
||||
For a C-function 'foo' this resulted in two symbol table entries like this
|
||||
(extracted from the output of 'readelf -a <lib.so>'):
|
||||
|
||||
Section Headers:
|
||||
[ 9] .text PROGBITS 0000000000000a20 00000a20
|
||||
00000000000005a0 0000000000000000 AX 0 0 16
|
||||
[21] .opd PROGBITS 00000000000113b8 000013b8
|
||||
0000000000000138 0000000000000000 WA 0 0 8
|
||||
|
||||
Symbol table '.symtab' contains 86 entries:
|
||||
Num: Value Size Type Bind Vis Ndx Name
|
||||
76: 00000000000114c0 24 FUNC GLOBAL DEFAULT 21 foo
|
||||
78: 0000000000000bb0 76 FUNC GLOBAL DEFAULT 9 .foo
|
||||
|
||||
You can see now that the '.foo' entry actually points into the '.text' segment
|
||||
('Ndx'=9) and its value and size fields represent the functions actual address
|
||||
and size. On the other hand, the entry for plain 'foo' points into the '.opd'
|
||||
section ('Ndx'=21) and its value and size fields are the index into the '.opd'
|
||||
section and the size of the corresponding '.opd' section entry (3 pointers on
|
||||
PPC64).
|
||||
|
||||
These so called 'dot symbols' were dropped around gcc 3.4 from GCC and BINUTILS,
|
||||
see http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html.
|
||||
But nevertheless it may still be necessary to support both formats because we
|
||||
either run on an old system or because it is possible at any time that functions
|
||||
appear in the stack trace which come from old-style libraries.
|
||||
|
||||
Therefore we not only have to check for the presence of the function descriptor
|
||||
table during symbol lookup in 'ElfSymbolTable::lookup()'. We additionally have
|
||||
to check that the symbol table entry references the '.opd' section. Only in
|
||||
that case we can resolve the actual function address from there. Otherwise we
|
||||
use the plain 'st_value' field from the symbol table as function address. This
|
||||
way we can also lookup the symbols in old-style ELF libraries (although we get
|
||||
the 'dotted' versions in that case). However, if present, the 'dot' will be
|
||||
conditionally removed on PPC64 from the symbol in 'ElfDecoder::demangle()' in
|
||||
decoder_linux.cpp.
|
||||
|
||||
Notice that we can not reliably get the function address from old-style
|
||||
libraries because the 'st_value' field of the symbol table entries which point
|
||||
into the '.opd' section denote the size of the corresponding '.opd' entry and
|
||||
not that of the corresponding function. This has changed for the symbol table
|
||||
entries in new-style libraries as described at the beginning of this
|
||||
documentation.
|
||||
|
||||
*/
|
||||
|
||||
class ElfFuncDescTable: public CHeapObj<mtInternal> {
|
||||
friend class ElfFile;
|
||||
public:
|
||||
ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index);
|
||||
~ElfFuncDescTable();
|
||||
|
||||
// return the function address for the function descriptor at 'index' or NULL on error
|
||||
address lookup(Elf_Word index);
|
||||
|
||||
int get_index() { return m_index; };
|
||||
|
||||
NullDecoder::decoder_status get_status() { return m_status; };
|
||||
|
||||
protected:
|
||||
// holds the complete function descriptor section if
|
||||
// we can allocate enough memory
|
||||
address* m_funcDescs;
|
||||
|
||||
// file contains string table
|
||||
FILE* m_file;
|
||||
|
||||
// section header
|
||||
Elf_Shdr m_shdr;
|
||||
|
||||
// The section index of this function descriptor (i.e. '.opd') section in the ELF file
|
||||
int m_index;
|
||||
|
||||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
||||
#endif // SHARE_VM_UTILITIES_ELF_FUNC_DESC_TABLE_HPP
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -87,4 +87,4 @@ bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
|
|
@ -70,6 +70,6 @@ class ElfStringTable: CHeapObj<mtInternal> {
|
|||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS and _APPLE
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
||||
#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,6 +27,7 @@
|
|||
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "utilities/elfFuncDescTable.hpp"
|
||||
#include "utilities/elfSymbolTable.hpp"
|
||||
|
||||
ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
||||
|
@ -68,7 +69,7 @@ ElfSymbolTable::~ElfSymbolTable() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
|
||||
bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
|
||||
assert(stringtableIndex, "null string table index pointer");
|
||||
assert(posIndex, "null string table offset pointer");
|
||||
assert(offset, "null offset pointer");
|
||||
|
@ -77,19 +78,25 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex,
|
|||
return false;
|
||||
}
|
||||
|
||||
address pc = 0;
|
||||
size_t sym_size = sizeof(Elf_Sym);
|
||||
assert((m_shdr.sh_size % sym_size) == 0, "check size");
|
||||
int count = m_shdr.sh_size / sym_size;
|
||||
if (m_symbols != NULL) {
|
||||
for (int index = 0; index < count; index ++) {
|
||||
if (STT_FUNC == ELF_ST_TYPE(m_symbols[index].st_info)) {
|
||||
address sym_addr = (address)m_symbols[index].st_value;
|
||||
if (sym_addr < addr && (addr - sym_addr) < *offset) {
|
||||
pc = (address)m_symbols[index].st_value;
|
||||
*offset = (int)(addr - pc);
|
||||
Elf_Word st_size = m_symbols[index].st_size;
|
||||
address sym_addr;
|
||||
if (funcDescTable != NULL && funcDescTable->get_index() == m_symbols[index].st_shndx) {
|
||||
// We need to go another step trough the function descriptor table (currently PPC64 only)
|
||||
sym_addr = funcDescTable->lookup(m_symbols[index].st_value);
|
||||
} else {
|
||||
sym_addr = (address)m_symbols[index].st_value;
|
||||
}
|
||||
if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
|
||||
*offset = (int)(addr - sym_addr);
|
||||
*posIndex = m_symbols[index].st_name;
|
||||
*stringtableIndex = m_shdr.sh_link;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,12 +112,19 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex,
|
|||
for (int index = 0; index < count; index ++) {
|
||||
if (fread(&sym, sym_size, 1, m_file) == 1) {
|
||||
if (STT_FUNC == ELF_ST_TYPE(sym.st_info)) {
|
||||
address sym_addr = (address)sym.st_value;
|
||||
if (sym_addr < addr && (addr - sym_addr) < *offset) {
|
||||
pc = (address)sym.st_value;
|
||||
*offset = (int)(addr - pc);
|
||||
Elf_Word st_size = sym.st_size;
|
||||
address sym_addr;
|
||||
if (funcDescTable != NULL && funcDescTable->get_index() == sym.st_shndx) {
|
||||
// We need to go another step trough the function descriptor table (currently PPC64 only)
|
||||
sym_addr = funcDescTable->lookup(sym.st_value);
|
||||
} else {
|
||||
sym_addr = (address)sym.st_value;
|
||||
}
|
||||
if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
|
||||
*offset = (int)(addr - sym_addr);
|
||||
*posIndex = sym.st_name;
|
||||
*stringtableIndex = m_shdr.sh_link;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -123,4 +137,4 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex,
|
|||
return true;
|
||||
}
|
||||
|
||||
#endif // _WINDOWS
|
||||
#endif // !_WINDOWS && !__APPLE__
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -45,7 +45,7 @@ class ElfSymbolTable: public CHeapObj<mtInternal> {
|
|||
~ElfSymbolTable();
|
||||
|
||||
// search the symbol that is nearest to the specified address.
|
||||
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
|
||||
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
|
||||
|
||||
NullDecoder::decoder_status get_status() { return m_status; };
|
||||
|
||||
|
@ -65,6 +65,6 @@ class ElfSymbolTable: public CHeapObj<mtInternal> {
|
|||
NullDecoder::decoder_status m_status;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS and _APPLE
|
||||
#endif // !_WINDOWS and !__APPLE__
|
||||
|
||||
#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue