GDB (API)
/home/stan/gdb/src/gdb/vaxobsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for OpenBSD/vax.
00002 
00003    Copyright (C) 2005-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 "osabi.h"
00025 #include "symtab.h"
00026 #include "trad-frame.h"
00027 
00028 #include "vax-tdep.h"
00029 
00030 #include "gdb_string.h"
00031 
00032 /* Signal trampolines.  */
00033 
00034 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
00035    in virtual memory.  The randomness makes it somewhat tricky to
00036    detect it, but fortunately we can rely on the fact that the start
00037    of the sigtramp routine is page-aligned.  We recognize the
00038    trampoline by looking for the code that invokes the sigreturn
00039    system call.  The offset where we can find that code varies from
00040    release to release.
00041 
00042    By the way, the mapping mentioned above is read-only, so you cannot
00043    place a breakpoint in the signal trampoline.  */
00044 
00045 /* Default page size.  */
00046 static const int vaxobsd_page_size = 4096;
00047 
00048 /* Offset for sigreturn(2).  */
00049 static const int vaxobsd_sigreturn_offset = 0x11;
00050 
00051 /* Instruction sequence for sigreturn(2).  VAX doesn't have
00052    fixed-length instructions so we include the ensuing exit(2) to
00053    reduce the chance of spurious matches.  */
00054 static const gdb_byte vaxobsd_sigreturn[] = {
00055   0xbc, 0x8f, 0x67, 0x00,       /* chmk $SYS_sigreturn */
00056   0xbc, 0x01                    /* chmk $SYS_exit */
00057 };
00058 
00059 static int
00060 vaxobsd_sigtramp_sniffer (const struct frame_unwind *self,
00061                           struct frame_info *this_frame,
00062                           void **this_cache)
00063 {
00064   CORE_ADDR pc = get_frame_pc (this_frame);
00065   CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1));
00066   CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset;
00067   gdb_byte *buf;
00068   const char *name;
00069 
00070   find_pc_partial_function (pc, &name, NULL, NULL);
00071   if (name)
00072     return 0;
00073 
00074   buf = alloca(sizeof vaxobsd_sigreturn);
00075   if (!safe_frame_unwind_memory (this_frame, sigreturn_addr,
00076                                  buf, sizeof vaxobsd_sigreturn))
00077     return 0;
00078 
00079   if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0)
00080     return 1;
00081 
00082   return 0;
00083 }
00084 
00085 static struct trad_frame_cache *
00086 vaxobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
00087 {
00088   struct trad_frame_cache *cache;
00089   CORE_ADDR addr, base, func;
00090 
00091   if (*this_cache)
00092     return *this_cache;
00093 
00094   cache = trad_frame_cache_zalloc (this_frame);
00095   *this_cache = cache;
00096 
00097   func = get_frame_pc (this_frame);
00098   func &= ~(vaxobsd_page_size - 1);
00099 
00100   base = get_frame_register_unsigned (this_frame, VAX_SP_REGNUM);
00101   addr = get_frame_memory_unsigned (this_frame, base - 4, 4);
00102 
00103   trad_frame_set_reg_addr (cache, VAX_SP_REGNUM, addr + 8);
00104   trad_frame_set_reg_addr (cache, VAX_FP_REGNUM, addr + 12);
00105   trad_frame_set_reg_addr (cache, VAX_AP_REGNUM, addr + 16);
00106   trad_frame_set_reg_addr (cache, VAX_PC_REGNUM, addr + 20);
00107   trad_frame_set_reg_addr (cache, VAX_PS_REGNUM, addr + 24);
00108 
00109   /* Construct the frame ID using the function start.  */
00110   trad_frame_set_id (cache, frame_id_build (base, func));
00111 
00112   return cache;
00113 }
00114 
00115 static void
00116 vaxobsd_sigtramp_frame_this_id (struct frame_info *this_frame,
00117                                 void **this_cache, struct frame_id *this_id)
00118 {
00119   struct trad_frame_cache *cache =
00120     vaxobsd_sigtramp_frame_cache (this_frame, this_cache);
00121 
00122   trad_frame_get_id (cache, this_id);
00123 }
00124 
00125 static struct value *
00126 vaxobsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
00127                                       void **this_cache, int regnum)
00128 {
00129   struct trad_frame_cache *cache =
00130     vaxobsd_sigtramp_frame_cache (this_frame, this_cache);
00131 
00132   return trad_frame_get_register (cache, this_frame, regnum);
00133 }
00134 
00135 static const struct frame_unwind vaxobsd_sigtramp_frame_unwind = {
00136   SIGTRAMP_FRAME,
00137   default_frame_unwind_stop_reason,
00138   vaxobsd_sigtramp_frame_this_id,
00139   vaxobsd_sigtramp_frame_prev_register,
00140   NULL,
00141   vaxobsd_sigtramp_sniffer
00142 };
00143 
00144 
00145 /* OpenBSD a.out.  */
00146 
00147 static void
00148 vaxobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00149 {
00150   frame_unwind_append_unwinder (gdbarch, &vaxobsd_sigtramp_frame_unwind);
00151 }
00152 
00153 /* FIXME: kettenis/20050821: Since OpenBSD/vax binaries are
00154    indistingushable from NetBSD/vax a.out binaries, building a GDB
00155    that should support both these targets will probably not work as
00156    expected.  */
00157 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
00158 
00159 static enum gdb_osabi
00160 vaxobsd_aout_osabi_sniffer (bfd *abfd)
00161 {
00162   if (strcmp (bfd_get_target (abfd), "a.out-vax-netbsd") == 0)
00163     return GDB_OSABI_OPENBSD_AOUT;
00164 
00165   return GDB_OSABI_UNKNOWN;
00166 }
00167 
00168 
00169 /* Provide a prototype to silence -Wmissing-prototypes.  */
00170 void _initialize_vaxobsd_tdep (void);
00171 
00172 void
00173 _initialize_vaxobsd_tdep (void)
00174 {
00175   gdbarch_register_osabi_sniffer (bfd_arch_vax, bfd_target_aout_flavour,
00176                                   vaxobsd_aout_osabi_sniffer);
00177 
00178   gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_OPENBSD_AOUT,
00179                           vaxobsd_init_abi);
00180 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines