8183262: noexecstack check in os::dll_load on Linux is too expensive
Summary: convert ElfFile::specifies_noexecstack() to static method which read file header and check executable stack flag.
Reviewed-by: iklam, stuefe
--- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 11:03:19 2017 -0700
@@ -1639,8 +1639,7 @@
//
// See Linux man page execstack(8) for more info.
if (os::uses_stack_guard_pages() && !os::Linux::_stack_is_executable) {
- ElfFile ef(filename);
- if (!ef.specifies_noexecstack()) {
+ if (!ElfFile::specifies_noexecstack(filename)) {
if (!is_init_completed()) {
os::Linux::_stack_is_executable = true;
// This is OK - No Java threads have been created yet, and hence no
--- a/hotspot/src/share/vm/aot/aotLoader.cpp Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/aot/aotLoader.cpp Wed Jul 05 11:03:19 2017 -0700
@@ -29,6 +29,7 @@
#include "oops/method.hpp"
#include "prims/jvm.h"
#include "runtime/os.hpp"
+#include "runtime/timerTrace.hpp"
GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, true);
GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, true);
@@ -112,6 +113,8 @@
};
void AOTLoader::initialize() {
+ TraceTime timer("AOT initialization", TRACETIME_LOG(Info, aot, startuptime));
+
if (FLAG_IS_DEFAULT(UseAOT) && AOTLibrary != NULL) {
// Don't need to set UseAOT on command line when AOTLibrary is specified
FLAG_SET_DEFAULT(UseAOT, true);
--- a/hotspot/src/share/vm/utilities/elfFile.cpp Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp Wed Jul 05 11:03:19 2017 -0700
@@ -242,32 +242,45 @@
}
#ifdef LINUX
-bool ElfFile::specifies_noexecstack() {
- Elf_Phdr phdr;
- if (!m_file) return true;
+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;
- if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) {
- for (int index = 0; index < m_elfHdr.e_phnum; index ++) {
- if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) {
- m_status = NullDecoder::file_invalid;
- return false;
+ // 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) {
- if (phdr.p_flags == (PF_R | PF_W)) {
- return true;
- } else {
- return false;
- }
+ result = (phdr.p_flags == (PF_R | PF_W));
+ break;
}
}
}
-// AARCH64 defaults to noexecstack. All others default to execstack.
-#ifdef AARCH64
- return true;
-#else
- return false;
-#endif
+ fclose(file);
+ return result;
}
-#endif
+#endif // LINUX
#endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/elfFile.hpp Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp Wed Jul 05 11:03:19 2017 -0700
@@ -108,7 +108,7 @@
private:
// sanity check, if the file is a real elf file
- bool is_elf_file(Elf_Ehdr&);
+ static bool is_elf_file(Elf_Ehdr&);
// load string tables from the elf file
bool load_tables();
@@ -132,7 +132,7 @@
// 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.
- bool specifies_noexecstack() NOT_LINUX({ return false; });
+ static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
protected:
ElfFile* m_next;