8193373: Cleanup ElfFile and family
Cleanup elf decoder and added test Reviewed-by: minqi, coleenp
This commit is contained in:
parent
d851dd077b
commit
f47021e2ab
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "utilities/decoder_elf.hpp"
|
#include "utilities/decoder_elf.hpp"
|
||||||
|
#include "utilities/elfFile.hpp"
|
||||||
|
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
|
|
||||||
@ -50,3 +51,38 @@ bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the elf file is marked NOT to require an executable stack,
|
||||||
|
// or if the file could not be opened.
|
||||||
|
// Returns false if the elf file requires an executable stack, the stack flag
|
||||||
|
// is not set at all, or if the file can not be read.
|
||||||
|
bool ElfFile::specifies_noexecstack(const char* filepath) {
|
||||||
|
if (filepath == NULL) return true;
|
||||||
|
|
||||||
|
FILE* file = fopen(filepath, "r");
|
||||||
|
if (file == NULL) return true;
|
||||||
|
|
||||||
|
// AARCH64 defaults to noexecstack. All others default to execstack.
|
||||||
|
bool result = AARCH64_ONLY(true) NOT_AARCH64(false);
|
||||||
|
|
||||||
|
// Read file header
|
||||||
|
Elf_Ehdr head;
|
||||||
|
if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
|
||||||
|
is_elf_file(head) &&
|
||||||
|
fseek(file, head.e_phoff, SEEK_SET) == 0) {
|
||||||
|
|
||||||
|
// Read program header table
|
||||||
|
Elf_Phdr phdr;
|
||||||
|
for (int index = 0; index < head.e_phnum; index ++) {
|
||||||
|
if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (phdr.p_type == PT_GNU_STACK) {
|
||||||
|
result = (phdr.p_flags == (PF_R | PF_W));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
LOG_TAG(cset) \
|
LOG_TAG(cset) \
|
||||||
LOG_TAG(data) \
|
LOG_TAG(data) \
|
||||||
LOG_TAG(datacreation) \
|
LOG_TAG(datacreation) \
|
||||||
|
LOG_TAG(decoder) \
|
||||||
LOG_TAG(defaultmethods) \
|
LOG_TAG(defaultmethods) \
|
||||||
LOG_TAG(dump) \
|
LOG_TAG(dump) \
|
||||||
LOG_TAG(ergo) \
|
LOG_TAG(ergo) \
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "utilities/align.hpp"
|
#include "utilities/align.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
#include "utilities/exceptions.hpp"
|
#include "utilities/exceptions.hpp"
|
||||||
|
#include "utilities/elfFile.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
#include "prims/cdsoffsets.hpp"
|
#include "prims/cdsoffsets.hpp"
|
||||||
@ -1911,6 +1912,13 @@ WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
|
|||||||
os::print_os_info(tty);
|
os::print_os_info(tty);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
// Elf decoder
|
||||||
|
WB_ENTRY(void, WB_DisableElfSectionCache(JNIEnv* env))
|
||||||
|
#if !defined(_WINDOWS) && !defined(__APPLE__)
|
||||||
|
ElfFile::_do_not_cache_elf_section = true;
|
||||||
|
#endif
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
|
||||||
#define CC (char*)
|
#define CC (char*)
|
||||||
|
|
||||||
@ -2125,6 +2133,7 @@ static JNINativeMethod methods[] = {
|
|||||||
(void*)&WB_CheckLibSpecifiesNoexecstack},
|
(void*)&WB_CheckLibSpecifiesNoexecstack},
|
||||||
{CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
|
{CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
|
||||||
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
|
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
|
||||||
|
{CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -33,12 +33,10 @@
|
|||||||
|
|
||||||
class AbstractDecoder : public CHeapObj<mtInternal> {
|
class AbstractDecoder : public CHeapObj<mtInternal> {
|
||||||
public:
|
public:
|
||||||
virtual ~AbstractDecoder() {}
|
|
||||||
|
|
||||||
// status code for decoding native C frame
|
// status code for decoding native C frame
|
||||||
enum decoder_status {
|
enum decoder_status {
|
||||||
not_available = -10, // real decoder is not available
|
not_available = -10, // real decoder is not available
|
||||||
no_error = 0, // successfully decoded frames
|
no_error = 0, // no error encountered
|
||||||
out_of_memory, // out of memory
|
out_of_memory, // out of memory
|
||||||
file_invalid, // invalid elf file
|
file_invalid, // invalid elf file
|
||||||
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
|
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
|
||||||
@ -46,6 +44,12 @@ public:
|
|||||||
helper_init_error // SymInitialize failed (Windows only)
|
helper_init_error // SymInitialize failed (Windows only)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
decoder_status _decoder_status;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~AbstractDecoder() {}
|
||||||
|
|
||||||
// decode an pc address to corresponding function name and an offset from the beginning of
|
// decode an pc address to corresponding function name and an offset from the beginning of
|
||||||
// the function
|
// the function
|
||||||
//
|
//
|
||||||
@ -68,11 +72,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool is_error(decoder_status status) {
|
static bool is_error(decoder_status status) {
|
||||||
return (status > 0);
|
return (status > no_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
decoder_status _decoder_status;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Do nothing decoder
|
// Do nothing decoder
|
||||||
@ -96,10 +97,8 @@ public:
|
|||||||
virtual bool demangle(const char* symbol, char* buf, int buflen) {
|
virtual bool demangle(const char* symbol, char* buf, int buflen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Decoder : AllStatic {
|
class Decoder : AllStatic {
|
||||||
public:
|
public:
|
||||||
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
|
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,60 +31,150 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder.hpp"
|
||||||
#include "utilities/elfFile.hpp"
|
#include "utilities/elfFile.hpp"
|
||||||
#include "utilities/elfFuncDescTable.hpp"
|
#include "utilities/elfFuncDescTable.hpp"
|
||||||
#include "utilities/elfStringTable.hpp"
|
#include "utilities/elfStringTable.hpp"
|
||||||
#include "utilities/elfSymbolTable.hpp"
|
#include "utilities/elfSymbolTable.hpp"
|
||||||
|
#include "utilities/ostream.hpp"
|
||||||
|
|
||||||
|
// For test only, disable elf section cache and force to read from file directly.
|
||||||
|
bool ElfFile::_do_not_cache_elf_section = false;
|
||||||
|
|
||||||
ElfFile::ElfFile(const char* filepath) {
|
ElfSection::ElfSection(FILE* fd, const Elf_Shdr& hdr) : _section_data(NULL) {
|
||||||
assert(filepath, "null file path");
|
_stat = load_section(fd, hdr);
|
||||||
memset(&m_elfHdr, 0, sizeof(m_elfHdr));
|
}
|
||||||
m_string_tables = NULL;
|
|
||||||
m_symbol_tables = NULL;
|
ElfSection::~ElfSection() {
|
||||||
m_funcDesc_table = NULL;
|
if (_section_data != NULL) {
|
||||||
m_next = NULL;
|
os::free(_section_data);
|
||||||
m_status = NullDecoder::no_error;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NullDecoder::decoder_status ElfSection::load_section(FILE* const fd, const Elf_Shdr& shdr) {
|
||||||
|
memcpy((void*)&_section_hdr, (const void*)&shdr, sizeof(shdr));
|
||||||
|
|
||||||
|
if (ElfFile::_do_not_cache_elf_section) {
|
||||||
|
log_debug(decoder)("Elf section cache is disabled");
|
||||||
|
return NullDecoder::no_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
_section_data = os::malloc(shdr.sh_size, mtInternal);
|
||||||
|
// No enough memory for caching. It is okay, we can try to read from
|
||||||
|
// file instead.
|
||||||
|
if (_section_data == NULL) return NullDecoder::no_error;
|
||||||
|
|
||||||
|
MarkedFileReader mfd(fd);
|
||||||
|
if (mfd.has_mark() &&
|
||||||
|
mfd.set_position(shdr.sh_offset) &&
|
||||||
|
mfd.read(_section_data, shdr.sh_size)) {
|
||||||
|
return NullDecoder::no_error;
|
||||||
|
} else {
|
||||||
|
os::free(_section_data);
|
||||||
|
_section_data = NULL;
|
||||||
|
return NullDecoder::file_invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileReader::read(void* buf, size_t size) {
|
||||||
|
assert(buf != NULL, "no buffer");
|
||||||
|
assert(size > 0, "no space");
|
||||||
|
return fread(buf, size, 1, _fd) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileReader::read_buffer(void* buf, size_t size) {
|
||||||
|
assert(buf != NULL, "no buffer");
|
||||||
|
assert(size > 0, "no space");
|
||||||
|
return fread(buf, 1, size, _fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileReader::set_position(long offset) {
|
||||||
|
return fseek(_fd, offset, SEEK_SET) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkedFileReader::MarkedFileReader(FILE* fd) : FileReader(fd) {
|
||||||
|
_marked_pos = ftell(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkedFileReader::~MarkedFileReader() {
|
||||||
|
if (_marked_pos != -1) {
|
||||||
|
set_position(_marked_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfFile::ElfFile(const char* filepath) :
|
||||||
|
_string_tables(NULL), _symbol_tables(NULL), _funcDesc_table(NULL),
|
||||||
|
_next(NULL), _status(NullDecoder::no_error),
|
||||||
|
_shdr_string_table(NULL), _file(NULL), _filepath(NULL) {
|
||||||
|
memset(&_elfHdr, 0, sizeof(_elfHdr));
|
||||||
|
|
||||||
int len = strlen(filepath) + 1;
|
int len = strlen(filepath) + 1;
|
||||||
m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);
|
_filepath = (char*)os::malloc(len * sizeof(char), mtInternal);
|
||||||
if (m_filepath != NULL) {
|
if (_filepath == NULL) {
|
||||||
strcpy((char*)m_filepath, filepath);
|
_status = NullDecoder::out_of_memory;
|
||||||
m_file = fopen(filepath, "r");
|
return;
|
||||||
if (m_file != NULL) {
|
}
|
||||||
load_tables();
|
strcpy(_filepath, filepath);
|
||||||
} else {
|
|
||||||
m_status = NullDecoder::file_not_found;
|
_status = parse_elf(filepath);
|
||||||
}
|
|
||||||
} else {
|
// we no longer need section header string table
|
||||||
m_status = NullDecoder::out_of_memory;
|
if (_shdr_string_table != NULL) {
|
||||||
|
delete _shdr_string_table;
|
||||||
|
_shdr_string_table = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfFile::~ElfFile() {
|
ElfFile::~ElfFile() {
|
||||||
if (m_string_tables != NULL) {
|
if (_shdr_string_table != NULL) {
|
||||||
delete m_string_tables;
|
delete _shdr_string_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_symbol_tables != NULL) {
|
cleanup_tables();
|
||||||
delete m_symbol_tables;
|
|
||||||
|
if (_file != NULL) {
|
||||||
|
fclose(_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_file != NULL) {
|
if (_filepath != NULL) {
|
||||||
fclose(m_file);
|
os::free((void*)_filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_filepath != NULL) {
|
if (_next != NULL) {
|
||||||
os::free((void*)m_filepath);
|
delete _next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElfFile::cleanup_tables() {
|
||||||
|
if (_string_tables != NULL) {
|
||||||
|
delete _string_tables;
|
||||||
|
_string_tables = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_next != NULL) {
|
if (_symbol_tables != NULL) {
|
||||||
delete m_next;
|
delete _symbol_tables;
|
||||||
|
_symbol_tables = NULL;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
if (_funcDesc_table != NULL) {
|
||||||
|
delete _funcDesc_table;
|
||||||
|
_funcDesc_table = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NullDecoder::decoder_status ElfFile::parse_elf(const char* filepath) {
|
||||||
|
assert(filepath, "null file path");
|
||||||
|
|
||||||
|
_file = fopen(filepath, "r");
|
||||||
|
if (_file != NULL) {
|
||||||
|
return load_tables();
|
||||||
|
} else {
|
||||||
|
return NullDecoder::file_not_found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Check elf header to ensure the file is valid.
|
//Check elf header to ensure the file is valid.
|
||||||
bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
|
bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
|
||||||
@ -96,116 +186,134 @@ bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
|
|||||||
ELFDATANONE != hdr.e_ident[EI_DATA]);
|
ELFDATANONE != hdr.e_ident[EI_DATA]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElfFile::load_tables() {
|
NullDecoder::decoder_status ElfFile::load_tables() {
|
||||||
assert(m_file, "file not open");
|
assert(_file, "file not open");
|
||||||
assert(!NullDecoder::is_error(m_status), "already in error");
|
assert(!NullDecoder::is_error(_status), "already in error");
|
||||||
|
|
||||||
|
FileReader freader(fd());
|
||||||
// read elf file header
|
// read elf file header
|
||||||
if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
|
if (!freader.read(&_elfHdr, sizeof(_elfHdr))) {
|
||||||
m_status = NullDecoder::file_invalid;
|
return NullDecoder::file_invalid;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_elf_file(m_elfHdr)) {
|
// Check signature
|
||||||
m_status = NullDecoder::file_invalid;
|
if (!is_elf_file(_elfHdr)) {
|
||||||
return false;
|
return NullDecoder::file_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk elf file's section headers, and load string tables
|
// walk elf file's section headers, and load string tables
|
||||||
Elf_Shdr shdr;
|
Elf_Shdr shdr;
|
||||||
if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
|
if (!freader.set_position(_elfHdr.e_shoff)) {
|
||||||
if (NullDecoder::is_error(m_status)) return false;
|
return NullDecoder::file_invalid;
|
||||||
|
|
||||||
for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
|
|
||||||
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
} 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;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
add_symbol_table(table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(PPC64) && !defined(ABI_ELFv2)
|
|
||||||
// Now read the .opd section wich contains the PPC64 function descriptor table.
|
|
||||||
// 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;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
|
|
||||||
if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {
|
|
||||||
ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);
|
|
||||||
if (string_table == NULL) {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
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, index);
|
|
||||||
if (m_funcDesc_table == NULL) {
|
|
||||||
m_status = NullDecoder::out_of_memory;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
for (int index = 0; index < _elfHdr.e_shnum; index ++) {
|
||||||
|
if (!freader.read(&shdr, sizeof(shdr))) {
|
||||||
|
return NullDecoder::file_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shdr.sh_type == SHT_STRTAB) {
|
||||||
|
// string tables
|
||||||
|
ElfStringTable* table = new (std::nothrow) ElfStringTable(fd(), shdr, index);
|
||||||
|
if (table == NULL) {
|
||||||
|
return NullDecoder::out_of_memory;
|
||||||
|
}
|
||||||
|
if (index == _elfHdr.e_shstrndx) {
|
||||||
|
assert(_shdr_string_table == NULL, "Only set once");
|
||||||
|
_shdr_string_table = table;
|
||||||
|
} else {
|
||||||
|
add_string_table(table);
|
||||||
|
}
|
||||||
|
} else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
|
||||||
|
// symbol tables
|
||||||
|
ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(fd(), shdr);
|
||||||
|
if (table == NULL) {
|
||||||
|
return NullDecoder::out_of_memory;
|
||||||
|
}
|
||||||
|
add_symbol_table(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(PPC64) && !defined(ABI_ELFv2)
|
||||||
|
// Now read the .opd section wich contains the PPC64 function descriptor table.
|
||||||
|
// 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
|
||||||
|
int sect_index = section_by_name(".opd", shdr);
|
||||||
|
|
||||||
|
if (sect_index == -1) {
|
||||||
|
return NullDecoder::file_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
_funcDesc_table = new (std::nothrow) ElfFuncDescTable(_file, shdr, sect_index);
|
||||||
|
if (_funcDesc_table == NULL) {
|
||||||
|
return NullDecoder::out_of_memory;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return NullDecoder::no_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ElfFile::section_by_name(const char* name, Elf_Shdr& hdr) {
|
||||||
|
assert(name != NULL, "No section name");
|
||||||
|
size_t len = strlen(name) + 1;
|
||||||
|
ResourceMark rm;
|
||||||
|
char* buf = NEW_RESOURCE_ARRAY(char, len);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_shdr_string_table != NULL, "Section header string table should be loaded");
|
||||||
|
ElfStringTable* const table = _shdr_string_table;
|
||||||
|
MarkedFileReader mfd(fd());
|
||||||
|
if (!mfd.has_mark() || !mfd.set_position(_elfHdr.e_shoff)) return -1;
|
||||||
|
|
||||||
|
int sect_index = -1;
|
||||||
|
for (int index = 0; index < _elfHdr.e_shnum; index ++) {
|
||||||
|
if (!mfd.read((void*)&hdr, sizeof(hdr))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (table->string_at(hdr.sh_name, buf, len)) {
|
||||||
|
if (strncmp(buf, name, len) == 0) {
|
||||||
|
sect_index = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sect_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
||||||
// something already went wrong, just give up
|
// something already went wrong, just give up
|
||||||
if (NullDecoder::is_error(m_status)) {
|
if (NullDecoder::is_error(_status)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ElfSymbolTable* symbol_table = m_symbol_tables;
|
|
||||||
int string_table_index;
|
int string_table_index;
|
||||||
int pos_in_string_table;
|
int pos_in_string_table;
|
||||||
int off = INT_MAX;
|
int off = INT_MAX;
|
||||||
bool found_symbol = false;
|
bool found_symbol = false;
|
||||||
|
ElfSymbolTable* symbol_table = _symbol_tables;
|
||||||
|
|
||||||
while (symbol_table != NULL) {
|
while (symbol_table != NULL) {
|
||||||
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
|
if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, _funcDesc_table)) {
|
||||||
found_symbol = true;
|
found_symbol = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
symbol_table = symbol_table->m_next;
|
symbol_table = symbol_table->next();
|
||||||
|
}
|
||||||
|
if (!found_symbol) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (!found_symbol) return false;
|
|
||||||
|
|
||||||
ElfStringTable* string_table = get_string_table(string_table_index);
|
ElfStringTable* string_table = get_string_table(string_table_index);
|
||||||
|
|
||||||
if (string_table == NULL) {
|
if (string_table == NULL) {
|
||||||
m_status = NullDecoder::file_invalid;
|
_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (offset) *offset = off;
|
if (offset) *offset = off;
|
||||||
@ -213,74 +321,31 @@ bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
|
|||||||
return string_table->string_at(pos_in_string_table, buf, buflen);
|
return string_table->string_at(pos_in_string_table, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ElfFile::add_symbol_table(ElfSymbolTable* table) {
|
void ElfFile::add_symbol_table(ElfSymbolTable* table) {
|
||||||
if (m_symbol_tables == NULL) {
|
if (_symbol_tables == NULL) {
|
||||||
m_symbol_tables = table;
|
_symbol_tables = table;
|
||||||
} else {
|
} else {
|
||||||
table->m_next = m_symbol_tables;
|
table->set_next(_symbol_tables);
|
||||||
m_symbol_tables = table;
|
_symbol_tables = table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfFile::add_string_table(ElfStringTable* table) {
|
void ElfFile::add_string_table(ElfStringTable* table) {
|
||||||
if (m_string_tables == NULL) {
|
if (_string_tables == NULL) {
|
||||||
m_string_tables = table;
|
_string_tables = table;
|
||||||
} else {
|
} else {
|
||||||
table->m_next = m_string_tables;
|
table->set_next(_string_tables);
|
||||||
m_string_tables = table;
|
_string_tables = table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfStringTable* ElfFile::get_string_table(int index) {
|
ElfStringTable* ElfFile::get_string_table(int index) {
|
||||||
ElfStringTable* p = m_string_tables;
|
ElfStringTable* p = _string_tables;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
if (p->index() == index) return p;
|
if (p->index() == index) return p;
|
||||||
p = p->m_next;
|
p = p->next();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LINUX
|
|
||||||
bool ElfFile::specifies_noexecstack(const char* filepath) {
|
|
||||||
// Returns true if the elf file is marked NOT to require an executable stack,
|
|
||||||
// or if the file could not be opened.
|
|
||||||
// Returns false if the elf file requires an executable stack, the stack flag
|
|
||||||
// is not set at all, or if the file can not be read.
|
|
||||||
if (filepath == NULL) return true;
|
|
||||||
|
|
||||||
FILE* file = fopen(filepath, "r");
|
|
||||||
if (file == NULL) return true;
|
|
||||||
|
|
||||||
// AARCH64 defaults to noexecstack. All others default to execstack.
|
|
||||||
#ifdef AARCH64
|
|
||||||
bool result = true;
|
|
||||||
#else
|
|
||||||
bool result = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read file header
|
|
||||||
Elf_Ehdr head;
|
|
||||||
if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
|
|
||||||
is_elf_file(head) &&
|
|
||||||
fseek(file, head.e_phoff, SEEK_SET) == 0) {
|
|
||||||
|
|
||||||
// Read program header table
|
|
||||||
Elf_Phdr phdr;
|
|
||||||
for (int index = 0; index < head.e_phnum; index ++) {
|
|
||||||
if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (phdr.p_type == PT_GNU_STACK) {
|
|
||||||
result = (phdr.p_flags == (PF_R | PF_W));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(file);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif // LINUX
|
|
||||||
|
|
||||||
#endif // !_WINDOWS && !__APPLE__
|
#endif // !_WINDOWS && !__APPLE__
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -57,7 +57,6 @@ typedef Elf32_Word Elf_Word;
|
|||||||
typedef Elf32_Off Elf_Off;
|
typedef Elf32_Off Elf_Off;
|
||||||
typedef Elf32_Addr Elf_Addr;
|
typedef Elf32_Addr Elf_Addr;
|
||||||
|
|
||||||
|
|
||||||
typedef Elf32_Ehdr Elf_Ehdr;
|
typedef Elf32_Ehdr Elf_Ehdr;
|
||||||
typedef Elf32_Shdr Elf_Shdr;
|
typedef Elf32_Shdr Elf_Shdr;
|
||||||
typedef Elf32_Phdr Elf_Phdr;
|
typedef Elf32_Phdr Elf_Phdr;
|
||||||
@ -72,46 +71,126 @@ typedef Elf32_Sym Elf_Sym;
|
|||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "utilities/decoder.hpp"
|
#include "utilities/decoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
class ElfStringTable;
|
class ElfStringTable;
|
||||||
class ElfSymbolTable;
|
class ElfSymbolTable;
|
||||||
class ElfFuncDescTable;
|
class ElfFuncDescTable;
|
||||||
|
|
||||||
|
// ELF section, may or may not have cached data
|
||||||
|
class ElfSection VALUE_OBJ_CLASS_SPEC {
|
||||||
|
private:
|
||||||
|
Elf_Shdr _section_hdr;
|
||||||
|
void* _section_data;
|
||||||
|
NullDecoder::decoder_status _stat;
|
||||||
|
public:
|
||||||
|
ElfSection(FILE* fd, const Elf_Shdr& hdr);
|
||||||
|
~ElfSection();
|
||||||
|
|
||||||
|
NullDecoder::decoder_status status() const { return _stat; }
|
||||||
|
|
||||||
|
const Elf_Shdr* section_header() const { return &_section_hdr; }
|
||||||
|
const void* section_data() const { return (const void*)_section_data; }
|
||||||
|
private:
|
||||||
|
// load this section.
|
||||||
|
// it return no_error, when it fails to cache the section data due to lack of memory
|
||||||
|
NullDecoder::decoder_status load_section(FILE* const file, const Elf_Shdr& hdr);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileReader : public StackObj {
|
||||||
|
protected:
|
||||||
|
FILE* const _fd;
|
||||||
|
public:
|
||||||
|
FileReader(FILE* const fd) : _fd(fd) {};
|
||||||
|
bool read(void* buf, size_t size);
|
||||||
|
int read_buffer(void* buf, size_t size);
|
||||||
|
bool set_position(long offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mark current position, so we can get back to it after
|
||||||
|
// reads.
|
||||||
|
class MarkedFileReader : public FileReader {
|
||||||
|
private:
|
||||||
|
long _marked_pos;
|
||||||
|
public:
|
||||||
|
MarkedFileReader(FILE* const fd);
|
||||||
|
~MarkedFileReader();
|
||||||
|
|
||||||
|
bool has_mark() const { return _marked_pos >= 0; }
|
||||||
|
};
|
||||||
|
|
||||||
// On Solaris/Linux platforms, libjvm.so does contain all private symbols.
|
|
||||||
// ElfFile is basically an elf file parser, which can lookup the symbol
|
// ElfFile is basically an elf file parser, which can lookup the symbol
|
||||||
// that is the nearest to the given address.
|
// that is the nearest to the given address.
|
||||||
// Beware, this code is called from vm error reporting code, when vm is already
|
// Beware, this code is called from vm error reporting code, when vm is already
|
||||||
// in "error" state, so there are scenarios, lookup will fail. We want this
|
// in "error" state, so there are scenarios, lookup will fail. We want this
|
||||||
// part of code to be very defensive, and bait out if anything went wrong.
|
// part of code to be very defensive, and bait out if anything went wrong.
|
||||||
|
|
||||||
class ElfFile: public CHeapObj<mtInternal> {
|
class ElfFile: public CHeapObj<mtInternal> {
|
||||||
friend class ElfDecoder;
|
friend class ElfDecoder;
|
||||||
public:
|
|
||||||
|
private:
|
||||||
|
// link ElfFiles
|
||||||
|
ElfFile* _next;
|
||||||
|
|
||||||
|
// Elf file
|
||||||
|
char* _filepath;
|
||||||
|
FILE* _file;
|
||||||
|
|
||||||
|
// Elf header
|
||||||
|
Elf_Ehdr _elfHdr;
|
||||||
|
|
||||||
|
// symbol tables
|
||||||
|
ElfSymbolTable* _symbol_tables;
|
||||||
|
|
||||||
|
// regular string tables
|
||||||
|
ElfStringTable* _string_tables;
|
||||||
|
|
||||||
|
// section header string table, used for finding section name
|
||||||
|
ElfStringTable* _shdr_string_table;
|
||||||
|
|
||||||
|
// function descriptors table
|
||||||
|
ElfFuncDescTable* _funcDesc_table;
|
||||||
|
|
||||||
|
NullDecoder::decoder_status _status;
|
||||||
|
|
||||||
|
public:
|
||||||
ElfFile(const char* filepath);
|
ElfFile(const char* filepath);
|
||||||
~ElfFile();
|
~ElfFile();
|
||||||
|
|
||||||
bool decode(address addr, char* buf, int buflen, int* offset);
|
bool decode(address addr, char* buf, int buflen, int* offset);
|
||||||
const char* filepath() {
|
|
||||||
return m_filepath;
|
const char* filepath() const {
|
||||||
|
return _filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool same_elf_file(const char* filepath) {
|
bool same_elf_file(const char* filepath) const {
|
||||||
assert(filepath, "null file path");
|
assert(filepath != NULL, "null file path");
|
||||||
assert(m_filepath, "already out of memory");
|
return (_filepath != NULL && !strcmp(filepath, _filepath));
|
||||||
return (m_filepath && !strcmp(filepath, m_filepath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NullDecoder::decoder_status get_status() {
|
NullDecoder::decoder_status get_status() const {
|
||||||
return m_status;
|
return _status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// Returns true if the elf file is marked NOT to require an executable stack,
|
||||||
|
// or if the file could not be opened.
|
||||||
|
// Returns false if the elf file requires an executable stack, the stack flag
|
||||||
|
// is not set at all, or if the file can not be read.
|
||||||
|
// On systems other than linux it always returns false.
|
||||||
|
static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
|
||||||
|
private:
|
||||||
// sanity check, if the file is a real elf file
|
// sanity check, if the file is a real elf file
|
||||||
static bool is_elf_file(Elf_Ehdr&);
|
static bool is_elf_file(Elf_Ehdr&);
|
||||||
|
|
||||||
// load string tables from the elf file
|
// parse this elf file
|
||||||
bool load_tables();
|
NullDecoder::decoder_status parse_elf(const char* filename);
|
||||||
|
|
||||||
|
// load string, symbol and function descriptor tables from the elf file
|
||||||
|
NullDecoder::decoder_status load_tables();
|
||||||
|
|
||||||
|
ElfFile* next() const { return _next; }
|
||||||
|
void set_next(ElfFile* file) { _next = file; }
|
||||||
|
|
||||||
|
// find a section by name, return section index
|
||||||
|
// if there is no such section, return -1
|
||||||
|
int section_by_name(const char* name, Elf_Shdr& hdr);
|
||||||
|
|
||||||
// string tables are stored in a linked list
|
// string tables are stored in a linked list
|
||||||
void add_string_table(ElfStringTable* table);
|
void add_string_table(ElfStringTable* table);
|
||||||
@ -122,39 +201,15 @@ class ElfFile: public CHeapObj<mtInternal> {
|
|||||||
// return a string table at specified section index
|
// return a string table at specified section index
|
||||||
ElfStringTable* get_string_table(int index);
|
ElfStringTable* get_string_table(int index);
|
||||||
|
|
||||||
protected:
|
|
||||||
ElfFile* next() const { return m_next; }
|
|
||||||
void set_next(ElfFile* file) { m_next = file; }
|
|
||||||
|
|
||||||
public:
|
FILE* const fd() const { return _file; }
|
||||||
// Returns true if the elf file is marked NOT to require an executable stack,
|
|
||||||
// or if the file could not be opened.
|
|
||||||
// Returns false if the elf file requires an executable stack, the stack flag
|
|
||||||
// is not set at all, or if the file can not be read.
|
|
||||||
// On systems other than linux it always returns false.
|
|
||||||
static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
|
|
||||||
|
|
||||||
protected:
|
// Cleanup string, symbol and function descriptor tables
|
||||||
ElfFile* m_next;
|
void cleanup_tables();
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// file
|
// For whitebox test
|
||||||
const char* m_filepath;
|
static bool _do_not_cache_elf_section;
|
||||||
FILE* m_file;
|
|
||||||
|
|
||||||
// Elf header
|
|
||||||
Elf_Ehdr m_elfHdr;
|
|
||||||
|
|
||||||
// symbol tables
|
|
||||||
ElfSymbolTable* m_symbol_tables;
|
|
||||||
|
|
||||||
// string tables
|
|
||||||
ElfStringTable* m_string_tables;
|
|
||||||
|
|
||||||
// function descriptors table
|
|
||||||
ElfFuncDescTable* m_funcDesc_table;
|
|
||||||
|
|
||||||
NullDecoder::decoder_status m_status;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !_WINDOWS && !__APPLE__
|
#endif // !_WINDOWS && !__APPLE__
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -30,7 +30,8 @@
|
|||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "utilities/elfFuncDescTable.hpp"
|
#include "utilities/elfFuncDescTable.hpp"
|
||||||
|
|
||||||
ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) {
|
ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) :
|
||||||
|
_file(file), _index(index), _section(file, shdr) {
|
||||||
assert(file, "null file handle");
|
assert(file, "null file handle");
|
||||||
// The actual function address (i.e. function entry point) is always the
|
// 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):
|
// first value in the function descriptor (on IA64 and PPC64 they look as follows):
|
||||||
@ -39,62 +40,33 @@ ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) {
|
|||||||
// Unfortunately 'shdr.sh_entsize' doesn't always seem to contain this size (it's zero on PPC64) so we can't assert
|
// 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");
|
// assert(IA64_ONLY(2) PPC64_ONLY(3) * sizeof(address) == shdr.sh_entsize, "Size mismatch for '.opd' section entries");
|
||||||
|
|
||||||
m_funcDescs = NULL;
|
_status = _section.status();
|
||||||
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() {
|
ElfFuncDescTable::~ElfFuncDescTable() {
|
||||||
if (m_funcDescs != NULL) {
|
|
||||||
os::free(m_funcDescs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
address ElfFuncDescTable::lookup(Elf_Word index) {
|
address ElfFuncDescTable::lookup(Elf_Word index) {
|
||||||
if (NullDecoder::is_error(m_status)) {
|
if (NullDecoder::is_error(_status)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_funcDescs != NULL) {
|
address* func_descs = cached_func_descs();
|
||||||
if (m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size) {
|
const Elf_Shdr* shdr = _section.section_header();
|
||||||
// Notice that 'index' is a byte-offset into the function descriptor table.
|
if (!(shdr->sh_size > 0 && shdr->sh_addr <= index && index <= shdr->sh_addr + shdr->sh_size)) {
|
||||||
return m_funcDescs[(index - m_shdr.sh_addr) / sizeof(address)];
|
// don't put the whole decoder in error mode if we just tried a wrong index
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func_descs != NULL) {
|
||||||
|
return func_descs[(index - shdr->sh_addr) / sizeof(address)];
|
||||||
} else {
|
} else {
|
||||||
long cur_pos;
|
MarkedFileReader mfd(_file);
|
||||||
address addr;
|
address addr;
|
||||||
if (!(m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size)) {
|
if (!mfd.has_mark() ||
|
||||||
// don't put the whole decoder in error mode if we just tried a wrong index
|
!mfd.set_position(shdr->sh_offset + index - shdr->sh_addr) ||
|
||||||
return NULL;
|
!mfd.read((void*)&addr, sizeof(addr))) {
|
||||||
}
|
_status = NullDecoder::file_invalid;
|
||||||
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 NULL;
|
||||||
}
|
}
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -116,32 +116,31 @@ documentation.
|
|||||||
|
|
||||||
class ElfFuncDescTable: public CHeapObj<mtInternal> {
|
class ElfFuncDescTable: public CHeapObj<mtInternal> {
|
||||||
friend class ElfFile;
|
friend class ElfFile;
|
||||||
public:
|
private:
|
||||||
|
// holds the complete function descriptor section if
|
||||||
|
// we can allocate enough memory
|
||||||
|
ElfSection _section;
|
||||||
|
|
||||||
|
// file contains string table
|
||||||
|
FILE* const _file;
|
||||||
|
|
||||||
|
// The section index of this function descriptor (i.e. '.opd') section in the ELF file
|
||||||
|
const int _index;
|
||||||
|
|
||||||
|
NullDecoder::decoder_status _status;
|
||||||
|
public:
|
||||||
ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index);
|
ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index);
|
||||||
~ElfFuncDescTable();
|
~ElfFuncDescTable();
|
||||||
|
|
||||||
// return the function address for the function descriptor at 'index' or NULL on error
|
// return the function address for the function descriptor at 'index' or NULL on error
|
||||||
address lookup(Elf_Word index);
|
address lookup(Elf_Word index);
|
||||||
|
|
||||||
int get_index() { return m_index; };
|
int get_index() const { return _index; };
|
||||||
|
|
||||||
NullDecoder::decoder_status get_status() { return m_status; };
|
NullDecoder::decoder_status get_status() const { return _status; };
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// holds the complete function descriptor section if
|
address* cached_func_descs() const { return (address*)_section.section_data(); }
|
||||||
// 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 // !_WINDOWS && !__APPLE__
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -33,58 +33,44 @@
|
|||||||
|
|
||||||
// We will try to load whole string table into memory if we can.
|
// We will try to load whole string table into memory if we can.
|
||||||
// Otherwise, fallback to more expensive file operation.
|
// Otherwise, fallback to more expensive file operation.
|
||||||
ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
|
ElfStringTable::ElfStringTable(FILE* const file, Elf_Shdr& shdr, int index) :
|
||||||
assert(file, "null file handle");
|
_section(file, shdr), _index(index), _fd(file), _next(NULL) {
|
||||||
m_table = NULL;
|
_status = _section.status();
|
||||||
m_index = index;
|
|
||||||
m_next = NULL;
|
|
||||||
m_file = file;
|
|
||||||
m_status = NullDecoder::no_error;
|
|
||||||
|
|
||||||
// try to load the string table
|
|
||||||
long cur_offset = ftell(file);
|
|
||||||
m_table = (char*)os::malloc(sizeof(char) * shdr.sh_size, mtInternal);
|
|
||||||
if (m_table != NULL) {
|
|
||||||
// if there is an error, mark the error
|
|
||||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
|
||||||
fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
|
|
||||||
fseek(file, cur_offset, SEEK_SET)) {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
os::free((void*)m_table);
|
|
||||||
m_table = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfStringTable::~ElfStringTable() {
|
ElfStringTable::~ElfStringTable() {
|
||||||
if (m_table != NULL) {
|
if (_next != NULL) {
|
||||||
os::free((void*)m_table);
|
delete _next;
|
||||||
}
|
|
||||||
|
|
||||||
if (m_next != NULL) {
|
|
||||||
delete m_next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
|
bool ElfStringTable::string_at(size_t pos, char* buf, int buflen) {
|
||||||
if (NullDecoder::is_error(m_status)) {
|
if (NullDecoder::is_error(get_status())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_table != NULL) {
|
|
||||||
jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
|
assert(buflen > 0, "no buffer");
|
||||||
|
if (pos >= _section.section_header()->sh_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* data = (const char*)_section.section_data();
|
||||||
|
if (data != NULL) {
|
||||||
|
jio_snprintf(buf, buflen, "%s", data + pos);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else { // no cache data, read from file instead
|
||||||
long cur_pos = ftell(m_file);
|
const Elf_Shdr* const shdr = _section.section_header();
|
||||||
if (cur_pos == -1 ||
|
MarkedFileReader mfd(_fd);
|
||||||
fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
|
if (mfd.has_mark() &&
|
||||||
fread(buf, 1, buflen, m_file) <= 0 ||
|
mfd.set_position(shdr->sh_offset + pos) &&
|
||||||
fseek(m_file, cur_pos, SEEK_SET)) {
|
mfd.read((void*)buf, size_t(buflen))) {
|
||||||
m_status = NullDecoder::file_invalid;
|
buf[buflen - 1] = '\0';
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// put it in error state to avoid retry
|
||||||
|
_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -37,37 +37,36 @@
|
|||||||
// one blob. Otherwise, it will load string from file when requested.
|
// one blob. Otherwise, it will load string from file when requested.
|
||||||
class ElfStringTable: CHeapObj<mtInternal> {
|
class ElfStringTable: CHeapObj<mtInternal> {
|
||||||
friend class ElfFile;
|
friend class ElfFile;
|
||||||
public:
|
private:
|
||||||
ElfStringTable(FILE* file, Elf_Shdr shdr, int index);
|
ElfStringTable* _next;
|
||||||
|
int _index; // section index
|
||||||
|
ElfSection _section;
|
||||||
|
FILE* const _fd;
|
||||||
|
NullDecoder::decoder_status _status;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ElfStringTable(FILE* const file, Elf_Shdr& shdr, int index);
|
||||||
~ElfStringTable();
|
~ElfStringTable();
|
||||||
|
|
||||||
// section index
|
// section index
|
||||||
int index() { return m_index; };
|
int index() const { return _index; };
|
||||||
|
|
||||||
// get string at specified offset
|
// get string at specified offset
|
||||||
bool string_at(int offset, char* buf, int buflen);
|
bool string_at(size_t offset, char* buf, int buflen);
|
||||||
|
|
||||||
// get status code
|
// get status code
|
||||||
NullDecoder::decoder_status get_status() { return m_status; };
|
NullDecoder::decoder_status get_status() const {
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
ElfStringTable* m_next;
|
void set_next(ElfStringTable* next) {
|
||||||
|
_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
// section index
|
ElfStringTable* next() const {
|
||||||
int m_index;
|
return _next;
|
||||||
|
}
|
||||||
// holds complete string table if can
|
|
||||||
// allocate enough memory
|
|
||||||
const char* m_table;
|
|
||||||
|
|
||||||
// file contains string table
|
|
||||||
FILE* m_file;
|
|
||||||
|
|
||||||
// section header
|
|
||||||
Elf_Shdr m_shdr;
|
|
||||||
|
|
||||||
// error code
|
|
||||||
NullDecoder::decoder_status m_status;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !_WINDOWS && !__APPLE__
|
#endif // !_WINDOWS && !__APPLE__
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,48 +30,26 @@
|
|||||||
#include "utilities/elfFuncDescTable.hpp"
|
#include "utilities/elfFuncDescTable.hpp"
|
||||||
#include "utilities/elfSymbolTable.hpp"
|
#include "utilities/elfSymbolTable.hpp"
|
||||||
|
|
||||||
ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
|
ElfSymbolTable::ElfSymbolTable(FILE* const file, Elf_Shdr& shdr) :
|
||||||
assert(file, "null file handle");
|
_section(file, shdr), _fd(file), _next(NULL) {
|
||||||
m_symbols = NULL;
|
assert(file != NULL, "null file handle");
|
||||||
m_next = NULL;
|
_status = _section.status();
|
||||||
m_file = file;
|
|
||||||
m_status = NullDecoder::no_error;
|
|
||||||
|
|
||||||
// try to load the string table
|
if (_section.section_header()->sh_size % sizeof(Elf_Sym) != 0) {
|
||||||
long cur_offset = ftell(file);
|
_status = NullDecoder::file_invalid;
|
||||||
if (cur_offset != -1) {
|
|
||||||
// call malloc so we can back up if memory allocation fails.
|
|
||||||
m_symbols = (Elf_Sym*)os::malloc(shdr.sh_size, mtInternal);
|
|
||||||
if (m_symbols) {
|
|
||||||
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
|
|
||||||
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
|
|
||||||
fseek(file, cur_offset, SEEK_SET)) {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
os::free(m_symbols);
|
|
||||||
m_symbols = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!NullDecoder::is_error(m_status)) {
|
|
||||||
memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfSymbolTable::~ElfSymbolTable() {
|
ElfSymbolTable::~ElfSymbolTable() {
|
||||||
if (m_symbols != NULL) {
|
if (_next != NULL) {
|
||||||
os::free(m_symbols);
|
delete _next;
|
||||||
}
|
|
||||||
|
|
||||||
if (m_next != NULL) {
|
|
||||||
delete m_next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
|
bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
|
||||||
if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
|
if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
|
||||||
Elf_Word st_size = sym->st_size;
|
Elf_Word st_size = sym->st_size;
|
||||||
|
const Elf_Shdr* shdr = _section.section_header();
|
||||||
address sym_addr;
|
address sym_addr;
|
||||||
if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) {
|
if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) {
|
||||||
// We need to go another step trough the function descriptor table (currently PPC64 only)
|
// We need to go another step trough the function descriptor table (currently PPC64 only)
|
||||||
@ -82,7 +60,7 @@ bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableI
|
|||||||
if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
|
if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
|
||||||
*offset = (int)(addr - sym_addr);
|
*offset = (int)(addr - sym_addr);
|
||||||
*posIndex = sym->st_name;
|
*posIndex = sym->st_name;
|
||||||
*stringtableIndex = m_shdr.sh_link;
|
*stringtableIndex = shdr->sh_link;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,39 +72,39 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex,
|
|||||||
assert(posIndex, "null string table offset pointer");
|
assert(posIndex, "null string table offset pointer");
|
||||||
assert(offset, "null offset pointer");
|
assert(offset, "null offset pointer");
|
||||||
|
|
||||||
if (NullDecoder::is_error(m_status)) {
|
if (NullDecoder::is_error(get_status())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sym_size = sizeof(Elf_Sym);
|
size_t sym_size = sizeof(Elf_Sym);
|
||||||
assert((m_shdr.sh_size % sym_size) == 0, "check size");
|
int count = _section.section_header()->sh_size / sym_size;
|
||||||
int count = m_shdr.sh_size / sym_size;
|
Elf_Sym* symbols = (Elf_Sym*)_section.section_data();
|
||||||
if (m_symbols != NULL) {
|
|
||||||
|
if (symbols != NULL) {
|
||||||
for (int index = 0; index < count; index ++) {
|
for (int index = 0; index < count; index ++) {
|
||||||
if (compare(&m_symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
|
if (compare(&symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
long cur_pos;
|
MarkedFileReader mfd(_fd);
|
||||||
if ((cur_pos = ftell(m_file)) == -1 ||
|
|
||||||
fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
|
if (!mfd.has_mark() || !mfd.set_position(_section.section_header()->sh_offset)) {
|
||||||
m_status = NullDecoder::file_invalid;
|
_status = NullDecoder::file_invalid;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Elf_Sym sym;
|
Elf_Sym sym;
|
||||||
for (int index = 0; index < count; index ++) {
|
for (int index = 0; index < count; index ++) {
|
||||||
if (fread(&sym, sym_size, 1, m_file) == 1) {
|
if (!mfd.read((void*)&sym, sizeof(sym))) {
|
||||||
if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
|
_status = NullDecoder::file_invalid;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_status = NullDecoder::file_invalid;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fseek(m_file, cur_pos, SEEK_SET);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,29 +40,27 @@
|
|||||||
*/
|
*/
|
||||||
class ElfSymbolTable: public CHeapObj<mtInternal> {
|
class ElfSymbolTable: public CHeapObj<mtInternal> {
|
||||||
friend class ElfFile;
|
friend class ElfFile;
|
||||||
public:
|
private:
|
||||||
ElfSymbolTable(FILE* file, Elf_Shdr shdr);
|
ElfSymbolTable* _next;
|
||||||
|
|
||||||
|
// file contains string table
|
||||||
|
FILE* const _fd;
|
||||||
|
|
||||||
|
// corresponding section
|
||||||
|
ElfSection _section;
|
||||||
|
|
||||||
|
NullDecoder::decoder_status _status;
|
||||||
|
public:
|
||||||
|
ElfSymbolTable(FILE* const file, Elf_Shdr& shdr);
|
||||||
~ElfSymbolTable();
|
~ElfSymbolTable();
|
||||||
|
|
||||||
// search the symbol that is nearest to the specified address.
|
// search the symbol that is nearest to the specified address.
|
||||||
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
|
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
|
||||||
|
|
||||||
NullDecoder::decoder_status get_status() { return m_status; };
|
NullDecoder::decoder_status get_status() const { return _status; };
|
||||||
|
private:
|
||||||
protected:
|
ElfSymbolTable* next() const { return _next; }
|
||||||
ElfSymbolTable* m_next;
|
void set_next(ElfSymbolTable* next) { _next = next; }
|
||||||
|
|
||||||
// holds a complete symbol table section if
|
|
||||||
// can allocate enough memory
|
|
||||||
Elf_Sym* m_symbols;
|
|
||||||
|
|
||||||
// file contains string table
|
|
||||||
FILE* m_file;
|
|
||||||
|
|
||||||
// section header
|
|
||||||
Elf_Shdr m_shdr;
|
|
||||||
|
|
||||||
NullDecoder::decoder_status m_status;
|
|
||||||
|
|
||||||
bool compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
|
bool compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
|
||||||
};
|
};
|
||||||
|
57
test/hotspot/jtreg/runtime/ElfDecoder/TestElfDirectRead.java
Normal file
57
test/hotspot/jtreg/runtime/ElfDecoder/TestElfDirectRead.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8193373
|
||||||
|
* @summary Test reading ELF info direct from underlaying file
|
||||||
|
* @requires (os.family == "linux")
|
||||||
|
* @modules java.base/jdk.internal.misc
|
||||||
|
* @library /test/lib
|
||||||
|
* @build sun.hotspot.WhiteBox
|
||||||
|
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail TestElfDirectRead
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.test.lib.process.ProcessTools;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
import jdk.test.lib.JDKToolFinder;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class TestElfDirectRead {
|
||||||
|
public static void main(String args[]) throws Exception {
|
||||||
|
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
wb.disableElfSectionCache();
|
||||||
|
ProcessBuilder pb = new ProcessBuilder();
|
||||||
|
OutputAnalyzer output;
|
||||||
|
// Grab my own PID
|
||||||
|
String pid = Long.toString(ProcessTools.getProcessId());
|
||||||
|
|
||||||
|
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
|
||||||
|
output = new OutputAnalyzer(pb.start());
|
||||||
|
// This is a pre-populated stack frame, should always exist if can decode
|
||||||
|
output.shouldContain("MallocSiteTable::new_entry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -541,4 +541,6 @@ public class WhiteBox {
|
|||||||
public native boolean isContainerized();
|
public native boolean isContainerized();
|
||||||
public native void printOsInfo();
|
public native void printOsInfo();
|
||||||
|
|
||||||
|
// Decoder
|
||||||
|
public native void disableElfSectionCache();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user