8019929: PPC64 (part 107): Extend ELF-decoder to support PPC64 function descriptor tables
Summary: Extend ELF-decoder to support PPC64 function descriptor tables
Reviewed-by: kvn, zgu
--- a/hotspot/make/aix/makefiles/vm.make Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/make/aix/makefiles/vm.make Thu Dec 05 19:19:09 2013 +0100
@@ -202,8 +202,8 @@
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)
--- a/hotspot/src/os/linux/vm/decoder_linux.cpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/os/linux/vm/decoder_linux.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -32,6 +32,12 @@
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'.
--- a/hotspot/src/share/vm/utilities/decoder_elf.cpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/decoder_elf.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -73,4 +73,4 @@
return file;
}
-#endif
+#endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/decoder_elf.hpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/decoder_elf.hpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
ElfFile* _opened_elf_files;
};
-#endif
+#endif // !_WINDOWS && !__APPLE__
#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP
--- a/hotspot/src/share/vm/utilities/elfFile.cpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
#endif
-#endif // _WINDOWS
+#endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/elfFile.hpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
class ElfStringTable;
class ElfSymbolTable;
+class ElfFuncDescTable;
// On Solaris/Linux platforms, libjvm.so does contain all private symbols.
@@ -150,9 +151,12 @@
// 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/elfFuncDescTable.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -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__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/elfFuncDescTable.hpp Thu Dec 05 19:19:09 2013 +0100
@@ -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
--- a/hotspot/src/share/vm/utilities/elfStringTable.cpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfStringTable.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
}
}
-#endif // _WINDOWS
+#endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/elfStringTable.hpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfStringTable.hpp Thu Dec 05 19:19:09 2013 +0100
@@ -70,6 +70,6 @@
NullDecoder::decoder_status m_status;
};
-#endif // _WINDOWS and _APPLE
+#endif // !_WINDOWS && !__APPLE__
#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
}
}
-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 @@
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 @@
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 @@
return true;
}
-#endif // _WINDOWS
+#endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Wed Nov 27 16:16:21 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Thu Dec 05 19:19:09 2013 +0100
@@ -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 @@
~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 @@
NullDecoder::decoder_status m_status;
};
-#endif // _WINDOWS and _APPLE
+#endif // !_WINDOWS and !__APPLE__
#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP