]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - gnu/usr.bin/gdb/kgdb/trgt_ia64.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_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 #ifdef CROSS_DEBUGGER
32 #include <sys/ia64/include/_regset.h>
33 #include <sys/ia64/include/frame.h>
34 #include <sys/ia64/include/md_var.h>
35 #include <sys/ia64/include/pcb.h>
36 #else
37 #include <machine/frame.h>
38 #include <machine/md_var.h>
39 #include <machine/pcb.h>
40 #endif
41 #include <err.h>
42 #include <kvm.h>
43 #include <string.h>
44
45 #include <defs.h>
46 #include <target.h>
47 #include <gdbthread.h>
48 #include <inferior.h>
49 #include <regcache.h>
50 #include <frame-unwind.h>
51 #include <ia64-tdep.h>
52
53 #include "kgdb.h"
54
55 void
56 kgdb_trgt_fetch_registers(int regno __unused)
57 {
58         struct kthr *kt;
59         struct pcb pcb;
60         uint64_t r;
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         /* Registers 0-127: general registers. */
71         supply_register(IA64_GR1_REGNUM, (char *)&pcb.pcb_special.gp);
72         supply_register(IA64_GR4_REGNUM, (char *)&pcb.pcb_preserved.gr4);
73         supply_register(IA64_GR5_REGNUM, (char *)&pcb.pcb_preserved.gr5);
74         supply_register(IA64_GR6_REGNUM, (char *)&pcb.pcb_preserved.gr6);
75         supply_register(IA64_GR7_REGNUM, (char *)&pcb.pcb_preserved.gr7);
76         supply_register(IA64_GR12_REGNUM, (char *)&pcb.pcb_special.sp);
77         supply_register(IA64_GR12_REGNUM+1, (char *)&pcb.pcb_special.tp);
78
79         /* Registers 128-255: floating-point registers. */
80         supply_register(IA64_FR2_REGNUM, (char *)&pcb.pcb_preserved_fp.fr2);
81         supply_register(IA64_FR2_REGNUM+1, (char *)&pcb.pcb_preserved_fp.fr3);
82         supply_register(IA64_FR2_REGNUM+2, (char *)&pcb.pcb_preserved_fp.fr4);
83         supply_register(IA64_FR2_REGNUM+3, (char *)&pcb.pcb_preserved_fp.fr5);
84         supply_register(IA64_FR16_REGNUM, (char *)&pcb.pcb_preserved_fp.fr16);
85         supply_register(IA64_FR16_REGNUM+1, (char*)&pcb.pcb_preserved_fp.fr17);
86         supply_register(IA64_FR16_REGNUM+2, (char*)&pcb.pcb_preserved_fp.fr18);
87         supply_register(IA64_FR16_REGNUM+3, (char*)&pcb.pcb_preserved_fp.fr19);
88         supply_register(IA64_FR16_REGNUM+4, (char*)&pcb.pcb_preserved_fp.fr20);
89         supply_register(IA64_FR16_REGNUM+5, (char*)&pcb.pcb_preserved_fp.fr21);
90         supply_register(IA64_FR16_REGNUM+6, (char*)&pcb.pcb_preserved_fp.fr22);
91         supply_register(IA64_FR16_REGNUM+7, (char*)&pcb.pcb_preserved_fp.fr23);
92         supply_register(IA64_FR16_REGNUM+8, (char*)&pcb.pcb_preserved_fp.fr24);
93         supply_register(IA64_FR16_REGNUM+9, (char*)&pcb.pcb_preserved_fp.fr25);
94         supply_register(IA64_FR16_REGNUM+10,(char*)&pcb.pcb_preserved_fp.fr26);
95         supply_register(IA64_FR16_REGNUM+11,(char*)&pcb.pcb_preserved_fp.fr27);
96         supply_register(IA64_FR16_REGNUM+12,(char*)&pcb.pcb_preserved_fp.fr28);
97         supply_register(IA64_FR16_REGNUM+13,(char*)&pcb.pcb_preserved_fp.fr29);
98         supply_register(IA64_FR16_REGNUM+14,(char*)&pcb.pcb_preserved_fp.fr30);
99         supply_register(IA64_FR16_REGNUM+15,(char*)&pcb.pcb_preserved_fp.fr31);
100
101         /* Registers 320-327: branch registers. */
102         if (pcb.pcb_special.__spare == ~0UL)
103                 supply_register(IA64_BR0_REGNUM, (char *)&pcb.pcb_special.rp);
104         supply_register(IA64_BR1_REGNUM, (char *)&pcb.pcb_preserved.br1);
105         supply_register(IA64_BR2_REGNUM, (char *)&pcb.pcb_preserved.br2);
106         supply_register(IA64_BR3_REGNUM, (char *)&pcb.pcb_preserved.br3);
107         supply_register(IA64_BR4_REGNUM, (char *)&pcb.pcb_preserved.br4);
108         supply_register(IA64_BR5_REGNUM, (char *)&pcb.pcb_preserved.br5);
109
110         /* Registers 328-333: misc. other registers. */
111         supply_register(IA64_PR_REGNUM, (char *)&pcb.pcb_special.pr);
112         if (pcb.pcb_special.__spare == ~0UL) {
113                 r = pcb.pcb_special.iip + ((pcb.pcb_special.psr >> 41) & 3);
114                 supply_register(IA64_IP_REGNUM, (char *)&r);
115                 supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.cfm);
116         } else {
117                 supply_register(IA64_IP_REGNUM, (char *)&pcb.pcb_special.rp);
118                 supply_register(IA64_CFM_REGNUM, (char *)&pcb.pcb_special.pfs);
119         }
120
121         /* Registers 334-461: application registers. */
122         supply_register(IA64_RSC_REGNUM, (char *)&pcb.pcb_special.rsc);
123         r = pcb.pcb_special.bspstore;
124         if (pcb.pcb_special.__spare == ~0UL)
125                 r += pcb.pcb_special.ndirty;
126         else
127                 r = ia64_bsp_adjust(r, IA64_CFM_SOF(pcb.pcb_special.pfs) -
128                     IA64_CFM_SOL(pcb.pcb_special.pfs));
129         supply_register(IA64_BSP_REGNUM, (char *)&r);
130         supply_register(IA64_BSPSTORE_REGNUM, (char *)&r);
131         supply_register(IA64_RNAT_REGNUM, (char *)&pcb.pcb_special.rnat);
132         supply_register(IA64_UNAT_REGNUM, (char *)&pcb.pcb_special.unat);
133         supply_register(IA64_FPSR_REGNUM, (char *)&pcb.pcb_special.fpsr);
134         if (pcb.pcb_special.__spare == ~0UL)
135                 supply_register(IA64_PFS_REGNUM, (char *)&pcb.pcb_special.pfs);
136         supply_register(IA64_LC_REGNUM, (char *)&pcb.pcb_preserved.lc);
137 }
138
139 void
140 kgdb_trgt_store_registers(int regno __unused)
141 {
142         fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
143 }
144
145 void
146 kgdb_trgt_new_objfile(struct objfile *objfile)
147 {
148 }
149
150 struct kgdb_frame_cache {
151         CORE_ADDR       bsp;
152         CORE_ADDR       ip;
153         CORE_ADDR       sp;
154         CORE_ADDR       saved_bsp;
155 };
156
157 #define SPECIAL(x)      offsetof(struct trapframe, tf_special)          \
158                         + offsetof(struct _special, x)
159 #define SCRATCH(x)      offsetof(struct trapframe, tf_scratch)          \
160                         + offsetof(struct _caller_saved, x)
161 #define SCRATCH_FP(x)   offsetof(struct trapframe, tf_scratch_fp)       \
162                         + offsetof(struct _caller_saved_fp, x)
163
164 static int kgdb_trgt_frame_ofs_gr[32] = {
165         -1,                                     /* gr0 */
166         SPECIAL(gp),
167         SCRATCH(gr2),   SCRATCH(gr3),
168         -1, -1, -1, -1,                         /* gr4-gr7 */
169         SCRATCH(gr8),   SCRATCH(gr9),   SCRATCH(gr10),  SCRATCH(gr11),
170         SPECIAL(sp),    SPECIAL(tp),
171         SCRATCH(gr14),  SCRATCH(gr15),  SCRATCH(gr16),  SCRATCH(gr17),
172         SCRATCH(gr18),  SCRATCH(gr19),  SCRATCH(gr20),  SCRATCH(gr21),
173         SCRATCH(gr22),  SCRATCH(gr23),  SCRATCH(gr24),  SCRATCH(gr25),
174         SCRATCH(gr26),  SCRATCH(gr27),  SCRATCH(gr28),  SCRATCH(gr29),
175         SCRATCH(gr30),  SCRATCH(gr31)
176 };
177
178 static int kgdb_trgt_frame_ofs_fr[32] = {
179         -1,                                     /* fr0: constant 0.0 */
180         -1,                                     /* fr1: constant 1.0 */
181         -1, -1, -1, -1,                         /* fr2-fr5 */
182         SCRATCH_FP(fr6), SCRATCH_FP(fr7), SCRATCH_FP(fr8), SCRATCH_FP(fr9),
183         SCRATCH_FP(fr10), SCRATCH_FP(fr11), SCRATCH_FP(fr12), SCRATCH_FP(fr13),
184         SCRATCH_FP(fr14), SCRATCH_FP(fr15)
185 };
186
187 static int kgdb_trgt_frame_ofs_br[8] = {
188         SPECIAL(rp),
189         -1, -1, -1, -1, -1,                     /* br1-br5 */
190         SCRATCH(br6), SCRATCH(br7)
191 };
192
193 static int kgdb_trgt_frame_ofs_ar[49] = {
194         /* ar0-ar15 */
195         SPECIAL(rsc),
196         -1,                                     /* ar.bsp */
197         SPECIAL(bspstore), SPECIAL(rnat),
198         -1, -1, -1, -1, -1,                     /* ar20-ar24 */
199         SCRATCH(csd), SCRATCH(ssd),
200         -1, -1, -1, -1, -1,                     /* ar27-ar31 */
201         SCRATCH(ccv),
202         -1, -1, -1,                             /* ar33-ar35 */
203         SPECIAL(unat),
204         -1, -1, -1,                             /* ar37-ar39 */
205         SPECIAL(fpsr),
206         -1, -1, -1, -1, -1, -1, -1,             /* ar41-ar47 */
207         -1, -1, -1, -1, -1, -1, -1, -1,         /* ar48-ar55 */
208         -1, -1, -1, -1, -1, -1, -1, -1,         /* ar56-ar63 */
209         SPECIAL(pfs)
210 };
211
212 static struct kgdb_frame_cache *
213 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
214 {
215         char buf[MAX_REGISTER_SIZE];
216         struct kgdb_frame_cache *cache;
217
218         cache = *this_cache;
219         if (cache == NULL) {
220                 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
221                 *this_cache = cache;
222                 frame_unwind_register(next_frame, IA64_BSP_REGNUM, buf);
223                 cache->bsp = extract_unsigned_integer(buf,
224                     register_size(current_gdbarch, IA64_BSP_REGNUM));
225                 cache->ip = frame_func_unwind(next_frame);
226                 frame_unwind_register(next_frame, SP_REGNUM, buf);
227                 cache->sp = extract_unsigned_integer(buf,
228                     register_size(current_gdbarch, SP_REGNUM));
229         }
230         return (cache);
231 }
232
233 static void
234 kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache,
235     struct frame_id *this_id)
236 {
237         struct kgdb_frame_cache *cache;
238
239         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
240         *this_id = frame_id_build_special(cache->sp, cache->ip, cache->bsp);
241 }
242
243 static void
244 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
245     void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
246     CORE_ADDR *addrp, int *realnump, void *valuep)
247 {
248         char buf[MAX_REGISTER_SIZE];
249         char dummy_valuep[MAX_REGISTER_SIZE];
250         struct kgdb_frame_cache *cache;
251         CORE_ADDR bsp;
252         int ofs, regsz;
253
254         regsz = register_size(current_gdbarch, regnum);
255
256         if (valuep == NULL)
257                 valuep = dummy_valuep;
258         memset(valuep, 0, regsz);
259         *optimizedp = 0;
260         *addrp = 0;
261         *lvalp = not_lval;
262         *realnump = -1;
263
264         cache = kgdb_trgt_frame_cache(next_frame, this_cache);
265
266         if (regnum == IA64_BSP_REGNUM) {
267                 if (cache->saved_bsp == 0) {
268                         target_read_memory(cache->sp + 16 + SPECIAL(bspstore),
269                             buf, regsz);
270                         bsp = extract_unsigned_integer(buf, regsz);
271                         target_read_memory(cache->sp + 16 + SPECIAL(ndirty),
272                             buf, regsz);
273                         bsp += extract_unsigned_integer(buf, regsz);
274                         cache->saved_bsp = bsp;
275                 }
276                 store_unsigned_integer(valuep, regsz, cache->saved_bsp);
277                 return;
278         }
279         if (regnum == IA64_PR_REGNUM)
280                 ofs = SPECIAL(pr);
281         else if (regnum == IA64_IP_REGNUM)
282                 ofs = SPECIAL(iip);
283         else if (regnum == IA64_PSR_REGNUM)
284                 ofs = SPECIAL(psr);
285         else if (regnum == IA64_CFM_REGNUM)
286                 ofs = SPECIAL(cfm);
287         else if (regnum >= IA64_GR0_REGNUM && regnum <= IA64_GR31_REGNUM)
288                 ofs = kgdb_trgt_frame_ofs_gr[regnum - IA64_GR0_REGNUM];
289         else if (regnum >= IA64_FR0_REGNUM && regnum <= IA64_FR15_REGNUM)
290                 ofs = kgdb_trgt_frame_ofs_fr[regnum - IA64_FR0_REGNUM];
291         else if (regnum >= IA64_BR0_REGNUM && regnum <= IA64_BR7_REGNUM)
292                 ofs = kgdb_trgt_frame_ofs_br[regnum - IA64_BR0_REGNUM];
293         else if (regnum >= IA64_RSC_REGNUM && regnum <= IA64_PFS_REGNUM)
294                 ofs = kgdb_trgt_frame_ofs_ar[regnum - IA64_RSC_REGNUM];
295         else
296                 ofs = -1;
297         if (ofs == -1)
298                 return;
299
300         *addrp = cache->sp + 16 + ofs;
301         *lvalp = lval_memory;
302         target_read_memory(*addrp, valuep, regsz);
303 }
304
305 static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
306         UNKNOWN_FRAME,
307         &kgdb_trgt_trapframe_this_id,
308         &kgdb_trgt_trapframe_prev_register
309 };
310
311 const struct frame_unwind *
312 kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
313 {
314         char *pname;
315         CORE_ADDR ip;
316
317         ip = frame_func_unwind(next_frame);
318         pname = NULL;
319         find_pc_partial_function(ip, &pname, NULL, NULL);
320         if (pname == NULL)
321                 return (NULL);
322         if (strncmp(pname, "ivt_", 4) == 0)
323                 return (&kgdb_trgt_trapframe_unwind);
324         /* printf("%s: %lx =%s\n", __func__, ip, pname); */
325         return (NULL);
326 }