gdb/amd64-windows-tdep.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
- #include "defs.h"
- #include "osabi.h"
- #include "amd64-tdep.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"
- static int amd64_windows_dummy_call_integer_regs[] =
- {
- AMD64_RCX_REGNUM,
- AMD64_RDX_REGNUM,
- AMD64_R8_REGNUM,
- AMD64_R9_REGNUM
- };
- static int
- amd64_windows_passed_by_integer_register (struct type *type)
- {
- switch (TYPE_CODE (type))
- {
- 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_STRUCT:
- case TYPE_CODE_UNION:
- return (TYPE_LENGTH (type) == 1
- || TYPE_LENGTH (type) == 2
- || TYPE_LENGTH (type) == 4
- || TYPE_LENGTH (type) == 8);
- default:
- return 0;
- }
- }
- static int
- amd64_windows_passed_by_xmm_register (struct type *type)
- {
- return ((TYPE_CODE (type) == TYPE_CODE_FLT
- || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- && (TYPE_LENGTH (type) == 4 || TYPE_LENGTH (type) == 8));
- }
- 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;
- }
- 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 (value_type (args[i])))
- {
- struct type *type = value_type (args[i]);
- const gdb_byte *valbuf = value_contents (args[i]);
- const int len = TYPE_LENGTH (type);
-
- sp -= len;
- sp &= ~0xf;
- write_memory (sp, valbuf, len);
- args[i]
- = value_addr (value_from_contents_and_address (type, valbuf, sp));
- }
- return sp;
- }
- static void
- amd64_windows_store_arg_in_reg (struct regcache *regcache,
- struct value *arg, int regno)
- {
- struct type *type = value_type (arg);
- const gdb_byte *valbuf = value_contents (arg);
- gdb_byte buf[8];
- gdb_assert (TYPE_LENGTH (type) <= 8);
- memset (buf, 0, sizeof buf);
- memcpy (buf, valbuf, min (TYPE_LENGTH (type), 8));
- regcache_cooked_write (regcache, regno, buf);
- }
- static CORE_ADDR
- amd64_windows_push_arguments (struct regcache *regcache, int nargs,
- struct value **args, CORE_ADDR sp,
- int struct_return)
- {
- int reg_idx = 0;
- int i;
- struct value **stack_args = alloca (nargs * sizeof (struct value *));
- int num_stack_args = 0;
- int num_elements = 0;
- int element = 0;
-
- {
- struct value **args1 = alloca (nargs * sizeof (struct value *));
- memcpy (args1, args, nargs * sizeof (struct value *));
- sp = amd64_windows_adjust_args_passed_by_pointer (args1, nargs, sp);
- args = args1;
- }
-
- if (struct_return)
- reg_idx++;
- for (i = 0; i < nargs; i++)
- {
- struct type *type = value_type (args[i]);
- int len = TYPE_LENGTH (type);
- 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);
-
- 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];
- }
- }
-
- sp -= num_elements * 8;
- sp &= ~0xf;
-
- for (i = 0; i < num_stack_args; i++)
- {
- struct type *type = value_type (stack_args[i]);
- const gdb_byte *valbuf = value_contents (stack_args[i]);
- write_memory (sp + element * 8, valbuf, TYPE_LENGTH (type));
- element += ((TYPE_LENGTH (type) + 7) / 8);
- }
- return sp;
- }
- 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, int struct_return, CORE_ADDR struct_addr)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- gdb_byte buf[8];
-
- sp = amd64_windows_push_arguments (regcache, nargs, args, sp,
- struct_return);
-
- if (struct_return)
- {
-
- const int arg_regnum = amd64_windows_dummy_call_integer_regs[0];
- store_unsigned_integer (buf, 8, byte_order, struct_addr);
- regcache_cooked_write (regcache, arg_regnum, buf);
- }
-
- sp -= ARRAY_SIZE (amd64_windows_dummy_call_integer_regs) * 8;
-
- sp -= 8;
- store_unsigned_integer (buf, 8, byte_order, bp_addr);
- write_memory (sp, buf, 8);
-
- store_unsigned_integer (buf, 8, byte_order, sp);
- regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
-
- regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
- return sp + 16;
- }
- static enum return_value_convention
- amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
- struct type *type, struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- int len = TYPE_LENGTH (type);
- int regnum = -1;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_FLT:
- case TYPE_CODE_DECFLOAT:
-
- if (len == 4 || len == 8 || len == 16)
- regnum = AMD64_XMM0_REGNUM;
- break;
- default:
-
- if (len == 1 || len == 2 || len == 4 || len == 8)
- regnum = AMD64_RAX_REGNUM;
- break;
- }
- if (regnum < 0)
- {
-
- if (readbuf)
- {
- ULONGEST addr;
- regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
- read_memory (addr, readbuf, TYPE_LENGTH (type));
- }
- return RETURN_VALUE_ABI_RETURNS_ADDRESS;
- }
- else
- {
-
- if (readbuf)
- regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
- if (writebuf)
- regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- }
- 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)
- {
- struct bound_minimal_symbol s;
- CORE_ADDR call_dest;
- call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
- s = lookup_minimal_symbol_by_pc (call_dest);
- if (s.minsym != NULL
- && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
- && strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__main") == 0)
- pc += 5;
- }
- }
- return pc;
- }
- struct amd64_windows_frame_cache
- {
-
- CORE_ADDR image_base;
-
- CORE_ADDR start_rva;
- CORE_ADDR end_rva;
-
- CORE_ADDR pc;
-
- CORE_ADDR sp;
-
- CORE_ADDR prev_reg_addr[16];
- CORE_ADDR prev_xmm_addr[16];
-
-
- CORE_ADDR prev_rip_addr;
-
- CORE_ADDR prev_rsp_addr;
-
- CORE_ADDR prev_sp;
- };
- 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
- };
- 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);
- }
- static int
- amd64_windows_frame_decode_epilogue (struct frame_info *this_frame,
- struct amd64_windows_frame_cache *cache)
- {
-
- 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;
-
-
- while (1)
- {
-
- if (target_read_memory (pc, &op, 1) != 0)
- return -1;
- if (op >= 0x40 && op <= 0x4f)
- {
-
- rex = op;
-
- if (target_read_memory (pc + 1, &op, 1) != 0)
- return -1;
- }
- else
- rex = 0;
- if (op >= 0x58 && op <= 0x5f)
- {
-
- gdb_byte reg = (op & 0x0f) | ((rex & 1) << 3);
- cache->prev_reg_addr[amd64_windows_w2gdb_regnum[reg]] = cur_sp;
- cur_sp += 8;
- }
- else
- break;
-
- QUIT;
- }
-
-
- if (target_read_memory (pc, &op, 1) != 0)
- return -1;
- switch (op)
- {
- case 0xc3:
-
- cache->prev_rip_addr = cur_sp;
- cache->prev_sp = cur_sp + 8;
- return 1;
- case 0xeb:
- {
-
- gdb_byte rel8;
- CORE_ADDR npc;
- if (target_read_memory (pc + 1, &rel8, 1) != 0)
- return -1;
- npc = pc + 2 + (signed char) rel8;
-
- return !pc_in_range (npc, cache);
- }
- case 0xec:
- {
-
- 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);
-
- return !pc_in_range (npc, cache);
- }
- case 0xc2:
- {
-
- 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:
- {
-
- 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:
-
- rex = op;
- if (target_read_memory (pc + 1, &op, 1) != 0)
- return -1;
- if (op == 0xff)
- {
-
- gdb_byte op1;
- unsigned int reg;
- gdb_byte buf[8];
- if (target_read_memory (pc + 2, &op1, 1) != 0)
- return -1;
- return (op1 & 0xf8) == 0xe0;
- }
- else
- return 0;
- default:
-
- return 0;
- }
- }
- static void
- amd64_windows_frame_decode_insns (struct frame_info *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 j;
- for (j = 0; ; j++)
- {
- struct external_pex64_unwind_info ex_ui;
-
- gdb_byte insns[2 * 256];
- gdb_byte *p;
- gdb_byte *end_insns;
- unsigned char codes_count;
- unsigned char frame_reg;
- unsigned char frame_off;
-
- if (target_read_memory (cache->image_base + unwind_info,
- (gdb_byte *) &ex_ui, sizeof (ex_ui)) != 0)
- return;
- if (frame_debug)
- fprintf_unfiltered
- (gdb_stdlog,
- "amd64_windows_frame_decodes_insn: "
- "%s: ver: %02x, plgsz: %02x, cnt: %02x, frame: %02x\n",
- paddress (gdbarch, unwind_info),
- ex_ui.Version_Flags, ex_ui.SizeOfPrologue,
- ex_ui.CountOfCodes, ex_ui.FrameRegisterOffset);
-
- if (PEX64_UWI_VERSION (ex_ui.Version_Flags) != 1
- && PEX64_UWI_VERSION (ex_ui.Version_Flags) != 2)
- return;
- if (j == 0
- && (cache->pc >=
- cache->image_base + cache->start_rva + ex_ui.SizeOfPrologue))
- {
-
- if (amd64_windows_frame_decode_epilogue (this_frame, cache) == 1)
- return;
-
- 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)
- {
-
- 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);
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog, " frame_reg=%s, val=%s\n",
- gdbarch_register_name (gdbarch, frreg),
- paddress (gdbarch, save_addr));
- }
-
- 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;
-
- 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;
- if (frame_debug)
- fprintf_unfiltered
- (gdb_stdlog, " op #%u: off=0x%02x, insn=0x%02x\n",
- (unsigned) (p - insns), p[0], p[1]);
-
- if (cache->pc >= cache->image_base + cache->start_rva + p[0])
- {
-
- if (frame_reg == 0)
- save_addr = cur_sp;
- switch (PEX64_UNWCODE_CODE (p[1]))
- {
- case UWOP_PUSH_NONVOL:
-
- 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;
- }
- }
-
- 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)
- break;
- else
- {
-
- struct external_pex64_runtime_function d;
- CORE_ADDR chain_vma;
- 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;
- 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);
- if (frame_debug)
- fprintf_unfiltered
- (gdb_stdlog,
- "amd64_windows_frame_decodes_insn (next in chain):"
- " unwind_data=%s, start_rva=%s, end_rva=%s\n",
- paddress (gdbarch, unwind_info),
- paddress (gdbarch, cache->start_rva),
- paddress (gdbarch, cache->end_rva));
- }
-
- QUIT;
- }
-
- if (cache->prev_rip_addr == 0)
- cache->prev_rip_addr = cur_sp;
- cache->prev_sp = cur_sp + 8;
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog, " prev_sp: %s, prev_pc @%s\n",
- paddress (gdbarch, cache->prev_sp),
- paddress (gdbarch, cache->prev_rip_addr));
- }
- 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);
-
- 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
- + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- *image_base = base;
-
- 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)
- {
-
- *start_rva = sa;
- *end_rva = ea;
- *unwind_info =
- extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);
- break;
- }
- else
- break;
- }
- if (frame_debug)
- fprintf_unfiltered
- (gdb_stdlog,
- "amd64_windows_find_unwind_data: image_base=%s, unwind_data=%s\n",
- paddress (gdbarch, base), paddress (gdbarch, *unwind_info));
- if (*unwind_info & 1)
- {
-
- struct external_pex64_runtime_function d;
- CORE_ADDR sa, ea;
- if (target_read_memory (base + (*unwind_info & ~1),
- (gdb_byte *) &d, sizeof (d)) != 0)
- return -1;
- *start_rva =
- extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
- *end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
- *unwind_info =
- extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);
- }
- return 0;
- }
- static struct amd64_windows_frame_cache *
- amd64_windows_frame_cache (struct frame_info *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];
- struct obj_section *sec;
- pe_data_type *pe;
- IMAGE_DATA_DIRECTORY *dir;
- CORE_ADDR image_base;
- CORE_ADDR pc;
- struct objfile *objfile;
- unsigned long lo, hi;
- CORE_ADDR unwind_info = 0;
- if (*this_cache)
- return *this_cache;
- cache = FRAME_OBSTACK_ZALLOC (struct amd64_windows_frame_cache);
- *this_cache = cache;
-
- 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 (amd64_windows_find_unwind_info (gdbarch, pc, &unwind_info,
- &cache->image_base,
- &cache->start_rva,
- &cache->end_rva))
- return cache;
- if (unwind_info == 0)
- {
-
- cache->prev_sp = cache->sp + 8;
- cache->prev_rip_addr = cache->sp;
- }
- else
- {
-
- amd64_windows_frame_decode_insns (this_frame, cache, unwind_info);
- }
- return cache;
- }
- static struct value *
- amd64_windows_frame_prev_register (struct frame_info *this_frame,
- void **this_cache, int regnum)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct amd64_windows_frame_cache *cache =
- amd64_windows_frame_cache (this_frame, this_cache);
- struct value *val;
- CORE_ADDR prev;
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog,
- "amd64_windows_frame_prev_register %s for sp=%s\n",
- 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 && frame_debug)
- fprintf_unfiltered (gdb_stdlog, " -> at %s\n", paddress (gdbarch, prev));
- if (prev)
- {
-
- return frame_unwind_got_memory (this_frame, regnum, prev);
- }
- else
- {
-
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- }
- static void
- amd64_windows_frame_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- 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);
- }
- static const struct frame_unwind amd64_windows_frame_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- &amd64_windows_frame_this_id,
- &amd64_windows_frame_prev_register,
- NULL,
- default_frame_sniffer
- };
- 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;
-
- if (amd64_windows_find_unwind_info (gdbarch, pc, &unwind_info,
- &image_base, &start_rva, &end_rva) == 0)
- {
- if (unwind_info == 0)
- {
-
- 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 max (pc, image_base + start_rva + ex_ui.SizeOfPrologue);
- }
-
- 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 max (pc, post_prologue_pc);
- }
- return pc;
- }
- static CORE_ADDR
- amd64_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
- {
- CORE_ADDR destination = 0;
- struct gdbarch *gdbarch = get_frame_arch (frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
- if (pc && read_memory_unsigned_integer (pc, 2, byte_order) == 0x25ff)
- {
-
- ULONGEST offset
- = read_memory_unsigned_integer (pc + 2, 4, byte_order);
-
- 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 ? MSYMBOL_LINKAGE_NAME (indsym) : NULL;
- if (symname)
- {
- if (strncmp (symname, "__imp_", 6) == 0
- || strncmp (symname, "_imp_", 5) == 0)
- destination
- = read_memory_unsigned_integer (indirect_addr, 8, byte_order);
- }
- }
- return destination;
- }
- static const char *
- amd64_windows_auto_wide_charset (void)
- {
- return "UTF-16";
- }
- static void
- amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- frame_unwind_append_unwinder (gdbarch, &amd64_windows_frame_unwind);
- amd64_init_abi (info, gdbarch);
- windows_init_abi (info, gdbarch);
-
- set_gdbarch_long_bit (gdbarch, 32);
-
- set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
- set_gdbarch_return_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);
- set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset);
- }
- extern initialize_file_ftype _initialize_amd64_windows_tdep;
- void
- _initialize_amd64_windows_tdep (void)
- {
- gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
- amd64_windows_init_abi);
- }