2 * Copyright (c) 2004 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 * $FreeBSD: src/gnu/usr.bin/gdb/kgdb/trgt_i386.c,v 1.5 2005/09/11 05:36:30 marcel Exp $
27 * $DragonFly: src/gnu/usr.bin/gdb/kgdb/trgt_i386.c,v 1.5 2008/01/14 21:36:38 corecode Exp $
30 #include <sys/cdefs.h>
32 #include <sys/types.h>
33 #include <machine/thread.h>
34 #include <sys/thread.h>
35 #include <machine/pcb.h>
36 #include <machine/frame.h>
43 #include <gdbthread.h>
46 #include <frame-unwind.h>
47 #include <i386-tdep.h>
52 kgdb_trgt_fetch_registers(struct regcache
*regcache
, int regno
)
57 kt
= kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid
));
59 regcache_raw_supply(regcache
, regno
, NULL
);
64 * kt->pcb == NULL is a marker for "non-dumping kernel thread".
66 if (kt
->pcb
== NULL
) {
71 addr
= kt
->kaddr
+ offsetof(struct thread
, td_sp
);
72 kvm_read(kvm
, addr
, &sp
, sizeof(sp
));
83 if (kvm_read(kvm
, sp
+ 2 * sizeof(regs
[0]), regs
, sizeof(regs
)) != sizeof(regs
)) {
84 warnx("kvm_read: %s", kvm_geterr(kvm
));
85 memset(regs
, 0, sizeof(regs
));
87 regcache_raw_supply(regcache
, I386_EDI_REGNUM
, ®s
[0]);
88 regcache_raw_supply(regcache
, I386_ESI_REGNUM
, ®s
[1]);
89 regcache_raw_supply(regcache
, I386_EBX_REGNUM
, ®s
[2]);
90 regcache_raw_supply(regcache
, I386_EBP_REGNUM
, ®s
[3]);
91 regcache_raw_supply(regcache
, I386_EIP_REGNUM
, ®s
[4]);
92 sp
+= 7 * sizeof(regs
[0]);
93 regcache_raw_supply(regcache
, I386_ESP_REGNUM
, &sp
);
97 if (kvm_read(kvm
, kt
->pcb
, &pcb
, sizeof(pcb
)) != sizeof(pcb
)) {
98 warnx("kvm_read: %s", kvm_geterr(kvm
));
99 memset(&pcb
, 0, sizeof(pcb
));
101 regcache_raw_supply(regcache
, I386_EBX_REGNUM
, (char *)&pcb
.pcb_ebx
);
102 regcache_raw_supply(regcache
, I386_ESP_REGNUM
, (char *)&pcb
.pcb_esp
);
103 regcache_raw_supply(regcache
, I386_EBP_REGNUM
, (char *)&pcb
.pcb_ebp
);
104 regcache_raw_supply(regcache
, I386_ESI_REGNUM
, (char *)&pcb
.pcb_esi
);
105 regcache_raw_supply(regcache
, I386_EDI_REGNUM
, (char *)&pcb
.pcb_edi
);
106 regcache_raw_supply(regcache
, I386_EIP_REGNUM
, (char *)&pcb
.pcb_eip
);
110 kgdb_trgt_store_registers(struct regcache
*regcache
, int regno __unused
)
112 fprintf_unfiltered(gdb_stderr
, "XXX: %s\n", __func__
);
115 struct kgdb_frame_cache
{
121 static int kgdb_trgt_frame_offset
[15] = {
122 offsetof(struct trapframe
, tf_eax
),
123 offsetof(struct trapframe
, tf_ecx
),
124 offsetof(struct trapframe
, tf_edx
),
125 offsetof(struct trapframe
, tf_ebx
),
126 offsetof(struct trapframe
, tf_esp
),
127 offsetof(struct trapframe
, tf_ebp
),
128 offsetof(struct trapframe
, tf_esi
),
129 offsetof(struct trapframe
, tf_edi
),
130 offsetof(struct trapframe
, tf_eip
),
131 offsetof(struct trapframe
, tf_eflags
),
132 offsetof(struct trapframe
, tf_cs
),
133 offsetof(struct trapframe
, tf_ss
),
134 offsetof(struct trapframe
, tf_ds
),
135 offsetof(struct trapframe
, tf_es
),
136 offsetof(struct trapframe
, tf_fs
)
139 static struct kgdb_frame_cache
*
140 kgdb_trgt_frame_cache(struct frame_info
*next_frame
, void **this_cache
)
142 char buf
[MAX_REGISTER_SIZE
];
143 struct kgdb_frame_cache
*cache
;
148 cache
= FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache
);
150 cache
->pc
= get_frame_address_in_block(next_frame
);
151 find_pc_partial_function(cache
->pc
, &pname
, NULL
, NULL
);
154 * Handle weird trapframe cases:
156 * 4 for pushed esp (IN the function!)
157 * + 8 for cpl/intno (IN the function, only intrs)
159 cache
->intrframe
= 4;
161 cache
->intrframe
+= offsetof(struct intrframe
, if_esp
) -
162 offsetof(struct trapframe
, tf_esp
);
164 frame_unwind_register(next_frame
, I386_ESP_REGNUM
, buf
);
165 cache
->sp
= extract_unsigned_integer(buf
,
166 register_size(current_gdbarch
, I386_ESP_REGNUM
));
172 kgdb_trgt_trapframe_this_id(struct frame_info
*next_frame
, void **this_cache
,
173 struct frame_id
*this_id
)
175 struct kgdb_frame_cache
*cache
;
177 cache
= kgdb_trgt_frame_cache(next_frame
, this_cache
);
178 *this_id
= frame_id_build(cache
->sp
, cache
->pc
);
182 kgdb_trgt_trapframe_prev_register(struct frame_info
*next_frame
,
183 void **this_cache
, int regnum
, int *optimizedp
, enum lval_type
*lvalp
,
184 CORE_ADDR
*addrp
, int *realnump
, gdb_byte
*valuep
)
186 char dummy_valuep
[MAX_REGISTER_SIZE
];
187 struct kgdb_frame_cache
*cache
;
190 regsz
= register_size(current_gdbarch
, regnum
);
193 valuep
= dummy_valuep
;
194 memset(valuep
, 0, regsz
);
200 if (regnum
< I386_EAX_REGNUM
|| regnum
> I386_FS_REGNUM
)
203 cache
= kgdb_trgt_frame_cache(next_frame
, this_cache
);
205 ofs
= kgdb_trgt_frame_offset
[regnum
];
206 *addrp
= cache
->sp
+ ofs
+ cache
->intrframe
;
209 * If we are in the kernel, we don't have esp stored in the
210 * trapframe, but we can calculate it simply by subtracting
211 * the size of the frame.
213 if (regnum
== I386_ESP_REGNUM
) {
216 frame_unwind_register(next_frame
, I386_CS_REGNUM
, buf
);
217 if (extract_unsigned_integer(buf
, 4) != SEL_UPL
) {
218 store_unsigned_integer(valuep
, regsz
, *addrp
);
223 *lvalp
= lval_memory
;
224 target_read_memory(*addrp
, valuep
, regsz
);
228 kgdb_trgt_trapframe_sniffer(const struct frame_unwind
*self
,
229 struct frame_info
*next_frame
,
230 void **this_prologue_cache
)
235 pc
= frame_unwind_address_in_block(next_frame
, NORMAL_FRAME
);
237 find_pc_partial_function(pc
, &pname
, NULL
, NULL
);
240 if (strcmp(pname
, "calltrap") == 0 ||
241 strcmp(pname
, "dblfault_handler") == 0 ||
242 (pname
[0] == 'X' && pname
[1] != '_'))
244 /* printf("%s: %llx =%s\n", __func__, pc, pname); */
248 const struct frame_unwind kgdb_trgt_trapframe_unwind
= {
250 &kgdb_trgt_trapframe_this_id
,
251 &kgdb_trgt_trapframe_prev_register
,
252 .sniffer
= kgdb_trgt_trapframe_sniffer