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