src/share/vm/utilities/elfFile.cpp

Tue, 19 Aug 2014 08:34:25 -0400

author
zgu
date
Tue, 19 Aug 2014 08:34:25 -0400
changeset 7078
c6211b707068
parent 6511
31e80afe3fed
child 6876
710a3c8b516e
child 7857
8c3941f2020c
permissions
-rw-r--r--

8055007: NMT2: emptyStack missing in minimal build
Summary: Refactored emptyStack to a static member of NativeCallStack, which is accessible in minimal build.
Reviewed-by: coleenp, dholmes

zgu@2364 1 /*
mikael@6198 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
zgu@2364 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
zgu@2364 4 *
zgu@2364 5 * This code is free software; you can redistribute it and/or modify it
zgu@2364 6 * under the terms of the GNU General Public License version 2 only, as
zgu@2364 7 * published by the Free Software Foundation.
zgu@2364 8 *
zgu@2364 9 * This code is distributed in the hope that it will be useful, but WITHOUT
zgu@2364 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
zgu@2364 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
zgu@2364 12 * version 2 for more details (a copy is included in the LICENSE file that
zgu@2364 13 * accompanied this code).
zgu@2364 14 *
zgu@2364 15 * You should have received a copy of the GNU General Public License version
zgu@2364 16 * 2 along with this work; if not, write to the Free Software Foundation,
zgu@2364 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
zgu@2364 18 *
zgu@2364 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
zgu@2364 20 * or visit www.oracle.com if you need additional information or have any
zgu@2364 21 * questions.
zgu@2364 22 *
zgu@2364 23 */
zgu@2364 24
zgu@2364 25 #include "precompiled.hpp"
zgu@2364 26
never@3156 27 #if !defined(_WINDOWS) && !defined(__APPLE__)
zgu@2364 28
zgu@2364 29 #include <string.h>
zgu@2364 30 #include <stdio.h>
zgu@2364 31 #include <limits.h>
zgu@2834 32 #include <new>
zgu@2364 33
zgu@2364 34 #include "memory/allocation.inline.hpp"
zgu@2364 35 #include "utilities/decoder.hpp"
zgu@2364 36 #include "utilities/elfFile.hpp"
simonis@6491 37 #include "utilities/elfFuncDescTable.hpp"
zgu@2364 38 #include "utilities/elfStringTable.hpp"
zgu@2364 39 #include "utilities/elfSymbolTable.hpp"
zgu@2364 40
zgu@2364 41
zgu@2364 42 ElfFile::ElfFile(const char* filepath) {
zgu@2364 43 assert(filepath, "null file path");
zgu@2364 44 memset(&m_elfHdr, 0, sizeof(m_elfHdr));
zgu@2364 45 m_string_tables = NULL;
zgu@2364 46 m_symbol_tables = NULL;
simonis@6491 47 m_funcDesc_table = NULL;
zgu@2364 48 m_next = NULL;
zgu@3430 49 m_status = NullDecoder::no_error;
zgu@2364 50
zgu@2364 51 int len = strlen(filepath) + 1;
zgu@3900 52 m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);
zgu@2364 53 if (m_filepath != NULL) {
zgu@2364 54 strcpy((char*)m_filepath, filepath);
zgu@2364 55 m_file = fopen(filepath, "r");
zgu@2364 56 if (m_file != NULL) {
zgu@2364 57 load_tables();
zgu@2364 58 } else {
zgu@3430 59 m_status = NullDecoder::file_not_found;
zgu@2364 60 }
zgu@2364 61 } else {
zgu@3430 62 m_status = NullDecoder::out_of_memory;
zgu@2364 63 }
zgu@2364 64 }
zgu@2364 65
zgu@2364 66 ElfFile::~ElfFile() {
zgu@2364 67 if (m_string_tables != NULL) {
zgu@2364 68 delete m_string_tables;
zgu@2364 69 }
zgu@2364 70
zgu@2364 71 if (m_symbol_tables != NULL) {
zgu@2364 72 delete m_symbol_tables;
zgu@2364 73 }
zgu@2364 74
zgu@2364 75 if (m_file != NULL) {
zgu@2364 76 fclose(m_file);
zgu@2364 77 }
zgu@2364 78
zgu@2364 79 if (m_filepath != NULL) {
zgu@2834 80 os::free((void*)m_filepath);
zgu@2364 81 }
zgu@2364 82
zgu@2364 83 if (m_next != NULL) {
zgu@2364 84 delete m_next;
zgu@2364 85 }
zgu@2364 86 };
zgu@2364 87
zgu@2364 88
zgu@2364 89 //Check elf header to ensure the file is valid.
zgu@2364 90 bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
zgu@2364 91 return (ELFMAG0 == hdr.e_ident[EI_MAG0] &&
zgu@2364 92 ELFMAG1 == hdr.e_ident[EI_MAG1] &&
zgu@2364 93 ELFMAG2 == hdr.e_ident[EI_MAG2] &&
zgu@2364 94 ELFMAG3 == hdr.e_ident[EI_MAG3] &&
zgu@2364 95 ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&
zgu@2364 96 ELFDATANONE != hdr.e_ident[EI_DATA]);
zgu@2364 97 }
zgu@2364 98
zgu@2364 99 bool ElfFile::load_tables() {
zgu@2364 100 assert(m_file, "file not open");
zgu@3430 101 assert(!NullDecoder::is_error(m_status), "already in error");
zgu@2364 102
zgu@2364 103 // read elf file header
zgu@2364 104 if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
zgu@3430 105 m_status = NullDecoder::file_invalid;
zgu@2364 106 return false;
zgu@2364 107 }
zgu@2364 108
zgu@2364 109 if (!is_elf_file(m_elfHdr)) {
zgu@3430 110 m_status = NullDecoder::file_invalid;
zgu@2364 111 return false;
zgu@2364 112 }
zgu@2364 113
zgu@2364 114 // walk elf file's section headers, and load string tables
zgu@2364 115 Elf_Shdr shdr;
zgu@2364 116 if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
zgu@3430 117 if (NullDecoder::is_error(m_status)) return false;
zgu@2364 118
zgu@2364 119 for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
zgu@2364 120 if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
zgu@3430 121 m_status = NullDecoder::file_invalid;
zgu@2364 122 return false;
zgu@2364 123 }
zgu@2364 124 if (shdr.sh_type == SHT_STRTAB) {
simonis@6491 125 // string tables
zgu@2834 126 ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
zgu@2364 127 if (table == NULL) {
zgu@3430 128 m_status = NullDecoder::out_of_memory;
zgu@2364 129 return false;
zgu@2364 130 }
zgu@2364 131 add_string_table(table);
zgu@2364 132 } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
simonis@6491 133 // symbol tables
zgu@2834 134 ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
zgu@2364 135 if (table == NULL) {
zgu@3430 136 m_status = NullDecoder::out_of_memory;
zgu@2364 137 return false;
zgu@2364 138 }
zgu@2364 139 add_symbol_table(table);
zgu@2364 140 }
zgu@2364 141 }
simonis@6491 142
goetz@6511 143 #if defined(PPC64) && !defined(ABI_ELFv2)
simonis@6491 144 // Now read the .opd section wich contains the PPC64 function descriptor table.
simonis@6491 145 // The .opd section is only available on PPC64 (see for example:
simonis@6491 146 // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
simonis@6491 147 // so this code should do no harm on other platforms but because of performance reasons we only
simonis@6491 148 // execute it on PPC64 platforms.
simonis@6491 149 // Notice that we can only find the .opd section after we have successfully read in the string
simonis@6491 150 // tables in the previous loop, because we need to query the name of each section which is
simonis@6491 151 // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
simonis@6491 152
simonis@6491 153 // Reset the file pointer
simonis@6491 154 if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
simonis@6491 155 m_status = NullDecoder::file_invalid;
simonis@6491 156 return false;
simonis@6491 157 }
simonis@6491 158 for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
simonis@6491 159 if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
simonis@6491 160 m_status = NullDecoder::file_invalid;
simonis@6491 161 return false;
simonis@6491 162 }
simonis@6491 163 if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {
simonis@6491 164 ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);
simonis@6491 165 if (string_table == NULL) {
simonis@6491 166 m_status = NullDecoder::file_invalid;
simonis@6491 167 return false;
simonis@6491 168 }
simonis@6491 169 char buf[8]; // '8' is enough because we only want to read ".opd"
simonis@6491 170 if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) {
simonis@6491 171 m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index);
simonis@6491 172 if (m_funcDesc_table == NULL) {
simonis@6491 173 m_status = NullDecoder::out_of_memory;
simonis@6491 174 return false;
simonis@6491 175 }
simonis@6491 176 break;
simonis@6491 177 }
simonis@6491 178 }
simonis@6491 179 }
simonis@6491 180 #endif
simonis@6491 181
zgu@2364 182 }
zgu@2364 183 return true;
zgu@2364 184 }
zgu@2364 185
zgu@3430 186 bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
zgu@2364 187 // something already went wrong, just give up
zgu@3430 188 if (NullDecoder::is_error(m_status)) {
zgu@3430 189 return false;
zgu@2364 190 }
zgu@2364 191 ElfSymbolTable* symbol_table = m_symbol_tables;
zgu@2364 192 int string_table_index;
zgu@2364 193 int pos_in_string_table;
zgu@2364 194 int off = INT_MAX;
zgu@2364 195 bool found_symbol = false;
zgu@2364 196 while (symbol_table != NULL) {
simonis@6491 197 if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
zgu@2364 198 found_symbol = true;
simonis@6491 199 break;
zgu@2364 200 }
zgu@2364 201 symbol_table = symbol_table->m_next;
zgu@2364 202 }
zgu@3430 203 if (!found_symbol) return false;
zgu@2364 204
zgu@2364 205 ElfStringTable* string_table = get_string_table(string_table_index);
zgu@3430 206
zgu@2364 207 if (string_table == NULL) {
zgu@3430 208 m_status = NullDecoder::file_invalid;
zgu@3430 209 return false;
zgu@2364 210 }
zgu@2364 211 if (offset) *offset = off;
zgu@3430 212
zgu@3430 213 return string_table->string_at(pos_in_string_table, buf, buflen);
zgu@2364 214 }
zgu@2364 215
zgu@2364 216
zgu@2364 217 void ElfFile::add_symbol_table(ElfSymbolTable* table) {
zgu@2364 218 if (m_symbol_tables == NULL) {
zgu@2364 219 m_symbol_tables = table;
zgu@2364 220 } else {
zgu@2364 221 table->m_next = m_symbol_tables;
zgu@2364 222 m_symbol_tables = table;
zgu@2364 223 }
zgu@2364 224 }
zgu@2364 225
zgu@2364 226 void ElfFile::add_string_table(ElfStringTable* table) {
zgu@2364 227 if (m_string_tables == NULL) {
zgu@2364 228 m_string_tables = table;
zgu@2364 229 } else {
zgu@2364 230 table->m_next = m_string_tables;
zgu@2364 231 m_string_tables = table;
zgu@2364 232 }
zgu@2364 233 }
zgu@2364 234
zgu@2364 235 ElfStringTable* ElfFile::get_string_table(int index) {
zgu@2364 236 ElfStringTable* p = m_string_tables;
zgu@2364 237 while (p != NULL) {
zgu@2364 238 if (p->index() == index) return p;
zgu@2364 239 p = p->m_next;
zgu@2364 240 }
zgu@2364 241 return NULL;
zgu@2364 242 }
zgu@2364 243
iklam@4710 244 #ifdef LINUX
iklam@4710 245 bool ElfFile::specifies_noexecstack() {
iklam@4710 246 Elf_Phdr phdr;
iklam@4710 247 if (!m_file) return true;
iklam@4710 248
iklam@4710 249 if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) {
iklam@4710 250 for (int index = 0; index < m_elfHdr.e_phnum; index ++) {
iklam@4710 251 if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) {
iklam@4710 252 m_status = NullDecoder::file_invalid;
iklam@4710 253 return false;
iklam@4710 254 }
iklam@4710 255 if (phdr.p_type == PT_GNU_STACK) {
iklam@4710 256 if (phdr.p_flags == (PF_R | PF_W)) {
iklam@4710 257 return true;
iklam@4710 258 } else {
iklam@4710 259 return false;
iklam@4710 260 }
iklam@4710 261 }
iklam@4710 262 }
iklam@4710 263 }
iklam@4710 264 return false;
iklam@4710 265 }
iklam@4710 266 #endif
iklam@4710 267
simonis@6491 268 #endif // !_WINDOWS && !__APPLE__

mercurial