diff -r 66173ef5fbbf -r 2c35fd3c5789 src/hotspot/share/utilities/elfFile.hpp --- a/src/hotspot/share/utilities/elfFile.hpp Wed Feb 14 16:42:00 2018 +0100 +++ b/src/hotspot/share/utilities/elfFile.hpp Wed Feb 14 17:20:59 2018 -0500 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,6 @@ typedef Elf32_Off Elf_Off; typedef Elf32_Addr Elf_Addr; - typedef Elf32_Ehdr Elf_Ehdr; typedef Elf32_Shdr Elf_Shdr; typedef Elf32_Phdr Elf_Phdr; @@ -72,46 +71,126 @@ #include "memory/allocation.hpp" #include "utilities/decoder.hpp" - class ElfStringTable; class ElfSymbolTable; 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(); -// On Solaris/Linux platforms, libjvm.so does contain all private symbols. + 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; } +}; + // ElfFile is basically an elf file parser, which can lookup the symbol // that is the nearest to the given address. // 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 // part of code to be very defensive, and bait out if anything went wrong. - class ElfFile: public CHeapObj { 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(); 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) const { + assert(filepath != NULL, "null file path"); + return (_filepath != NULL && !strcmp(filepath, _filepath)); } - bool same_elf_file(const char* filepath) { - assert(filepath, "null file path"); - assert(m_filepath, "already out of memory"); - return (m_filepath && !strcmp(filepath, m_filepath)); + NullDecoder::decoder_status get_status() const { + return _status; } - NullDecoder::decoder_status get_status() { - return m_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 static bool is_elf_file(Elf_Ehdr&); - // load string tables from the elf file - bool load_tables(); + // parse this elf file + 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 void add_string_table(ElfStringTable* table); @@ -122,39 +201,15 @@ // return a string table at specified section index ElfStringTable* get_string_table(int index); -protected: - ElfFile* next() const { return m_next; } - void set_next(ElfFile* file) { m_next = file; } - public: - // 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: - ElfFile* m_next; + FILE* const fd() const { return _file; } - private: - // file - const char* m_filepath; - FILE* m_file; - - // Elf header - Elf_Ehdr m_elfHdr; + // Cleanup string, symbol and function descriptor tables + void cleanup_tables(); - // symbol tables - ElfSymbolTable* m_symbol_tables; - - // string tables - ElfStringTable* m_string_tables; - - // function descriptors table - ElfFuncDescTable* m_funcDesc_table; - - NullDecoder::decoder_status m_status; +public: + // For whitebox test + static bool _do_not_cache_elf_section; }; #endif // !_WINDOWS && !__APPLE__