hotspot/src/share/vm/utilities/elfFile.cpp
changeset 22872 b6902ee5bc8d
parent 22234 da823d78ad65
parent 22857 2167396cfc83
child 23211 954e3a81da29
--- a/hotspot/src/share/vm/utilities/elfFile.cpp	Tue Jan 28 11:21:43 2014 -0800
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp	Tue Jan 28 12:25:34 2014 -0800
@@ -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__