X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Famd64-tdep.c;h=a26dca43372af7fb9ffbbbfbf6fbc91e99965d65;hb=05c0465e16a5e2db92f8975aebf2bb5aacb1c542;hp=54b17236db972b428e95eece7578ca5d70d2d2da;hpb=05d1431c1e0a4ecf30462109f5fb9876d78b7b4a;p=binutils-gdb.git diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 54b17236db9..a26dca43372 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2001-2013 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -38,12 +37,18 @@ #include "symfile.h" #include "disasm.h" #include "gdb_assert.h" - +#include "exceptions.h" #include "amd64-tdep.h" #include "i387-tdep.h" #include "features/i386/amd64.c" #include "features/i386/amd64-avx.c" +#include "features/i386/amd64-mpx.c" +#include "features/i386/x32.c" +#include "features/i386/x32-avx.c" + +#include "ax.h" +#include "ax-gdb.h" /* Note that the AMD64 architecture was previously known as x86-64. The latter is (forever) engraved into the canonical system name as @@ -88,15 +93,9 @@ static const char *amd64_ymmh_names[] = "ymm12h", "ymm13h", "ymm14h", "ymm15h" }; -/* The registers used to pass integer arguments during a function call. */ -static int amd64_dummy_call_integer_regs[] = +static const char *amd64_mpx_names[] = { - AMD64_RDI_REGNUM, /* %rdi */ - AMD64_RSI_REGNUM, /* %rsi */ - AMD64_RDX_REGNUM, /* %rdx */ - AMD64_RCX_REGNUM, /* %rcx */ - 8, /* %r8 */ - 9 /* %r9 */ + "bnd0raw", "bnd1raw", "bnd2raw", "bnd3raw", "bndcfgu", "bndstatus" }; /* DWARF Register Number Mapping as defined in the System V psABI, @@ -116,7 +115,14 @@ static int amd64_dwarf_regmap[] = AMD64_RSP_REGNUM, /* Extended Integer Registers 8 - 15. */ - 8, 9, 10, 11, 12, 13, 14, 15, + AMD64_R8_REGNUM, /* %r8 */ + AMD64_R9_REGNUM, /* %r9 */ + AMD64_R10_REGNUM, /* %r10 */ + AMD64_R11_REGNUM, /* %r11 */ + AMD64_R12_REGNUM, /* %r12 */ + AMD64_R13_REGNUM, /* %r13 */ + AMD64_R14_REGNUM, /* %r14 */ + AMD64_R15_REGNUM, /* %r15 */ /* Return Address RA. Mapped to RIP. */ AMD64_RIP_REGNUM, @@ -254,7 +260,8 @@ static const char *amd64_word_names[] = static const char *amd64_dword_names[] = { "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp", - "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", + "eip" }; /* Return the name of register REGNUM. */ @@ -275,14 +282,21 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) return i386_pseudo_register_name (gdbarch, regnum); } -static enum register_status -amd64_pseudo_register_read (struct gdbarch *gdbarch, - struct regcache *regcache, - int regnum, gdb_byte *buf) +static struct value * +amd64_pseudo_register_read_value (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum) { gdb_byte raw_buf[MAX_REGISTER_SIZE]; struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum register_status status; + struct value *result_value; + gdb_byte *buf; + + result_value = allocate_value (register_type (gdbarch, regnum)); + VALUE_LVAL (result_value) = lval_register; + VALUE_REGNUM (result_value) = regnum; + buf = value_contents_raw (result_value); if (i386_byte_regnum_p (gdbarch, regnum)) { @@ -297,15 +311,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf + 1, 1); + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } else { status = regcache_raw_read (regcache, gpnum, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf, 1); + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } - - return status; } else if (i386_dword_regnum_p (gdbarch, regnum)) { @@ -314,11 +332,15 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch, status = regcache_raw_read (regcache, gpnum, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf, 4); - - return status; + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } else - return i386_pseudo_register_read (gdbarch, regcache, regnum, buf); + i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, + result_value); + + return result_value; } static void @@ -371,6 +393,20 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch, +/* Register classes as defined in the psABI. */ + +enum amd64_reg_class +{ + AMD64_INTEGER, + AMD64_SSE, + AMD64_SSEUP, + AMD64_X87, + AMD64_X87UP, + AMD64_COMPLEX_X87, + AMD64_NO_CLASS, + AMD64_MEMORY +}; + /* Return the union class of CLASS1 and CLASS2. See the psABI for details. */ @@ -407,6 +443,8 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2) return AMD64_SSE; } +static void amd64_classify (struct type *type, enum amd64_reg_class class[2]); + /* Return non-zero if TYPE is a non-POD structure or union type. */ static int @@ -426,12 +464,10 @@ amd64_non_pod_p (struct type *type) static void amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) { - int len = TYPE_LENGTH (type); - /* 1. If the size of an object is larger than two eightbytes, or in C++, is a non-POD structure or union type, or contains unaligned fields, it has class memory. */ - if (len > 16 || amd64_non_pod_p (type)) + if (TYPE_LENGTH (type) > 16 || amd64_non_pod_p (type)) { class[0] = class[1] = AMD64_MEMORY; return; @@ -451,7 +487,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) /* All fields in an array have the same type. */ amd64_classify (subtype, class); - if (len > 8 && class[1] == AMD64_NO_CLASS) + if (TYPE_LENGTH (type) > 8 && class[1] == AMD64_NO_CLASS) class[1] = class[0]; } else @@ -518,7 +554,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) if (class[0] == AMD64_MEMORY || class[1] == AMD64_MEMORY) class[0] = class[1] = AMD64_MEMORY; - /* Rule (b): If SSEUP is not preceeded by SSE, it is converted to + /* Rule (b): If SSEUP is not preceded by SSE, it is converted to SSE. */ if (class[0] == AMD64_SSEUP) class[0] = AMD64_SSE; @@ -528,7 +564,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) /* Classify TYPE, and store the result in CLASS. */ -void +static void amd64_classify (struct type *type, enum amd64_reg_class class[2]) { enum type_code code = TYPE_CODE (type); @@ -568,6 +604,23 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2]) /* Class X87 and X87UP. */ class[0] = AMD64_X87, class[1] = AMD64_X87UP; + /* Arguments of complex T where T is one of the types float or + double get treated as if they are implemented as: + + struct complexT { + T real; + T imag; + }; */ + else if (code == TYPE_CODE_COMPLEX && len == 8) + class[0] = AMD64_SSE; + else if (code == TYPE_CODE_COMPLEX && len == 16) + class[0] = class[1] = AMD64_SSE; + + /* A variable of type complex long double is classified as type + COMPLEX_X87. */ + else if (code == TYPE_CODE_COMPLEX && len == 32) + class[0] = AMD64_COMPLEX_X87; + /* Aggregates. */ else if (code == TYPE_CODE_ARRAY || code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) @@ -575,11 +628,10 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2]) } static enum return_value_convention -amd64_return_value (struct gdbarch *gdbarch, struct type *func_type, +amd64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum amd64_reg_class class[2]; int len = TYPE_LENGTH (type); static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM }; @@ -589,10 +641,9 @@ amd64_return_value (struct gdbarch *gdbarch, struct type *func_type, int i; gdb_assert (!(readbuf && writebuf)); - gdb_assert (tdep->classify); /* 1. Classify the return type with the classification algorithm. */ - tdep->classify (type, class); + amd64_classify (type, class); /* 2. If the type has class MEMORY, then the caller provides space for the return value and passes the address of this storage in @@ -618,6 +669,30 @@ amd64_return_value (struct gdbarch *gdbarch, struct type *func_type, return RETURN_VALUE_ABI_RETURNS_ADDRESS; } + /* 8. If the class is COMPLEX_X87, the real part of the value is + returned in %st0 and the imaginary part in %st1. */ + if (class[0] == AMD64_COMPLEX_X87) + { + if (readbuf) + { + regcache_raw_read (regcache, AMD64_ST0_REGNUM, readbuf); + regcache_raw_read (regcache, AMD64_ST1_REGNUM, readbuf + 16); + } + + if (writebuf) + { + i387_return_value (gdbarch, regcache); + regcache_raw_write (regcache, AMD64_ST0_REGNUM, writebuf); + regcache_raw_write (regcache, AMD64_ST1_REGNUM, writebuf + 16); + + /* Fix up the tag word such that both %st(0) and %st(1) are + marked as valid. */ + regcache_raw_write_unsigned (regcache, AMD64_FTAG_REGNUM, 0xfff); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + gdb_assert (class[1] != AMD64_MEMORY); gdb_assert (len <= 16); @@ -690,11 +765,15 @@ static CORE_ADDR amd64_push_arguments (struct regcache *regcache, int nargs, struct value **args, CORE_ADDR sp, int struct_return) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int *integer_regs = tdep->call_dummy_integer_regs; - int num_integer_regs = tdep->call_dummy_num_integer_regs; - + static int integer_regnum[] = + { + AMD64_RDI_REGNUM, /* %rdi */ + AMD64_RSI_REGNUM, /* %rsi */ + AMD64_RDX_REGNUM, /* %rdx */ + AMD64_RCX_REGNUM, /* %rcx */ + AMD64_R8_REGNUM, /* %r8 */ + AMD64_R9_REGNUM /* %r9 */ + }; static int sse_regnum[] = { /* %xmm0 ... %xmm7 */ @@ -704,11 +783,6 @@ amd64_push_arguments (struct regcache *regcache, int nargs, AMD64_XMM0_REGNUM + 6, AMD64_XMM0_REGNUM + 7, }; struct value **stack_args = alloca (nargs * sizeof (struct value *)); - /* An array that mirrors the stack_args array. For all arguments - that are passed by MEMORY, if that argument's address also needs - to be stored in a register, the ARG_ADDR_REGNO array will contain - that register number (or a negative value otherwise). */ - int *arg_addr_regno = alloca (nargs * sizeof (int)); int num_stack_args = 0; int num_elements = 0; int element = 0; @@ -716,8 +790,6 @@ amd64_push_arguments (struct regcache *regcache, int nargs, int sse_reg = 0; int i; - gdb_assert (tdep->classify); - /* Reserve a register for the "hidden" argument. */ if (struct_return) integer_reg++; @@ -732,7 +804,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs, int j; /* Classify argument. */ - tdep->classify (type, class); + amd64_classify (type, class); /* Calculate the number of integer and SSE registers needed for this argument. */ @@ -746,25 +818,13 @@ amd64_push_arguments (struct regcache *regcache, int nargs, /* Check whether enough registers are available, and if the argument should be passed in registers at all. */ - if (integer_reg + needed_integer_regs > num_integer_regs + if (integer_reg + needed_integer_regs > ARRAY_SIZE (integer_regnum) || sse_reg + needed_sse_regs > ARRAY_SIZE (sse_regnum) || (needed_integer_regs == 0 && needed_sse_regs == 0)) { /* The argument will be passed on the stack. */ num_elements += ((len + 7) / 8); - stack_args[num_stack_args] = args[i]; - /* If this is an AMD64_MEMORY argument whose address must also - be passed in one of the integer registers, reserve that - register and associate this value to that register so that - we can store the argument address as soon as we know it. */ - if (class[0] == AMD64_MEMORY - && tdep->memory_args_by_pointer - && integer_reg < tdep->call_dummy_num_integer_regs) - arg_addr_regno[num_stack_args] = - tdep->call_dummy_integer_regs[integer_reg++]; - else - arg_addr_regno[num_stack_args] = -1; - num_stack_args++; + stack_args[num_stack_args++] = args[i]; } else { @@ -782,7 +842,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs, switch (class[j]) { case AMD64_INTEGER: - regnum = integer_regs[integer_reg++]; + regnum = integer_regnum[integer_reg++]; break; case AMD64_SSE: @@ -820,19 +880,8 @@ amd64_push_arguments (struct regcache *regcache, int nargs, struct type *type = value_type (stack_args[i]); const gdb_byte *valbuf = value_contents (stack_args[i]); int len = TYPE_LENGTH (type); - CORE_ADDR arg_addr = sp + element * 8; - - write_memory (arg_addr, valbuf, len); - if (arg_addr_regno[i] >= 0) - { - /* We also need to store the address of that argument in - the given register. */ - gdb_byte buf[8]; - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - - store_unsigned_integer (buf, 8, byte_order, arg_addr); - regcache_cooked_write (regcache, arg_addr_regno[i], buf); - } + + write_memory (sp + element * 8, valbuf, len); element += ((len + 7) / 8); } @@ -851,7 +900,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int struct_return, CORE_ADDR struct_addr) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_byte buf[8]; /* Pass arguments. */ @@ -860,20 +908,10 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Pass "hidden" argument". */ if (struct_return) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - /* The "hidden" argument is passed throught the first argument - register. */ - const int arg_regnum = tdep->call_dummy_integer_regs[0]; - store_unsigned_integer (buf, 8, byte_order, struct_addr); - regcache_cooked_write (regcache, arg_regnum, buf); + regcache_cooked_write (regcache, AMD64_RDI_REGNUM, buf); } - /* Reserve some memory on the stack for the integer-parameter registers, - if required by the ABI. */ - if (tdep->integer_param_regs_saved_in_caller_frame) - sp -= tdep->call_dummy_num_integer_regs * 8; - /* Store return address. */ sp -= 8; store_unsigned_integer (buf, 8, byte_order, bp_addr); @@ -1064,9 +1102,9 @@ amd64_get_unused_input_int_reg (const struct amd64_insn *details) if (have_sib) { int base = SIB_BASE_FIELD (details->raw_insn[details->modrm_offset + 1]); - int index = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]); + int idx = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]); used_regs_mask |= 1 << base; - used_regs_mask |= 1 << index; + used_regs_mask |= 1 << idx; } else { @@ -1242,7 +1280,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch, struct regcache *regs) { int len = gdbarch_max_insn_length (gdbarch); - /* Extra space for sentinels so fixup_{riprel,displaced_copy don't have to + /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to continually watch for running off the end of the buffer. */ int fixup_sentinel_space = len; struct displaced_step_closure *dsc = @@ -1533,7 +1571,7 @@ append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf) *to += len; } -void +static void amd64_relocate_instruction (struct gdbarch *gdbarch, CORE_ADDR *to, CORE_ADDR oldloc) { @@ -1574,7 +1612,7 @@ amd64_relocate_instruction (struct gdbarch *gdbarch, /* Where "ret" in the original code will return to. */ ret_addr = oldloc + insn_length; push_buf[0] = 0x68; /* pushq $... */ - memcpy (&push_buf[1], &ret_addr, 4); + store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr); /* Push the push. */ append_insns (to, 5, push_buf); @@ -1635,6 +1673,7 @@ struct amd64_frame_cache { /* Base address. */ CORE_ADDR base; + int base_p; CORE_ADDR sp_offset; CORE_ADDR pc; @@ -1656,6 +1695,7 @@ amd64_init_frame_cache (struct amd64_frame_cache *cache) /* Base address. */ cache->base = 0; + cache->base_p = 0; cache->sp_offset = -8; cache->pc = 0; @@ -1721,7 +1761,7 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, int reg, r; int offset, offset_and; - if (target_read_memory (pc, buf, sizeof buf)) + if (target_read_code (pc, buf, sizeof buf)) return pc; /* Check caller-saved saved register. The first instruction has @@ -1840,6 +1880,188 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, return min (pc + offset + 2, current_pc); } +/* Similar to amd64_analyze_stack_align for x32. */ + +static CORE_ADDR +amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, + struct amd64_frame_cache *cache) +{ + /* There are 2 code sequences to re-align stack before the frame + gets set up: + + 1. Use a caller-saved saved register: + + leaq 8(%rsp), %reg + andq $-XXX, %rsp + pushq -8(%reg) + + or + + [addr32] leal 8(%rsp), %reg + andl $-XXX, %esp + [addr32] pushq -8(%reg) + + 2. Use a callee-saved saved register: + + pushq %reg + leaq 16(%rsp), %reg + andq $-XXX, %rsp + pushq -8(%reg) + + or + + pushq %reg + [addr32] leal 16(%rsp), %reg + andl $-XXX, %esp + [addr32] pushq -8(%reg) + + "andq $-XXX, %rsp" can be either 4 bytes or 7 bytes: + + 0x48 0x83 0xe4 0xf0 andq $-16, %rsp + 0x48 0x81 0xe4 0x00 0xff 0xff 0xff andq $-256, %rsp + + "andl $-XXX, %esp" can be either 3 bytes or 6 bytes: + + 0x83 0xe4 0xf0 andl $-16, %esp + 0x81 0xe4 0x00 0xff 0xff 0xff andl $-256, %esp + */ + + gdb_byte buf[19]; + int reg, r; + int offset, offset_and; + + if (target_read_memory (pc, buf, sizeof buf)) + return pc; + + /* Skip optional addr32 prefix. */ + offset = buf[0] == 0x67 ? 1 : 0; + + /* Check caller-saved saved register. The first instruction has + to be "leaq 8(%rsp), %reg" or "leal 8(%rsp), %reg". */ + if (((buf[offset] & 0xfb) == 0x48 || (buf[offset] & 0xfb) == 0x40) + && buf[offset + 1] == 0x8d + && buf[offset + 3] == 0x24 + && buf[offset + 4] == 0x8) + { + /* MOD must be binary 10 and R/M must be binary 100. */ + if ((buf[offset + 2] & 0xc7) != 0x44) + return pc; + + /* REG has register number. */ + reg = (buf[offset + 2] >> 3) & 7; + + /* Check the REX.R bit. */ + if ((buf[offset] & 0x4) != 0) + reg += 8; + + offset += 5; + } + else + { + /* Check callee-saved saved register. The first instruction + has to be "pushq %reg". */ + reg = 0; + if ((buf[offset] & 0xf6) == 0x40 + && (buf[offset + 1] & 0xf8) == 0x50) + { + /* Check the REX.B bit. */ + if ((buf[offset] & 1) != 0) + reg = 8; + + offset += 1; + } + else if ((buf[offset] & 0xf8) != 0x50) + return pc; + + /* Get register. */ + reg += buf[offset] & 0x7; + + offset++; + + /* Skip optional addr32 prefix. */ + if (buf[offset] == 0x67) + offset++; + + /* The next instruction has to be "leaq 16(%rsp), %reg" or + "leal 16(%rsp), %reg". */ + if (((buf[offset] & 0xfb) != 0x48 && (buf[offset] & 0xfb) != 0x40) + || buf[offset + 1] != 0x8d + || buf[offset + 3] != 0x24 + || buf[offset + 4] != 0x10) + return pc; + + /* MOD must be binary 10 and R/M must be binary 100. */ + if ((buf[offset + 2] & 0xc7) != 0x44) + return pc; + + /* REG has register number. */ + r = (buf[offset + 2] >> 3) & 7; + + /* Check the REX.R bit. */ + if ((buf[offset] & 0x4) != 0) + r += 8; + + /* Registers in pushq and leaq have to be the same. */ + if (reg != r) + return pc; + + offset += 5; + } + + /* Rigister can't be %rsp nor %rbp. */ + if (reg == 4 || reg == 5) + return pc; + + /* The next instruction may be "andq $-XXX, %rsp" or + "andl $-XXX, %esp". */ + if (buf[offset] != 0x48) + offset--; + + if (buf[offset + 2] != 0xe4 + || (buf[offset + 1] != 0x81 && buf[offset + 1] != 0x83)) + return pc; + + offset_and = offset; + offset += buf[offset + 1] == 0x81 ? 7 : 4; + + /* Skip optional addr32 prefix. */ + if (buf[offset] == 0x67) + offset++; + + /* The next instruction has to be "pushq -8(%reg)". */ + r = 0; + if (buf[offset] == 0xff) + offset++; + else if ((buf[offset] & 0xf6) == 0x40 + && buf[offset + 1] == 0xff) + { + /* Check the REX.B bit. */ + if ((buf[offset] & 0x1) != 0) + r = 8; + offset += 2; + } + else + return pc; + + /* 8bit -8 is 0xf8. REG must be binary 110 and MOD must be binary + 01. */ + if (buf[offset + 1] != 0xf8 + || (buf[offset] & 0xf8) != 0x70) + return pc; + + /* R/M has register. */ + r += buf[offset] & 7; + + /* Registers in leaq and pushq have to be the same. */ + if (reg != r) + return pc; + + if (current_pc > pc + offset_and) + cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg); + + return min (pc + offset + 2, current_pc); +} + /* Do a limited analysis of the prologue at PC and update CACHE accordingly. Bail out early if CURRENT_PC is reached. Return the address where the analysis stopped. @@ -1847,10 +2069,16 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, We will handle only functions beginning with: pushq %rbp 0x55 - movq %rsp, %rbp 0x48 0x89 0xe5 + movq %rsp, %rbp 0x48 0x89 0xe5 (or 0x48 0x8b 0xec) + + or (for the X32 ABI): - Any function that doesn't start with this sequence will be assumed - to have no prologue and thus no valid frame pointer in %rbp. */ + pushq %rbp 0x55 + movl %esp, %ebp 0x89 0xe5 (or 0x8b 0xec) + + Any function that doesn't start with one of these sequences will be + assumed to have no prologue and thus no valid frame pointer in + %rbp. */ static CORE_ADDR amd64_analyze_prologue (struct gdbarch *gdbarch, @@ -1858,16 +2086,25 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, struct amd64_frame_cache *cache) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - static gdb_byte proto[3] = { 0x48, 0x89, 0xe5 }; /* movq %rsp, %rbp */ + /* There are two variations of movq %rsp, %rbp. */ + static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 }; + static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec }; + /* Ditto for movl %esp, %ebp. */ + static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 }; + static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec }; + gdb_byte buf[3]; gdb_byte op; if (current_pc <= pc) return current_pc; - pc = amd64_analyze_stack_align (pc, current_pc, cache); + if (gdbarch_ptr_bit (gdbarch) == 32) + pc = amd64_x32_analyze_stack_align (pc, current_pc, cache); + else + pc = amd64_analyze_stack_align (pc, current_pc, cache); - op = read_memory_unsigned_integer (pc, 1, byte_order); + op = read_code_unsigned_integer (pc, 1, byte_order); if (op == 0x55) /* pushq %rbp */ { @@ -1880,19 +2117,115 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, if (current_pc <= pc + 1) return current_pc; + read_code (pc + 1, buf, 3); + /* Check for `movq %rsp, %rbp'. */ - read_memory (pc + 1, buf, 3); - if (memcmp (buf, proto, 3) != 0) - return pc + 1; + if (memcmp (buf, mov_rsp_rbp_1, 3) == 0 + || memcmp (buf, mov_rsp_rbp_2, 3) == 0) + { + /* OK, we actually have a frame. */ + cache->frameless_p = 0; + return pc + 4; + } - /* OK, we actually have a frame. */ - cache->frameless_p = 0; - return pc + 4; + /* For X32, also check for `movq %esp, %ebp'. */ + if (gdbarch_ptr_bit (gdbarch) == 32) + { + if (memcmp (buf, mov_esp_ebp_1, 2) == 0 + || memcmp (buf, mov_esp_ebp_2, 2) == 0) + { + /* OK, we actually have a frame. */ + cache->frameless_p = 0; + return pc + 3; + } + } + + return pc + 1; } return pc; } +/* Work around false termination of prologue - GCC PR debug/48827. + + START_PC is the first instruction of a function, PC is its minimal already + determined advanced address. Function returns PC if it has nothing to do. + + 84 c0 test %al,%al + 74 23 je after + <-- here is 0 lines advance - the false prologue end marker. + 0f 29 85 70 ff ff ff movaps %xmm0,-0x90(%rbp) + 0f 29 4d 80 movaps %xmm1,-0x80(%rbp) + 0f 29 55 90 movaps %xmm2,-0x70(%rbp) + 0f 29 5d a0 movaps %xmm3,-0x60(%rbp) + 0f 29 65 b0 movaps %xmm4,-0x50(%rbp) + 0f 29 6d c0 movaps %xmm5,-0x40(%rbp) + 0f 29 75 d0 movaps %xmm6,-0x30(%rbp) + 0f 29 7d e0 movaps %xmm7,-0x20(%rbp) + after: */ + +static CORE_ADDR +amd64_skip_xmm_prologue (CORE_ADDR pc, CORE_ADDR start_pc) +{ + struct symtab_and_line start_pc_sal, next_sal; + gdb_byte buf[4 + 8 * 7]; + int offset, xmmreg; + + if (pc == start_pc) + return pc; + + start_pc_sal = find_pc_sect_line (start_pc, NULL, 0); + if (start_pc_sal.symtab == NULL + || producer_is_gcc_ge_4 (start_pc_sal.symtab->producer) < 6 + || start_pc_sal.pc != start_pc || pc >= start_pc_sal.end) + return pc; + + next_sal = find_pc_sect_line (start_pc_sal.end, NULL, 0); + if (next_sal.line != start_pc_sal.line) + return pc; + + /* START_PC can be from overlayed memory, ignored here. */ + if (target_read_code (next_sal.pc - 4, buf, sizeof (buf)) != 0) + return pc; + + /* test %al,%al */ + if (buf[0] != 0x84 || buf[1] != 0xc0) + return pc; + /* je AFTER */ + if (buf[2] != 0x74) + return pc; + + offset = 4; + for (xmmreg = 0; xmmreg < 8; xmmreg++) + { + /* 0x0f 0x29 0b??000101 movaps %xmmreg?,-0x??(%rbp) */ + if (buf[offset] != 0x0f || buf[offset + 1] != 0x29 + || (buf[offset + 2] & 0x3f) != (xmmreg << 3 | 0x5)) + return pc; + + /* 0b01?????? */ + if ((buf[offset + 2] & 0xc0) == 0x40) + { + /* 8-bit displacement. */ + offset += 4; + } + /* 0b10?????? */ + else if ((buf[offset + 2] & 0xc0) == 0x80) + { + /* 32-bit displacement. */ + offset += 7; + } + else + return pc; + } + + /* je AFTER */ + if (offset - 4 != buf[3]) + return pc; + + return next_sal.end; +} + /* Return PC of first real instruction. */ static CORE_ADDR @@ -1900,6 +2233,22 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) { struct amd64_frame_cache cache; CORE_ADDR pc; + CORE_ADDR func_addr; + + if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL)) + { + CORE_ADDR post_prologue_pc + = skip_prologue_using_sal (gdbarch, func_addr); + struct symtab *s = find_pc_symtab (func_addr); + + /* Clang always emits a line note before the prologue and another + one after. We trust clang to emit usable line notes. */ + if (post_prologue_pc + && (s != NULL + && s->producer != NULL + && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0)) + return max (start_pc, post_prologue_pc); + } amd64_init_frame_cache (&cache); pc = amd64_analyze_prologue (gdbarch, start_pc, 0xffffffffffffffffLL, @@ -1907,39 +2256,26 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) if (cache.frameless_p) return start_pc; - return pc; + return amd64_skip_xmm_prologue (pc, start_pc); } /* Normal frames. */ -static struct amd64_frame_cache * -amd64_frame_cache (struct frame_info *this_frame, void **this_cache) +static void +amd64_frame_cache_1 (struct frame_info *this_frame, + struct amd64_frame_cache *cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct amd64_frame_cache *cache; gdb_byte buf[8]; int i; - if (*this_cache) - return *this_cache; - - cache = amd64_alloc_frame_cache (); - *this_cache = cache; - cache->pc = get_frame_func (this_frame); if (cache->pc != 0) amd64_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame), cache); - if (cache->saved_sp_reg != -1) - { - /* Stack pointer has been saved. */ - get_frame_register (this_frame, cache->saved_sp_reg, buf); - cache->saved_sp = extract_unsigned_integer(buf, 8, byte_order); - } - if (cache->frameless_p) { /* We didn't find a valid frame. If we're at the start of a @@ -1951,6 +2287,10 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_sp_reg != -1) { + /* Stack pointer has been saved. */ + get_frame_register (this_frame, cache->saved_sp_reg, buf); + cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order); + /* We're halfway aligning the stack. */ cache->base = ((cache->saved_sp - 8) & 0xfffffffffffffff0LL) - 8; cache->saved_regs[AMD64_RIP_REGNUM] = cache->saved_sp - 8; @@ -1988,21 +2328,64 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_regs[i] != -1) cache->saved_regs[i] += cache->base; + cache->base_p = 1; +} + +static struct amd64_frame_cache * +amd64_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct amd64_frame_cache *cache; + + if (*this_cache) + return *this_cache; + + cache = amd64_alloc_frame_cache (); + *this_cache = cache; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + amd64_frame_cache_1 (this_frame, cache); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + return cache; } -static void -amd64_frame_this_id (struct frame_info *this_frame, void **this_cache, - struct frame_id *this_id) +static enum unwind_stop_reason +amd64_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) { struct amd64_frame_cache *cache = amd64_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + /* This marks the outermost frame. */ if (cache->base == 0) - return; + return UNWIND_OUTERMOST; + + return UNWIND_NO_REASON; +} + +static void +amd64_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) +{ + struct amd64_frame_cache *cache = + amd64_frame_cache (this_frame, this_cache); - (*this_id) = frame_id_build (cache->base + 16, cache->pc); + if (!cache->base_p) + (*this_id) = frame_id_build_unavailable_stack (cache->pc); + else if (cache->base == 0) + { + /* This marks the outermost frame. */ + return; + } + else + (*this_id) = frame_id_build (cache->base + 16, cache->pc); } static struct value * @@ -2028,12 +2411,29 @@ amd64_frame_prev_register (struct frame_info *this_frame, void **this_cache, static const struct frame_unwind amd64_frame_unwind = { NORMAL_FRAME, + amd64_frame_unwind_stop_reason, amd64_frame_this_id, amd64_frame_prev_register, NULL, default_frame_sniffer }; +/* Generate a bytecode expression to get the value of the saved PC. */ + +static void +amd64_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + CORE_ADDR scope) +{ + /* The following sequence assumes the traditional use of the base + register. */ + ax_reg (ax, AMD64_RBP_REGNUM); + ax_const_l (ax, 8); + ax_simple (ax, aop_add); + value->type = register_type (gdbarch, AMD64_RIP_REGNUM); + value->kind = axs_lvalue_memory; +} + /* Signal trampolines. */ @@ -2047,6 +2447,7 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct amd64_frame_cache *cache; CORE_ADDR addr; gdb_byte buf[8]; @@ -2057,20 +2458,40 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); - get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8; - addr = tdep->sigcontext_addr (this_frame); - gdb_assert (tdep->sc_reg_offset); - gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS); - for (i = 0; i < tdep->sc_num_regs; i++) - if (tdep->sc_reg_offset[i] != -1) - cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + addr = tdep->sigcontext_addr (this_frame); + gdb_assert (tdep->sc_reg_offset); + gdb_assert (tdep->sc_num_regs <= AMD64_NUM_SAVED_REGS); + for (i = 0; i < tdep->sc_num_regs; i++) + if (tdep->sc_reg_offset[i] != -1) + cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); *this_cache = cache; return cache; } +static enum unwind_stop_reason +amd64_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct amd64_frame_cache *cache = + amd64_sigtramp_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void amd64_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -2078,7 +2499,15 @@ amd64_sigtramp_frame_this_id (struct frame_info *this_frame, struct amd64_frame_cache *cache = amd64_sigtramp_frame_cache (this_frame, this_cache); - (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame)); + if (!cache->base_p) + (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame)); + else if (cache->base == 0) + { + /* This marks the outermost frame. */ + return; + } + else + (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame)); } static struct value * @@ -2124,6 +2553,7 @@ amd64_sigtramp_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind amd64_sigtramp_frame_unwind = { SIGTRAMP_FRAME, + amd64_sigtramp_frame_unwind_stop_reason, amd64_sigtramp_frame_this_id, amd64_sigtramp_frame_prev_register, NULL, @@ -2158,6 +2588,11 @@ static int amd64_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { gdb_byte insn; + struct symtab *symtab; + + symtab = find_pc_symtab (pc); + if (symtab && symtab->epilogue_unwind_valid) + return 0; if (target_read_memory (pc, &insn, 1)) return 0; /* Can't read memory at pc. */ @@ -2185,6 +2620,7 @@ amd64_epilogue_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); + volatile struct gdb_exception ex; struct amd64_frame_cache *cache; gdb_byte buf[8]; @@ -2194,23 +2630,43 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache = amd64_alloc_frame_cache (); *this_cache = cache; - /* Cache base will be %esp plus cache->sp_offset (-8). */ - get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 8, - byte_order) + cache->sp_offset; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* Cache base will be %esp plus cache->sp_offset (-8). */ + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 8, + byte_order) + cache->sp_offset; - /* Cache pc will be the frame func. */ - cache->pc = get_frame_pc (this_frame); + /* Cache pc will be the frame func. */ + cache->pc = get_frame_pc (this_frame); - /* The saved %esp will be at cache->base plus 16. */ - cache->saved_sp = cache->base + 16; + /* The saved %esp will be at cache->base plus 16. */ + cache->saved_sp = cache->base + 16; - /* The saved %eip will be at cache->base plus 8. */ - cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8; + /* The saved %eip will be at cache->base plus 8. */ + cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8; + + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); return cache; } +static enum unwind_stop_reason +amd64_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct amd64_frame_cache *cache + = amd64_epilogue_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void amd64_epilogue_frame_this_id (struct frame_info *this_frame, void **this_cache, @@ -2219,12 +2675,16 @@ amd64_epilogue_frame_this_id (struct frame_info *this_frame, struct amd64_frame_cache *cache = amd64_epilogue_frame_cache (this_frame, this_cache); - (*this_id) = frame_id_build (cache->base + 8, cache->pc); + if (!cache->base_p) + (*this_id) = frame_id_build_unavailable_stack (cache->pc); + else + (*this_id) = frame_id_build (cache->base + 8, cache->pc); } static const struct frame_unwind amd64_epilogue_frame_unwind = { NORMAL_FRAME, + amd64_epilogue_frame_unwind_stop_reason, amd64_epilogue_frame_this_id, amd64_frame_prev_register, NULL, @@ -2378,6 +2838,12 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct target_desc *tdesc = info.target_desc; + static const char *const stap_integer_prefixes[] = { "$", NULL }; + static const char *const stap_register_prefixes[] = { "%", NULL }; + static const char *const stap_register_indirection_prefixes[] = { "(", + NULL }; + static const char *const stap_register_indirection_suffixes[] = { ")", + NULL }; /* AMD64 generally uses `fxsave' instead of `fsave' for saving its floating-point registers. */ @@ -2397,14 +2863,21 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->ymm0h_regnum = AMD64_YMM0H_REGNUM; } + if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.mpx") != NULL) + { + tdep->mpx_register_names = amd64_mpx_names; + tdep->bndcfgu_regnum = AMD64_BNDCFGU_REGNUM; + tdep->bnd0r_regnum = AMD64_BND0R_REGNUM; + } + tdep->num_byte_regs = 20; tdep->num_word_regs = 16; tdep->num_dword_regs = 16; /* Avoid wiring in the MMX registers for now. */ tdep->num_mmx_regs = 0; - set_gdbarch_pseudo_register_read (gdbarch, - amd64_pseudo_register_read); + set_gdbarch_pseudo_register_read_value (gdbarch, + amd64_pseudo_register_read_value); set_gdbarch_pseudo_register_write (gdbarch, amd64_pseudo_register_write); @@ -2448,10 +2921,6 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_push_dummy_call (gdbarch, amd64_push_dummy_call); set_gdbarch_frame_align (gdbarch, amd64_frame_align); set_gdbarch_frame_red_zone_size (gdbarch, 128); - tdep->call_dummy_num_integer_regs = - ARRAY_SIZE (amd64_dummy_call_integer_regs); - tdep->call_dummy_integer_regs = amd64_dummy_call_integer_regs; - tdep->classify = amd64_classify; set_gdbarch_convert_register_p (gdbarch, i387_convert_register_p); set_gdbarch_register_to_value (gdbarch, i387_register_to_value); @@ -2483,6 +2952,57 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target); set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction); + + set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address); + + /* SystemTap variables and functions. */ + set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes); + set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes); + set_gdbarch_stap_register_indirection_prefixes (gdbarch, + stap_register_indirection_prefixes); + set_gdbarch_stap_register_indirection_suffixes (gdbarch, + stap_register_indirection_suffixes); + set_gdbarch_stap_is_single_operand (gdbarch, + i386_stap_is_single_operand); + set_gdbarch_stap_parse_special_token (gdbarch, + i386_stap_parse_special_token); +} + + +static struct type * +amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + switch (regnum - tdep->eax_regnum) + { + case AMD64_RBP_REGNUM: /* %ebp */ + case AMD64_RSP_REGNUM: /* %esp */ + return builtin_type (gdbarch)->builtin_data_ptr; + case AMD64_RIP_REGNUM: /* %eip */ + return builtin_type (gdbarch)->builtin_func_ptr; + } + + return i386_pseudo_register_type (gdbarch, regnum); +} + +void +amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const struct target_desc *tdesc = info.target_desc; + + amd64_init_abi (info, gdbarch); + + if (! tdesc_has_registers (tdesc)) + tdesc = tdesc_x32; + tdep->tdesc = tdesc; + + tdep->num_dword_regs = 17; + set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type); + + set_gdbarch_long_bit (gdbarch, 32); + set_gdbarch_ptr_bit (gdbarch, 32); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -2493,6 +3013,9 @@ _initialize_amd64_tdep (void) { initialize_tdesc_amd64 (); initialize_tdesc_amd64_avx (); + initialize_tdesc_amd64_mpx (); + initialize_tdesc_x32 (); + initialize_tdesc_x32_avx (); } @@ -2517,7 +3040,8 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum, i387_supply_fxsave (regcache, regnum, fxsave); - if (fxsave && gdbarch_ptr_bit (gdbarch) == 64) + if (fxsave + && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64) { const gdb_byte *regs = fxsave; @@ -2539,7 +3063,8 @@ amd64_supply_xsave (struct regcache *regcache, int regnum, i387_supply_xsave (regcache, regnum, xsave); - if (xsave && gdbarch_ptr_bit (gdbarch) == 64) + if (xsave + && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64) { const gdb_byte *regs = xsave; @@ -2567,7 +3092,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum, i387_collect_fxsave (regcache, regnum, fxsave); - if (gdbarch_ptr_bit (gdbarch) == 64) + if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64) { if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep)) regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12); @@ -2576,7 +3101,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum, } } -/* Similar to amd64_collect_fxsave, but but use XSAVE extended state. */ +/* Similar to amd64_collect_fxsave, but use XSAVE extended state. */ void amd64_collect_xsave (const struct regcache *regcache, int regnum, @@ -2588,7 +3113,7 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum, i387_collect_xsave (regcache, regnum, xsave, gcore); - if (gdbarch_ptr_bit (gdbarch) == 64) + if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64) { if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep)) regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),