]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - gnu/usr.bin/gdb/kgdb/trgt_ia64.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_ia64.c
1 /*
2  * Copyright (c) 2004 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <machine/frame.h>
32 #include <machine/md_var.h>
33 #include <machine/pcb.h>
34 #include <err.h>
35 #include <kvm.h>
36 #include <string.h>
37
38 #include <defs.h>
39 #include <target.h>
40 #include <gdbthread.h>
41 #include <inferior.h>
42 #include <regcache.h>
43 #include <frame-unwind.h>
44 #include <ia64-tdep.h>
45
46 #include "kgdb.h"
47
48 void
49 kgdb_trgt_fetch_registers(int regno __unused)
50 {
51         struct kthr *kt;
52         struct pcb pcb;
53         uint64_t r;
54
55         kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
56         if (kt == NULL)
57                 return;
58         if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
59                 warnx("kvm_read: %s", kvm_geterr(kvm));
60                 memset(&pcb, 0, sizeof(pcb));
61         }
62
63         /* Registers 0-127: general registers. */
64         supply_register(IA64_GR1_REGNUM, (char *)&pcb.pcb_special.gp);
65         supply_register(IA64_GR4_REGNUM, (char *)&pcb.pcb_preserved.gr4);
66         supply_register(IA64_GR5_REGNUM, (char *)&pcb.pcb_preserved.gr5);
67         supply_register(IA64_GR6_REGNUM, (char *)&pcb.pcb_preserved.gr6);
68         supply_register(IA64_GR7_REGNUM, (char *)&pcb.pcb_preserved.gr7);
69         supply_register(IA64_GR12_REGNUM, (char *)&pcb.pcb_special.sp);
70         supply_register(IA64_GR12_REGNUM+1, (char *)&pcb.pcb_special.tp);
71
72         /* Registers 128-255: floating-point registers. */
73         supply_register(IA64_FR2_REGNUM, (char *)&pcb.pcb_preserved_fp.fr2);
74         supply_register(IA64_FR2_REGNUM+1, (char *)&pcb.pcb_preserved_fp.fr3);
75         supply_register(IA64_FR2_REGNUM+2, (char *)&pcb.pcb_preserved_fp.fr4);
76         supply_register(IA64_FR2_REGNUM+3, (char *)&pcb.pcb_preserved_fp.fr5);
77         supply_register(IA64_FR16_REGNUM, (char *)&pcb.pcb_preserved_fp.fr16);
78         supply_register(IA64_FR16_REGNUM+1, (char*)&pcb.pcb_preserved_fp.fr17);
79         supply_register(IA64_FR16_REGNUM+2, (char*)&pcb.pcb_preserved_fp.fr18);
80         supply_register(IA64_FR16_REGNUM+3, (char*)&pcb.pcb_preserved_fp.fr19);
81         supply_register(IA64_FR16_REGNUM+4, (char*)&pcb.pcb_preserved_fp.fr20);
82         supply_register(IA64_FR16_REGNUM+5, (char*)&pcb.pcb_preserved_fp.fr21);
83         supply_register(IA64_FR16_REGNUM+6, (char*)&pcb.pcb_preserved_fp.fr22);
84         supply_register(IA64_FR16_REGNUM+7, (char*)&pcb.pcb_preserved_fp.fr23);
85         supply_register(IA64_FR16_REGNUM+8, (char*)&pcb.pcb_preserved_fp.fr24);
86         supply_register(IA64_FR16_REGNUM+9, (char*)&pcb.pcb_preserved_fp.fr25);
87         supply_register(IA64_FR16_REGNUM+10,(char*)&pcb.pcb_preserved_fp.fr26);
88         supply_register(IA64_FR16_REGNUM+11,(char*)&pcb.pcb_preserved_fp.fr27);
89         supply_register(IA64_FR16_REGNUM+12,(char*)&pcb.pcb_preserved_fp.fr28);
90         supply_register(IA64_FR16_REGNUM+13,(char*)&pcb.pcb_preserved_fp.fr29);
91         supply_register(IA64_FR16_REGNUM+14,(char*)&pcb.pcb_preserved_fp.fr30);
92         supply_register(IA64_FR16_REGNUM+15,(char*)&pcb.pcb_preserved_fp.fr31);
93
94         /* Registers 320-327: branch registers. */
95         if (pcb.pcb_special.__spare == ~0UL)
96                 supply_register(IA64_BR0_REGNUM, (char *)&pcb.pcb_special.rp);
97         supply_register(IA64_BR1_REGNUM, (char *)&pcb.pcb_preserved.br1);
98         supply_register(IA64_BR2_REGNUM, (char *)&pcb.pcb_preserved.br2);
99         supply_register(IA64_BR3_REGNUM, (char *)&pcb.pcb_preserved.br3);
100         supply_register(IA64_BR4_REGNUM, (char *)&pcb.pcb_preserved.br4);
101         supply_register(IA64_BR5_REGNUM, (char *)&pcb.pcb_preserved.br5);
102
103         /* Registers 328-333: misc. other registers. */
104         supply_register(IA64_PR_REGNUM, (char *)&pcb.pcb_special.pr);
105         if (pcb.pcb_special.__spare == ~0UL) {
106                 r = pcb.pcb_special.iip + ((pcb.pcb_special.psr >> 41) & 3);
107                 supply_register(IA64_IP_REGNUM, (char *)&r);
108                 supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.cfm);
109         } else {
110                 supply_register(IA64_IP_REGNUM, (char *)&pcb.pcb_special.rp);
111                 supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.pfs);
112         }
113
114         /* Registers 334-461: application registers. */
115         supply_register(IA64_RSC_REGNUM, (char *)&pcb.pcb_special.rsc);
116         r = pcb.pcb_special.bspstore;
117         if (pcb.pcb_special.__spare == ~0UL)
118                 r += pcb.pcb_special.ndirty;
119         else
120                 r = ia64_bsp_adjust(r, IA64_CFM_SOF(pcb.pcb_special.pfs) -
121                     IA64_CFM_SOL(pcb.pcb_special.pfs));
122         supply_register(IA64_BSP_REGNUM, (char *)&r);
123         supply_register(IA64_BSPSTORE_REGNUM, (char *)&r);
124         supply_register(IA64_RNAT_REGNUM, (char *)&pcb.pcb_special.rnat);
125         supply_register(IA64_UNAT_REGNUM, (char *)&pcb.pcb_special.unat);
126         supply_register(IA64_FPSR_REGNUM, (char *)&pcb.pcb_special.fpsr);
127         if (pcb.pcb_special.__spare == ~0UL)
128                 supply_register(IA64_PFS_REGNUM, (char *)&pcb.pcb_special.pfs);
129         supply_register(IA64_LC_REGNUM, (char *)&pcb.pcb_preserved.lc);
130 }
131
132 void
133 kgdb_trgt_store_registers(int regno __unused)
134 {
135         fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
136 }
137
138 void
139 kgdb_trgt_new_objfile(struct objfile *objfile)
140 {
141 }
142
143 struct kgdb_frame_cache {
144         CORE_ADDR       bsp;
145         CORE_ADDR       ip;
146         CORE_ADDR       sp;
147         CORE_ADDR       saved_bsp;
148 };
149
150 #define SPECIAL(x)      offsetof(struct trapframe, tf_special)          \
151                         + offsetof(struct _special, x)
152 #define SCRATCH(x)      offsetof(struct trapframe, tf_scratch)          \
153                         + offsetof(struct _caller_saved, x)
154 #define SCRATCH_FP(x)   offsetof(struct trapframe, tf_scratch_fp)       \
155                         + offsetof(struct _caller_saved_fp, x)
156
157 static int kgdb_trgt_frame_ofs_gr[32] = {
158         -1,                                     /* gr0 */
159         SPECIAL(gp),
160         SCRATCH(gr2),   SCRATCH(gr3),
161         -1, -1, -1, -1,                         /* gr4-gr7 */
162         SCRATCH(gr8),   SCRATCH(gr9),   SCRATCH(gr10),  SCRATCH(gr11),
163         SPECIAL(sp),    SPECIAL(tp),
164         SCRATCH(gr14),  SCRATCH(gr15),  SCRATCH(gr16),  SCRATCH(gr17),
165         SCRATCH(gr18),  SCRATCH(gr19),  SCRATCH(gr20),  SCRATCH(gr21),
166         SCRATCH(gr22),  SCRATCH(gr23),  SCRATCH(gr24),  SCRATCH(gr25),
167         SCRATCH(gr26),  SCRATCH(gr27),  SCRATCH(gr28),  SCRATCH(gr29),
168         SCRATCH(gr30),  SCRATCH(gr31)
169 };
170
171 static int kgdb_trgt_frame_ofs_fr[32] = {
172         -1,                                     /* fr0: constant 0.0 */
173         -1,                                     /* fr1: constant 1.0 */
174         -1, -1, -1, -1,                         /* fr2-fr5 */
175         SCRATCH_FP(fr6), SCRATCH_FP(fr7), SCRATCH_FP(fr8), SCRATCH_FP(fr9),
176         SCRATCH_FP(fr10), SCRATCH_FP(fr11), SCRATCH_FP(fr12), SCRATCH_FP(fr13),
177         SCRATCH_FP(fr14), SCRATCH_FP(fr15)
178 };
179
180 static int kgdb_trgt_frame_ofs_br[8] = {
181         SPECIAL(rp),
182         -1, -1, -1, -1, -1,                     /* br1-br5 */
183         SCRATCH(br6), SCRATCH(br7)
184 };
185
186 static int kgdb_trgt_frame_ofs_ar[49] = {
187         /* ar0-ar15 */
188         SPECIAL(rsc),
189         -1,                                     /* ar.bsp */
190         SPECIAL(bspstore), SPECIAL(rnat),
191         -1, -1, -1, -1, -1,                     /* ar20-ar24 */
192         SCRATCH(csd), SCRATCH(ssd),
193         -1, -1, -1, -1, -1,                     /* ar27-ar31 */
194         SCRATCH(ccv),
195         -1, -1, -1,                             /* ar33-ar35 */
196         SPECIAL(unat),
197         -1, -1, -1,                             /* ar37-ar39 */
198         SPECIAL(fpsr),
199         -1, -1, -1, -1, -1, -1, -1,             /* ar41-ar47 */
200         -1, -1, -1, -1, -1, -1, -1, -1,         /* ar48-ar55 */
201         -1, -1, -1, -1, -1, -1, -1, -1,         /* ar56-ar63 */
202         SPECIAL(pfs)
203 };
204
205 static struct kgdb_frame_cache *
206 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
207 {
208         char buf[MAX_REGISTER_SIZE];
209         struct kgdb_frame_cache *cache;
210
211         cache = *this_cache;
212         if (cache == NULL) {
213                 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
214                 *this_cache = cache;
215                 frame_unwind_register(next_frame, IA64_BSP_REGNUM, buf);
216                 cache->bsp = extract_unsigned_integer(buf,
217                     register_size(current_gdbarch, IA64_BSP_REGNUM));
218                 cache->ip = frame_func_unwind(next_frame);
219                 frame_unwind_register(next_frame, SP_REGNUM, buf);
220                 cache->sp = extract_unsigned_integer(buf,
221                     register_size(current_gdbarch, SP_REGNUM));
222         }
223         return (cache);
224 }
225
226 static void
227 kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
228     struct frame_id *this_id)
229 {
230         struct kgdb_frame_cache *cache;
231
232         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
233         *this_id = frame_id_build_special(cache->sp, cache->ip, cache->bsp);
234 }
235
236 static void
237 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
238     void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
239     CORE_ADDR *addrp, int *realnump, void *valuep)
240 {
241         char buf[MAX_REGISTER_SIZE];
242         char dummy_valuep[MAX_REGISTER_SIZE];
243         struct kgdb_frame_cache *cache;
244         CORE_ADDR bsp;
245         int ofs, regsz;
246
247         regsz = register_size(current_gdbarch, regnum);
248
249         if (valuep == NULL)
250                 valuep = dummy_valuep;
251         memset(valuep, 0, regsz);
252         *optimizedp = 0;
253         *addrp = 0;
254         *lvalp = not_lval;
255         *realnump = -1;
256
257         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
258
259         if (regnum == IA64_BSP_REGNUM) {
260                 if (cache->saved_bsp == 0) {
261                         target_read_memory(cache->sp + 16 + SPECIAL(bspstore),
262                             buf, regsz);
263                         bsp = extract_unsigned_integer(buf, regsz);
264                         target_read_memory(cache->sp + 16 + SPECIAL(ndirty),
265                             buf, regsz);
266                         bsp += extract_unsigned_integer(buf, regsz);
267                         cache->saved_bsp = bsp;
268                 }
269                 store_unsigned_integer(valuep, regsz, cache->saved_bsp);
270                 return;
271         }
272         if (regnum == IA64_PR_REGNUM)
273                 ofs = SPECIAL(pr);
274         else if (regnum == IA64_IP_REGNUM)
275                 ofs = SPECIAL(iip);
276         else if (regnum == IA64_PSR_REGNUM)
277                 ofs = SPECIAL(psr);
278         else if (regnum == IA64_CFM_REGNUM)
279                 ofs = SPECIAL(cfm);
280         else if (regnum >= IA64_GR0_REGNUM && regnum <= IA64_GR31_REGNUM)
281                 ofs = kgdb_trgt_frame_ofs_gr[regnum - IA64_GR0_REGNUM];
282         else if (regnum >= IA64_FR0_REGNUM && regnum <= IA64_FR15_REGNUM)
283                 ofs = kgdb_trgt_frame_ofs_fr[regnum - IA64_FR0_REGNUM];
284         else if (regnum >= IA64_BR0_REGNUM && regnum <= IA64_BR7_REGNUM)
285                 ofs = kgdb_trgt_frame_ofs_br[regnum - IA64_BR0_REGNUM];
286         else if (regnum >= IA64_RSC_REGNUM && regnum <= IA64_PFS_REGNUM)
287                 ofs = kgdb_trgt_frame_ofs_ar[regnum - IA64_RSC_REGNUM];
288         else
289                 ofs = -1;
290         if (ofs == -1)
291                 return;
292
293         *addrp = cache->sp + 16 + ofs;
294         *lvalp = lval_memory;
295         target_read_memory(*addrp, valuep, regsz);
296 }
297
298 static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
299         UNKNOWN_FRAME,
300         &kgdb_trgt_trapframe_this_id,
301         &kgdb_trgt_trapframe_prev_register
302 };
303
304 const struct frame_unwind *
305 kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
306 {
307         char *pname;
308         CORE_ADDR ip;
309
310         ip = frame_func_unwind(next_frame);
311         pname = NULL;
312         find_pc_partial_function(ip, &pname, NULL, NULL);
313         if (pname == NULL)
314                 return (NULL);
315         if (strncmp(pname, "ivt_", 4) == 0)
316                 return (&kgdb_trgt_trapframe_unwind);
317         /* printf("%s: %lx =%s\n", __func__, ip, pname); */
318         return (NULL);
319 }