GDB (API)
/home/stan/gdb/src/gdb/sparcobsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for OpenBSD/sparc.
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 "floatformat.h"
00022 #include "frame.h"
00023 #include "frame-unwind.h"
00024 #include "gdbcore.h"
00025 #include "osabi.h"
00026 #include "regcache.h"
00027 #include "symtab.h"
00028 #include "trad-frame.h"
00029 
00030 #include "gdb_assert.h"
00031 
00032 #include "obsd-tdep.h"
00033 #include "sparc-tdep.h"
00034 #include "solib-svr4.h"
00035 #include "bsd-uthread.h"
00036 
00037 /* Signal trampolines.  */
00038 
00039 /* The OpenBSD kernel maps the signal trampoline at some random
00040    location in user space, which means that the traditional BSD way of
00041    detecting it won't work.
00042 
00043    The signal trampoline will be mapped at an address that is page
00044    aligned.  We recognize the signal trampoline by looking for the
00045    sigreturn system call.  */
00046 
00047 static const int sparc32obsd_page_size = 4096;
00048 
00049 static int
00050 sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
00051 {
00052   CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1));
00053   unsigned long insn;
00054 
00055   if (name)
00056     return 0;
00057 
00058   /* Check for "restore %g0, SYS_sigreturn, %g1".  */
00059   insn = sparc_fetch_instruction (start_pc + 0xec);
00060   if (insn != 0x83e82067)
00061     return 0;
00062 
00063   /* Check for "t ST_SYSCALL".  */
00064   insn = sparc_fetch_instruction (start_pc + 0xf4);
00065   if (insn != 0x91d02000)
00066     return 0;
00067 
00068   return 1;
00069 }
00070 
00071 static struct sparc_frame_cache *
00072 sparc32obsd_sigtramp_frame_cache (struct frame_info *this_frame,
00073                                   void **this_cache)
00074 {
00075   struct sparc_frame_cache *cache;
00076   CORE_ADDR addr;
00077 
00078   if (*this_cache)
00079     return *this_cache;
00080 
00081   cache = sparc_frame_cache (this_frame, this_cache);
00082   gdb_assert (cache == *this_cache);
00083 
00084   /* If we couldn't find the frame's function, we're probably dealing
00085      with an on-stack signal trampoline.  */
00086   if (cache->pc == 0)
00087     {
00088       cache->pc = get_frame_pc (this_frame);
00089       cache->pc &= ~(sparc32obsd_page_size - 1);
00090 
00091       /* Since we couldn't find the frame's function, the cache was
00092          initialized under the assumption that we're frameless.  */
00093       sparc_record_save_insn (cache);
00094       addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
00095       cache->base = addr;
00096     }
00097 
00098   cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame);
00099 
00100   return cache;
00101 }
00102 
00103 static void
00104 sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame,
00105                                     void **this_cache,
00106                                     struct frame_id *this_id)
00107 {
00108   struct sparc_frame_cache *cache =
00109     sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
00110 
00111   (*this_id) = frame_id_build (cache->base, cache->pc);
00112 }
00113 
00114 static struct value *
00115 sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
00116                                           void **this_cache, int regnum)
00117 {
00118   struct sparc_frame_cache *cache =
00119     sparc32obsd_sigtramp_frame_cache (this_frame, this_cache);
00120 
00121   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
00122 }
00123 
00124 static int
00125 sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
00126                                     struct frame_info *this_frame,
00127                                     void **this_cache)
00128 {
00129   CORE_ADDR pc = get_frame_pc (this_frame);
00130   const char *name;
00131 
00132   find_pc_partial_function (pc, &name, NULL, NULL);
00133   if (sparc32obsd_pc_in_sigtramp (pc, name))
00134     return 1;
00135 
00136   return 0;
00137 }
00138 static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind =
00139 {
00140   SIGTRAMP_FRAME,
00141   default_frame_unwind_stop_reason,
00142   sparc32obsd_sigtramp_frame_this_id,
00143   sparc32obsd_sigtramp_frame_prev_register,
00144   NULL,
00145   sparc32obsd_sigtramp_frame_sniffer
00146 };
00147 
00148 
00149 
00150 /* Offset wthin the thread structure where we can find %fp and %i7.  */
00151 #define SPARC32OBSD_UTHREAD_FP_OFFSET   128
00152 #define SPARC32OBSD_UTHREAD_PC_OFFSET   132
00153 
00154 static void
00155 sparc32obsd_supply_uthread (struct regcache *regcache,
00156                             int regnum, CORE_ADDR addr)
00157 {
00158   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00159   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00160   CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
00161   gdb_byte buf[4];
00162 
00163   gdb_assert (regnum >= -1);
00164 
00165   fp = read_memory_unsigned_integer (fp_addr, 4, byte_order);
00166   if (regnum == SPARC_SP_REGNUM || regnum == -1)
00167     {
00168       store_unsigned_integer (buf, 4, byte_order, fp);
00169       regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf);
00170 
00171       if (regnum == SPARC_SP_REGNUM)
00172         return;
00173     }
00174 
00175   if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM
00176       || regnum == -1)
00177     {
00178       CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
00179 
00180       i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order);
00181       if (regnum == SPARC32_PC_REGNUM || regnum == -1)
00182         {
00183           store_unsigned_integer (buf, 4, byte_order, i7 + 8);
00184           regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf);
00185         }
00186       if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
00187         {
00188           store_unsigned_integer (buf, 4, byte_order, i7 + 12);
00189           regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf);
00190         }
00191 
00192       if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM)
00193         return;
00194     }
00195 
00196   sparc_supply_rwindow (regcache, fp, regnum);
00197 }
00198 
00199 static void
00200 sparc32obsd_collect_uthread(const struct regcache *regcache,
00201                             int regnum, CORE_ADDR addr)
00202 {
00203   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00204   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00205   CORE_ADDR sp;
00206   gdb_byte buf[4];
00207 
00208   gdb_assert (regnum >= -1);
00209 
00210   if (regnum == SPARC_SP_REGNUM || regnum == -1)
00211     {
00212       CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET;
00213 
00214       regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
00215       write_memory (fp_addr,buf, 4);
00216     }
00217 
00218   if (regnum == SPARC32_PC_REGNUM || regnum == -1)
00219     {
00220       CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET;
00221 
00222       regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf);
00223       i7 = extract_unsigned_integer (buf, 4, byte_order) - 8;
00224       write_memory_unsigned_integer (i7_addr, 4, byte_order, i7);
00225 
00226       if (regnum == SPARC32_PC_REGNUM)
00227         return;
00228     }
00229 
00230   regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf);
00231   sp = extract_unsigned_integer (buf, 4, byte_order);
00232   sparc_collect_rwindow (regcache, sp, regnum);
00233 }
00234 
00235 
00236 static void
00237 sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00238 {
00239   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00240 
00241   /* OpenBSD/sparc is very similar to NetBSD/sparc ELF.  */
00242   sparc32nbsd_elf_init_abi (info, gdbarch);
00243 
00244   set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
00245 
00246   frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind);
00247 
00248   /* OpenBSD provides a user-level threads implementation.  */
00249   bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread);
00250   bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread);
00251 }
00252 
00253 
00254 /* Provide a prototype to silence -Wmissing-prototypes.  */
00255 void _initialize_sparc32obsd_tdep (void);
00256 
00257 void
00258 _initialize_sparc32obsd_tdep (void)
00259 {
00260   gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF,
00261                           sparc32obsd_init_abi);
00262 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines