1 /*
2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 
27 #if !defined(_WINDOWS) && !defined(__APPLE__)
28 
29 #include "memory/allocation.inline.hpp"
30 #include "utilities/elfFuncDescTable.hpp"
31 #include "utilities/elfSymbolTable.hpp"
32 
ElfSymbolTable(FILE * const file,Elf_Shdr & shdr)33 ElfSymbolTable::ElfSymbolTable(FILE* const file, Elf_Shdr& shdr) :
34   _next(NULL), _fd(file), _section(file, shdr) {
35   assert(file != NULL, "null file handle");
36   _status = _section.status();
37 
38   if (_section.section_header()->sh_size % sizeof(Elf_Sym) != 0) {
39     _status = NullDecoder::file_invalid;
40   }
41 }
42 
~ElfSymbolTable()43 ElfSymbolTable::~ElfSymbolTable() {
44   if (_next != NULL) {
45     delete _next;
46   }
47 }
48 
compare(const Elf_Sym * sym,address addr,int * stringtableIndex,int * posIndex,int * offset,ElfFuncDescTable * funcDescTable)49 bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
50   if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
51     Elf_Word st_size = sym->st_size;
52     const Elf_Shdr* shdr = _section.section_header();
53     address sym_addr;
54     if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) {
55       // We need to go another step trough the function descriptor table (currently PPC64 only)
56       sym_addr = funcDescTable->lookup(sym->st_value);
57     } else {
58       sym_addr = (address)sym->st_value;
59     }
60     if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
61       *offset = (int)(addr - sym_addr);
62       *posIndex = sym->st_name;
63       *stringtableIndex = shdr->sh_link;
64       return true;
65     }
66   }
67   return false;
68 }
69 
lookup(address addr,int * stringtableIndex,int * posIndex,int * offset,ElfFuncDescTable * funcDescTable)70 bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
71   assert(stringtableIndex, "null string table index pointer");
72   assert(posIndex, "null string table offset pointer");
73   assert(offset, "null offset pointer");
74 
75   if (NullDecoder::is_error(get_status())) {
76     return false;
77   }
78 
79   size_t  sym_size = sizeof(Elf_Sym);
80   int count = _section.section_header()->sh_size / sym_size;
81   Elf_Sym* symbols = (Elf_Sym*)_section.section_data();
82 
83   if (symbols != NULL) {
84     for (int index = 0; index < count; index ++) {
85       if (compare(&symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
86         return true;
87       }
88     }
89   } else {
90     MarkedFileReader mfd(_fd);
91 
92     if (!mfd.has_mark() || !mfd.set_position(_section.section_header()->sh_offset)) {
93       _status = NullDecoder::file_invalid;
94       return false;
95     }
96 
97     Elf_Sym sym;
98     for (int index = 0; index < count; index ++) {
99       if (!mfd.read((void*)&sym, sizeof(sym))) {
100         _status = NullDecoder::file_invalid;
101         return false;
102       }
103 
104       if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
105         return true;
106       }
107     }
108   }
109   return false;
110 }
111 
112 #endif // !_WINDOWS && !__APPLE__
113