GDB (API)
|
00001 /* Target-dependent code for NetBSD/mips. 00002 00003 Copyright (C) 2002-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Wasabi Systems, Inc. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "gdbcore.h" 00024 #include "regcache.h" 00025 #include "regset.h" 00026 #include "target.h" 00027 #include "value.h" 00028 #include "osabi.h" 00029 00030 #include "gdb_assert.h" 00031 #include "gdb_string.h" 00032 00033 #include "nbsd-tdep.h" 00034 #include "mipsnbsd-tdep.h" 00035 #include "mips-tdep.h" 00036 00037 #include "solib-svr4.h" 00038 00039 /* Shorthand for some register numbers used below. */ 00040 #define MIPS_PC_REGNUM MIPS_EMBED_PC_REGNUM 00041 #define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM 00042 #define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32 00043 00044 /* Core file support. */ 00045 00046 /* Number of registers in `struct reg' from <machine/reg.h>. */ 00047 #define MIPSNBSD_NUM_GREGS 38 00048 00049 /* Number of registers in `struct fpreg' from <machine/reg.h>. */ 00050 #define MIPSNBSD_NUM_FPREGS 33 00051 00052 /* Supply register REGNUM from the buffer specified by FPREGS and LEN 00053 in the floating-point register set REGSET to register cache 00054 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 00055 00056 static void 00057 mipsnbsd_supply_fpregset (const struct regset *regset, 00058 struct regcache *regcache, 00059 int regnum, const void *fpregs, size_t len) 00060 { 00061 size_t regsize = mips_isa_regsize (get_regcache_arch (regcache)); 00062 const char *regs = fpregs; 00063 int i; 00064 00065 gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize); 00066 00067 for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++) 00068 { 00069 if (regnum == i || regnum == -1) 00070 regcache_raw_supply (regcache, i, 00071 regs + (i - MIPS_FP0_REGNUM) * regsize); 00072 } 00073 } 00074 00075 /* Supply register REGNUM from the buffer specified by GREGS and LEN 00076 in the general-purpose register set REGSET to register cache 00077 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ 00078 00079 static void 00080 mipsnbsd_supply_gregset (const struct regset *regset, 00081 struct regcache *regcache, int regnum, 00082 const void *gregs, size_t len) 00083 { 00084 size_t regsize = mips_isa_regsize (get_regcache_arch (regcache)); 00085 const char *regs = gregs; 00086 int i; 00087 00088 gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize); 00089 00090 for (i = 0; i <= MIPS_PC_REGNUM; i++) 00091 { 00092 if (regnum == i || regnum == -1) 00093 regcache_raw_supply (regcache, i, regs + i * regsize); 00094 } 00095 00096 if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize) 00097 { 00098 regs += MIPSNBSD_NUM_GREGS * regsize; 00099 len -= MIPSNBSD_NUM_GREGS * regsize; 00100 mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len); 00101 } 00102 } 00103 00104 /* NetBSD/mips register sets. */ 00105 00106 static struct regset mipsnbsd_gregset = 00107 { 00108 NULL, 00109 mipsnbsd_supply_gregset 00110 }; 00111 00112 static struct regset mipsnbsd_fpregset = 00113 { 00114 NULL, 00115 mipsnbsd_supply_fpregset 00116 }; 00117 00118 /* Return the appropriate register set for the core section identified 00119 by SECT_NAME and SECT_SIZE. */ 00120 00121 static const struct regset * 00122 mipsnbsd_regset_from_core_section (struct gdbarch *gdbarch, 00123 const char *sect_name, size_t sect_size) 00124 { 00125 size_t regsize = mips_isa_regsize (gdbarch); 00126 00127 if (strcmp (sect_name, ".reg") == 0 00128 && sect_size >= MIPSNBSD_NUM_GREGS * regsize) 00129 return &mipsnbsd_gregset; 00130 00131 if (strcmp (sect_name, ".reg2") == 0 00132 && sect_size >= MIPSNBSD_NUM_FPREGS * regsize) 00133 return &mipsnbsd_fpregset; 00134 00135 return NULL; 00136 } 00137 00138 00139 /* Conveniently, GDB uses the same register numbering as the 00140 ptrace register structure used by NetBSD/mips. */ 00141 00142 void 00143 mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno) 00144 { 00145 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00146 int i; 00147 00148 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) 00149 { 00150 if (regno == i || regno == -1) 00151 { 00152 if (gdbarch_cannot_fetch_register (gdbarch, i)) 00153 regcache_raw_supply (regcache, i, NULL); 00154 else 00155 regcache_raw_supply (regcache, i, 00156 regs + (i * mips_isa_regsize (gdbarch))); 00157 } 00158 } 00159 } 00160 00161 void 00162 mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno) 00163 { 00164 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00165 int i; 00166 00167 for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) 00168 if ((regno == i || regno == -1) 00169 && ! gdbarch_cannot_store_register (gdbarch, i)) 00170 regcache_raw_collect (regcache, i, 00171 regs + (i * mips_isa_regsize (gdbarch))); 00172 } 00173 00174 void 00175 mipsnbsd_supply_fpreg (struct regcache *regcache, 00176 const char *fpregs, int regno) 00177 { 00178 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00179 int i; 00180 00181 for (i = gdbarch_fp0_regnum (gdbarch); 00182 i <= mips_regnum (gdbarch)->fp_implementation_revision; 00183 i++) 00184 { 00185 if (regno == i || regno == -1) 00186 { 00187 if (gdbarch_cannot_fetch_register (gdbarch, i)) 00188 regcache_raw_supply (regcache, i, NULL); 00189 else 00190 regcache_raw_supply (regcache, i, 00191 fpregs 00192 + ((i - gdbarch_fp0_regnum (gdbarch)) 00193 * mips_isa_regsize (gdbarch))); 00194 } 00195 } 00196 } 00197 00198 void 00199 mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno) 00200 { 00201 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00202 int i; 00203 00204 for (i = gdbarch_fp0_regnum (gdbarch); 00205 i <= mips_regnum (gdbarch)->fp_control_status; 00206 i++) 00207 if ((regno == i || regno == -1) 00208 && ! gdbarch_cannot_store_register (gdbarch, i)) 00209 regcache_raw_collect (regcache, i, 00210 fpregs + ((i - gdbarch_fp0_regnum (gdbarch)) 00211 * mips_isa_regsize (gdbarch))); 00212 } 00213 00214 /* Under NetBSD/mips, signal handler invocations can be identified by the 00215 designated code sequence that is used to return from a signal handler. 00216 In particular, the return address of a signal handler points to the 00217 following code sequence: 00218 00219 addu a0, sp, 16 00220 li v0, 295 # __sigreturn14 00221 syscall 00222 00223 Each instruction has a unique encoding, so we simply attempt to match 00224 the instruction the PC is pointing to with any of the above instructions. 00225 If there is a hit, we know the offset to the start of the designated 00226 sequence and can then check whether we really are executing in the 00227 signal trampoline. If not, -1 is returned, otherwise the offset from the 00228 start of the return sequence is returned. */ 00229 00230 #define RETCODE_NWORDS 3 00231 #define RETCODE_SIZE (RETCODE_NWORDS * 4) 00232 00233 static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] = 00234 { 00235 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */ 00236 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */ 00237 0x0c, 0x00, 0x00, 0x00, /* syscall */ 00238 }; 00239 00240 static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] = 00241 { 00242 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */ 00243 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */ 00244 0x00, 0x00, 0x00, 0x0c, /* syscall */ 00245 }; 00246 00247 /* Figure out where the longjmp will land. We expect that we have 00248 just entered longjmp and haven't yet setup the stack frame, so the 00249 args are still in the argument regs. MIPS_A0_REGNUM points at the 00250 jmp_buf structure from which we extract the PC that we will land 00251 at. The PC is copied into *pc. This routine returns true on 00252 success. */ 00253 00254 #define NBSD_MIPS_JB_PC (2 * 4) 00255 #define NBSD_MIPS_JB_ELEMENT_SIZE(gdbarch) mips_isa_regsize (gdbarch) 00256 #define NBSD_MIPS_JB_OFFSET(gdbarch) (NBSD_MIPS_JB_PC * \ 00257 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)) 00258 00259 static int 00260 mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) 00261 { 00262 struct gdbarch *gdbarch = get_frame_arch (frame); 00263 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00264 CORE_ADDR jb_addr; 00265 gdb_byte *buf; 00266 00267 buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)); 00268 00269 jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM); 00270 00271 if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf, 00272 NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))) 00273 return 0; 00274 00275 *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch), 00276 byte_order); 00277 return 1; 00278 } 00279 00280 static int 00281 mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno) 00282 { 00283 return (regno == MIPS_ZERO_REGNUM 00284 || regno == mips_regnum (gdbarch)->fp_implementation_revision); 00285 } 00286 00287 static int 00288 mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno) 00289 { 00290 return (regno == MIPS_ZERO_REGNUM 00291 || regno == mips_regnum (gdbarch)->fp_implementation_revision); 00292 } 00293 00294 /* Shared library support. */ 00295 00296 /* NetBSD/mips uses a slightly different `struct link_map' than the 00297 other NetBSD platforms. */ 00298 00299 static struct link_map_offsets * 00300 mipsnbsd_ilp32_fetch_link_map_offsets (void) 00301 { 00302 static struct link_map_offsets lmo; 00303 static struct link_map_offsets *lmp = NULL; 00304 00305 if (lmp == NULL) 00306 { 00307 lmp = &lmo; 00308 00309 lmo.r_version_offset = 0; 00310 lmo.r_version_size = 4; 00311 lmo.r_map_offset = 4; 00312 lmo.r_brk_offset = 8; 00313 lmo.r_ldsomap_offset = -1; 00314 00315 /* Everything we need is in the first 24 bytes. */ 00316 lmo.link_map_size = 24; 00317 lmo.l_addr_offset = 4; 00318 lmo.l_name_offset = 8; 00319 lmo.l_ld_offset = 12; 00320 lmo.l_next_offset = 16; 00321 lmo.l_prev_offset = 20; 00322 } 00323 00324 return lmp; 00325 } 00326 00327 static struct link_map_offsets * 00328 mipsnbsd_lp64_fetch_link_map_offsets (void) 00329 { 00330 static struct link_map_offsets lmo; 00331 static struct link_map_offsets *lmp = NULL; 00332 00333 if (lmp == NULL) 00334 { 00335 lmp = &lmo; 00336 00337 lmo.r_version_offset = 0; 00338 lmo.r_version_size = 4; 00339 lmo.r_map_offset = 8; 00340 lmo.r_brk_offset = 16; 00341 lmo.r_ldsomap_offset = -1; 00342 00343 /* Everything we need is in the first 40 bytes. */ 00344 lmo.link_map_size = 48; 00345 lmo.l_addr_offset = 0; 00346 lmo.l_name_offset = 16; 00347 lmo.l_ld_offset = 24; 00348 lmo.l_next_offset = 32; 00349 lmo.l_prev_offset = 40; 00350 } 00351 00352 return lmp; 00353 } 00354 00355 00356 static void 00357 mipsnbsd_init_abi (struct gdbarch_info info, 00358 struct gdbarch *gdbarch) 00359 { 00360 set_gdbarch_regset_from_core_section 00361 (gdbarch, mipsnbsd_regset_from_core_section); 00362 00363 set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target); 00364 00365 set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register); 00366 set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register); 00367 00368 set_gdbarch_software_single_step (gdbarch, mips_software_single_step); 00369 00370 /* NetBSD/mips has SVR4-style shared libraries. */ 00371 set_solib_svr4_fetch_link_map_offsets 00372 (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ? 00373 mipsnbsd_ilp32_fetch_link_map_offsets : 00374 mipsnbsd_lp64_fetch_link_map_offsets)); 00375 } 00376 00377 00378 /* Provide a prototype to silence -Wmissing-prototypes. */ 00379 extern initialize_file_ftype _initialize_mipsnbsd_tdep; 00380 00381 void 00382 _initialize_mipsnbsd_tdep (void) 00383 { 00384 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF, 00385 mipsnbsd_init_abi); 00386 }