/* * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * 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. *
*/
frame os::current_frame() { // The only thing that calls this is the stack printing code in // VMError::report: // - Step 110 (printing stack bounds) uses the sp in the frame // to determine the amount of free space on the stack. We // set the sp to a close approximation of the real value in // order to allow this step to complete. // - Step 120 (printing native stack) tries to walk the stack. // The frame we create has a NULL pc, which is ignored as an // invalid frame.
frame dummy = frame();
dummy.set_sp((intptr_t *) current_stack_pointer()); return dummy;
}
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). // This is the value for x86; works pretty well for PPC too. return (char *) -1;
}
address os::Posix::ucontext_get_pc(const ucontext_t* uc) { if (DecodeErrorContext) { #ifdefined(IA32) return (address)uc->uc_mcontext.gregs[REG_EIP]; #elifdefined(AMD64) return (address)uc->uc_mcontext.gregs[REG_RIP]; #elifdefined(ARM) return (address)uc->uc_mcontext.arm_pc; #elifdefined(AARCH64) return (address)uc->uc_mcontext.pc; #elifdefined(PPC) return (address)uc->uc_mcontext.regs->nip; #elifdefined(RISCV) return (address)uc->uc_mcontext.__gregs[REG_PC]; #elifdefined(S390) return (address)uc->uc_mcontext.psw.addr; #else // Non-arch-specific Zero code does not really know the PC. // If possible, add the arch-specific definition in this method.
fatal("Cannot handle ucontext_get_pc"); #endif
}
// Answer the default and hope for the best return nullptr;
}
if (uc != NULL) {
epc = os::Posix::ucontext_get_pc(uc); if (ret_sp) {
*ret_sp = (intptr_t*) os::Linux::ucontext_get_sp(uc);
} if (ret_fp) {
*ret_fp = (intptr_t*) os::Linux::ucontext_get_fp(uc);
}
} else {
epc = NULL; if (ret_sp) {
*ret_sp = nullptr;
} if (ret_fp) {
*ret_fp = nullptr;
}
}
return epc;
}
frame os::fetch_frame_from_context(constvoid* ucVoid) { // This code is only called from error handler to get PC and SP. // We don't have the ready ZeroFrame* at this point, so fake the // frame with bare minimum. if (ucVoid != NULL) { const ucontext_t* uc = (const ucontext_t*)ucVoid;
frame dummy = frame();
dummy.set_pc(os::Posix::ucontext_get_pc(uc));
dummy.set_sp((intptr_t*)os::Linux::ucontext_get_sp(uc)); return dummy;
} else { return frame(nullptr, nullptr);
}
}
if (info != NULL && thread != NULL) { // Handle ALL stack overflow variations here if (sig == SIGSEGV) {
address addr = (address) info->si_addr;
// check if fault address is within thread stack if (thread->is_in_full_stack(addr)) {
StackOverflow* overflow_state = thread->stack_overflow_state(); // stack overflow if (overflow_state->in_stack_yellow_reserved_zone(addr)) {
overflow_state->disable_stack_yellow_reserved_zone();
ShouldNotCallThis();
} elseif (overflow_state->in_stack_red_zone(addr)) {
overflow_state->disable_stack_red_zone();
ShouldNotCallThis();
} 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. if (thread->osthread()->expanding_stack() == 0) {
thread->osthread()->set_expanding_stack(); if (os::Linux::manually_expand_stack(thread, addr)) {
thread->osthread()->clear_expanding_stack(); returntrue;
}
thread->osthread()->clear_expanding_stack();
} else {
fatal("recursive segv. expanding stack.");
}
}
}
}
// 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; }
}*/
}
returnfalse; // Fatal error
}
void os::Linux::init_thread_fpu_state(void) { // Nothing to do
}
pthread_attr_t attr; int res = pthread_getattr_np(pthread_self(), &attr); if (res != 0) { if (res == ENOMEM) {
vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
} else {
fatal("pthread_getattr_np failed with error = %d", res);
}
}
address stack_bottom;
size_t stack_bytes;
res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes); if (res != 0) {
fatal("pthread_attr_getstack failed with error = %d", res);
}
address stack_top = stack_bottom + stack_bytes;
// The block of memory returned by pthread_attr_getstack() includes // guard pages where present. We need to trim these off.
size_t page_bytes = os::vm_page_size();
assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack");
size_t guard_bytes;
res = pthread_attr_getguardsize(&attr, &guard_bytes); if (res != 0) {
fatal("pthread_attr_getguardsize failed with errno = %d", res);
} int guard_pages = align_up(guard_bytes, page_bytes) / page_bytes;
assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");
#ifdef IA64 // IA64 has two stacks sharing the same area of memory, a normal // stack growing downwards and a register stack growing upwards. // Guard pages, if present, are in the centre. This code splits // the stack in two even without guard pages, though in theory // there's nothing to stop us allocating more to the normal stack // or more to the register stack if one or the other were found // to grow faster. int total_pages = align_down(stack_bytes, page_bytes) / page_bytes;
stack_bottom += (total_pages - guard_pages) / 2 * page_bytes; #endif// IA64
// 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, sizeof(char));
st->cr();
}
///////////////////////////////////////////////////////////////////////////// // Stubs for things that would be in linux_zero.s if it existed. // You probably want to disassemble these monkeys to check they're ok.
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.