X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsparc-tdep.c;h=f129a55003dc86640825b901cd834df6e598ad56;hb=7c953934352840c28dcda0c8a6a18660aa1e3ab9;hp=a2af11a44b56bbe84ef4e6862a992bb982ebaff0;hpb=47ef841b87a6a90470514c1ff318289dc1fac749;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index a2af11a44b..f129a55003 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1,12 +1,13 @@ /* Target-dependent code for SPARC. - Copyright 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 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" @@ -64,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,6 +81,7 @@ struct regset; #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) @@ -151,32 +152,21 @@ sparc_is_unimp_insn (CORE_ADDR pc) /* Fetch StackGhost Per-Process XOR cookie. */ ULONGEST -sparc_fetch_wcookie (void) +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_partial (ops, TARGET_OBJECT_WCOOKIE, NULL, buf, 0, 8); + 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); -} - - -/* Return the contents if register REGNUM as an address. */ - -static CORE_ADDR -sparc_address_from_register (int regnum) -{ - ULONGEST addr; - - regcache_cooked_read_unsigned (current_regcache, regnum, &addr); - return addr; + return extract_unsigned_integer (buf, len, byte_order); } @@ -283,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]; @@ -293,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. */ @@ -301,18 +348,24 @@ 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 @@ -342,20 +395,24 @@ sparc32_pseudo_register_write (struct gdbarch *gdbarch, 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)) { 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; } @@ -368,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; @@ -404,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); } } @@ -449,7 +509,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, { 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); } @@ -491,9 +551,9 @@ sparc32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, location for inserting the breakpoint. */ static const gdb_byte * -sparc_breakpoint_from_pc (CORE_ADDR *pc, int *len) +sparc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len) { - static gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 }; + static const gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 }; *len = sizeof (break_insn); return break_insn; @@ -522,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; @@ -578,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; @@ -605,7 +817,7 @@ sparc32_skip_prologue (CORE_ADDR start_pc) return sal.end; } - start_pc = 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 @@ -640,7 +852,7 @@ sparc32_skip_prologue (CORE_ADDR 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; @@ -650,12 +862,10 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache) cache = sparc_alloc_frame_cache (); *this_cache = 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) { @@ -663,14 +873,14 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache) pointer for our calling frame. Use %sp (%o6) as this frame's base address. */ cache->base = - frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM); + 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 = - frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM); + get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); } if (cache->base & 1) @@ -679,8 +889,25 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache) 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; @@ -688,21 +915,12 @@ 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); - - 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; - } + cache->struct_return_p = sparc32_struct_return_from_sym (sym); } else { @@ -715,7 +933,7 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_cache) CORE_ADDR pc; int regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM; - pc = frame_unwind_register_unsigned (next_frame, regnum) + 8; + pc = get_frame_register_unsigned (this_frame, regnum) + 8; if (sparc_is_unimp_insn (pc)) cache->struct_return_p = 1; } @@ -724,11 +942,11 @@ sparc32_frame_cache (struct frame_info *next_frame, void **this_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) @@ -737,58 +955,41 @@ 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, gdb_byte *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 (); + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); if (wcookie != 0 && !cache->frameless_p && regnum == SPARC_I7_REGNUM) { - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (valuep) - { - CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4; - ULONGEST i7; - - /* Read the value in from memory. */ - i7 = get_frame_memory_unsigned (next_frame, addr, 4); - store_unsigned_integer (valuep, 4, i7 ^ wcookie); - } - return; + 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); } } @@ -797,53 +998,35 @@ sparc32_frame_prev_register (struct frame_info *next_frame, void **this_cache, 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); - *optimizedp = 0; - *lvalp = lval_register; - *addrp = 0; - *realnump = regnum; - if (valuep) - frame_unwind_register (next_frame, (*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; } @@ -857,19 +1040,19 @@ 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); + sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); if (sp & 1) sp += BIAS; - return frame_id_build (sp, frame_pc_unwind (next_frame)); + 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, @@ -910,8 +1093,8 @@ 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, @@ -952,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, gdb_byte *readbuf, - const gdb_byte *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); @@ -968,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 - DEPRECATED_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; + } } @@ -1007,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; @@ -1045,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) @@ -1077,87 +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 gdb_byte npc_save[4], nnpc_save[4]; - - if (insert_breakpoints_p) - { - CORE_ADDR pc, orig_npc; - - pc = sparc_address_from_register (tdep->pc_regnum); - orig_npc = npc = sparc_address_from_register (tdep->npc_regnum); - - /* 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); - - /* 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); - } - else - { - if (npc != 0) - target_remove_breakpoint (npc, npc_save); - if (nnpc != 0) - target_remove_breakpoint (nnpc, nnpc_save); - } + return 0; } -static void -sparc_write_pc (CORE_ADDR pc, ptid_t ptid) +int +sparc_software_single_step (struct frame_info *frame) { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + 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; + + CORE_ADDR pc, orig_npc; + + pc = get_frame_register_unsigned (frame, tdep->pc_regnum); + orig_npc = npc = get_frame_register_unsigned (frame, tdep->npc_regnum); - write_register_pid (tdep->pc_regnum, pc, ptid); - write_register_pid (tdep->npc_regnum, pc + 4, ptid); + /* Analyze the instruction at PC. */ + nnpc = sparc_analyze_control_transfer (frame, pc, &npc); + if (npc != 0) + insert_single_step_breakpoint (arch, aspace, npc); + + 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); + + 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) { @@ -1185,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); @@ -1234,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) @@ -1258,6 +1452,8 @@ 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; gdb_byte buf[8]; int i; @@ -1276,10 +1472,12 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum) /* Handle StackGhost. */ if (i == SPARC_I7_REGNUM) { - ULONGEST wcookie = sparc_fetch_wcookie (); - ULONGEST i7 = extract_unsigned_integer (buf + offset, 8); + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + ULONGEST i7; - store_unsigned_integer (buf + offset, 8, i7 ^ wcookie); + 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); @@ -1294,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; @@ -1310,10 +1508,12 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum) /* Handle StackGhost. */ if (i == SPARC_I7_REGNUM) { - ULONGEST wcookie = sparc_fetch_wcookie (); - ULONGEST i7 = extract_unsigned_integer (buf + offset, 4); + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + ULONGEST i7; - store_unsigned_integer (buf + offset, 4, i7 ^ wcookie); + 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); @@ -1326,6 +1526,8 @@ 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; gdb_byte buf[8]; int i; @@ -1344,10 +1546,11 @@ sparc_collect_rwindow (const struct regcache *regcache, /* Handle StackGhost. */ if (i == SPARC_I7_REGNUM) { - ULONGEST wcookie = sparc_fetch_wcookie (); - ULONGEST i7 = extract_unsigned_integer (buf + offset, 8); + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + ULONGEST i7; - store_unsigned_integer (buf, 8, i7 ^ wcookie); + 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); @@ -1361,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++) @@ -1373,10 +1576,12 @@ sparc_collect_rwindow (const struct regcache *regcache, /* Handle StackGhost. */ if (i == SPARC_I7_REGNUM) { - ULONGEST wcookie = sparc_fetch_wcookie (); - ULONGEST i7 = extract_unsigned_integer (buf + offset, 4); + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + ULONGEST i7; - store_unsigned_integer (buf + offset, 4, i7 ^ wcookie); + 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),