Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/elfFile.cpp
32285 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"2526#if !defined(_WINDOWS) && !defined(__APPLE__)2728#include <string.h>29#include <stdio.h>30#include <limits.h>31#include <new>3233#include "memory/allocation.inline.hpp"34#include "utilities/decoder.hpp"35#include "utilities/elfFile.hpp"36#include "utilities/elfFuncDescTable.hpp"37#include "utilities/elfStringTable.hpp"38#include "utilities/elfSymbolTable.hpp"394041ElfFile::ElfFile(const char* filepath) {42assert(filepath, "null file path");43memset(&m_elfHdr, 0, sizeof(m_elfHdr));44m_string_tables = NULL;45m_symbol_tables = NULL;46m_funcDesc_table = NULL;47m_next = NULL;48m_status = NullDecoder::no_error;4950int len = strlen(filepath) + 1;51m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);52if (m_filepath != NULL) {53strcpy((char*)m_filepath, filepath);54m_file = fopen(filepath, "r");55if (m_file != NULL) {56load_tables();57} else {58m_status = NullDecoder::file_not_found;59}60} else {61m_status = NullDecoder::out_of_memory;62}63}6465ElfFile::~ElfFile() {66if (m_string_tables != NULL) {67delete m_string_tables;68}6970if (m_symbol_tables != NULL) {71delete m_symbol_tables;72}7374if (m_file != NULL) {75fclose(m_file);76}7778if (m_filepath != NULL) {79os::free((void*)m_filepath);80}8182if (m_next != NULL) {83delete m_next;84}85};868788//Check elf header to ensure the file is valid.89bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {90return (ELFMAG0 == hdr.e_ident[EI_MAG0] &&91ELFMAG1 == hdr.e_ident[EI_MAG1] &&92ELFMAG2 == hdr.e_ident[EI_MAG2] &&93ELFMAG3 == hdr.e_ident[EI_MAG3] &&94ELFCLASSNONE != hdr.e_ident[EI_CLASS] &&95ELFDATANONE != hdr.e_ident[EI_DATA]);96}9798bool ElfFile::load_tables() {99assert(m_file, "file not open");100assert(!NullDecoder::is_error(m_status), "already in error");101102// read elf file header103if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {104m_status = NullDecoder::file_invalid;105return false;106}107108if (!is_elf_file(m_elfHdr)) {109m_status = NullDecoder::file_invalid;110return false;111}112113// walk elf file's section headers, and load string tables114Elf_Shdr shdr;115if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {116if (NullDecoder::is_error(m_status)) return false;117118for (int index = 0; index < m_elfHdr.e_shnum; index ++) {119if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {120m_status = NullDecoder::file_invalid;121return false;122}123if (shdr.sh_type == SHT_STRTAB) {124// string tables125ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);126if (table == NULL) {127m_status = NullDecoder::out_of_memory;128return false;129}130add_string_table(table);131} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {132// symbol tables133ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);134if (table == NULL) {135m_status = NullDecoder::out_of_memory;136return false;137}138add_symbol_table(table);139}140}141142#if defined(PPC64) && !defined(ABI_ELFv2)143// Now read the .opd section wich contains the PPC64 function descriptor table.144// The .opd section is only available on PPC64 (see for example:145// http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)146// so this code should do no harm on other platforms but because of performance reasons we only147// execute it on PPC64 platforms.148// Notice that we can only find the .opd section after we have successfully read in the string149// tables in the previous loop, because we need to query the name of each section which is150// contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).151152// Reset the file pointer153if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {154m_status = NullDecoder::file_invalid;155return false;156}157for (int index = 0; index < m_elfHdr.e_shnum; index ++) {158if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {159m_status = NullDecoder::file_invalid;160return false;161}162if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {163ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);164if (string_table == NULL) {165m_status = NullDecoder::file_invalid;166return false;167}168char buf[8]; // '8' is enough because we only want to read ".opd"169if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) {170m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index);171if (m_funcDesc_table == NULL) {172m_status = NullDecoder::out_of_memory;173return false;174}175break;176}177}178}179#endif180181}182return true;183}184185bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {186// something already went wrong, just give up187if (NullDecoder::is_error(m_status)) {188return false;189}190ElfSymbolTable* symbol_table = m_symbol_tables;191int string_table_index;192int pos_in_string_table;193int off = INT_MAX;194bool found_symbol = false;195while (symbol_table != NULL) {196if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {197found_symbol = true;198break;199}200symbol_table = symbol_table->m_next;201}202if (!found_symbol) return false;203204ElfStringTable* string_table = get_string_table(string_table_index);205206if (string_table == NULL) {207m_status = NullDecoder::file_invalid;208return false;209}210if (offset) *offset = off;211212return string_table->string_at(pos_in_string_table, buf, buflen);213}214215216void ElfFile::add_symbol_table(ElfSymbolTable* table) {217if (m_symbol_tables == NULL) {218m_symbol_tables = table;219} else {220table->m_next = m_symbol_tables;221m_symbol_tables = table;222}223}224225void ElfFile::add_string_table(ElfStringTable* table) {226if (m_string_tables == NULL) {227m_string_tables = table;228} else {229table->m_next = m_string_tables;230m_string_tables = table;231}232}233234ElfStringTable* ElfFile::get_string_table(int index) {235ElfStringTable* p = m_string_tables;236while (p != NULL) {237if (p->index() == index) return p;238p = p->m_next;239}240return NULL;241}242243#ifdef LINUX244bool ElfFile::specifies_noexecstack() {245Elf_Phdr phdr;246if (!m_file) return true;247248if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) {249for (int index = 0; index < m_elfHdr.e_phnum; index ++) {250if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) {251m_status = NullDecoder::file_invalid;252return false;253}254if (phdr.p_type == PT_GNU_STACK) {255if (phdr.p_flags == (PF_R | PF_W)) {256return true;257} else {258return false;259}260}261}262}263// AARCH64 defaults to noexecstack. All others default to execstack.264#ifdef AARCH64265return true;266#else267return false;268#endif269}270#endif271272#endif // !_WINDOWS && !__APPLE__273274275