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>
31161589Smarcel#include <machine/pcb.h>
32161589Smarcel#include <machine/frame.h>
33161589Smarcel#include <err.h>
34161589Smarcel#include <kvm.h>
35161589Smarcel#include <string.h>
36161589Smarcel
37161589Smarcel#include <defs.h>
38161589Smarcel#include <target.h>
39161589Smarcel#include <gdbthread.h>
40161589Smarcel#include <inferior.h>
41161589Smarcel#include <regcache.h>
42161589Smarcel#include <frame-unwind.h>
43161589Smarcel#include <ppc-tdep.h>
44161589Smarcel
45161589Smarcel#include "kgdb.h"
46161589Smarcel
47246893SmarcelCORE_ADDR
48246893Smarcelkgdb_trgt_core_pcb(u_int cpuid)
49246893Smarcel{
50246893Smarcel	return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
51246893Smarcel}
52246893Smarcel
53161589Smarcelvoid
54161589Smarcelkgdb_trgt_fetch_registers(int regno __unused)
55161589Smarcel{
56161589Smarcel	struct kthr *kt;
57163440Sjhb	struct pcb pcb;
58161589Smarcel	struct gdbarch_tdep *tdep;
59161589Smarcel	int i;
60161589Smarcel
61161589Smarcel	tdep = gdbarch_tdep (current_gdbarch);
62161589Smarcel
63178713Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
64161589Smarcel	if (kt == NULL)
65161589Smarcel		return;
66161589Smarcel	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
67161589Smarcel		warnx("kvm_read: %s", kvm_geterr(kvm));
68161589Smarcel		memset(&pcb, 0, sizeof(pcb));
69161589Smarcel	}
70161589Smarcel
71161589Smarcel	/*
72161589Smarcel	 * r14-r31 are saved in the pcb
73161589Smarcel	 */
74161589Smarcel	for (i = 14; i <= 31; i++) {
75161589Smarcel		supply_register(tdep->ppc_gp0_regnum + i,
76161589Smarcel		    (char *)&pcb.pcb_context[i]);
77161589Smarcel	}
78163440Sjhb
79161589Smarcel	/* r1 is saved in the sp field */
80161589Smarcel	supply_register(tdep->ppc_gp0_regnum + 1, (char *)&pcb.pcb_sp);
81209867Snwhitehorn	/* r2 is saved in the toc field */
82209867Snwhitehorn	supply_register(tdep->ppc_gp0_regnum + 2, (char *)&pcb.pcb_toc);
83161589Smarcel
84161589Smarcel	supply_register(tdep->ppc_lr_regnum, (char *)&pcb.pcb_lr);
85161589Smarcel	supply_register(tdep->ppc_cr_regnum, (char *)&pcb.pcb_cr);
86161589Smarcel}
87161589Smarcel
88161589Smarcelvoid
89161589Smarcelkgdb_trgt_store_registers(int regno __unused)
90161589Smarcel{
91161589Smarcel	fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
92161589Smarcel}
93161589Smarcel
94178670Sjhbvoid
95178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
96178670Sjhb{
97178670Sjhb}
98178670Sjhb
99161589Smarcelstruct kgdb_frame_cache {
100161589Smarcel	CORE_ADDR	pc;
101161589Smarcel	CORE_ADDR	sp;
102161589Smarcel};
103161589Smarcel
104161589Smarcelstatic struct kgdb_frame_cache *
105161589Smarcelkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
106161589Smarcel{
107161589Smarcel	char buf[MAX_REGISTER_SIZE];
108161589Smarcel	struct kgdb_frame_cache *cache;
109161589Smarcel
110161589Smarcel	cache = *this_cache;
111161589Smarcel	if (cache == NULL) {
112161589Smarcel		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
113161589Smarcel		*this_cache = cache;
114161589Smarcel		cache->pc = frame_func_unwind(next_frame);
115161589Smarcel		frame_unwind_register(next_frame, SP_REGNUM, buf);
116161589Smarcel		cache->sp = extract_unsigned_integer(buf,
117161589Smarcel		    register_size(current_gdbarch, SP_REGNUM));
118161589Smarcel	}
119161589Smarcel	return (cache);
120161589Smarcel}
121161589Smarcel
122161589Smarcelstatic void
123161589Smarcelkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
124161589Smarcel    struct frame_id *this_id)
125161589Smarcel{
126161589Smarcel	struct kgdb_frame_cache *cache;
127161589Smarcel
128161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
129161589Smarcel	*this_id = frame_id_build(cache->sp, cache->pc);
130161589Smarcel}
131161589Smarcel
132161589Smarcelstatic void
133161589Smarcelkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
134161589Smarcel    void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
135161589Smarcel    CORE_ADDR *addrp, int *realnump, void *valuep)
136161589Smarcel{
137161589Smarcel	char dummy_valuep[MAX_REGISTER_SIZE];
138161589Smarcel	struct gdbarch_tdep *tdep;
139161589Smarcel	struct kgdb_frame_cache *cache;
140161589Smarcel	int ofs, regsz;
141161589Smarcel
142161589Smarcel	tdep = gdbarch_tdep(current_gdbarch);
143161589Smarcel	regsz = register_size(current_gdbarch, regnum);
144161589Smarcel
145161589Smarcel	if (valuep == NULL)
146161589Smarcel		valuep = dummy_valuep;
147161589Smarcel	memset(valuep, 0, regsz);
148161589Smarcel	*optimizedp = 0;
149161589Smarcel	*addrp = 0;
150161589Smarcel	*lvalp = not_lval;
151161589Smarcel	*realnump = -1;
152161589Smarcel
153161589Smarcel	if (regnum >= tdep->ppc_gp0_regnum &&
154161589Smarcel	    regnum <= tdep->ppc_gplast_regnum)
155161589Smarcel		ofs = offsetof(struct trapframe,
156161589Smarcel		    fixreg[regnum - tdep->ppc_gp0_regnum]);
157161589Smarcel	else if (regnum == tdep->ppc_lr_regnum)
158161589Smarcel		ofs = offsetof(struct trapframe, lr);
159161589Smarcel	else if (regnum == tdep->ppc_cr_regnum)
160161589Smarcel		ofs = offsetof(struct trapframe, cr);
161161589Smarcel	else if (regnum == tdep->ppc_xer_regnum)
162161589Smarcel		ofs = offsetof(struct trapframe, xer);
163161589Smarcel	else if (regnum == tdep->ppc_ctr_regnum)
164161589Smarcel		ofs = offsetof(struct trapframe, ctr);
165161589Smarcel	else if (regnum == PC_REGNUM)
166161589Smarcel		ofs = offsetof(struct trapframe, srr0);
167161589Smarcel	else
168161589Smarcel		return;
169161589Smarcel
170161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
171209867Snwhitehorn	*addrp = cache->sp + 48 + ofs;
172161589Smarcel	*lvalp = lval_memory;
173161589Smarcel	target_read_memory(*addrp, valuep, regsz);
174161589Smarcel}
175161589Smarcel
176161589Smarcelstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
177161589Smarcel        UNKNOWN_FRAME,
178161589Smarcel        &kgdb_trgt_trapframe_this_id,
179161589Smarcel        &kgdb_trgt_trapframe_prev_register
180161589Smarcel};
181161589Smarcel
182161589Smarcelconst struct frame_unwind *
183161589Smarcelkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
184161589Smarcel{
185161589Smarcel	char *pname;
186161589Smarcel	CORE_ADDR pc;
187161589Smarcel
188161589Smarcel	pc = frame_pc_unwind(next_frame);
189161589Smarcel	pname = NULL;
190161589Smarcel	find_pc_partial_function(pc, &pname, NULL, NULL);
191161589Smarcel	if (pname == NULL)
192161589Smarcel		return (NULL);
193161589Smarcel	if (strcmp(pname, "asttrapexit") == 0 ||
194161589Smarcel	    strcmp(pname, "trapexit") == 0)
195161589Smarcel		return (&kgdb_trgt_trapframe_unwind);
196161589Smarcel	/* printf("%s: %llx =%s\n", __func__, pc, pname); */
197161589Smarcel	return (NULL);
198161589Smarcel}
199