]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/usr.bin/gdb/kgdb/trgt_arm.c
Since contrib/libc++'s ancestry was never correct, subversion 1.8 and
[FreeBSD/FreeBSD.git] / gnu / usr.bin / gdb / kgdb / trgt_arm.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 #ifndef CROSS_DEBUGGER
32 #include <machine/pcb.h>
33 #include <machine/frame.h>
34 #include <machine/armreg.h>
35 #endif
36 #include <err.h>
37 #include <kvm.h>
38 #include <string.h>
39
40 #include <defs.h>
41 #include <target.h>
42 #include <gdbthread.h>
43 #include <inferior.h>
44 #include <regcache.h>
45 #include <frame-unwind.h>
46 #include <arm-tdep.h>
47
48 #include "kgdb.h"
49
50 CORE_ADDR
51 kgdb_trgt_core_pcb(u_int cpuid)
52 {
53 #ifndef CROSS_DEBUGGER
54         return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb)));
55 #else
56         return -1;
57 #endif
58 }
59
60 void
61 kgdb_trgt_fetch_registers(int regno __unused)
62 {
63 #ifndef CROSS_DEBUGGER
64         struct kthr *kt;
65         struct pcb pcb;
66         int i, reg;
67
68         kt = kgdb_thr_lookup_tid(ptid_get_pid(inferior_ptid));
69         if (kt == NULL)
70                 return;
71         if (kvm_read(kvm, kt->pcb, &pcb, sizeof(pcb)) != sizeof(pcb)) {
72                 warnx("kvm_read: %s", kvm_geterr(kvm));
73                 memset(&pcb, 0, sizeof(pcb));
74         }
75         for (i = ARM_A1_REGNUM + 4; i <= ARM_SP_REGNUM; i++) {
76                 supply_register(i, (char *)&pcb.pcb_regs.sf_r4 +
77                     (i - (ARM_A1_REGNUM + 4 )) * 4);
78         }
79         if (pcb.pcb_regs.sf_sp != 0) {
80                 if (kvm_read(kvm, pcb.pcb_regs.sf_sp + 4 * 4, &reg, 4) != 4)
81                         warnx("kvm_read :%s", kvm_geterr(kvm));
82                 else
83                         supply_register(ARM_PC_REGNUM, (char *)&reg);
84         }
85 #endif
86 }
87
88 void
89 kgdb_trgt_store_registers(int regno __unused)
90 {
91         fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__);
92 }
93
94 void
95 kgdb_trgt_new_objfile(struct objfile *objfile)
96 {
97 }
98
99 #ifndef CROSS_DEBUGGER
100 struct kgdb_frame_cache {
101         CORE_ADDR       fp;
102         CORE_ADDR       sp;
103 };
104
105 static int kgdb_trgt_frame_offset[26] = {
106         offsetof(struct trapframe, tf_r0),
107         offsetof(struct trapframe, tf_r1),
108         offsetof(struct trapframe, tf_r2),
109         offsetof(struct trapframe, tf_r3),
110         offsetof(struct trapframe, tf_r4),
111         offsetof(struct trapframe, tf_r5),
112         offsetof(struct trapframe, tf_r6),
113         offsetof(struct trapframe, tf_r7),
114         offsetof(struct trapframe, tf_r8),
115         offsetof(struct trapframe, tf_r9),
116         offsetof(struct trapframe, tf_r10),
117         offsetof(struct trapframe, tf_r11),
118         offsetof(struct trapframe, tf_r12),
119         offsetof(struct trapframe, tf_svc_sp),
120         offsetof(struct trapframe, tf_svc_lr),
121         offsetof(struct trapframe, tf_pc),
122         -1, -1, -1, -1, -1, -1, -1, -1, -1,
123         offsetof(struct trapframe, tf_spsr)
124 };
125
126 static struct kgdb_frame_cache *
127 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
128 {
129         char buf[MAX_REGISTER_SIZE];
130         struct kgdb_frame_cache *cache;
131
132         cache = *this_cache;
133         if (cache == NULL) {
134                 cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
135                 *this_cache = cache;
136                 frame_unwind_register(next_frame, ARM_SP_REGNUM, buf);
137                 cache->sp = extract_unsigned_integer(buf,
138                     register_size(current_gdbarch, ARM_SP_REGNUM));
139                 frame_unwind_register(next_frame, ARM_FP_REGNUM, buf);
140                 cache->fp = extract_unsigned_integer(buf,
141                     register_size(current_gdbarch, ARM_FP_REGNUM));
142         }
143         return (cache);
144 }
145
146 static int is_undef;
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->fp, 0);
156 }
157
158 static void
159 kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
160     void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp,
161     CORE_ADDR *addrp, int *realnump, void *valuep)
162 {
163         char dummy_valuep[MAX_REGISTER_SIZE];
164         struct kgdb_frame_cache *cache;
165         int ofs, regsz;
166         int is_undefined = 0;
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 <= ARM_PS_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
185         if (is_undef && (regnum == ARM_SP_REGNUM || regnum == ARM_PC_REGNUM)) {
186                 *addrp = cache->sp + offsetof(struct trapframe, tf_spsr);
187                 target_read_memory(*addrp, valuep, regsz);
188                 is_undefined = 1;
189                 ofs = kgdb_trgt_frame_offset[ARM_SP_REGNUM];
190
191         }
192         *addrp = cache->sp + ofs;
193         *lvalp = lval_memory;
194         target_read_memory(*addrp, valuep, regsz);
195
196         if (is_undefined) {
197                 *addrp = *(unsigned int *)valuep + (regnum == ARM_SP_REGNUM ?
198                     0 : 8);
199                 target_read_memory(*addrp, valuep, regsz);
200
201         }
202 }
203
204 static const struct frame_unwind kgdb_trgt_trapframe_unwind = {
205         UNKNOWN_FRAME,
206         &kgdb_trgt_trapframe_this_id,
207         &kgdb_trgt_trapframe_prev_register
208 };
209 #endif
210
211 const struct frame_unwind *
212 kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame)
213 {
214 #ifndef CROSS_DEBUGGER
215         char *pname;
216         CORE_ADDR pc;
217
218         pc = frame_pc_unwind(next_frame);
219         pname = NULL;
220         find_pc_partial_function(pc, &pname, NULL, NULL);
221         if (pname == NULL) {
222                 is_undef = 0;
223                 return (NULL);
224         }
225         if (!strcmp(pname, "undefinedinstruction"))
226                 is_undef = 1;
227         if (strcmp(pname, "Laddress_exception_entry") == 0 ||
228             strcmp(pname, "undefined_entry") == 0 ||
229             strcmp(pname, "exception_exit") == 0 ||
230             strcmp(pname, "Laddress_exception_msg") == 0 ||
231             strcmp(pname, "irq_entry") == 0)
232                 return (&kgdb_trgt_trapframe_unwind);
233         if (!strcmp(pname, "undefinedinstruction"))
234                 is_undef = 1;
235         else
236                 is_undef = 0;
237 #endif
238         return (NULL);
239 }