GDB (API)
/home/stan/gdb/src/gdb/sparc64obsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for OpenBSD/sparc64.
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 "frame.h"
00022 #include "frame-unwind.h"
00023 #include "gdbcore.h"
00024 #include "osabi.h"
00025 #include "regcache.h"
00026 #include "regset.h"
00027 #include "symtab.h"
00028 #include "objfiles.h"
00029 #include "trad-frame.h"
00030 
00031 #include "gdb_assert.h"
00032 
00033 #include "obsd-tdep.h"
00034 #include "sparc64-tdep.h"
00035 #include "solib-svr4.h"
00036 #include "bsd-uthread.h"
00037 
00038 /* OpenBSD uses the traditional NetBSD core file format, even for
00039    ports that use ELF.  The core files don't use multiple register
00040    sets.  Instead, the general-purpose and floating-point registers
00041    are lumped together in a single section.  Unlike on NetBSD, OpenBSD
00042    uses a different layout for its general-purpose registers than the
00043    layout used for ptrace(2).  */
00044 
00045 /* From <machine/reg.h>.  */
00046 const struct sparc_gregset sparc64obsd_core_gregset =
00047 {
00048   0 * 8,                        /* "tstate" */
00049   1 * 8,                        /* %pc */
00050   2 * 8,                        /* %npc */
00051   3 * 8,                        /* %y */
00052   -1,                           /* %fprs */
00053   -1,
00054   7 * 8,                        /* %g1 */
00055   22 * 8,                       /* %l0 */
00056   4                             /* sizeof (%y) */
00057 };
00058 
00059 static void
00060 sparc64obsd_supply_gregset (const struct regset *regset,
00061                             struct regcache *regcache,
00062                             int regnum, const void *gregs, size_t len)
00063 {
00064   const char *regs = gregs;
00065 
00066   sparc64_supply_gregset (&sparc64obsd_core_gregset, regcache, regnum, regs);
00067   sparc64_supply_fpregset (&sparc64_bsd_fpregset, regcache, regnum, regs + 288);
00068 }
00069 
00070 
00071 /* Signal trampolines.  */
00072 
00073 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
00074    in virtual memory.  The randomness makes it somewhat tricky to
00075    detect it, but fortunately we can rely on the fact that the start
00076    of the sigtramp routine is page-aligned.  We recognize the
00077    trampoline by looking for the code that invokes the sigreturn
00078    system call.  The offset where we can find that code varies from
00079    release to release.
00080 
00081    By the way, the mapping mentioned above is read-only, so you cannot
00082    place a breakpoint in the signal trampoline.  */
00083 
00084 /* Default page size.  */
00085 static const int sparc64obsd_page_size = 8192;
00086 
00087 /* Offset for sigreturn(2).  */
00088 static const int sparc64obsd_sigreturn_offset[] = {
00089   0xf0,                         /* OpenBSD 3.8 */
00090   0xec,                         /* OpenBSD 3.6 */
00091   0xe8,                         /* OpenBSD 3.2 */
00092   -1
00093 };
00094 
00095 static int
00096 sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
00097 {
00098   CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
00099   unsigned long insn;
00100   const int *offset;
00101 
00102   if (name)
00103     return 0;
00104 
00105   for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++)
00106     {
00107       /* Check for "restore %g0, SYS_sigreturn, %g1".  */
00108       insn = sparc_fetch_instruction (start_pc + *offset);
00109       if (insn != 0x83e82067)
00110         continue;
00111 
00112       /* Check for "t ST_SYSCALL".  */
00113       insn = sparc_fetch_instruction (start_pc + *offset + 8);
00114       if (insn != 0x91d02000)
00115         continue;
00116 
00117       return 1;
00118     }
00119 
00120   return 0;
00121 }
00122 
00123 static struct sparc_frame_cache *
00124 sparc64obsd_frame_cache (struct frame_info *this_frame, void **this_cache)
00125 {
00126   struct sparc_frame_cache *cache;
00127   CORE_ADDR addr;
00128 
00129   if (*this_cache)
00130     return *this_cache;
00131 
00132   cache = sparc_frame_cache (this_frame, this_cache);
00133   gdb_assert (cache == *this_cache);
00134 
00135   /* If we couldn't find the frame's function, we're probably dealing
00136      with an on-stack signal trampoline.  */
00137   if (cache->pc == 0)
00138     {
00139       cache->pc = get_frame_pc (this_frame);
00140       cache->pc &= ~(sparc64obsd_page_size - 1);
00141 
00142       /* Since we couldn't find the frame's function, the cache was
00143          initialized under the assumption that we're frameless.  */
00144       sparc_record_save_insn (cache);
00145       addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
00146       if (addr & 1)
00147         addr += BIAS;
00148       cache->base = addr;
00149     }
00150 
00151   /* We find the appropriate instance of `struct sigcontext' at a
00152      fixed offset in the signal frame.  */
00153   addr = cache->base + 128 + 16;
00154   cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame);
00155 
00156   return cache;
00157 }
00158 
00159 static void
00160 sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache,
00161                            struct frame_id *this_id)
00162 {
00163   struct sparc_frame_cache *cache =
00164     sparc64obsd_frame_cache (this_frame, this_cache);
00165 
00166   (*this_id) = frame_id_build (cache->base, cache->pc);
00167 }
00168 
00169 static struct value *
00170 sparc64obsd_frame_prev_register (struct frame_info *this_frame,
00171                                  void **this_cache, int regnum)
00172 {
00173   struct sparc_frame_cache *cache =
00174     sparc64obsd_frame_cache (this_frame, this_cache);
00175 
00176   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
00177 }
00178 
00179 static int
00180 sparc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
00181                                     struct frame_info *this_frame,
00182                                     void **this_cache)
00183 {
00184   CORE_ADDR pc = get_frame_pc (this_frame);
00185   const char *name;
00186 
00187   find_pc_partial_function (pc, &name, NULL, NULL);
00188   if (sparc64obsd_pc_in_sigtramp (pc, name))
00189     return 1;
00190 
00191   return 0;
00192 }
00193 
00194 static const struct frame_unwind sparc64obsd_frame_unwind =
00195 {
00196   SIGTRAMP_FRAME,
00197   default_frame_unwind_stop_reason,
00198   sparc64obsd_frame_this_id,
00199   sparc64obsd_frame_prev_register,
00200   NULL,
00201   sparc64obsd_sigtramp_frame_sniffer
00202 };
00203 
00204 /* Kernel debugging support.  */
00205 
00206 static struct sparc_frame_cache *
00207 sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache)
00208 {
00209   struct sparc_frame_cache *cache;
00210   CORE_ADDR sp, trapframe_addr;
00211   int regnum;
00212 
00213   if (*this_cache)
00214     return *this_cache;
00215 
00216   cache = sparc_frame_cache (this_frame, this_cache);
00217   gdb_assert (cache == *this_cache);
00218 
00219   sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
00220   trapframe_addr = sp + BIAS + 176;
00221 
00222   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
00223 
00224   cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr;
00225   cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8;
00226   cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16;
00227 
00228   for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++)
00229     cache->saved_regs[regnum].addr =
00230       trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8;
00231 
00232   return cache;
00233 }
00234 
00235 static void
00236 sparc64obsd_trapframe_this_id (struct frame_info *this_frame,
00237                                void **this_cache, struct frame_id *this_id)
00238 {
00239   struct sparc_frame_cache *cache =
00240     sparc64obsd_trapframe_cache (this_frame, this_cache);
00241 
00242   (*this_id) = frame_id_build (cache->base, cache->pc);
00243 }
00244 
00245 static struct value *
00246 sparc64obsd_trapframe_prev_register (struct frame_info *this_frame,
00247                                      void **this_cache, int regnum)
00248 {
00249   struct sparc_frame_cache *cache =
00250     sparc64obsd_trapframe_cache (this_frame, this_cache);
00251 
00252   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
00253 }
00254 
00255 static int
00256 sparc64obsd_trapframe_sniffer (const struct frame_unwind *self,
00257                                struct frame_info *this_frame,
00258                                void **this_cache)
00259 {
00260   CORE_ADDR pc;
00261   ULONGEST pstate;
00262   const char *name;
00263 
00264   /* Check whether we are in privileged mode, and bail out if we're not.  */
00265   pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM);
00266   if ((pstate & SPARC64_PSTATE_PRIV) == 0)
00267     return 0;
00268 
00269   pc = get_frame_address_in_block (this_frame);
00270   find_pc_partial_function (pc, &name, NULL, NULL);
00271   if (name && strcmp (name, "Lslowtrap_reenter") == 0)
00272     return 1;
00273 
00274   return 0;
00275 }
00276 
00277 static const struct frame_unwind sparc64obsd_trapframe_unwind =
00278 {
00279   NORMAL_FRAME,
00280   default_frame_unwind_stop_reason,
00281   sparc64obsd_trapframe_this_id,
00282   sparc64obsd_trapframe_prev_register,
00283   NULL,
00284   sparc64obsd_trapframe_sniffer
00285 };
00286 
00287 
00288 /* Threads support.  */
00289 
00290 /* Offset wthin the thread structure where we can find %fp and %i7.  */
00291 #define SPARC64OBSD_UTHREAD_FP_OFFSET   232
00292 #define SPARC64OBSD_UTHREAD_PC_OFFSET   240
00293 
00294 static void
00295 sparc64obsd_supply_uthread (struct regcache *regcache,
00296                             int regnum, CORE_ADDR addr)
00297 {
00298   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00299   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00300   CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
00301   gdb_byte buf[8];
00302 
00303   gdb_assert (regnum >= -1);
00304 
00305   fp = read_memory_unsigned_integer (fp_addr, 8, byte_order);
00306   if (regnum == SPARC_SP_REGNUM || regnum == -1)
00307     {
00308       store_unsigned_integer (buf, 8, byte_order, fp);
00309       regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
00310 
00311       if (regnum == SPARC_SP_REGNUM)
00312         return;
00313     }
00314 
00315   if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM
00316       || regnum == -1)
00317     {
00318       CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
00319 
00320       i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order);
00321       if (regnum == SPARC64_PC_REGNUM || regnum == -1)
00322         {
00323           store_unsigned_integer (buf, 8, byte_order, i7 + 8);
00324           regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf);
00325         }
00326       if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
00327         {
00328           store_unsigned_integer (buf, 8, byte_order, i7 + 12);
00329           regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf);
00330         }
00331 
00332       if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM)
00333         return;
00334     }
00335 
00336   sparc_supply_rwindow (regcache, fp, regnum);
00337 }
00338 
00339 static void
00340 sparc64obsd_collect_uthread(const struct regcache *regcache,
00341                             int regnum, CORE_ADDR addr)
00342 {
00343   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00344   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00345   CORE_ADDR sp;
00346   gdb_byte buf[8];
00347 
00348   gdb_assert (regnum >= -1);
00349 
00350   if (regnum == SPARC_SP_REGNUM || regnum == -1)
00351     {
00352       CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET;
00353 
00354       regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
00355       write_memory (fp_addr,buf, 8);
00356     }
00357 
00358   if (regnum == SPARC64_PC_REGNUM || regnum == -1)
00359     {
00360       CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET;
00361 
00362       regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf);
00363       i7 = extract_unsigned_integer (buf, 8, byte_order) - 8;
00364       write_memory_unsigned_integer (i7_addr, 8, byte_order, i7);
00365 
00366       if (regnum == SPARC64_PC_REGNUM)
00367         return;
00368     }
00369 
00370   regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
00371   sp = extract_unsigned_integer (buf, 8, byte_order);
00372   sparc_collect_rwindow (regcache, sp, regnum);
00373 }
00374 
00375 
00376 static void
00377 sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00378 {
00379   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00380 
00381   tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL);
00382   tdep->sizeof_gregset = 832;
00383 
00384   /* Make sure we can single-step "new" syscalls.  */
00385   tdep->step_trap = sparcnbsd_step_trap;
00386 
00387   frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind);
00388   frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind);
00389 
00390   sparc64_init_abi (info, gdbarch);
00391 
00392   /* OpenBSD/sparc64 has SVR4-style shared libraries.  */
00393   set_solib_svr4_fetch_link_map_offsets
00394     (gdbarch, svr4_lp64_fetch_link_map_offsets);
00395   set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
00396 
00397   /* OpenBSD provides a user-level threads implementation.  */
00398   bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread);
00399   bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread);
00400 }
00401 
00402 
00403 /* Provide a prototype to silence -Wmissing-prototypes.  */
00404 void _initialize_sparc64obsd_tdep (void);
00405 
00406 void
00407 _initialize_sparc64obsd_tdep (void)
00408 {
00409   gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
00410                           GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi);
00411 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines