| /* Copyright (C) 2009-2024 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program 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 for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "event-top.h" | 
 | #include "extract-store-integer.h" | 
 | #include "osabi.h" | 
 | #include "amd64-tdep.h" | 
 | #include "gdbsupport/x86-xstate.h" | 
 | #include "gdbtypes.h" | 
 | #include "gdbcore.h" | 
 | #include "regcache.h" | 
 | #include "windows-tdep.h" | 
 | #include "frame.h" | 
 | #include "objfiles.h" | 
 | #include "frame-unwind.h" | 
 | #include "coff/internal.h" | 
 | #include "coff/i386.h" | 
 | #include "coff/pe.h" | 
 | #include "libcoff.h" | 
 | #include "value.h" | 
 | #include <algorithm> | 
 |  | 
 | /* The registers used to pass integer arguments during a function call.  */ | 
 | static int amd64_windows_dummy_call_integer_regs[] = | 
 | { | 
 |   AMD64_RCX_REGNUM,          /* %rcx */ | 
 |   AMD64_RDX_REGNUM,          /* %rdx */ | 
 |   AMD64_R8_REGNUM,           /* %r8 */ | 
 |   AMD64_R9_REGNUM            /* %r9 */ | 
 | }; | 
 |  | 
 | /* This vector maps GDB's idea of a register's number into an offset into | 
 |    the Windows API CONTEXT structure.  */ | 
 | static int amd64_windows_gregset_reg_offset[] = | 
 | { | 
 |   120, /* Rax */ | 
 |   144, /* Rbx */ | 
 |   128, /* Rcx */ | 
 |   136, /* Rdx */ | 
 |   168, /* Rsi */ | 
 |   176, /* Rdi */ | 
 |   160, /* Rbp */ | 
 |   152, /* Rsp */ | 
 |   184, /* R8 */ | 
 |   192, /* R9 */ | 
 |   200, /* R10 */ | 
 |   208, /* R11 */ | 
 |   216, /* R12 */ | 
 |   224, /* R13 */ | 
 |   232, /* R14 */ | 
 |   240, /* R15 */ | 
 |   248, /* Rip */ | 
 |   68,  /* EFlags */ | 
 |   56,  /* SegCs */ | 
 |   66,  /* SegSs */ | 
 |   58,  /* SegDs */ | 
 |   60,  /* SegEs */ | 
 |   62,  /* SegFs */ | 
 |   64,  /* SegGs */ | 
 |   288, /* FloatSave.FloatRegisters[0] */ | 
 |   304, /* FloatSave.FloatRegisters[1] */ | 
 |   320, /* FloatSave.FloatRegisters[2] */ | 
 |   336, /* FloatSave.FloatRegisters[3] */ | 
 |   352, /* FloatSave.FloatRegisters[4] */ | 
 |   368, /* FloatSave.FloatRegisters[5] */ | 
 |   384, /* FloatSave.FloatRegisters[6] */ | 
 |   400, /* FloatSave.FloatRegisters[7] */ | 
 |   256, /* FloatSave.ControlWord */ | 
 |   258, /* FloatSave.StatusWord */ | 
 |   260, /* FloatSave.TagWord */ | 
 |   268, /* FloatSave.ErrorSelector */ | 
 |   264, /* FloatSave.ErrorOffset */ | 
 |   276, /* FloatSave.DataSelector */ | 
 |   272, /* FloatSave.DataOffset */ | 
 |   268, /* FloatSave.ErrorSelector */ | 
 |   416, /* Xmm0 */ | 
 |   432, /* Xmm1 */ | 
 |   448, /* Xmm2 */ | 
 |   464, /* Xmm3 */ | 
 |   480, /* Xmm4 */ | 
 |   496, /* Xmm5 */ | 
 |   512, /* Xmm6 */ | 
 |   528, /* Xmm7 */ | 
 |   544, /* Xmm8 */ | 
 |   560, /* Xmm9 */ | 
 |   576, /* Xmm10 */ | 
 |   592, /* Xmm11 */ | 
 |   608, /* Xmm12 */ | 
 |   624, /* Xmm13 */ | 
 |   640, /* Xmm14 */ | 
 |   656, /* Xmm15 */ | 
 |   280, /* FloatSave.MxCsr */ | 
 | }; | 
 |  | 
 | #define AMD64_WINDOWS_SIZEOF_GREGSET 1232 | 
 |  | 
 | /* Return nonzero if an argument of type TYPE should be passed | 
 |    via one of the integer registers.  */ | 
 |  | 
 | static int | 
 | amd64_windows_passed_by_integer_register (struct type *type) | 
 | { | 
 |   switch (type->code ()) | 
 |     { | 
 |       case TYPE_CODE_INT: | 
 |       case TYPE_CODE_ENUM: | 
 |       case TYPE_CODE_BOOL: | 
 |       case TYPE_CODE_RANGE: | 
 |       case TYPE_CODE_CHAR: | 
 |       case TYPE_CODE_PTR: | 
 |       case TYPE_CODE_REF: | 
 |       case TYPE_CODE_RVALUE_REF: | 
 |       case TYPE_CODE_STRUCT: | 
 |       case TYPE_CODE_UNION: | 
 |       case TYPE_CODE_COMPLEX: | 
 | 	return (type->length () == 1 | 
 | 		|| type->length () == 2 | 
 | 		|| type->length () == 4 | 
 | 		|| type->length () == 8); | 
 |  | 
 |       default: | 
 | 	return 0; | 
 |     } | 
 | } | 
 |  | 
 | /* Return nonzero if an argument of type TYPE should be passed | 
 |    via one of the XMM registers.  */ | 
 |  | 
 | static int | 
 | amd64_windows_passed_by_xmm_register (struct type *type) | 
 | { | 
 |   return ((type->code () == TYPE_CODE_FLT | 
 | 	   || type->code () == TYPE_CODE_DECFLOAT) | 
 | 	  && (type->length () == 4 || type->length () == 8)); | 
 | } | 
 |  | 
 | /* Return non-zero iff an argument of the given TYPE should be passed | 
 |    by pointer.  */ | 
 |  | 
 | static int | 
 | amd64_windows_passed_by_pointer (struct type *type) | 
 | { | 
 |   if (amd64_windows_passed_by_integer_register (type)) | 
 |     return 0; | 
 |  | 
 |   if (amd64_windows_passed_by_xmm_register (type)) | 
 |     return 0; | 
 |  | 
 |   return 1; | 
 | } | 
 |  | 
 | /* For each argument that should be passed by pointer, reserve some | 
 |    stack space, store a copy of the argument on the stack, and replace | 
 |    the argument by its address.  Return the new Stack Pointer value. | 
 |  | 
 |    NARGS is the number of arguments. ARGS is the array containing | 
 |    the value of each argument.  SP is value of the Stack Pointer.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_windows_adjust_args_passed_by_pointer (struct value **args, | 
 | 					     int nargs, CORE_ADDR sp) | 
 | { | 
 |   int i; | 
 |  | 
 |   for (i = 0; i < nargs; i++) | 
 |     if (amd64_windows_passed_by_pointer (args[i]->type ())) | 
 |       { | 
 | 	struct type *type = args[i]->type (); | 
 | 	const gdb_byte *valbuf = args[i]->contents ().data (); | 
 | 	const int len = type->length (); | 
 |  | 
 | 	/* Store a copy of that argument on the stack, aligned to | 
 | 	   a 16 bytes boundary, and then use the copy's address as | 
 | 	   the argument.  */ | 
 |  | 
 | 	sp -= len; | 
 | 	sp &= ~0xf; | 
 | 	write_memory (sp, valbuf, len); | 
 |  | 
 | 	args[i] | 
 | 	  = value_addr (value_from_contents_and_address (type, valbuf, sp)); | 
 |       } | 
 |  | 
 |   return sp; | 
 | } | 
 |  | 
 | /* Store the value of ARG in register REGNO (right-justified). | 
 |    REGCACHE is the register cache.  */ | 
 |  | 
 | static void | 
 | amd64_windows_store_arg_in_reg (struct regcache *regcache, | 
 | 				struct value *arg, int regno) | 
 | { | 
 |   struct type *type = arg->type (); | 
 |   const gdb_byte *valbuf = arg->contents ().data (); | 
 |   gdb_byte buf[8]; | 
 |  | 
 |   gdb_assert (type->length () <= 8); | 
 |   memset (buf, 0, sizeof buf); | 
 |   memcpy (buf, valbuf, std::min (type->length (), (ULONGEST) 8)); | 
 |   regcache->cooked_write (regno, buf); | 
 | } | 
 |  | 
 | /* Push the arguments for an inferior function call, and return | 
 |    the updated value of the SP (Stack Pointer). | 
 |  | 
 |    All arguments are identical to the arguments used in | 
 |    amd64_windows_push_dummy_call.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_windows_push_arguments (struct regcache *regcache, int nargs, | 
 | 			      struct value **args, CORE_ADDR sp, | 
 | 			      function_call_return_method return_method) | 
 | { | 
 |   int reg_idx = 0; | 
 |   int i; | 
 |   struct value **stack_args = XALLOCAVEC (struct value *, nargs); | 
 |   int num_stack_args = 0; | 
 |   int num_elements = 0; | 
 |   int element = 0; | 
 |  | 
 |   /* First, handle the arguments passed by pointer. | 
 |  | 
 |      These arguments are replaced by pointers to a copy we are making | 
 |      in inferior memory.  So use a copy of the ARGS table, to avoid | 
 |      modifying the original one.  */ | 
 |   { | 
 |     struct value **args1 = XALLOCAVEC (struct value *, nargs); | 
 |  | 
 |     memcpy (args1, args, nargs * sizeof (struct value *)); | 
 |     sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp); | 
 |     args = args1; | 
 |   } | 
 |  | 
 |   /* Reserve a register for the "hidden" argument.  */ | 
 |   if (return_method == return_method_struct) | 
 |     reg_idx++; | 
 |  | 
 |   for (i = 0; i < nargs; i++) | 
 |     { | 
 |       struct type *type = args[i]->type (); | 
 |       int len = type->length (); | 
 |       int on_stack_p = 1; | 
 |  | 
 |       if (reg_idx < ARRAY_SIZE (amd64_windows_dummy_call_integer_regs)) | 
 | 	{ | 
 | 	  if (amd64_windows_passed_by_integer_register (type)) | 
 | 	    { | 
 | 	      amd64_windows_store_arg_in_reg | 
 | 		(regcache, args[i], | 
 | 		 amd64_windows_dummy_call_integer_regs[reg_idx]); | 
 | 	      on_stack_p = 0; | 
 | 	      reg_idx++; | 
 | 	    } | 
 | 	  else if (amd64_windows_passed_by_xmm_register (type)) | 
 | 	    { | 
 | 	      amd64_windows_store_arg_in_reg | 
 | 		(regcache, args[i], AMD64_XMM0_REGNUM + reg_idx); | 
 | 	      /* In case of varargs, these parameters must also be | 
 | 		 passed via the integer registers.  */ | 
 | 	      amd64_windows_store_arg_in_reg | 
 | 		(regcache, args[i], | 
 | 		 amd64_windows_dummy_call_integer_regs[reg_idx]); | 
 | 	      on_stack_p = 0; | 
 | 	      reg_idx++; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       if (on_stack_p) | 
 | 	{ | 
 | 	  num_elements += ((len + 7) / 8); | 
 | 	  stack_args[num_stack_args++] = args[i]; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Allocate space for the arguments on the stack, keeping it | 
 |      aligned on a 16 byte boundary.  */ | 
 |   sp -= num_elements * 8; | 
 |   sp &= ~0xf; | 
 |  | 
 |   /* Write out the arguments to the stack.  */ | 
 |   for (i = 0; i < num_stack_args; i++) | 
 |     { | 
 |       struct type *type = stack_args[i]->type (); | 
 |       const gdb_byte *valbuf = stack_args[i]->contents ().data (); | 
 |  | 
 |       write_memory (sp + element * 8, valbuf, type->length ()); | 
 |       element += ((type->length () + 7) / 8); | 
 |     } | 
 |  | 
 |   return sp; | 
 | } | 
 |  | 
 | /* Implement the "push_dummy_call" gdbarch method.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_windows_push_dummy_call | 
 |   (struct gdbarch *gdbarch, struct value *function, | 
 |    struct regcache *regcache, CORE_ADDR bp_addr, | 
 |    int nargs, struct value **args, CORE_ADDR sp, | 
 |    function_call_return_method return_method, CORE_ADDR struct_addr) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte buf[8]; | 
 |  | 
 |   /* Pass arguments.  */ | 
 |   sp = amd64_windows_push_arguments (regcache, nargs, args, sp, | 
 | 				     return_method); | 
 |  | 
 |   /* Pass "hidden" argument".  */ | 
 |   if (return_method == return_method_struct) | 
 |     { | 
 |       /* The "hidden" argument is passed through the first argument | 
 | 	 register.  */ | 
 |       const int arg_regnum = amd64_windows_dummy_call_integer_regs[0]; | 
 |  | 
 |       store_unsigned_integer (buf, 8, byte_order, struct_addr); | 
 |       regcache->cooked_write (arg_regnum, buf); | 
 |     } | 
 |  | 
 |   /* Reserve some memory on the stack for the integer-parameter | 
 |      registers, as required by the ABI.  */ | 
 |   sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8; | 
 |  | 
 |   /* Store return address.  */ | 
 |   sp -= 8; | 
 |   store_unsigned_integer (buf, 8, byte_order, bp_addr); | 
 |   write_memory (sp, buf, 8); | 
 |  | 
 |   /* Update the stack pointer...  */ | 
 |   store_unsigned_integer (buf, 8, byte_order, sp); | 
 |   regcache->cooked_write (AMD64_RSP_REGNUM, buf); | 
 |  | 
 |   /* ...and fake a frame pointer.  */ | 
 |   regcache->cooked_write (AMD64_RBP_REGNUM, buf); | 
 |  | 
 |   return sp + 16; | 
 | } | 
 |  | 
 | /* Implement the "return_value" gdbarch method for amd64-windows.  */ | 
 |  | 
 | static enum return_value_convention | 
 | amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function, | 
 | 			    struct type *type, struct regcache *regcache, | 
 | 			    struct value **read_value, const gdb_byte *writebuf) | 
 | { | 
 |   int len = type->length (); | 
 |   int regnum = -1; | 
 |  | 
 |   /* See if our value is returned through a register.  If it is, then | 
 |      store the associated register number in REGNUM.  */ | 
 |   switch (type->code ()) | 
 |     { | 
 |       case TYPE_CODE_FLT: | 
 | 	/* floats, and doubles are returned via XMM0.  */ | 
 | 	if (len == 4 || len == 8) | 
 | 	  regnum = AMD64_XMM0_REGNUM; | 
 | 	break; | 
 |       case TYPE_CODE_ARRAY: | 
 | 	/* __m128, __m128i and __m128d are returned via XMM0.  */ | 
 | 	if (type->is_vector () && len == 16) | 
 | 	  { | 
 | 	    enum type_code code = type->target_type ()->code (); | 
 | 	    if (code == TYPE_CODE_INT || code == TYPE_CODE_FLT) | 
 | 	      { | 
 | 		regnum = AMD64_XMM0_REGNUM; | 
 | 		break; | 
 | 	      } | 
 | 	  } | 
 | 	[[fallthrough]]; | 
 |       default: | 
 | 	/* All other values that are 1, 2, 4 or 8 bytes long are returned | 
 | 	   via RAX.  */ | 
 | 	if (len == 1 || len == 2 || len == 4 || len == 8) | 
 | 	  regnum = AMD64_RAX_REGNUM; | 
 | 	else if (len == 16 && type->code () == TYPE_CODE_INT) | 
 | 	  regnum = AMD64_XMM0_REGNUM; | 
 | 	break; | 
 |     } | 
 |  | 
 |   if (regnum < 0) | 
 |     { | 
 |       /* RAX contains the address where the return value has been stored.  */ | 
 |       if (read_value != nullptr) | 
 | 	{ | 
 | 	  ULONGEST addr; | 
 |  | 
 | 	  regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr); | 
 | 	  *read_value = value_at_non_lval (type, addr); | 
 | 	} | 
 |       return RETURN_VALUE_ABI_RETURNS_ADDRESS; | 
 |     } | 
 |   else | 
 |     { | 
 |       /* Extract the return value from the register where it was stored.  */ | 
 |       if (read_value != nullptr) | 
 | 	{ | 
 | 	  *read_value = value::allocate (type); | 
 | 	  regcache->raw_read_part (regnum, 0, len, | 
 | 				   (*read_value)->contents_raw ().data ()); | 
 | 	} | 
 |       if (writebuf) | 
 | 	regcache->raw_write_part (regnum, 0, len, writebuf); | 
 |       return RETURN_VALUE_REGISTER_CONVENTION; | 
 |     } | 
 | } | 
 |  | 
 | /* Check that the code pointed to by PC corresponds to a call to | 
 |    __main, skip it if so.  Return PC otherwise.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) | 
 | { | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte op; | 
 |  | 
 |   target_read_memory (pc, &op, 1); | 
 |   if (op == 0xe8) | 
 |     { | 
 |       gdb_byte buf[4]; | 
 |  | 
 |       if (target_read_memory (pc + 1, buf, sizeof buf) == 0) | 
 | 	{ | 
 | 	  CORE_ADDR call_dest; | 
 |  | 
 | 	  call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order); | 
 | 	  bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest); | 
 | 	  if (s.minsym != NULL | 
 | 	      && s.minsym->linkage_name () != NULL | 
 | 	      && strcmp (s.minsym->linkage_name (), "__main") == 0) | 
 | 	    pc += 5; | 
 | 	} | 
 |     } | 
 |  | 
 |   return pc; | 
 | } | 
 |  | 
 | struct amd64_windows_frame_cache | 
 | { | 
 |   /* ImageBase for the module.  */ | 
 |   CORE_ADDR image_base; | 
 |  | 
 |   /* Function start and end rva.  */ | 
 |   CORE_ADDR start_rva; | 
 |   CORE_ADDR end_rva; | 
 |  | 
 |   /* Next instruction to be executed.  */ | 
 |   CORE_ADDR pc; | 
 |  | 
 |   /* Current sp.  */ | 
 |   CORE_ADDR sp; | 
 |  | 
 |   /* Address of saved integer and xmm registers.  */ | 
 |   CORE_ADDR prev_reg_addr[16]; | 
 |   CORE_ADDR prev_xmm_addr[16]; | 
 |  | 
 |   /* These two next fields are set only for machine info frames.  */ | 
 |  | 
 |   /* Likewise for RIP.  */ | 
 |   CORE_ADDR prev_rip_addr; | 
 |  | 
 |   /* Likewise for RSP.  */ | 
 |   CORE_ADDR prev_rsp_addr; | 
 |  | 
 |   /* Address of the previous frame.  */ | 
 |   CORE_ADDR prev_sp; | 
 | }; | 
 |  | 
 | /* Convert a Windows register number to gdb.  */ | 
 | static const enum amd64_regnum amd64_windows_w2gdb_regnum[] = | 
 | { | 
 |   AMD64_RAX_REGNUM, | 
 |   AMD64_RCX_REGNUM, | 
 |   AMD64_RDX_REGNUM, | 
 |   AMD64_RBX_REGNUM, | 
 |   AMD64_RSP_REGNUM, | 
 |   AMD64_RBP_REGNUM, | 
 |   AMD64_RSI_REGNUM, | 
 |   AMD64_RDI_REGNUM, | 
 |   AMD64_R8_REGNUM, | 
 |   AMD64_R9_REGNUM, | 
 |   AMD64_R10_REGNUM, | 
 |   AMD64_R11_REGNUM, | 
 |   AMD64_R12_REGNUM, | 
 |   AMD64_R13_REGNUM, | 
 |   AMD64_R14_REGNUM, | 
 |   AMD64_R15_REGNUM | 
 | }; | 
 |  | 
 | /* Return TRUE iff PC is the range of the function corresponding to | 
 |    CACHE.  */ | 
 |  | 
 | static int | 
 | pc_in_range (CORE_ADDR pc, const struct amd64_windows_frame_cache *cache) | 
 | { | 
 |   return (pc >= cache->image_base + cache->start_rva | 
 | 	  && pc < cache->image_base + cache->end_rva); | 
 | } | 
 |  | 
 | /* Try to recognize and decode an epilogue sequence. | 
 |  | 
 |    Return -1 if we fail to read the instructions for any reason. | 
 |    Return 1 if an epilogue sequence was recognized, 0 otherwise.  */ | 
 |  | 
 | static int | 
 | amd64_windows_frame_decode_epilogue (const frame_info_ptr &this_frame, | 
 | 				     struct amd64_windows_frame_cache *cache) | 
 | { | 
 |   /* According to MSDN an epilogue "must consist of either an add RSP,constant | 
 |      or lea RSP,constant[FPReg], followed by a series of zero or more 8-byte | 
 |      register pops and a return or a jmp". | 
 |  | 
 |      Furthermore, according to RtlVirtualUnwind, the complete list of | 
 |      epilog marker is: | 
 |      - ret                      [c3] | 
 |      - ret n                    [c2 imm16] | 
 |      - rep ret                  [f3 c3] | 
 |      - jmp imm8 | imm32         [eb rel8] or [e9 rel32] | 
 |      - jmp qword ptr imm32                 - not handled | 
 |      - rex.w jmp reg            [4X ff eY] | 
 |   */ | 
 |  | 
 |   CORE_ADDR pc = cache->pc; | 
 |   CORE_ADDR cur_sp = cache->sp; | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   gdb_byte op; | 
 |   gdb_byte rex; | 
 |  | 
 |   /* We don't care about the instruction deallocating the frame: | 
 |      if it hasn't been executed, the pc is still in the body, | 
 |      if it has been executed, the following epilog decoding will work.  */ | 
 |  | 
 |   /* First decode: | 
 |      -  pop reg                 [41 58-5f] or [58-5f].  */ | 
 |  | 
 |   while (1) | 
 |     { | 
 |       /* Read opcode. */ | 
 |       if (target_read_memory (pc, &op, 1) != 0) | 
 | 	return -1; | 
 |  | 
 |       if (op >= 0x40 && op <= 0x4f) | 
 | 	{ | 
 | 	  /* REX prefix.  */ | 
 | 	  rex = op; | 
 |  | 
 | 	  /* Read opcode. */ | 
 | 	  if (target_read_memory (pc + 1, &op, 1) != 0) | 
 | 	    return -1; | 
 | 	} | 
 |       else | 
 | 	rex = 0; | 
 |  | 
 |       if (op >= 0x58 && op <= 0x5f) | 
 | 	{ | 
 | 	  /* pop reg  */ | 
 | 	  gdb_byte reg = (op & 0x0f) | ((rex & 1) << 3); | 
 |  | 
 | 	  cache->prev_reg_addr[amd64_windows_w2gdb_regnum[reg]] = cur_sp; | 
 | 	  cur_sp += 8; | 
 | 	  pc += rex ? 2 : 1; | 
 | 	} | 
 |       else | 
 | 	break; | 
 |  | 
 |       /* Allow the user to break this loop.  This shouldn't happen as the | 
 | 	 number of consecutive pop should be small.  */ | 
 |       QUIT; | 
 |     } | 
 |  | 
 |   /* Then decode the marker.  */ | 
 |  | 
 |   /* Read opcode.  */ | 
 |   if (target_read_memory (pc, &op, 1) != 0) | 
 |     return -1; | 
 |  | 
 |   switch (op) | 
 |     { | 
 |     case 0xc3: | 
 |       /* Ret.  */ | 
 |       cache->prev_rip_addr = cur_sp; | 
 |       cache->prev_sp = cur_sp + 8; | 
 |       return 1; | 
 |  | 
 |     case 0xeb: | 
 |       { | 
 | 	/* jmp rel8  */ | 
 | 	gdb_byte rel8; | 
 | 	CORE_ADDR npc; | 
 |  | 
 | 	if (target_read_memory (pc + 1, &rel8, 1) != 0) | 
 | 	  return -1; | 
 | 	npc = pc + 2 + (signed char) rel8; | 
 |  | 
 | 	/* If the jump is within the function, then this is not a marker, | 
 | 	   otherwise this is a tail-call.  */ | 
 | 	return !pc_in_range (npc, cache); | 
 |       } | 
 |  | 
 |     case 0xec: | 
 |       { | 
 | 	/* jmp rel32  */ | 
 | 	gdb_byte rel32[4]; | 
 | 	CORE_ADDR npc; | 
 |  | 
 | 	if (target_read_memory (pc + 1, rel32, 4) != 0) | 
 | 	  return -1; | 
 | 	npc = pc + 5 + extract_signed_integer (rel32, 4, byte_order); | 
 |  | 
 | 	/* If the jump is within the function, then this is not a marker, | 
 | 	   otherwise this is a tail-call.  */ | 
 | 	return !pc_in_range (npc, cache); | 
 |       } | 
 |  | 
 |     case 0xc2: | 
 |       { | 
 | 	/* ret n  */ | 
 | 	gdb_byte imm16[2]; | 
 |  | 
 | 	if (target_read_memory (pc + 1, imm16, 2) != 0) | 
 | 	  return -1; | 
 | 	cache->prev_rip_addr = cur_sp; | 
 | 	cache->prev_sp = cur_sp | 
 | 	  + extract_unsigned_integer (imm16, 4, byte_order); | 
 | 	return 1; | 
 |       } | 
 |  | 
 |     case 0xf3: | 
 |       { | 
 | 	/* rep; ret  */ | 
 | 	gdb_byte op1; | 
 |  | 
 | 	if (target_read_memory (pc + 2, &op1, 1) != 0) | 
 | 	  return -1; | 
 | 	if (op1 != 0xc3) | 
 | 	  return 0; | 
 |  | 
 | 	cache->prev_rip_addr = cur_sp; | 
 | 	cache->prev_sp = cur_sp + 8; | 
 | 	return 1; | 
 |       } | 
 |  | 
 |     case 0x40: | 
 |     case 0x41: | 
 |     case 0x42: | 
 |     case 0x43: | 
 |     case 0x44: | 
 |     case 0x45: | 
 |     case 0x46: | 
 |     case 0x47: | 
 |     case 0x48: | 
 |     case 0x49: | 
 |     case 0x4a: | 
 |     case 0x4b: | 
 |     case 0x4c: | 
 |     case 0x4d: | 
 |     case 0x4e: | 
 |     case 0x4f: | 
 |       /* Got a REX prefix, read next byte.  */ | 
 |       rex = op; | 
 |       if (target_read_memory (pc + 1, &op, 1) != 0) | 
 | 	return -1; | 
 |  | 
 |       if (op == 0xff) | 
 | 	{ | 
 | 	  /* rex jmp reg  */ | 
 | 	  gdb_byte op1; | 
 |  | 
 | 	  if (target_read_memory (pc + 2, &op1, 1) != 0) | 
 | 	    return -1; | 
 | 	  return (op1 & 0xf8) == 0xe0; | 
 | 	} | 
 |       else | 
 | 	return 0; | 
 |  | 
 |     default: | 
 |       /* Not REX, so unknown.  */ | 
 |       return 0; | 
 |     } | 
 | } | 
 |  | 
 | /* Decode and execute unwind insns at UNWIND_INFO.  */ | 
 |  | 
 | static void | 
 | amd64_windows_frame_decode_insns (const frame_info_ptr &this_frame, | 
 | 				  struct amd64_windows_frame_cache *cache, | 
 | 				  CORE_ADDR unwind_info) | 
 | { | 
 |   CORE_ADDR save_addr = 0; | 
 |   CORE_ADDR cur_sp = cache->sp; | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   int first = 1; | 
 |  | 
 |   /* There are at least 3 possibilities to share an unwind info entry: | 
 |      1. Two different runtime_function entries (in .pdata) can point to the | 
 | 	same unwind info entry.  There is no such indication while unwinding, | 
 | 	so we don't really care about that case.  We suppose this scheme is | 
 | 	used to save memory when the unwind entries are exactly the same. | 
 |      2. Chained unwind_info entries, with no unwind codes (no prologue). | 
 | 	There is a major difference with the previous case: the pc range for | 
 | 	the function is different (in case 1, the pc range comes from the | 
 | 	runtime_function entry; in case 2, the pc range for the chained entry | 
 | 	comes from the first unwind entry).  Case 1 cannot be used instead as | 
 | 	the pc is not in the prologue.  This case is officially documented. | 
 | 	(There might be unwind code in the first unwind entry to handle | 
 | 	additional unwinding).  GCC (at least until gcc 5.0) doesn't chain | 
 | 	entries. | 
 |      3. Undocumented unwind info redirection.  Hard to know the exact purpose, | 
 | 	so it is considered as a memory optimization of case 2. | 
 |   */ | 
 |  | 
 |   if (unwind_info & 1) | 
 |     { | 
 |       /* Unofficially documented unwind info redirection, when UNWIND_INFO | 
 | 	 address is odd (http://www.codemachine.com/article_x64deepdive.html). | 
 |       */ | 
 |       struct external_pex64_runtime_function d; | 
 |  | 
 |       if (target_read_memory (cache->image_base + (unwind_info & ~1), | 
 | 			      (gdb_byte *) &d, sizeof (d)) != 0) | 
 | 	return; | 
 |  | 
 |       cache->start_rva | 
 | 	= extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); | 
 |       cache->end_rva | 
 | 	= extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); | 
 |       unwind_info | 
 | 	= extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); | 
 |     } | 
 |  | 
 |   while (1) | 
 |     { | 
 |       struct external_pex64_unwind_info ex_ui; | 
 |       /* There are at most 256 16-bit unwind insns.  */ | 
 |       gdb_byte insns[2 * 256]; | 
 |       gdb_byte *p; | 
 |       gdb_byte *end_insns; | 
 |       unsigned char codes_count; | 
 |       unsigned char frame_reg; | 
 |       CORE_ADDR start; | 
 |  | 
 |       /* Read and decode header.  */ | 
 |       if (target_read_memory (cache->image_base + unwind_info, | 
 | 			      (gdb_byte *) &ex_ui, sizeof (ex_ui)) != 0) | 
 | 	return; | 
 |  | 
 |       frame_debug_printf ("%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x", | 
 | 			  paddress (gdbarch, unwind_info), | 
 | 			  ex_ui.Version_Flags, ex_ui.SizeOfPrologue, | 
 | 			  ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset); | 
 |  | 
 |       /* Check version.  */ | 
 |       if (PEX64_UWI_VERSION (ex_ui.Version_Flags) != 1 | 
 | 	  && PEX64_UWI_VERSION (ex_ui.Version_Flags) != 2) | 
 | 	return; | 
 |  | 
 |       start = cache->image_base + cache->start_rva; | 
 |       if (first | 
 | 	  && !(cache->pc >= start && cache->pc < start + ex_ui.SizeOfPrologue)) | 
 | 	{ | 
 | 	  /* We want to detect if the PC points to an epilogue.  This needs | 
 | 	     to be checked only once, and an epilogue can be anywhere but in | 
 | 	     the prologue.  If so, the epilogue detection+decoding function is | 
 | 	     sufficient.  Otherwise, the unwinder will consider that the PC | 
 | 	     is in the body of the function and will need to decode unwind | 
 | 	     info.  */ | 
 | 	  if (amd64_windows_frame_decode_epilogue (this_frame, cache) == 1) | 
 | 	    return; | 
 |  | 
 | 	  /* Not in an epilog.  Clear possible side effects.  */ | 
 | 	  memset (cache->prev_reg_addr, 0, sizeof (cache->prev_reg_addr)); | 
 | 	} | 
 |  | 
 |       codes_count = ex_ui.CountOfCodes; | 
 |       frame_reg = PEX64_UWI_FRAMEREG (ex_ui.FrameRegisterOffset); | 
 |  | 
 |       if (frame_reg != 0) | 
 | 	{ | 
 | 	  /* According to msdn: | 
 | 	     If an FP reg is used, then any unwind code taking an offset must | 
 | 	     only be used after the FP reg is established in the prolog.  */ | 
 | 	  gdb_byte buf[8]; | 
 | 	  int frreg = amd64_windows_w2gdb_regnum[frame_reg]; | 
 |  | 
 | 	  get_frame_register (this_frame, frreg, buf); | 
 | 	  save_addr = extract_unsigned_integer (buf, 8, byte_order); | 
 |  | 
 | 	  frame_debug_printf ("   frame_reg=%s, val=%s", | 
 | 			      gdbarch_register_name (gdbarch, frreg), | 
 | 			      paddress (gdbarch, save_addr)); | 
 | 	} | 
 |  | 
 |       /* Read opcodes.  */ | 
 |       if (codes_count != 0 | 
 | 	  && target_read_memory (cache->image_base + unwind_info | 
 | 				 + sizeof (ex_ui), | 
 | 				 insns, codes_count * 2) != 0) | 
 | 	return; | 
 |  | 
 |       end_insns = &insns[codes_count * 2]; | 
 |       p = insns; | 
 |  | 
 |       /* Skip opcodes 6 of version 2.  This opcode is not documented.  */ | 
 |       if (PEX64_UWI_VERSION (ex_ui.Version_Flags) == 2) | 
 | 	{ | 
 | 	  for (; p < end_insns; p += 2) | 
 | 	    if (PEX64_UNWCODE_CODE (p[1]) != 6) | 
 | 	      break; | 
 | 	} | 
 |  | 
 |       for (; p < end_insns; p += 2) | 
 | 	{ | 
 | 	  int reg; | 
 |  | 
 | 	  /* Virtually execute the operation if the pc is after the | 
 | 	     corresponding instruction (that does matter in case of break | 
 | 	     within the prologue).  Note that for chained info (!first), the | 
 | 	     prologue has been fully executed.  */ | 
 | 	  if (cache->pc >= start + p[0] || cache->pc < start) | 
 | 	    { | 
 | 	      frame_debug_printf ("   op #%u: off=0x%02x, insn=0x%02x", | 
 | 				  (unsigned) (p - insns), p[0], p[1]); | 
 |  | 
 | 	      /* If there is no frame registers defined, the current value of | 
 | 		 rsp is used instead.  */ | 
 | 	      if (frame_reg == 0) | 
 | 		save_addr = cur_sp; | 
 |  | 
 | 	      reg = -1; | 
 |  | 
 | 	      switch (PEX64_UNWCODE_CODE (p[1])) | 
 | 		{ | 
 | 		case UWOP_PUSH_NONVOL: | 
 | 		  /* Push pre-decrements RSP.  */ | 
 | 		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; | 
 | 		  cache->prev_reg_addr[reg] = cur_sp; | 
 | 		  cur_sp += 8; | 
 | 		  break; | 
 | 		case UWOP_ALLOC_LARGE: | 
 | 		  if (PEX64_UNWCODE_INFO (p[1]) == 0) | 
 | 		    cur_sp += | 
 | 		      8 * extract_unsigned_integer (p + 2, 2, byte_order); | 
 | 		  else if (PEX64_UNWCODE_INFO (p[1]) == 1) | 
 | 		    cur_sp += extract_unsigned_integer (p + 2, 4, byte_order); | 
 | 		  else | 
 | 		    return; | 
 | 		  break; | 
 | 		case UWOP_ALLOC_SMALL: | 
 | 		  cur_sp += 8 + 8 * PEX64_UNWCODE_INFO (p[1]); | 
 | 		  break; | 
 | 		case UWOP_SET_FPREG: | 
 | 		  cur_sp = save_addr | 
 | 		    - PEX64_UWI_FRAMEOFF (ex_ui.FrameRegisterOffset) * 16; | 
 | 		  break; | 
 | 		case UWOP_SAVE_NONVOL: | 
 | 		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; | 
 | 		  cache->prev_reg_addr[reg] = save_addr | 
 | 		    + 8 * extract_unsigned_integer (p + 2, 2, byte_order); | 
 | 		  break; | 
 | 		case UWOP_SAVE_NONVOL_FAR: | 
 | 		  reg = amd64_windows_w2gdb_regnum[PEX64_UNWCODE_INFO (p[1])]; | 
 | 		  cache->prev_reg_addr[reg] = save_addr | 
 | 		    + 8 * extract_unsigned_integer (p + 2, 4, byte_order); | 
 | 		  break; | 
 | 		case UWOP_SAVE_XMM128: | 
 | 		  cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] = | 
 | 		    save_addr | 
 | 		    - 16 * extract_unsigned_integer (p + 2, 2, byte_order); | 
 | 		  break; | 
 | 		case UWOP_SAVE_XMM128_FAR: | 
 | 		  cache->prev_xmm_addr[PEX64_UNWCODE_INFO (p[1])] = | 
 | 		    save_addr | 
 | 		    - 16 * extract_unsigned_integer (p + 2, 4, byte_order); | 
 | 		  break; | 
 | 		case UWOP_PUSH_MACHFRAME: | 
 | 		  if (PEX64_UNWCODE_INFO (p[1]) == 0) | 
 | 		    { | 
 | 		      cache->prev_rip_addr = cur_sp + 0; | 
 | 		      cache->prev_rsp_addr = cur_sp + 24; | 
 | 		      cur_sp += 40; | 
 | 		    } | 
 | 		  else if (PEX64_UNWCODE_INFO (p[1]) == 1) | 
 | 		    { | 
 | 		      cache->prev_rip_addr = cur_sp + 8; | 
 | 		      cache->prev_rsp_addr = cur_sp + 32; | 
 | 		      cur_sp += 48; | 
 | 		    } | 
 | 		  else | 
 | 		    return; | 
 | 		  break; | 
 | 		default: | 
 | 		  return; | 
 | 		} | 
 |  | 
 | 	      /* Display address where the register was saved.  */ | 
 | 	      if (reg >= 0) | 
 | 		frame_debug_printf ("     [reg %s at %s]", | 
 | 				    gdbarch_register_name (gdbarch, reg), | 
 | 				    paddress (gdbarch, | 
 | 					      cache->prev_reg_addr[reg])); | 
 | 	    } | 
 |  | 
 | 	  /* Adjust with the length of the opcode.  */ | 
 | 	  switch (PEX64_UNWCODE_CODE (p[1])) | 
 | 	    { | 
 | 	    case UWOP_PUSH_NONVOL: | 
 | 	    case UWOP_ALLOC_SMALL: | 
 | 	    case UWOP_SET_FPREG: | 
 | 	    case UWOP_PUSH_MACHFRAME: | 
 | 	      break; | 
 | 	    case UWOP_ALLOC_LARGE: | 
 | 	      if (PEX64_UNWCODE_INFO (p[1]) == 0) | 
 | 		p += 2; | 
 | 	      else if (PEX64_UNWCODE_INFO (p[1]) == 1) | 
 | 		p += 4; | 
 | 	      else | 
 | 		return; | 
 | 	      break; | 
 | 	    case UWOP_SAVE_NONVOL: | 
 | 	    case UWOP_SAVE_XMM128: | 
 | 	      p += 2; | 
 | 	      break; | 
 | 	    case UWOP_SAVE_NONVOL_FAR: | 
 | 	    case UWOP_SAVE_XMM128_FAR: | 
 | 	      p += 4; | 
 | 	      break; | 
 | 	    default: | 
 | 	      return; | 
 | 	    } | 
 | 	} | 
 |       if (PEX64_UWI_FLAGS (ex_ui.Version_Flags) != UNW_FLAG_CHAININFO) | 
 | 	{ | 
 | 	  /* End of unwind info.  */ | 
 | 	  break; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* Read the chained unwind info.  */ | 
 | 	  struct external_pex64_runtime_function d; | 
 | 	  CORE_ADDR chain_vma; | 
 |  | 
 | 	  /* Not anymore the first entry.  */ | 
 | 	  first = 0; | 
 |  | 
 | 	  /* Stay aligned on word boundary.  */ | 
 | 	  chain_vma = cache->image_base + unwind_info | 
 | 	    + sizeof (ex_ui) + ((codes_count + 1) & ~1) * 2; | 
 |  | 
 | 	  if (target_read_memory (chain_vma, (gdb_byte *) &d, sizeof (d)) != 0) | 
 | 	    return; | 
 |  | 
 | 	  /* Decode begin/end.  This may be different from .pdata index, as | 
 | 	     an unwind info may be shared by several functions (in particular | 
 | 	     if many functions have the same prolog and handler.  */ | 
 | 	  cache->start_rva = | 
 | 	    extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); | 
 | 	  cache->end_rva = | 
 | 	    extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); | 
 | 	  unwind_info = | 
 | 	    extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); | 
 |  | 
 | 	  frame_debug_printf ("next in chain: unwind_data=%s, start_rva=%s, " | 
 | 			      "end_rva=%s", | 
 | 			      paddress (gdbarch, unwind_info), | 
 | 			      paddress (gdbarch, cache->start_rva), | 
 | 			      paddress (gdbarch, cache->end_rva)); | 
 | 	} | 
 |  | 
 |       /* Allow the user to break this loop.  */ | 
 |       QUIT; | 
 |     } | 
 |   /* PC is saved by the call.  */ | 
 |   if (cache->prev_rip_addr == 0) | 
 |     cache->prev_rip_addr = cur_sp; | 
 |   cache->prev_sp = cur_sp + 8; | 
 |  | 
 |   frame_debug_printf ("   prev_sp: %s, prev_pc @%s", | 
 | 		      paddress (gdbarch, cache->prev_sp), | 
 | 		      paddress (gdbarch, cache->prev_rip_addr)); | 
 | } | 
 |  | 
 | /* Find SEH unwind info for PC, returning 0 on success. | 
 |  | 
 |    UNWIND_INFO is set to the rva of unwind info address, IMAGE_BASE | 
 |    to the base address of the corresponding image, and START_RVA | 
 |    to the rva of the function containing PC.  */ | 
 |  | 
 | static int | 
 | amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc, | 
 | 				CORE_ADDR *unwind_info, | 
 | 				CORE_ADDR *image_base, | 
 | 				CORE_ADDR *start_rva, | 
 | 				CORE_ADDR *end_rva) | 
 | { | 
 |   struct obj_section *sec; | 
 |   pe_data_type *pe; | 
 |   IMAGE_DATA_DIRECTORY *dir; | 
 |   struct objfile *objfile; | 
 |   unsigned long lo, hi; | 
 |   CORE_ADDR base; | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |  | 
 |   /* Get the corresponding exception directory.  */ | 
 |   sec = find_pc_section (pc); | 
 |   if (sec == NULL) | 
 |     return -1; | 
 |   objfile = sec->objfile; | 
 |   pe = pe_data (sec->objfile->obfd); | 
 |   dir = &pe->pe_opthdr.DataDirectory[PE_EXCEPTION_TABLE]; | 
 |  | 
 |   base = pe->pe_opthdr.ImageBase + objfile->text_section_offset (); | 
 |   *image_base = base; | 
 |  | 
 |   /* Find the entry. | 
 |  | 
 |      Note: This does not handle dynamically added entries (for JIT | 
 |      engines).  For this, we would need to ask the kernel directly, | 
 |      which means getting some info from the native layer.  For the | 
 |      rest of the code, however, it's probably faster to search | 
 |      the entry ourselves.  */ | 
 |   lo = 0; | 
 |   hi = dir->Size / sizeof (struct external_pex64_runtime_function); | 
 |   *unwind_info = 0; | 
 |   while (lo <= hi) | 
 |     { | 
 |       unsigned long mid = lo + (hi - lo) / 2; | 
 |       struct external_pex64_runtime_function d; | 
 |       CORE_ADDR sa, ea; | 
 |  | 
 |       if (target_read_memory (base + dir->VirtualAddress + mid * sizeof (d), | 
 | 			      (gdb_byte *) &d, sizeof (d)) != 0) | 
 | 	return -1; | 
 |  | 
 |       sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); | 
 |       ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); | 
 |       if (pc < base + sa) | 
 | 	hi = mid - 1; | 
 |       else if (pc >= base + ea) | 
 | 	lo = mid + 1; | 
 |       else if (pc >= base + sa && pc < base + ea) | 
 | 	{ | 
 | 	  /* Got it.  */ | 
 | 	  *start_rva = sa; | 
 | 	  *end_rva = ea; | 
 | 	  *unwind_info = | 
 | 	    extract_unsigned_integer (d.rva_UnwindData, 4, byte_order); | 
 | 	  break; | 
 | 	} | 
 |       else | 
 | 	break; | 
 |     } | 
 |  | 
 |   frame_debug_printf ("image_base=%s, unwind_data=%s", | 
 | 		      paddress (gdbarch, base), | 
 | 		      paddress (gdbarch, *unwind_info)); | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | /* Fill THIS_CACHE using the native amd64-windows unwinding data | 
 |    for THIS_FRAME.  */ | 
 |  | 
 | static struct amd64_windows_frame_cache * | 
 | amd64_windows_frame_cache (const frame_info_ptr &this_frame, void **this_cache) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |   struct amd64_windows_frame_cache *cache; | 
 |   gdb_byte buf[8]; | 
 |   CORE_ADDR pc; | 
 |   CORE_ADDR unwind_info = 0; | 
 |  | 
 |   if (*this_cache) | 
 |     return (struct amd64_windows_frame_cache *) *this_cache; | 
 |  | 
 |   cache = FRAME_OBSTACK_ZALLOC (struct amd64_windows_frame_cache); | 
 |   *this_cache = cache; | 
 |  | 
 |   /* Get current PC and SP.  */ | 
 |   pc = get_frame_pc (this_frame); | 
 |   get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); | 
 |   cache->sp = extract_unsigned_integer (buf, 8, byte_order); | 
 |   cache->pc = pc; | 
 |  | 
 |   /* If we can't find the unwind info, keep trying as though this is a | 
 |      leaf function.  This situation can happen when PC==0, see | 
 |      https://sourceware.org/bugzilla/show_bug.cgi?id=30255.  */ | 
 |   if (amd64_windows_find_unwind_info (gdbarch, pc, &unwind_info, | 
 | 				      &cache->image_base, | 
 | 				      &cache->start_rva, | 
 | 				      &cache->end_rva) | 
 |       || unwind_info == 0) | 
 |     { | 
 |       /* Assume a leaf function.  */ | 
 |       cache->prev_sp = cache->sp + 8; | 
 |       cache->prev_rip_addr = cache->sp; | 
 |     } | 
 |   else | 
 |     { | 
 |       /* Decode unwind insns to compute saved addresses.  */ | 
 |       amd64_windows_frame_decode_insns (this_frame, cache, unwind_info); | 
 |     } | 
 |   return cache; | 
 | } | 
 |  | 
 | /* Implement the "prev_register" method of struct frame_unwind | 
 |    using the standard Windows x64 SEH info.  */ | 
 |  | 
 | static struct value * | 
 | amd64_windows_frame_prev_register (const frame_info_ptr &this_frame, | 
 | 				   void **this_cache, int regnum) | 
 | { | 
 |   struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
 |   struct amd64_windows_frame_cache *cache = | 
 |     amd64_windows_frame_cache (this_frame, this_cache); | 
 |   CORE_ADDR prev; | 
 |  | 
 |   frame_debug_printf ("%s for sp=%s", | 
 | 		      gdbarch_register_name (gdbarch, regnum), | 
 | 		      paddress (gdbarch, cache->prev_sp)); | 
 |  | 
 |   if (regnum >= AMD64_XMM0_REGNUM && regnum <= AMD64_XMM0_REGNUM + 15) | 
 |       prev = cache->prev_xmm_addr[regnum - AMD64_XMM0_REGNUM]; | 
 |   else if (regnum == AMD64_RSP_REGNUM) | 
 |     { | 
 |       prev = cache->prev_rsp_addr; | 
 |       if (prev == 0) | 
 | 	return frame_unwind_got_constant (this_frame, regnum, cache->prev_sp); | 
 |     } | 
 |   else if (regnum >= AMD64_RAX_REGNUM && regnum <= AMD64_R15_REGNUM) | 
 |     prev = cache->prev_reg_addr[regnum - AMD64_RAX_REGNUM]; | 
 |   else if (regnum == AMD64_RIP_REGNUM) | 
 |     prev = cache->prev_rip_addr; | 
 |   else | 
 |     prev = 0; | 
 |  | 
 |   if (prev != 0) | 
 |     frame_debug_printf ("  -> at %s", paddress (gdbarch, prev)); | 
 |  | 
 |   if (prev) | 
 |     { | 
 |       /* Register was saved.  */ | 
 |       return frame_unwind_got_memory (this_frame, regnum, prev); | 
 |     } | 
 |   else | 
 |     { | 
 |       /* Register is either volatile or not modified.  */ | 
 |       return frame_unwind_got_register (this_frame, regnum, regnum); | 
 |     } | 
 | } | 
 |  | 
 | /* Implement the "this_id" method of struct frame_unwind using | 
 |    the standard Windows x64 SEH info.  */ | 
 |  | 
 | static void | 
 | amd64_windows_frame_this_id (const frame_info_ptr &this_frame, void **this_cache, | 
 | 		   struct frame_id *this_id) | 
 | { | 
 |   struct amd64_windows_frame_cache *cache = | 
 |     amd64_windows_frame_cache (this_frame, this_cache); | 
 |  | 
 |   *this_id = frame_id_build (cache->prev_sp, | 
 | 			     cache->image_base + cache->start_rva); | 
 | } | 
 |  | 
 | /* Windows x64 SEH unwinder.  */ | 
 |  | 
 | static const struct frame_unwind amd64_windows_frame_unwind = | 
 | { | 
 |   "amd64 windows", | 
 |   NORMAL_FRAME, | 
 |   default_frame_unwind_stop_reason, | 
 |   &amd64_windows_frame_this_id, | 
 |   &amd64_windows_frame_prev_register, | 
 |   NULL, | 
 |   default_frame_sniffer | 
 | }; | 
 |  | 
 | /* Implement the "skip_prologue" gdbarch method.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_windows_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) | 
 | { | 
 |   CORE_ADDR func_addr; | 
 |   CORE_ADDR unwind_info = 0; | 
 |   CORE_ADDR image_base, start_rva, end_rva; | 
 |   struct external_pex64_unwind_info ex_ui; | 
 |  | 
 |   /* Use prologue size from unwind info.  */ | 
 |   if (amd64_windows_find_unwind_info (gdbarch, pc, &unwind_info, | 
 | 				      &image_base, &start_rva, &end_rva) == 0) | 
 |     { | 
 |       if (unwind_info == 0) | 
 | 	{ | 
 | 	  /* Leaf function.  */ | 
 | 	  return pc; | 
 | 	} | 
 |       else if (target_read_memory (image_base + unwind_info, | 
 | 				   (gdb_byte *) &ex_ui, sizeof (ex_ui)) == 0 | 
 | 	       && PEX64_UWI_VERSION (ex_ui.Version_Flags) == 1) | 
 | 	return std::max (pc, image_base + start_rva + ex_ui.SizeOfPrologue); | 
 |     } | 
 |  | 
 |   /* See if we can determine the end of the prologue via the symbol | 
 |      table.  If so, then return either the PC, or the PC after | 
 |      the prologue, whichever is greater.  */ | 
 |   if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) | 
 |     { | 
 |       CORE_ADDR post_prologue_pc | 
 | 	= skip_prologue_using_sal (gdbarch, func_addr); | 
 |  | 
 |       if (post_prologue_pc != 0) | 
 | 	return std::max (pc, post_prologue_pc); | 
 |     } | 
 |  | 
 |   return pc; | 
 | } | 
 |  | 
 | /* Check Win64 DLL jmp trampolines and find jump destination.  */ | 
 |  | 
 | static CORE_ADDR | 
 | amd64_windows_skip_trampoline_code (const frame_info_ptr &frame, CORE_ADDR pc) | 
 | { | 
 |   CORE_ADDR destination = 0; | 
 |   struct gdbarch *gdbarch = get_frame_arch (frame); | 
 |   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
 |  | 
 |   /* Check for jmp *<offset>(%rip) (jump near, absolute indirect (/4)).  */ | 
 |   if (pc && read_memory_unsigned_integer (pc, 2, byte_order) == 0x25ff) | 
 |     { | 
 |       /* Get opcode offset and see if we can find a reference in our data.  */ | 
 |       ULONGEST offset | 
 | 	= read_memory_unsigned_integer (pc + 2, 4, byte_order); | 
 |  | 
 |       /* Get address of function pointer at end of pc.  */ | 
 |       CORE_ADDR indirect_addr = pc + offset + 6; | 
 |  | 
 |       struct minimal_symbol *indsym | 
 | 	= (indirect_addr | 
 | 	   ? lookup_minimal_symbol_by_pc (indirect_addr).minsym | 
 | 	   : NULL); | 
 |       const char *symname = indsym ? indsym->linkage_name () : NULL; | 
 |  | 
 |       if (symname) | 
 | 	{ | 
 | 	  if (startswith (symname, "__imp_") | 
 | 	      || startswith (symname, "_imp_")) | 
 | 	    destination | 
 | 	      = read_memory_unsigned_integer (indirect_addr, 8, byte_order); | 
 | 	} | 
 |     } | 
 |  | 
 |   return destination; | 
 | } | 
 |  | 
 | /* Implement the "auto_wide_charset" gdbarch method.  */ | 
 |  | 
 | static const char * | 
 | amd64_windows_auto_wide_charset (void) | 
 | { | 
 |   return "UTF-16"; | 
 | } | 
 |  | 
 | /* Common parts for gdbarch initialization for Windows and Cygwin on AMD64.  */ | 
 |  | 
 | static void | 
 | amd64_windows_init_abi_common (gdbarch_info info, struct gdbarch *gdbarch) | 
 | { | 
 |   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch); | 
 |  | 
 |   /* The dwarf2 unwinder (appended very early by i386_gdbarch_init) is | 
 |      preferred over the SEH one.  The reasons are: | 
 |      - binaries without SEH but with dwarf2 debug info are correctly handled | 
 |        (although they aren't ABI compliant, gcc before 4.7 didn't emit SEH | 
 |        info). | 
 |      - dwarf3 DW_OP_call_frame_cfa is correctly handled (it can only be | 
 |        handled if the dwarf2 unwinder is used). | 
 |  | 
 |     The call to amd64_init_abi appends default unwinders, that aren't | 
 |     compatible with the SEH one. | 
 |   */ | 
 |   frame_unwind_append_unwinder (gdbarch, &amd64_windows_frame_unwind); | 
 |  | 
 |   amd64_init_abi (info, gdbarch, | 
 | 		  amd64_target_description (X86_XSTATE_SSE_MASK, false)); | 
 |  | 
 |   /* Function calls.  */ | 
 |   set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call); | 
 |   set_gdbarch_return_value_as_value (gdbarch, amd64_windows_return_value); | 
 |   set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue); | 
 |   set_gdbarch_skip_trampoline_code (gdbarch, | 
 | 				    amd64_windows_skip_trampoline_code); | 
 |  | 
 |   set_gdbarch_skip_prologue (gdbarch, amd64_windows_skip_prologue); | 
 |  | 
 |   tdep->gregset_reg_offset = amd64_windows_gregset_reg_offset; | 
 |   tdep->gregset_num_regs = ARRAY_SIZE (amd64_windows_gregset_reg_offset); | 
 |   tdep->sizeof_gregset = AMD64_WINDOWS_SIZEOF_GREGSET; | 
 |   tdep->sizeof_fpregset = 0; | 
 |  | 
 |   /* Core file support.  */ | 
 |   set_gdbarch_core_xfer_shared_libraries | 
 |     (gdbarch, windows_core_xfer_shared_libraries); | 
 |   set_gdbarch_core_pid_to_str (gdbarch, windows_core_pid_to_str); | 
 |  | 
 |   set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset); | 
 | } | 
 |  | 
 | /* gdbarch initialization for Windows on AMD64.  */ | 
 |  | 
 | static void | 
 | amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | 
 | { | 
 |   amd64_windows_init_abi_common (info, gdbarch); | 
 |   windows_init_abi (info, gdbarch); | 
 |  | 
 |   /* On Windows, "long"s are only 32bit.  */ | 
 |   set_gdbarch_long_bit (gdbarch, 32); | 
 | } | 
 |  | 
 | /* Sigwrapper unwinder instruction patterns for AMD64.  */ | 
 |  | 
 | static const gdb_byte amd64_sigbe_bytes[] = { | 
 |   0x49, 0xc7, 0xc3, 0xf8, 0xff, 0xff, 0xff,	/* movq $-8,%r11 */ | 
 |   0x4d, 0x0f, 0xc1, 0x9a,			/* xaddq %r11,$tls::stackptr(%r10) */ | 
 |   /* 4 bytes for tls::stackptr operand.  */ | 
 | }; | 
 |  | 
 | static const gdb_byte amd64_sigdelayed_bytes[] = { | 
 |   0x49, 0xc7, 0xc3, 0xf8, 0xff, 0xff, 0xff,	/* movq $-8,%r11 */ | 
 |   0x4d, 0x0f, 0xc1, 0x9c, 0x24,			/* xaddq %r11,$tls::stackptr(%r12) */ | 
 |   /* 4 bytes for tls::stackptr operand.  */ | 
 | }; | 
 |  | 
 | static const gdb::array_view<const gdb_byte> amd64_sig_patterns[] { | 
 |   { amd64_sigbe_bytes }, | 
 |   { amd64_sigdelayed_bytes }, | 
 | }; | 
 |  | 
 | /* The sigwrapper unwinder on AMD64.  */ | 
 |  | 
 | static const cygwin_sigwrapper_frame_unwind | 
 |   amd64_cygwin_sigwrapper_frame_unwind (amd64_sig_patterns); | 
 |  | 
 | /* gdbarch initialization for Cygwin on AMD64.  */ | 
 |  | 
 | static void | 
 | amd64_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | 
 | { | 
 |   frame_unwind_append_unwinder (gdbarch, &amd64_cygwin_sigwrapper_frame_unwind); | 
 |  | 
 |   amd64_windows_init_abi_common (info, gdbarch); | 
 |   cygwin_init_abi (info, gdbarch); | 
 | } | 
 |  | 
 | static gdb_osabi | 
 | amd64_windows_osabi_sniffer (bfd *abfd) | 
 | { | 
 |   const char *target_name = bfd_get_target (abfd); | 
 |  | 
 |   if (!streq (target_name, "pei-x86-64")) | 
 |     return GDB_OSABI_UNKNOWN; | 
 |  | 
 |   if (is_linked_with_cygwin_dll (abfd)) | 
 |     return GDB_OSABI_CYGWIN; | 
 |  | 
 |   return GDB_OSABI_WINDOWS; | 
 | } | 
 |  | 
 | static enum gdb_osabi | 
 | amd64_cygwin_core_osabi_sniffer (bfd *abfd) | 
 | { | 
 |   const char *target_name = bfd_get_target (abfd); | 
 |  | 
 |   /* Cygwin uses elf core dumps.  Do not claim all ELF executables, | 
 |      check whether there is a .reg section of proper size.  */ | 
 |   if (strcmp (target_name, "elf64-x86-64") == 0) | 
 |     { | 
 |       asection *section = bfd_get_section_by_name (abfd, ".reg"); | 
 |       if (section != nullptr | 
 | 	  && bfd_section_size (section) == AMD64_WINDOWS_SIZEOF_GREGSET) | 
 | 	return GDB_OSABI_CYGWIN; | 
 |     } | 
 |  | 
 |   return GDB_OSABI_UNKNOWN; | 
 | } | 
 |  | 
 | void _initialize_amd64_windows_tdep (); | 
 | void | 
 | _initialize_amd64_windows_tdep () | 
 | { | 
 |   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_WINDOWS, | 
 | 			  amd64_windows_init_abi); | 
 |   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN, | 
 | 			  amd64_cygwin_init_abi); | 
 |  | 
 |   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour, | 
 | 				  amd64_windows_osabi_sniffer); | 
 |  | 
 |   /* Cygwin uses elf core dumps.  */ | 
 |   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, | 
 | 				  amd64_cygwin_core_osabi_sniffer); | 
 |  | 
 | } |