1161589Smarcel/*-
2161589Smarcel * Copyright (c) 2006 Marcel Moolenaar
3161589Smarcel * All rights reserved.
4161589Smarcel *
5161589Smarcel * Redistribution and use in source and binary forms, with or without
6161589Smarcel * modification, are permitted provided that the following conditions
7161589Smarcel * are met:
8161589Smarcel *
9161589Smarcel * 1. Redistributions of source code must retain the above copyright
10161589Smarcel *    notice, this list of conditions and the following disclaimer.
11161589Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12161589Smarcel *    notice, this list of conditions and the following disclaimer in the
13161589Smarcel *    documentation and/or other materials provided with the distribution.
14161589Smarcel *
15161589Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16161589Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17161589Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18161589Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19161589Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20161589Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21161589Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22161589Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23161589Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24161589Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25161589Smarcel */
26161589Smarcel
27161589Smarcel#include <sys/cdefs.h>
28161589Smarcel__FBSDID("$FreeBSD$");
29161589Smarcel
30161589Smarcel#include <sys/types.h>
31234739Smarcel#ifdef CROSS_DEBUGGER
32234739Smarcel#include <sys/powerpc/include/pcb.h>
33234739Smarcel#include <sys/powerpc/include/frame.h>
34234739Smarcel#else
35161589Smarcel#include <machine/pcb.h>
36161589Smarcel#include <machine/frame.h>
37234739Smarcel#endif
38161589Smarcel#include <err.h>
39161589Smarcel#include <kvm.h>
40161589Smarcel#include <string.h>
41161589Smarcel
42161589Smarcel#include <defs.h>
43161589Smarcel#include <target.h>
44161589Smarcel#include <gdbthread.h>
45161589Smarcel#include <inferior.h>
46161589Smarcel#include <regcache.h>
47161589Smarcel#include <frame-unwind.h>
48161589Smarcel#include <ppc-tdep.h>
49161589Smarcel
50161589Smarcel#include "kgdb.h"
51161589Smarcel
52246893SmarcelCORE_ADDR
53246893Smarcelkgdb_trgt_core_pcb(u_int cpuid)
54246893Smarcel{
55246893Smarcel	return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
56246893Smarcel}
57246893Smarcel
58161589Smarcelvoid
59161589Smarcelkgdb_trgt_fetch_registers(int regno __unused)
60161589Smarcel{
61161589Smarcel	struct kthr *kt;
62163440Sjhb	struct pcb pcb;
63161589Smarcel	struct gdbarch_tdep *tdep;
64161589Smarcel	int i;
65161589Smarcel
66161589Smarcel	tdep = gdbarch_tdep (current_gdbarch);
67161589Smarcel
68178713Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
69161589Smarcel	if (kt == NULL)
70161589Smarcel		return;
71161589Smarcel	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
72161589Smarcel		warnx("kvm_read: %s", kvm_geterr(kvm));
73161589Smarcel		memset(&pcb, 0, sizeof(pcb));
74161589Smarcel	}
75161589Smarcel
76161589Smarcel	/*
77161589Smarcel	 * r14-r31 are saved in the pcb
78161589Smarcel	 */
79161589Smarcel	for (i = 14; i <= 31; i++) {
80161589Smarcel		supply_register(tdep->ppc_gp0_regnum + i,
81161589Smarcel		    (char *)&pcb.pcb_context[i]);
82161589Smarcel	}
83163440Sjhb
84161589Smarcel	/* r1 is saved in the sp field */
85161589Smarcel	supply_register(tdep->ppc_gp0_regnum + 1, (char *)&pcb.pcb_sp);
86161589Smarcel
87161589Smarcel	supply_register(tdep->ppc_lr_regnum, (char *)&pcb.pcb_lr);
88161589Smarcel	supply_register(tdep->ppc_cr_regnum, (char *)&pcb.pcb_cr);
89161589Smarcel}
90161589Smarcel
91161589Smarcelvoid
92161589Smarcelkgdb_trgt_store_registers(int regno __unused)
93161589Smarcel{
94161589Smarcel	fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
95161589Smarcel}
96161589Smarcel
97178670Sjhbvoid
98178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
99178670Sjhb{
100178670Sjhb}
101178670Sjhb
102161589Smarcelstruct kgdb_frame_cache {
103161589Smarcel	CORE_ADDR	pc;
104161589Smarcel	CORE_ADDR	sp;
105161589Smarcel};
106161589Smarcel
107161589Smarcelstatic struct kgdb_frame_cache *
108161589Smarcelkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
109161589Smarcel{
110161589Smarcel	char buf[MAX_REGISTER_SIZE];
111161589Smarcel	struct kgdb_frame_cache *cache;
112161589Smarcel
113161589Smarcel	cache = *this_cache;
114161589Smarcel	if (cache == NULL) {
115161589Smarcel		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
116161589Smarcel		*this_cache = cache;
117161589Smarcel		cache->pc = frame_func_unwind(next_frame);
118161589Smarcel		frame_unwind_register(next_frame, SP_REGNUM, buf);
119161589Smarcel		cache->sp = extract_unsigned_integer(buf,
120161589Smarcel		    register_size(current_gdbarch, SP_REGNUM));
121161589Smarcel	}
122161589Smarcel	return (cache);
123161589Smarcel}
124161589Smarcel
125161589Smarcelstatic void
126161589Smarcelkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
127161589Smarcel    struct frame_id *this_id)
128161589Smarcel{
129161589Smarcel	struct kgdb_frame_cache *cache;
130161589Smarcel
131161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
132161589Smarcel	*this_id = frame_id_build(cache->sp, cache->pc);
133161589Smarcel}
134161589Smarcel
135161589Smarcelstatic void
136161589Smarcelkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
137161589Smarcel    void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
138161589Smarcel    CORE_ADDR *addrp, int *realnump, void *valuep)
139161589Smarcel{
140161589Smarcel	char dummy_valuep[MAX_REGISTER_SIZE];
141161589Smarcel	struct gdbarch_tdep *tdep;
142161589Smarcel	struct kgdb_frame_cache *cache;
143161589Smarcel	int ofs, regsz;
144161589Smarcel
145161589Smarcel	tdep = gdbarch_tdep(current_gdbarch);
146161589Smarcel	regsz = register_size(current_gdbarch, regnum);
147161589Smarcel
148161589Smarcel	if (valuep == NULL)
149161589Smarcel		valuep = dummy_valuep;
150161589Smarcel	memset(valuep, 0, regsz);
151161589Smarcel	*optimizedp = 0;
152161589Smarcel	*addrp = 0;
153161589Smarcel	*lvalp = not_lval;
154161589Smarcel	*realnump = -1;
155161589Smarcel
156161589Smarcel	if (regnum >= tdep->ppc_gp0_regnum &&
157161589Smarcel	    regnum <= tdep->ppc_gplast_regnum)
158161589Smarcel		ofs = offsetof(struct trapframe,
159161589Smarcel		    fixreg[regnum - tdep->ppc_gp0_regnum]);
160161589Smarcel	else if (regnum == tdep->ppc_lr_regnum)
161161589Smarcel		ofs = offsetof(struct trapframe, lr);
162161589Smarcel	else if (regnum == tdep->ppc_cr_regnum)
163161589Smarcel		ofs = offsetof(struct trapframe, cr);
164161589Smarcel	else if (regnum == tdep->ppc_xer_regnum)
165161589Smarcel		ofs = offsetof(struct trapframe, xer);
166161589Smarcel	else if (regnum == tdep->ppc_ctr_regnum)
167161589Smarcel		ofs = offsetof(struct trapframe, ctr);
168161589Smarcel	else if (regnum == PC_REGNUM)
169161589Smarcel		ofs = offsetof(struct trapframe, srr0);
170161589Smarcel	else
171161589Smarcel		return;
172161589Smarcel
173161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
174161589Smarcel	*addrp = cache->sp + 8 + ofs;
175161589Smarcel	*lvalp = lval_memory;
176161589Smarcel	target_read_memory(*addrp, valuep, regsz);
177161589Smarcel}
178161589Smarcel
179161589Smarcelstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
180161589Smarcel        UNKNOWN_FRAME,
181161589Smarcel        &kgdb_trgt_trapframe_this_id,
182161589Smarcel        &kgdb_trgt_trapframe_prev_register
183161589Smarcel};
184161589Smarcel
185161589Smarcelconst struct frame_unwind *
186161589Smarcelkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
187161589Smarcel{
188161589Smarcel	char *pname;
189161589Smarcel	CORE_ADDR pc;
190161589Smarcel
191161589Smarcel	pc = frame_pc_unwind(next_frame);
192161589Smarcel	pname = NULL;
193161589Smarcel	find_pc_partial_function(pc, &pname, NULL, NULL);
194161589Smarcel	if (pname == NULL)
195161589Smarcel		return (NULL);
196161589Smarcel	if (strcmp(pname, "asttrapexit") == 0 ||
197161589Smarcel	    strcmp(pname, "trapexit") == 0)
198161589Smarcel		return (&kgdb_trgt_trapframe_unwind);
199161589Smarcel	/* printf("%s: %llx =%s\n", __func__, pc, pname); */
200161589Smarcel	return (NULL);
201161589Smarcel}
202