/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*
*/
// no precompiled headers
#include "assembler_x86.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "mutex_linux.inline.hpp"
#include "nativeInst_x86.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/osThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "thread_linux.inline.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
// put OS-includes here
# include <pthread.h>
# include <signal.h>
# include <errno.h>
# include <dlfcn.h>
# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <sys/resource.h>
# include <pthread.h>
# include <pwd.h>
# include <poll.h>
# include <ucontext.h>
# include <fpu_control.h>
#ifdef AMD64
#else
#endif // AMD64
#ifdef SPARC_WORKS
register void *esp;
#else
#endif
}
// Must never look like an address returned by reserve_memory,
// even in its subfields (as defined by the CPU immediate fields,
// if the CPU splits constants across multiple instructions).
return (char*) -1;
}
// Nothing to do.
}
}
}
}
// For Forte Analyzer AsyncGetCallTrace profiling support - thread
// is currently interrupted by SIGPROF.
// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
// frames. Currently we don't do that on Linux, so it's the same as
// os::fetch_frame_from_context().
}
} else {
// construct empty ExtendedPC for return value checking
}
return epc;
}
}
// By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
// turned off by -fomit-frame-pointer,
}
#ifdef SPARC_WORKS
#else
#endif
}
// stack is not walkable
} else {
}
}
// Utility functions
// From IA32 System Programming Guide
enum {
};
extern "C" void Fetch32PFI () ;
extern "C" void Fetch32Resume () ;
#ifdef AMD64
extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ;
#endif // AMD64
extern "C" JNIEXPORT int
void* ucVoid,
int abort_if_unrecognized) {
SignalHandlerMark shm(t);
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// allow chained handler to go first
return true;
} else {
warning("Ignoring %s - see bugs 4229104 or 646499219",
}
return true;
}
}
if (t != NULL ){
if(t->is_Java_thread()) {
thread = (JavaThread*)t;
}
else if(t->is_VM_thread()){
}
}
}
/*
NOTE: does not seem to work on linux.
if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
// can't decode this kind of signal
info = NULL;
} else {
assert(sig == info->si_signo, "bad siginfo");
}
*/
// decide if this trap can be handled by a stub
//%note os_trap_1
return 1 ;
}
#ifdef AMD64
return 1 ;
}
#endif // AMD64
// Handle ALL stack overflow variations here
// check if fault address is within thread stack
// stack overflow
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
return 1;
}
// Fatal red zone violation. Disable the guard pages and fall through
// to handle_unexpected_exception way down below.
// This is a likely cause, but hard to verify. Let's just print
// it as a hint.
"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
// current thread was created by user code with MAP_GROWSDOWN flag
// and then attached to VM. See notes in os_linux.cpp.
return 1;
}
} else {
fatal("recursive segv. expanding stack.");
}
}
}
}
// Java thread running in Java code => find exception handler if any
// a fault inside compiled code, the interpreter, or a stub
// BugId 4454115: A read from a MappedByteBuffer can fault
// here if the underlying file has been truncated.
// Do not crash the VM in such a case.
}
}
else
#ifdef AMD64
stub =
pc,
#else
// HACK: si_code does not work on linux 2.2.12-20!!!
if (op == 0xDB) {
// FIST
// TODO: The encoding of D2I in i486.ad can cause an exception
// prior to the fist instruction if there was an invalid operation
// pending. We want to dismiss that exception. From the win_32
// side it also seems that if it really was the fist causing
// the exception that we do the d2i by hand with different
// rounding. Seems kind of weird.
// NOTE: that we take the exception at the NEXT floating point instruction.
return true;
} else if (op == 0xF7) {
// IDIV
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
} else {
// TODO: handle more cases if we are using other x86 instructions
// that can generate SIGFPE signal on linux.
fatal("please update this code.");
}
#endif // AMD64
// Determination of interpreter/vtable stub/compiled code null exception
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
}
thread->doing_unsafe_access()) {
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
// and the heap gets shrunk before the field access.
}
}
// Check to see if we caught the safepoint code in the
// process of write protecting the memory serialization page.
// It write enables the page immediately after protecting it
// so we can just return to retry the write.
// Block current thread until the memory serialize page permission restored.
return true;
}
}
#ifndef AMD64
// Execution protection violation
//
// This should be kept as the last step in the triage. We don't
// have a dedicated trap number for a no-execute fault, so be
// conservative and allow other handlers the first shot.
//
// Note: We don't test that info->si_code == SEGV_ACCERR here.
// this si_code is so generic that it is almost meaningless; and
// the si_code for this condition may change in the future.
// Furthermore, a false-positive should be harmless.
if (UnguardOnExecutionViolation > 0 &&
// Make sure the pc and the faulting address are sane.
//
// If an instruction spans a page boundary, and the page containing
// the beginning of the instruction is executable but the following
// page is not, the pc and the faulting address might be slightly
// different - we still want to unguard the 2nd page in this case.
//
// 15 bytes seems to be a (very) safe value for max instruction size.
bool pc_is_near_addr =
bool instr_spans_page_boundary =
// In conservative mode, don't unguard unless the address is in the VM
// Set memory to RWX and retry
os::MEM_PROT_RWX);
if (PrintMiscellaneous && Verbose) {
"at " INTPTR_FORMAT
}
// Set last_addr so if we fault again at the same address, we don't end
// up in an endless loop.
//
// There are two potential complications here. Two threads trapping at
// the same address at the same time could cause one of the threads to
// think it already unguarded, and abort the VM. Likely very rare.
//
// The other race involves two threads alternately trapping at
// different addresses and failing to unguard the page, resulting in
// an endless loop. This condition is probably even more unlikely than
// the first.
//
// Although both cases could be avoided by using locks or thread local
// last_addr, these solutions are unnecessary complication: this
// handler is a best-effort safety net, not a complete solution. It is
// disabled by default and should only be used as a workaround in case
// we missed any no-execute-unsafe VM code.
}
}
}
#endif // !AMD64
// save all thread context in case we need to restore it
return true;
}
// signal-chaining
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
}
// unmask current signal
}
#ifndef AMD64
// set fpu to 53 bit precision
set_fpu_control_word(0x27f);
#endif // !AMD64
}
#ifdef AMD64
return 0;
#else
int fpu_control;
return fpu_control & 0xffff;
#endif // AMD64
}
#ifndef AMD64
#endif // !AMD64
}
// Check that the linux kernel version is 2.4 or higher since earlier
// versions do not support SSE without patches.
#ifdef AMD64
return true;
#else
char *minor_string;
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
}
#endif
return result;
#endif // AMD64
}
#ifdef AMD64
// unused on amd64?
return true;
#else
if (bytes < 2 * G) {
return true;
}
}
#endif // AMD64
}
////////////////////////////////////////////////////////////////////////////////
// thread stack
#ifdef AMD64
// amd64: pthread on amd64 is always in floating stack mode
#else
#ifdef __GNUC__
#endif
// Test if pthread library can support variable thread stack size. LinuxThreads
// in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
// in floating stack mode and NPTL support variable stack size.
// NPTL, yes
return true;
} else {
// Note: We can't control default stack size when creating a thread.
// If we use non-default stack size (pthread_attr_setstacksize), both
// floating stack and non-floating stack LinuxThreads will return the
// same value. This makes it impossible to implement this function by
// detecting thread stack size directly.
//
// An alternative approach is to check %gs. Fixed-stack LinuxThreads
// do not use %gs, so its value is 0. Floating-stack LinuxThreads use
// %gs (either as LDT selector or GDT selector, depending on kernel)
// to access thread specific data.
//
// Note that %gs is a reserved glibc register since early 2001, so
// applications are not allowed to change its value (Ulrich Drepper from
// Redhat confirmed that all known offenders have been modified to use
// either %fs or TSD). In the worst case scenario, when VM is embedded in
// a native application that plays with %gs, we might see non-zero %gs
// even LinuxThreads is running in fixed stack mode. As the result, we'll
// return true and skip _thread_safety_check(), so we may not be able to
// detect stack-heap collisions. But otherwise it's harmless.
//
#ifdef __GNUC__
return (GET_GS() != 0);
#else
return false;
#endif
}
}
#endif // AMD64
// return default stack size for thr_type
// default stack size (compiler thread needs larger stack)
#ifdef AMD64
#else
#endif // AMD64
return s;
}
// Creating guard page is very expensive. Java thread has HotSpot
// guard page, only enable glibc guard page for non-Java threads.
}
// Java thread:
//
// Low memory addresses
// +------------------------+
// | |\ JavaThread created by VM does not have glibc
// | glibc guard page | - guard, attached Java thread usually has
// | |/ 1 page glibc guard.
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | HotSpot Guard Pages | - red and yellow pages
// | |/
// +------------------------+ JavaThread::stack_yellow_zone_base()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// Non-Java thread:
//
// Low memory addresses
// +------------------------+
// | |\
// | glibc guard page | - usually 1 page
// | |/
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
// | |\
// | Normal Stack | -
// | |/
// P2 +------------------------+ Thread::stack_base()
//
// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
// pthread_attr_getstack()
// initial thread needs special handling because pthread_getattr_np()
// may return bogus value.
} else {
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0) {
vm_exit_out_of_memory(0, "pthread_getattr_np");
} else {
}
}
fatal("Can not locate current stack attributes!");
}
}
}
}
// stack size includes normal stack and HotSpot guard pages
return size;
}
/////////////////////////////////////////////////////////////////////////////
// helper functions for fatal error handler
#ifdef AMD64
#else
#endif // AMD64
// Note: it may be unsafe to inspect memory near pc. For example, pc may
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
}
// this is horrendously verbose but the layout of the registers in the
// context does not match how we defined our abstract Register set, so
// we can't just iterate through the gregs area
// this is only for the "general purpose" registers
#ifdef AMD64
#else
#endif // AMD64
}
#ifndef AMD64
__asm__ volatile ( "fldcw (%0)" :
#endif // !AMD64
}
#ifndef PRODUCT
#ifdef AMD64
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
#endif
}
#endif