GDB (API)
|
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 }