X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fsparc-tdep.c;h=bf711f0e6dddaac6f5f04d0cb7f522cfeebd2cbc;hb=e17a4113357102b55cfa5b80557d590a46a43300;hp=92684a325b5adf4734d9efe0cc20fb7c953738cd;hpb=9515395e66db89b143374414b98ef8c3ee233a7b;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 92684a325b..bf711f0e6d 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1,12 +1,13 @@
/* Target-dependent code for SPARC.
- Copyright 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -15,13 +16,12 @@
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. */
+ along with this program. If not, see . */
#include "defs.h"
#include "arch-utils.h"
#include "dis-asm.h"
+#include "dwarf2-frame.h"
#include "floatformat.h"
#include "frame.h"
#include "frame-base.h"
@@ -41,12 +41,13 @@
#include "sparc-tdep.h"
-/* This file implements the The SPARC 32-bit ABI as defined by the
- section "Low-Level System Information" of the SPARC Compliance
- Definition (SCD) 2.4.1, which is the 32-bit System V psABI for
- SPARC. The SCD lists changes with respect to the origional 32-bit
- psABI as defined in the "System V ABI, SPARC Processor
- Supplement".
+struct regset;
+
+/* This file implements the SPARC 32-bit ABI as defined by the section
+ "Low-Level System Information" of the SPARC Compliance Definition
+ (SCD) 2.4.1, which is the 32-bit System V psABI for SPARC. The SCD
+ lists changes with respect to the original 32-bit psABI as defined
+ in the "System V ABI, SPARC Processor Supplement".
Note that if we talk about SunOS, we mean SunOS 4.x, which was
BSD-based, which is sometimes (retroactively?) referred to as
@@ -63,7 +64,7 @@
/* The SPARC Floating-Point Quad-Precision format is similar to
big-endian IA-64 Quad-recision format. */
-#define floatformat_sparc_quad floatformat_ia64_quad_big
+#define floatformats_sparc_quad floatformats_ia64_quad
/* The stack pointer is offset from the stack frame by a BIAS of 2047
(0x7ff) for 64-bit code. BIAS is likely to be defined on SPARC
@@ -79,10 +80,13 @@
#define X_OP2(i) (((i) >> 22) & 0x7)
#define X_IMM22(i) ((i) & 0x3fffff)
#define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_RS2(i) ((i) & 0x1f)
#define X_I(i) (((i) >> 13) & 1)
/* Sign extension macros. */
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
+#define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
/* Fetch the instruction at PC. Instructions are always big-endian
even if the processor operates in little-endian mode. */
@@ -90,11 +94,13 @@
unsigned long
sparc_fetch_instruction (CORE_ADDR pc)
{
- unsigned char buf[4];
+ gdb_byte buf[4];
unsigned long insn;
int i;
- read_memory (pc, buf, sizeof (buf));
+ /* If we can't read the instruction at PC, return zero. */
+ if (target_read_memory (pc, buf, sizeof (buf)))
+ return 0;
insn = 0;
for (i = 0; i < sizeof (buf); i++)
@@ -102,15 +108,65 @@ sparc_fetch_instruction (CORE_ADDR pc)
return insn;
}
-/* Return the contents if register REGNUM as an address. */
-static CORE_ADDR
-sparc_address_from_register (int regnum)
+/* Return non-zero if the instruction corresponding to PC is an "unimp"
+ instruction. */
+
+static int
+sparc_is_unimp_insn (CORE_ADDR pc)
{
- ULONGEST addr;
+ const unsigned long insn = sparc_fetch_instruction (pc);
+
+ return ((insn & 0xc1c00000) == 0);
+}
+
+/* OpenBSD/sparc includes StackGhost, which according to the author's
+ website http://stackghost.cerias.purdue.edu "... transparently and
+ automatically protects applications' stack frames; more
+ specifically, it guards the return pointers. The protection
+ mechanisms require no application source or binary modification and
+ imposes only a negligible performance penalty."
+
+ The same website provides the following description of how
+ StackGhost works:
- regcache_cooked_read_unsigned (current_regcache, regnum, &addr);
- return addr;
+ "StackGhost interfaces with the kernel trap handler that would
+ normally write out registers to the stack and the handler that
+ would read them back in. By XORing a cookie into the
+ return-address saved in the user stack when it is actually written
+ to the stack, and then XOR it out when the return-address is pulled
+ from the stack, StackGhost can cause attacker corrupted return
+ pointers to behave in a manner the attacker cannot predict.
+ StackGhost can also use several unused bits in the return pointer
+ to detect a smashed return pointer and abort the process."
+
+ For GDB this means that whenever we're reading %i7 from a stack
+ frame's window save area, we'll have to XOR the cookie.
+
+ More information on StackGuard can be found on in:
+
+ Mike Frantzen and Mike Shuey. "StackGhost: Hardware Facilitated
+ Stack Protection." 2001. Published in USENIX Security Symposium
+ '01. */
+
+/* Fetch StackGhost Per-Process XOR cookie. */
+
+ULONGEST
+sparc_fetch_wcookie (struct gdbarch *gdbarch)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct target_ops *ops = ¤t_target;
+ gdb_byte buf[8];
+ int len;
+
+ len = target_read (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8);
+ if (len == -1)
+ return 0;
+
+ /* We should have either an 32-bit or an 64-bit cookie. */
+ gdb_assert (len == 4 || len == 8);
+
+ return extract_unsigned_integer (buf, len, byte_order);
}
@@ -122,6 +178,8 @@ sparc_address_from_register (int regnum)
static int
sparc_integral_or_pointer_p (const struct type *type)
{
+ int len = TYPE_LENGTH (type);
+
switch (TYPE_CODE (type))
{
case TYPE_CODE_INT:
@@ -129,22 +187,14 @@ sparc_integral_or_pointer_p (const struct type *type)
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
case TYPE_CODE_RANGE:
- {
- /* We have byte, half-word, word and extended-word/doubleword
- integral types. The doubleword is an extension to the
- origional 32-bit ABI by the SCD 2.4.x. */
- int len = TYPE_LENGTH (type);
- return (len == 1 || len == 2 || len == 4 || len == 8);
- }
- return 1;
+ /* We have byte, half-word, word and extended-word/doubleword
+ integral types. The doubleword is an extension to the
+ original 32-bit ABI by the SCD 2.4.x. */
+ return (len == 1 || len == 2 || len == 4 || len == 8);
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
- {
- /* Allow either 32-bit or 64-bit pointers. */
- int len = TYPE_LENGTH (type);
- return (len == 4 || len == 8);
- }
- return 1;
+ /* Allow either 32-bit or 64-bit pointers. */
+ return (len == 4 || len == 8);
default:
break;
}
@@ -223,7 +273,7 @@ static const char *sparc32_pseudo_register_names[] =
/* Return the name of register REGNUM. */
static const char *
-sparc32_register_name (int regnum)
+sparc32_register_name (struct gdbarch *gdbarch, int regnum)
{
if (regnum >= 0 && regnum < SPARC32_NUM_REGS)
return sparc32_register_names[regnum];
@@ -233,6 +283,63 @@ sparc32_register_name (int regnum)
return NULL;
}
+
+/* Construct types for ISA-specific registers. */
+
+static struct type *
+sparc_psr_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->sparc_psr_type)
+ {
+ struct type *type;
+
+ type = arch_flags_type (gdbarch, "builtin_type_sparc_psr", 4);
+ append_flags_type_flag (type, 5, "ET");
+ append_flags_type_flag (type, 6, "PS");
+ append_flags_type_flag (type, 7, "S");
+ append_flags_type_flag (type, 12, "EF");
+ append_flags_type_flag (type, 13, "EC");
+
+ tdep->sparc_psr_type = type;
+ }
+
+ return tdep->sparc_psr_type;
+}
+
+static struct type *
+sparc_fsr_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (!tdep->sparc_fsr_type)
+ {
+ struct type *type;
+
+ type = arch_flags_type (gdbarch, "builtin_type_sparc_fsr", 4);
+ append_flags_type_flag (type, 0, "NXA");
+ append_flags_type_flag (type, 1, "DZA");
+ append_flags_type_flag (type, 2, "UFA");
+ append_flags_type_flag (type, 3, "OFA");
+ append_flags_type_flag (type, 4, "NVA");
+ append_flags_type_flag (type, 5, "NXC");
+ append_flags_type_flag (type, 6, "DZC");
+ append_flags_type_flag (type, 7, "UFC");
+ append_flags_type_flag (type, 8, "OFC");
+ append_flags_type_flag (type, 9, "NVC");
+ append_flags_type_flag (type, 22, "NS");
+ append_flags_type_flag (type, 23, "NXM");
+ append_flags_type_flag (type, 24, "DZM");
+ append_flags_type_flag (type, 25, "UFM");
+ append_flags_type_flag (type, 26, "OFM");
+ append_flags_type_flag (type, 27, "NVM");
+
+ tdep->sparc_fsr_type = type;
+ }
+
+ return tdep->sparc_fsr_type;
+}
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. */
@@ -241,61 +348,71 @@ static struct type *
sparc32_register_type (struct gdbarch *gdbarch, int regnum)
{
if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
- return builtin_type_float;
+ return builtin_type (gdbarch)->builtin_float;
if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
- return builtin_type_double;
+ return builtin_type (gdbarch)->builtin_double;
if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
- return builtin_type_void_data_ptr;
+ return builtin_type (gdbarch)->builtin_data_ptr;
if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
- return builtin_type_void_func_ptr;
+ return builtin_type (gdbarch)->builtin_func_ptr;
+
+ if (regnum == SPARC32_PSR_REGNUM)
+ return sparc_psr_type (gdbarch);
+
+ if (regnum == SPARC32_FSR_REGNUM)
+ return sparc_fsr_type (gdbarch);
- return builtin_type_int32;
+ return builtin_type (gdbarch)->builtin_int32;
}
static void
sparc32_pseudo_register_read (struct gdbarch *gdbarch,
struct regcache *regcache,
- int regnum, void *buf)
+ int regnum, gdb_byte *buf)
{
gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
regcache_raw_read (regcache, regnum, buf);
- regcache_raw_read (regcache, regnum + 1, ((char *)buf) + 4);
+ regcache_raw_read (regcache, regnum + 1, buf + 4);
}
static void
sparc32_pseudo_register_write (struct gdbarch *gdbarch,
struct regcache *regcache,
- int regnum, const void *buf)
+ int regnum, const gdb_byte *buf)
{
gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
regcache_raw_write (regcache, regnum, buf);
- regcache_raw_write (regcache, regnum + 1, ((const char *)buf) + 4);
+ regcache_raw_write (regcache, regnum + 1, buf + 4);
}
static CORE_ADDR
sparc32_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
- CORE_ADDR funcaddr, int using_gcc,
+ CORE_ADDR funcaddr,
struct value **args, int nargs,
struct type *value_type,
- CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
+ CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+ struct regcache *regcache)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
*bp_addr = sp - 4;
*real_pc = funcaddr;
- if (using_struct_return (value_type, using_gcc))
+ if (using_struct_return (gdbarch, NULL, value_type))
{
- char buf[4];
+ gdb_byte buf[4];
/* This is an UNIMP instruction. */
- store_unsigned_integer (buf, 4, TYPE_LENGTH (value_type) & 0x1fff);
+ store_unsigned_integer (buf, 4, byte_order,
+ TYPE_LENGTH (value_type) & 0x1fff);
write_memory (sp - 8, buf, 4);
return sp - 8;
}
@@ -308,6 +425,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Number of words in the "parameter array". */
int num_elements = 0;
int element = 0;
@@ -315,7 +434,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
for (i = 0; i < nargs; i++)
{
- struct type *type = VALUE_TYPE (args[i]);
+ struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
if (sparc_structure_or_union_p (type)
@@ -328,7 +447,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
correct, and wasting a few bytes shouldn't be a problem. */
sp &= ~0x7;
- write_memory (sp, VALUE_CONTENTS (args[i]), len);
+ write_memory (sp, value_contents (args[i]), len);
args[i] = value_from_pointer (lookup_pointer_type (type), sp);
num_elements++;
}
@@ -344,7 +463,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
gdb_assert (sparc_integral_or_pointer_p (type));
if (len < 4)
- args[i] = value_cast (builtin_type_int32, args[i]);
+ args[i] = value_cast (builtin_type (gdbarch)->builtin_int32,
+ args[i]);
num_elements += ((len + 3) / 4);
}
}
@@ -363,8 +483,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
for (i = 0; i < nargs; i++)
{
- char *valbuf = VALUE_CONTENTS (args[i]);
- struct type *type = VALUE_TYPE (args[i]);
+ const bfd_byte *valbuf = value_contents (args[i]);
+ struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
gdb_assert (len == 4 || len == 8);
@@ -387,9 +507,9 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
if (struct_return)
{
- char buf[4];
+ gdb_byte buf[4];
- store_unsigned_integer (buf, 4, struct_addr);
+ store_unsigned_integer (buf, 4, byte_order, struct_addr);
write_memory (sp, buf, 4);
}
@@ -397,7 +517,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
}
static CORE_ADDR
-sparc32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+sparc32_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)
@@ -430,10 +550,10 @@ sparc32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
*LEN and optionally adjust *PC to point to the correct memory
location for inserting the breakpoint. */
-static const unsigned char *
-sparc_breakpoint_from_pc (CORE_ADDR *pc, int *len)
+static const gdb_byte *
+sparc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
{
- static unsigned char break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
+ static const gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
*len = sizeof (break_insn);
return break_insn;
@@ -462,15 +582,167 @@ sparc_alloc_frame_cache (void)
return cache;
}
+/* GCC generates several well-known sequences of instructions at the begining
+ of each function prologue when compiling with -fstack-check. If one of
+ such sequences starts at START_PC, then return the address of the
+ instruction immediately past this sequence. Otherwise, return START_PC. */
+
+static CORE_ADDR
+sparc_skip_stack_check (const CORE_ADDR start_pc)
+{
+ CORE_ADDR pc = start_pc;
+ unsigned long insn;
+ int offset_stack_checking_sequence = 0;
+
+ /* With GCC, all stack checking sequences begin with the same two
+ instructions. */
+
+ /* sethi ,%g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 1))
+ return start_pc;
+
+ /* sub %sp, %g1, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 1 && X_RS1 (insn) == 14 && X_RS2 (insn) == 1))
+ return start_pc;
+
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+
+ /* First possible sequence:
+ [first two instructions above]
+ clr [%g1 - some immediate] */
+
+ /* clr [%g1 - some immediate] */
+ if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+ {
+ /* Valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* Second possible sequence: A small number of probes.
+ [first two instructions above]
+ clr [%g1]
+ add %g1, -, %g1
+ clr [%g1]
+ [repeat the two instructions above any (small) number of times]
+ clr [%g1 - some immediate] */
+
+ /* clr [%g1] */
+ else if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0)
+ {
+ while (1)
+ {
+ /* add %g1, -, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ break;
+
+ /* clr [%g1] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+ return start_pc;
+ }
+
+ /* clr [%g1 - some immediate] */
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0))
+ return start_pc;
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* Third sequence: A probing loop.
+ [first two instructions above]
+ sethi , %g4
+ sub %g1, %g4, %g4
+ cmp %g1, %g4
+ be
+ add %g1, -, %g1
+ ba
+ clr [%g1]
+ clr [%g4 - some immediate] */
+
+ /* sethi , %g4 */
+ else if (X_OP (insn) == 0 && X_OP2 (insn) == 0x4 && X_RD (insn) == 4)
+ {
+ /* sub %g1, %g4, %g4 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 4 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
+
+ /* cmp %g1, %g4 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x14 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
+
+ /* be */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_COND (insn) == 0x1))
+ return start_pc;
+
+ /* add %g1, -, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ return start_pc;
+
+ /* ba */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 0 && X_COND (insn) == 0x8))
+ return start_pc;
+
+ /* clr [%g1] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+ return start_pc;
+
+ /* clr [%g4 - some immediate] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
+ && X_RS1 (insn) == 4 && X_RD (insn) == 0))
+ return start_pc;
+
+ /* We found a valid stack-check sequence, return the new PC. */
+ return pc;
+ }
+
+ /* No stack check code in our prologue, return the start_pc. */
+ return start_pc;
+}
+
CORE_ADDR
-sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
- struct sparc_frame_cache *cache)
+sparc_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
+ CORE_ADDR current_pc, struct sparc_frame_cache *cache)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
unsigned long insn;
int offset = 0;
int dest = -1;
+ pc = sparc_skip_stack_check (pc);
+
if (current_pc <= pc)
return current_pc;
@@ -518,17 +790,17 @@ sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
}
static CORE_ADDR
-sparc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+sparc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- return frame_unwind_register_unsigned (next_frame, tdep->pc_regnum);
+ return frame_unwind_register_unsigned (this_frame, tdep->pc_regnum);
}
/* Return PC of first real instruction of the function starting at
START_PC. */
static CORE_ADDR
-sparc32_skip_prologue (CORE_ADDR start_pc)
+sparc32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
struct symtab_and_line sal;
CORE_ADDR func_start, func_end;
@@ -545,13 +817,42 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
return sal.end;
}
- return sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+ start_pc = sparc_analyze_prologue (gdbarch, start_pc, 0xffffffffUL, &cache);
+
+ /* The psABI says that "Although the first 6 words of arguments
+ reside in registers, the standard stack frame reserves space for
+ them.". It also suggests that a function may use that space to
+ "write incoming arguments 0 to 5" into that space, and that's
+ indeed what GCC seems to be doing. In that case GCC will
+ generate debug information that points to the stack slots instead
+ of the registers, so we should consider the instructions that
+ write out these incoming arguments onto the stack. Of course we
+ only need to do this if we have a stack frame. */
+
+ while (!cache.frameless_p)
+ {
+ unsigned long insn = sparc_fetch_instruction (start_pc);
+
+ /* Recognize instructions that store incoming arguments in
+ %i0...%i5 into the corresponding stack slot. */
+ if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04 && X_I (insn)
+ && (X_RD (insn) >= 24 && X_RD (insn) <= 29) && X_RS1 (insn) == 30
+ && X_SIMM13 (insn) == 68 + (X_RD (insn) - 24) * 4)
+ {
+ start_pc += 4;
+ continue;
+ }
+
+ break;
+ }
+
+ return start_pc;
}
/* Normal frames. */
struct sparc_frame_cache *
-sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
+sparc_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct sparc_frame_cache *cache;
@@ -561,34 +862,52 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
cache = sparc_alloc_frame_cache ();
*this_cache = cache;
- /* In priciple, for normal frames, %fp (%i6) holds the frame
- pointer, which holds the base address for the current stack
- frame. */
-
- cache->base = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
- if (cache->base == 0)
- return cache;
-
- cache->pc = frame_func_unwind (next_frame);
+ cache->pc = get_frame_func (this_frame);
if (cache->pc != 0)
- {
- CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame);
- sparc_analyze_prologue (cache->pc, addr_in_block, cache);
- }
+ sparc_analyze_prologue (get_frame_arch (this_frame), cache->pc,
+ get_frame_pc (this_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. */
- cache->base = frame_unwind_register_unsigned (next_frame,
- SPARC_SP_REGNUM);
+ /* This function is frameless, so %fp (%i6) holds the frame
+ pointer for our calling frame. Use %sp (%o6) as this frame's
+ base address. */
+ cache->base =
+ get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
+ }
+ else
+ {
+ /* For normal frames, %fp (%i6) holds the frame pointer, the
+ base address for the current stack frame. */
+ cache->base =
+ get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
}
+ if (cache->base & 1)
+ cache->base += BIAS;
+
return cache;
}
+static int
+sparc32_struct_return_from_sym (struct symbol *sym)
+{
+ struct type *type = check_typedef (SYMBOL_TYPE (sym));
+ enum type_code code = TYPE_CODE (type);
+
+ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+ {
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (sparc_structure_or_union_p (type)
+ || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
+ return 1;
+ }
+
+ return 0;
+}
+
struct sparc_frame_cache *
-sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
+sparc32_frame_cache (struct frame_info *this_frame, void **this_cache)
{
struct sparc_frame_cache *cache;
struct symbol *sym;
@@ -596,32 +915,38 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache)
if (*this_cache)
return *this_cache;
- cache = sparc_frame_cache (next_frame, this_cache);
+ cache = sparc_frame_cache (this_frame, this_cache);
sym = find_pc_function (cache->pc);
if (sym)
{
- struct type *type = check_typedef (SYMBOL_TYPE (sym));
- enum type_code code = TYPE_CODE (type);
+ cache->struct_return_p = sparc32_struct_return_from_sym (sym);
+ }
+ else
+ {
+ /* There is no debugging information for this function to
+ help us determine whether this function returns a struct
+ or not. So we rely on another heuristic which is to check
+ the instruction at the return address and see if this is
+ an "unimp" instruction. If it is, then it is a struct-return
+ function. */
+ CORE_ADDR pc;
+ int regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM;
- if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
- {
- type = check_typedef (TYPE_TARGET_TYPE (type));
- if (sparc_structure_or_union_p (type)
- || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
- cache->struct_return_p = 1;
- }
+ pc = get_frame_register_unsigned (this_frame, regnum) + 8;
+ if (sparc_is_unimp_insn (pc))
+ cache->struct_return_p = 1;
}
return cache;
}
static void
-sparc32_frame_this_id (struct frame_info *next_frame, void **this_cache,
+sparc32_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
{
struct sparc_frame_cache *cache =
- sparc32_frame_cache (next_frame, this_cache);
+ sparc32_frame_cache (this_frame, this_cache);
/* This marks the outermost frame. */
if (cache->base == 0)
@@ -630,86 +955,78 @@ sparc32_frame_this_id (struct frame_info *next_frame, void **this_cache,
(*this_id) = frame_id_build (cache->base, cache->pc);
}
-static void
-sparc32_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)
+static struct value *
+sparc32_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache, int regnum)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct sparc_frame_cache *cache =
- sparc32_frame_cache (next_frame, this_cache);
+ sparc32_frame_cache (this_frame, this_cache);
if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
{
- *optimizedp = 0;
- *lvalp = not_lval;
- *addrp = 0;
- *realnump = -1;
- if (valuep)
- {
- CORE_ADDR pc = (regnum == SPARC32_NPC_REGNUM) ? 4 : 0;
+ CORE_ADDR pc = (regnum == SPARC32_NPC_REGNUM) ? 4 : 0;
- /* If this functions has a Structure, Union or
- Quad-Precision return value, we have to skip the UNIMP
- instruction that encodes the size of the structure. */
- if (cache->struct_return_p)
- pc += 4;
+ /* If this functions has a Structure, Union or Quad-Precision
+ return value, we have to skip the UNIMP instruction that encodes
+ the size of the structure. */
+ if (cache->struct_return_p)
+ pc += 4;
- regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM;
- pc += frame_unwind_register_unsigned (next_frame, regnum) + 8;
- store_unsigned_integer (valuep, 4, pc);
- }
- return;
+ regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM;
+ pc += get_frame_register_unsigned (this_frame, regnum) + 8;
+ return frame_unwind_got_constant (this_frame, regnum, pc);
}
+ /* Handle StackGhost. */
+ {
+ ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+
+ if (wcookie != 0 && !cache->frameless_p && regnum == SPARC_I7_REGNUM)
+ {
+ CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
+ ULONGEST i7;
+
+ /* Read the value in from memory. */
+ i7 = get_frame_memory_unsigned (this_frame, addr, 4);
+ return frame_unwind_got_constant (this_frame, regnum, i7 ^ wcookie);
+ }
+ }
+
/* The previous frame's `local' and `in' registers have been saved
in the register save area. */
if (!cache->frameless_p
&& regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM)
{
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
- *realnump = -1;
- if (valuep)
- {
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
- /* Read the value in from memory. */
- read_memory (*addrp, valuep, register_size (gdbarch, regnum));
- }
- return;
+ return frame_unwind_got_memory (this_frame, regnum, addr);
}
- /* The previous frame's `out' registers are accessable as the
+ /* The previous frame's `out' registers are accessible as the
current frame's `in' registers. */
if (!cache->frameless_p
&& regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
- frame_register_unwind (next_frame, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ return frame_unwind_got_register (this_frame, regnum, regnum);
}
static const struct frame_unwind sparc32_frame_unwind =
{
NORMAL_FRAME,
sparc32_frame_this_id,
- sparc32_frame_prev_register
+ sparc32_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-
-static const struct frame_unwind *
-sparc32_frame_sniffer (struct frame_info *next_frame)
-{
- return &sparc32_frame_unwind;
-}
static CORE_ADDR
-sparc32_frame_base_address (struct frame_info *next_frame, void **this_cache)
+sparc32_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
struct sparc_frame_cache *cache =
- sparc32_frame_cache (next_frame, this_cache);
+ sparc32_frame_cache (this_frame, this_cache);
return cache->base;
}
@@ -723,24 +1040,26 @@ static const struct frame_base sparc32_frame_base =
};
static struct frame_id
-sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+sparc_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
CORE_ADDR sp;
- sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
- return frame_id_build (sp, frame_pc_unwind (next_frame));
+ sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
+ if (sp & 1)
+ sp += BIAS;
+ return frame_id_build (sp, get_frame_pc (this_frame));
}
-/* Extract from an array REGBUF containing the (raw) register state, a
- function return value of TYPE, and copy that into VALBUF. */
+/* Extract a function return value of TYPE from REGCACHE, and copy
+ that into VALBUF. */
static void
sparc32_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+ gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
- char buf[8];
+ gdb_byte buf[8];
gdb_assert (!sparc_structure_or_union_p (type));
gdb_assert (!(sparc_floating_p (type) && len == 16));
@@ -774,15 +1093,15 @@ sparc32_extract_return_value (struct type *type, struct regcache *regcache,
}
}
-/* Write into the appropriate registers a function return value stored
- in VALBUF of type TYPE. */
+/* Store the function return value of type TYPE from VALBUF into
+ REGCACHE. */
static void
sparc32_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+ const gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
- char buf[8];
+ gdb_byte buf[8];
gdb_assert (!sparc_structure_or_union_p (type));
gdb_assert (!(sparc_floating_p (type) && len == 16));
@@ -816,13 +1135,34 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache,
}
static enum return_value_convention
-sparc32_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, void *readbuf,
- const void *writebuf)
+sparc32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+ /* The psABI says that "...every stack frame reserves the word at
+ %fp+64. If a function returns a structure, union, or
+ quad-precision value, this word should hold the address of the
+ object into which the return value should be copied." This
+ guarantees that we can always find the return value, not just
+ before the function returns. */
+
if (sparc_structure_or_union_p (type)
|| (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
- return RETURN_VALUE_STRUCT_CONVENTION;
+ {
+ if (readbuf)
+ {
+ ULONGEST sp;
+ CORE_ADDR addr;
+
+ regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+ addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
+ read_memory (addr, readbuf, TYPE_LENGTH (type));
+ }
+
+ return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
+ }
if (readbuf)
sparc32_extract_return_value (type, regcache, readbuf);
@@ -832,24 +1172,53 @@ sparc32_return_value (struct gdbarch *gdbarch, struct type *type,
return RETURN_VALUE_REGISTER_CONVENTION;
}
-/* 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 int
+sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
+{
+ return (sparc_structure_or_union_p (type)
+ || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16));
+}
-static CORE_ADDR
-sparc_extract_struct_value_address (struct regcache *regcache)
+static int
+sparc32_dwarf2_struct_return_p (struct frame_info *this_frame)
{
- ULONGEST sp;
+ CORE_ADDR pc = get_frame_address_in_block (this_frame);
+ struct symbol *sym = find_pc_function (pc);
- regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
- return read_memory_unsigned_integer (sp + 64, 4);
+ if (sym)
+ return sparc32_struct_return_from_sym (sym);
+ return 0;
}
-static int
-sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
+static void
+sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
{
- return (sparc_structure_or_union_p (type)
- || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16));
+ int off;
+
+ switch (regnum)
+ {
+ case SPARC_G0_REGNUM:
+ /* Since %g0 is always zero, there is no point in saving it, and
+ people will be inclined omit it from the CFI. Make sure we
+ don't warn about that. */
+ reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+ break;
+ case SPARC_SP_REGNUM:
+ reg->how = DWARF2_FRAME_REG_CFA;
+ break;
+ case SPARC32_PC_REGNUM:
+ case SPARC32_NPC_REGNUM:
+ reg->how = DWARF2_FRAME_REG_RA_OFFSET;
+ off = 8;
+ if (sparc32_dwarf2_struct_return_p (this_frame))
+ off += 4;
+ if (regnum == SPARC32_NPC_REGNUM)
+ off += 4;
+ reg->loc.offset = off;
+ break;
+ }
}
@@ -858,7 +1227,8 @@ sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
software single-step mechanism. */
static CORE_ADDR
-sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
+sparc_analyze_control_transfer (struct frame_info *frame,
+ CORE_ADDR pc, CORE_ADDR *npc)
{
unsigned long insn = sparc_fetch_instruction (pc);
int conditional_p = X_COND (insn) & 0x7;
@@ -896,11 +1266,14 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
branch_p = 1;
offset = 4 * X_DISP19 (insn);
}
+ else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
+ {
+ /* Trap instruction (TRAP). */
+ return gdbarch_tdep (get_frame_arch (frame))->step_trap (frame, insn);
+ }
/* FIXME: Handle DONE and RETRY instructions. */
- /* FIXME: Handle the Trap instruction. */
-
if (branch_p)
{
if (conditional_p)
@@ -928,79 +1301,67 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
return 0;
}
-void
-sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+static CORE_ADDR
+sparc_step_trap (struct frame_info *frame, unsigned long insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- static CORE_ADDR npc, nnpc;
- static char npc_save[4], nnpc_save[4];
+ return 0;
+}
- if (insert_breakpoints_p)
- {
- CORE_ADDR pc;
+int
+sparc_software_single_step (struct frame_info *frame)
+{
+ struct gdbarch *arch = get_frame_arch (frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ CORE_ADDR npc, nnpc;
- pc = sparc_address_from_register (tdep->pc_regnum);
- npc = sparc_address_from_register (tdep->npc_regnum);
+ CORE_ADDR pc, orig_npc;
- /* Analyze the instruction at PC. */
- nnpc = sparc_analyze_control_transfer (pc, &npc);
- if (npc != 0)
- target_insert_breakpoint (npc, npc_save);
- if (nnpc != 0)
- target_insert_breakpoint (nnpc, nnpc_save);
+ pc = get_frame_register_unsigned (frame, tdep->pc_regnum);
+ orig_npc = npc = get_frame_register_unsigned (frame, tdep->npc_regnum);
- /* Assert that we have set at least one breakpoint, and that
- they're not set at the same spot. */
- gdb_assert (npc != 0 || nnpc != 0);
- gdb_assert (nnpc != npc);
- }
- else
- {
- if (npc != 0)
- target_remove_breakpoint (npc, npc_save);
- if (nnpc != 0)
- target_remove_breakpoint (nnpc, nnpc_save);
- }
+ /* Analyze the instruction at PC. */
+ nnpc = sparc_analyze_control_transfer (frame, pc, &npc);
+ if (npc != 0)
+ insert_single_step_breakpoint (arch, npc);
+
+ if (nnpc != 0)
+ insert_single_step_breakpoint (arch, nnpc);
+
+ /* Assert that we have set at least one breakpoint, and that
+ they're not set at the same spot - unless we're going
+ from here straight to NULL, i.e. a call or jump to 0. */
+ gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
+ gdb_assert (nnpc != npc || orig_npc == 0);
+
+ return 1;
}
static void
-sparc_write_pc (CORE_ADDR pc, ptid_t ptid)
+sparc_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
- write_register_pid (tdep->pc_regnum, pc, ptid);
- write_register_pid (tdep->npc_regnum, pc + 4, ptid);
+ regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+ regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
}
-/* Unglobalize NAME. */
-char *
-sparc_stabs_unglobalize_name (char *name)
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
+
+static const struct regset *
+sparc_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name, size_t sect_size)
{
- /* The Sun compilers (Sun ONE Studio, Forte Developer, Sun WorkShop,
- SunPRO) convert file static variables into global values, a
- process known as globalization. In order to do this, the
- compiler will create a unique prefix and prepend it to each file
- static variable. For static variables within a function, this
- globalization prefix is followed by the function name (nested
- static variables within a function are supposed to generate a
- warning message, and are left alone). The procedure is
- documented in the Stabs Interface Manual, which is distrubuted
- with the compilers, although version 4.0 of the manual seems to
- be incorrect in some places, at least for SPARC. The
- globalization prefix is encoded into an N_OPT stab, with the form
- "G=". The globalization prefix always seems to start
- with a dollar sign '$'; a dot '.' is used as a seperator. So we
- simply strip everything up until the last dot. */
-
- if (name[0] == '$')
- {
- char *p = strrchr (name, '.');
- if (p)
- return p + 1;
- }
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
+ return tdep->gregset;
+
+ if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
+ return tdep->fpregset;
- return name;
+ return NULL;
}
@@ -1021,10 +1382,15 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->pc_regnum = SPARC32_PC_REGNUM;
tdep->npc_regnum = SPARC32_NPC_REGNUM;
+ tdep->gregset = NULL;
+ tdep->sizeof_gregset = 0;
+ tdep->fpregset = NULL;
+ tdep->sizeof_fpregset = 0;
tdep->plt_entry_size = 0;
+ tdep->step_trap = sparc_step_trap;
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad);
+ set_gdbarch_long_double_format (gdbarch, floatformats_sparc_quad);
set_gdbarch_num_regs (gdbarch, SPARC32_NUM_REGS);
set_gdbarch_register_name (gdbarch, sparc32_register_name);
@@ -1053,8 +1419,6 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_breakpoint_from_pc (gdbarch, sparc_breakpoint_from_pc);
- set_gdbarch_decr_pc_after_break (gdbarch, 0);
- set_gdbarch_function_start_offset (gdbarch, 0);
set_gdbarch_frame_args_skip (gdbarch, 8);
@@ -1063,16 +1427,26 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
set_gdbarch_write_pc (gdbarch, sparc_write_pc);
- set_gdbarch_unwind_dummy_id (gdbarch, sparc_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, sparc_dummy_id);
set_gdbarch_unwind_pc (gdbarch, sparc_unwind_pc);
frame_base_set_default (gdbarch, &sparc32_frame_base);
+ /* Hook in the DWARF CFI frame unwinder. */
+ dwarf2_frame_set_init_reg (gdbarch, sparc32_dwarf2_frame_init_reg);
+ /* FIXME: kettenis/20050423: Don't enable the unwinder until the
+ StackGhost issues have been resolved. */
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
- frame_unwind_append_sniffer (gdbarch, sparc32_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &sparc32_frame_unwind);
+
+ /* If we have register sets, enable the generic core file support. */
+ if (tdep->gregset)
+ set_gdbarch_regset_from_core_section (gdbarch,
+ sparc_regset_from_core_section);
return gdbarch;
}
@@ -1082,8 +1456,10 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
void
sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int offset = 0;
- char buf[8];
+ gdb_byte buf[8];
int i;
if (sp & 1)
@@ -1096,6 +1472,18 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
if (regnum == i || regnum == -1)
{
target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
+
+ /* Handle StackGhost. */
+ if (i == SPARC_I7_REGNUM)
+ {
+ ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+ ULONGEST i7;
+
+ i7 = extract_unsigned_integer (buf + offset, 8, byte_order);
+ store_unsigned_integer (buf + offset, 8, byte_order,
+ i7 ^ wcookie);
+ }
+
regcache_raw_supply (regcache, i, buf);
}
}
@@ -1108,7 +1496,7 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
/* Clear out the top half of the temporary buffer, and put the
register value in the bottom half if we're in 64-bit mode. */
- if (gdbarch_ptr_bit (current_gdbarch) == 64)
+ if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
{
memset (buf, 0, 4);
offset = 4;
@@ -1120,6 +1508,18 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
{
target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 4),
buf + offset, 4);
+
+ /* Handle StackGhost. */
+ if (i == SPARC_I7_REGNUM)
+ {
+ ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+ ULONGEST i7;
+
+ i7 = extract_unsigned_integer (buf + offset, 4, byte_order);
+ store_unsigned_integer (buf + offset, 4, byte_order,
+ i7 ^ wcookie);
+ }
+
regcache_raw_supply (regcache, i, buf);
}
}
@@ -1130,8 +1530,10 @@ void
sparc_collect_rwindow (const struct regcache *regcache,
CORE_ADDR sp, int regnum)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int offset = 0;
- char buf[8];
+ gdb_byte buf[8];
int i;
if (sp & 1)
@@ -1144,6 +1546,17 @@ sparc_collect_rwindow (const struct regcache *regcache,
if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
{
regcache_raw_collect (regcache, i, buf);
+
+ /* Handle StackGhost. */
+ if (i == SPARC_I7_REGNUM)
+ {
+ ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+ ULONGEST i7;
+
+ i7 = extract_unsigned_integer (buf + offset, 8, byte_order);
+ store_unsigned_integer (buf, 8, byte_order, i7 ^ wcookie);
+ }
+
target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
}
}
@@ -1155,7 +1568,7 @@ sparc_collect_rwindow (const struct regcache *regcache,
sp &= 0xffffffffUL;
/* Only use the bottom half if we're in 64-bit mode. */
- if (gdbarch_ptr_bit (current_gdbarch) == 64)
+ if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
offset = 4;
for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
@@ -1163,6 +1576,18 @@ sparc_collect_rwindow (const struct regcache *regcache,
if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
{
regcache_raw_collect (regcache, i, buf);
+
+ /* Handle StackGhost. */
+ if (i == SPARC_I7_REGNUM)
+ {
+ ULONGEST wcookie = sparc_fetch_wcookie (gdbarch);
+ ULONGEST i7;
+
+ i7 = extract_unsigned_integer (buf + offset, 4, byte_order);
+ store_unsigned_integer (buf + offset, 4, byte_order,
+ i7 ^ wcookie);
+ }
+
target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 4),
buf + offset, 4);
}
@@ -1177,7 +1602,7 @@ sparc32_supply_gregset (const struct sparc_gregset *gregset,
struct regcache *regcache,
int regnum, const void *gregs)
{
- const char *regs = gregs;
+ const gdb_byte *regs = gregs;
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
@@ -1241,7 +1666,7 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
const struct regcache *regcache,
int regnum, void *gregs)
{
- char *regs = gregs;
+ gdb_byte *regs = gregs;
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
@@ -1295,7 +1720,7 @@ void
sparc32_supply_fpregset (struct regcache *regcache,
int regnum, const void *fpregs)
{
- const char *regs = fpregs;
+ const gdb_byte *regs = fpregs;
int i;
for (i = 0; i < 32; i++)
@@ -1312,7 +1737,7 @@ void
sparc32_collect_fpregset (const struct regcache *regcache,
int regnum, void *fpregs)
{
- char *regs = fpregs;
+ gdb_byte *regs = fpregs;
int i;
for (i = 0; i < 32; i++)