GDB (API)
/home/stan/gdb/src/gdb/ppcnbsd-tdep.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines