Tue, 03 Aug 2010 08:13:38 -0400
6953477: Increase portability and flexibility of building Hotspot
Summary: A collection of portability improvements including shared code support for PPC, ARM platforms, software floating point, cross compilation support and improvements in error crash detail.
Reviewed-by: phh, never, coleenp, dholmes
duke@435 | 1 | /* |
trims@1907 | 2 | * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | // do not include precompiled header file |
duke@435 | 26 | # include "incls/_os_linux_x86.cpp.incl" |
duke@435 | 27 | |
duke@435 | 28 | // put OS-includes here |
duke@435 | 29 | # include <sys/types.h> |
duke@435 | 30 | # include <sys/mman.h> |
duke@435 | 31 | # include <pthread.h> |
duke@435 | 32 | # include <signal.h> |
duke@435 | 33 | # include <errno.h> |
duke@435 | 34 | # include <dlfcn.h> |
duke@435 | 35 | # include <stdlib.h> |
duke@435 | 36 | # include <stdio.h> |
duke@435 | 37 | # include <unistd.h> |
duke@435 | 38 | # include <sys/resource.h> |
duke@435 | 39 | # include <pthread.h> |
duke@435 | 40 | # include <sys/stat.h> |
duke@435 | 41 | # include <sys/time.h> |
duke@435 | 42 | # include <sys/utsname.h> |
duke@435 | 43 | # include <sys/socket.h> |
duke@435 | 44 | # include <sys/wait.h> |
duke@435 | 45 | # include <pwd.h> |
duke@435 | 46 | # include <poll.h> |
duke@435 | 47 | # include <ucontext.h> |
duke@435 | 48 | # include <fpu_control.h> |
duke@435 | 49 | |
duke@435 | 50 | #ifdef AMD64 |
duke@435 | 51 | #define REG_SP REG_RSP |
duke@435 | 52 | #define REG_PC REG_RIP |
duke@435 | 53 | #define REG_FP REG_RBP |
duke@435 | 54 | #define SPELL_REG_SP "rsp" |
duke@435 | 55 | #define SPELL_REG_FP "rbp" |
duke@435 | 56 | #else |
duke@435 | 57 | #define REG_SP REG_UESP |
duke@435 | 58 | #define REG_PC REG_EIP |
duke@435 | 59 | #define REG_FP REG_EBP |
duke@435 | 60 | #define SPELL_REG_SP "esp" |
duke@435 | 61 | #define SPELL_REG_FP "ebp" |
duke@435 | 62 | #endif // AMD64 |
duke@435 | 63 | |
duke@435 | 64 | address os::current_stack_pointer() { |
dcubed@485 | 65 | #ifdef SPARC_WORKS |
dcubed@485 | 66 | register void *esp; |
dcubed@485 | 67 | __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp)); |
dcubed@485 | 68 | return (address) ((char*)esp + sizeof(long)*2); |
dcubed@485 | 69 | #else |
duke@435 | 70 | register void *esp __asm__ (SPELL_REG_SP); |
duke@435 | 71 | return (address) esp; |
dcubed@485 | 72 | #endif |
duke@435 | 73 | } |
duke@435 | 74 | |
duke@435 | 75 | char* os::non_memory_address_word() { |
duke@435 | 76 | // Must never look like an address returned by reserve_memory, |
duke@435 | 77 | // even in its subfields (as defined by the CPU immediate fields, |
duke@435 | 78 | // if the CPU splits constants across multiple instructions). |
duke@435 | 79 | |
duke@435 | 80 | return (char*) -1; |
duke@435 | 81 | } |
duke@435 | 82 | |
duke@435 | 83 | void os::initialize_thread() { |
duke@435 | 84 | // Nothing to do. |
duke@435 | 85 | } |
duke@435 | 86 | |
duke@435 | 87 | address os::Linux::ucontext_get_pc(ucontext_t * uc) { |
duke@435 | 88 | return (address)uc->uc_mcontext.gregs[REG_PC]; |
duke@435 | 89 | } |
duke@435 | 90 | |
duke@435 | 91 | intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) { |
duke@435 | 92 | return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; |
duke@435 | 93 | } |
duke@435 | 94 | |
duke@435 | 95 | intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) { |
duke@435 | 96 | return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; |
duke@435 | 97 | } |
duke@435 | 98 | |
duke@435 | 99 | // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
duke@435 | 100 | // is currently interrupted by SIGPROF. |
duke@435 | 101 | // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal |
duke@435 | 102 | // frames. Currently we don't do that on Linux, so it's the same as |
duke@435 | 103 | // os::fetch_frame_from_context(). |
duke@435 | 104 | ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, |
duke@435 | 105 | ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
duke@435 | 106 | |
duke@435 | 107 | assert(thread != NULL, "just checking"); |
duke@435 | 108 | assert(ret_sp != NULL, "just checking"); |
duke@435 | 109 | assert(ret_fp != NULL, "just checking"); |
duke@435 | 110 | |
duke@435 | 111 | return os::fetch_frame_from_context(uc, ret_sp, ret_fp); |
duke@435 | 112 | } |
duke@435 | 113 | |
duke@435 | 114 | ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
duke@435 | 115 | intptr_t** ret_sp, intptr_t** ret_fp) { |
duke@435 | 116 | |
duke@435 | 117 | ExtendedPC epc; |
duke@435 | 118 | ucontext_t* uc = (ucontext_t*)ucVoid; |
duke@435 | 119 | |
duke@435 | 120 | if (uc != NULL) { |
duke@435 | 121 | epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); |
duke@435 | 122 | if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc); |
duke@435 | 123 | if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc); |
duke@435 | 124 | } else { |
duke@435 | 125 | // construct empty ExtendedPC for return value checking |
duke@435 | 126 | epc = ExtendedPC(NULL); |
duke@435 | 127 | if (ret_sp) *ret_sp = (intptr_t *)NULL; |
duke@435 | 128 | if (ret_fp) *ret_fp = (intptr_t *)NULL; |
duke@435 | 129 | } |
duke@435 | 130 | |
duke@435 | 131 | return epc; |
duke@435 | 132 | } |
duke@435 | 133 | |
duke@435 | 134 | frame os::fetch_frame_from_context(void* ucVoid) { |
duke@435 | 135 | intptr_t* sp; |
duke@435 | 136 | intptr_t* fp; |
duke@435 | 137 | ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); |
duke@435 | 138 | return frame(sp, fp, epc.pc()); |
duke@435 | 139 | } |
duke@435 | 140 | |
duke@435 | 141 | // By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get |
duke@435 | 142 | // turned off by -fomit-frame-pointer, |
duke@435 | 143 | frame os::get_sender_for_C_frame(frame* fr) { |
duke@435 | 144 | return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); |
duke@435 | 145 | } |
duke@435 | 146 | |
duke@435 | 147 | intptr_t* _get_previous_fp() { |
dcubed@485 | 148 | #ifdef SPARC_WORKS |
dcubed@485 | 149 | register intptr_t **ebp; |
dcubed@485 | 150 | __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp)); |
dcubed@485 | 151 | #else |
duke@435 | 152 | register intptr_t **ebp __asm__ (SPELL_REG_FP); |
dcubed@485 | 153 | #endif |
duke@435 | 154 | return (intptr_t*) *ebp; // we want what it points to. |
duke@435 | 155 | } |
duke@435 | 156 | |
duke@435 | 157 | |
duke@435 | 158 | frame os::current_frame() { |
duke@435 | 159 | intptr_t* fp = _get_previous_fp(); |
duke@435 | 160 | frame myframe((intptr_t*)os::current_stack_pointer(), |
duke@435 | 161 | (intptr_t*)fp, |
duke@435 | 162 | CAST_FROM_FN_PTR(address, os::current_frame)); |
duke@435 | 163 | if (os::is_first_C_frame(&myframe)) { |
duke@435 | 164 | // stack is not walkable |
duke@435 | 165 | return frame(NULL, NULL, NULL); |
duke@435 | 166 | } else { |
duke@435 | 167 | return os::get_sender_for_C_frame(&myframe); |
duke@435 | 168 | } |
duke@435 | 169 | } |
duke@435 | 170 | |
duke@435 | 171 | // Utility functions |
duke@435 | 172 | |
duke@435 | 173 | // From IA32 System Programming Guide |
duke@435 | 174 | enum { |
duke@435 | 175 | trap_page_fault = 0xE |
duke@435 | 176 | }; |
duke@435 | 177 | |
duke@435 | 178 | extern "C" void Fetch32PFI () ; |
duke@435 | 179 | extern "C" void Fetch32Resume () ; |
duke@435 | 180 | #ifdef AMD64 |
duke@435 | 181 | extern "C" void FetchNPFI () ; |
duke@435 | 182 | extern "C" void FetchNResume () ; |
duke@435 | 183 | #endif // AMD64 |
duke@435 | 184 | |
duke@435 | 185 | extern "C" int |
duke@435 | 186 | JVM_handle_linux_signal(int sig, |
duke@435 | 187 | siginfo_t* info, |
duke@435 | 188 | void* ucVoid, |
duke@435 | 189 | int abort_if_unrecognized) { |
duke@435 | 190 | ucontext_t* uc = (ucontext_t*) ucVoid; |
duke@435 | 191 | |
duke@435 | 192 | Thread* t = ThreadLocalStorage::get_thread_slow(); |
duke@435 | 193 | |
duke@435 | 194 | SignalHandlerMark shm(t); |
duke@435 | 195 | |
duke@435 | 196 | // Note: it's not uncommon that JNI code uses signal/sigset to install |
duke@435 | 197 | // then restore certain signal handler (e.g. to temporarily block SIGPIPE, |
duke@435 | 198 | // or have a SIGILL handler when detecting CPU type). When that happens, |
duke@435 | 199 | // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To |
duke@435 | 200 | // avoid unnecessary crash when libjsig is not preloaded, try handle signals |
duke@435 | 201 | // that do not require siginfo/ucontext first. |
duke@435 | 202 | |
duke@435 | 203 | if (sig == SIGPIPE || sig == SIGXFSZ) { |
duke@435 | 204 | // allow chained handler to go first |
duke@435 | 205 | if (os::Linux::chained_handler(sig, info, ucVoid)) { |
duke@435 | 206 | return true; |
duke@435 | 207 | } else { |
duke@435 | 208 | if (PrintMiscellaneous && (WizardMode || Verbose)) { |
duke@435 | 209 | char buf[64]; |
duke@435 | 210 | warning("Ignoring %s - see bugs 4229104 or 646499219", |
duke@435 | 211 | os::exception_name(sig, buf, sizeof(buf))); |
duke@435 | 212 | } |
duke@435 | 213 | return true; |
duke@435 | 214 | } |
duke@435 | 215 | } |
duke@435 | 216 | |
duke@435 | 217 | JavaThread* thread = NULL; |
duke@435 | 218 | VMThread* vmthread = NULL; |
duke@435 | 219 | if (os::Linux::signal_handlers_are_installed) { |
duke@435 | 220 | if (t != NULL ){ |
duke@435 | 221 | if(t->is_Java_thread()) { |
duke@435 | 222 | thread = (JavaThread*)t; |
duke@435 | 223 | } |
duke@435 | 224 | else if(t->is_VM_thread()){ |
duke@435 | 225 | vmthread = (VMThread *)t; |
duke@435 | 226 | } |
duke@435 | 227 | } |
duke@435 | 228 | } |
duke@435 | 229 | /* |
duke@435 | 230 | NOTE: does not seem to work on linux. |
duke@435 | 231 | if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) { |
duke@435 | 232 | // can't decode this kind of signal |
duke@435 | 233 | info = NULL; |
duke@435 | 234 | } else { |
duke@435 | 235 | assert(sig == info->si_signo, "bad siginfo"); |
duke@435 | 236 | } |
duke@435 | 237 | */ |
duke@435 | 238 | // decide if this trap can be handled by a stub |
duke@435 | 239 | address stub = NULL; |
duke@435 | 240 | |
duke@435 | 241 | address pc = NULL; |
duke@435 | 242 | |
duke@435 | 243 | //%note os_trap_1 |
duke@435 | 244 | if (info != NULL && uc != NULL && thread != NULL) { |
duke@435 | 245 | pc = (address) os::Linux::ucontext_get_pc(uc); |
duke@435 | 246 | |
duke@435 | 247 | if (pc == (address) Fetch32PFI) { |
duke@435 | 248 | uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ; |
duke@435 | 249 | return 1 ; |
duke@435 | 250 | } |
duke@435 | 251 | #ifdef AMD64 |
duke@435 | 252 | if (pc == (address) FetchNPFI) { |
duke@435 | 253 | uc->uc_mcontext.gregs[REG_PC] = intptr_t (FetchNResume) ; |
duke@435 | 254 | return 1 ; |
duke@435 | 255 | } |
duke@435 | 256 | #endif // AMD64 |
duke@435 | 257 | |
duke@435 | 258 | // Handle ALL stack overflow variations here |
duke@435 | 259 | if (sig == SIGSEGV) { |
duke@435 | 260 | address addr = (address) info->si_addr; |
duke@435 | 261 | |
duke@435 | 262 | // check if fault address is within thread stack |
duke@435 | 263 | if (addr < thread->stack_base() && |
duke@435 | 264 | addr >= thread->stack_base() - thread->stack_size()) { |
duke@435 | 265 | // stack overflow |
duke@435 | 266 | if (thread->in_stack_yellow_zone(addr)) { |
duke@435 | 267 | thread->disable_stack_yellow_zone(); |
duke@435 | 268 | if (thread->thread_state() == _thread_in_Java) { |
duke@435 | 269 | // Throw a stack overflow exception. Guard pages will be reenabled |
duke@435 | 270 | // while unwinding the stack. |
duke@435 | 271 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); |
duke@435 | 272 | } else { |
duke@435 | 273 | // Thread was in the vm or native code. Return and try to finish. |
duke@435 | 274 | return 1; |
duke@435 | 275 | } |
duke@435 | 276 | } else if (thread->in_stack_red_zone(addr)) { |
duke@435 | 277 | // Fatal red zone violation. Disable the guard pages and fall through |
duke@435 | 278 | // to handle_unexpected_exception way down below. |
duke@435 | 279 | thread->disable_stack_red_zone(); |
duke@435 | 280 | tty->print_raw_cr("An irrecoverable stack overflow has occurred."); |
duke@435 | 281 | } else { |
duke@435 | 282 | // Accessing stack address below sp may cause SEGV if current |
duke@435 | 283 | // thread has MAP_GROWSDOWN stack. This should only happen when |
duke@435 | 284 | // current thread was created by user code with MAP_GROWSDOWN flag |
duke@435 | 285 | // and then attached to VM. See notes in os_linux.cpp. |
duke@435 | 286 | if (thread->osthread()->expanding_stack() == 0) { |
duke@435 | 287 | thread->osthread()->set_expanding_stack(); |
duke@435 | 288 | if (os::Linux::manually_expand_stack(thread, addr)) { |
duke@435 | 289 | thread->osthread()->clear_expanding_stack(); |
duke@435 | 290 | return 1; |
duke@435 | 291 | } |
duke@435 | 292 | thread->osthread()->clear_expanding_stack(); |
duke@435 | 293 | } else { |
duke@435 | 294 | fatal("recursive segv. expanding stack."); |
duke@435 | 295 | } |
duke@435 | 296 | } |
duke@435 | 297 | } |
duke@435 | 298 | } |
duke@435 | 299 | |
duke@435 | 300 | if (thread->thread_state() == _thread_in_Java) { |
duke@435 | 301 | // Java thread running in Java code => find exception handler if any |
duke@435 | 302 | // a fault inside compiled code, the interpreter, or a stub |
duke@435 | 303 | |
duke@435 | 304 | if (sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) { |
duke@435 | 305 | stub = SharedRuntime::get_poll_stub(pc); |
duke@435 | 306 | } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { |
duke@435 | 307 | // BugId 4454115: A read from a MappedByteBuffer can fault |
duke@435 | 308 | // here if the underlying file has been truncated. |
duke@435 | 309 | // Do not crash the VM in such a case. |
duke@435 | 310 | CodeBlob* cb = CodeCache::find_blob_unsafe(pc); |
duke@435 | 311 | nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; |
duke@435 | 312 | if (nm != NULL && nm->has_unsafe_access()) { |
duke@435 | 313 | stub = StubRoutines::handler_for_unsafe_access(); |
duke@435 | 314 | } |
duke@435 | 315 | } |
duke@435 | 316 | else |
duke@435 | 317 | |
duke@435 | 318 | #ifdef AMD64 |
duke@435 | 319 | if (sig == SIGFPE && |
duke@435 | 320 | (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { |
duke@435 | 321 | stub = |
duke@435 | 322 | SharedRuntime:: |
duke@435 | 323 | continuation_for_implicit_exception(thread, |
duke@435 | 324 | pc, |
duke@435 | 325 | SharedRuntime:: |
duke@435 | 326 | IMPLICIT_DIVIDE_BY_ZERO); |
duke@435 | 327 | #else |
duke@435 | 328 | if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) { |
duke@435 | 329 | // HACK: si_code does not work on linux 2.2.12-20!!! |
duke@435 | 330 | int op = pc[0]; |
duke@435 | 331 | if (op == 0xDB) { |
duke@435 | 332 | // FIST |
duke@435 | 333 | // TODO: The encoding of D2I in i486.ad can cause an exception |
duke@435 | 334 | // prior to the fist instruction if there was an invalid operation |
duke@435 | 335 | // pending. We want to dismiss that exception. From the win_32 |
duke@435 | 336 | // side it also seems that if it really was the fist causing |
duke@435 | 337 | // the exception that we do the d2i by hand with different |
duke@435 | 338 | // rounding. Seems kind of weird. |
duke@435 | 339 | // NOTE: that we take the exception at the NEXT floating point instruction. |
duke@435 | 340 | assert(pc[0] == 0xDB, "not a FIST opcode"); |
duke@435 | 341 | assert(pc[1] == 0x14, "not a FIST opcode"); |
duke@435 | 342 | assert(pc[2] == 0x24, "not a FIST opcode"); |
duke@435 | 343 | return true; |
duke@435 | 344 | } else if (op == 0xF7) { |
duke@435 | 345 | // IDIV |
duke@435 | 346 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); |
duke@435 | 347 | } else { |
duke@435 | 348 | // TODO: handle more cases if we are using other x86 instructions |
duke@435 | 349 | // that can generate SIGFPE signal on linux. |
duke@435 | 350 | tty->print_cr("unknown opcode 0x%X with SIGFPE.", op); |
duke@435 | 351 | fatal("please update this code."); |
duke@435 | 352 | } |
duke@435 | 353 | #endif // AMD64 |
duke@435 | 354 | } else if (sig == SIGSEGV && |
duke@435 | 355 | !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { |
duke@435 | 356 | // Determination of interpreter/vtable stub/compiled code null exception |
duke@435 | 357 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); |
duke@435 | 358 | } |
duke@435 | 359 | } else if (thread->thread_state() == _thread_in_vm && |
duke@435 | 360 | sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ |
duke@435 | 361 | thread->doing_unsafe_access()) { |
duke@435 | 362 | stub = StubRoutines::handler_for_unsafe_access(); |
duke@435 | 363 | } |
duke@435 | 364 | |
duke@435 | 365 | // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in |
duke@435 | 366 | // and the heap gets shrunk before the field access. |
duke@435 | 367 | if ((sig == SIGSEGV) || (sig == SIGBUS)) { |
duke@435 | 368 | address addr = JNI_FastGetField::find_slowcase_pc(pc); |
duke@435 | 369 | if (addr != (address)-1) { |
duke@435 | 370 | stub = addr; |
duke@435 | 371 | } |
duke@435 | 372 | } |
duke@435 | 373 | |
duke@435 | 374 | // Check to see if we caught the safepoint code in the |
duke@435 | 375 | // process of write protecting the memory serialization page. |
duke@435 | 376 | // It write enables the page immediately after protecting it |
duke@435 | 377 | // so we can just return to retry the write. |
duke@435 | 378 | if ((sig == SIGSEGV) && |
duke@435 | 379 | os::is_memory_serialize_page(thread, (address) info->si_addr)) { |
duke@435 | 380 | // Block current thread until the memory serialize page permission restored. |
duke@435 | 381 | os::block_on_serialize_page_trap(); |
duke@435 | 382 | return true; |
duke@435 | 383 | } |
duke@435 | 384 | } |
duke@435 | 385 | |
duke@435 | 386 | #ifndef AMD64 |
duke@435 | 387 | // Execution protection violation |
duke@435 | 388 | // |
duke@435 | 389 | // This should be kept as the last step in the triage. We don't |
duke@435 | 390 | // have a dedicated trap number for a no-execute fault, so be |
duke@435 | 391 | // conservative and allow other handlers the first shot. |
duke@435 | 392 | // |
duke@435 | 393 | // Note: We don't test that info->si_code == SEGV_ACCERR here. |
duke@435 | 394 | // this si_code is so generic that it is almost meaningless; and |
duke@435 | 395 | // the si_code for this condition may change in the future. |
duke@435 | 396 | // Furthermore, a false-positive should be harmless. |
duke@435 | 397 | if (UnguardOnExecutionViolation > 0 && |
duke@435 | 398 | (sig == SIGSEGV || sig == SIGBUS) && |
duke@435 | 399 | uc->uc_mcontext.gregs[REG_TRAPNO] == trap_page_fault) { |
duke@435 | 400 | int page_size = os::vm_page_size(); |
duke@435 | 401 | address addr = (address) info->si_addr; |
duke@435 | 402 | address pc = os::Linux::ucontext_get_pc(uc); |
duke@435 | 403 | // Make sure the pc and the faulting address are sane. |
duke@435 | 404 | // |
duke@435 | 405 | // If an instruction spans a page boundary, and the page containing |
duke@435 | 406 | // the beginning of the instruction is executable but the following |
duke@435 | 407 | // page is not, the pc and the faulting address might be slightly |
duke@435 | 408 | // different - we still want to unguard the 2nd page in this case. |
duke@435 | 409 | // |
duke@435 | 410 | // 15 bytes seems to be a (very) safe value for max instruction size. |
duke@435 | 411 | bool pc_is_near_addr = |
duke@435 | 412 | (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15); |
duke@435 | 413 | bool instr_spans_page_boundary = |
duke@435 | 414 | (align_size_down((intptr_t) pc ^ (intptr_t) addr, |
duke@435 | 415 | (intptr_t) page_size) > 0); |
duke@435 | 416 | |
duke@435 | 417 | if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) { |
duke@435 | 418 | static volatile address last_addr = |
duke@435 | 419 | (address) os::non_memory_address_word(); |
duke@435 | 420 | |
duke@435 | 421 | // In conservative mode, don't unguard unless the address is in the VM |
duke@435 | 422 | if (addr != last_addr && |
duke@435 | 423 | (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) { |
duke@435 | 424 | |
coleenp@912 | 425 | // Set memory to RWX and retry |
duke@435 | 426 | address page_start = |
duke@435 | 427 | (address) align_size_down((intptr_t) addr, (intptr_t) page_size); |
coleenp@912 | 428 | bool res = os::protect_memory((char*) page_start, page_size, |
coleenp@912 | 429 | os::MEM_PROT_RWX); |
duke@435 | 430 | |
duke@435 | 431 | if (PrintMiscellaneous && Verbose) { |
duke@435 | 432 | char buf[256]; |
duke@435 | 433 | jio_snprintf(buf, sizeof(buf), "Execution protection violation " |
duke@435 | 434 | "at " INTPTR_FORMAT |
duke@435 | 435 | ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, |
duke@435 | 436 | page_start, (res ? "success" : "failed"), errno); |
duke@435 | 437 | tty->print_raw_cr(buf); |
duke@435 | 438 | } |
duke@435 | 439 | stub = pc; |
duke@435 | 440 | |
duke@435 | 441 | // Set last_addr so if we fault again at the same address, we don't end |
duke@435 | 442 | // up in an endless loop. |
duke@435 | 443 | // |
duke@435 | 444 | // There are two potential complications here. Two threads trapping at |
duke@435 | 445 | // the same address at the same time could cause one of the threads to |
duke@435 | 446 | // think it already unguarded, and abort the VM. Likely very rare. |
duke@435 | 447 | // |
duke@435 | 448 | // The other race involves two threads alternately trapping at |
duke@435 | 449 | // different addresses and failing to unguard the page, resulting in |
duke@435 | 450 | // an endless loop. This condition is probably even more unlikely than |
duke@435 | 451 | // the first. |
duke@435 | 452 | // |
duke@435 | 453 | // Although both cases could be avoided by using locks or thread local |
duke@435 | 454 | // last_addr, these solutions are unnecessary complication: this |
duke@435 | 455 | // handler is a best-effort safety net, not a complete solution. It is |
duke@435 | 456 | // disabled by default and should only be used as a workaround in case |
duke@435 | 457 | // we missed any no-execute-unsafe VM code. |
duke@435 | 458 | |
duke@435 | 459 | last_addr = addr; |
duke@435 | 460 | } |
duke@435 | 461 | } |
duke@435 | 462 | } |
duke@435 | 463 | #endif // !AMD64 |
duke@435 | 464 | |
duke@435 | 465 | if (stub != NULL) { |
duke@435 | 466 | // save all thread context in case we need to restore it |
duke@435 | 467 | if (thread != NULL) thread->set_saved_exception_pc(pc); |
duke@435 | 468 | |
duke@435 | 469 | uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub; |
duke@435 | 470 | return true; |
duke@435 | 471 | } |
duke@435 | 472 | |
duke@435 | 473 | // signal-chaining |
duke@435 | 474 | if (os::Linux::chained_handler(sig, info, ucVoid)) { |
duke@435 | 475 | return true; |
duke@435 | 476 | } |
duke@435 | 477 | |
duke@435 | 478 | if (!abort_if_unrecognized) { |
duke@435 | 479 | // caller wants another chance, so give it to him |
duke@435 | 480 | return false; |
duke@435 | 481 | } |
duke@435 | 482 | |
duke@435 | 483 | if (pc == NULL && uc != NULL) { |
duke@435 | 484 | pc = os::Linux::ucontext_get_pc(uc); |
duke@435 | 485 | } |
duke@435 | 486 | |
duke@435 | 487 | // unmask current signal |
duke@435 | 488 | sigset_t newset; |
duke@435 | 489 | sigemptyset(&newset); |
duke@435 | 490 | sigaddset(&newset, sig); |
duke@435 | 491 | sigprocmask(SIG_UNBLOCK, &newset, NULL); |
duke@435 | 492 | |
duke@435 | 493 | VMError err(t, sig, pc, info, ucVoid); |
duke@435 | 494 | err.report_and_die(); |
duke@435 | 495 | |
duke@435 | 496 | ShouldNotReachHere(); |
duke@435 | 497 | } |
duke@435 | 498 | |
duke@435 | 499 | void os::Linux::init_thread_fpu_state(void) { |
duke@435 | 500 | #ifndef AMD64 |
duke@435 | 501 | // set fpu to 53 bit precision |
duke@435 | 502 | set_fpu_control_word(0x27f); |
duke@435 | 503 | #endif // !AMD64 |
duke@435 | 504 | } |
duke@435 | 505 | |
duke@435 | 506 | int os::Linux::get_fpu_control_word(void) { |
duke@435 | 507 | #ifdef AMD64 |
duke@435 | 508 | return 0; |
duke@435 | 509 | #else |
duke@435 | 510 | int fpu_control; |
duke@435 | 511 | _FPU_GETCW(fpu_control); |
duke@435 | 512 | return fpu_control & 0xffff; |
duke@435 | 513 | #endif // AMD64 |
duke@435 | 514 | } |
duke@435 | 515 | |
duke@435 | 516 | void os::Linux::set_fpu_control_word(int fpu_control) { |
duke@435 | 517 | #ifndef AMD64 |
duke@435 | 518 | _FPU_SETCW(fpu_control); |
duke@435 | 519 | #endif // !AMD64 |
duke@435 | 520 | } |
duke@435 | 521 | |
duke@435 | 522 | // Check that the linux kernel version is 2.4 or higher since earlier |
duke@435 | 523 | // versions do not support SSE without patches. |
duke@435 | 524 | bool os::supports_sse() { |
duke@435 | 525 | #ifdef AMD64 |
duke@435 | 526 | return true; |
duke@435 | 527 | #else |
duke@435 | 528 | struct utsname uts; |
duke@435 | 529 | if( uname(&uts) != 0 ) return false; // uname fails? |
duke@435 | 530 | char *minor_string; |
duke@435 | 531 | int major = strtol(uts.release,&minor_string,10); |
duke@435 | 532 | int minor = strtol(minor_string+1,NULL,10); |
duke@435 | 533 | bool result = (major > 2 || (major==2 && minor >= 4)); |
duke@435 | 534 | #ifndef PRODUCT |
duke@435 | 535 | if (PrintMiscellaneous && Verbose) { |
duke@435 | 536 | tty->print("OS version is %d.%d, which %s support SSE/SSE2\n", |
duke@435 | 537 | major,minor, result ? "DOES" : "does NOT"); |
duke@435 | 538 | } |
duke@435 | 539 | #endif |
duke@435 | 540 | return result; |
duke@435 | 541 | #endif // AMD64 |
duke@435 | 542 | } |
duke@435 | 543 | |
duke@435 | 544 | bool os::is_allocatable(size_t bytes) { |
duke@435 | 545 | #ifdef AMD64 |
duke@435 | 546 | // unused on amd64? |
duke@435 | 547 | return true; |
duke@435 | 548 | #else |
duke@435 | 549 | |
duke@435 | 550 | if (bytes < 2 * G) { |
duke@435 | 551 | return true; |
duke@435 | 552 | } |
duke@435 | 553 | |
duke@435 | 554 | char* addr = reserve_memory(bytes, NULL); |
duke@435 | 555 | |
duke@435 | 556 | if (addr != NULL) { |
duke@435 | 557 | release_memory(addr, bytes); |
duke@435 | 558 | } |
duke@435 | 559 | |
duke@435 | 560 | return addr != NULL; |
duke@435 | 561 | #endif // AMD64 |
duke@435 | 562 | } |
duke@435 | 563 | |
duke@435 | 564 | //////////////////////////////////////////////////////////////////////////////// |
duke@435 | 565 | // thread stack |
duke@435 | 566 | |
duke@435 | 567 | #ifdef AMD64 |
duke@435 | 568 | size_t os::Linux::min_stack_allowed = 64 * K; |
duke@435 | 569 | |
duke@435 | 570 | // amd64: pthread on amd64 is always in floating stack mode |
duke@435 | 571 | bool os::Linux::supports_variable_stack_size() { return true; } |
duke@435 | 572 | #else |
duke@435 | 573 | size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K; |
duke@435 | 574 | |
dcubed@485 | 575 | #ifdef __GNUC__ |
duke@435 | 576 | #define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;}) |
dcubed@485 | 577 | #endif |
duke@435 | 578 | |
duke@435 | 579 | // Test if pthread library can support variable thread stack size. LinuxThreads |
duke@435 | 580 | // in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads |
duke@435 | 581 | // in floating stack mode and NPTL support variable stack size. |
duke@435 | 582 | bool os::Linux::supports_variable_stack_size() { |
duke@435 | 583 | if (os::Linux::is_NPTL()) { |
duke@435 | 584 | // NPTL, yes |
duke@435 | 585 | return true; |
duke@435 | 586 | |
duke@435 | 587 | } else { |
duke@435 | 588 | // Note: We can't control default stack size when creating a thread. |
duke@435 | 589 | // If we use non-default stack size (pthread_attr_setstacksize), both |
duke@435 | 590 | // floating stack and non-floating stack LinuxThreads will return the |
duke@435 | 591 | // same value. This makes it impossible to implement this function by |
duke@435 | 592 | // detecting thread stack size directly. |
duke@435 | 593 | // |
duke@435 | 594 | // An alternative approach is to check %gs. Fixed-stack LinuxThreads |
duke@435 | 595 | // do not use %gs, so its value is 0. Floating-stack LinuxThreads use |
duke@435 | 596 | // %gs (either as LDT selector or GDT selector, depending on kernel) |
duke@435 | 597 | // to access thread specific data. |
duke@435 | 598 | // |
duke@435 | 599 | // Note that %gs is a reserved glibc register since early 2001, so |
duke@435 | 600 | // applications are not allowed to change its value (Ulrich Drepper from |
duke@435 | 601 | // Redhat confirmed that all known offenders have been modified to use |
duke@435 | 602 | // either %fs or TSD). In the worst case scenario, when VM is embedded in |
duke@435 | 603 | // a native application that plays with %gs, we might see non-zero %gs |
duke@435 | 604 | // even LinuxThreads is running in fixed stack mode. As the result, we'll |
duke@435 | 605 | // return true and skip _thread_safety_check(), so we may not be able to |
duke@435 | 606 | // detect stack-heap collisions. But otherwise it's harmless. |
duke@435 | 607 | // |
dcubed@485 | 608 | #ifdef __GNUC__ |
duke@435 | 609 | return (GET_GS() != 0); |
dcubed@485 | 610 | #else |
dcubed@485 | 611 | return false; |
dcubed@485 | 612 | #endif |
duke@435 | 613 | } |
duke@435 | 614 | } |
duke@435 | 615 | #endif // AMD64 |
duke@435 | 616 | |
duke@435 | 617 | // return default stack size for thr_type |
duke@435 | 618 | size_t os::Linux::default_stack_size(os::ThreadType thr_type) { |
duke@435 | 619 | // default stack size (compiler thread needs larger stack) |
duke@435 | 620 | #ifdef AMD64 |
duke@435 | 621 | size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); |
duke@435 | 622 | #else |
duke@435 | 623 | size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K); |
duke@435 | 624 | #endif // AMD64 |
duke@435 | 625 | return s; |
duke@435 | 626 | } |
duke@435 | 627 | |
duke@435 | 628 | size_t os::Linux::default_guard_size(os::ThreadType thr_type) { |
duke@435 | 629 | // Creating guard page is very expensive. Java thread has HotSpot |
duke@435 | 630 | // guard page, only enable glibc guard page for non-Java threads. |
duke@435 | 631 | return (thr_type == java_thread ? 0 : page_size()); |
duke@435 | 632 | } |
duke@435 | 633 | |
duke@435 | 634 | // Java thread: |
duke@435 | 635 | // |
duke@435 | 636 | // Low memory addresses |
duke@435 | 637 | // +------------------------+ |
duke@435 | 638 | // | |\ JavaThread created by VM does not have glibc |
duke@435 | 639 | // | glibc guard page | - guard, attached Java thread usually has |
duke@435 | 640 | // | |/ 1 page glibc guard. |
duke@435 | 641 | // P1 +------------------------+ Thread::stack_base() - Thread::stack_size() |
duke@435 | 642 | // | |\ |
duke@435 | 643 | // | HotSpot Guard Pages | - red and yellow pages |
duke@435 | 644 | // | |/ |
duke@435 | 645 | // +------------------------+ JavaThread::stack_yellow_zone_base() |
duke@435 | 646 | // | |\ |
duke@435 | 647 | // | Normal Stack | - |
duke@435 | 648 | // | |/ |
duke@435 | 649 | // P2 +------------------------+ Thread::stack_base() |
duke@435 | 650 | // |
duke@435 | 651 | // Non-Java thread: |
duke@435 | 652 | // |
duke@435 | 653 | // Low memory addresses |
duke@435 | 654 | // +------------------------+ |
duke@435 | 655 | // | |\ |
duke@435 | 656 | // | glibc guard page | - usually 1 page |
duke@435 | 657 | // | |/ |
duke@435 | 658 | // P1 +------------------------+ Thread::stack_base() - Thread::stack_size() |
duke@435 | 659 | // | |\ |
duke@435 | 660 | // | Normal Stack | - |
duke@435 | 661 | // | |/ |
duke@435 | 662 | // P2 +------------------------+ Thread::stack_base() |
duke@435 | 663 | // |
duke@435 | 664 | // ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from |
duke@435 | 665 | // pthread_attr_getstack() |
duke@435 | 666 | |
duke@435 | 667 | static void current_stack_region(address * bottom, size_t * size) { |
duke@435 | 668 | if (os::Linux::is_initial_thread()) { |
duke@435 | 669 | // initial thread needs special handling because pthread_getattr_np() |
duke@435 | 670 | // may return bogus value. |
duke@435 | 671 | *bottom = os::Linux::initial_thread_stack_bottom(); |
duke@435 | 672 | *size = os::Linux::initial_thread_stack_size(); |
duke@435 | 673 | } else { |
duke@435 | 674 | pthread_attr_t attr; |
duke@435 | 675 | |
duke@435 | 676 | int rslt = pthread_getattr_np(pthread_self(), &attr); |
duke@435 | 677 | |
duke@435 | 678 | // JVM needs to know exact stack location, abort if it fails |
duke@435 | 679 | if (rslt != 0) { |
duke@435 | 680 | if (rslt == ENOMEM) { |
duke@435 | 681 | vm_exit_out_of_memory(0, "pthread_getattr_np"); |
duke@435 | 682 | } else { |
jcoomes@1845 | 683 | fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt)); |
duke@435 | 684 | } |
duke@435 | 685 | } |
duke@435 | 686 | |
duke@435 | 687 | if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) { |
duke@435 | 688 | fatal("Can not locate current stack attributes!"); |
duke@435 | 689 | } |
duke@435 | 690 | |
duke@435 | 691 | pthread_attr_destroy(&attr); |
duke@435 | 692 | |
duke@435 | 693 | } |
duke@435 | 694 | assert(os::current_stack_pointer() >= *bottom && |
duke@435 | 695 | os::current_stack_pointer() < *bottom + *size, "just checking"); |
duke@435 | 696 | } |
duke@435 | 697 | |
duke@435 | 698 | address os::current_stack_base() { |
duke@435 | 699 | address bottom; |
duke@435 | 700 | size_t size; |
duke@435 | 701 | current_stack_region(&bottom, &size); |
duke@435 | 702 | return (bottom + size); |
duke@435 | 703 | } |
duke@435 | 704 | |
duke@435 | 705 | size_t os::current_stack_size() { |
duke@435 | 706 | // stack size includes normal stack and HotSpot guard pages |
duke@435 | 707 | address bottom; |
duke@435 | 708 | size_t size; |
duke@435 | 709 | current_stack_region(&bottom, &size); |
duke@435 | 710 | return size; |
duke@435 | 711 | } |
duke@435 | 712 | |
duke@435 | 713 | ///////////////////////////////////////////////////////////////////////////// |
duke@435 | 714 | // helper functions for fatal error handler |
duke@435 | 715 | |
duke@435 | 716 | void os::print_context(outputStream *st, void *context) { |
duke@435 | 717 | if (context == NULL) return; |
duke@435 | 718 | |
duke@435 | 719 | ucontext_t *uc = (ucontext_t*)context; |
duke@435 | 720 | st->print_cr("Registers:"); |
bobv@2036 | 721 | |
bobv@2036 | 722 | // this is horrendously verbose but the layout of the registers in the |
bobv@2036 | 723 | // context does not match how we defined our abstract Register set, so |
bobv@2036 | 724 | // we can't just iterate through the gregs area |
bobv@2036 | 725 | |
duke@435 | 726 | #ifdef AMD64 |
duke@435 | 727 | st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]); |
duke@435 | 728 | st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]); |
duke@435 | 729 | st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]); |
duke@435 | 730 | st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]); |
duke@435 | 731 | st->cr(); |
duke@435 | 732 | st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]); |
duke@435 | 733 | st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]); |
duke@435 | 734 | st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]); |
duke@435 | 735 | st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]); |
duke@435 | 736 | st->cr(); |
duke@435 | 737 | st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); |
duke@435 | 738 | st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]); |
duke@435 | 739 | st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]); |
duke@435 | 740 | st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]); |
duke@435 | 741 | st->cr(); |
duke@435 | 742 | st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); |
duke@435 | 743 | st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]); |
duke@435 | 744 | st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]); |
duke@435 | 745 | st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]); |
duke@435 | 746 | st->cr(); |
duke@435 | 747 | st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]); |
duke@435 | 748 | st->print(", EFL=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]); |
duke@435 | 749 | st->print(", CSGSFS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_CSGSFS]); |
duke@435 | 750 | st->print(", ERR=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ERR]); |
duke@435 | 751 | st->cr(); |
duke@435 | 752 | st->print(" TRAPNO=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_TRAPNO]); |
bobv@2036 | 753 | |
bobv@2036 | 754 | st->cr(); |
bobv@2036 | 755 | st->cr(); |
bobv@2036 | 756 | |
bobv@2036 | 757 | st->print_cr("Register to memory mapping:"); |
bobv@2036 | 758 | st->cr(); |
bobv@2036 | 759 | |
bobv@2036 | 760 | // this is only for the "general purpose" registers |
bobv@2036 | 761 | |
bobv@2036 | 762 | st->print_cr("RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]); |
bobv@2036 | 763 | print_location(st, uc->uc_mcontext.gregs[REG_RAX]); |
bobv@2036 | 764 | st->cr(); |
bobv@2036 | 765 | st->print_cr("RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]); |
bobv@2036 | 766 | print_location(st, uc->uc_mcontext.gregs[REG_RBX]); |
bobv@2036 | 767 | st->cr(); |
bobv@2036 | 768 | st->print_cr("RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]); |
bobv@2036 | 769 | print_location(st, uc->uc_mcontext.gregs[REG_RCX]); |
bobv@2036 | 770 | st->cr(); |
bobv@2036 | 771 | st->print_cr("RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]); |
bobv@2036 | 772 | print_location(st, uc->uc_mcontext.gregs[REG_RDX]); |
bobv@2036 | 773 | st->cr(); |
bobv@2036 | 774 | st->print_cr("RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]); |
bobv@2036 | 775 | print_location(st, uc->uc_mcontext.gregs[REG_RSP]); |
bobv@2036 | 776 | st->cr(); |
bobv@2036 | 777 | st->print_cr("RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]); |
bobv@2036 | 778 | print_location(st, uc->uc_mcontext.gregs[REG_RBP]); |
bobv@2036 | 779 | st->cr(); |
bobv@2036 | 780 | st->print_cr("RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]); |
bobv@2036 | 781 | print_location(st, uc->uc_mcontext.gregs[REG_RSI]); |
bobv@2036 | 782 | st->cr(); |
bobv@2036 | 783 | st->print_cr("RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]); |
bobv@2036 | 784 | print_location(st, uc->uc_mcontext.gregs[REG_RDI]); |
bobv@2036 | 785 | st->cr(); |
bobv@2036 | 786 | st->print_cr("R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); |
bobv@2036 | 787 | print_location(st, uc->uc_mcontext.gregs[REG_R8]); |
bobv@2036 | 788 | st->cr(); |
bobv@2036 | 789 | st->print_cr("R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]); |
bobv@2036 | 790 | print_location(st, uc->uc_mcontext.gregs[REG_R9]); |
bobv@2036 | 791 | st->cr(); |
bobv@2036 | 792 | st->print_cr("R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]); |
bobv@2036 | 793 | print_location(st, uc->uc_mcontext.gregs[REG_R10]); |
bobv@2036 | 794 | st->cr(); |
bobv@2036 | 795 | st->print_cr("R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]); |
bobv@2036 | 796 | print_location(st, uc->uc_mcontext.gregs[REG_R11]); |
bobv@2036 | 797 | st->cr(); |
bobv@2036 | 798 | st->print_cr("R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); |
bobv@2036 | 799 | print_location(st, uc->uc_mcontext.gregs[REG_R12]); |
bobv@2036 | 800 | st->cr(); |
bobv@2036 | 801 | st->print_cr("R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]); |
bobv@2036 | 802 | print_location(st, uc->uc_mcontext.gregs[REG_R13]); |
bobv@2036 | 803 | st->cr(); |
bobv@2036 | 804 | st->print_cr("R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]); |
bobv@2036 | 805 | print_location(st, uc->uc_mcontext.gregs[REG_R14]); |
bobv@2036 | 806 | st->cr(); |
bobv@2036 | 807 | st->print_cr("R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]); |
bobv@2036 | 808 | print_location(st, uc->uc_mcontext.gregs[REG_R15]); |
bobv@2036 | 809 | |
duke@435 | 810 | #else |
duke@435 | 811 | st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]); |
duke@435 | 812 | st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]); |
duke@435 | 813 | st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ECX]); |
duke@435 | 814 | st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDX]); |
duke@435 | 815 | st->cr(); |
duke@435 | 816 | st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_UESP]); |
duke@435 | 817 | st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBP]); |
duke@435 | 818 | st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESI]); |
duke@435 | 819 | st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]); |
duke@435 | 820 | st->cr(); |
duke@435 | 821 | st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EIP]); |
duke@435 | 822 | st->print(", CR2=" INTPTR_FORMAT, uc->uc_mcontext.cr2); |
duke@435 | 823 | st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]); |
bobv@2036 | 824 | |
bobv@2036 | 825 | st->cr(); |
bobv@2036 | 826 | st->cr(); |
bobv@2036 | 827 | |
bobv@2036 | 828 | st->print_cr("Register to memory mapping:"); |
bobv@2036 | 829 | st->cr(); |
bobv@2036 | 830 | |
bobv@2036 | 831 | // this is only for the "general purpose" registers |
bobv@2036 | 832 | |
bobv@2036 | 833 | st->print_cr("EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]); |
bobv@2036 | 834 | print_location(st, uc->uc_mcontext.gregs[REG_EAX]); |
bobv@2036 | 835 | st->cr(); |
bobv@2036 | 836 | st->print_cr("EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]); |
bobv@2036 | 837 | print_location(st, uc->uc_mcontext.gregs[REG_EBX]); |
bobv@2036 | 838 | st->cr(); |
bobv@2036 | 839 | st->print_cr("ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ECX]); |
bobv@2036 | 840 | print_location(st, uc->uc_mcontext.gregs[REG_ECX]); |
bobv@2036 | 841 | st->cr(); |
bobv@2036 | 842 | st->print_cr("EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDX]); |
bobv@2036 | 843 | print_location(st, uc->uc_mcontext.gregs[REG_EDX]); |
bobv@2036 | 844 | st->cr(); |
bobv@2036 | 845 | st->print_cr("ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESP]); |
bobv@2036 | 846 | print_location(st, uc->uc_mcontext.gregs[REG_ESP]); |
bobv@2036 | 847 | st->cr(); |
bobv@2036 | 848 | st->print_cr("EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBP]); |
bobv@2036 | 849 | print_location(st, uc->uc_mcontext.gregs[REG_EBP]); |
bobv@2036 | 850 | st->cr(); |
bobv@2036 | 851 | st->print_cr("ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESI]); |
bobv@2036 | 852 | print_location(st, uc->uc_mcontext.gregs[REG_ESI]); |
bobv@2036 | 853 | st->cr(); |
bobv@2036 | 854 | st->print_cr("EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]); |
bobv@2036 | 855 | print_location(st, uc->uc_mcontext.gregs[REG_EDI]); |
bobv@2036 | 856 | |
duke@435 | 857 | #endif // AMD64 |
duke@435 | 858 | st->cr(); |
duke@435 | 859 | st->cr(); |
duke@435 | 860 | |
duke@435 | 861 | intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc); |
duke@435 | 862 | st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); |
duke@435 | 863 | print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t)); |
duke@435 | 864 | st->cr(); |
duke@435 | 865 | |
duke@435 | 866 | // Note: it may be unsafe to inspect memory near pc. For example, pc may |
duke@435 | 867 | // point to garbage if entry point in an nmethod is corrupted. Leave |
duke@435 | 868 | // this at the end, and hope for the best. |
duke@435 | 869 | address pc = os::Linux::ucontext_get_pc(uc); |
duke@435 | 870 | st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
duke@435 | 871 | print_hex_dump(st, pc - 16, pc + 16, sizeof(char)); |
duke@435 | 872 | } |
duke@435 | 873 | |
duke@435 | 874 | void os::setup_fpu() { |
duke@435 | 875 | #ifndef AMD64 |
duke@435 | 876 | address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); |
duke@435 | 877 | __asm__ volatile ( "fldcw (%0)" : |
duke@435 | 878 | : "r" (fpu_cntrl) : "memory"); |
duke@435 | 879 | #endif // !AMD64 |
duke@435 | 880 | } |