1/* Target-dependent code for Solaris SPARC. 2 3 Copyright 2003 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "defs.h" 23#include "frame.h" 24#include "frame-unwind.h" 25#include "gdbcore.h" 26#include "symtab.h" 27#include "objfiles.h" 28#include "osabi.h" 29#include "regcache.h" 30#include "target.h" 31#include "trad-frame.h" 32 33#include "gdb_assert.h" 34#include "gdb_string.h" 35 36#include "sparc-tdep.h" 37 38/* From <sys/regset.h>. */ 39const struct sparc_gregset sparc32_sol2_gregset = 40{ 41 32 * 4, /* %psr */ 42 33 * 4, /* %pc */ 43 34 * 4, /* %npc */ 44 35 * 4, /* %y */ 45 36 * 4, /* %wim */ 46 37 * 4, /* %tbr */ 47 1 * 4, /* %g1 */ 48 16 * 4, /* %l0 */ 49}; 50 51 52/* The Solaris signal trampolines reside in libc. For normal signals, 53 the function `sigacthandler' is used. This signal trampoline will 54 call the signal handler using the System V calling convention, 55 where the third argument is a pointer to an instance of 56 `ucontext_t', which has a member `uc_mcontext' that contains the 57 saved registers. Incidentally, the kernel passes the `ucontext_t' 58 pointer as the third argument of the signal trampoline too, and 59 `sigacthandler' simply passes it on. However, if you link your 60 program with "-L/usr/ucblib -R/usr/ucblib -lucb", the function 61 `ucbsigvechandler' will be used, which invokes the using the BSD 62 convention, where the third argument is a pointer to an instance of 63 `struct sigcontext'. It is the `ucbsigvechandler' function that 64 converts the `ucontext_t' to a `sigcontext', and back. Unless the 65 signal handler modifies the `struct sigcontext' we can safely 66 ignore this. */ 67 68int 69sparc_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name) 70{ 71 return (name && (strcmp (name, "sigacthandler") == 0 72 || strcmp (name, "ucbsigvechandler") == 0)); 73} 74 75static struct sparc_frame_cache * 76sparc32_sol2_sigtramp_frame_cache (struct frame_info *next_frame, 77 void **this_cache) 78{ 79 struct sparc_frame_cache *cache; 80 CORE_ADDR mcontext_addr, addr; 81 int regnum; 82 83 if (*this_cache) 84 return *this_cache; 85 86 cache = sparc_frame_cache (next_frame, this_cache); 87 gdb_assert (cache == *this_cache); 88 89 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); 90 91 /* The third argument is a pointer to an instance of `ucontext_t', 92 which has a member `uc_mcontext' that contains the saved 93 registers. */ 94 regnum = (cache->frameless_p ? SPARC_O2_REGNUM : SPARC_I2_REGNUM); 95 mcontext_addr = frame_unwind_register_unsigned (next_frame, regnum) + 40; 96 97 cache->saved_regs[SPARC32_PSR_REGNUM].addr = mcontext_addr + 0 * 4; 98 cache->saved_regs[SPARC32_PC_REGNUM].addr = mcontext_addr + 1 * 4; 99 cache->saved_regs[SPARC32_NPC_REGNUM].addr = mcontext_addr + 2 * 4; 100 cache->saved_regs[SPARC32_Y_REGNUM].addr = mcontext_addr + 3 * 4; 101 102 /* Since %g0 is always zero, keep the identity encoding. */ 103 for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 4 * 4; 104 regnum <= SPARC_O7_REGNUM; regnum++, addr += 4) 105 cache->saved_regs[regnum].addr = addr; 106 107 if (get_frame_memory_unsigned (next_frame, mcontext_addr + 19 * 4, 4)) 108 { 109 /* The register windows haven't been flushed. */ 110 for (regnum = SPARC_L0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) 111 trad_frame_set_unknown (cache->saved_regs, regnum); 112 } 113 else 114 { 115 addr = cache->saved_regs[SPARC_SP_REGNUM].addr; 116 addr = get_frame_memory_unsigned (next_frame, addr, 4); 117 for (regnum = SPARC_L0_REGNUM; 118 regnum <= SPARC_I7_REGNUM; regnum++, addr += 4) 119 cache->saved_regs[regnum].addr = addr; 120 } 121 122 return cache; 123} 124 125static void 126sparc32_sol2_sigtramp_frame_this_id (struct frame_info *next_frame, 127 void **this_cache, 128 struct frame_id *this_id) 129{ 130 struct sparc_frame_cache *cache = 131 sparc32_sol2_sigtramp_frame_cache (next_frame, this_cache); 132 133 (*this_id) = frame_id_build (cache->base, cache->pc); 134} 135 136static void 137sparc32_sol2_sigtramp_frame_prev_register (struct frame_info *next_frame, 138 void **this_cache, 139 int regnum, int *optimizedp, 140 enum lval_type *lvalp, 141 CORE_ADDR *addrp, 142 int *realnump, void *valuep) 143{ 144 struct sparc_frame_cache *cache = 145 sparc32_sol2_sigtramp_frame_cache (next_frame, this_cache); 146 147 trad_frame_prev_register (next_frame, cache->saved_regs, regnum, 148 optimizedp, lvalp, addrp, realnump, valuep); 149} 150 151static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind = 152{ 153 SIGTRAMP_FRAME, 154 sparc32_sol2_sigtramp_frame_this_id, 155 sparc32_sol2_sigtramp_frame_prev_register 156}; 157 158static const struct frame_unwind * 159sparc32_sol2_sigtramp_frame_sniffer (struct frame_info *next_frame) 160{ 161 CORE_ADDR pc = frame_pc_unwind (next_frame); 162 char *name; 163 164 find_pc_partial_function (pc, &name, NULL, NULL); 165 if (sparc_sol2_pc_in_sigtramp (pc, name)) 166 return &sparc32_sol2_sigtramp_frame_unwind; 167 168 return NULL; 169} 170 171 172void 173sparc32_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 174{ 175 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 176 177 /* Solaris has SVR4-style shared libraries... */ 178 set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); 179 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 180 181 /* ...which means that we need some special handling when doing 182 prologue analysis. */ 183 tdep->plt_entry_size = 12; 184 185 /* Solaris has kernel-assisted single-stepping support. */ 186 set_gdbarch_software_single_step (gdbarch, NULL); 187 188 set_gdbarch_pc_in_sigtramp (gdbarch, sparc_sol2_pc_in_sigtramp); 189 frame_unwind_append_sniffer (gdbarch, sparc32_sol2_sigtramp_frame_sniffer); 190} 191 192 193/* Provide a prototype to silence -Wmissing-prototypes. */ 194void _initialize_sparc_sol2_tdep (void); 195 196void 197_initialize_sparc_sol2_tdep (void) 198{ 199 gdbarch_register_osabi (bfd_arch_sparc, 0, 200 GDB_OSABI_SOLARIS, sparc32_sol2_init_abi); 201} 202