/* * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. 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. *
*/
// put OS-includes here # include <sys/types.h> # include <sys/mman.h> # 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 <sys/stat.h> # include <sys/time.h> # include <sys/utsname.h> # include <sys/socket.h> # include <sys/wait.h> # include <pwd.h> # include <poll.h> #ifndef __OpenBSD__ # include <ucontext.h> #endif
#if !defined(__APPLE__) && !defined(__NetBSD__) # include <pthread_np.h> #endif
char* os::non_memory_address_word() { // 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).
// the return value used in computation of Universe::non_oop_word(), which // is loaded by cpu/aarch64 by MacroAssembler::movptr(Register, uintptr_t) return (char*) 0xffffffffffff;
}
frame os::fetch_compiled_frame_from_context(constvoid* ucVoid) { const ucontext_t* uc = (const ucontext_t*)ucVoid; // In compiled code, the stack banging is performed before LR // has been saved in the frame. LR is live, and SP and FP // belong to the caller.
intptr_t* fp = os::Bsd::ucontext_get_fp(uc);
intptr_t* sp = os::Bsd::ucontext_get_sp(uc);
address pc = (address)(uc->context_lr
- NativeInstruction::instruction_size); return frame(sp, fp, pc);
}
// JVM compiled with -fno-omit-frame-pointer, so RFP is saved on the stack.
frame os::get_sender_for_C_frame(frame* fr) { return frame(fr->link(), fr->link(), fr->sender_pc());
}
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) { // Enable WXWrite: this function is called by the signal handler at arbitrary // point of execution.
ThreadWXEnable wx(WXWrite, thread);
// decide if this trap can be handled by a stub
address stub = NULL;
address pc = NULL;
//%note os_trap_1 if (info != NULL && uc != NULL && thread != NULL) {
pc = (address) os::Posix::ucontext_get_pc(uc);
// Handle ALL stack overflow variations here if (sig == SIGSEGV || sig == SIGBUS) {
address addr = (address) info->si_addr;
// Make sure the high order byte is sign extended, as it may be masked away by the hardware. if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) {
addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56));
}
// check if fault address is within thread stack if (thread->is_in_full_stack(addr)) { // stack overflow if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) { returntrue; // continue
}
}
}
// We test if stub is already set (by the stack overflow code // above) so it is not overwritten by the code that follows. This // check is not required on other platforms, because on other // platforms we check for SIGSEGV only or SIGBUS only, where here // we have to check for both SIGSEGV and SIGBUS. if (thread->thread_state() == _thread_in_Java && stub == NULL) { // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub
// Handle signal from NativeJump::patch_verified_entry(). if ((sig == SIGILL)
&& nativeInstruction_at(pc)->is_sigill_not_entrant()) { if (TraceTraps) {
tty->print_cr("trap: not_entrant");
}
stub = SharedRuntime::get_handle_wrong_method_stub();
} elseif ((sig == SIGSEGV || sig == SIGBUS) && SafepointMechanism::is_poll_address((address)info->si_addr)) {
stub = SharedRuntime::get_poll_stub(pc); #ifdefined(__APPLE__) // 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions. // 64-bit Darwin may also use a SIGBUS (seen with compressed oops). // Catching SIGBUS here prevents the implicit SIGBUS NULL check below from // being called, so only do so if the implicit NULL check is not necessary.
} elseif (sig == SIGBUS && !MacroAssembler::uses_implicit_null_check(info->si_addr)) { #else
} elseif (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { #endif // 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.
CodeBlob* cb = CodeCache::find_blob(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc)); if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) {
address next_pc = pc + NativeCall::instruction_size; if (is_unsafe_arraycopy) {
next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);
}
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
} elseif (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) { // Pull a pointer to the error message out of the instruction // stream. const uint64_t *detail_msg_ptr
= (uint64_t*)(pc + NativeInstruction::instruction_size); constchar *detail_msg = (constchar *)*detail_msg_ptr; constchar *msg = "stop"; if (TraceTraps) {
tty->print_cr("trap: %s: (SIGILL)", msg);
}
// End life with a fatal error, message and detail message and the context. // Note: no need to do any post-processing here (e.g. signal chaining)
report_and_die(thread, uc, NULL, 0, msg, "%s", detail_msg);
ShouldNotReachHere();
// 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. if ((sig == SIGSEGV) || (sig == SIGBUS)) {
address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) {
stub = addr;
}
}
}
if (stub != NULL) { // save all thread context in case we need to restore it if (thread != NULL) thread->set_saved_exception_pc(pc);
// 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.
address pc = os::Posix::ucontext_get_pc(uc);
print_instructions(st, pc, 4/*native instruction size*/);
st->cr();
}
st->print_cr("Register to memory mapping:");
st->cr();
// 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
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.