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
55179161Sobrienvoid
56179161Sobrienkgdb_trgt_fetch_registers(int regno __unused)
57179161Sobrien{
58214962Sgonzo#ifndef	CROSS_DEBUGGER
59179161Sobrien	struct kthr *kt;
60179161Sobrien	struct pcb pcb;
61179161Sobrien
62179859Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
63179161Sobrien	if (kt == NULL)
64179161Sobrien		return;
65179161Sobrien	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
66179161Sobrien		warnx("kvm_read: %s", kvm_geterr(kvm));
67179161Sobrien		memset(&pcb, 0, sizeof(pcb));
68179161Sobrien	}
69214952Sgonzo
70214952Sgonzo	supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
71214952Sgonzo	supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
72214952Sgonzo	supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
73214952Sgonzo	supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
74214952Sgonzo	supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
75214952Sgonzo	supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
76214952Sgonzo	supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
77214952Sgonzo	supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
78214952Sgonzo	supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
79214952Sgonzo	supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
80214952Sgonzo	supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
81214952Sgonzo	supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
82214962Sgonzo#endif
83179161Sobrien}
84179161Sobrien
85179161Sobrienvoid
86179161Sobrienkgdb_trgt_store_registers(int regno __unused)
87179161Sobrien{
88179161Sobrien
89214952Sgonzo	fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
90179161Sobrien}
91179161Sobrien
92179859Sjhbvoid
93179859Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
94179859Sjhb{
95179859Sjhb}
96179859Sjhb
97214962Sgonzo#ifndef CROSS_DEBUGGER
98179161Sobrienstruct kgdb_frame_cache {
99179161Sobrien	CORE_ADDR	pc;
100179161Sobrien	CORE_ADDR	sp;
101179161Sobrien};
102179161Sobrien
103179161Sobrienstatic int kgdb_trgt_frame_offset[] = {
104179161Sobrien	offsetof(struct trapframe, zero),
105179161Sobrien	offsetof(struct trapframe, ast),
106179161Sobrien	offsetof(struct trapframe, v0),
107179161Sobrien	offsetof(struct trapframe, v1),
108179161Sobrien	offsetof(struct trapframe, a0),
109179161Sobrien	offsetof(struct trapframe, a1),
110179161Sobrien	offsetof(struct trapframe, a2),
111179161Sobrien	offsetof(struct trapframe, a3),
112179161Sobrien	offsetof(struct trapframe, t0),
113179161Sobrien	offsetof(struct trapframe, t1),
114179161Sobrien	offsetof(struct trapframe, t2),
115179161Sobrien	offsetof(struct trapframe, t3),
116179161Sobrien	offsetof(struct trapframe, t4),
117179161Sobrien	offsetof(struct trapframe, t5),
118179161Sobrien	offsetof(struct trapframe, t6),
119179161Sobrien	offsetof(struct trapframe, t7),
120179161Sobrien	offsetof(struct trapframe, s0),
121179161Sobrien	offsetof(struct trapframe, s1),
122179161Sobrien	offsetof(struct trapframe, s2),
123179161Sobrien	offsetof(struct trapframe, s3),
124179161Sobrien	offsetof(struct trapframe, s4),
125179161Sobrien	offsetof(struct trapframe, s5),
126179161Sobrien	offsetof(struct trapframe, s6),
127179161Sobrien	offsetof(struct trapframe, s7),
128179161Sobrien	offsetof(struct trapframe, t8),
129179161Sobrien	offsetof(struct trapframe, t9),
130179161Sobrien	offsetof(struct trapframe, k0),
131179161Sobrien	offsetof(struct trapframe, k1),
132179161Sobrien	offsetof(struct trapframe, gp),
133179161Sobrien	offsetof(struct trapframe, sp),
134179161Sobrien	offsetof(struct trapframe, s8),
135179161Sobrien	offsetof(struct trapframe, ra),
136179161Sobrien};
137179161Sobrien
138179161Sobrienstatic struct kgdb_frame_cache *
139214952Sgonzokgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
140179161Sobrien{
141179161Sobrien	char buf[MAX_REGISTER_SIZE];
142179161Sobrien	struct kgdb_frame_cache *cache;
143179161Sobrien
144179161Sobrien	cache = *this_cache;
145179161Sobrien	if (cache == NULL) {
146179161Sobrien		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
147179161Sobrien		*this_cache = cache;
148179161Sobrien		cache->pc = frame_func_unwind(next_frame);
149179161Sobrien		frame_unwind_register(next_frame, SP_REGNUM, buf);
150179161Sobrien		cache->sp = extract_unsigned_integer(buf,
151179161Sobrien		    register_size(current_gdbarch, SP_REGNUM));
152179161Sobrien	}
153179161Sobrien	return (cache);
154179161Sobrien}
155179161Sobrien
156179161Sobrienstatic void
157179161Sobrienkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
158179161Sobrien    struct frame_id *this_id)
159179161Sobrien{
160179161Sobrien	struct kgdb_frame_cache *cache;
161179161Sobrien
162179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
163179161Sobrien	*this_id = frame_id_build(cache->sp, cache->pc);
164179161Sobrien}
165179161Sobrien
166179161Sobrienstatic void
167179161Sobrienkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
168179161Sobrien    void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
169179161Sobrien    enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
170179161Sobrien    int *realnump __unused, void *valuep __unused)
171179161Sobrien{
172179161Sobrien	char dummy_valuep[MAX_REGISTER_SIZE];
173179161Sobrien	struct kgdb_frame_cache *cache;
174179161Sobrien	int ofs, regsz;
175179161Sobrien
176179161Sobrien	regsz = register_size(current_gdbarch, regnum);
177179161Sobrien
178179161Sobrien	if (valuep == NULL)
179179161Sobrien		valuep = dummy_valuep;
180179161Sobrien	memset(valuep, 0, regsz);
181179161Sobrien	*optimizedp = 0;
182179161Sobrien	*addrp = 0;
183179161Sobrien	*lvalp = not_lval;
184179161Sobrien	*realnump = -1;
185179161Sobrien
186179161Sobrien	ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
187179161Sobrien	    kgdb_trgt_frame_offset[regnum] : -1;
188179161Sobrien	if (ofs == -1)
189179161Sobrien		return;
190179161Sobrien
191179161Sobrien	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
192179161Sobrien	*addrp = cache->sp + ofs * 8;
193179161Sobrien	*lvalp = lval_memory;
194179161Sobrien	target_read_memory(*addrp, valuep, regsz);
195179161Sobrien}
196179161Sobrien
197179161Sobrienstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
198179161Sobrien	UNKNOWN_FRAME,
199179161Sobrien	&kgdb_trgt_trapframe_this_id,
200179161Sobrien	&kgdb_trgt_trapframe_prev_register
201179161Sobrien};
202214962Sgonzo#endif
203179161Sobrien
204179161Sobrienconst struct frame_unwind *
205214952Sgonzokgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
206179161Sobrien{
207214962Sgonzo#ifndef CROSS_DEBUGGER
208179161Sobrien	char *pname;
209179161Sobrien	CORE_ADDR pc;
210179161Sobrien
211179161Sobrien	pc = frame_pc_unwind(next_frame);
212179161Sobrien	pname = NULL;
213179161Sobrien	find_pc_partial_function(pc, &pname, NULL, NULL);
214179161Sobrien	if (pname == NULL)
215179161Sobrien		return (NULL);
216179161Sobrien	if ((strcmp(pname, "MipsKernIntr") == 0) ||
217179161Sobrien	    (strcmp(pname, "MipsKernGenException") == 0) ||
218179161Sobrien	    (strcmp(pname, "MipsUserIntr") == 0) ||
219179161Sobrien	    (strcmp(pname, "MipsUserGenException") == 0))
220179161Sobrien		return (&kgdb_trgt_trapframe_unwind);
221214962Sgonzo#endif
222179161Sobrien	return (NULL);
223179161Sobrien}
224