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