]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - gnu/usr.bin/gdb/kgdb/trgt_mips.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / gnu / usr.bin / gdb / kgdb / trgt_mips.c
1 /*
2  * Copyright (c) 2007 Juniper Networks, Inc.
3  * Copyright (c) 2004 Marcel Moolenaar
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * from: src/gnu/usr.bin/gdb/kgdb/trgt_alpha.c,v 1.2.2.1 2005/09/15 05:32:10 marcel
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/types.h>
34 #include <machine/asm.h>
35 #include <machine/pcb.h>
36 #include <machine/frame.h>
37 #include <err.h>
38 #include <kvm.h>
39 #include <string.h>
40
41 #include <defs.h>
42 #include <target.h>
43 #include <gdbthread.h>
44 #include <inferior.h>
45 #include <regcache.h>
46 #include <frame-unwind.h>
47 #include <mips-tdep.h>
48
49 #include "kgdb.h"
50
51 void
52 kgdb_trgt_fetch_registers(int regno __unused)
53 {
54         struct kthr *kt;
55         struct pcb pcb;
56
57         kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
58         if (kt == NULL)
59                 return;
60         if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
61                 warnx("kvm_read: %s", kvm_geterr(kvm));
62                 memset(&pcb, 0, sizeof(pcb));
63         }
64         supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context.val[0]);
65         supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context.val[1]);
66         supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context.val[2]);
67         supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context.val[3]);
68         supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context.val[4]);
69         supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context.val[5]);
70         supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context.val[6]);
71         supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context.val[7]);
72         supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context.val[8]);
73         supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context.val[8]);
74         supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context.val[9]);
75         supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context.val[10]);
76 }
77
78 void
79 kgdb_trgt_store_registers(int regno __unused)
80 {
81
82         fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
83 }
84
85 void
86 kgdb_trgt_new_objfile(struct objfile *objfile)
87 {
88 }
89
90 struct kgdb_frame_cache {
91         CORE_ADDR       pc;
92         CORE_ADDR       sp;
93 };
94
95 static int kgdb_trgt_frame_offset[] = {
96         offsetof(struct trapframe, zero),
97         offsetof(struct trapframe, ast),
98         offsetof(struct trapframe, v0),
99         offsetof(struct trapframe, v1),
100         offsetof(struct trapframe, a0),
101         offsetof(struct trapframe, a1),
102         offsetof(struct trapframe, a2),
103         offsetof(struct trapframe, a3),
104         offsetof(struct trapframe, t0),
105         offsetof(struct trapframe, t1),
106         offsetof(struct trapframe, t2),
107         offsetof(struct trapframe, t3),
108         offsetof(struct trapframe, t4),
109         offsetof(struct trapframe, t5),
110         offsetof(struct trapframe, t6),
111         offsetof(struct trapframe, t7),
112         offsetof(struct trapframe, s0),
113         offsetof(struct trapframe, s1),
114         offsetof(struct trapframe, s2),
115         offsetof(struct trapframe, s3),
116         offsetof(struct trapframe, s4),
117         offsetof(struct trapframe, s5),
118         offsetof(struct trapframe, s6),
119         offsetof(struct trapframe, s7),
120         offsetof(struct trapframe, t8),
121         offsetof(struct trapframe, t9),
122         offsetof(struct trapframe, k0),
123         offsetof(struct trapframe, k1),
124         offsetof(struct trapframe, gp),
125         offsetof(struct trapframe, sp),
126         offsetof(struct trapframe, s8),
127         offsetof(struct trapframe, ra),
128 };
129
130 static struct kgdb_frame_cache *
131 kgdb_trgt_frame_cache(struct frame_info *next_frame __unused, void **this_cache __unused)
132 {
133         char buf[MAX_REGISTER_SIZE];
134         struct kgdb_frame_cache *cache;
135
136         cache = *this_cache;
137         if (cache == NULL) {
138                 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
139                 *this_cache = cache;
140                 cache->pc = frame_func_unwind(next_frame);
141                 frame_unwind_register(next_frame, SP_REGNUM, buf);
142                 cache->sp = extract_unsigned_integer(buf,
143                     register_size(current_gdbarch, SP_REGNUM));
144         }
145         return (cache);
146 }
147
148 static void
149 kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
150     struct frame_id *this_id)
151 {
152         struct kgdb_frame_cache *cache;
153
154         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
155         *this_id = frame_id_build(cache->sp, cache->pc);
156 }
157
158 static void
159 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
160     void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
161     enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
162     int *realnump __unused, void *valuep __unused)
163 {
164         char dummy_valuep[MAX_REGISTER_SIZE];
165         struct kgdb_frame_cache *cache;
166         int ofs, regsz;
167
168         regsz = register_size(current_gdbarch, regnum);
169
170         if (valuep == NULL)
171                 valuep = dummy_valuep;
172         memset(valuep, 0, regsz);
173         *optimizedp = 0;
174         *addrp = 0;
175         *lvalp = not_lval;
176         *realnump = -1;
177
178         ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
179             kgdb_trgt_frame_offset[regnum] : -1;
180         if (ofs == -1)
181                 return;
182
183         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
184         *addrp = cache->sp + ofs * 8;
185         *lvalp = lval_memory;
186         target_read_memory(*addrp, valuep, regsz);
187 }
188
189 static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
190         UNKNOWN_FRAME,
191         &kgdb_trgt_trapframe_this_id,
192         &kgdb_trgt_trapframe_prev_register
193 };
194
195 const struct frame_unwind *
196 kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame __unused)
197 {
198         char *pname;
199         CORE_ADDR pc;
200
201         pc = frame_pc_unwind(next_frame);
202         pname = NULL;
203         find_pc_partial_function(pc, &pname, NULL, NULL);
204         if (pname == NULL)
205                 return (NULL);
206         if ((strcmp(pname, "MipsKernIntr") == 0) ||
207             (strcmp(pname, "MipsKernGenException") == 0) ||
208             (strcmp(pname, "MipsUserIntr") == 0) ||
209             (strcmp(pname, "MipsUserGenException") == 0))
210                 return (&kgdb_trgt_trapframe_unwind);
211         /* printf("%s: %llx =%s\n", __func__, pc, pname); */
212         return (NULL);
213 }