trgt_mips.c revision 214952
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 214952 2010-11-07 20:56:41Z gonzo $"); 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#include <machine/pcb.h> 50 51#include "kgdb.h" 52 53void 54kgdb_trgt_fetch_registers(int regno __unused) 55{ 56 struct kthr *kt; 57 struct pcb pcb; 58 59 kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid)); 60 if (kt == NULL) 61 return; 62 if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) { 63 warnx("kvm_read: %s", kvm_geterr(kvm)); 64 memset(&pcb, 0, sizeof(pcb)); 65 } 66 67 supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]); 68 supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]); 69 supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]); 70 supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]); 71 supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]); 72 supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]); 73 supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]); 74 supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]); 75 supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]); 76 supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]); 77 supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]); 78 supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]); 79} 80 81void 82kgdb_trgt_store_registers(int regno __unused) 83{ 84 85 fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__); 86} 87 88void 89kgdb_trgt_new_objfile(struct objfile *objfile) 90{ 91} 92 93struct kgdb_frame_cache { 94 CORE_ADDR pc; 95 CORE_ADDR sp; 96}; 97 98static int kgdb_trgt_frame_offset[] = { 99 offsetof(struct trapframe, zero), 100 offsetof(struct trapframe, ast), 101 offsetof(struct trapframe, v0), 102 offsetof(struct trapframe, v1), 103 offsetof(struct trapframe, a0), 104 offsetof(struct trapframe, a1), 105 offsetof(struct trapframe, a2), 106 offsetof(struct trapframe, a3), 107 offsetof(struct trapframe, t0), 108 offsetof(struct trapframe, t1), 109 offsetof(struct trapframe, t2), 110 offsetof(struct trapframe, t3), 111 offsetof(struct trapframe, t4), 112 offsetof(struct trapframe, t5), 113 offsetof(struct trapframe, t6), 114 offsetof(struct trapframe, t7), 115 offsetof(struct trapframe, s0), 116 offsetof(struct trapframe, s1), 117 offsetof(struct trapframe, s2), 118 offsetof(struct trapframe, s3), 119 offsetof(struct trapframe, s4), 120 offsetof(struct trapframe, s5), 121 offsetof(struct trapframe, s6), 122 offsetof(struct trapframe, s7), 123 offsetof(struct trapframe, t8), 124 offsetof(struct trapframe, t9), 125 offsetof(struct trapframe, k0), 126 offsetof(struct trapframe, k1), 127 offsetof(struct trapframe, gp), 128 offsetof(struct trapframe, sp), 129 offsetof(struct trapframe, s8), 130 offsetof(struct trapframe, ra), 131}; 132 133static struct kgdb_frame_cache * 134kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) 135{ 136 char buf[MAX_REGISTER_SIZE]; 137 struct kgdb_frame_cache *cache; 138 139 cache = *this_cache; 140 if (cache == NULL) { 141 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); 142 *this_cache = cache; 143 cache->pc = frame_func_unwind(next_frame); 144 frame_unwind_register(next_frame, SP_REGNUM, buf); 145 cache->sp = extract_unsigned_integer(buf, 146 register_size(current_gdbarch, SP_REGNUM)); 147 } 148 return (cache); 149} 150 151static void 152kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, 153 struct frame_id *this_id) 154{ 155 struct kgdb_frame_cache *cache; 156 157 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 158 *this_id = frame_id_build(cache->sp, cache->pc); 159} 160 161static void 162kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused, 163 void **this_cache __unused, int regnum __unused, int *optimizedp __unused, 164 enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused, 165 int *realnump __unused, void *valuep __unused) 166{ 167 char dummy_valuep[MAX_REGISTER_SIZE]; 168 struct kgdb_frame_cache *cache; 169 int ofs, regsz; 170 171 regsz = register_size(current_gdbarch, regnum); 172 173 if (valuep == NULL) 174 valuep = dummy_valuep; 175 memset(valuep, 0, regsz); 176 *optimizedp = 0; 177 *addrp = 0; 178 *lvalp = not_lval; 179 *realnump = -1; 180 181 ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ? 182 kgdb_trgt_frame_offset[regnum] : -1; 183 if (ofs == -1) 184 return; 185 186 cache = kgdb_trgt_frame_cache(next_frame, this_cache); 187 *addrp = cache->sp + ofs * 8; 188 *lvalp = lval_memory; 189 target_read_memory(*addrp, valuep, regsz); 190} 191 192static const struct frame_unwind kgdb_trgt_trapframe_unwind = { 193 UNKNOWN_FRAME, 194 &kgdb_trgt_trapframe_this_id, 195 &kgdb_trgt_trapframe_prev_register 196}; 197 198const struct frame_unwind * 199kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) 200{ 201 char *pname; 202 CORE_ADDR pc; 203 204 pc = frame_pc_unwind(next_frame); 205 pname = NULL; 206 find_pc_partial_function(pc, &pname, NULL, NULL); 207 if (pname == NULL) 208 return (NULL); 209 if ((strcmp(pname, "MipsKernIntr") == 0) || 210 (strcmp(pname, "MipsKernGenException") == 0) || 211 (strcmp(pname, "MipsUserIntr") == 0) || 212 (strcmp(pname, "MipsUserGenException") == 0)) 213 return (&kgdb_trgt_trapframe_unwind); 214 return (NULL); 215} 216