GDB (API)
/home/stan/gdb/src/gdb/sh-linux-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for GNU/Linux Super-H.
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 "osabi.h"
00022 
00023 #include "solib-svr4.h"
00024 #include "symtab.h"
00025 
00026 #include "trad-frame.h"
00027 #include "tramp-frame.h"
00028 
00029 #include "glibc-tdep.h"
00030 #include "sh-tdep.h"
00031 #include "linux-tdep.h"
00032 
00033 #define REGSx16(base) \
00034   {(base),      0}, \
00035   {(base) +  1, 4}, \
00036   {(base) +  2, 8}, \
00037   {(base) +  3, 12}, \
00038   {(base) +  4, 16}, \
00039   {(base) +  5, 20}, \
00040   {(base) +  6, 24}, \
00041   {(base) +  7, 28}, \
00042   {(base) +  8, 32}, \
00043   {(base) +  9, 36}, \
00044   {(base) + 10, 40}, \
00045   {(base) + 11, 44}, \
00046   {(base) + 12, 48}, \
00047   {(base) + 13, 52}, \
00048   {(base) + 14, 56}, \
00049   {(base) + 15, 60}
00050 
00051 /* Describe the contents of the .reg section of the core file.  */
00052 
00053 static const struct sh_corefile_regmap gregs_table[] =
00054 {
00055   REGSx16 (R0_REGNUM),
00056   {PC_REGNUM,   64},
00057   {PR_REGNUM,   68},
00058   {SR_REGNUM,   72},
00059   {GBR_REGNUM,  76},
00060   {MACH_REGNUM, 80},
00061   {MACL_REGNUM, 84},
00062   {-1 /* Terminator.  */, 0}
00063 };
00064 
00065 /* Describe the contents of the .reg2 section of the core file.  */
00066 
00067 static const struct sh_corefile_regmap fpregs_table[] =
00068 {
00069   REGSx16 (FR0_REGNUM),
00070   /* REGSx16 xfp_regs omitted.  */
00071   {FPSCR_REGNUM, 128},
00072   {FPUL_REGNUM,  132},
00073   {-1 /* Terminator.  */, 0}
00074 };
00075 
00076 /* SH signal handler frame support.  */
00077 
00078 static void
00079 sh_linux_sigtramp_cache (struct frame_info *this_frame,
00080                          struct trad_frame_cache *this_cache,
00081                          CORE_ADDR func, int regs_offset)
00082 {
00083   int i;
00084   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00085   CORE_ADDR base = get_frame_register_unsigned (this_frame,
00086                                                 gdbarch_sp_regnum (gdbarch));
00087   CORE_ADDR regs = base + regs_offset;
00088 
00089   for (i = 0; i < 18; i++)
00090     trad_frame_set_reg_addr (this_cache, i, regs + i * 4);
00091 
00092   trad_frame_set_reg_addr (this_cache, SR_REGNUM, regs + 18 * 4);
00093   trad_frame_set_reg_addr (this_cache, GBR_REGNUM, regs + 19 * 4);
00094   trad_frame_set_reg_addr (this_cache, MACH_REGNUM, regs + 20 * 4);
00095   trad_frame_set_reg_addr (this_cache, MACL_REGNUM, regs + 21 * 4);
00096 
00097   /* Restore FP state if we have an FPU.  */
00098   if (gdbarch_fp0_regnum (gdbarch) != -1)
00099     {
00100       CORE_ADDR fpregs = regs + 22 * 4;
00101       for (i = FR0_REGNUM; i <= FP_LAST_REGNUM; i++)
00102         trad_frame_set_reg_addr (this_cache, i, fpregs + i * 4);
00103       trad_frame_set_reg_addr (this_cache, FPSCR_REGNUM, fpregs + 32 * 4);
00104       trad_frame_set_reg_addr (this_cache, FPUL_REGNUM, fpregs + 33 * 4);
00105     }
00106 
00107   /* Save a frame ID.  */
00108   trad_frame_set_id (this_cache, frame_id_build (base, func));
00109 }
00110 
00111 /* Implement struct tramp_frame "init" callbacks for signal
00112    trampolines on 32-bit SH.  */
00113 
00114 static void
00115 sh_linux_sigreturn_init (const struct tramp_frame *self,
00116                          struct frame_info *this_frame,
00117                          struct trad_frame_cache *this_cache,
00118                          CORE_ADDR func)
00119 {
00120   /* SH 32-bit sigframe: sigcontext at start of sigframe,
00121      registers start after a single 'oldmask' word.  */
00122   sh_linux_sigtramp_cache (this_frame, this_cache, func, 4);
00123 }
00124 
00125 static void
00126 sh_linux_rt_sigreturn_init (const struct tramp_frame *self,
00127                             struct frame_info *this_frame,
00128                             struct trad_frame_cache *this_cache,
00129                             CORE_ADDR func)
00130 {
00131   /* SH 32-bit rt_sigframe: starts with a siginfo (128 bytes), then
00132      we can find sigcontext embedded within a ucontext (offset 20 bytes).
00133      Then registers start after a single 'oldmask' word.  */
00134   sh_linux_sigtramp_cache (this_frame, this_cache, func,
00135                            128 /* sizeof (struct siginfo)  */
00136                            + 20 /* offsetof (struct ucontext, uc_mcontext) */
00137                            + 4 /* oldmask word at start of sigcontext */);
00138 }
00139 
00140 /* Instruction patterns.  */
00141 #define SH_MOVW     0x9305
00142 #define SH_TRAP     0xc300
00143 #define SH_OR_R0_R0 0x200b       
00144 
00145 /* SH sigreturn syscall numbers.  */
00146 #define SH_NR_SIGRETURN 0x0077
00147 #define SH_NR_RT_SIGRETURN 0x00ad
00148 
00149 static struct tramp_frame sh_linux_sigreturn_tramp_frame = {
00150   SIGTRAMP_FRAME,
00151   2,
00152   {
00153     { SH_MOVW, 0xffff },
00154     { SH_TRAP, 0xff00 }, /* #imm argument part filtered out.  */
00155     { SH_OR_R0_R0, 0xffff },
00156     { SH_OR_R0_R0, 0xffff },
00157     { SH_OR_R0_R0, 0xffff },
00158     { SH_OR_R0_R0, 0xffff },
00159     { SH_OR_R0_R0, 0xffff },
00160     { SH_NR_SIGRETURN, 0xffff },
00161     { TRAMP_SENTINEL_INSN }
00162   },
00163   sh_linux_sigreturn_init
00164 };
00165 
00166 static struct tramp_frame sh_linux_rt_sigreturn_tramp_frame = {
00167   SIGTRAMP_FRAME,
00168   2,
00169   {
00170     { SH_MOVW, 0xffff },
00171     { SH_TRAP, 0xff00 }, /* #imm argument part filtered out.  */
00172     { SH_OR_R0_R0, 0xffff },
00173     { SH_OR_R0_R0, 0xffff },
00174     { SH_OR_R0_R0, 0xffff },
00175     { SH_OR_R0_R0, 0xffff },
00176     { SH_OR_R0_R0, 0xffff },
00177     { SH_NR_RT_SIGRETURN, 0xffff },
00178     { TRAMP_SENTINEL_INSN }
00179   },
00180   sh_linux_rt_sigreturn_init
00181 };
00182 
00183 static void
00184 sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00185 {
00186   linux_init_abi (info, gdbarch);
00187 
00188   /* GNU/Linux uses SVR4-style shared libraries.  */
00189   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
00190   set_solib_svr4_fetch_link_map_offsets
00191     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
00192   set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
00193 
00194   set_gdbarch_fetch_tls_load_module_address (gdbarch,
00195                                              svr4_fetch_objfile_link_map);
00196 
00197   /* Core files and signal handler frame unwinding are supported for
00198      32-bit SH only, at present.  */
00199   if (info.bfd_arch_info->mach != bfd_mach_sh5)
00200     {
00201       struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00202 
00203       tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table;
00204       tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table;
00205 
00206       tramp_frame_prepend_unwinder (gdbarch, &sh_linux_sigreturn_tramp_frame);
00207       tramp_frame_prepend_unwinder (gdbarch, &sh_linux_rt_sigreturn_tramp_frame);
00208     }
00209 }
00210 
00211 /* Provide a prototype to silence -Wmissing-prototypes.  */
00212 extern void _initialize_sh_linux_tdep (void);
00213 
00214 void
00215 _initialize_sh_linux_tdep (void)
00216 {
00217   gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi);
00218 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines