trgt_mips.c revision 249878
1/* 2 * Copyright (c) 2007 Juniper Networks, Inc. 3 * Copyright (c) 2004 Marcel Moolenaar 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * from: src/gnu/usr.bin/gdb/kgdb/trgt_alpha.c,v 1.2.2.1 2005/09/15 05:32:10 marcel 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/kgdb/trgt_mips.c 249878 2013-04-25 04:53:01Z imp $"); 32 33#include <sys/types.h> 34#include <machine/asm.h> 35#include <machine/pcb.h> 36#include <machine/frame.h> 37#include <err.h> 38#include <kvm.h> 39#include <string.h> 40 41#include <defs.h> 42#include <target.h> 43#include <gdbthread.h> 44#include <inferior.h> 45#include <regcache.h> 46#include <frame-unwind.h> 47#include <mips-tdep.h> 48 49#ifndef CROSS_DEBUGGER 50#include <machine/pcb.h> 51#endif 52 53#include "kgdb.h" 54 55CORE_ADDR 56kgdb_trgt_core_pcb(u_int cpuid) 57{ 58 return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); 59} 60 61void 62kgdb_trgt_fetch_registers(int regno __unused) 63{ 64#ifndef CROSS_DEBUGGER 65 struct kthr *kt; 66 struct pcb pcb; 67 68 kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 69 if (kt == NULL) 70 return; 71 if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 72 warnx("kvm_read: %s", kvm_geterr(kvm)); 73 memset(&pcb, 0, sizeof(pcb)); 74 } 75 76 supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]); 77 supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]); 78 supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]); 79 supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]); 80 supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]); 81 supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]); 82 supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]); 83 supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]); 84 supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]); 85 supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]); 86 supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]); 87 supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]); 88#endif 89} 90 91void 92kgdb_trgt_store_registers(int regno __unused) 93{ 94 95 fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__); 96} 97 98void 99kgdb_trgt_new_objfile(struct objfile *objfile) 100{ 101} 102 103#ifndef CROSS_DEBUGGER 104struct kgdb_frame_cache { 105 CORE_ADDR pc; 106 CORE_ADDR sp; 107}; 108 109static int kgdb_trgt_frame_offset[] = { 110 offsetof(struct trapframe, zero), 111 offsetof(struct trapframe, ast), 112 offsetof(struct trapframe, v0), 113 offsetof(struct trapframe, v1), 114 offsetof(struct trapframe, a0), 115 offsetof(struct trapframe, a1), 116 offsetof(struct trapframe, a2), 117 offsetof(struct trapframe, a3), 118#if defined(__mips_n32) || defined(__mips_n64) 119 offsetof(struct trapframe, a4), 120 offsetof(struct trapframe, a5), 121 offsetof(struct trapframe, a6), 122 offsetof(struct trapframe, a7), 123 offsetof(struct trapframe, t0), 124 offsetof(struct trapframe, t1), 125 offsetof(struct trapframe, t2), 126 offsetof(struct trapframe, t3), 127#else 128 offsetof(struct trapframe, t0), 129 offsetof(struct trapframe, t1), 130 offsetof(struct trapframe, t2), 131 offsetof(struct trapframe, t3), 132 offsetof(struct trapframe, t4), 133 offsetof(struct trapframe, t5), 134 offsetof(struct trapframe, t6), 135 offsetof(struct trapframe, t7), 136#endif 137 offsetof(struct trapframe, s0), 138 offsetof(struct trapframe, s1), 139 offsetof(struct trapframe, s2), 140 offsetof(struct trapframe, s3), 141 offsetof(struct trapframe, s4), 142 offsetof(struct trapframe, s5), 143 offsetof(struct trapframe, s6), 144 offsetof(struct trapframe, s7), 145 offsetof(struct trapframe, t8), 146 offsetof(struct trapframe, t9), 147 offsetof(struct trapframe, k0), 148 offsetof(struct trapframe, k1), 149 offsetof(struct trapframe, gp), 150 offsetof(struct trapframe, sp), 151 offsetof(struct trapframe, s8), 152 offsetof(struct trapframe, ra), 153}; 154 155static struct kgdb_frame_cache * 156kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 157{ 158 char buf[MAX_REGISTER_SIZE]; 159 struct kgdb_frame_cache *cache; 160 161 cache = *this_cache; 162 if (cache == NULL) { 163 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 164 *this_cache = cache; 165 cache->pc = frame_func_unwind(next_frame); 166 frame_unwind_register(next_frame, SP_REGNUM, buf); 167 cache->sp = extract_unsigned_integer(buf, 168 register_size(current_gdbarch, SP_REGNUM)); 169 } 170 return (cache); 171} 172 173static void 174kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 175 struct frame_id *this_id) 176{ 177 struct kgdb_frame_cache *cache; 178 179 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 180 *this_id = frame_id_build(cache->sp, cache->pc); 181} 182 183static void 184kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused, 185 void **this_cache __unused, int regnum __unused, int *optimizedp __unused, 186 enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused, 187 int *realnump __unused, void *valuep __unused) 188{ 189 char dummy_valuep[MAX_REGISTER_SIZE]; 190 struct kgdb_frame_cache *cache; 191 int ofs, regsz; 192 193 regsz = register_size(current_gdbarch, regnum); 194 195 if (valuep == NULL) 196 valuep = dummy_valuep; 197 memset(valuep, 0, regsz); 198 *optimizedp = 0; 199 *addrp = 0; 200 *lvalp = not_lval; 201 *realnump = -1; 202 203 ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ? 204 kgdb_trgt_frame_offset[regnum] : -1; 205 if (ofs == -1) 206 return; 207 208 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 209 *addrp = cache->sp + ofs * 8; 210 *lvalp = lval_memory; 211 target_read_memory(*addrp, valuep, regsz); 212} 213 214static const struct frame_unwind kgdb_trgt_trapframe_unwind = { 215 UNKNOWN_FRAME, 216 &kgdb_trgt_trapframe_this_id, 217 &kgdb_trgt_trapframe_prev_register 218}; 219#endif 220 221const struct frame_unwind * 222kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 223{ 224#ifndef CROSS_DEBUGGER 225 char *pname; 226 CORE_ADDR pc; 227 228 pc = frame_pc_unwind(next_frame); 229 pname = NULL; 230 find_pc_partial_function(pc, &pname, NULL, NULL); 231 if (pname == NULL) 232 return (NULL); 233 if ((strcmp(pname, "MipsKernIntr") == 0) || 234 (strcmp(pname, "MipsKernGenException") == 0) || 235 (strcmp(pname, "MipsUserIntr") == 0) || 236 (strcmp(pname, "MipsUserGenException") == 0)) 237 return (&kgdb_trgt_trapframe_unwind); 238#endif 239 return (NULL); 240} 241