X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsparc-tdep.c;h=1ec7d515b47522a8e5ddda7342c14cc180b6a86a;hb=d9b76ff95d9cc3471b46fdae062c5a1d302f5ee7;hp=ed4888044f78a06132922467d8d82e6120f2acdd;hpb=c558d81a8728761eea59e8c9549dfd3eb8933406;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index ed4888044f..1ec7d515b4 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" @@ -43,12 +43,11 @@ struct regset; -/* 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". +/* 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 @@ -65,7 +64,7 @@ struct regset; /* 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 @@ -81,10 +80,13 @@ struct regset; #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. */ @@ -92,7 +94,7 @@ struct regset; unsigned long sparc_fetch_instruction (CORE_ADDR pc) { - unsigned char buf[4]; + gdb_byte buf[4]; unsigned long insn; int i; @@ -106,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) +{ + 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: + + "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) { - ULONGEST addr; + 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; - regcache_cooked_read_unsigned (current_regcache, regnum, &addr); - return addr; + /* 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); } @@ -126,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: @@ -133,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; } @@ -227,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]; @@ -237,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. */ @@ -245,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); - return builtin_type_int32; + if (regnum == SPARC32_FSR_REGNUM) + return sparc_fsr_type (gdbarch); + + 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; } @@ -312,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; @@ -319,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) @@ -332,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++; } @@ -348,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); } } @@ -367,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); @@ -391,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); } @@ -401,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) @@ -434,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; @@ -466,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; @@ -522,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; @@ -549,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; @@ -565,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; @@ -600,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) @@ -634,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; } @@ -727,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)); @@ -778,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)); @@ -820,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); @@ -836,37 +1172,53 @@ sparc32_return_value (struct gdbarch *gdbarch, struct type *type, return RETURN_VALUE_REGISTER_CONVENTION; } -#if 0 -/* NOTE: cagney/2004-01-17: For the moment disable this method. The - architecture and CORE-gdb will need new code (and a replacement for - EXTRACT_STRUCT_VALUE_ADDRESS) before this can be made to work - robustly. Here is a possible function signature: */ -/* NOTE: cagney/2004-01-17: So far only the 32-bit SPARC ABI has been - identifed as having a way to robustly recover the address of a - struct-convention return-value (after the function has returned). - For all other ABIs so far examined, the calling convention makes no - guarenteed that the register containing the return-value will be - preserved and hence that the return-value's address can be - recovered. */ -/* 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 -sparc32_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; } -#endif -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; + } } @@ -875,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; @@ -913,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) @@ -945,86 +1301,56 @@ 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); + struct address_space *aspace = get_frame_address_space (frame); + 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, aspace, npc); -static void -sparc_write_pc (CORE_ADDR pc, ptid_t ptid) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + if (nnpc != 0) + insert_single_step_breakpoint (arch, aspace, 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); - write_register_pid (tdep->pc_regnum, pc, ptid); - write_register_pid (tdep->npc_regnum, pc + 4, ptid); + return 1; } - -/* Unglobalize NAME. */ -char * -sparc_stabs_unglobalize_name (char *name) +static void +sparc_write_pc (struct regcache *regcache, CORE_ADDR pc) { - /* 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 (get_regcache_arch (regcache)); - return name; + regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc); + regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4); } /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ -const struct regset * +static const struct regset * sparc_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size) { @@ -1052,19 +1378,15 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return arches->gdbarch; /* Allocate space for the new architecture. */ - tdep = XMALLOC (struct gdbarch_tdep); + tdep = XZALLOC (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); 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); @@ -1101,16 +1423,21 @@ 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) @@ -1125,8 +1452,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) @@ -1139,6 +1468,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); } } @@ -1151,7 +1492,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; @@ -1163,6 +1504,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); } } @@ -1173,8 +1526,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) @@ -1187,6 +1542,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); } } @@ -1198,7 +1564,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++) @@ -1206,6 +1572,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); } @@ -1220,7 +1598,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) @@ -1284,7 +1662,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) @@ -1338,7 +1716,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++) @@ -1355,7 +1733,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++)