GDB (API)
/home/stan/gdb/src/gdb/nios2-linux-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for GNU/Linux on Nios II.
00002    Copyright (C) 2012-2013 Free Software Foundation, Inc.
00003    Contributed by Mentor Graphics, 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 "gdb_assert.h"
00023 #include "gdb_string.h"
00024 #include "osabi.h"
00025 #include "solib-svr4.h"
00026 #include "trad-frame.h"
00027 #include "tramp-frame.h"
00028 #include "symtab.h"
00029 #include "regset.h"
00030 #include "regcache.h"
00031 #include "linux-tdep.h"
00032 #include "glibc-tdep.h"
00033 #include "nios2-tdep.h"
00034 
00035 #include "features/nios2-linux.c"
00036 
00037 /* Core file and register set support.  */
00038 
00039 /* Map from the normal register enumeration order to the order that
00040    registers appear in core files, which corresponds to the order
00041    of the register slots in the kernel's struct pt_regs.  */
00042 
00043 static const int reg_offsets[NIOS2_NUM_REGS] =
00044 {
00045   -1,  8,  9, 10, 11, 12, 13, 14,       /* r0 - r7 */
00046   0,  1,  2,  3,  4,  5,  6,  7,        /* r8 - r15 */
00047   23, 24, 25, 26, 27, 28, 29, 30,       /* r16 - r23 */
00048   -1, -1, 19, 18, 17, 21, -1, 16,       /* et bt gp sp fp ea ba ra */
00049   21,                                   /* pc */
00050   -1, 20, -1, -1, -1, -1, -1, -1,       /* status estatus ...  */
00051   -1, -1, -1, -1, -1, -1, -1, -1
00052 };
00053 
00054 /* Implement the supply_regset hook for core files.  */
00055 
00056 static void
00057 nios2_supply_gregset (const struct regset *regset,
00058                       struct regcache *regcache,
00059                       int regnum, const void *gregs_buf, size_t len)
00060 {
00061   const gdb_byte *gregs = gregs_buf;
00062   int regno;
00063   static const gdb_byte zero_buf[4] = {0, 0, 0, 0};
00064 
00065   for (regno = NIOS2_Z_REGNUM; regno <= NIOS2_MPUACC_REGNUM; regno++)
00066     if (regnum == -1 || regnum == regno)
00067       {
00068         if (reg_offsets[regno] != -1)
00069           regcache_raw_supply (regcache, regno,
00070                                gregs + 4 * reg_offsets[regno]);
00071         else
00072           regcache_raw_supply (regcache, regno, zero_buf);
00073       }
00074 }
00075 
00076 static struct regset nios2_core_regset =
00077 {
00078   NULL,
00079   nios2_supply_gregset,
00080   NULL,
00081   NULL
00082 };
00083 
00084 /* Implement the regset_from_core_section gdbarch method.  */
00085 
00086 static const struct regset *
00087 nios2_regset_from_core_section (struct gdbarch *gdbarch,
00088                                 const char *sect_name, size_t sect_size)
00089 {
00090   if (strcmp (sect_name, ".reg") == 0)
00091     return &nios2_core_regset;
00092 
00093   return NULL;
00094 }
00095 
00096 /* Initialize a trad-frame cache corresponding to the tramp-frame.
00097    FUNC is the address of the instruction TRAMP[0] in memory.  */
00098 
00099 static void
00100 nios2_linux_sigreturn_init (const struct tramp_frame *self,
00101                             struct frame_info *next_frame,
00102                             struct trad_frame_cache *this_cache,
00103                             CORE_ADDR func)
00104 {
00105   CORE_ADDR base = func + 16;
00106   int i;
00107 
00108   for (i = 0; i < 8; i++)
00109     trad_frame_set_reg_addr (this_cache, i + 8, base + i * 4);
00110   for (i = 0; i < 7; i++)
00111     trad_frame_set_reg_addr (this_cache, i + 1, base + (i + 8) * 4);
00112   trad_frame_set_reg_addr (this_cache, NIOS2_RA_REGNUM, base + 16 * 4);
00113   trad_frame_set_reg_addr (this_cache, NIOS2_FP_REGNUM, base + 17 * 4);
00114   trad_frame_set_reg_addr (this_cache, NIOS2_SP_REGNUM, base + 18 * 4);
00115   trad_frame_set_reg_addr (this_cache, NIOS2_GP_REGNUM, base + 19 * 4);
00116   trad_frame_set_reg_addr (this_cache, NIOS2_ESTATUS_REGNUM, base + 20 * 4);
00117   trad_frame_set_reg_addr (this_cache, NIOS2_PC_REGNUM, base + 21 * 4);
00118 
00119   /* Save a frame ID.  */
00120   trad_frame_set_id (this_cache, frame_id_build (base, func));
00121 }
00122 
00123 /* Initialize a trad-frame cache corresponding to the tramp-frame.
00124    FUNC is the address of the instruction TRAMP[0] in memory.  */
00125 
00126 static void
00127 nios2_linux_rt_sigreturn_init (const struct tramp_frame *self,
00128                                struct frame_info *next_frame,
00129                                struct trad_frame_cache *this_cache,
00130                                CORE_ADDR func)
00131 {
00132   CORE_ADDR base = func + 41 * 4;
00133   int i;
00134 
00135   for (i = 0; i < 23; i++)
00136     trad_frame_set_reg_addr (this_cache, i + 1, base + i * 4);
00137   trad_frame_set_reg_addr (this_cache, NIOS2_RA_REGNUM, base + 23 * 4);
00138   trad_frame_set_reg_addr (this_cache, NIOS2_FP_REGNUM, base + 24 * 4);
00139   trad_frame_set_reg_addr (this_cache, NIOS2_GP_REGNUM, base + 25 * 4);
00140   trad_frame_set_reg_addr (this_cache, NIOS2_PC_REGNUM, base + 27 * 4);
00141   trad_frame_set_reg_addr (this_cache, NIOS2_SP_REGNUM, base + 28 * 4);
00142 
00143   /* Save a frame ID.  */
00144   trad_frame_set_id (this_cache, frame_id_build (base, func));
00145 }
00146 
00147 static struct tramp_frame nios2_linux_sigreturn_tramp_frame =
00148 {
00149   SIGTRAMP_FRAME,
00150   4,
00151   {
00152     { 0x00800004 | (119 << 6), -1 },  /* movi r2,__NR_sigreturn */
00153     { 0x003b683a, -1 },               /* trap */
00154     { TRAMP_SENTINEL_INSN }
00155   },
00156   nios2_linux_sigreturn_init
00157 };
00158 
00159 static struct tramp_frame nios2_linux_rt_sigreturn_tramp_frame =
00160 {
00161   SIGTRAMP_FRAME,
00162   4,
00163   {
00164     { 0x00800004 | (173 << 6), -1 },  /* movi r2,__NR_rt_sigreturn */
00165     { 0x003b683a, -1 },               /* trap */
00166     { TRAMP_SENTINEL_INSN }
00167   },
00168   nios2_linux_rt_sigreturn_init
00169 };
00170 
00171 /* When FRAME is at a syscall instruction, return the PC of the next
00172    instruction to be executed.  */
00173 
00174 static CORE_ADDR
00175 nios2_linux_syscall_next_pc (struct frame_info *frame)
00176 {
00177   CORE_ADDR pc = get_frame_pc (frame);
00178   ULONGEST syscall_nr = get_frame_register_unsigned (frame, NIOS2_R2_REGNUM);
00179 
00180   /* If we are about to make a sigreturn syscall, use the unwinder to
00181      decode the signal frame.  */
00182   if (syscall_nr == 119 /* sigreturn */
00183       || syscall_nr == 173 /* rt_sigreturn */)
00184     return frame_unwind_caller_pc (frame);
00185 
00186   return pc + NIOS2_OPCODE_SIZE;
00187 }
00188 
00189 /* Hook function for gdbarch_register_osabi.  */
00190 
00191 static void
00192 nios2_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00193 {
00194   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00195 
00196   linux_init_abi (info, gdbarch);
00197 
00198   /* Shared library handling.  */
00199   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
00200   set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
00201 
00202   set_solib_svr4_fetch_link_map_offsets (gdbarch,
00203                                          svr4_ilp32_fetch_link_map_offsets);
00204   /* Enable TLS support.  */
00205   set_gdbarch_fetch_tls_load_module_address (gdbarch,
00206                                              svr4_fetch_objfile_link_map);
00207   /* Core file support.  */
00208   set_gdbarch_regset_from_core_section (gdbarch,
00209                                         nios2_regset_from_core_section);
00210   /* Linux signal frame unwinders.  */
00211   tramp_frame_prepend_unwinder (gdbarch,
00212                                 &nios2_linux_sigreturn_tramp_frame);
00213   tramp_frame_prepend_unwinder (gdbarch,
00214                                 &nios2_linux_rt_sigreturn_tramp_frame);
00215 
00216   tdep->syscall_next_pc = nios2_linux_syscall_next_pc;
00217 
00218   /* Index of target address word in glibc jmp_buf.  */
00219   tdep->jb_pc = 10;
00220 }
00221 
00222 /* Provide a prototype to silence -Wmissing-prototypes.  */
00223 
00224 extern initialize_file_ftype _initialize_nios2_linux_tdep;
00225 
00226 void
00227 _initialize_nios2_linux_tdep (void)
00228 {
00229   gdbarch_register_osabi (bfd_arch_nios2, 0, GDB_OSABI_LINUX,
00230                           nios2_linux_init_abi);
00231 
00232   initialize_tdesc_nios2_linux ();
00233 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines