/* Intel 386 target-dependent stuff.
- Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GDB.
#include "dummy-frame.h"
#include "dwarf2-frame.h"
#include "doublest.h"
-#include "floatformat.h"
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
#include "inferior.h"
#include "gdbcmd.h"
#include "gdbcore.h"
+#include "gdbtypes.h"
#include "objfiles.h"
#include "osabi.h"
#include "regcache.h"
}
/* This will hopefully provoke a warning. */
- return NUM_REGS + NUM_PSEUDO_REGS;
+ return gdbarch_num_regs (current_gdbarch)
+ + gdbarch_num_pseudo_regs (current_gdbarch);
}
/* Convert SVR4 register number REG to the appropriate register number
}
/* This will hopefully provoke a warning. */
- return NUM_REGS + NUM_PSEUDO_REGS;
+ return gdbarch_num_regs (current_gdbarch)
+ + gdbarch_num_pseudo_regs (current_gdbarch);
}
#undef I387_ST0_REGNUM
/* Saved registers. */
CORE_ADDR saved_regs[I386_NUM_SAVED_REGS];
CORE_ADDR saved_sp;
+ int stack_align;
int pc_in_eax;
/* Stack space reserved for local variables. */
for (i = 0; i < I386_NUM_SAVED_REGS; i++)
cache->saved_regs[i] = -1;
cache->saved_sp = 0;
+ cache->stack_align = 0;
cache->pc_in_eax = 0;
/* Frameless until proven otherwise. */
long delta = 0;
int data16 = 0;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x66)
{
data16 = 1;
if (current_pc <= pc)
return pc;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op != 0x58) /* popl %eax */
return pc;
- read_memory (pc + 1, buf, 4);
+ read_memory_nobpt (pc + 1, buf, 4);
if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
return pc;
gdb_byte buf[8];
gdb_byte op;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x68 || op == 0x6a)
{
return pc;
}
+/* GCC 4.1 and later, can put code in the prologue to realign the
+ stack pointer. Check whether PC points to such code, and update
+ CACHE accordingly. Return the first instruction after the code
+ sequence or CURRENT_PC, whichever is smaller. If we don't
+ recognize the code, return PC. */
+
+static CORE_ADDR
+i386_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct i386_frame_cache *cache)
+{
+ /* The register used by the compiler to perform the stack re-alignment
+ is, in order of preference, either %ecx, %edx, or %eax. GCC should
+ never use %ebx as it always treats it as callee-saved, whereas
+ the compiler can only use caller-saved registers. */
+ static const gdb_byte insns_ecx[10] = {
+ 0x8d, 0x4c, 0x24, 0x04, /* leal 4(%esp), %ecx */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x71, 0xfc /* pushl -4(%ecx) */
+ };
+ static const gdb_byte insns_edx[10] = {
+ 0x8d, 0x54, 0x24, 0x04, /* leal 4(%esp), %edx */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x72, 0xfc /* pushl -4(%edx) */
+ };
+ static const gdb_byte insns_eax[10] = {
+ 0x8d, 0x44, 0x24, 0x04, /* leal 4(%esp), %eax */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x70, 0xfc /* pushl -4(%eax) */
+ };
+ gdb_byte buf[10];
+
+ if (target_read_memory (pc, buf, sizeof buf)
+ || (memcmp (buf, insns_ecx, sizeof buf) != 0
+ && memcmp (buf, insns_edx, sizeof buf) != 0
+ && memcmp (buf, insns_eax, sizeof buf) != 0))
+ return pc;
+
+ if (current_pc > pc + 4)
+ cache->stack_align = 1;
+
+ return min (pc + 10, current_pc);
+}
+
/* Maximum instruction length we need to handle. */
#define I386_MAX_INSN_LEN 6
struct i386_insn *insn;
gdb_byte op;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
for (insn = skip_insns; insn->len > 0; insn++)
{
gdb_assert (insn->len > 1);
gdb_assert (insn->len <= I386_MAX_INSN_LEN);
- read_memory (pc + 1, buf, insn->len - 1);
+ read_memory_nobpt (pc + 1, buf, insn->len - 1);
for (i = 1; i < insn->len; i++)
{
if ((buf[i - 1] & insn->mask[i]) != insn->insn[i])
if (limit <= pc)
return limit;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x55) /* pushl %ebp */
{
if (limit <= pc + skip)
return limit;
- op = read_memory_unsigned_integer (pc + skip, 1);
+ read_memory_nobpt (pc + skip, &op, 1);
/* Check for `movl %esp, %ebp' -- can be written in two ways. */
switch (op)
NOTE: You can't subtract a 16-bit immediate from a 32-bit
reg, so we don't have to worry about a data16 prefix. */
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x83)
{
/* `subl' with 8-bit immediate. */
offset -= cache->locals;
for (i = 0; i < 8 && pc < current_pc; i++)
{
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op < 0x50 || op > 0x57)
break;
pc = i386_follow_jump (pc);
pc = i386_analyze_struct_return (pc, current_pc, cache);
pc = i386_skip_probe (pc);
+ pc = i386_analyze_stack_align (pc, current_pc, cache);
pc = i386_analyze_frame_setup (pc, current_pc, cache);
return i386_analyze_register_saves (pc, current_pc, cache);
}
for (i = 0; i < 6; i++)
{
- op = read_memory_unsigned_integer (pc + i, 1);
+ read_memory_nobpt (pc + i, &op, 1);
if (pic_pat[i] != op)
break;
}
{
int delta = 6;
- op = read_memory_unsigned_integer (pc + delta, 1);
+ read_memory_nobpt (pc + delta, &op, 1);
if (op == 0x89) /* movl %ebx, x(%ebp) */
{
else /* Unexpected instruction. */
delta = 0;
- op = read_memory_unsigned_integer (pc + delta, 1);
+ read_memory_nobpt (pc + delta, &op, 1);
}
/* addl y,%ebx */
if (delta > 0 && op == 0x81
- && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3);
+ && read_memory_unsigned_integer (pc + delta + 1, 1) == 0xc3)
{
pc += delta + 6;
}
{
gdb_byte buf[8];
- frame_unwind_register (next_frame, PC_REGNUM, buf);
+ frame_unwind_register (next_frame, gdbarch_pc_regnum (current_gdbarch), buf);
return extract_typed_address (buf, builtin_type_void_func_ptr);
}
\f
/* For normal frames, %eip is stored at 4(%ebp). */
cache->saved_regs[I386_EIP_REGNUM] = 4;
- cache->pc = frame_func_unwind (next_frame);
+ cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
if (cache->pc != 0)
i386_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
+ if (cache->stack_align)
+ {
+ /* Saved stack pointer has been saved in %ecx. */
+ frame_unwind_register (next_frame, I386_ECX_REGNUM, buf);
+ cache->saved_sp = extract_unsigned_integer(buf, 4);
+ }
+
if (cache->locals < 0)
{
/* We didn't find a valid frame, which means that CACHE->base
frame by looking at the stack pointer. For truly "frameless"
functions this might work too. */
- frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+ if (cache->stack_align)
+ {
+ /* We're halfway aligning the stack. */
+ cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
+ cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
+
+ /* This will be added back below. */
+ cache->saved_regs[I386_EIP_REGNUM] -= cache->base;
+ }
+ else
+ {
+ frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
+ }
}
/* Now that we have the base address for the stack frame we can
calculate the value of %esp in the calling frame. */
- cache->saved_sp = cache->base + 8;
+ if (cache->saved_sp == 0)
+ cache->saved_sp = cache->base + 8;
/* Adjust all the saved registers such that they contain addresses
instead of offsets. */
This function is 64-bit safe. */
static int
-i386_get_longjmp_target (CORE_ADDR *pc)
+i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
{
gdb_byte buf[8];
CORE_ADDR sp, jb_addr;
- int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
+ int jb_pc_offset = gdbarch_tdep (get_frame_arch (frame))->jb_pc_offset;
int len = TYPE_LENGTH (builtin_type_void_func_ptr);
/* If JB_PC_OFFSET is -1, we have no way to find out where the
/* Don't use I386_ESP_REGNUM here, since this function is also used
for AMD64. */
- regcache_cooked_read (current_regcache, SP_REGNUM, buf);
+ get_frame_register (frame, gdbarch_sp_regnum (current_gdbarch), buf);
sp = extract_typed_address (buf, builtin_type_void_data_ptr);
if (target_read_memory (sp + len, buf, len))
return 0;
multiple of [32-bit] words. This may require tail padding,
depending on the size of the argument."
- This makes sure the stack says word-aligned. */
+ This makes sure the stack stays word-aligned. */
sp -= (len + 3) & ~3;
write_memory (sp, value_contents_all (args[i]), len);
}
/* Type for %eflags. */
struct type *i386_eflags_type;
-/* Types for the MMX and SSE registers. */
-struct type *i386_mmx_type;
-struct type *i386_sse_type;
+/* Type for %mxcsr. */
+struct type *i386_mxcsr_type;
/* Construct types for ISA-specific registers. */
static void
append_flags_type_flag (type, 21, "ID");
i386_eflags_type = type;
- /* The type we're building is this: */
+ type = init_flags_type ("builtin_type_i386_mxcsr", 4);
+ append_flags_type_flag (type, 0, "IE");
+ append_flags_type_flag (type, 1, "DE");
+ append_flags_type_flag (type, 2, "ZE");
+ append_flags_type_flag (type, 3, "OE");
+ append_flags_type_flag (type, 4, "UE");
+ append_flags_type_flag (type, 5, "PE");
+ append_flags_type_flag (type, 6, "DAZ");
+ append_flags_type_flag (type, 7, "IM");
+ append_flags_type_flag (type, 8, "DM");
+ append_flags_type_flag (type, 9, "ZM");
+ append_flags_type_flag (type, 10, "OM");
+ append_flags_type_flag (type, 11, "UM");
+ append_flags_type_flag (type, 12, "PM");
+ append_flags_type_flag (type, 15, "FZ");
+ i386_mxcsr_type = type;
+}
+
+/* Construct vector type for MMX registers. */
+struct type *
+i386_mmx_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->i386_mmx_type)
+ {
+ /* The type we're building is this: */
#if 0
- union __gdb_builtin_type_vec64i
- {
- int64_t uint64;
- int32_t v2_int32[2];
- int16_t v4_int16[4];
- int8_t v8_int8[8];
- };
+ union __gdb_builtin_type_vec64i
+ {
+ int64_t uint64;
+ int32_t v2_int32[2];
+ int16_t v4_int16[4];
+ int8_t v8_int8[8];
+ };
#endif
- type = init_composite_type ("__gdb_builtin_type_vec64i", TYPE_CODE_UNION);
- append_composite_type_field (type, "uint64", builtin_type_int64);
- append_composite_type_field (type, "v2_int32", builtin_type_v2_int32);
- append_composite_type_field (type, "v4_int16", builtin_type_v4_int16);
- append_composite_type_field (type, "v8_int8", builtin_type_v8_int8);
- TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
- TYPE_NAME (type) = "builtin_type_vec64i";
- i386_mmx_type = type;
+ struct type *t;
+
+ t = init_composite_type ("__gdb_builtin_type_vec64i", TYPE_CODE_UNION);
+ append_composite_type_field (t, "uint64", builtin_type_int64);
+ append_composite_type_field (t, "v2_int32",
+ init_vector_type (builtin_type_int32, 2));
+ append_composite_type_field (t, "v4_int16",
+ init_vector_type (builtin_type_int16, 4));
+ append_composite_type_field (t, "v8_int8",
+ init_vector_type (builtin_type_int8, 8));
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_NAME (t) = "builtin_type_vec64i";
+ tdep->i386_mmx_type = t;
+ }
- /* The type we're building is this: */
+ return tdep->i386_mmx_type;
+}
+
+struct type *
+i386_sse_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->i386_sse_type)
+ {
+ /* The type we're building is this: */
#if 0
- union __gdb_builtin_type_vec128i
- {
- int128_t uint128;
- int64_t v2_int64[2];
- int32_t v4_int32[4];
- int16_t v8_int16[8];
- int8_t v16_int8[16];
- double v2_double[2];
- float v4_float[4];
- };
+ union __gdb_builtin_type_vec128i
+ {
+ int128_t uint128;
+ int64_t v2_int64[2];
+ int32_t v4_int32[4];
+ int16_t v8_int16[8];
+ int8_t v16_int8[16];
+ double v2_double[2];
+ float v4_float[4];
+ };
#endif
- type = init_composite_type ("__gdb_builtin_type_vec128i", TYPE_CODE_UNION);
- append_composite_type_field (type, "v4_float", builtin_type_v4_float);
- append_composite_type_field (type, "v2_double", builtin_type_v2_double);
- append_composite_type_field (type, "v16_int8", builtin_type_v16_int8);
- append_composite_type_field (type, "v8_int16", builtin_type_v8_int16);
- append_composite_type_field (type, "v4_int32", builtin_type_v4_int32);
- append_composite_type_field (type, "v2_int64", builtin_type_v2_int64);
- append_composite_type_field (type, "uint128", builtin_type_int128);
- TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
- TYPE_NAME (type) = "builtin_type_vec128i";
- i386_sse_type = type;
+ struct type *t;
+
+ t = init_composite_type ("__gdb_builtin_type_vec128i", TYPE_CODE_UNION);
+ append_composite_type_field (t, "v4_float",
+ init_vector_type (builtin_type_float, 4));
+ append_composite_type_field (t, "v2_double",
+ init_vector_type (builtin_type_double, 2));
+ append_composite_type_field (t, "v16_int8",
+ init_vector_type (builtin_type_int8, 16));
+ append_composite_type_field (t, "v8_int16",
+ init_vector_type (builtin_type_int16, 8));
+ append_composite_type_field (t, "v4_int32",
+ init_vector_type (builtin_type_int32, 4));
+ append_composite_type_field (t, "v2_int64",
+ init_vector_type (builtin_type_int64, 2));
+ append_composite_type_field (t, "uint128", builtin_type_int128);
+
+ TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+ TYPE_NAME (t) = "builtin_type_vec128i";
+ tdep->i386_sse_type = t;
+ }
+
+ return tdep->i386_sse_type;
}
/* Return the GDB type object for the "standard" data type of data in
if (i386_fp_regnum_p (regnum))
return builtin_type_i387_ext;
+ if (i386_mmx_regnum_p (gdbarch, regnum))
+ return i386_mmx_type (gdbarch);
+
if (i386_sse_regnum_p (gdbarch, regnum))
- return i386_sse_type;
+ return i386_sse_type (gdbarch);
- if (i386_mmx_regnum_p (gdbarch, regnum))
- return i386_mmx_type;
+#define I387_ST0_REGNUM I386_ST0_REGNUM
+#define I387_NUM_XMM_REGS (gdbarch_tdep (current_gdbarch)->num_xmm_regs)
+
+ if (regnum == I387_MXCSR_REGNUM)
+ return i386_mxcsr_type;
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
return builtin_type_int;
}
tdep->jb_pc_offset = 36;
}
-
-/* NetWare. */
-
-static void
-i386_nw_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- tdep->jb_pc_offset = 24;
-}
\f
/* i386 register groups. In addition to the normal groups, add "mmx"
return arches->gdbarch;
/* Allocate space for the new architecture. */
- tdep = XMALLOC (struct gdbarch_tdep);
+ tdep = XCALLOC (1, struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* General-purpose registers. */
the i387 extended floating-point format. In fact, of all targets
in the GCC 2.95 tree, only OSF/1 does it different, and insists
on having a `long double' that's not `long' at all. */
- set_gdbarch_long_double_format (gdbarch, &floatformat_i387_ext);
+ set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
/* Although the i387 extended floating-point has only 80 significant
bits, a `long double' actually takes up 96, probably to enforce
set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
- /* We don't define ECOFF_REG_TO_REGNUM, since ECOFF doesn't seem to
+ /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
be in use on any of the supported i386 targets. */
set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
return GDB_OSABI_UNKNOWN;
}
-
-static enum gdb_osabi
-i386_nlm_osabi_sniffer (bfd *abfd)
-{
- return GDB_OSABI_NETWARE;
-}
\f
/* Provide a prototype to silence -Wmissing-prototypes. */
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);
- gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_nlm_flavour,
- i386_nlm_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_SVR4,
i386_svr4_init_abi);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_GO32,
i386_go32_init_abi);
- gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETWARE,
- i386_nw_init_abi);
/* Initialize the i386-specific register groups & types. */
i386_init_reggroups ();