GDB (API)
|
00001 /* Target-dependent code for NetBSD/powerpc. 00002 00003 Copyright (C) 2002-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Wasabi Systems, Inc. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "gdbtypes.h" 00024 #include "osabi.h" 00025 #include "regcache.h" 00026 #include "regset.h" 00027 #include "trad-frame.h" 00028 #include "tramp-frame.h" 00029 00030 #include "gdb_assert.h" 00031 #include "gdb_string.h" 00032 00033 #include "ppc-tdep.h" 00034 #include "ppcnbsd-tdep.h" 00035 #include "solib-svr4.h" 00036 00037 /* Register offsets from <machine/reg.h>. */ 00038 struct ppc_reg_offsets ppcnbsd_reg_offsets; 00039 00040 00041 /* Core file support. */ 00042 00043 /* NetBSD/powerpc register sets. */ 00044 00045 struct regset ppcnbsd_gregset = 00046 { 00047 &ppcnbsd_reg_offsets, 00048 ppc_supply_gregset 00049 }; 00050 00051 struct regset ppcnbsd_fpregset = 00052 { 00053 &ppcnbsd_reg_offsets, 00054 ppc_supply_fpregset 00055 }; 00056 00057 /* Return the appropriate register set for the core section identified 00058 by SECT_NAME and SECT_SIZE. */ 00059 00060 static const struct regset * 00061 ppcnbsd_regset_from_core_section (struct gdbarch *gdbarch, 00062 const char *sect_name, size_t sect_size) 00063 { 00064 if (strcmp (sect_name, ".reg") == 0 && sect_size >= 148) 00065 return &ppcnbsd_gregset; 00066 00067 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 264) 00068 return &ppcnbsd_fpregset; 00069 00070 return NULL; 00071 } 00072 00073 00074 /* NetBSD is confused. It appears that 1.5 was using the correct SVR4 00075 convention but, 1.6 switched to the below broken convention. For 00076 the moment use the broken convention. Ulgh! */ 00077 00078 static enum return_value_convention 00079 ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, 00080 struct type *valtype, struct regcache *regcache, 00081 gdb_byte *readbuf, const gdb_byte *writebuf) 00082 { 00083 #if 0 00084 if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT 00085 || TYPE_CODE (valtype) == TYPE_CODE_UNION) 00086 && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8) 00087 && TYPE_VECTOR (valtype)) 00088 && !(TYPE_LENGTH (valtype) == 1 00089 || TYPE_LENGTH (valtype) == 2 00090 || TYPE_LENGTH (valtype) == 4 00091 || TYPE_LENGTH (valtype) == 8)) 00092 return RETURN_VALUE_STRUCT_CONVENTION; 00093 else 00094 #endif 00095 return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, 00096 regcache, readbuf, writebuf); 00097 } 00098 00099 00100 /* Signal trampolines. */ 00101 00102 static const struct tramp_frame ppcnbsd2_sigtramp; 00103 00104 static void 00105 ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, 00106 struct frame_info *this_frame, 00107 struct trad_frame_cache *this_cache, 00108 CORE_ADDR func) 00109 { 00110 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00111 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00112 CORE_ADDR addr, base; 00113 int i; 00114 00115 base = get_frame_register_unsigned (this_frame, 00116 gdbarch_sp_regnum (gdbarch)); 00117 if (self == &ppcnbsd2_sigtramp) 00118 addr = base + 0x10 + 2 * tdep->wordsize; 00119 else 00120 addr = base + 0x18 + 2 * tdep->wordsize; 00121 for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) 00122 { 00123 int regnum = i + tdep->ppc_gp0_regnum; 00124 trad_frame_set_reg_addr (this_cache, regnum, addr); 00125 } 00126 trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr); 00127 addr += tdep->wordsize; 00128 trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr); 00129 addr += tdep->wordsize; 00130 trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr); 00131 addr += tdep->wordsize; 00132 trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr); 00133 addr += tdep->wordsize; 00134 trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch), 00135 addr); /* SRR0? */ 00136 addr += tdep->wordsize; 00137 00138 /* Construct the frame ID using the function start. */ 00139 trad_frame_set_id (this_cache, frame_id_build (base, func)); 00140 } 00141 00142 static const struct tramp_frame ppcnbsd_sigtramp = 00143 { 00144 SIGTRAMP_FRAME, 00145 4, 00146 { 00147 { 0x3821fff0, -1 }, /* add r1,r1,-16 */ 00148 { 0x4e800021, -1 }, /* blrl */ 00149 { 0x38610018, -1 }, /* addi r3,r1,24 */ 00150 { 0x38000127, -1 }, /* li r0,295 */ 00151 { 0x44000002, -1 }, /* sc */ 00152 { 0x38000001, -1 }, /* li r0,1 */ 00153 { 0x44000002, -1 }, /* sc */ 00154 { TRAMP_SENTINEL_INSN, -1 } 00155 }, 00156 ppcnbsd_sigtramp_cache_init 00157 }; 00158 00159 /* NetBSD 2.0 introduced a slightly different signal trampoline. */ 00160 00161 static const struct tramp_frame ppcnbsd2_sigtramp = 00162 { 00163 SIGTRAMP_FRAME, 00164 4, 00165 { 00166 { 0x3821fff0, -1 }, /* add r1,r1,-16 */ 00167 { 0x4e800021, -1 }, /* blrl */ 00168 { 0x38610010, -1 }, /* addi r3,r1,16 */ 00169 { 0x38000127, -1 }, /* li r0,295 */ 00170 { 0x44000002, -1 }, /* sc */ 00171 { 0x38000001, -1 }, /* li r0,1 */ 00172 { 0x44000002, -1 }, /* sc */ 00173 { TRAMP_SENTINEL_INSN, -1 } 00174 }, 00175 ppcnbsd_sigtramp_cache_init 00176 }; 00177 00178 00179 static void 00180 ppcnbsd_init_abi (struct gdbarch_info info, 00181 struct gdbarch *gdbarch) 00182 { 00183 /* For NetBSD, this is an on again, off again thing. Some systems 00184 do use the broken struct convention, and some don't. */ 00185 set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); 00186 00187 /* NetBSD uses SVR4-style shared libraries. */ 00188 set_solib_svr4_fetch_link_map_offsets 00189 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 00190 00191 set_gdbarch_regset_from_core_section 00192 (gdbarch, ppcnbsd_regset_from_core_section); 00193 00194 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp); 00195 tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp); 00196 } 00197 00198 00199 /* Provide a prototype to silence -Wmissing-prototypes. */ 00200 void _initialize_ppcnbsd_tdep (void); 00201 00202 void 00203 _initialize_ppcnbsd_tdep (void) 00204 { 00205 gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF, 00206 ppcnbsd_init_abi); 00207 00208 /* Avoid initializing the register offsets again if they were 00209 already initailized by ppcnbsd-nat.c. */ 00210 if (ppcnbsd_reg_offsets.pc_offset == 0) 00211 { 00212 /* General-purpose registers. */ 00213 ppcnbsd_reg_offsets.r0_offset = 0; 00214 ppcnbsd_reg_offsets.gpr_size = 4; 00215 ppcnbsd_reg_offsets.xr_size = 4; 00216 ppcnbsd_reg_offsets.lr_offset = 128; 00217 ppcnbsd_reg_offsets.cr_offset = 132; 00218 ppcnbsd_reg_offsets.xer_offset = 136; 00219 ppcnbsd_reg_offsets.ctr_offset = 140; 00220 ppcnbsd_reg_offsets.pc_offset = 144; 00221 ppcnbsd_reg_offsets.ps_offset = -1; 00222 ppcnbsd_reg_offsets.mq_offset = -1; 00223 00224 /* Floating-point registers. */ 00225 ppcnbsd_reg_offsets.f0_offset = 0; 00226 ppcnbsd_reg_offsets.fpscr_offset = 256; 00227 ppcnbsd_reg_offsets.fpscr_size = 4; 00228 00229 /* AltiVec registers. */ 00230 ppcnbsd_reg_offsets.vr0_offset = 0; 00231 ppcnbsd_reg_offsets.vrsave_offset = 512; 00232 ppcnbsd_reg_offsets.vscr_offset = 524; 00233 } 00234 }