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