trgt_mips.c revision 179162
1179161Sobrien/*
2179162Sobrien * Copyright (c) 2007 Juniper Networks, Inc.
3179161Sobrien * Copyright (c) 2004 Marcel Moolenaar
4179161Sobrien * All rights reserved.
5179161Sobrien *
6179161Sobrien * Redistribution and use in source and binary forms, with or without
7179161Sobrien * modification, are permitted provided that the following conditions
8179161Sobrien * are met:
9179161Sobrien *
10179161Sobrien * 1. Redistributions of source code must retain the above copyright
11179161Sobrien *    notice, this list of conditions and the following disclaimer.
12179161Sobrien * 2. Redistributions in binary form must reproduce the above copyright
13179161Sobrien *    notice, this list of conditions and the following disclaimer in the
14179161Sobrien *    documentation and/or other materials provided with the distribution.
15179161Sobrien *
16179161Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17179161Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18179161Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19179161Sobrien * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20179161Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21179161Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22179161Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23179161Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24179161Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25179161Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26179161Sobrien *
27179161Sobrien * from: src/gnu/usr.bin/gdb/kgdb/trgt_alpha.c,v 1.2.2.1 2005/09/15 05:32:10 marcel
28179161Sobrien */
29179161Sobrien
30179161Sobrien#include <sys/cdefs.h>
31179161Sobrien__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/kgdb/trgt_mips.c 179162 2008-05-20 22:58:47Z obrien $");
32179161Sobrien
33179161Sobrien#include <sys/types.h>
34179161Sobrien#include <machine/asm.h>
35179161Sobrien#include <machine/pcb.h>
36179161Sobrien#include <machine/frame.h>
37179161Sobrien#include <err.h>
38179161Sobrien#include <kvm.h>
39179161Sobrien#include <string.h>
40179161Sobrien
41179161Sobrien#include <defs.h>
42179161Sobrien#include <target.h>
43179161Sobrien#include <gdbthread.h>
44179161Sobrien#include <inferior.h>
45179161Sobrien#include <regcache.h>
46179161Sobrien#include <frame-unwind.h>
47179161Sobrien#include <mips-tdep.h>
48179161Sobrien
49179161Sobrien#include "kgdb.h"
50179161Sobrien
51179161Sobrienvoid
52179161Sobrienkgdb_trgt_fetch_registers(int regno __unused)
53179161Sobrien{
54179161Sobrien	struct kthr *kt;
55179161Sobrien	struct pcb pcb;
56179161Sobrien
57179161Sobrien	kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid));
58179161Sobrien	if (kt == NULL)
59179161Sobrien		return;
60179161Sobrien	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
61179161Sobrien		warnx("kvm_read: %s", kvm_geterr(kvm));
62179161Sobrien		memset(&pcb, 0, sizeof(pcb));
63179161Sobrien	}
64179161Sobrien	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context.val[0]);
65179161Sobrien	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context.val[1]);
66179161Sobrien	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context.val[2]);
67179161Sobrien	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context.val[3]);
68179161Sobrien	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context.val[4]);
69179161Sobrien	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context.val[5]);
70179161Sobrien	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context.val[6]);
71179161Sobrien	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context.val[7]);
72179161Sobrien	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context.val[8]);
73179161Sobrien	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context.val[8]);
74179161Sobrien	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context.val[9]);
75179161Sobrien	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context.val[10]);
76179161Sobrien}
77179161Sobrien
78179161Sobrienvoid
79179161Sobrienkgdb_trgt_store_registers(int regno __unused)
80179161Sobrien{
81179161Sobrien
82179161Sobrien	fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
83179161Sobrien}
84179161Sobrien
85179161Sobrienstruct kgdb_frame_cache {
86179161Sobrien	CORE_ADDR	pc;
87179161Sobrien	CORE_ADDR	sp;
88179161Sobrien};
89179161Sobrien
90179161Sobrienstatic int kgdb_trgt_frame_offset[] = {
91179161Sobrien	offsetof(struct trapframe, zero),
92179161Sobrien	offsetof(struct trapframe, ast),
93179161Sobrien	offsetof(struct trapframe, v0),
94179161Sobrien	offsetof(struct trapframe, v1),
95179161Sobrien	offsetof(struct trapframe, a0),
96179161Sobrien	offsetof(struct trapframe, a1),
97179161Sobrien	offsetof(struct trapframe, a2),
98179161Sobrien	offsetof(struct trapframe, a3),
99179161Sobrien	offsetof(struct trapframe, t0),
100179161Sobrien	offsetof(struct trapframe, t1),
101179161Sobrien	offsetof(struct trapframe, t2),
102179161Sobrien	offsetof(struct trapframe, t3),
103179161Sobrien	offsetof(struct trapframe, t4),
104179161Sobrien	offsetof(struct trapframe, t5),
105179161Sobrien	offsetof(struct trapframe, t6),
106179161Sobrien	offsetof(struct trapframe, t7),
107179161Sobrien	offsetof(struct trapframe, s0),
108179161Sobrien	offsetof(struct trapframe, s1),
109179161Sobrien	offsetof(struct trapframe, s2),
110179161Sobrien	offsetof(struct trapframe, s3),
111179161Sobrien	offsetof(struct trapframe, s4),
112179161Sobrien	offsetof(struct trapframe, s5),
113179161Sobrien	offsetof(struct trapframe, s6),
114179161Sobrien	offsetof(struct trapframe, s7),
115179161Sobrien	offsetof(struct trapframe, t8),
116179161Sobrien	offsetof(struct trapframe, t9),
117179161Sobrien	offsetof(struct trapframe, k0),
118179161Sobrien	offsetof(struct trapframe, k1),
119179161Sobrien	offsetof(struct trapframe, gp),
120179161Sobrien	offsetof(struct trapframe, sp),
121179161Sobrien	offsetof(struct trapframe, s8),
122179161Sobrien	offsetof(struct trapframe, ra),
123179161Sobrien};
124179161Sobrien
125179161Sobrienstatic struct kgdb_frame_cache *
126179161Sobrienkgdb_trgt_frame_cache(struct frame_info *next_frame __unused, void **this_cache __unused)
127179161Sobrien{
128179161Sobrien	char buf[MAX_REGISTER_SIZE];
129179161Sobrien	struct kgdb_frame_cache *cache;
130179161Sobrien
131179161Sobrien	cache = *this_cache;
132179161Sobrien	if (cache == NULL) {
133179161Sobrien		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
134179161Sobrien		*this_cache = cache;
135179161Sobrien		cache->pc = frame_func_unwind(next_frame);
136179161Sobrien		frame_unwind_register(next_frame, SP_REGNUM, buf);
137179161Sobrien		cache->sp = extract_unsigned_integer(buf,
138179161Sobrien		    register_size(current_gdbarch, SP_REGNUM));
139179161Sobrien	}
140179161Sobrien	return (cache);
141179161Sobrien}
142179161Sobrien
143179161Sobrienstatic void
144179161Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
145179161Sobrien    struct frame_id *this_id)
146179161Sobrien{
147179161Sobrien	struct kgdb_frame_cache *cache;
148179161Sobrien
149179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
150179161Sobrien	*this_id = frame_id_build(cache->sp, cache->pc);
151179161Sobrien}
152179161Sobrien
153179161Sobrienstatic void
154179161Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
155179161Sobrien    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
156179161Sobrien    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
157179161Sobrien    int *realnump __unused, void *valuep __unused)
158179161Sobrien{
159179161Sobrien	char dummy_valuep[MAX_REGISTER_SIZE];
160179161Sobrien	struct kgdb_frame_cache *cache;
161179161Sobrien	int ofs, regsz;
162179161Sobrien
163179161Sobrien	regsz = register_size(current_gdbarch, regnum);
164179161Sobrien
165179161Sobrien	if (valuep == NULL)
166179161Sobrien		valuep = dummy_valuep;
167179161Sobrien	memset(valuep, 0, regsz);
168179161Sobrien	*optimizedp = 0;
169179161Sobrien	*addrp = 0;
170179161Sobrien	*lvalp = not_lval;
171179161Sobrien	*realnump = -1;
172179161Sobrien
173179161Sobrien	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
174179161Sobrien	    kgdb_trgt_frame_offset[regnum] : -1;
175179161Sobrien	if (ofs == -1)
176179161Sobrien		return;
177179161Sobrien
178179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
179179161Sobrien	*addrp = cache->sp + ofs * 8;
180179161Sobrien	*lvalp = lval_memory;
181179161Sobrien	target_read_memory(*addrp, valuep, regsz);
182179161Sobrien}
183179161Sobrien
184179161Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
185179161Sobrien	UNKNOWN_FRAME,
186179161Sobrien	&kgdb_trgt_trapframe_this_id,
187179161Sobrien	&kgdb_trgt_trapframe_prev_register
188179161Sobrien};
189179161Sobrien
190179161Sobrienconst struct frame_unwind *
191179161Sobrienkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame __unused)
192179161Sobrien{
193179161Sobrien	char *pname;
194179161Sobrien	CORE_ADDR pc;
195179161Sobrien
196179161Sobrien	pc = frame_pc_unwind(next_frame);
197179161Sobrien	pname = NULL;
198179161Sobrien	find_pc_partial_function(pc, &pname, NULL, NULL);
199179161Sobrien	if (pname == NULL)
200179161Sobrien		return (NULL);
201179161Sobrien	if ((strcmp(pname, "MipsKernIntr") == 0) ||
202179161Sobrien	    (strcmp(pname, "MipsKernGenException") == 0) ||
203179161Sobrien	    (strcmp(pname, "MipsUserIntr") == 0) ||
204179161Sobrien	    (strcmp(pname, "MipsUserGenException") == 0))
205179161Sobrien		return (&kgdb_trgt_trapframe_unwind);
206179161Sobrien	/* printf("%s: %llx =%s\n", __func__, pc, pname); */
207179161Sobrien	return (NULL);
208179161Sobrien}
209