src/share/vm/utilities/elfFile.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

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

mercurial