trgt_mips.c revision 214952
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 214952 2010-11-07 20:56:41Z gonzo $");
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
49214952Sgonzo#include <machine/pcb.h>
50214952Sgonzo
51179161Sobrien#include "kgdb.h"
52179161Sobrien
53179161Sobrienvoid
54179161Sobrienkgdb_trgt_fetch_registers(int regno __unused)
55179161Sobrien{
56179161Sobrien	struct kthr *kt;
57179161Sobrien	struct pcb pcb;
58179161Sobrien
59179859Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
60179161Sobrien	if (kt == NULL)
61179161Sobrien		return;
62179161Sobrien	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
63179161Sobrien		warnx("kvm_read: %s", kvm_geterr(kvm));
64179161Sobrien		memset(&pcb, 0, sizeof(pcb));
65179161Sobrien	}
66214952Sgonzo
67214952Sgonzo	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
68214952Sgonzo	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
69214952Sgonzo	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
70214952Sgonzo	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
71214952Sgonzo	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
72214952Sgonzo	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
73214952Sgonzo	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
74214952Sgonzo	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
75214952Sgonzo	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
76214952Sgonzo	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
77214952Sgonzo	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
78214952Sgonzo	supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
79179161Sobrien}
80179161Sobrien
81179161Sobrienvoid
82179161Sobrienkgdb_trgt_store_registers(int regno __unused)
83179161Sobrien{
84179161Sobrien
85214952Sgonzo	fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
86179161Sobrien}
87179161Sobrien
88179859Sjhbvoid
89179859Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
90179859Sjhb{
91179859Sjhb}
92179859Sjhb
93179161Sobrienstruct kgdb_frame_cache {
94179161Sobrien	CORE_ADDR	pc;
95179161Sobrien	CORE_ADDR	sp;
96179161Sobrien};
97179161Sobrien
98179161Sobrienstatic int kgdb_trgt_frame_offset[] = {
99179161Sobrien	offsetof(struct trapframe, zero),
100179161Sobrien	offsetof(struct trapframe, ast),
101179161Sobrien	offsetof(struct trapframe, v0),
102179161Sobrien	offsetof(struct trapframe, v1),
103179161Sobrien	offsetof(struct trapframe, a0),
104179161Sobrien	offsetof(struct trapframe, a1),
105179161Sobrien	offsetof(struct trapframe, a2),
106179161Sobrien	offsetof(struct trapframe, a3),
107179161Sobrien	offsetof(struct trapframe, t0),
108179161Sobrien	offsetof(struct trapframe, t1),
109179161Sobrien	offsetof(struct trapframe, t2),
110179161Sobrien	offsetof(struct trapframe, t3),
111179161Sobrien	offsetof(struct trapframe, t4),
112179161Sobrien	offsetof(struct trapframe, t5),
113179161Sobrien	offsetof(struct trapframe, t6),
114179161Sobrien	offsetof(struct trapframe, t7),
115179161Sobrien	offsetof(struct trapframe, s0),
116179161Sobrien	offsetof(struct trapframe, s1),
117179161Sobrien	offsetof(struct trapframe, s2),
118179161Sobrien	offsetof(struct trapframe, s3),
119179161Sobrien	offsetof(struct trapframe, s4),
120179161Sobrien	offsetof(struct trapframe, s5),
121179161Sobrien	offsetof(struct trapframe, s6),
122179161Sobrien	offsetof(struct trapframe, s7),
123179161Sobrien	offsetof(struct trapframe, t8),
124179161Sobrien	offsetof(struct trapframe, t9),
125179161Sobrien	offsetof(struct trapframe, k0),
126179161Sobrien	offsetof(struct trapframe, k1),
127179161Sobrien	offsetof(struct trapframe, gp),
128179161Sobrien	offsetof(struct trapframe, sp),
129179161Sobrien	offsetof(struct trapframe, s8),
130179161Sobrien	offsetof(struct trapframe, ra),
131179161Sobrien};
132179161Sobrien
133179161Sobrienstatic struct kgdb_frame_cache *
134214952Sgonzokgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
135179161Sobrien{
136179161Sobrien	char buf[MAX_REGISTER_SIZE];
137179161Sobrien	struct kgdb_frame_cache *cache;
138179161Sobrien
139179161Sobrien	cache = *this_cache;
140179161Sobrien	if (cache == NULL) {
141179161Sobrien		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
142179161Sobrien		*this_cache = cache;
143179161Sobrien		cache->pc = frame_func_unwind(next_frame);
144179161Sobrien		frame_unwind_register(next_frame, SP_REGNUM, buf);
145179161Sobrien		cache->sp = extract_unsigned_integer(buf,
146179161Sobrien		    register_size(current_gdbarch, SP_REGNUM));
147179161Sobrien	}
148179161Sobrien	return (cache);
149179161Sobrien}
150179161Sobrien
151179161Sobrienstatic void
152179161Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
153179161Sobrien    struct frame_id *this_id)
154179161Sobrien{
155179161Sobrien	struct kgdb_frame_cache *cache;
156179161Sobrien
157179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
158179161Sobrien	*this_id = frame_id_build(cache->sp, cache->pc);
159179161Sobrien}
160179161Sobrien
161179161Sobrienstatic void
162179161Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
163179161Sobrien    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
164179161Sobrien    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
165179161Sobrien    int *realnump __unused, void *valuep __unused)
166179161Sobrien{
167179161Sobrien	char dummy_valuep[MAX_REGISTER_SIZE];
168179161Sobrien	struct kgdb_frame_cache *cache;
169179161Sobrien	int ofs, regsz;
170179161Sobrien
171179161Sobrien	regsz = register_size(current_gdbarch, regnum);
172179161Sobrien
173179161Sobrien	if (valuep == NULL)
174179161Sobrien		valuep = dummy_valuep;
175179161Sobrien	memset(valuep, 0, regsz);
176179161Sobrien	*optimizedp = 0;
177179161Sobrien	*addrp = 0;
178179161Sobrien	*lvalp = not_lval;
179179161Sobrien	*realnump = -1;
180179161Sobrien
181179161Sobrien	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
182179161Sobrien	    kgdb_trgt_frame_offset[regnum] : -1;
183179161Sobrien	if (ofs == -1)
184179161Sobrien		return;
185179161Sobrien
186179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
187179161Sobrien	*addrp = cache->sp + ofs * 8;
188179161Sobrien	*lvalp = lval_memory;
189179161Sobrien	target_read_memory(*addrp, valuep, regsz);
190179161Sobrien}
191179161Sobrien
192179161Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
193179161Sobrien	UNKNOWN_FRAME,
194179161Sobrien	&kgdb_trgt_trapframe_this_id,
195179161Sobrien	&kgdb_trgt_trapframe_prev_register
196179161Sobrien};
197179161Sobrien
198179161Sobrienconst struct frame_unwind *
199214952Sgonzokgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
200179161Sobrien{
201179161Sobrien	char *pname;
202179161Sobrien	CORE_ADDR pc;
203179161Sobrien
204179161Sobrien	pc = frame_pc_unwind(next_frame);
205179161Sobrien	pname = NULL;
206179161Sobrien	find_pc_partial_function(pc, &pname, NULL, NULL);
207179161Sobrien	if (pname == NULL)
208179161Sobrien		return (NULL);
209179161Sobrien	if ((strcmp(pname, "MipsKernIntr") == 0) ||
210179161Sobrien	    (strcmp(pname, "MipsKernGenException") == 0) ||
211179161Sobrien	    (strcmp(pname, "MipsUserIntr") == 0) ||
212179161Sobrien	    (strcmp(pname, "MipsUserGenException") == 0))
213179161Sobrien		return (&kgdb_trgt_trapframe_unwind);
214179161Sobrien	return (NULL);
215179161Sobrien}
216