GDB (API)
/home/stan/gdb/src/gdb/ppcfbsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for PowerPC systems running FreeBSD.
00002 
00003    Copyright (C) 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 "gdbcore.h"
00024 #include "frame-unwind.h"
00025 #include "gdbtypes.h"
00026 #include "osabi.h"
00027 #include "regcache.h"
00028 #include "regset.h"
00029 #include "symtab.h"
00030 #include "target.h"
00031 #include "trad-frame.h"
00032 
00033 #include "gdb_assert.h"
00034 #include "gdb_string.h"
00035 
00036 #include "ppc-tdep.h"
00037 #include "ppc64-tdep.h"
00038 #include "ppcfbsd-tdep.h"
00039 #include "solib-svr4.h"
00040 
00041 
00042 /* 32-bit regset descriptions.  */
00043 
00044 static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets =
00045   {
00046         /* General-purpose registers.  */
00047         /* .r0_offset = */     0,
00048         /* .gpr_size = */      4,
00049         /* .xr_size = */       4,
00050         /* .pc_offset = */     144,
00051         /* .ps_offset = */     -1,
00052         /* .cr_offset = */     132,
00053         /* .lr_offset = */     128,
00054         /* .ctr_offset = */    140,
00055         /* .xer_offset = */    136,
00056         /* .mq_offset = */     -1,
00057 
00058         /* Floating-point registers.  */
00059         /* .f0_offset = */     0,
00060         /* .fpscr_offset = */  256,
00061         /* .fpscr_size = */    8,
00062 #ifdef NOTYET
00063         /* AltiVec registers.  */
00064         /* .vr0_offset = */    0,
00065         /* .vscr_offset = */   512 + 12,
00066         /* .vrsave_offset = */ 512
00067 #endif
00068   };
00069 
00070 /* 64-bit regset descriptions.  */
00071 
00072 static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets =
00073   {
00074         /* General-purpose registers.  */
00075         /* .r0_offset = */     0,
00076         /* .gpr_size = */      8,
00077         /* .xr_size = */       8,
00078         /* .pc_offset = */     288,
00079         /* .ps_offset = */     -1,
00080         /* .cr_offset = */     264,
00081         /* .lr_offset = */     256,
00082         /* .ctr_offset = */    280,
00083         /* .xer_offset = */    272,
00084         /* .mq_offset = */     -1,
00085 
00086         /* Floating-point registers.  */
00087         /* .f0_offset = */     0,
00088         /* .fpscr_offset = */  256,
00089         /* .fpscr_size = */    8,
00090 #ifdef NOYET
00091         /* AltiVec registers.  */
00092         /* .vr0_offset = */    0,
00093         /* .vscr_offset = */   512 + 12,
00094         /* .vrsave_offset = */ 528
00095 #endif
00096   };
00097 
00098 /* 32-bit general-purpose register set.  */
00099 
00100 static const struct regset ppc32_fbsd_gregset = {
00101   &ppc32_fbsd_reg_offsets,
00102   ppc_supply_gregset,
00103   ppc_collect_gregset,
00104   NULL
00105 };
00106 
00107 /* 64-bit general-purpose register set.  */
00108 
00109 static const struct regset ppc64_fbsd_gregset = {
00110   &ppc64_fbsd_reg_offsets,
00111   ppc_supply_gregset,
00112   ppc_collect_gregset,
00113   NULL
00114 };
00115 
00116 /* 32-/64-bit floating-point register set.  */
00117 
00118 static struct regset ppc32_fbsd_fpregset = {
00119   &ppc32_fbsd_reg_offsets,
00120   ppc_supply_fpregset,
00121   ppc_collect_fpregset
00122 };
00123 
00124 const struct regset *
00125 ppc_fbsd_gregset (int wordsize)
00126 {
00127   return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset;
00128 }
00129 
00130 const struct regset *
00131 ppc_fbsd_fpregset (void)
00132 {
00133   return &ppc32_fbsd_fpregset;
00134 }
00135 
00136 /* Return the appropriate register set for the core section identified
00137    by SECT_NAME and SECT_SIZE.  */
00138 
00139 static const struct regset *
00140 ppcfbsd_regset_from_core_section (struct gdbarch *gdbarch,
00141                                   const char *sect_name, size_t sect_size)
00142 {
00143   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00144   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 148)
00145     {
00146       if (tdep->wordsize == 4)
00147         return &ppc32_fbsd_gregset;
00148       else
00149         return &ppc64_fbsd_gregset;
00150     }
00151   if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 264)
00152     return &ppc32_fbsd_fpregset;
00153   return NULL;
00154 }
00155 
00156 /* Default page size.  */
00157 
00158 static const int ppcfbsd_page_size = 4096;
00159 
00160 /* Offset for sigreturn(2).  */
00161 
00162 static const int ppcfbsd_sigreturn_offset[] = {
00163   0xc,                          /* FreeBSD 32-bit  */
00164   -1
00165 };
00166 
00167 /* Signal trampolines.  */
00168 
00169 static int
00170 ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
00171                                 struct frame_info *this_frame,
00172                                 void **this_cache)
00173 {
00174   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00175   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00176   CORE_ADDR pc = get_frame_pc (this_frame);
00177   CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1));
00178   const int *offset;
00179   const char *name;
00180 
00181   /* A stack trampoline is detected if no name is associated
00182    to the current pc and if it points inside a trampoline
00183    sequence.  */
00184 
00185   find_pc_partial_function (pc, &name, NULL, NULL);
00186 
00187   /* If we have a name, we have no trampoline, return.  */
00188   if (name)
00189     return 0;
00190 
00191   for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++)
00192     {
00193       gdb_byte buf[2 * PPC_INSN_SIZE];
00194       unsigned long insn;
00195 
00196       if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
00197                                      buf, sizeof buf))
00198         continue;
00199 
00200       /* Check for "li r0,SYS_sigreturn".  */
00201       insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
00202       if (insn != 0x380001a1)
00203         continue;
00204 
00205       /* Check for "sc".  */
00206       insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
00207                                        PPC_INSN_SIZE, byte_order);
00208       if (insn != 0x44000002)
00209         continue;
00210 
00211       return 1;
00212     }
00213 
00214   return 0;
00215 }
00216 
00217 static struct trad_frame_cache *
00218 ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
00219 {
00220   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00221   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00222   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00223   struct trad_frame_cache *cache;
00224   CORE_ADDR addr, base, func;
00225   gdb_byte buf[PPC_INSN_SIZE];
00226   int i;
00227 
00228   if (*this_cache)
00229     return *this_cache;
00230 
00231   cache = trad_frame_cache_zalloc (this_frame);
00232   *this_cache = cache;
00233 
00234   func = get_frame_pc (this_frame);
00235   func &= ~(ppcfbsd_page_size - 1);
00236   if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
00237     return cache;
00238 
00239   base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
00240   addr = base + 0x10 + 2 * tdep->wordsize;
00241   for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
00242     {
00243       int regnum = i + tdep->ppc_gp0_regnum;
00244       trad_frame_set_reg_addr (cache, regnum, addr);
00245     }
00246   trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
00247   addr += tdep->wordsize;
00248   trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
00249   addr += tdep->wordsize;
00250   trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
00251   addr += tdep->wordsize;
00252   trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
00253   addr += tdep->wordsize;
00254   trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
00255   /* SRR0?  */
00256   addr += tdep->wordsize;
00257 
00258   /* Construct the frame ID using the function start.  */
00259   trad_frame_set_id (cache, frame_id_build (base, func));
00260 
00261   return cache;
00262 }
00263 
00264 static void
00265 ppcfbsd_sigtramp_frame_this_id (struct frame_info *this_frame,
00266                                 void **this_cache, struct frame_id *this_id)
00267 {
00268   struct trad_frame_cache *cache =
00269     ppcfbsd_sigtramp_frame_cache (this_frame, this_cache);
00270 
00271   trad_frame_get_id (cache, this_id);
00272 }
00273 
00274 static struct value *
00275 ppcfbsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
00276                                       void **this_cache, int regnum)
00277 {
00278   struct trad_frame_cache *cache =
00279     ppcfbsd_sigtramp_frame_cache (this_frame, this_cache);
00280 
00281   return trad_frame_get_register (cache, this_frame, regnum);
00282 }
00283 
00284 static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = {
00285   SIGTRAMP_FRAME,
00286   default_frame_unwind_stop_reason,
00287   ppcfbsd_sigtramp_frame_this_id,
00288   ppcfbsd_sigtramp_frame_prev_register,
00289   NULL,
00290   ppcfbsd_sigtramp_frame_sniffer
00291 };
00292 
00293 static enum return_value_convention
00294 ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function,
00295                       struct type *valtype, struct regcache *regcache,
00296                       gdb_byte *readbuf, const gdb_byte *writebuf)
00297 {
00298   return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype,
00299                                            regcache, readbuf, writebuf);
00300 }
00301 
00302 
00303 static void
00304 ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00305 {
00306   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00307 
00308   /* FreeBSD doesn't support the 128-bit `long double' from the psABI.  */
00309   set_gdbarch_long_double_bit (gdbarch, 64);
00310   set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
00311 
00312   if (tdep->wordsize == 4)
00313     {
00314       set_gdbarch_return_value (gdbarch, ppcfbsd_return_value);
00315 
00316       set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
00317       set_solib_svr4_fetch_link_map_offsets (gdbarch,
00318                                              svr4_ilp32_fetch_link_map_offsets);
00319 
00320       frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind);
00321       set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
00322     }
00323 
00324   if (tdep->wordsize == 8)
00325     {
00326       set_gdbarch_convert_from_func_ptr_addr
00327         (gdbarch, ppc64_convert_from_func_ptr_addr);
00328       set_gdbarch_elf_make_msymbol_special (gdbarch,
00329                                             ppc64_elf_make_msymbol_special);
00330 
00331       set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
00332       set_solib_svr4_fetch_link_map_offsets (gdbarch,
00333                                              svr4_lp64_fetch_link_map_offsets);
00334       set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
00335     }
00336 
00337   set_gdbarch_regset_from_core_section
00338     (gdbarch, ppcfbsd_regset_from_core_section);
00339 
00340   set_gdbarch_fetch_tls_load_module_address (gdbarch,
00341                                              svr4_fetch_objfile_link_map);
00342 }
00343 
00344 /* Provide a prototype to silence -Wmissing-prototypes.  */
00345 
00346 void _initialize_ppcfbsd_tdep (void);
00347 
00348 void
00349 _initialize_ppcfbsd_tdep (void)
00350 {
00351   gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD_ELF,
00352                           ppcfbsd_init_abi);
00353   gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64,
00354                           GDB_OSABI_FREEBSD_ELF,
00355                           ppcfbsd_init_abi);
00356   gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF,
00357                           ppcfbsd_init_abi);
00358 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines