Mercurial > hg > icedtea7-forest > hotspot
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