/* Intel 386 target-dependent stuff.
- Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GDB.
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "arch-utils.h"
#include "i386-tdep.h"
#include "i387-tdep.h"
-/* Names of the registers. The first 10 registers match the register
- numbering scheme used by GCC for stabs and DWARF. */
+/* Register names. */
static char *i386_register_names[] =
{
static const int i386_num_register_names = ARRAY_SIZE (i386_register_names);
-/* MMX registers. */
+/* Register names for MMX pseudo-registers. */
static char *i386_mmx_names[] =
{
return (I387_FCTRL_REGNUM <= regnum && regnum < I387_XMM0_REGNUM);
}
-/* Return the name of register REG. */
+/* Return the name of register REGNUM. */
const char *
-i386_register_name (int reg)
+i386_register_name (int regnum)
{
- if (i386_mmx_regnum_p (current_gdbarch, reg))
- return i386_mmx_names[reg - I387_MM0_REGNUM];
+ if (i386_mmx_regnum_p (current_gdbarch, regnum))
+ return i386_mmx_names[regnum - I387_MM0_REGNUM];
- if (reg >= 0 && reg < i386_num_register_names)
- return i386_register_names[reg];
+ if (regnum >= 0 && regnum < i386_num_register_names)
+ return i386_register_names[regnum];
return NULL;
}
-/* Convert stabs register number REG to the appropriate register
+/* Convert a dbx register number REG to the appropriate register
number used by GDB. */
static int
-i386_stab_reg_to_regnum (int reg)
+i386_dbx_reg_to_regnum (int reg)
{
- /* This implements what GCC calls the "default" register map. */
+ /* This implements what GCC calls the "default" register map
+ (dbx_register_map[]). */
+
if (reg >= 0 && reg <= 7)
{
- /* General-purpose registers. */
- return reg;
+ /* General-purpose registers. The debug info calls %ebp
+ register 4, and %esp register 5. */
+ if (reg == 4)
+ return 5;
+ else if (reg == 5)
+ return 4;
+ else return reg;
}
else if (reg >= 12 && reg <= 19)
{
return NUM_REGS + NUM_PSEUDO_REGS;
}
-/* Convert DWARF register number REG to the appropriate register
- number used by GDB. */
+/* Convert SVR4 register number REG to the appropriate register number
+ used by GDB. */
static int
-i386_dwarf_reg_to_regnum (int reg)
+i386_svr4_reg_to_regnum (int reg)
{
- /* The DWARF register numbering includes %eip and %eflags, and
+ /* This implements the GCC register map that tries to be compatible
+ with the SVR4 C compiler for DWARF (svr4_dbx_register_map[]). */
+
+ /* The SVR4 register numbering includes %eip and %eflags, and
numbers the floating point registers differently. */
if (reg >= 0 && reg <= 9)
{
/* Floating-point registers. */
return reg - 11 + I387_ST0_REGNUM;
}
- else if (reg >= 21)
+ else if (reg >= 21 && reg <= 36)
+ {
+ /* The SSE and MMX registers have the same numbers as with dbx. */
+ return i386_dbx_reg_to_regnum (reg);
+ }
+
+ switch (reg)
{
- /* The SSE and MMX registers have identical numbers as in stabs. */
- return i386_stab_reg_to_regnum (reg);
+ case 37: return I387_FCTRL_REGNUM;
+ case 38: return I387_FSTAT_REGNUM;
+ case 39: return I387_MXCSR_REGNUM;
+ case 40: return I386_ES_REGNUM;
+ case 41: return I386_CS_REGNUM;
+ case 42: return I386_SS_REGNUM;
+ case 43: return I386_DS_REGNUM;
+ case 44: return I386_FS_REGNUM;
+ case 45: return I386_GS_REGNUM;
}
/* This will hopefully provoke a warning. */
and can be inserted anywhere.
This function is 64-bit safe. */
-
-static const unsigned char *
+
+static const gdb_byte *
i386_breakpoint_from_pc (CORE_ADDR *pc, int *len)
{
- static unsigned char break_insn[] = { 0xcc }; /* int 3 */
-
+ static gdb_byte break_insn[] = { 0xcc }; /* int 3 */
+
*len = sizeof (break_insn);
return break_insn;
}
{
/* Base address. */
CORE_ADDR base;
- CORE_ADDR sp_offset;
+ LONGEST sp_offset;
CORE_ADDR pc;
/* 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. */
static CORE_ADDR
i386_follow_jump (CORE_ADDR pc)
{
- unsigned char op;
+ gdb_byte op;
long delta = 0;
int data16 = 0;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x66)
{
data16 = 1;
and the assembler doesn't try to optimize it, so the 'sib' form
gets generated). This sequence is used to get the address of the
return buffer for a function that returns a structure. */
- static unsigned char proto1[3] = { 0x87, 0x04, 0x24 };
- static unsigned char proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
- unsigned char buf[4];
- unsigned char op;
+ static gdb_byte proto1[3] = { 0x87, 0x04, 0x24 };
+ static gdb_byte proto2[4] = { 0x87, 0x44, 0x24, 0x00 };
+ gdb_byte buf[4];
+ gdb_byte op;
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;
pushl %ebp
etc. */
- unsigned char buf[8];
- unsigned char op;
+ 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)
+{
+ static const gdb_byte insns[10] = {
+ 0x8d, 0x4c, 0x24, 0x04, /* leal 4(%esp), %ecx */
+ 0x83, 0xe4, 0xf0, /* andl $-16, %esp */
+ 0xff, 0x71, 0xfc /* pushl -4(%ecx) */
+ };
+ gdb_byte buf[10];
+
+ if (target_read_memory (pc, buf, sizeof buf)
+ || memcmp (buf, insns, 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
+
+/* Instruction description. */
+struct i386_insn
+{
+ size_t len;
+ gdb_byte insn[I386_MAX_INSN_LEN];
+ gdb_byte mask[I386_MAX_INSN_LEN];
+};
+
+/* Search for the instruction at PC in the list SKIP_INSNS. Return
+ the first instruction description that matches. Otherwise, return
+ NULL. */
+
+static struct i386_insn *
+i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns)
+{
+ struct i386_insn *insn;
+ gdb_byte op;
+
+ read_memory_nobpt (pc, &op, 1);
+
+ for (insn = skip_insns; insn->len > 0; insn++)
+ {
+ if ((op & insn->mask[0]) == insn->insn[0])
+ {
+ gdb_byte buf[I386_MAX_INSN_LEN - 1];
+ int insn_matched = 1;
+ size_t i;
+
+ gdb_assert (insn->len > 1);
+ gdb_assert (insn->len <= I386_MAX_INSN_LEN);
+
+ 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])
+ insn_matched = 0;
+ }
+
+ if (insn_matched)
+ return insn;
+ }
+ }
+
+ return NULL;
+}
+
+/* Some special instructions that might be migrated by GCC into the
+ part of the prologue that sets up the new stack frame. Because the
+ stack frame hasn't been setup yet, no registers have been saved
+ yet, and only the scratch registers %eax, %ecx and %edx can be
+ touched. */
+
+struct i386_insn i386_frame_setup_skip_insns[] =
+{
+ /* Check for `movb imm8, r' and `movl imm32, r'.
+
+ ??? Should we handle 16-bit operand-sizes here? */
+
+ /* `movb imm8, %al' and `movb imm8, %ah' */
+ /* `movb imm8, %cl' and `movb imm8, %ch' */
+ { 2, { 0xb0, 0x00 }, { 0xfa, 0x00 } },
+ /* `movb imm8, %dl' and `movb imm8, %dh' */
+ { 2, { 0xb2, 0x00 }, { 0xfb, 0x00 } },
+ /* `movl imm32, %eax' and `movl imm32, %ecx' */
+ { 5, { 0xb8 }, { 0xfe } },
+ /* `movl imm32, %edx' */
+ { 5, { 0xba }, { 0xff } },
+
+ /* Check for `mov imm32, r32'. Note that there is an alternative
+ encoding for `mov m32, %eax'.
+
+ ??? Should we handle SIB adressing here?
+ ??? Should we handle 16-bit operand-sizes here? */
+
+ /* `movl m32, %eax' */
+ { 5, { 0xa1 }, { 0xff } },
+ /* `movl m32, %eax' and `mov; m32, %ecx' */
+ { 6, { 0x89, 0x05 }, {0xff, 0xf7 } },
+ /* `movl m32, %edx' */
+ { 6, { 0x89, 0x15 }, {0xff, 0xff } },
+
+ /* Check for `xorl r32, r32' and the equivalent `subl r32, r32'.
+ Because of the symmetry, there are actually two ways to encode
+ these instructions; opcode bytes 0x29 and 0x2b for `subl' and
+ opcode bytes 0x31 and 0x33 for `xorl'. */
+
+ /* `subl %eax, %eax' */
+ { 2, { 0x29, 0xc0 }, { 0xfd, 0xff } },
+ /* `subl %ecx, %ecx' */
+ { 2, { 0x29, 0xc9 }, { 0xfd, 0xff } },
+ /* `subl %edx, %edx' */
+ { 2, { 0x29, 0xd2 }, { 0xfd, 0xff } },
+ /* `xorl %eax, %eax' */
+ { 2, { 0x31, 0xc0 }, { 0xfd, 0xff } },
+ /* `xorl %ecx, %ecx' */
+ { 2, { 0x31, 0xc9 }, { 0xfd, 0xff } },
+ /* `xorl %edx, %edx' */
+ { 2, { 0x31, 0xd2 }, { 0xfd, 0xff } },
+ { 0 }
+};
+
/* Check whether PC points at a code that sets up a new stack frame.
If so, it updates CACHE and returns the address of the first
- instruction after the sequence that sets removes the "hidden"
- argument from the stack or CURRENT_PC, whichever is smaller.
- Otherwise, return PC. */
+ instruction after the sequence that sets up the frame or LIMIT,
+ whichever is smaller. If we don't recognize the code, return PC. */
static CORE_ADDR
-i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
+i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR limit,
struct i386_frame_cache *cache)
{
- unsigned char op;
+ struct i386_insn *insn;
+ gdb_byte op;
int skip = 0;
- if (current_pc <= pc)
- return current_pc;
+ if (limit <= pc)
+ return limit;
- op = read_memory_unsigned_integer (pc, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x55) /* pushl %ebp */
{
starts this instruction sequence. */
cache->saved_regs[I386_EBP_REGNUM] = 0;
cache->sp_offset += 4;
+ pc++;
/* If that's all, return now. */
- if (current_pc <= pc + 1)
- return current_pc;
+ if (limit <= pc)
+ return limit;
- op = read_memory_unsigned_integer (pc + 1, 1);
-
- /* Check for some special instructions that might be migrated
- by GCC into the prologue. We check for
-
- xorl %ebx, %ebx
- xorl %ecx, %ecx
- xorl %edx, %edx
- xorl %eax, %eax
-
- and the equivalent
-
- subl %ebx, %ebx
- subl %ecx, %ecx
- subl %edx, %edx
- subl %eax, %eax
+ /* Check for some special instructions that might be migrated by
+ GCC into the prologue and skip them. At this point in the
+ prologue, code should only touch the scratch registers %eax,
+ %ecx and %edx, so while the number of posibilities is sheer,
+ it is limited.
Make sure we only skip these instructions if we later see the
`movl %esp, %ebp' that actually sets up the frame. */
- while (op == 0x29 || op == 0x31)
+ while (pc + skip < limit)
{
- op = read_memory_unsigned_integer (pc + skip + 2, 1);
- switch (op)
- {
- case 0xdb: /* %ebx */
- case 0xc9: /* %ecx */
- case 0xd2: /* %edx */
- case 0xc0: /* %eax */
- skip += 2;
- break;
- default:
- return pc + 1;
- }
+ insn = i386_match_insn (pc + skip, i386_frame_setup_skip_insns);
+ if (insn == NULL)
+ break;
- op = read_memory_unsigned_integer (pc + skip + 1, 1);
+ skip += insn->len;
}
+ /* If that's all, return now. */
+ if (limit <= pc + skip)
+ return limit;
+
+ read_memory_nobpt (pc + skip, &op, 1);
+
/* Check for `movl %esp, %ebp' -- can be written in two ways. */
switch (op)
{
case 0x8b:
- if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xec)
- return pc + 1;
+ if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xec)
+ return pc;
break;
case 0x89:
- if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xe5)
- return pc + 1;
+ if (read_memory_unsigned_integer (pc + skip + 1, 1) != 0xe5)
+ return pc;
break;
default:
- return pc + 1;
+ return pc;
}
/* OK, we actually have a frame. We just don't know how large
necessary. We also now commit to skipping the special
instructions mentioned before. */
cache->locals = 0;
- pc += skip;
+ pc += (skip + 2);
/* If that's all, return now. */
- if (current_pc <= pc + 3)
- return current_pc;
+ if (limit <= pc)
+ return limit;
/* Check for stack adjustment
subl $XXX, %esp
- NOTE: You can't subtract a 16 bit immediate from a 32 bit
+ 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 + 3, 1);
+ read_memory_nobpt (pc, &op, 1);
if (op == 0x83)
{
- /* `subl' with 8 bit immediate. */
- if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
+ /* `subl' with 8-bit immediate. */
+ if (read_memory_unsigned_integer (pc + 1, 1) != 0xec)
/* Some instruction starting with 0x83 other than `subl'. */
- return pc + 3;
+ return pc;
- /* `subl' with signed byte immediate (though it wouldn't make
- sense to be negative). */
- cache->locals = read_memory_integer (pc + 5, 1);
- return pc + 6;
+ /* `subl' with signed 8-bit immediate (though it wouldn't
+ make sense to be negative). */
+ cache->locals = read_memory_integer (pc + 2, 1);
+ return pc + 3;
}
else if (op == 0x81)
{
- /* Maybe it is `subl' with a 32 bit immedediate. */
- if (read_memory_unsigned_integer (pc + 4, 1) != 0xec)
+ /* Maybe it is `subl' with a 32-bit immediate. */
+ if (read_memory_unsigned_integer (pc + 1, 1) != 0xec)
/* Some instruction starting with 0x81 other than `subl'. */
- return pc + 3;
+ return pc;
- /* It is `subl' with a 32 bit immediate. */
- cache->locals = read_memory_integer (pc + 5, 4);
- return pc + 9;
+ /* It is `subl' with a 32-bit immediate. */
+ cache->locals = read_memory_integer (pc + 2, 4);
+ return pc + 6;
}
else
{
/* Some instruction other than `subl'. */
- return pc + 3;
+ return pc;
}
}
- else if (op == 0xc8) /* enter $XXX */
+ else if (op == 0xc8) /* enter */
{
cache->locals = read_memory_unsigned_integer (pc + 1, 2);
return pc + 4;
struct i386_frame_cache *cache)
{
CORE_ADDR offset = 0;
- unsigned char op;
+ gdb_byte op;
int i;
if (cache->locals > 0)
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;
once used in the System V compiler).
Local space is allocated just below the saved %ebp by either the
- 'enter' instruction, or by "subl $<size>, %esp". 'enter' has a 16
- bit unsigned argument for space to allocate, and the 'addl'
- instruction could have either a signed byte, or 32 bit immediate.
+ 'enter' instruction, or by "subl $<size>, %esp". 'enter' has a
+ 16-bit unsigned argument for space to allocate, and the 'addl'
+ instruction could have either a signed byte, or 32-bit immediate.
Next, the registers used by this function are pushed. With the
System V compiler they will always be in the order: %edi, %esi,
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);
}
static CORE_ADDR
i386_skip_prologue (CORE_ADDR start_pc)
{
- static unsigned char pic_pat[6] =
+ static gdb_byte pic_pat[6] =
{
0xe8, 0, 0, 0, 0, /* call 0x0 */
0x5b, /* popl %ebx */
};
struct i386_frame_cache cache;
CORE_ADDR pc;
- unsigned char op;
+ gdb_byte op;
int i;
cache.locals = -1;
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 */
}
}
- return i386_follow_jump (pc);
+ /* If the function starts with a branch (to startup code at the end)
+ the last instruction should bring us back to the first
+ instruction of the real code. */
+ if (i386_follow_jump (start_pc) != start_pc)
+ pc = i386_follow_jump (pc);
+
+ return pc;
}
/* This function is 64-bit safe. */
static CORE_ADDR
i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- char buf[8];
+ gdb_byte buf[8];
frame_unwind_register (next_frame, PC_REGNUM, buf);
return extract_typed_address (buf, builtin_type_void_func_ptr);
i386_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct i386_frame_cache *cache;
- char buf[4];
+ gdb_byte buf[4];
int i;
if (*this_cache)
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. */
i386_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)
+ int *realnump, gdb_byte *valuep)
{
struct i386_frame_cache *cache = i386_frame_cache (next_frame, this_cache);
if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
{
- frame_register_unwind (next_frame, I386_EAX_REGNUM,
- optimizedp, lvalp, addrp, realnump, valuep);
+ *optimizedp = 0;
+ *lvalp = lval_register;
+ *addrp = 0;
+ *realnump = I386_EAX_REGNUM;
+ if (valuep)
+ frame_unwind_register (next_frame, (*realnump), valuep);
return;
}
return;
}
- frame_register_unwind (next_frame, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ *optimizedp = 0;
+ *lvalp = lval_register;
+ *addrp = 0;
+ *realnump = regnum;
+ if (valuep)
+ frame_unwind_register (next_frame, (*realnump), valuep);
}
static const struct frame_unwind i386_frame_unwind =
struct i386_frame_cache *cache;
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR addr;
- char buf[4];
+ gdb_byte buf[4];
if (*this_cache)
return *this_cache;
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ int *realnump, gdb_byte *valuep)
{
/* Make sure we've initialized the cache. */
i386_sigtramp_frame_cache (next_frame, this_cache);
static const struct frame_unwind *
i386_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));
- /* We shouldn't even bother to try if the OSABI didn't register
- a sigcontext_addr handler. */
- if (!gdbarch_tdep (current_gdbarch)->sigcontext_addr)
+ /* We shouldn't even bother if we don't have a sigcontext_addr
+ handler. */
+ if (tdep->sigcontext_addr == NULL)
return NULL;
- find_pc_partial_function (pc, &name, NULL, NULL);
- if (PC_IN_SIGTRAMP (pc, name))
- return &i386_sigtramp_frame_unwind;
+ if (tdep->sigtramp_p != NULL)
+ {
+ if (tdep->sigtramp_p (next_frame))
+ return &i386_sigtramp_frame_unwind;
+ }
+
+ if (tdep->sigtramp_start != 0)
+ {
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+
+ gdb_assert (tdep->sigtramp_end != 0);
+ if (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end)
+ return &i386_sigtramp_frame_unwind;
+ }
return NULL;
}
static struct frame_id
i386_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- char buf[4];
+ gdb_byte buf[4];
CORE_ADDR fp;
frame_unwind_register (next_frame, I386_EBP_REGNUM, buf);
static int
i386_get_longjmp_target (CORE_ADDR *pc)
{
- char buf[8];
+ gdb_byte buf[8];
CORE_ADDR sp, jb_addr;
int jb_pc_offset = gdbarch_tdep (current_gdbarch)->jb_pc_offset;
int len = TYPE_LENGTH (builtin_type_void_func_ptr);
\f
static CORE_ADDR
-i386_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+i386_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)
{
- char buf[4];
+ gdb_byte buf[4];
int i;
/* Push arguments in reverse order. */
for (i = nargs - 1; i >= 0; i--)
{
- int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+ int len = TYPE_LENGTH (value_enclosing_type (args[i]));
/* The System V ABI says that:
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);
+ write_memory (sp, value_contents_all (args[i]), len);
}
/* Push value address. */
(i386_frame_this_id, i386_sigtramp_frame_this_id,
i386_unwind_dummy_id). It's there, since all frame unwinders for
a given target have to agree (within a certain margin) on the
- defenition of the stack address of a frame. Otherwise
+ definition of the stack address of a frame. Otherwise
frame_id_inner() won't work correctly. Since DWARF2/GCC uses the
stack address *before* the function call as a frame's CFA. On
the i386, when %ebp is used as a frame pointer, the offset
#define LOW_RETURN_REGNUM I386_EAX_REGNUM /* %eax */
#define HIGH_RETURN_REGNUM I386_EDX_REGNUM /* %edx */
-/* Extract from an array REGBUF containing the (raw) register state, a
- function return value of TYPE, and copy that, in virtual format,
- into VALBUF. */
+/* Read, for architecture GDBARCH, a function return value of TYPE
+ from REGCACHE, and copy that into VALBUF. */
static void
-i386_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, gdb_byte *valbuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int len = TYPE_LENGTH (type);
- char buf[I386_MAX_REGISTER_SIZE];
-
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && TYPE_NFIELDS (type) == 1)
- {
- i386_extract_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
- return;
- }
+ gdb_byte buf[I386_MAX_REGISTER_SIZE];
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
if (tdep->st0_regnum < 0)
{
- warning ("Cannot find floating-point return value.");
+ warning (_("Cannot find floating-point return value."));
memset (valbuf, 0, len);
return;
}
regcache_raw_read (regcache, LOW_RETURN_REGNUM, buf);
memcpy (valbuf, buf, low_size);
regcache_raw_read (regcache, HIGH_RETURN_REGNUM, buf);
- memcpy ((char *) valbuf + low_size, buf, len - low_size);
+ memcpy (valbuf + low_size, buf, len - low_size);
}
else
internal_error (__FILE__, __LINE__,
- "Cannot extract return value of %d bytes long.", len);
+ _("Cannot extract return value of %d bytes long."), len);
}
}
-/* Write into the appropriate registers a function return value stored
- in VALBUF of type TYPE, given in virtual format. */
+/* Write, for architecture GDBARCH, a function return value of TYPE
+ from VALBUF into REGCACHE. */
static void
-i386_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, const gdb_byte *valbuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int len = TYPE_LENGTH (type);
/* Define I387_ST0_REGNUM such that we use the proper definitions
for the architecture. */
#define I387_ST0_REGNUM I386_ST0_REGNUM
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && TYPE_NFIELDS (type) == 1)
- {
- i386_store_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
- return;
- }
-
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
ULONGEST fstat;
- char buf[I386_MAX_REGISTER_SIZE];
+ gdb_byte buf[I386_MAX_REGISTER_SIZE];
if (tdep->st0_regnum < 0)
{
- warning ("Cannot set floating-point return value.");
+ warning (_("Cannot set floating-point return value."));
return;
}
{
regcache_raw_write (regcache, LOW_RETURN_REGNUM, valbuf);
regcache_raw_write_part (regcache, HIGH_RETURN_REGNUM, 0,
- len - low_size, (char *) valbuf + low_size);
+ len - low_size, valbuf + low_size);
}
else
internal_error (__FILE__, __LINE__,
- "Cannot store return value of %d bytes long.", len);
+ _("Cannot store return value of %d bytes long."), len);
}
#undef I387_ST0_REGNUM
}
-
-/* Extract from REGCACHE, which contains the (raw) register state, the
- address in which a function should return its structure value, as a
- CORE_ADDR. */
-
-static CORE_ADDR
-i386_extract_struct_value_address (struct regcache *regcache)
-{
- char buf[4];
-
- regcache_cooked_read (regcache, I386_EAX_REGNUM, buf);
- return extract_unsigned_integer (buf, 4);
-}
\f
/* This is the variable that is set with "set struct-convention", and
};
static const char *struct_convention = default_struct_convention;
+/* Return non-zero if TYPE, which is assumed to be a structure,
+ a union type, or an array type, should be returned in registers
+ for architecture GDBARCH. */
+
static int
-i386_use_struct_convention (int gcc_p, struct type *type)
+i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
{
- enum struct_return struct_return;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum type_code code = TYPE_CODE (type);
+ int len = TYPE_LENGTH (type);
- if (struct_convention == default_struct_convention)
- struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
- else if (struct_convention == pcc_struct_convention)
- struct_return = pcc_struct_return;
- else
- struct_return = reg_struct_return;
+ gdb_assert (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY);
+
+ if (struct_convention == pcc_struct_convention
+ || (struct_convention == default_struct_convention
+ && tdep->struct_return == pcc_struct_return))
+ return 0;
+
+ /* Structures consisting of a single `float', `double' or 'long
+ double' member are returned in %st(0). */
+ if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+ {
+ type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return (len == 4 || len == 8 || len == 12);
+ }
+
+ return (len == 1 || len == 2 || len == 4 || len == 8);
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+ should be returned. If it is supposed to be returned in registers,
+ and READBUF is non-zero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is non-zero, write the value
+ from WRITEBUF into REGCACHE. */
+
+static enum return_value_convention
+i386_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, gdb_byte *readbuf,
+ const gdb_byte *writebuf)
+{
+ enum type_code code = TYPE_CODE (type);
+
+ if ((code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY)
+ && !i386_reg_struct_return_p (gdbarch, type))
+ {
+ /* The System V ABI says that:
+
+ "A function that returns a structure or union also sets %eax
+ to the value of the original address of the caller's area
+ before it returns. Thus when the caller receives control
+ again, the address of the returned object resides in register
+ %eax and can be used to access the object."
+
+ So the ABI guarantees that we can always find the return
+ value just after the function has returned. */
+
+ /* Note that the ABI doesn't mention functions returning arrays,
+ which is something possible in certain languages such as Ada.
+ In this case, the value is returned as if it was wrapped in
+ a record, so the convention applied to records also applies
+ to arrays. */
+
+ if (readbuf)
+ {
+ ULONGEST addr;
+
+ regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
+ read_memory (addr, readbuf, TYPE_LENGTH (type));
+ }
+
+ return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+ }
+
+ /* This special case is for structures consisting of a single
+ `float', `double' or 'long double' member. These structures are
+ returned in %st(0). For these structures, we call ourselves
+ recursively, changing TYPE into the type of the first member of
+ the structure. Since that should work for all structures that
+ have only one member, we don't bother to check the member's type
+ here. */
+ if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+ {
+ type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ return i386_return_value (gdbarch, type, regcache, readbuf, writebuf);
+ }
- return generic_use_struct_convention (struct_return == reg_struct_return,
- type);
+ if (readbuf)
+ i386_extract_return_value (gdbarch, type, regcache, readbuf);
+ if (writebuf)
+ i386_store_return_value (gdbarch, type, regcache, writebuf);
+
+ return RETURN_VALUE_REGISTER_CONVENTION;
}
\f
+/* 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;
+struct type *i386_mxcsr_type;
+
+/* Construct types for ISA-specific registers. */
+static void
+i386_init_types (void)
+{
+ struct type *type;
+
+ type = init_flags_type ("builtin_type_i386_eflags", 4);
+ append_flags_type_flag (type, 0, "CF");
+ append_flags_type_flag (type, 1, NULL);
+ append_flags_type_flag (type, 2, "PF");
+ append_flags_type_flag (type, 4, "AF");
+ append_flags_type_flag (type, 6, "ZF");
+ append_flags_type_flag (type, 7, "SF");
+ append_flags_type_flag (type, 8, "TF");
+ append_flags_type_flag (type, 9, "IF");
+ append_flags_type_flag (type, 10, "DF");
+ append_flags_type_flag (type, 11, "OF");
+ append_flags_type_flag (type, 14, "NT");
+ append_flags_type_flag (type, 16, "RF");
+ append_flags_type_flag (type, 17, "VM");
+ append_flags_type_flag (type, 18, "AC");
+ append_flags_type_flag (type, 19, "VIF");
+ append_flags_type_flag (type, 20, "VIP");
+ append_flags_type_flag (type, 21, "ID");
+ i386_eflags_type = 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];
+ };
+#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;
+
+ /* 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];
+ };
+#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;
+
+ 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;
+}
+
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. Perhaps %esi and %edi should go here, but
potentially they could be used for things other than address. */
static struct type *
i386_register_type (struct gdbarch *gdbarch, int regnum)
{
- if (regnum == I386_EIP_REGNUM
- || regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
- return lookup_pointer_type (builtin_type_void);
+ if (regnum == I386_EIP_REGNUM)
+ return builtin_type_void_func_ptr;
+
+ if (regnum == I386_EFLAGS_REGNUM)
+ return i386_eflags_type;
+
+ if (regnum == I386_EBP_REGNUM || regnum == I386_ESP_REGNUM)
+ return builtin_type_void_data_ptr;
if (i386_fp_regnum_p (regnum))
return builtin_type_i387_ext;
+ if (i386_mmx_regnum_p (gdbarch, regnum))
+ return i386_mmx_type;
+
if (i386_sse_regnum_p (gdbarch, regnum))
- return builtin_type_vec128i;
+ return i386_sse_type;
- if (i386_mmx_regnum_p (gdbarch, regnum))
- return builtin_type_vec64i;
+#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;
}
static void
i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
- int regnum, void *buf)
+ int regnum, gdb_byte *buf)
{
if (i386_mmx_regnum_p (gdbarch, regnum))
{
- char mmx_buf[MAX_REGISTER_SIZE];
+ gdb_byte mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
/* Extract (always little endian). */
static void
i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
- int regnum, const void *buf)
+ int regnum, const gdb_byte *buf)
{
if (i386_mmx_regnum_p (gdbarch, regnum))
{
- char mmx_buf[MAX_REGISTER_SIZE];
+ gdb_byte mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
/* Read ... */
static void
i386_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, void *to)
+ struct type *type, gdb_byte *to)
{
int len = TYPE_LENGTH (type);
- char *buf = to;
/* FIXME: kettenis/20030609: What should we do if REGNUM isn't
available in FRAME (i.e. if it wasn't saved)? */
return;
}
- /* Read a value spread accross multiple registers. */
+ /* Read a value spread across multiple registers. */
gdb_assert (len > 4 && len % 4 == 0);
gdb_assert (regnum != -1);
gdb_assert (register_size (current_gdbarch, regnum) == 4);
- get_frame_register (frame, regnum, buf);
+ get_frame_register (frame, regnum, to);
regnum = i386_next_regnum (regnum);
len -= 4;
- buf += 4;
+ to += 4;
}
}
static void
i386_value_to_register (struct frame_info *frame, int regnum,
- struct type *type, const void *from)
+ struct type *type, const gdb_byte *from)
{
int len = TYPE_LENGTH (type);
- const char *buf = from;
if (i386_fp_regnum_p (regnum))
{
return;
}
- /* Write a value spread accross multiple registers. */
+ /* Write a value spread across multiple registers. */
gdb_assert (len > 4 && len % 4 == 0);
gdb_assert (regnum != -1);
gdb_assert (register_size (current_gdbarch, regnum) == 4);
- put_frame_register (frame, regnum, buf);
+ put_frame_register (frame, regnum, from);
regnum = i386_next_regnum (regnum);
len -= 4;
- buf += 4;
+ from += 4;
}
}
\f
-/* Supply register REGNUM from the general-purpose register set REGSET
- to register cache REGCACHE. If REGNUM is -1, do this for all
- registers in REGSET. */
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+ in the general-purpose register set REGSET to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
void
i386_supply_gregset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
- const char *regs = gregs;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+ const gdb_byte *regs = gregs;
int i;
gdb_assert (len == tdep->sizeof_gregset);
}
}
-/* Supply register REGNUM from the floating-point register set REGSET
- to register cache REGCACHE. If REGNUM is -1, do this for all
- registers in REGSET. */
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by GREGS and LEN as described by the
+ general-purpose register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */
+
+void
+i386_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t len)
+{
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+ gdb_byte *regs = gregs;
+ int i;
+
+ gdb_assert (len == tdep->sizeof_gregset);
+
+ for (i = 0; i < tdep->gregset_num_regs; i++)
+ {
+ if ((regnum == i || regnum == -1)
+ && tdep->gregset_reg_offset[i] != -1)
+ regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
+ }
+}
+
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
+ in the floating-point register set REGSET to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
static void
i386_supply_fpregset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *fpregs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
if (len == I387_SIZEOF_FXSAVE)
{
i387_supply_fsave (regcache, regnum, fpregs);
}
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by FPREGS and LEN as described by the
+ floating-point register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */
+
+static void
+i386_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *fpregs, size_t len)
+{
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+
+ if (len == I387_SIZEOF_FXSAVE)
+ {
+ i387_collect_fxsave (regcache, regnum, fpregs);
+ return;
+ }
+
+ gdb_assert (len == tdep->sizeof_fpregset);
+ i387_collect_fsave (regcache, regnum, fpregs);
+}
+
/* Return the appropriate register set for the core section identified
by SECT_NAME and SECT_SIZE. */
if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
{
if (tdep->gregset == NULL)
- {
- tdep->gregset = XMALLOC (struct regset);
- tdep->gregset->descr = tdep;
- tdep->gregset->supply_regset = i386_supply_gregset;
- }
+ tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
+ i386_collect_gregset);
return tdep->gregset;
}
&& sect_size == I387_SIZEOF_FXSAVE))
{
if (tdep->fpregset == NULL)
- {
- tdep->fpregset = XMALLOC (struct regset);
- tdep->fpregset->descr = tdep;
- tdep->fpregset->supply_regset = i386_supply_fpregset;
- }
+ tdep->fpregset = regset_alloc (gdbarch, i386_supply_fpregset,
+ i386_collect_fpregset);
return tdep->fpregset;
}
}
\f
-/* Return non-zero if PC and NAME show that we are in a signal
- trampoline. */
+/* Return whether the frame preceding NEXT_FRAME corresponds to a
+ sigtramp routine. */
static int
-i386_pc_in_sigtramp (CORE_ADDR pc, char *name)
+i386_sigtramp_p (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
return (name && strcmp ("_sigtramp", name) == 0);
}
\f
/* System V Release 4 (SVR4). */
+/* Return whether the frame preceding NEXT_FRAME corresponds to a SVR4
+ sigtramp routine. */
+
static int
-i386_svr4_pc_in_sigtramp (CORE_ADDR pc, char *name)
+i386_svr4_sigtramp_p (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
+ char *name;
+
/* UnixWare uses _sigacthandler. The origin of the other symbols is
currently unknown. */
+ find_pc_partial_function (pc, &name, NULL, NULL);
return (name && (strcmp ("_sigreturn", name) == 0
|| strcmp ("_sigacthandler", name) == 0
|| strcmp ("sigvechandler", name) == 0));
static CORE_ADDR
i386_svr4_sigcontext_addr (struct frame_info *next_frame)
{
- char buf[4];
+ gdb_byte buf[4];
CORE_ADDR sp;
frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
}
\f
-/* DJGPP. */
-
-static int
-i386_go32_pc_in_sigtramp (CORE_ADDR pc, char *name)
-{
- /* DJGPP doesn't have any special frames for signal handlers. */
- return 0;
-}
-\f
-
/* Generic ELF. */
void
i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
- /* We typically use stabs-in-ELF with the DWARF register numbering. */
- set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+ /* We typically use stabs-in-ELF with the SVR4 register numbering. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
}
/* System V Release 4 (SVR4). */
i386_elf_init_abi (info, gdbarch);
/* System V Release 4 has shared libraries. */
- set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
- set_gdbarch_pc_in_sigtramp (gdbarch, i386_svr4_pc_in_sigtramp);
+ tdep->sigtramp_p = i386_svr4_sigtramp_p;
tdep->sigcontext_addr = i386_svr4_sigcontext_addr;
tdep->sc_pc_offset = 36 + 14 * 4;
tdep->sc_sp_offset = 36 + 17 * 4;
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- set_gdbarch_pc_in_sigtramp (gdbarch, i386_go32_pc_in_sigtramp);
+ /* DJGPP doesn't have any special frames for signal handlers. */
+ tdep->sigtramp_p = NULL;
tdep->jb_pc_offset = 36;
}
tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
/* The default settings include the FPU registers, the MMX registers
- and the SSE registers. This can be overidden for a specific ABI
+ and the SSE registers. This can be overridden for a specific ABI
by adjusting the members `st0_regnum', `mm0_regnum' and
`num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
will show up in the output of "info all-registers". Ideally we
tdep->st0_regnum = I386_ST0_REGNUM;
/* The MMX registers are implemented as pseudo-registers. Put off
- caclulating the register number for %mm0 until we know the number
+ calculating the register number for %mm0 until we know the number
of raw registers. */
tdep->mm0_regnum = 0;
tdep->struct_return = pcc_struct_return;
tdep->sigtramp_start = 0;
tdep->sigtramp_end = 0;
+ tdep->sigtramp_p = i386_sigtramp_p;
tdep->sigcontext_addr = NULL;
tdep->sc_reg_offset = NULL;
tdep->sc_pc_offset = -1;
set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
- /* Use the "default" register numbering scheme for stabs and COFF. */
- set_gdbarch_stab_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
- set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_stab_reg_to_regnum);
-
- /* Use the DWARF register numbering scheme for DWARF and DWARF 2. */
- set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_dwarf_reg_to_regnum);
+ /* NOTE: kettenis/20040418: GCC does have two possible register
+ numbering schemes on the i386: dbx and SVR4. These schemes
+ differ in how they number %ebp, %esp, %eflags, and the
+ floating-point registers, and are implemented by the arrays
+ dbx_register_map[] and svr4_dbx_register_map in
+ gcc/config/i386.c. GCC also defines a third numbering scheme in
+ gcc/config/i386.c, which it designates as the "default" register
+ map used in 64bit mode. This last register numbering scheme is
+ implemented in dbx64_register_map, and is used for AMD64; see
+ amd64-tdep.c.
+
+ Currently, each GCC i386 target always uses the same register
+ numbering scheme across all its supported debugging formats
+ i.e. SDB (COFF), stabs and DWARF 2. This is because
+ gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
+ DBX_REGISTER_NUMBER macro which is defined by each target's
+ respective config header in a manner independent of the requested
+ output debugging format.
+
+ This does not match the arrangement below, which presumes that
+ the SDB and stabs numbering schemes differ from the DWARF and
+ DWARF 2 ones. The reason for this arrangement is that it is
+ likely to get the numbering scheme for the target's
+ default/native debug format right. For targets where GCC is the
+ native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
+ targets where the native toolchain uses a different numbering
+ scheme for a particular debug format (stabs-in-ELF on Solaris)
+ the defaults below will have to be overridden, like
+ i386_elf_init_abi() does. */
+
+ /* Use the dbx register numbering scheme for stabs and COFF. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+ set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+
+ /* Use the SVR4 register numbering scheme for DWARF and DWARF 2. */
+ 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
be in use on any of the supported i386 targets. */
set_gdbarch_register_to_value (gdbarch, i386_register_to_value);
set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
- set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
- set_gdbarch_store_return_value (gdbarch, i386_store_return_value);
- set_gdbarch_extract_struct_value_address (gdbarch,
- i386_extract_struct_value_address);
- set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
+ set_gdbarch_return_value (gdbarch, i386_return_value);
set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
set_gdbarch_decr_pc_after_break (gdbarch, 1);
- set_gdbarch_function_start_offset (gdbarch, 0);
set_gdbarch_frame_args_skip (gdbarch, 8);
- set_gdbarch_pc_in_sigtramp (gdbarch, i386_pc_in_sigtramp);
/* Wire in the MMX registers. */
set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
register_gdbarch_init (bfd_arch_i386, i386_gdbarch_init);
/* Add the variable that controls the disassembly flavor. */
- {
- struct cmd_list_element *new_cmd;
-
- new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
- valid_flavors,
- &disassembly_flavor,
- "\
-Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
-and the default value is \"att\".",
- &setlist);
- add_show_from_set (new_cmd, &showlist);
- }
+ add_setshow_enum_cmd ("disassembly-flavor", no_class, valid_flavors,
+ &disassembly_flavor, _("\
+Set the disassembly flavor."), _("\
+Show the disassembly flavor."), _("\
+The valid values are \"att\" and \"intel\", and the default value is \"att\"."),
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setlist, &showlist);
/* Add the variable that controls the convention for returning
structs. */
- {
- struct cmd_list_element *new_cmd;
-
- new_cmd = add_set_enum_cmd ("struct-convention", no_class,
- valid_conventions,
- &struct_convention, "\
-Set the convention for returning small structs, valid values \
-are \"default\", \"pcc\" and \"reg\", and the default value is \"default\".",
- &setlist);
- add_show_from_set (new_cmd, &showlist);
- }
+ add_setshow_enum_cmd ("struct-convention", no_class, valid_conventions,
+ &struct_convention, _("\
+Set the convention for returning small structs."), _("\
+Show the convention for returning small structs."), _("\
+Valid values are \"default\", \"pcc\" and \"reg\", and the default value\n\
+is \"default\"."),
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setlist, &showlist);
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_coff_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETWARE,
i386_nw_init_abi);
- /* Initialize the i386 specific register groups. */
+ /* Initialize the i386-specific register groups & types. */
i386_init_reggroups ();
+ i386_init_types();
}