trgt_mips.c revision 214952
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 214952 2010-11-07 20:56:41Z gonzo $");
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#include <machine/pcb.h>
50
51#include "kgdb.h"
52
53void
54kgdb_trgt_fetch_registers(int regno __unused)
55{
56	struct kthr *kt;
57	struct pcb pcb;
58
59	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
60	if (kt == NULL)
61		return;
62	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
63		warnx("kvm_read: %s", kvm_geterr(kvm));
64		memset(&pcb, 0, sizeof(pcb));
65	}
66
67	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
68	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
69	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
70	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
71	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
72	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
73	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
74	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
75	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
76	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
77	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
78	supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
79}
80
81void
82kgdb_trgt_store_registers(int regno __unused)
83{
84
85	fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
86}
87
88void
89kgdb_trgt_new_objfile(struct objfile *objfile)
90{
91}
92
93struct kgdb_frame_cache {
94	CORE_ADDR	pc;
95	CORE_ADDR	sp;
96};
97
98static int kgdb_trgt_frame_offset[] = {
99	offsetof(struct trapframe, zero),
100	offsetof(struct trapframe, ast),
101	offsetof(struct trapframe, v0),
102	offsetof(struct trapframe, v1),
103	offsetof(struct trapframe, a0),
104	offsetof(struct trapframe, a1),
105	offsetof(struct trapframe, a2),
106	offsetof(struct trapframe, a3),
107	offsetof(struct trapframe, t0),
108	offsetof(struct trapframe, t1),
109	offsetof(struct trapframe, t2),
110	offsetof(struct trapframe, t3),
111	offsetof(struct trapframe, t4),
112	offsetof(struct trapframe, t5),
113	offsetof(struct trapframe, t6),
114	offsetof(struct trapframe, t7),
115	offsetof(struct trapframe, s0),
116	offsetof(struct trapframe, s1),
117	offsetof(struct trapframe, s2),
118	offsetof(struct trapframe, s3),
119	offsetof(struct trapframe, s4),
120	offsetof(struct trapframe, s5),
121	offsetof(struct trapframe, s6),
122	offsetof(struct trapframe, s7),
123	offsetof(struct trapframe, t8),
124	offsetof(struct trapframe, t9),
125	offsetof(struct trapframe, k0),
126	offsetof(struct trapframe, k1),
127	offsetof(struct trapframe, gp),
128	offsetof(struct trapframe, sp),
129	offsetof(struct trapframe, s8),
130	offsetof(struct trapframe, ra),
131};
132
133static struct kgdb_frame_cache *
134kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
135{
136	char buf[MAX_REGISTER_SIZE];
137	struct kgdb_frame_cache *cache;
138
139	cache = *this_cache;
140	if (cache == NULL) {
141		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
142		*this_cache = cache;
143		cache->pc = frame_func_unwind(next_frame);
144		frame_unwind_register(next_frame, SP_REGNUM, buf);
145		cache->sp = extract_unsigned_integer(buf,
146		    register_size(current_gdbarch, SP_REGNUM));
147	}
148	return (cache);
149}
150
151static void
152kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
153    struct frame_id *this_id)
154{
155	struct kgdb_frame_cache *cache;
156
157	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
158	*this_id = frame_id_build(cache->sp, cache->pc);
159}
160
161static void
162kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
163    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
164    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
165    int *realnump __unused, void *valuep __unused)
166{
167	char dummy_valuep[MAX_REGISTER_SIZE];
168	struct kgdb_frame_cache *cache;
169	int ofs, regsz;
170
171	regsz = register_size(current_gdbarch, regnum);
172
173	if (valuep == NULL)
174		valuep = dummy_valuep;
175	memset(valuep, 0, regsz);
176	*optimizedp = 0;
177	*addrp = 0;
178	*lvalp = not_lval;
179	*realnump = -1;
180
181	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
182	    kgdb_trgt_frame_offset[regnum] : -1;
183	if (ofs == -1)
184		return;
185
186	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
187	*addrp = cache->sp + ofs * 8;
188	*lvalp = lval_memory;
189	target_read_memory(*addrp, valuep, regsz);
190}
191
192static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
193	UNKNOWN_FRAME,
194	&kgdb_trgt_trapframe_this_id,
195	&kgdb_trgt_trapframe_prev_register
196};
197
198const struct frame_unwind *
199kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
200{
201	char *pname;
202	CORE_ADDR pc;
203
204	pc = frame_pc_unwind(next_frame);
205	pname = NULL;
206	find_pc_partial_function(pc, &pname, NULL, NULL);
207	if (pname == NULL)
208		return (NULL);
209	if ((strcmp(pname, "MipsKernIntr") == 0) ||
210	    (strcmp(pname, "MipsKernGenException") == 0) ||
211	    (strcmp(pname, "MipsUserIntr") == 0) ||
212	    (strcmp(pname, "MipsUserGenException") == 0))
213		return (&kgdb_trgt_trapframe_unwind);
214	return (NULL);
215}
216