Path: blob/master/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
40930 views
/*1* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324// no precompiled headers25#include "jvm.h"26#include "asm/macroAssembler.hpp"27#include "classfile/vmSymbols.hpp"28#include "code/icBuffer.hpp"29#include "code/vtableStubs.hpp"30#include "interpreter/interpreter.hpp"31#include "memory/allocation.inline.hpp"32#include "memory/resourceArea.hpp"33#include "nativeInst_x86.hpp"34#include "os_share_windows.hpp"35#include "prims/jniFastGetField.hpp"36#include "prims/jvm_misc.hpp"37#include "runtime/arguments.hpp"38#include "runtime/frame.inline.hpp"39#include "runtime/interfaceSupport.inline.hpp"40#include "runtime/java.hpp"41#include "runtime/javaCalls.hpp"42#include "runtime/mutexLocker.hpp"43#include "runtime/osThread.hpp"44#include "runtime/sharedRuntime.hpp"45#include "runtime/stubRoutines.hpp"46#include "runtime/thread.inline.hpp"47#include "runtime/timer.hpp"48#include "symbolengine.hpp"49#include "unwind_windows_x86.hpp"50#include "utilities/events.hpp"51#include "utilities/vmError.hpp"52#include "windbghelp.hpp"535455#undef REG_SP56#undef REG_FP57#undef REG_PC58#ifdef AMD6459#define REG_SP Rsp60#define REG_FP Rbp61#define REG_PC Rip62#else63#define REG_SP Esp64#define REG_FP Ebp65#define REG_PC Eip66#endif // AMD646768JNIEXPORT69extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );7071// Install a win32 structured exception handler around thread.72void os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, JavaThread* thread) {73__try {7475#ifndef AMD6476// We store the current thread in this wrapperthread location77// and determine how far away this address is from the structured78// execption pointer that FS:[0] points to. This get_thread79// code can then get the thread pointer via FS.80//81// Warning: This routine must NEVER be inlined since we'd end up with82// multiple offsets.83//84volatile Thread* wrapperthread = thread;8586if (os::win32::get_thread_ptr_offset() == 0) {87int thread_ptr_offset;88__asm {89lea eax, dword ptr wrapperthread;90sub eax, dword ptr FS:[0H];91mov thread_ptr_offset, eax92};93os::win32::set_thread_ptr_offset(thread_ptr_offset);94}95#ifdef ASSERT96// Verify that the offset hasn't changed since we initally captured97// it. This might happen if we accidentally ended up with an98// inlined version of this routine.99else {100int test_thread_ptr_offset;101__asm {102lea eax, dword ptr wrapperthread;103sub eax, dword ptr FS:[0H];104mov test_thread_ptr_offset, eax105};106assert(test_thread_ptr_offset == os::win32::get_thread_ptr_offset(),107"thread pointer offset from SEH changed");108}109#endif // ASSERT110#endif // !AMD64111112f(value, method, args, thread);113} __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {114// Nothing to do.115}116}117118#ifdef AMD64119120// This is the language specific handler for exceptions121// originating from dynamically generated code.122// We call the standard structured exception handler123// We only expect Continued Execution since we cannot unwind124// from generated code.125LONG HandleExceptionFromCodeCache(126IN PEXCEPTION_RECORD ExceptionRecord,127IN ULONG64 EstablisherFrame,128IN OUT PCONTEXT ContextRecord,129IN OUT PDISPATCHER_CONTEXT DispatcherContext) {130EXCEPTION_POINTERS ep;131LONG result;132133ep.ExceptionRecord = ExceptionRecord;134ep.ContextRecord = ContextRecord;135136result = topLevelExceptionFilter(&ep);137138// We better only get a CONTINUE_EXECUTION from our handler139// since we don't have unwind information registered.140141guarantee( result == EXCEPTION_CONTINUE_EXECUTION,142"Unexpected result from topLevelExceptionFilter");143144return(ExceptionContinueExecution);145}146147148// Structure containing the Windows Data Structures required149// to register our Code Cache exception handler.150// We put these in the CodeCache since the API requires151// all addresses in these structures are relative to the Code152// area registered with RtlAddFunctionTable.153typedef struct {154char ExceptionHandlerInstr[16]; // jmp HandleExceptionFromCodeCache155RUNTIME_FUNCTION rt;156UNWIND_INFO_EH_ONLY unw;157} DynamicCodeData, *pDynamicCodeData;158159#endif // AMD64160//161// Register our CodeCache area with the OS so it will dispatch exceptions162// to our topLevelExceptionFilter when we take an exception in our163// dynamically generated code.164//165// Arguments: low and high are the address of the full reserved166// codeCache area167//168bool os::register_code_area(char *low, char *high) {169#ifdef AMD64170171ResourceMark rm;172173pDynamicCodeData pDCD;174PRUNTIME_FUNCTION prt;175PUNWIND_INFO_EH_ONLY punwind;176177BufferBlob* blob = BufferBlob::create("CodeCache Exception Handler", sizeof(DynamicCodeData));178CodeBuffer cb(blob);179MacroAssembler* masm = new MacroAssembler(&cb);180pDCD = (pDynamicCodeData) masm->pc();181182masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache));183masm->flush();184185// Create an Unwind Structure specifying no unwind info186// other than an Exception Handler187punwind = &pDCD->unw;188punwind->Version = 1;189punwind->Flags = UNW_FLAG_EHANDLER;190punwind->SizeOfProlog = 0;191punwind->CountOfCodes = 0;192punwind->FrameRegister = 0;193punwind->FrameOffset = 0;194punwind->ExceptionHandler = (char *)(&(pDCD->ExceptionHandlerInstr[0])) -195(char*)low;196punwind->ExceptionData[0] = 0;197198// This structure describes the covered dynamic code area.199// Addresses are relative to the beginning on the code cache area200prt = &pDCD->rt;201prt->BeginAddress = 0;202prt->EndAddress = (ULONG)(high - low);203prt->UnwindData = ((char *)punwind - low);204205guarantee(RtlAddFunctionTable(prt, 1, (ULONGLONG)low),206"Failed to register Dynamic Code Exception Handler with RtlAddFunctionTable");207208#endif // AMD64209return true;210}211212#ifdef AMD64213/*214* Windows/x64 does not use stack frames the way expected by Java:215* [1] in most cases, there is no frame pointer. All locals are addressed via RSP216* [2] in rare cases, when alloca() is used, a frame pointer is used, but this may217* not be RBP.218* See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx219*220* So it's not possible to print the native stack using the221* while (...) {... fr = os::get_sender_for_C_frame(&fr); }222* loop in vmError.cpp. We need to roll our own loop.223*/224bool os::platform_print_native_stack(outputStream* st, const void* context,225char *buf, int buf_size)226{227CONTEXT ctx;228if (context != NULL) {229memcpy(&ctx, context, sizeof(ctx));230} else {231RtlCaptureContext(&ctx);232}233234st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");235236STACKFRAME stk;237memset(&stk, 0, sizeof(stk));238stk.AddrStack.Offset = ctx.Rsp;239stk.AddrStack.Mode = AddrModeFlat;240stk.AddrFrame.Offset = ctx.Rbp;241stk.AddrFrame.Mode = AddrModeFlat;242stk.AddrPC.Offset = ctx.Rip;243stk.AddrPC.Mode = AddrModeFlat;244245int count = 0;246address lastpc = 0;247while (count++ < StackPrintLimit) {248intptr_t* sp = (intptr_t*)stk.AddrStack.Offset;249intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!250address pc = (address)stk.AddrPC.Offset;251252if (pc != NULL) {253if (count == 2 && lastpc == pc) {254// Skip it -- StackWalk64() may return the same PC255// (but different SP) on the first try.256} else {257// Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame258// may not contain what Java expects, and may cause the frame() constructor259// to crash. Let's just print out the symbolic address.260frame::print_C_frame(st, buf, buf_size, pc);261// print source file and line, if available262char buf[128];263int line_no;264if (SymbolEngine::get_source_info(pc, buf, sizeof(buf), &line_no)) {265st->print(" (%s:%d)", buf, line_no);266}267st->cr();268}269lastpc = pc;270}271272PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);273if (!p) {274// StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash.275break;276}277278BOOL result = WindowsDbgHelp::stackWalk64(279IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType,280GetCurrentProcess(), // __in HANDLE hProcess,281GetCurrentThread(), // __in HANDLE hThread,282&stk, // __inout LP STACKFRAME64 StackFrame,283&ctx); // __inout PVOID ContextRecord,284285if (!result) {286break;287}288}289if (count > StackPrintLimit) {290st->print_cr("...<more frames>...");291}292st->cr();293294return true;295}296#endif // AMD64297298address os::fetch_frame_from_context(const void* ucVoid,299intptr_t** ret_sp, intptr_t** ret_fp) {300301address epc;302CONTEXT* uc = (CONTEXT*)ucVoid;303304if (uc != NULL) {305epc = (address)uc->REG_PC;306if (ret_sp) *ret_sp = (intptr_t*)uc->REG_SP;307if (ret_fp) *ret_fp = (intptr_t*)uc->REG_FP;308} else {309epc = NULL;310if (ret_sp) *ret_sp = (intptr_t *)NULL;311if (ret_fp) *ret_fp = (intptr_t *)NULL;312}313314return epc;315}316317frame os::fetch_frame_from_context(const void* ucVoid) {318intptr_t* sp;319intptr_t* fp;320address epc = fetch_frame_from_context(ucVoid, &sp, &fp);321return frame(sp, fp, epc);322}323324#ifndef AMD64325// Ignore "C4172: returning address of local variable or temporary" on 32bit326PRAGMA_DIAG_PUSH327PRAGMA_DISABLE_MSVC_WARNING(4172)328// Returns an estimate of the current stack pointer. Result must be guaranteed329// to point into the calling threads stack, and be no lower than the current330// stack pointer.331address os::current_stack_pointer() {332int dummy;333address sp = (address)&dummy;334return sp;335}336PRAGMA_DIAG_POP337#else338// Returns the current stack pointer. Accurate value needed for339// os::verify_stack_alignment().340address os::current_stack_pointer() {341typedef address get_sp_func();342get_sp_func* func = CAST_TO_FN_PTR(get_sp_func*,343StubRoutines::x86::get_previous_sp_entry());344return (*func)();345}346#endif347348bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread,349struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) {350PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;351address addr = (address) exceptionRecord->ExceptionInformation[1];352if (Interpreter::contains(pc)) {353*fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);354if (!fr->is_first_java_frame()) {355// get_frame_at_stack_banging_point() is only called when we356// have well defined stacks so java_sender() calls do not need357// to assert safe_for_sender() first.358*fr = fr->java_sender();359}360} else {361// more complex code with compiled code362assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");363CodeBlob* cb = CodeCache::find_blob(pc);364if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {365// Not sure where the pc points to, fallback to default366// stack overflow handling367return false;368} else {369// in compiled code, the stack banging is performed just after the return pc370// has been pushed on the stack371intptr_t* fp = (intptr_t*)exceptionInfo->ContextRecord->REG_FP;372intptr_t* sp = (intptr_t*)exceptionInfo->ContextRecord->REG_SP;373*fr = frame(sp + 1, fp, (address)*sp);374if (!fr->is_java_frame()) {375// See java_sender() comment above.376*fr = fr->java_sender();377}378}379}380assert(fr->is_java_frame(), "Safety check");381return true;382}383384385// VC++ does not save frame pointer on stack in optimized build. It386// can be turned off by /Oy-. If we really want to walk C frames,387// we can use the StackWalk() API.388frame os::get_sender_for_C_frame(frame* fr) {389ShouldNotReachHere();390return frame();391}392393frame os::current_frame() {394return frame(); // cannot walk Windows frames this way. See os::get_native_stack395// and os::platform_print_native_stack396}397398void os::print_context(outputStream *st, const void *context) {399if (context == NULL) return;400401const CONTEXT* uc = (const CONTEXT*)context;402403st->print_cr("Registers:");404#ifdef AMD64405st->print( "RAX=" INTPTR_FORMAT, uc->Rax);406st->print(", RBX=" INTPTR_FORMAT, uc->Rbx);407st->print(", RCX=" INTPTR_FORMAT, uc->Rcx);408st->print(", RDX=" INTPTR_FORMAT, uc->Rdx);409st->cr();410st->print( "RSP=" INTPTR_FORMAT, uc->Rsp);411st->print(", RBP=" INTPTR_FORMAT, uc->Rbp);412st->print(", RSI=" INTPTR_FORMAT, uc->Rsi);413st->print(", RDI=" INTPTR_FORMAT, uc->Rdi);414st->cr();415st->print( "R8 =" INTPTR_FORMAT, uc->R8);416st->print(", R9 =" INTPTR_FORMAT, uc->R9);417st->print(", R10=" INTPTR_FORMAT, uc->R10);418st->print(", R11=" INTPTR_FORMAT, uc->R11);419st->cr();420st->print( "R12=" INTPTR_FORMAT, uc->R12);421st->print(", R13=" INTPTR_FORMAT, uc->R13);422st->print(", R14=" INTPTR_FORMAT, uc->R14);423st->print(", R15=" INTPTR_FORMAT, uc->R15);424st->cr();425st->print( "RIP=" INTPTR_FORMAT, uc->Rip);426st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);427#else428st->print( "EAX=" INTPTR_FORMAT, uc->Eax);429st->print(", EBX=" INTPTR_FORMAT, uc->Ebx);430st->print(", ECX=" INTPTR_FORMAT, uc->Ecx);431st->print(", EDX=" INTPTR_FORMAT, uc->Edx);432st->cr();433st->print( "ESP=" INTPTR_FORMAT, uc->Esp);434st->print(", EBP=" INTPTR_FORMAT, uc->Ebp);435st->print(", ESI=" INTPTR_FORMAT, uc->Esi);436st->print(", EDI=" INTPTR_FORMAT, uc->Edi);437st->cr();438st->print( "EIP=" INTPTR_FORMAT, uc->Eip);439st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);440#endif // AMD64441st->cr();442st->cr();443444intptr_t *sp = (intptr_t *)uc->REG_SP;445st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);446print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t));447st->cr();448449// Note: it may be unsafe to inspect memory near pc. For example, pc may450// point to garbage if entry point in an nmethod is corrupted. Leave451// this at the end, and hope for the best.452address pc = (address)uc->REG_PC;453print_instructions(st, pc, sizeof(char));454st->cr();455}456457458void os::print_register_info(outputStream *st, const void *context) {459if (context == NULL) return;460461const CONTEXT* uc = (const CONTEXT*)context;462463st->print_cr("Register to memory mapping:");464st->cr();465466// this is only for the "general purpose" registers467468#ifdef AMD64469st->print("RIP="); print_location(st, uc->Rip);470st->print("RAX="); print_location(st, uc->Rax);471st->print("RBX="); print_location(st, uc->Rbx);472st->print("RCX="); print_location(st, uc->Rcx);473st->print("RDX="); print_location(st, uc->Rdx);474st->print("RSP="); print_location(st, uc->Rsp);475st->print("RBP="); print_location(st, uc->Rbp);476st->print("RSI="); print_location(st, uc->Rsi);477st->print("RDI="); print_location(st, uc->Rdi);478st->print("R8 ="); print_location(st, uc->R8);479st->print("R9 ="); print_location(st, uc->R9);480st->print("R10="); print_location(st, uc->R10);481st->print("R11="); print_location(st, uc->R11);482st->print("R12="); print_location(st, uc->R12);483st->print("R13="); print_location(st, uc->R13);484st->print("R14="); print_location(st, uc->R14);485st->print("R15="); print_location(st, uc->R15);486#else487st->print("EIP="); print_location(st, uc->Eip);488st->print("EAX="); print_location(st, uc->Eax);489st->print("EBX="); print_location(st, uc->Ebx);490st->print("ECX="); print_location(st, uc->Ecx);491st->print("EDX="); print_location(st, uc->Edx);492st->print("ESP="); print_location(st, uc->Esp);493st->print("EBP="); print_location(st, uc->Ebp);494st->print("ESI="); print_location(st, uc->Esi);495st->print("EDI="); print_location(st, uc->Edi);496#endif497498st->cr();499}500501extern "C" int SpinPause () {502#ifdef AMD64503return 0 ;504#else505// pause == rep:nop506// On systems that don't support pause a rep:nop507// is executed as a nop. The rep: prefix is ignored.508_asm {509pause ;510};511return 1 ;512#endif // AMD64513}514515juint os::cpu_microcode_revision() {516juint result = 0;517BYTE data[8] = {0};518HKEY key;519DWORD status = RegOpenKey(HKEY_LOCAL_MACHINE,520"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);521if (status == ERROR_SUCCESS) {522DWORD size = sizeof(data);523status = RegQueryValueEx(key, "Update Revision", NULL, NULL, data, &size);524if (status == ERROR_SUCCESS) {525if (size == 4) result = *((juint*)data);526if (size == 8) result = *((juint*)data + 1); // upper 32-bits527}528RegCloseKey(key);529}530return result;531}532533void os::setup_fpu() {534#ifndef AMD64535int fpu_cntrl_word = StubRoutines::fpu_cntrl_wrd_std();536__asm fldcw fpu_cntrl_word;537#endif // !AMD64538}539540#ifndef PRODUCT541void os::verify_stack_alignment() {542#ifdef AMD64543// The current_stack_pointer() calls generated get_previous_sp stub routine.544// Only enable the assert after the routine becomes available.545if (StubRoutines::code1() != NULL) {546assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");547}548#endif549}550#endif551552int os::extra_bang_size_in_bytes() {553// JDK-8050147 requires the full cache line bang for x86.554return VM_Version::L1_line_size();555}556557558