1156772Sdeischen/*
2156772Sdeischen * Copyright (c) 2007 Juniper Networks, Inc.
3156772Sdeischen * Copyright (c) 2004 Marcel Moolenaar
4156772Sdeischen * All rights reserved.
5156772Sdeischen *
6156772Sdeischen * Redistribution and use in source and binary forms, with or without
7156772Sdeischen * modification, are permitted provided that the following conditions
8156772Sdeischen * are met:
9156772Sdeischen *
10156772Sdeischen * 1. Redistributions of source code must retain the above copyright
11156772Sdeischen *    notice, this list of conditions and the following disclaimer.
12156772Sdeischen * 2. Redistributions in binary form must reproduce the above copyright
13156772Sdeischen *    notice, this list of conditions and the following disclaimer in the
14156772Sdeischen *    documentation and/or other materials provided with the distribution.
15156772Sdeischen *
16156772Sdeischen * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17156772Sdeischen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18156772Sdeischen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19156772Sdeischen * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20156772Sdeischen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21156772Sdeischen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22156772Sdeischen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23156772Sdeischen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24156772Sdeischen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25156772Sdeischen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26156772Sdeischen *
27156772Sdeischen * from: src/gnu/usr.bin/gdb/kgdb/trgt_alpha.c,v 1.2.2.1 2005/09/15 05:32:10 marcel
28156772Sdeischen */
29156772Sdeischen
30156772Sdeischen#include <sys/cdefs.h>
31156772Sdeischen__FBSDID("$FreeBSD: releng/11.0/gnu/usr.bin/gdb/kgdb/trgt_mips.c 298363 2016-04-20 20:22:48Z wma $");
32156772Sdeischen
33156772Sdeischen#include <sys/types.h>
34156772Sdeischen#include <machine/asm.h>
35156772Sdeischen#include <machine/pcb.h>
36156772Sdeischen#include <machine/frame.h>
37172729Syar#include <err.h>
38172729Syar#include <kvm.h>
39156772Sdeischen#include <string.h>
40156772Sdeischen
41156772Sdeischen#include <defs.h>
42156772Sdeischen#include <target.h>
43156772Sdeischen#include <gdbthread.h>
44156772Sdeischen#include <inferior.h>
45156772Sdeischen#include <regcache.h>
46156772Sdeischen#include <frame-unwind.h>
47156772Sdeischen#include <mips-tdep.h>
48156772Sdeischen
49156772Sdeischen#ifndef	CROSS_DEBUGGER
50172729Syar#include <machine/pcb.h>
51172729Syar#endif
52172729Syar
53156772Sdeischen#include "kgdb.h"
54172729Syar
55172729SyarCORE_ADDR
56172729Syarkgdb_trgt_core_pcb(u_int cpuid)
57156772Sdeischen{
58156772Sdeischen	return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
59156772Sdeischen}
60156772Sdeischen
61168963Sdeischenvoid
62156772Sdeischenkgdb_trgt_fetch_registers(int regno __unused)
63156772Sdeischen{
64172729Syar#ifndef	CROSS_DEBUGGER
65172729Syar	struct kthr *kt;
66172729Syar	struct pcb pcb;
67172729Syar
68156772Sdeischen	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
69172729Syar	if (kt == NULL)
70172729Syar		return;
71172729Syar	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
72172729Syar		warnx("kvm_read: %s", kvm_geterr(kvm));
73172729Syar		memset(&pcb, 0, sizeof(pcb));
74172729Syar	}
75172729Syar
76172729Syar	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
77172729Syar	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
78172729Syar	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
79172729Syar	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
80172729Syar	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
81156772Sdeischen	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
82172729Syar	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
83156772Sdeischen	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
84156772Sdeischen	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
85172729Syar	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
86172729Syar	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
87156772Sdeischen	supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
88156772Sdeischen#endif
89172729Syar}
90172729Syar
91156772Sdeischenvoid
92156772Sdeischenkgdb_trgt_store_registers(int regno __unused)
93156772Sdeischen{
94172729Syar
95172729Syar	fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
96156772Sdeischen}
97172729Syar
98156772Sdeischenvoid
99156772Sdeischenkgdb_trgt_new_objfile(struct objfile *objfile)
100156772Sdeischen{
101172729Syar}
102172729Syar
103156772Sdeischen#ifndef CROSS_DEBUGGER
104172729Syarstruct kgdb_frame_cache {
105172729Syar	CORE_ADDR	pc;
106156772Sdeischen	CORE_ADDR	sp;
107156772Sdeischen};
108156772Sdeischen
109156772Sdeischenstatic int kgdb_trgt_frame_offset[] = {
110172729Syar	offsetof(struct trapframe, zero),
111172729Syar	offsetof(struct trapframe, ast),
112172729Syar	offsetof(struct trapframe, v0),
113172729Syar	offsetof(struct trapframe, v1),
114156772Sdeischen	offsetof(struct trapframe, a0),
115156772Sdeischen	offsetof(struct trapframe, a1),
116156772Sdeischen	offsetof(struct trapframe, a2),
117156772Sdeischen	offsetof(struct trapframe, a3),
118156772Sdeischen#if defined(__mips_n32) || defined(__mips_n64)
119156772Sdeischen	offsetof(struct trapframe, a4),
120156772Sdeischen	offsetof(struct trapframe, a5),
121156772Sdeischen	offsetof(struct trapframe, a6),
122156772Sdeischen	offsetof(struct trapframe, a7),
123172729Syar	offsetof(struct trapframe, t0),
124156772Sdeischen	offsetof(struct trapframe, t1),
125156772Sdeischen	offsetof(struct trapframe, t2),
126172729Syar	offsetof(struct trapframe, t3),
127156772Sdeischen#else
128172729Syar	offsetof(struct trapframe, t0),
129172729Syar	offsetof(struct trapframe, t1),
130172729Syar	offsetof(struct trapframe, t2),
131156772Sdeischen	offsetof(struct trapframe, t3),
132156772Sdeischen	offsetof(struct trapframe, t4),
133172729Syar	offsetof(struct trapframe, t5),
134172729Syar	offsetof(struct trapframe, t6),
135156772Sdeischen	offsetof(struct trapframe, t7),
136156772Sdeischen#endif
137156772Sdeischen	offsetof(struct trapframe, s0),
138156772Sdeischen	offsetof(struct trapframe, s1),
139156772Sdeischen	offsetof(struct trapframe, s2),
140156772Sdeischen	offsetof(struct trapframe, s3),
141156772Sdeischen	offsetof(struct trapframe, s4),
142156772Sdeischen	offsetof(struct trapframe, s5),
143156772Sdeischen	offsetof(struct trapframe, s6),
144172729Syar	offsetof(struct trapframe, s7),
145172729Syar	offsetof(struct trapframe, t8),
146172729Syar	offsetof(struct trapframe, t9),
147156772Sdeischen	offsetof(struct trapframe, k0),
148156772Sdeischen	offsetof(struct trapframe, k1),
149156772Sdeischen	offsetof(struct trapframe, gp),
150156772Sdeischen	offsetof(struct trapframe, sp),
151172729Syar	offsetof(struct trapframe, s8),
152172729Syar	offsetof(struct trapframe, ra),
153172729Syar};
154172729Syar
155172729Syarstatic struct kgdb_frame_cache *
156172729Syarkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
157156772Sdeischen{
158172729Syar	char buf[MAX_REGISTER_SIZE];
159172729Syar	struct kgdb_frame_cache *cache;
160172729Syar
161172729Syar	cache = *this_cache;
162172729Syar	if (cache == NULL) {
163156772Sdeischen		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
164156772Sdeischen		*this_cache = cache;
165156772Sdeischen		cache->pc = frame_func_unwind(next_frame);
166172729Syar		frame_unwind_register(next_frame, SP_REGNUM, buf);
167156772Sdeischen		cache->sp = extract_unsigned_integer(buf,
168156772Sdeischen		    register_size(current_gdbarch, SP_REGNUM));
169156772Sdeischen	}
170172729Syar	return (cache);
171172729Syar}
172156772Sdeischen
173156772Sdeischenstatic void
174156772Sdeischenkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
175156772Sdeischen    struct frame_id *this_id)
176156772Sdeischen{
177156772Sdeischen	struct kgdb_frame_cache *cache;
178156772Sdeischen
179172729Syar	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
180172729Syar	*this_id = frame_id_build(cache->sp, cache->pc);
181172729Syar}
182172729Syar
183156772Sdeischenstatic void
184156772Sdeischenkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
185168963Sdeischen    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
186168963Sdeischen    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
187168963Sdeischen    int *realnump __unused, void *valuep __unused)
188168963Sdeischen{
189168963Sdeischen	char dummy_valuep[MAX_REGISTER_SIZE];
190168963Sdeischen	struct kgdb_frame_cache *cache;
191168963Sdeischen	int ofs, regsz;
192168963Sdeischen
193168963Sdeischen	regsz = register_size(current_gdbarch, regnum);
194168963Sdeischen
195168963Sdeischen	if (valuep == NULL)
196168963Sdeischen		valuep = dummy_valuep;
197168963Sdeischen	memset(valuep, 0, regsz);
198168963Sdeischen	*optimizedp = 0;
199168963Sdeischen	*addrp = 0;
200168963Sdeischen	*lvalp = not_lval;
201168963Sdeischen	*realnump = -1;
202168963Sdeischen
203168963Sdeischen	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
204168963Sdeischen	    kgdb_trgt_frame_offset[regnum] : -1;
205172729Syar	if (ofs == -1)
206168963Sdeischen		return;
207171530Skan
208171530Skan	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
209171530Skan	*addrp = cache->sp + ofs * 8;
210168963Sdeischen	*lvalp = lval_memory;
211168963Sdeischen	target_read_memory(*addrp, valuep, regsz);
212171530Skan}
213171530Skan
214168963Sdeischenstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
215168963Sdeischen	UNKNOWN_FRAME,
216168963Sdeischen	&kgdb_trgt_trapframe_this_id,
217168963Sdeischen	&kgdb_trgt_trapframe_prev_register
218168963Sdeischen};
219168963Sdeischen#endif
220168963Sdeischen
221172729Syarconst struct frame_unwind *
222156772Sdeischenkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
223172729Syar{
224172729Syar#ifndef CROSS_DEBUGGER
225172729Syar	char *pname;
226172729Syar	CORE_ADDR pc;
227172729Syar
228156772Sdeischen	pc = frame_pc_unwind(next_frame);
229168963Sdeischen	pname = NULL;
230156772Sdeischen	find_pc_partial_function(pc, &pname, NULL, NULL);
231156772Sdeischen	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
242/*
243 * This function ensures, that the PC is inside the
244 * function section which is understood by GDB.
245 *
246 * Return 0 when fixup is necessary, -1 otherwise.
247 */
248int
249kgdb_trgt_pc_fixup(CORE_ADDR *pc __unused)
250{
251
252	return (-1);
253}
254