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$");
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
49214962Sgonzo#ifndef	CROSS_DEBUGGER
50214952Sgonzo#include <machine/pcb.h>
51214962Sgonzo#endif
52214952Sgonzo
53179161Sobrien#include "kgdb.h"
54179161Sobrien
55246893SmarcelCORE_ADDR
56246893Smarcelkgdb_trgt_core_pcb(u_int cpuid)
57246893Smarcel{
58246893Smarcel	return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
59246893Smarcel}
60246893Smarcel
61179161Sobrienvoid
62179161Sobrienkgdb_trgt_fetch_registers(int regno __unused)
63179161Sobrien{
64214962Sgonzo#ifndef	CROSS_DEBUGGER
65179161Sobrien	struct kthr *kt;
66179161Sobrien	struct pcb pcb;
67179161Sobrien
68179859Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
69179161Sobrien	if (kt == NULL)
70179161Sobrien		return;
71179161Sobrien	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
72179161Sobrien		warnx("kvm_read: %s", kvm_geterr(kvm));
73179161Sobrien		memset(&pcb, 0, sizeof(pcb));
74179161Sobrien	}
75214952Sgonzo
76214952Sgonzo	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
77214952Sgonzo	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
78214952Sgonzo	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
79214952Sgonzo	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
80214952Sgonzo	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
81214952Sgonzo	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
82214952Sgonzo	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
83214952Sgonzo	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
84214952Sgonzo	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
85214952Sgonzo	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
86214952Sgonzo	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
87214952Sgonzo	supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
88214962Sgonzo#endif
89179161Sobrien}
90179161Sobrien
91179161Sobrienvoid
92179161Sobrienkgdb_trgt_store_registers(int regno __unused)
93179161Sobrien{
94179161Sobrien
95214952Sgonzo	fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
96179161Sobrien}
97179161Sobrien
98179859Sjhbvoid
99179859Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
100179859Sjhb{
101179859Sjhb}
102179859Sjhb
103214962Sgonzo#ifndef CROSS_DEBUGGER
104179161Sobrienstruct kgdb_frame_cache {
105179161Sobrien	CORE_ADDR	pc;
106179161Sobrien	CORE_ADDR	sp;
107179161Sobrien};
108179161Sobrien
109179161Sobrienstatic int kgdb_trgt_frame_offset[] = {
110179161Sobrien	offsetof(struct trapframe, zero),
111179161Sobrien	offsetof(struct trapframe, ast),
112179161Sobrien	offsetof(struct trapframe, v0),
113179161Sobrien	offsetof(struct trapframe, v1),
114179161Sobrien	offsetof(struct trapframe, a0),
115179161Sobrien	offsetof(struct trapframe, a1),
116179161Sobrien	offsetof(struct trapframe, a2),
117179161Sobrien	offsetof(struct trapframe, a3),
118249878Simp#if defined(__mips_n32) || defined(__mips_n64)
119249878Simp	offsetof(struct trapframe, a4),
120249878Simp	offsetof(struct trapframe, a5),
121249878Simp	offsetof(struct trapframe, a6),
122249878Simp	offsetof(struct trapframe, a7),
123179161Sobrien	offsetof(struct trapframe, t0),
124179161Sobrien	offsetof(struct trapframe, t1),
125179161Sobrien	offsetof(struct trapframe, t2),
126179161Sobrien	offsetof(struct trapframe, t3),
127249878Simp#else
128249878Simp	offsetof(struct trapframe, t0),
129249878Simp	offsetof(struct trapframe, t1),
130249878Simp	offsetof(struct trapframe, t2),
131249878Simp	offsetof(struct trapframe, t3),
132179161Sobrien	offsetof(struct trapframe, t4),
133179161Sobrien	offsetof(struct trapframe, t5),
134179161Sobrien	offsetof(struct trapframe, t6),
135179161Sobrien	offsetof(struct trapframe, t7),
136249878Simp#endif
137179161Sobrien	offsetof(struct trapframe, s0),
138179161Sobrien	offsetof(struct trapframe, s1),
139179161Sobrien	offsetof(struct trapframe, s2),
140179161Sobrien	offsetof(struct trapframe, s3),
141179161Sobrien	offsetof(struct trapframe, s4),
142179161Sobrien	offsetof(struct trapframe, s5),
143179161Sobrien	offsetof(struct trapframe, s6),
144179161Sobrien	offsetof(struct trapframe, s7),
145179161Sobrien	offsetof(struct trapframe, t8),
146179161Sobrien	offsetof(struct trapframe, t9),
147179161Sobrien	offsetof(struct trapframe, k0),
148179161Sobrien	offsetof(struct trapframe, k1),
149179161Sobrien	offsetof(struct trapframe, gp),
150179161Sobrien	offsetof(struct trapframe, sp),
151179161Sobrien	offsetof(struct trapframe, s8),
152179161Sobrien	offsetof(struct trapframe, ra),
153179161Sobrien};
154179161Sobrien
155179161Sobrienstatic struct kgdb_frame_cache *
156214952Sgonzokgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
157179161Sobrien{
158179161Sobrien	char buf[MAX_REGISTER_SIZE];
159179161Sobrien	struct kgdb_frame_cache *cache;
160179161Sobrien
161179161Sobrien	cache = *this_cache;
162179161Sobrien	if (cache == NULL) {
163179161Sobrien		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
164179161Sobrien		*this_cache = cache;
165179161Sobrien		cache->pc = frame_func_unwind(next_frame);
166179161Sobrien		frame_unwind_register(next_frame, SP_REGNUM, buf);
167179161Sobrien		cache->sp = extract_unsigned_integer(buf,
168179161Sobrien		    register_size(current_gdbarch, SP_REGNUM));
169179161Sobrien	}
170179161Sobrien	return (cache);
171179161Sobrien}
172179161Sobrien
173179161Sobrienstatic void
174179161Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
175179161Sobrien    struct frame_id *this_id)
176179161Sobrien{
177179161Sobrien	struct kgdb_frame_cache *cache;
178179161Sobrien
179179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
180179161Sobrien	*this_id = frame_id_build(cache->sp, cache->pc);
181179161Sobrien}
182179161Sobrien
183179161Sobrienstatic void
184179161Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
185179161Sobrien    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
186179161Sobrien    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
187179161Sobrien    int *realnump __unused, void *valuep __unused)
188179161Sobrien{
189179161Sobrien	char dummy_valuep[MAX_REGISTER_SIZE];
190179161Sobrien	struct kgdb_frame_cache *cache;
191179161Sobrien	int ofs, regsz;
192179161Sobrien
193179161Sobrien	regsz = register_size(current_gdbarch, regnum);
194179161Sobrien
195179161Sobrien	if (valuep == NULL)
196179161Sobrien		valuep = dummy_valuep;
197179161Sobrien	memset(valuep, 0, regsz);
198179161Sobrien	*optimizedp = 0;
199179161Sobrien	*addrp = 0;
200179161Sobrien	*lvalp = not_lval;
201179161Sobrien	*realnump = -1;
202179161Sobrien
203179161Sobrien	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
204179161Sobrien	    kgdb_trgt_frame_offset[regnum] : -1;
205179161Sobrien	if (ofs == -1)
206179161Sobrien		return;
207179161Sobrien
208179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
209179161Sobrien	*addrp = cache->sp + ofs * 8;
210179161Sobrien	*lvalp = lval_memory;
211179161Sobrien	target_read_memory(*addrp, valuep, regsz);
212179161Sobrien}
213179161Sobrien
214179161Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
215179161Sobrien	UNKNOWN_FRAME,
216179161Sobrien	&kgdb_trgt_trapframe_this_id,
217179161Sobrien	&kgdb_trgt_trapframe_prev_register
218179161Sobrien};
219214962Sgonzo#endif
220179161Sobrien
221179161Sobrienconst struct frame_unwind *
222214952Sgonzokgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
223179161Sobrien{
224214962Sgonzo#ifndef CROSS_DEBUGGER
225179161Sobrien	char *pname;
226179161Sobrien	CORE_ADDR pc;
227179161Sobrien
228179161Sobrien	pc = frame_pc_unwind(next_frame);
229179161Sobrien	pname = NULL;
230179161Sobrien	find_pc_partial_function(pc, &pname, NULL, NULL);
231179161Sobrien	if (pname == NULL)
232179161Sobrien		return (NULL);
233179161Sobrien	if ((strcmp(pname, "MipsKernIntr") == 0) ||
234179161Sobrien	    (strcmp(pname, "MipsKernGenException") == 0) ||
235179161Sobrien	    (strcmp(pname, "MipsUserIntr") == 0) ||
236179161Sobrien	    (strcmp(pname, "MipsUserGenException") == 0))
237179161Sobrien		return (&kgdb_trgt_trapframe_unwind);
238214962Sgonzo#endif
239179161Sobrien	return (NULL);
240179161Sobrien}
241298363Swma
242298363Swma/*
243298363Swma * This function ensures, that the PC is inside the
244298363Swma * function section which is understood by GDB.
245298363Swma *
246298363Swma * Return 0 when fixup is necessary, -1 otherwise.
247298363Swma */
248298363Swmaint
249298363Swmakgdb_trgt_pc_fixup(CORE_ADDR *pc __unused)
250298363Swma{
251298363Swma
252298363Swma	return (-1);
253298363Swma}
254