--- a/hotspot/agent/src/os/linux/ps_core.c Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/agent/src/os/linux/ps_core.c Fri Mar 08 17:14:22 2013 -0800
@@ -132,12 +132,12 @@
}
// Part of the class sharing workaround
-static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
+static void add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
uintptr_t vaddr, size_t memsz) {
map_info* map;
if ((map = allocate_init_map(ph->core->classes_jsa_fd,
offset, vaddr, memsz)) == NULL) {
- return NULL;
+ return;
}
map->next = ph->core->class_share_maps;
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -57,6 +57,7 @@
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
@@ -2275,13 +2276,25 @@
return NULL;
}
+ // The memory is committed
+ address pc = CALLER_PC;
+ MemTracker::record_virtual_memory_reserve((address)addr, bytes, pc);
+ MemTracker::record_virtual_memory_commit((address)addr, bytes, pc);
+
return addr;
}
bool os::release_memory_special(char* base, size_t bytes) {
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
- return rslt == 0;
+ if (rslt == 0) {
+ MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+ MemTracker::record_virtual_memory_release((address)base, bytes);
+ return true;
+ } else {
+ return false;
+ }
+
}
size_t os::large_page_size() {
--- a/hotspot/src/os/linux/vm/globals_linux.hpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/linux/vm/globals_linux.hpp Fri Mar 08 17:14:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -40,6 +40,9 @@
product(bool, UseHugeTLBFS, false, \
"Use MAP_HUGETLB for large pages") \
\
+ product(bool, LoadExecStackDllInVMThread, true, \
+ "Load DLLs with executable-stack attribute in the VM Thread") \
+ \
product(bool, UseSHM, false, \
"Use SYSV shared memory for large pages")
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -44,6 +44,7 @@
#include "runtime/extendedPC.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.hpp"
+#include "runtime/init.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
@@ -57,10 +58,12 @@
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
+#include "utilities/elfFile.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/vmError.hpp"
@@ -1796,9 +1799,93 @@
// in case of error it checks if .dll/.so was built for the
// same architecture as Hotspot is running on
+
+// Remember the stack's state. The Linux dynamic linker will change
+// the stack to 'executable' at most once, so we must safepoint only once.
+bool os::Linux::_stack_is_executable = false;
+
+// VM operation that loads a library. This is necessary if stack protection
+// of the Java stacks can be lost during loading the library. If we
+// do not stop the Java threads, they can stack overflow before the stacks
+// are protected again.
+class VM_LinuxDllLoad: public VM_Operation {
+ private:
+ const char *_filename;
+ void *_lib;
+ public:
+ VM_LinuxDllLoad(const char *fn) :
+ _filename(fn), _lib(NULL) {}
+ VMOp_Type type() const { return VMOp_LinuxDllLoad; }
+ void doit() {
+ _lib = os::Linux::dll_load_inner(_filename);
+ os::Linux::_stack_is_executable = true;
+ }
+ void* loaded_library() { return _lib; }
+};
+
void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
{
- void * result= ::dlopen(filename, RTLD_LAZY);
+ void * result = NULL;
+ bool load_attempted = false;
+
+ // Check whether the library to load might change execution rights
+ // of the stack. If they are changed, the protection of the stack
+ // guard pages will be lost. We need a safepoint to fix this.
+ //
+ // 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 (!is_init_completed()) {
+ os::Linux::_stack_is_executable = true;
+ // This is OK - No Java threads have been created yet, and hence no
+ // stack guard pages to fix.
+ //
+ // This should happen only when you are building JDK7 using a very
+ // old version of JDK6 (e.g., with JPRT) and running test_gamma.
+ //
+ // Dynamic loader will make all stacks executable after
+ // this function returns, and will not do that again.
+ assert(Threads::first() == NULL, "no Java threads should exist yet.");
+ } else {
+ warning("You have loaded library %s which might have disabled stack guard. "
+ "The VM will try to fix the stack guard now.\n"
+ "It's highly recommended that you fix the library with "
+ "'execstack -c <libfile>', or link it with '-z noexecstack'.",
+ filename);
+
+ assert(Thread::current()->is_Java_thread(), "must be Java thread");
+ JavaThread *jt = JavaThread::current();
+ if (jt->thread_state() != _thread_in_native) {
+ // This happens when a compiler thread tries to load a hsdis-<arch>.so file
+ // that requires ExecStack. Cannot enter safe point. Let's give up.
+ warning("Unable to fix stack guard. Giving up.");
+ } else {
+ if (!LoadExecStackDllInVMThread) {
+ // This is for the case where the DLL has an static
+ // constructor function that executes JNI code. We cannot
+ // load such DLLs in the VMThread.
+ result = ::dlopen(filename, RTLD_LAZY);
+ }
+
+ ThreadInVMfromNative tiv(jt);
+ debug_only(VMNativeEntryWrapper vew;)
+
+ VM_LinuxDllLoad op(filename);
+ VMThread::execute(&op);
+ if (LoadExecStackDllInVMThread) {
+ result = op.loaded_library();
+ }
+ load_attempted = true;
+ }
+ }
+ }
+ }
+
+ if (!load_attempted) {
+ result = ::dlopen(filename, RTLD_LAZY);
+ }
+
if (result != NULL) {
// Successful loading
return result;
@@ -1952,6 +2039,38 @@
return NULL;
}
+void * os::Linux::dll_load_inner(const char *filename) {
+ void * result = NULL;
+ if (LoadExecStackDllInVMThread) {
+ result = ::dlopen(filename, RTLD_LAZY);
+ }
+
+ // Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a
+ // library that requires an executable stack, or which does not have this
+ // stack attribute set, dlopen changes the stack attribute to executable. The
+ // read protection of the guard pages gets lost.
+ //
+ // Need to check _stack_is_executable again as multiple VM_LinuxDllLoad
+ // may have been queued at the same time.
+
+ if (!_stack_is_executable) {
+ JavaThread *jt = Threads::first();
+
+ while (jt) {
+ if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized
+ jt->stack_yellow_zone_enabled()) { // No pending stack overflow exceptions
+ if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(),
+ jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) {
+ warning("Attempt to reguard stack yellow zone failed.");
+ }
+ }
+ jt = jt->next();
+ }
+ }
+
+ return result;
+}
+
/*
* glibc-2.0 libdl is not MT safe. If you are building with any glibc,
* chances are you might want to run the generated bits against glibc-2.0
@@ -3094,13 +3213,24 @@
numa_make_global(addr, bytes);
}
+ // The memory is committed
+ address pc = CALLER_PC;
+ MemTracker::record_virtual_memory_reserve((address)addr, bytes, pc);
+ MemTracker::record_virtual_memory_commit((address)addr, bytes, pc);
+
return addr;
}
bool os::release_memory_special(char* base, size_t bytes) {
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
- return rslt == 0;
+ if (rslt == 0) {
+ MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+ MemTracker::record_virtual_memory_release((address)base, bytes);
+ return true;
+ } else {
+ return false;
+ }
}
size_t os::large_page_size() {
--- a/hotspot/src/os/linux/vm/os_linux.hpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.hpp Fri Mar 08 17:14:22 2013 -0800
@@ -94,6 +94,9 @@
static void print_libversion_info(outputStream* st);
public:
+ static bool _stack_is_executable;
+ static void *dll_load_inner(const char *name);
+
static void init_thread_fpu_state();
static int get_fpu_control_word();
static void set_fpu_control_word(int fpu_control);
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -3420,13 +3420,25 @@
if ((retAddr != NULL) && UseNUMAInterleaving) {
numa_make_global(retAddr, size);
}
+
+ // The memory is committed
+ address pc = CALLER_PC;
+ MemTracker::record_virtual_memory_reserve((address)retAddr, size, pc);
+ MemTracker::record_virtual_memory_commit((address)retAddr, size, pc);
+
return retAddr;
}
bool os::release_memory_special(char* base, size_t bytes) {
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
- return rslt == 0;
+ if (rslt == 0) {
+ MemTracker::record_virtual_memory_uncommit((address)base, bytes);
+ MemTracker::record_virtual_memory_release((address)base, bytes);
+ return true;
+ } else {
+ return false;
+ }
}
size_t os::large_page_size() {
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -60,6 +60,7 @@
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
@@ -2836,7 +2837,7 @@
PAGE_READWRITE);
// If reservation failed, return NULL
if (p_buf == NULL) return NULL;
-
+ MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
os::release_memory(p_buf, bytes + chunk_size);
// we still need to round up to a page boundary (in case we are using large pages)
@@ -2898,6 +2899,11 @@
if (next_alloc_addr > p_buf) {
// Some memory was committed so release it.
size_t bytes_to_release = bytes - bytes_remaining;
+ // NMT has yet to record any individual blocks, so it
+ // need to create a dummy 'reserve' record to match
+ // the release.
+ MemTracker::record_virtual_memory_reserve((address)p_buf,
+ bytes_to_release, CALLER_PC);
os::release_memory(p_buf, bytes_to_release);
}
#ifdef ASSERT
@@ -2909,10 +2915,19 @@
#endif
return NULL;
}
+
bytes_remaining -= bytes_to_rq;
next_alloc_addr += bytes_to_rq;
count++;
}
+ // Although the memory is allocated individually, it is returned as one.
+ // NMT records it as one block.
+ address pc = CALLER_PC;
+ MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, pc);
+ if ((flags & MEM_COMMIT) != 0) {
+ MemTracker::record_virtual_memory_commit((address)p_buf, bytes, pc);
+ }
+
// made it this far, success
return p_buf;
}
@@ -3099,11 +3114,20 @@
// normal policy just allocate it all at once
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot);
+ if (res != NULL) {
+ address pc = CALLER_PC;
+ MemTracker::record_virtual_memory_reserve((address)res, bytes, pc);
+ MemTracker::record_virtual_memory_commit((address)res, bytes, pc);
+ }
+
return res;
}
}
bool os::release_memory_special(char* base, size_t bytes) {
+ assert(base != NULL, "Sanity check");
+ // Memory allocated via reserve_memory_special() is committed
+ MemTracker::record_virtual_memory_uncommit((address)base, bytes);
return release_memory(base, bytes);
}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -410,6 +410,11 @@
// to handle_unexpected_exception way down below.
thread->disable_stack_red_zone();
tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+
+ // This is a likely cause, but hard to verify. Let's just print
+ // it as a hint.
+ tty->print_raw_cr("Please check if any of your loaded .so files has "
+ "enabled executable stack (see man page execstack(8))");
} else {
// Accessing stack address below sp may cause SEGV if current
// thread has MAP_GROWSDOWN stack. This should only happen when
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -305,6 +305,11 @@
// to handle_unexpected_exception way down below.
thread->disable_stack_red_zone();
tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
+
+ // This is a likely cause, but hard to verify. Let's just print
+ // it as a hint.
+ tty->print_raw_cr("Please check if any of your loaded .so files has "
+ "enabled executable stack (see man page execstack(8))");
} else {
// Accessing stack address below sp may cause SEGV if current
// thread has MAP_GROWSDOWN stack. This should only happen when
--- a/hotspot/src/share/vm/runtime/thread.hpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Mar 08 17:14:22 2013 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -1289,6 +1289,7 @@
void enable_stack_red_zone();
void disable_stack_red_zone();
+ inline bool stack_guard_zone_unused();
inline bool stack_yellow_zone_disabled();
inline bool stack_yellow_zone_enabled();
@@ -1759,6 +1760,10 @@
return (CompilerThread*)this;
}
+inline bool JavaThread::stack_guard_zone_unused() {
+ return _stack_guard_state == stack_guard_unused;
+}
+
inline bool JavaThread::stack_yellow_zone_disabled() {
return _stack_guard_state == stack_guard_yellow_disabled;
}
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Mar 08 17:14:22 2013 -0800
@@ -94,6 +94,7 @@
template(ReportJavaOutOfMemory) \
template(JFRCheckpoint) \
template(Exit) \
+ template(LinuxDllLoad) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
--- a/hotspot/src/share/vm/utilities/elfFile.cpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp Fri Mar 08 17:14:22 2013 -0800
@@ -197,4 +197,28 @@
return NULL;
}
+#ifdef LINUX
+bool ElfFile::specifies_noexecstack() {
+ Elf_Phdr phdr;
+ if (!m_file) 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;
+ }
+ if (phdr.p_type == PT_GNU_STACK) {
+ if (phdr.p_flags == (PF_R | PF_W)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+ return false;
+}
+#endif
+
#endif // _WINDOWS
--- a/hotspot/src/share/vm/utilities/elfFile.hpp Fri Mar 08 08:22:18 2013 -0800
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp Fri Mar 08 17:14:22 2013 -0800
@@ -43,6 +43,7 @@
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Phdr Elf_Phdr;
typedef Elf64_Sym Elf_Sym;
#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
@@ -59,6 +60,7 @@
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Phdr Elf_Phdr;
typedef Elf32_Sym Elf_Sym;
#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
@@ -123,6 +125,14 @@
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.
+ bool specifies_noexecstack() NOT_LINUX({ return false; });
+
protected:
ElfFile* m_next;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7107135/Test.java Fri Mar 08 17:14:22 2013 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG. 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.
+ */
+
+class Test {
+
+ static boolean loadLib(String libName){
+ try {
+ System.loadLibrary(libName);
+ System.out.println("Loaded library "+ libName + ".");
+ return true;
+ } catch (SecurityException e) {
+ System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+ } catch (UnsatisfiedLinkError e) {
+ System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+ }
+ return false;
+ }
+
+ public static int counter = 1;
+
+ static int Runner() {
+ counter = counter * -1;
+ int i = counter;
+ if(counter < 2) counter += Runner();
+ return i;
+ }
+
+ public static int run() {
+ try{
+ Runner();
+ } catch (StackOverflowError e) {
+ System.out.println("Caught stack overflow error.");
+ return 0;
+ } catch (OutOfMemoryError e) {
+ return 0;
+ }
+ return 2;
+ }
+
+ public static void main(String argv[]) {
+ loadLib(argv[0]);
+ System.exit(run());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7107135/Test7107135.sh Fri Mar 08 17:14:22 2013 -0800
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+#
+# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011 SAP AG. 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 Test7107135.sh
+## @bug 7107135
+## @summary Stack guard pages lost after loading library with executable stack.
+## @run shell Test7107135.sh
+##
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ echo "TESTJAVA not set, selecting " ${TESTJAVA}
+ echo "If this is incorrect, try setting the variable manually."
+fi
+
+BIT_FLAG=""
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ Linux)
+ NULL=/dev/null
+ PS=":"
+ FS="/"
+ ;;
+ *)
+ NULL=NUL
+ PS=";"
+ FS="\\"
+ echo "Test passed; only valid for Linux"
+ exit 0;
+ ;;
+esac
+
+ARCH=`uname -m`
+
+THIS_DIR=`pwd`
+
+cp ${TESTSRC}${FS}*.java ${THIS_DIR}
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+gcc -fPIC -shared -c -o test.o -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux ${TESTSRC}${FS}test.c
+ld -shared -z execstack -o libtest-rwx.so test.o
+ld -shared -z noexecstack -o libtest-rw.so test.o
+
+
+LD_LIBRARY_PATH=${THIS_DIR}
+echo LD_LIBRARY_PATH = ${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+# This should not fail.
+echo Check testprogram. Expected to pass:
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+
+echo
+echo Test changing of stack protection:
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rw
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} Test test-rwx
+
+if [ "$?" == "0" ]
+then
+ echo
+ echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx
+ ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} TestMT test-rwx
+fi
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7107135/TestMT.java Fri Mar 08 17:14:22 2013 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG. 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.
+ */
+
+class TestMT {
+
+ static boolean loadLib(String libName) {
+ try {
+ System.loadLibrary(libName);
+ System.out.println("Loaded library "+ libName + ".");
+ return true;
+ } catch (SecurityException e) {
+ System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+ } catch (UnsatisfiedLinkError e) {
+ System.out.println("loadLibrary(\"" + libName + "\") throws: " + e + "\n");
+ }
+ return false;
+ }
+
+ public static int counter = 1;
+ static int Runner() {
+ counter = counter * -1;
+ int i = counter;
+ if (counter < 2) counter += Runner();
+ return i;
+ }
+
+ public static int run(String msg) {
+ try {
+ Runner();
+ } catch (StackOverflowError e) {
+ System.out.println(msg + " caught stack overflow error.");
+ return 0;
+ } catch (OutOfMemoryError e) {
+ return 0;
+ }
+ return 2;
+ }
+
+ public static void main(String argv[]) {
+ try {
+ for (int i = 0; i < 20; i++) {
+ Thread t = new DoStackOverflow("SpawnedThread " + i);
+ t.start();
+ }
+ run("Main thread");
+ loadLib("test-rwx");
+ run("Main thread");
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ static class DoStackOverflow extends Thread {
+ public DoStackOverflow(String name) {
+ super(name);
+ }
+ public void run() {
+ for (int i = 0; i < 10; ++i) {
+ TestMT.run(getName());
+ yield();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/7107135/test.c Fri Mar 08 17:14:22 2013 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002-2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 SAP AG. 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "jni.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jint JNICALL Java_Test_someMethod(JNIEnv *env, jobject mainObject) {
+ return 3;
+}
+
+#ifdef __cplusplus
+}
+#endif