trgt_mips.c revision 179859
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 179859 2008-06-18 14:23:28Z jhb $");
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
57179859Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(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
85179859Sjhbvoid
86179859Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
87179859Sjhb{
88179859Sjhb}
89179859Sjhb
90179161Sobrienstruct kgdb_frame_cache {
91179161Sobrien	CORE_ADDR	pc;
92179161Sobrien	CORE_ADDR	sp;
93179161Sobrien};
94179161Sobrien
95179161Sobrienstatic int kgdb_trgt_frame_offset[] = {
96179161Sobrien	offsetof(struct trapframe, zero),
97179161Sobrien	offsetof(struct trapframe, ast),
98179161Sobrien	offsetof(struct trapframe, v0),
99179161Sobrien	offsetof(struct trapframe, v1),
100179161Sobrien	offsetof(struct trapframe, a0),
101179161Sobrien	offsetof(struct trapframe, a1),
102179161Sobrien	offsetof(struct trapframe, a2),
103179161Sobrien	offsetof(struct trapframe, a3),
104179161Sobrien	offsetof(struct trapframe, t0),
105179161Sobrien	offsetof(struct trapframe, t1),
106179161Sobrien	offsetof(struct trapframe, t2),
107179161Sobrien	offsetof(struct trapframe, t3),
108179161Sobrien	offsetof(struct trapframe, t4),
109179161Sobrien	offsetof(struct trapframe, t5),
110179161Sobrien	offsetof(struct trapframe, t6),
111179161Sobrien	offsetof(struct trapframe, t7),
112179161Sobrien	offsetof(struct trapframe, s0),
113179161Sobrien	offsetof(struct trapframe, s1),
114179161Sobrien	offsetof(struct trapframe, s2),
115179161Sobrien	offsetof(struct trapframe, s3),
116179161Sobrien	offsetof(struct trapframe, s4),
117179161Sobrien	offsetof(struct trapframe, s5),
118179161Sobrien	offsetof(struct trapframe, s6),
119179161Sobrien	offsetof(struct trapframe, s7),
120179161Sobrien	offsetof(struct trapframe, t8),
121179161Sobrien	offsetof(struct trapframe, t9),
122179161Sobrien	offsetof(struct trapframe, k0),
123179161Sobrien	offsetof(struct trapframe, k1),
124179161Sobrien	offsetof(struct trapframe, gp),
125179161Sobrien	offsetof(struct trapframe, sp),
126179161Sobrien	offsetof(struct trapframe, s8),
127179161Sobrien	offsetof(struct trapframe, ra),
128179161Sobrien};
129179161Sobrien
130179161Sobrienstatic struct kgdb_frame_cache *
131179161Sobrienkgdb_trgt_frame_cache(struct frame_info *next_frame __unused, void **this_cache __unused)
132179161Sobrien{
133179161Sobrien	char buf[MAX_REGISTER_SIZE];
134179161Sobrien	struct kgdb_frame_cache *cache;
135179161Sobrien
136179161Sobrien	cache = *this_cache;
137179161Sobrien	if (cache == NULL) {
138179161Sobrien		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
139179161Sobrien		*this_cache = cache;
140179161Sobrien		cache->pc = frame_func_unwind(next_frame);
141179161Sobrien		frame_unwind_register(next_frame, SP_REGNUM, buf);
142179161Sobrien		cache->sp = extract_unsigned_integer(buf,
143179161Sobrien		    register_size(current_gdbarch, SP_REGNUM));
144179161Sobrien	}
145179161Sobrien	return (cache);
146179161Sobrien}
147179161Sobrien
148179161Sobrienstatic void
149179161Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
150179161Sobrien    struct frame_id *this_id)
151179161Sobrien{
152179161Sobrien	struct kgdb_frame_cache *cache;
153179161Sobrien
154179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
155179161Sobrien	*this_id = frame_id_build(cache->sp, cache->pc);
156179161Sobrien}
157179161Sobrien
158179161Sobrienstatic void
159179161Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
160179161Sobrien    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
161179161Sobrien    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
162179161Sobrien    int *realnump __unused, void *valuep __unused)
163179161Sobrien{
164179161Sobrien	char dummy_valuep[MAX_REGISTER_SIZE];
165179161Sobrien	struct kgdb_frame_cache *cache;
166179161Sobrien	int ofs, regsz;
167179161Sobrien
168179161Sobrien	regsz = register_size(current_gdbarch, regnum);
169179161Sobrien
170179161Sobrien	if (valuep == NULL)
171179161Sobrien		valuep = dummy_valuep;
172179161Sobrien	memset(valuep, 0, regsz);
173179161Sobrien	*optimizedp = 0;
174179161Sobrien	*addrp = 0;
175179161Sobrien	*lvalp = not_lval;
176179161Sobrien	*realnump = -1;
177179161Sobrien
178179161Sobrien	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
179179161Sobrien	    kgdb_trgt_frame_offset[regnum] : -1;
180179161Sobrien	if (ofs == -1)
181179161Sobrien		return;
182179161Sobrien
183179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
184179161Sobrien	*addrp = cache->sp + ofs * 8;
185179161Sobrien	*lvalp = lval_memory;
186179161Sobrien	target_read_memory(*addrp, valuep, regsz);
187179161Sobrien}
188179161Sobrien
189179161Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
190179161Sobrien	UNKNOWN_FRAME,
191179161Sobrien	&kgdb_trgt_trapframe_this_id,
192179161Sobrien	&kgdb_trgt_trapframe_prev_register
193179161Sobrien};
194179161Sobrien
195179161Sobrienconst struct frame_unwind *
196179161Sobrienkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame __unused)
197179161Sobrien{
198179161Sobrien	char *pname;
199179161Sobrien	CORE_ADDR pc;
200179161Sobrien
201179161Sobrien	pc = frame_pc_unwind(next_frame);
202179161Sobrien	pname = NULL;
203179161Sobrien	find_pc_partial_function(pc, &pname, NULL, NULL);
204179161Sobrien	if (pname == NULL)
205179161Sobrien		return (NULL);
206179161Sobrien	if ((strcmp(pname, "MipsKernIntr") == 0) ||
207179161Sobrien	    (strcmp(pname, "MipsKernGenException") == 0) ||
208179161Sobrien	    (strcmp(pname, "MipsUserIntr") == 0) ||
209179161Sobrien	    (strcmp(pname, "MipsUserGenException") == 0))
210179161Sobrien		return (&kgdb_trgt_trapframe_unwind);
211179161Sobrien	/* printf("%s: %llx =%s\n", __func__, pc, pname); */
212179161Sobrien	return (NULL);
213179161Sobrien}
214