GDB (API)
/home/stan/gdb/src/gdb/ppcobsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for OpenBSD/powerpc.
00002 
00003    Copyright (C) 2004-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "arch-utils.h"
00022 #include "frame.h"
00023 #include "frame-unwind.h"
00024 #include "gdbtypes.h"
00025 #include "osabi.h"
00026 #include "regcache.h"
00027 #include "regset.h"
00028 #include "symtab.h"
00029 #include "trad-frame.h"
00030 
00031 #include "gdb_assert.h"
00032 #include "gdb_string.h"
00033 
00034 #include "ppc-tdep.h"
00035 #include "ppcobsd-tdep.h"
00036 #include "solib-svr4.h"
00037 
00038 /* Register offsets from <machine/reg.h>.  */
00039 struct ppc_reg_offsets ppcobsd_reg_offsets;
00040 struct ppc_reg_offsets ppcobsd_fpreg_offsets;
00041 
00042 
00043 /* Core file support.  */
00044 
00045 /* Supply register REGNUM in the general-purpose register set REGSET
00046    from the buffer specified by GREGS and LEN to register cache
00047    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
00048 
00049 void
00050 ppcobsd_supply_gregset (const struct regset *regset,
00051                         struct regcache *regcache, int regnum,
00052                         const void *gregs, size_t len)
00053 {
00054   ppc_supply_gregset (regset, regcache, regnum, gregs, len);
00055   ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
00056 }
00057 
00058 /* Collect register REGNUM in the general-purpose register set
00059    REGSET, from register cache REGCACHE into the buffer specified by
00060    GREGS and LEN.  If REGNUM is -1, do this for all registers in
00061    REGSET.  */
00062 
00063 void
00064 ppcobsd_collect_gregset (const struct regset *regset,
00065                          const struct regcache *regcache, int regnum,
00066                          void *gregs, size_t len)
00067 {
00068   ppc_collect_gregset (regset, regcache, regnum, gregs, len);
00069   ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
00070 }
00071 
00072 /* OpenBSD/powerpc register set.  */
00073 
00074 struct regset ppcobsd_gregset =
00075 {
00076   &ppcobsd_reg_offsets,
00077   ppcobsd_supply_gregset
00078 };
00079 
00080 struct regset ppcobsd_fpregset =
00081 {
00082   &ppcobsd_fpreg_offsets,
00083   ppc_supply_fpregset
00084 };
00085 
00086 /* Return the appropriate register set for the core section identified
00087    by SECT_NAME and SECT_SIZE.  */
00088 
00089 static const struct regset *
00090 ppcobsd_regset_from_core_section (struct gdbarch *gdbarch,
00091                                   const char *sect_name, size_t sect_size)
00092 {
00093   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 412)
00094     return &ppcobsd_gregset;
00095 
00096   return NULL;
00097 }
00098 
00099 
00100 /* Signal trampolines.  */
00101 
00102 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
00103    in virtual memory.  The randomness makes it somewhat tricky to
00104    detect it, but fortunately we can rely on the fact that the start
00105    of the sigtramp routine is page-aligned.  We recognize the
00106    trampoline by looking for the code that invokes the sigreturn
00107    system call.  The offset where we can find that code varies from
00108    release to release.
00109 
00110    By the way, the mapping mentioned above is read-only, so you cannot
00111    place a breakpoint in the signal trampoline.  */
00112 
00113 /* Default page size.  */
00114 static const int ppcobsd_page_size = 4096;
00115 
00116 /* Offset for sigreturn(2).  */
00117 static const int ppcobsd_sigreturn_offset[] = {
00118   0x98,                         /* OpenBSD 3.8 */
00119   0x0c,                         /* OpenBSD 3.2 */
00120   -1
00121 };
00122 
00123 static int
00124 ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
00125                                 struct frame_info *this_frame,
00126                                 void **this_cache)
00127 {
00128   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00129   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00130   CORE_ADDR pc = get_frame_pc (this_frame);
00131   CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1));
00132   const int *offset;
00133   const char *name;
00134 
00135   find_pc_partial_function (pc, &name, NULL, NULL);
00136   if (name)
00137     return 0;
00138 
00139   for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++)
00140     {
00141       gdb_byte buf[2 * PPC_INSN_SIZE];
00142       unsigned long insn;
00143 
00144       if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
00145                                      buf, sizeof buf))
00146         continue;
00147 
00148       /* Check for "li r0,SYS_sigreturn".  */
00149       insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
00150       if (insn != 0x38000067)
00151         continue;
00152 
00153       /* Check for "sc".  */
00154       insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
00155                                        PPC_INSN_SIZE, byte_order);
00156       if (insn != 0x44000002)
00157         continue;
00158 
00159       return 1;
00160     }
00161 
00162   return 0;
00163 }
00164 
00165 static struct trad_frame_cache *
00166 ppcobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
00167 {
00168   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00169   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00170   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00171   struct trad_frame_cache *cache;
00172   CORE_ADDR addr, base, func;
00173   gdb_byte buf[PPC_INSN_SIZE];
00174   unsigned long insn, sigcontext_offset;
00175   int i;
00176 
00177   if (*this_cache)
00178     return *this_cache;
00179 
00180   cache = trad_frame_cache_zalloc (this_frame);
00181   *this_cache = cache;
00182 
00183   func = get_frame_pc (this_frame);
00184   func &= ~(ppcobsd_page_size - 1);
00185   if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
00186     return cache;
00187 
00188   /* Calculate the offset where we can find `struct sigcontext'.  We
00189      base our calculation on the amount of stack space reserved by the
00190      first instruction of the signal trampoline.  */
00191   insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
00192   sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;
00193 
00194   base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
00195   addr = base + sigcontext_offset + 2 * tdep->wordsize;
00196   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
00197     {
00198       int regnum = i + tdep->ppc_gp0_regnum;
00199       trad_frame_set_reg_addr (cache, regnum, addr);
00200     }
00201   trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
00202   addr += tdep->wordsize;
00203   trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
00204   addr += tdep->wordsize;
00205   trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
00206   addr += tdep->wordsize;
00207   trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
00208   addr += tdep->wordsize;
00209   trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
00210   /* SRR0?  */
00211   addr += tdep->wordsize;
00212 
00213   /* Construct the frame ID using the function start.  */
00214   trad_frame_set_id (cache, frame_id_build (base, func));
00215 
00216   return cache;
00217 }
00218 
00219 static void
00220 ppcobsd_sigtramp_frame_this_id (struct frame_info *this_frame,
00221                                 void **this_cache, struct frame_id *this_id)
00222 {
00223   struct trad_frame_cache *cache =
00224     ppcobsd_sigtramp_frame_cache (this_frame, this_cache);
00225 
00226   trad_frame_get_id (cache, this_id);
00227 }
00228 
00229 static struct value *
00230 ppcobsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
00231                                       void **this_cache, int regnum)
00232 {
00233   struct trad_frame_cache *cache =
00234     ppcobsd_sigtramp_frame_cache (this_frame, this_cache);
00235 
00236   return trad_frame_get_register (cache, this_frame, regnum);
00237 }
00238 
00239 static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = {
00240   SIGTRAMP_FRAME,
00241   default_frame_unwind_stop_reason,
00242   ppcobsd_sigtramp_frame_this_id,
00243   ppcobsd_sigtramp_frame_prev_register,
00244   NULL,
00245   ppcobsd_sigtramp_frame_sniffer
00246 };
00247 
00248 
00249 static void
00250 ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00251 {
00252   /* OpenBSD doesn't support the 128-bit `long double' from the psABI.  */
00253   set_gdbarch_long_double_bit (gdbarch, 64);
00254   set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
00255 
00256   /* OpenBSD currently uses a broken GCC.  */
00257   set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value);
00258 
00259   /* OpenBSD uses SVR4-style shared libraries.  */
00260   set_solib_svr4_fetch_link_map_offsets
00261     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
00262 
00263   set_gdbarch_regset_from_core_section
00264     (gdbarch, ppcobsd_regset_from_core_section);
00265 
00266   frame_unwind_append_unwinder (gdbarch, &ppcobsd_sigtramp_frame_unwind);
00267 }
00268 
00269 
00270 /* OpenBSD uses uses the traditional NetBSD core file format, even for
00271    ports that use ELF.  */
00272 #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
00273 
00274 static enum gdb_osabi
00275 ppcobsd_core_osabi_sniffer (bfd *abfd)
00276 {
00277   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
00278     return GDB_OSABI_NETBSD_CORE;
00279 
00280   return GDB_OSABI_UNKNOWN;
00281 }
00282 
00283 
00284 /* Provide a prototype to silence -Wmissing-prototypes.  */
00285 void _initialize_ppcobsd_tdep (void);
00286 
00287 void
00288 _initialize_ppcobsd_tdep (void)
00289 {
00290   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
00291   gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour,
00292                                   ppcobsd_core_osabi_sniffer);
00293 
00294   gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF,
00295                           ppcobsd_init_abi);
00296   gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF,
00297                           ppcobsd_init_abi);
00298 
00299   /* Avoid initializing the register offsets again if they were
00300      already initailized by ppcobsd-nat.c.  */
00301   if (ppcobsd_reg_offsets.pc_offset == 0)
00302     {
00303       /* General-purpose registers.  */
00304       ppcobsd_reg_offsets.r0_offset = 0;
00305       ppcobsd_reg_offsets.gpr_size = 4;
00306       ppcobsd_reg_offsets.xr_size = 4;
00307       ppcobsd_reg_offsets.pc_offset = 384;
00308       ppcobsd_reg_offsets.ps_offset = 388;
00309       ppcobsd_reg_offsets.cr_offset = 392;
00310       ppcobsd_reg_offsets.lr_offset = 396;
00311       ppcobsd_reg_offsets.ctr_offset = 400;
00312       ppcobsd_reg_offsets.xer_offset = 404;
00313       ppcobsd_reg_offsets.mq_offset = 408;
00314 
00315       /* Floating-point registers.  */
00316       ppcobsd_reg_offsets.f0_offset = 128;
00317       ppcobsd_reg_offsets.fpscr_offset = -1;
00318 
00319       /* AltiVec registers.  */
00320       ppcobsd_reg_offsets.vr0_offset = 0;
00321       ppcobsd_reg_offsets.vscr_offset = 512;
00322       ppcobsd_reg_offsets.vrsave_offset = 520;
00323     }
00324 
00325   if (ppcobsd_fpreg_offsets.fpscr_offset == 0)
00326     {
00327       /* Floating-point registers.  */
00328       ppcobsd_reg_offsets.f0_offset = 0;
00329       ppcobsd_reg_offsets.fpscr_offset = 256;
00330       ppcobsd_reg_offsets.fpscr_size = 4;
00331     }
00332 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines