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
47161589Smarcelvoid
48161589Smarcelkgdb_trgt_fetch_registers(int regno __unused)
49161589Smarcel{
50161589Smarcel	struct kthr *kt;
51163440Sjhb	struct pcb pcb;
52161589Smarcel	struct gdbarch_tdep *tdep;
53161589Smarcel	int i;
54161589Smarcel
55161589Smarcel	tdep = gdbarch_tdep (current_gdbarch);
56161589Smarcel
57178713Sjhb	kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
58161589Smarcel	if (kt == NULL)
59161589Smarcel		return;
60161589Smarcel	if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
61161589Smarcel		warnx("kvm_read: %s", kvm_geterr(kvm));
62161589Smarcel		memset(&pcb, 0, sizeof(pcb));
63161589Smarcel	}
64161589Smarcel
65161589Smarcel	/*
66161589Smarcel	 * r14-r31 are saved in the pcb
67161589Smarcel	 */
68161589Smarcel	for (i = 14; i <= 31; i++) {
69161589Smarcel		supply_register(tdep->ppc_gp0_regnum + i,
70161589Smarcel		    (char *)&pcb.pcb_context[i]);
71161589Smarcel	}
72163440Sjhb
73161589Smarcel	/* r1 is saved in the sp field */
74161589Smarcel	supply_register(tdep->ppc_gp0_regnum + 1, (char *)&pcb.pcb_sp);
75209867Snwhitehorn	/* r2 is saved in the toc field */
76209867Snwhitehorn	supply_register(tdep->ppc_gp0_regnum + 2, (char *)&pcb.pcb_toc);
77161589Smarcel
78161589Smarcel	supply_register(tdep->ppc_lr_regnum, (char *)&pcb.pcb_lr);
79161589Smarcel	supply_register(tdep->ppc_cr_regnum, (char *)&pcb.pcb_cr);
80161589Smarcel}
81161589Smarcel
82161589Smarcelvoid
83161589Smarcelkgdb_trgt_store_registers(int regno __unused)
84161589Smarcel{
85161589Smarcel	fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
86161589Smarcel}
87161589Smarcel
88178670Sjhbvoid
89178670Sjhbkgdb_trgt_new_objfile(struct objfile *objfile)
90178670Sjhb{
91178670Sjhb}
92178670Sjhb
93161589Smarcelstruct kgdb_frame_cache {
94161589Smarcel	CORE_ADDR	pc;
95161589Smarcel	CORE_ADDR	sp;
96161589Smarcel};
97161589Smarcel
98161589Smarcelstatic struct kgdb_frame_cache *
99161589Smarcelkgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
100161589Smarcel{
101161589Smarcel	char buf[MAX_REGISTER_SIZE];
102161589Smarcel	struct kgdb_frame_cache *cache;
103161589Smarcel
104161589Smarcel	cache = *this_cache;
105161589Smarcel	if (cache == NULL) {
106161589Smarcel		cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
107161589Smarcel		*this_cache = cache;
108161589Smarcel		cache->pc = frame_func_unwind(next_frame);
109161589Smarcel		frame_unwind_register(next_frame, SP_REGNUM, buf);
110161589Smarcel		cache->sp = extract_unsigned_integer(buf,
111161589Smarcel		    register_size(current_gdbarch, SP_REGNUM));
112161589Smarcel	}
113161589Smarcel	return (cache);
114161589Smarcel}
115161589Smarcel
116161589Smarcelstatic void
117161589Smarcelkgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
118161589Smarcel    struct frame_id *this_id)
119161589Smarcel{
120161589Smarcel	struct kgdb_frame_cache *cache;
121161589Smarcel
122161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
123161589Smarcel	*this_id = frame_id_build(cache->sp, cache->pc);
124161589Smarcel}
125161589Smarcel
126161589Smarcelstatic void
127161589Smarcelkgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
128161589Smarcel    void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
129161589Smarcel    CORE_ADDR *addrp, int *realnump, void *valuep)
130161589Smarcel{
131161589Smarcel	char dummy_valuep[MAX_REGISTER_SIZE];
132161589Smarcel	struct gdbarch_tdep *tdep;
133161589Smarcel	struct kgdb_frame_cache *cache;
134161589Smarcel	int ofs, regsz;
135161589Smarcel
136161589Smarcel	tdep = gdbarch_tdep(current_gdbarch);
137161589Smarcel	regsz = register_size(current_gdbarch, regnum);
138161589Smarcel
139161589Smarcel	if (valuep == NULL)
140161589Smarcel		valuep = dummy_valuep;
141161589Smarcel	memset(valuep, 0, regsz);
142161589Smarcel	*optimizedp = 0;
143161589Smarcel	*addrp = 0;
144161589Smarcel	*lvalp = not_lval;
145161589Smarcel	*realnump = -1;
146161589Smarcel
147161589Smarcel	if (regnum >= tdep->ppc_gp0_regnum &&
148161589Smarcel	    regnum <= tdep->ppc_gplast_regnum)
149161589Smarcel		ofs = offsetof(struct trapframe,
150161589Smarcel		    fixreg[regnum - tdep->ppc_gp0_regnum]);
151161589Smarcel	else if (regnum == tdep->ppc_lr_regnum)
152161589Smarcel		ofs = offsetof(struct trapframe, lr);
153161589Smarcel	else if (regnum == tdep->ppc_cr_regnum)
154161589Smarcel		ofs = offsetof(struct trapframe, cr);
155161589Smarcel	else if (regnum == tdep->ppc_xer_regnum)
156161589Smarcel		ofs = offsetof(struct trapframe, xer);
157161589Smarcel	else if (regnum == tdep->ppc_ctr_regnum)
158161589Smarcel		ofs = offsetof(struct trapframe, ctr);
159161589Smarcel	else if (regnum == PC_REGNUM)
160161589Smarcel		ofs = offsetof(struct trapframe, srr0);
161161589Smarcel	else
162161589Smarcel		return;
163161589Smarcel
164161589Smarcel	cache = kgdb_trgt_frame_cache(next_frame, this_cache);
165209867Snwhitehorn	*addrp = cache->sp + 48 + ofs;
166161589Smarcel	*lvalp = lval_memory;
167161589Smarcel	target_read_memory(*addrp, valuep, regsz);
168161589Smarcel}
169161589Smarcel
170161589Smarcelstatic const struct frame_unwind kgdb_trgt_trapframe_unwind = {
171161589Smarcel        UNKNOWN_FRAME,
172161589Smarcel        &kgdb_trgt_trapframe_this_id,
173161589Smarcel        &kgdb_trgt_trapframe_prev_register
174161589Smarcel};
175161589Smarcel
176161589Smarcelconst struct frame_unwind *
177161589Smarcelkgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
178161589Smarcel{
179161589Smarcel	char *pname;
180161589Smarcel	CORE_ADDR pc;
181161589Smarcel
182161589Smarcel	pc = frame_pc_unwind(next_frame);
183161589Smarcel	pname = NULL;
184161589Smarcel	find_pc_partial_function(pc, &pname, NULL, NULL);
185161589Smarcel	if (pname == NULL)
186161589Smarcel		return (NULL);
187161589Smarcel	if (strcmp(pname, "asttrapexit") == 0 ||
188161589Smarcel	    strcmp(pname, "trapexit") == 0)
189161589Smarcel		return (&kgdb_trgt_trapframe_unwind);
190161589Smarcel	/* printf("%s: %llx =%s\n", __func__, pc, pname); */
191161589Smarcel	return (NULL);
192161589Smarcel}
193