/* Target-dependent code for the x86-64 for GDB, the GNU debugger. Copyright 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "arch-utils.h" #include "block.h" #include "dummy-frame.h" #include "frame.h" #include "frame-base.h" #include "frame-unwind.h" #include "inferior.h" #include "gdbcmd.h" #include "gdbcore.h" #include "objfiles.h" #include "regcache.h" #include "symfile.h" #include "gdb_assert.h" #include "x86-64-tdep.h" #include "i387-tdep.h" /* Register numbers of various important registers. */ #define X86_64_RAX_REGNUM 0 /* %rax */ #define X86_64_RDX_REGNUM 3 /* %rdx */ #define X86_64_RDI_REGNUM 5 /* %rdi */ #define X86_64_RBP_REGNUM 6 /* %rbp */ #define X86_64_RSP_REGNUM 7 /* %rsp */ #define X86_64_RIP_REGNUM 16 /* %rip */ #define X86_64_EFLAGS_REGNUM 17 /* %eflags */ #define X86_64_ST0_REGNUM 22 /* %st0 */ #define X86_64_XMM0_REGNUM 38 /* %xmm0 */ #define X86_64_XMM1_REGNUM 39 /* %xmm1 */ struct x86_64_register_info { char *name; struct type **type; }; static struct x86_64_register_info x86_64_register_info[] = { { "rax", &builtin_type_int64 }, { "rbx", &builtin_type_int64 }, { "rcx", &builtin_type_int64 }, { "rdx", &builtin_type_int64 }, { "rsi", &builtin_type_int64 }, { "rdi", &builtin_type_int64 }, { "rbp", &builtin_type_void_data_ptr }, { "rsp", &builtin_type_void_data_ptr }, /* %r8 is indeed register number 8. */ { "r8", &builtin_type_int64 }, { "r9", &builtin_type_int64 }, { "r10", &builtin_type_int64 }, { "r11", &builtin_type_int64 }, { "r12", &builtin_type_int64 }, { "r13", &builtin_type_int64 }, { "r14", &builtin_type_int64 }, { "r15", &builtin_type_int64 }, { "rip", &builtin_type_void_func_ptr }, { "eflags", &builtin_type_int32 }, { "ds", &builtin_type_int32 }, { "es", &builtin_type_int32 }, { "fs", &builtin_type_int32 }, { "gs", &builtin_type_int32 }, /* %st0 is register number 22. */ { "st0", &builtin_type_i387_ext }, { "st1", &builtin_type_i387_ext }, { "st2", &builtin_type_i387_ext }, { "st3", &builtin_type_i387_ext }, { "st4", &builtin_type_i387_ext }, { "st5", &builtin_type_i387_ext }, { "st6", &builtin_type_i387_ext }, { "st7", &builtin_type_i387_ext }, { "fctrl", &builtin_type_int32 }, { "fstat", &builtin_type_int32 }, { "ftag", &builtin_type_int32 }, { "fiseg", &builtin_type_int32 }, { "fioff", &builtin_type_int32 }, { "foseg", &builtin_type_int32 }, { "fooff", &builtin_type_int32 }, { "fop", &builtin_type_int32 }, /* %xmm0 is register number 38. */ { "xmm0", &builtin_type_v4sf }, { "xmm1", &builtin_type_v4sf }, { "xmm2", &builtin_type_v4sf }, { "xmm3", &builtin_type_v4sf }, { "xmm4", &builtin_type_v4sf }, { "xmm5", &builtin_type_v4sf }, { "xmm6", &builtin_type_v4sf }, { "xmm7", &builtin_type_v4sf }, { "xmm8", &builtin_type_v4sf }, { "xmm9", &builtin_type_v4sf }, { "xmm10", &builtin_type_v4sf }, { "xmm11", &builtin_type_v4sf }, { "xmm12", &builtin_type_v4sf }, { "xmm13", &builtin_type_v4sf }, { "xmm14", &builtin_type_v4sf }, { "xmm15", &builtin_type_v4sf }, { "mxcsr", &builtin_type_int32 } }; /* Total number of registers. */ #define X86_64_NUM_REGS \ (sizeof (x86_64_register_info) / sizeof (x86_64_register_info[0])) /* Return the name of register REGNUM. */ static const char * x86_64_register_name (int regnum) { if (regnum >= 0 && regnum < X86_64_NUM_REGS) return x86_64_register_info[regnum].name; return NULL; } /* Return the GDB type object for the "standard" data type of data in register REGNUM. */ static struct type * x86_64_register_type (struct gdbarch *gdbarch, int regnum) { gdb_assert (regnum >= 0 && regnum < X86_64_NUM_REGS); return *x86_64_register_info[regnum].type; } /* DWARF Register Number Mapping as defined in the System V psABI, section 3.6. */ static int x86_64_dwarf_regmap[] = { /* General Purpose Registers RAX, RDX, RCX, RBX, RSI, RDI. */ X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, 3, 2, 4, X86_64_RDI_REGNUM, /* Frame Pointer Register RBP. */ X86_64_RBP_REGNUM, /* Stack Pointer Register RSP. */ X86_64_RSP_REGNUM, /* Extended Integer Registers 8 - 15. */ 8, 9, 10, 11, 12, 13, 14, 15, /* Return Address RA. Not mapped. */ -1, /* SSE Registers 0 - 7. */ X86_64_XMM0_REGNUM + 0, X86_64_XMM1_REGNUM, X86_64_XMM0_REGNUM + 2, X86_64_XMM0_REGNUM + 3, X86_64_XMM0_REGNUM + 4, X86_64_XMM0_REGNUM + 5, X86_64_XMM0_REGNUM + 6, X86_64_XMM0_REGNUM + 7, /* Extended SSE Registers 8 - 15. */ X86_64_XMM0_REGNUM + 8, X86_64_XMM0_REGNUM + 9, X86_64_XMM0_REGNUM + 10, X86_64_XMM0_REGNUM + 11, X86_64_XMM0_REGNUM + 12, X86_64_XMM0_REGNUM + 13, X86_64_XMM0_REGNUM + 14, X86_64_XMM0_REGNUM + 15, /* Floating Point Registers 0-7. */ X86_64_ST0_REGNUM + 0, X86_64_ST0_REGNUM + 1, X86_64_ST0_REGNUM + 2, X86_64_ST0_REGNUM + 3, X86_64_ST0_REGNUM + 4, X86_64_ST0_REGNUM + 5, X86_64_ST0_REGNUM + 6, X86_64_ST0_REGNUM + 7 }; static const int x86_64_dwarf_regmap_len = (sizeof (x86_64_dwarf_regmap) / sizeof (x86_64_dwarf_regmap[0])); /* Convert DWARF register number REG to the appropriate register number used by GDB. */ static int x86_64_dwarf_reg_to_regnum (int reg) { int regnum = -1; if (reg >= 0 || reg < x86_64_dwarf_regmap_len) regnum = x86_64_dwarf_regmap[reg]; if (regnum == -1) warning ("Unmapped DWARF Register #%d encountered\n", reg); return regnum; } /* Return nonzero if a value of type TYPE stored in register REGNUM needs any special handling. */ static int x86_64_convert_register_p (int regnum, struct type *type) { return i386_fp_regnum_p (regnum); } /* The returning of values is done according to the special algorithm. Some types are returned in registers an some (big structures) in memory. See the System V psABI for details. */ #define MAX_CLASSES 4 enum x86_64_reg_class { X86_64_NO_CLASS, X86_64_INTEGER_CLASS, X86_64_INTEGERSI_CLASS, X86_64_SSE_CLASS, X86_64_SSESF_CLASS, X86_64_SSEDF_CLASS, X86_64_SSEUP_CLASS, X86_64_X87_CLASS, X86_64_X87UP_CLASS, X86_64_MEMORY_CLASS }; /* Return the union class of CLASS1 and CLASS2. See the System V psABI for details. */ static enum x86_64_reg_class merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) { /* Rule (a): If both classes are equal, this is the resulting class. */ if (class1 == class2) return class1; /* Rule (b): If one of the classes is NO_CLASS, the resulting class is the other class. */ if (class1 == X86_64_NO_CLASS) return class2; if (class2 == X86_64_NO_CLASS) return class1; /* Rule (c): If one of the classes is MEMORY, the result is MEMORY. */ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) return X86_64_MEMORY_CLASS; /* Rule (d): If one of the classes is INTEGER, the result is INTEGER. */ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) return X86_64_INTEGERSI_CLASS; if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) return X86_64_INTEGER_CLASS; /* Rule (e): If one of the classes is X87 or X87UP class, MEMORY is used as class. */ if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS) return X86_64_MEMORY_CLASS; /* Rule (f): Otherwise class SSE is used. */ return X86_64_SSE_CLASS; } /* Classify the argument type. CLASSES will be filled by the register class used to pass each word of the operand. The number of words is returned. In case the parameter should be passed in memory, 0 is returned. As a special case for zero sized containers, classes[0] will be NO_CLASS and 1 is returned. See the System V psABI for details. */ static int classify_argument (struct type *type, enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset) { int bytes = TYPE_LENGTH (type); int words = (bytes + 8 - 1) / 8; switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: { int i; enum x86_64_reg_class subclasses[MAX_CLASSES]; /* On x86-64 we pass structures larger than 16 bytes on the stack. */ if (bytes > 16) return 0; for (i = 0; i < words; i++) classes[i] = X86_64_NO_CLASS; /* Zero sized arrays or structures are NO_CLASS. We return 0 to signalize memory class, so handle it as special case. */ if (!words) { classes[0] = X86_64_NO_CLASS; return 1; } switch (TYPE_CODE (type)) { case TYPE_CODE_STRUCT: { int j; for (j = 0; j < TYPE_NFIELDS (type); ++j) { int num = classify_argument (TYPE_FIELDS (type)[j].type, subclasses, (TYPE_FIELDS (type)[j].loc. bitpos + bit_offset) % 256); if (!num) return 0; for (i = 0; i < num; i++) { int pos = (TYPE_FIELDS (type)[j].loc.bitpos + bit_offset) / 8 / 8; classes[i + pos] = merge_classes (subclasses[i], classes[i + pos]); } } } break; case TYPE_CODE_ARRAY: { int num; num = classify_argument (TYPE_TARGET_TYPE (type), subclasses, bit_offset); if (!num) return 0; /* The partial classes are now full classes. */ if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4) subclasses[0] = X86_64_SSE_CLASS; if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4) subclasses[0] = X86_64_INTEGER_CLASS; for (i = 0; i < words; i++) classes[i] = subclasses[i % num]; } break; case TYPE_CODE_UNION: { int j; { for (j = 0; j < TYPE_NFIELDS (type); ++j) { int num; num = classify_argument (TYPE_FIELDS (type)[j].type, subclasses, bit_offset); if (!num) return 0; for (i = 0; i < num; i++) classes[i] = merge_classes (subclasses[i], classes[i]); } } } break; default: break; } /* Final merger cleanup. */ for (i = 0; i < words; i++) { /* If one class is MEMORY, everything should be passed in memory. */ if (classes[i] == X86_64_MEMORY_CLASS) return 0; /* The X86_64_SSEUP_CLASS should be always preceeded by X86_64_SSE_CLASS. */ if (classes[i] == X86_64_SSEUP_CLASS && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS)) classes[i] = X86_64_SSE_CLASS; /* X86_64_X87UP_CLASS should be preceeded by X86_64_X87_CLASS. */ if (classes[i] == X86_64_X87UP_CLASS && (i == 0 || classes[i - 1] != X86_64_X87_CLASS)) classes[i] = X86_64_SSE_CLASS; } return words; } break; case TYPE_CODE_FLT: switch (bytes) { case 4: if (!(bit_offset % 64)) classes[0] = X86_64_SSESF_CLASS; else classes[0] = X86_64_SSE_CLASS; return 1; case 8: classes[0] = X86_64_SSEDF_CLASS; return 1; case 16: classes[0] = X86_64_X87_CLASS; classes[1] = X86_64_X87UP_CLASS; return 2; } break; case TYPE_CODE_ENUM: case TYPE_CODE_REF: case TYPE_CODE_INT: case TYPE_CODE_PTR: switch (bytes) { case 1: case 2: case 4: case 8: if (bytes * 8 + bit_offset <= 32) classes[0] = X86_64_INTEGERSI_CLASS; else classes[0] = X86_64_INTEGER_CLASS; return 1; case 16: classes[0] = classes[1] = X86_64_INTEGER_CLASS; return 2; default: break; } case TYPE_CODE_VOID: return 0; default: /* Avoid warning. */ break; } internal_error (__FILE__, __LINE__, "classify_argument: unknown argument type"); } /* Examine the argument and set *INT_NREGS and *SSE_NREGS to the number of registers required based on the information passed in CLASSES. Return 0 if parameter should be passed in memory. */ static int examine_argument (enum x86_64_reg_class classes[MAX_CLASSES], int n, int *int_nregs, int *sse_nregs) { *int_nregs = 0; *sse_nregs = 0; if (!n) return 0; for (n--; n >= 0; n--) switch (classes[n]) { case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: (*int_nregs)++; break; case X86_64_SSE_CLASS: case X86_64_SSESF_CLASS: case X86_64_SSEDF_CLASS: (*sse_nregs)++; break; case X86_64_NO_CLASS: case X86_64_SSEUP_CLASS: case X86_64_X87_CLASS: case X86_64_X87UP_CLASS: break; case X86_64_MEMORY_CLASS: internal_error (__FILE__, __LINE__, "examine_argument: unexpected memory class"); } return 1; } #define RET_INT_REGS 2 #define RET_SSE_REGS 2 /* Check if the structure in value_type is returned in registers or in memory. If this function returns 1, GDB will call STORE_STRUCT_RETURN and EXTRACT_STRUCT_VALUE_ADDRESS else STORE_RETURN_VALUE and EXTRACT_RETURN_VALUE will be used. */ static int x86_64_use_struct_convention (int gcc_p, struct type *value_type) { enum x86_64_reg_class class[MAX_CLASSES]; int n = classify_argument (value_type, class, 0); int needed_intregs; int needed_sseregs; return (!n || !examine_argument (class, n, &needed_intregs, &needed_sseregs) || needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS); } /* Extract from an array REGBUF containing the (raw) register state, a function return value of TYPE, and copy that, in virtual format, into VALBUF. */ static void x86_64_extract_return_value (struct type *type, struct regcache *regcache, void *valbuf) { enum x86_64_reg_class class[MAX_CLASSES]; int n = classify_argument (type, class, 0); int needed_intregs; int needed_sseregs; int intreg = 0; int ssereg = 0; int offset = 0; int ret_int_r[RET_INT_REGS] = { X86_64_RAX_REGNUM, X86_64_RDX_REGNUM }; int ret_sse_r[RET_SSE_REGS] = { X86_64_XMM0_REGNUM, X86_64_XMM1_REGNUM }; if (!n || !examine_argument (class, n, &needed_intregs, &needed_sseregs) || needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS) { /* memory class */ CORE_ADDR addr; regcache_cooked_read (regcache, X86_64_RAX_REGNUM, &addr); read_memory (addr, valbuf, TYPE_LENGTH (type)); return; } else { int i; for (i = 0; i < n; i++) { switch (class[i]) { case X86_64_NO_CLASS: break; case X86_64_INTEGER_CLASS: regcache_cooked_read (regcache, ret_int_r[(intreg + 1) / 2], (char *) valbuf + offset); offset += 8; intreg += 2; break; case X86_64_INTEGERSI_CLASS: regcache_cooked_read_part (regcache, ret_int_r[intreg / 2], 0, 4, (char *) valbuf + offset); offset += 8; intreg++; break; case X86_64_SSEDF_CLASS: case X86_64_SSESF_CLASS: case X86_64_SSE_CLASS: regcache_cooked_read_part (regcache, ret_sse_r[(ssereg + 1) / 2], 0, 8, (char *) valbuf + offset); offset += 8; ssereg += 2; break; case X86_64_SSEUP_CLASS: regcache_cooked_read_part (regcache, ret_sse_r[ssereg / 2], 0, 8, (char *) valbuf + offset); offset += 8; ssereg++; break; case X86_64_X87_CLASS: regcache_cooked_read_part (regcache, X86_64_ST0_REGNUM, 0, 8, (char *) valbuf + offset); offset += 8; break; case X86_64_X87UP_CLASS: regcache_cooked_read_part (regcache, X86_64_ST0_REGNUM, 8, 2, (char *) valbuf + offset); offset += 8; break; case X86_64_MEMORY_CLASS: default: internal_error (__FILE__, __LINE__, "Unexpected argument class"); } } } } #define INT_REGS 6 #define SSE_REGS 8 static CORE_ADDR x86_64_push_arguments (struct regcache *regcache, int nargs, struct value **args, CORE_ADDR sp) { int intreg = 0; int ssereg = 0; int i; static int int_parameter_registers[INT_REGS] = { X86_64_RDI_REGNUM, 4, /* %rdi, %rsi */ X86_64_RDX_REGNUM, 2, /* %rdx, %rcx */ 8, 9 /* %r8, %r9 */ }; /* %xmm0 - %xmm7 */ static int sse_parameter_registers[SSE_REGS] = { X86_64_XMM0_REGNUM + 0, X86_64_XMM1_REGNUM, X86_64_XMM0_REGNUM + 2, X86_64_XMM0_REGNUM + 3, X86_64_XMM0_REGNUM + 4, X86_64_XMM0_REGNUM + 5, X86_64_XMM0_REGNUM + 6, X86_64_XMM0_REGNUM + 7, }; int stack_values_count = 0; int *stack_values; stack_values = alloca (nargs * sizeof (int)); for (i = 0; i < nargs; i++) { enum x86_64_reg_class class[MAX_CLASSES]; int n = classify_argument (args[i]->type, class, 0); int needed_intregs; int needed_sseregs; if (!n || !examine_argument (class, n, &needed_intregs, &needed_sseregs) || intreg / 2 + needed_intregs > INT_REGS || ssereg / 2 + needed_sseregs > SSE_REGS) { /* memory class */ stack_values[stack_values_count++] = i; } else { int j; int offset = 0; for (j = 0; j < n; j++) { switch (class[j]) { case X86_64_NO_CLASS: break; case X86_64_INTEGER_CLASS: regcache_cooked_write (regcache, int_parameter_registers[(intreg + 1) / 2], VALUE_CONTENTS_ALL (args[i]) + offset); offset += 8; intreg += 2; break; case X86_64_INTEGERSI_CLASS: { LONGEST val = extract_signed_integer (VALUE_CONTENTS_ALL (args[i]) + offset, 4); regcache_cooked_write_signed (regcache, int_parameter_registers[intreg / 2], val); offset += 8; intreg++; break; } case X86_64_SSEDF_CLASS: case X86_64_SSESF_CLASS: case X86_64_SSE_CLASS: regcache_cooked_write (regcache, sse_parameter_registers[(ssereg + 1) / 2], VALUE_CONTENTS_ALL (args[i]) + offset); offset += 8; ssereg += 2; break; case X86_64_SSEUP_CLASS: regcache_cooked_write (regcache, sse_parameter_registers[ssereg / 2], VALUE_CONTENTS_ALL (args[i]) + offset); offset += 8; ssereg++; break; case X86_64_X87_CLASS: case X86_64_MEMORY_CLASS: stack_values[stack_values_count++] = i; break; case X86_64_X87UP_CLASS: break; default: internal_error (__FILE__, __LINE__, "Unexpected argument class"); } intreg += intreg % 2; ssereg += ssereg % 2; } } } /* Push any remaining arguments onto the stack. */ while (--stack_values_count >= 0) { struct value *arg = args[stack_values[stack_values_count]]; int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)); /* Make sure the stack stays eightbyte-aligned. */ sp -= (len + 7) & ~7; write_memory (sp, VALUE_CONTENTS_ALL (arg), len); } return sp; } /* Write into the appropriate registers a function return value stored in VALBUF of type TYPE, given in virtual format. */ static void x86_64_store_return_value (struct type *type, struct regcache *regcache, const void *valbuf) { int len = TYPE_LENGTH (type); if (TYPE_CODE_FLT == TYPE_CODE (type)) { ULONGEST fstat; char buf[FPU_REG_RAW_SIZE]; /* Returning floating-point values is a bit tricky. Apart from storing the return value in %st(0), we have to simulate the state of the FPU at function return point. */ /* Convert the value found in VALBUF to the extended floating-point format used by the FPU. This is probably not exactly how it would happen on the target itself, but it is the best we can do. */ convert_typed_floating (valbuf, type, buf, builtin_type_i387_ext); regcache_raw_write (regcache, X86_64_ST0_REGNUM, buf); /* Set the top of the floating-point register stack to 7. The actual value doesn't really matter, but 7 is what a normal function return would end up with if the program started out with a freshly initialized FPU. */ regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat); fstat |= (7 << 11); regcache_raw_write_unsigned (regcache, FSTAT_REGNUM, fstat); /* Mark %st(1) through %st(7) as empty. Since we set the top of the floating-point register stack to 7, the appropriate value for the tag word is 0x3fff. */ regcache_raw_write_unsigned (regcache, FTAG_REGNUM, 0x3fff); } else { int low_size = REGISTER_RAW_SIZE (0); int high_size = REGISTER_RAW_SIZE (1); if (len <= low_size) regcache_cooked_write_part (regcache, 0, 0, len, valbuf); else if (len <= (low_size + high_size)) { regcache_cooked_write_part (regcache, 0, 0, low_size, valbuf); regcache_cooked_write_part (regcache, 1, 0, len - low_size, (const char *) valbuf + low_size); } else internal_error (__FILE__, __LINE__, "Cannot store return value of %d bytes long.", len); } } static CORE_ADDR x86_64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { char buf[8]; /* Pass arguments. */ sp = x86_64_push_arguments (regcache, nargs, args, sp); /* Pass "hidden" argument". */ if (struct_return) { store_unsigned_integer (buf, 8, struct_addr); regcache_cooked_write (regcache, X86_64_RDI_REGNUM, buf); } /* Store return address. */ sp -= 8; store_unsigned_integer (buf, 8, bp_addr); write_memory (sp, buf, 8); /* Finally, update the stack pointer... */ store_unsigned_integer (buf, 8, sp); regcache_cooked_write (regcache, X86_64_RSP_REGNUM, buf); /* ...and fake a frame pointer. */ regcache_cooked_write (regcache, X86_64_RBP_REGNUM, buf); return sp + 16; } /* The maximum number of saved registers. This should include %rip. */ #define X86_64_NUM_SAVED_REGS X86_64_NUM_GREGS struct x86_64_frame_cache { /* Base address. */ CORE_ADDR base; CORE_ADDR sp_offset; CORE_ADDR pc; /* Saved registers. */ CORE_ADDR saved_regs[X86_64_NUM_SAVED_REGS]; CORE_ADDR saved_sp; /* Do we have a frame? */ int frameless_p; }; /* Allocate and initialize a frame cache. */ static struct x86_64_frame_cache * x86_64_alloc_frame_cache (void) { struct x86_64_frame_cache *cache; int i; cache = FRAME_OBSTACK_ZALLOC (struct x86_64_frame_cache); /* Base address. */ cache->base = 0; cache->sp_offset = -8; cache->pc = 0; /* Saved registers. We initialize these to -1 since zero is a valid offset (that's where %rbp is supposed to be stored). */ for (i = 0; i < X86_64_NUM_SAVED_REGS; i++) cache->saved_regs[i] = -1; cache->saved_sp = 0; /* Frameless until proven otherwise. */ cache->frameless_p = 1; return cache; } /* 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. We will handle only functions beginning with: pushq %rbp 0x55 movq %rsp, %rbp 0x48 0x89 0xe5 Any function that doesn't start with this sequence will be assumed to have no prologue and thus no valid frame pointer in %rbp. */ static CORE_ADDR x86_64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc, struct x86_64_frame_cache *cache) { static unsigned char proto[3] = { 0x48, 0x89, 0xe5 }; unsigned char buf[3]; unsigned char op; if (current_pc <= pc) return current_pc; op = read_memory_unsigned_integer (pc, 1); if (op == 0x55) /* pushq %rbp */ { /* Take into account that we've executed the `pushq %rbp' that starts this instruction sequence. */ cache->saved_regs[X86_64_RBP_REGNUM] = 0; cache->sp_offset += 8; /* If that's all, return now. */ if (current_pc <= pc + 1) return current_pc; /* Check for `movq %rsp, %rbp'. */ read_memory (pc + 1, buf, 3); if (memcmp (buf, proto, 3) != 0) return pc + 1; /* OK, we actually have a frame. */ cache->frameless_p = 0; return pc + 4; } return pc; } /* Return PC of first real instruction. */ static CORE_ADDR x86_64_skip_prologue (CORE_ADDR start_pc) { struct x86_64_frame_cache cache; CORE_ADDR pc; pc = x86_64_analyze_prologue (start_pc, 0xffffffffffffffff, &cache); if (cache.frameless_p) return start_pc; return pc; } /* Normal frames. */ static struct x86_64_frame_cache * x86_64_frame_cache (struct frame_info *next_frame, void **this_cache) { struct x86_64_frame_cache *cache; char buf[8]; int i; if (*this_cache) return *this_cache; cache = x86_64_alloc_frame_cache (); *this_cache = cache; frame_unwind_register (next_frame, X86_64_RBP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 8); if (cache->base == 0) return cache; /* For normal frames, %rip is stored at 8(%rbp). */ cache->saved_regs[X86_64_RIP_REGNUM] = 8; cache->pc = frame_func_unwind (next_frame); if (cache->pc != 0) x86_64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache); if (cache->frameless_p) { /* We didn't find a valid frame, which means that CACHE->base currently holds the frame pointer for our calling frame. If we're at the start of a function, or somewhere half-way its prologue, the function's frame probably hasn't been fully setup yet. Try to reconstruct the base address for the stack frame by looking at the stack pointer. For truly "frameless" functions this might work too. */ frame_unwind_register (next_frame, X86_64_RSP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 8) + cache->sp_offset; } /* Now that we have the base address for the stack frame we can calculate the value of %rsp in the calling frame. */ cache->saved_sp = cache->base + 16; /* Adjust all the saved registers such that they contain addresses instead of offsets. */ for (i = 0; i < X86_64_NUM_SAVED_REGS; i++) if (cache->saved_regs[i] != -1) cache->saved_regs[i] += cache->base; return cache; } static void x86_64_frame_this_id (struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct x86_64_frame_cache *cache = x86_64_frame_cache (next_frame, this_cache); /* This marks the outermost frame. */ if (cache->base == 0) return; (*this_id) = frame_id_build (cache->base + 16, cache->pc); } static void x86_64_frame_prev_register (struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { struct x86_64_frame_cache *cache = x86_64_frame_cache (next_frame, this_cache); gdb_assert (regnum >= 0); if (regnum == SP_REGNUM && cache->saved_sp) { *optimizedp = 0; *lvalp = not_lval; *addrp = 0; *realnump = -1; if (valuep) { /* Store the value. */ store_unsigned_integer (valuep, 8, cache->saved_sp); } return; } if (regnum < X86_64_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1) { *optimizedp = 0; *lvalp = lval_memory; *addrp = cache->saved_regs[regnum]; *realnump = -1; if (valuep) { /* Read the value in from memory. */ read_memory (*addrp, valuep, register_size (current_gdbarch, regnum)); } return; } frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp, realnump, valuep); } static const struct frame_unwind x86_64_frame_unwind = { NORMAL_FRAME, x86_64_frame_this_id, x86_64_frame_prev_register }; static const struct frame_unwind * x86_64_frame_p (CORE_ADDR pc) { return &x86_64_frame_unwind; } /* Signal trampolines. */ /* FIXME: kettenis/20030419: Perhaps, we can unify the 32-bit and 64-bit variants. This would require using identical frame caches on both platforms. */ static struct x86_64_frame_cache * x86_64_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) { struct x86_64_frame_cache *cache; struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); CORE_ADDR addr; char buf[8]; int i; if (*this_cache) return *this_cache; cache = x86_64_alloc_frame_cache (); frame_unwind_register (next_frame, X86_64_RSP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 8) - 8; addr = tdep->sigcontext_addr (next_frame); gdb_assert (tdep->sc_reg_offset); gdb_assert (tdep->sc_num_regs <= X86_64_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]; *this_cache = cache; return cache; } static void x86_64_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { struct x86_64_frame_cache *cache = x86_64_sigtramp_frame_cache (next_frame, this_cache); (*this_id) = frame_id_build (cache->base + 16, frame_pc_unwind (next_frame)); } static void x86_64_sigtramp_frame_prev_register (struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { /* Make sure we've initialized the cache. */ x86_64_sigtramp_frame_cache (next_frame, this_cache); x86_64_frame_prev_register (next_frame, this_cache, regnum, optimizedp, lvalp, addrp, realnump, valuep); } static const struct frame_unwind x86_64_sigtramp_frame_unwind = { SIGTRAMP_FRAME, x86_64_sigtramp_frame_this_id, x86_64_sigtramp_frame_prev_register }; static const struct frame_unwind * x86_64_sigtramp_frame_p (CORE_ADDR pc) { char *name; find_pc_partial_function (pc, &name, NULL, NULL); if (PC_IN_SIGTRAMP (pc, name)) { gdb_assert (gdbarch_tdep (current_gdbarch)->sigcontext_addr); return &x86_64_sigtramp_frame_unwind; } return NULL; } static CORE_ADDR x86_64_frame_base_address (struct frame_info *next_frame, void **this_cache) { struct x86_64_frame_cache *cache = x86_64_frame_cache (next_frame, this_cache); return cache->base; } static const struct frame_base x86_64_frame_base = { &x86_64_frame_unwind, x86_64_frame_base_address, x86_64_frame_base_address, x86_64_frame_base_address }; static struct frame_id x86_64_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) { char buf[8]; CORE_ADDR fp; frame_unwind_register (next_frame, X86_64_RBP_REGNUM, buf); fp = extract_unsigned_integer (buf, 8); return frame_id_build (fp + 16, frame_pc_unwind (next_frame)); } void x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* The x86-64 has 16 SSE registers. */ tdep->num_xmm_regs = 16; /* This is what all the fuss is about. */ set_gdbarch_long_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); set_gdbarch_ptr_bit (gdbarch, 64); /* In contrast to the i386, on the x86-64 a `long double' actually takes up 128 bits, even though it's still based on the i387 extended floating-point format which has only 80 significant bits. */ set_gdbarch_long_double_bit (gdbarch, 128); set_gdbarch_num_regs (gdbarch, X86_64_NUM_REGS); set_gdbarch_register_name (gdbarch, x86_64_register_name); set_gdbarch_register_type (gdbarch, x86_64_register_type); /* Register numbers of various important registers. */ set_gdbarch_sp_regnum (gdbarch, X86_64_RSP_REGNUM); /* %rsp */ set_gdbarch_pc_regnum (gdbarch, X86_64_RIP_REGNUM); /* %rip */ set_gdbarch_ps_regnum (gdbarch, X86_64_EFLAGS_REGNUM); /* %eflags */ set_gdbarch_fp0_regnum (gdbarch, X86_64_ST0_REGNUM); /* %st(0) */ /* The "default" register numbering scheme for the x86-64 is referred to as the "DWARF Register Number Mapping" in the System V psABI. The preferred debugging format for all known x86-64 targets is actually DWARF2, and GCC doesn't seem to support DWARF (that is DWARF-1), but we provide the same mapping just in case. This mapping is also used for stabs, which GCC does support. */ set_gdbarch_stab_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum); set_gdbarch_dwarf_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum); /* We don't override SDB_REG_RO_REGNUM, since COFF doesn't seem to be in use on any of the supported x86-64 targets. */ /* Call dummy code. */ set_gdbarch_push_dummy_call (gdbarch, x86_64_push_dummy_call); set_gdbarch_convert_register_p (gdbarch, x86_64_convert_register_p); set_gdbarch_register_to_value (gdbarch, i387_register_to_value); set_gdbarch_value_to_register (gdbarch, i387_value_to_register); set_gdbarch_extract_return_value (gdbarch, x86_64_extract_return_value); set_gdbarch_store_return_value (gdbarch, x86_64_store_return_value); /* Override, since this is handled by x86_64_extract_return_value. */ set_gdbarch_extract_struct_value_address (gdbarch, NULL); set_gdbarch_use_struct_convention (gdbarch, x86_64_use_struct_convention); set_gdbarch_skip_prologue (gdbarch, x86_64_skip_prologue); /* Avoid wiring in the MMX registers for now. */ set_gdbarch_num_pseudo_regs (gdbarch, 0); set_gdbarch_unwind_dummy_id (gdbarch, x86_64_unwind_dummy_id); /* FIXME: kettenis/20021026: This is ELF-specific. Fine for now, since all supported x86-64 targets are ELF, but that might change in the future. */ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); frame_unwind_append_predicate (gdbarch, x86_64_sigtramp_frame_p); frame_unwind_append_predicate (gdbarch, x86_64_frame_p); frame_base_set_default (gdbarch, &x86_64_frame_base); } #define I387_FISEG_REGNUM FISEG_REGNUM #define I387_FOSEG_REGNUM FOSEG_REGNUM /* The 64-bit FXSAVE format differs from the 32-bit format in the sense that the instruction pointer and data pointer are simply 64-bit offsets into the code segment and the data segment instead of a selector offset pair. The functions below store the upper 32 bits of these pointers (instead of just the 16-bits of the segment selector). */ /* Fill GDB's register array with the floating-point and SSE register values in *FXSAVE. This function masks off any of the reserved bits in *FXSAVE. */ void x86_64_supply_fxsave (char *fxsave) { i387_supply_fxsave (fxsave); if (fxsave) { supply_register (I387_FISEG_REGNUM, fxsave + 12); supply_register (I387_FOSEG_REGNUM, fxsave + 20); } } /* Fill register REGNUM (if it is a floating-point or SSE register) in *FXSAVE with the value in GDB's register array. If REGNUM is -1, do this for all registers. This function doesn't touch any of the reserved bits in *FXSAVE. */ void x86_64_fill_fxsave (char *fxsave, int regnum) { i387_fill_fxsave (fxsave, regnum); if (regnum == -1 || regnum == I387_FISEG_REGNUM) regcache_collect (I387_FISEG_REGNUM, fxsave + 12); if (regnum == -1 || regnum == I387_FOSEG_REGNUM) regcache_collect (I387_FOSEG_REGNUM, fxsave + 20); }