]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - gnu/usr.bin/gdb/kgdb/trgt_mips.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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 #ifndef CROSS_DEBUGGER
50 #include <machine/pcb.h>
51 #endif
52
53 #include "kgdb.h"
54
55 void
56 kgdb_trgt_fetch_registers(int regno __unused)
57 {
58 #ifndef CROSS_DEBUGGER
59         struct kthr *kt;
60         struct pcb pcb;
61
62         kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
63         if (kt == NULL)
64                 return;
65         if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
66                 warnx("kvm_read: %s", kvm_geterr(kvm));
67                 memset(&pcb, 0, sizeof(pcb));
68         }
69
70         supply_register(MIPS_S0_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S0]);
71         supply_register(MIPS_S1_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S1]);
72         supply_register(MIPS_S2_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S2]);
73         supply_register(MIPS_S3_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S3]);
74         supply_register(MIPS_S4_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S4]);
75         supply_register(MIPS_S5_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S5]);
76         supply_register(MIPS_S6_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S6]);
77         supply_register(MIPS_S7_REGNUM, (char *)&pcb.pcb_context[PCB_REG_S7]);
78         supply_register(MIPS_SP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_SP]);
79         supply_register(MIPS_FP_REGNUM, (char *)&pcb.pcb_context[PCB_REG_GP]);
80         supply_register(MIPS_RA_REGNUM, (char *)&pcb.pcb_context[PCB_REG_RA]);
81         supply_register(MIPS_EMBED_PC_REGNUM, (char *)&pcb.pcb_context[PCB_REG_PC]);
82 #endif
83 }
84
85 void
86 kgdb_trgt_store_registers(int regno __unused)
87 {
88
89         fprintf_unfiltered(gdb_stderr, "Unimplemented function: %s\n", __func__);
90 }
91
92 void
93 kgdb_trgt_new_objfile(struct objfile *objfile)
94 {
95 }
96
97 #ifndef CROSS_DEBUGGER
98 struct kgdb_frame_cache {
99         CORE_ADDR       pc;
100         CORE_ADDR       sp;
101 };
102
103 static int kgdb_trgt_frame_offset[] = {
104         offsetof(struct trapframe, zero),
105         offsetof(struct trapframe, ast),
106         offsetof(struct trapframe, v0),
107         offsetof(struct trapframe, v1),
108         offsetof(struct trapframe, a0),
109         offsetof(struct trapframe, a1),
110         offsetof(struct trapframe, a2),
111         offsetof(struct trapframe, a3),
112         offsetof(struct trapframe, t0),
113         offsetof(struct trapframe, t1),
114         offsetof(struct trapframe, t2),
115         offsetof(struct trapframe, t3),
116         offsetof(struct trapframe, t4),
117         offsetof(struct trapframe, t5),
118         offsetof(struct trapframe, t6),
119         offsetof(struct trapframe, t7),
120         offsetof(struct trapframe, s0),
121         offsetof(struct trapframe, s1),
122         offsetof(struct trapframe, s2),
123         offsetof(struct trapframe, s3),
124         offsetof(struct trapframe, s4),
125         offsetof(struct trapframe, s5),
126         offsetof(struct trapframe, s6),
127         offsetof(struct trapframe, s7),
128         offsetof(struct trapframe, t8),
129         offsetof(struct trapframe, t9),
130         offsetof(struct trapframe, k0),
131         offsetof(struct trapframe, k1),
132         offsetof(struct trapframe, gp),
133         offsetof(struct trapframe, sp),
134         offsetof(struct trapframe, s8),
135         offsetof(struct trapframe, ra),
136 };
137
138 static struct kgdb_frame_cache *
139 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
140 {
141         char buf[MAX_REGISTER_SIZE];
142         struct kgdb_frame_cache *cache;
143
144         cache = *this_cache;
145         if (cache == NULL) {
146                 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
147                 *this_cache = cache;
148                 cache->pc = frame_func_unwind(next_frame);
149                 frame_unwind_register(next_frame, SP_REGNUM, buf);
150                 cache->sp = extract_unsigned_integer(buf,
151                     register_size(current_gdbarch, SP_REGNUM));
152         }
153         return (cache);
154 }
155
156 static void
157 kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
158     struct frame_id *this_id)
159 {
160         struct kgdb_frame_cache *cache;
161
162         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
163         *this_id = frame_id_build(cache->sp, cache->pc);
164 }
165
166 static void
167 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame __unused,
168     void **this_cache __unused, int regnum __unused, int *optimizedp __unused,
169     enum lval_type *lvalp __unused, CORE_ADDR *addrp __unused,
170     int *realnump __unused, void *valuep __unused)
171 {
172         char dummy_valuep[MAX_REGISTER_SIZE];
173         struct kgdb_frame_cache *cache;
174         int ofs, regsz;
175
176         regsz = register_size(current_gdbarch, regnum);
177
178         if (valuep == NULL)
179                 valuep = dummy_valuep;
180         memset(valuep, 0, regsz);
181         *optimizedp = 0;
182         *addrp = 0;
183         *lvalp = not_lval;
184         *realnump = -1;
185
186         ofs = (regnum >= 0 && regnum <= MIPS_RA_REGNUM) ?
187             kgdb_trgt_frame_offset[regnum] : -1;
188         if (ofs == -1)
189                 return;
190
191         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
192         *addrp = cache->sp + ofs * 8;
193         *lvalp = lval_memory;
194         target_read_memory(*addrp, valuep, regsz);
195 }
196
197 static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
198         UNKNOWN_FRAME,
199         &kgdb_trgt_trapframe_this_id,
200         &kgdb_trgt_trapframe_prev_register
201 };
202 #endif
203
204 const struct frame_unwind *
205 kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
206 {
207 #ifndef CROSS_DEBUGGER
208         char *pname;
209         CORE_ADDR pc;
210
211         pc = frame_pc_unwind(next_frame);
212         pname = NULL;
213         find_pc_partial_function(pc, &pname, NULL, NULL);
214         if (pname == NULL)
215                 return (NULL);
216         if ((strcmp(pname, "MipsKernIntr") == 0) ||
217             (strcmp(pname, "MipsKernGenException") == 0) ||
218             (strcmp(pname, "MipsUserIntr") == 0) ||
219             (strcmp(pname, "MipsUserGenException") == 0))
220                 return (&kgdb_trgt_trapframe_unwind);
221 #endif
222         return (NULL);
223 }