changeset 6478:e37038685e3f

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
author goetz
date Mon, 10 Feb 2014 11:09:31 +0100
parents 4b0ce9977f3c
children dfc4a5d5995b
files make/aix/makefiles/vm.make src/os/linux/vm/decoder_linux.cpp src/share/vm/utilities/decoder_elf.cpp src/share/vm/utilities/decoder_elf.hpp src/share/vm/utilities/elfFile.cpp src/share/vm/utilities/elfFile.hpp src/share/vm/utilities/elfFuncDescTable.cpp src/share/vm/utilities/elfFuncDescTable.hpp src/share/vm/utilities/elfStringTable.cpp src/share/vm/utilities/elfStringTable.hpp src/share/vm/utilities/elfSymbolTable.cpp src/share/vm/utilities/elfSymbolTable.hpp
diffstat 12 files changed, 312 insertions(+), 158 deletions(-) [+]
line wrap: on
line diff
--- a/make/aix/makefiles/vm.make	Mon Feb 10 10:47:51 2014 +0100
+++ b/make/aix/makefiles/vm.make	Mon Feb 10 11:09:31 2014 +0100
@@ -201,8 +201,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/src/os/linux/vm/decoder_linux.cpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/os/linux/vm/decoder_linux.cpp	Mon Feb 10 11:09:31 2014 +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/src/share/vm/utilities/decoder_elf.cpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/decoder_elf.cpp	Mon Feb 10 11:09:31 2014 +0100
@@ -73,4 +73,4 @@
 
   return file;
 }
-#endif
+#endif // !_WINDOWS && !__APPLE__
--- a/src/share/vm/utilities/decoder_elf.hpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/decoder_elf.hpp	Mon Feb 10 11:09:31 2014 +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/src/share/vm/utilities/elfFile.cpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfFile.cpp	Mon Feb 10 11:09:31 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, 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,17 +121,16 @@
         m_status = NullDecoder::file_invalid;
         return false;
       }
-      // string tables
       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;
           return false;
         }
         add_string_table(table);
-      }
-      // symbol tables
-      else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
+      } 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;
@@ -141,8 +142,14 @@
 
 #if defined(PPC64)
     // Now read the .opd section wich contains the PPC64 function descriptor table.
-    // This is only possible after we have successfully read in the string tables in te previous loop.
-    m_funcDesc_table = NULL;
+    // 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;
@@ -159,9 +166,14 @@
           m_status = NullDecoder::file_invalid;
           return false;
         }
-        char buf[8]; // We only want to read ".opd"
+        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);
+          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;
         }
       }
     }
@@ -182,11 +194,7 @@
   int off = INT_MAX;
   bool found_symbol = false;
   while (symbol_table != NULL) {
-#if defined(PPC64)
     if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
-#else
-    if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) {
-#endif
       found_symbol = true;
       break;
     }
@@ -257,4 +265,4 @@
 }
 #endif
 
-#endif // _WINDOWS
+#endif // !_WINDOWS && !__APPLE__
--- a/src/share/vm/utilities/elfFile.hpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfFile.hpp	Mon Feb 10 11:09:31 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, 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,9 +75,7 @@
 
 class ElfStringTable;
 class ElfSymbolTable;
-#if defined(PPC64)
 class ElfFuncDescTable;
-#endif
 
 
 // On Solaris/Linux platforms, libjvm.so does contain all private symbols.
@@ -153,14 +151,12 @@
   // string tables
   ElfStringTable*              m_string_tables;
 
-#if defined(PPC64)
   // function descriptors table
   ElfFuncDescTable*            m_funcDesc_table;
-#endif
 
   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/src/share/vm/utilities/elfFuncDescTable.cpp	Mon Feb 10 11:09:31 2014 +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/src/share/vm/utilities/elfFuncDescTable.hpp	Mon Feb 10 11:09:31 2014 +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/src/share/vm/utilities/elfStringTable.cpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfStringTable.cpp	Mon Feb 10 11:09:31 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, 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/src/share/vm/utilities/elfStringTable.hpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfStringTable.hpp	Mon Feb 10 11:09:31 2014 +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/src/share/vm/utilities/elfSymbolTable.cpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfSymbolTable.cpp	Mon Feb 10 11:09:31 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, 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,11 +69,7 @@
   }
 }
 
-#if defined(PPC64)
 bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
-#else
-bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) {
-#endif
   assert(stringtableIndex, "null string table index pointer");
   assert(posIndex, "null string table offset pointer");
   assert(offset, "null offset pointer");
@@ -88,13 +85,14 @@
     for (int index = 0; index < count; index ++) {
       if (STT_FUNC == ELF_ST_TYPE(m_symbols[index].st_info)) {
         Elf_Word st_size = m_symbols[index].st_size;
-#if defined(PPC64)
-        Elf_Word sym_fd = m_symbols[index].st_value;
-        address sym_addr = funcDescTable->lookup(sym_fd);
-#else
-        address sym_addr = (address)m_symbols[index].st_value;
-#endif
-        if (sym_addr <= addr && (addr - sym_addr) < 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;
@@ -115,13 +113,14 @@
       if (fread(&sym, sym_size, 1, m_file) == 1) {
         if (STT_FUNC == ELF_ST_TYPE(sym.st_info)) {
           Elf_Word st_size = sym.st_size;
-#if defined(PPC64)
-          Elf_Word sym_fd = sym.st_value;
-          address sym_addr = funcDescTable->lookup(sym_fd);
-#else
-          address sym_addr = (address)sym.st_value;
-#endif
-          if (sym_addr <= addr && (addr - sym_addr) < 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;
@@ -138,79 +137,4 @@
   return true;
 }
 
-#if defined(PPC64)
-
-ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr) {
-  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_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
-
-#endif // _WINDOWS
+#endif // !_WINDOWS && !__APPLE__
--- a/src/share/vm/utilities/elfSymbolTable.hpp	Mon Feb 10 10:47:51 2014 +0100
+++ b/src/share/vm/utilities/elfSymbolTable.hpp	Mon Feb 10 11:09:31 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, 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,11 +45,7 @@
   ~ElfSymbolTable();
 
   // search the symbol that is nearest to the specified address.
-#if defined(PPC64)
   bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
-#else
-  bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset);
-#endif
 
   NullDecoder::decoder_status get_status() { return m_status; };
 
@@ -69,35 +65,6 @@
   NullDecoder::decoder_status  m_status;
 };
 
-#if defined(PPC64)
-
-class ElfFuncDescTable: public CHeapObj<mtInternal> {
-  friend class ElfFile;
- public:
-  ElfFuncDescTable(FILE* file, Elf_Shdr shdr);
-  ~ElfFuncDescTable();
-
-  // return the function address for the function descriptor at 'index' or NULL on error
-  address lookup(Elf_Word 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;
-
-  NullDecoder::decoder_status  m_status;
-};
-
-#endif
-
-#endif // _WINDOWS and _APPLE
+#endif // !_WINDOWS and !__APPLE__
 
 #endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP