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: head/devel/gdb/files/kgdb/i386fbsd-kern.c 480613 2018-09-24 17:23:35Z jhb $"); |
29 |
|
30 |
#include "defs.h" |
31 |
#include "frame-unwind.h" |
32 |
#include "gdbcore.h" |
33 |
#include "inferior.h" |
34 |
#include "osabi.h" |
35 |
#include "regcache.h" |
36 |
#include "progspace.h" |
37 |
#include "solib.h" |
38 |
#include "trad-frame.h" |
39 |
#include "i386-tdep.h" |
40 |
|
41 |
#ifdef __i386__ |
42 |
#include <sys/proc.h> |
43 |
#include <machine/pcb.h> |
44 |
#include <machine/frame.h> |
45 |
#include <machine/segments.h> |
46 |
#include <machine/tss.h> |
47 |
#endif |
48 |
|
49 |
#include "kgdb.h" |
50 |
|
51 |
struct i386fbsd_info { |
52 |
int ofs_fix; |
53 |
}; |
54 |
|
55 |
/* Per-program-space data key. */ |
56 |
static const struct program_space_data *i386fbsd_pspace_data; |
57 |
|
58 |
static void |
59 |
i386fbsd_pspace_data_cleanup (struct program_space *pspace, void *arg) |
60 |
{ |
61 |
struct i386fbsd_info *info = (struct i386fbsd_info *)arg; |
62 |
|
63 |
xfree (info); |
64 |
} |
65 |
|
66 |
/* Get the current i386fbsd data. If none is found yet, add it now. This |
67 |
function always returns a valid object. */ |
68 |
|
69 |
static struct i386fbsd_info * |
70 |
get_i386fbsd_info (void) |
71 |
{ |
72 |
struct i386fbsd_info *info; |
73 |
|
74 |
info = (struct i386fbsd_info *) |
75 |
program_space_data (current_program_space, i386fbsd_pspace_data); |
76 |
if (info != NULL) |
77 |
return info; |
78 |
|
79 |
info = XCNEW (struct i386fbsd_info); |
80 |
set_program_space_data (current_program_space, i386fbsd_pspace_data, info); |
81 |
|
82 |
/* |
83 |
* In revision 1.117 of i386/i386/exception.S trap handlers |
84 |
* were changed to pass trapframes by reference rather than |
85 |
* by value. Detect this by seeing if the first instruction |
86 |
* at the 'calltrap' label is a "push %esp" which has the |
87 |
* opcode 0x54. |
88 |
*/ |
89 |
if (parse_and_eval_long("((char *)calltrap)[0]") == 0x54) |
90 |
info->ofs_fix = 4; |
91 |
else |
92 |
info->ofs_fix = 0; |
93 |
return info; |
94 |
} |
95 |
|
96 |
/* |
97 |
* Even though the pcb contains fields for the segment selectors, only |
98 |
* %gs is updated on each context switch. The other selectors are |
99 |
* saved in stoppcbs[], but we just hardcode their known values rather |
100 |
* than handling that special case. |
101 |
*/ |
102 |
static const int i386fbsd_pcb_offset[] = { |
103 |
-1, /* %eax */ |
104 |
-1, /* %ecx */ |
105 |
-1, /* %edx */ |
106 |
4 * 4, /* %ebx */ |
107 |
3 * 4, /* %esp */ |
108 |
2 * 4, /* %ebp */ |
109 |
1 * 4, /* %esi */ |
110 |
0 * 4, /* %edi */ |
111 |
5 * 4, /* %eip */ |
112 |
-1, /* %eflags */ |
113 |
-1, /* %cs */ |
114 |
-1, /* %ss */ |
115 |
-1, /* %ds */ |
116 |
-1, /* %es */ |
117 |
-1, /* %fs */ |
118 |
-1, /* %gs */ |
119 |
}; |
120 |
|
121 |
#define CODE_SEL (4 << 3) |
122 |
#define DATA_SEL (5 << 3) |
123 |
#define PRIV_SEL (1 << 3) |
124 |
|
125 |
static void |
126 |
i386fbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr) |
127 |
{ |
128 |
gdb_byte buf[4]; |
129 |
int i; |
130 |
|
131 |
memset(buf, 0, sizeof(buf)); |
132 |
|
133 |
/* |
134 |
* XXX The PCB may have been swapped out. Supply a dummy %eip value |
135 |
* so as to avoid triggering an exception during stack unwinding. |
136 |
*/ |
137 |
regcache->raw_supply(I386_EIP_REGNUM, buf); |
138 |
for (i = 0; i < ARRAY_SIZE (i386fbsd_pcb_offset); i++) |
139 |
if (i386fbsd_pcb_offset[i] != -1) { |
140 |
if (target_read_memory(pcb_addr + i386fbsd_pcb_offset[i], buf, sizeof buf) |
141 |
!= 0) |
142 |
continue; |
143 |
regcache->raw_supply(i, buf); |
144 |
} |
145 |
regcache->raw_supply_unsigned(I386_CS_REGNUM, CODE_SEL); |
146 |
regcache->raw_supply_unsigned(I386_DS_REGNUM, DATA_SEL); |
147 |
regcache->raw_supply_unsigned(I386_ES_REGNUM, DATA_SEL); |
148 |
regcache->raw_supply_unsigned(I386_FS_REGNUM, PRIV_SEL); |
149 |
regcache->raw_supply_unsigned(I386_GS_REGNUM, DATA_SEL); |
150 |
regcache->raw_supply_unsigned(I386_SS_REGNUM, DATA_SEL); |
151 |
} |
152 |
|
153 |
#ifdef __i386__ |
154 |
/* TODO: Make this cross-debugger friendly. */ |
155 |
static const int i386fbsd_tss_offset[] = { |
156 |
10 * 4, /* %eax */ |
157 |
11 * 4, /* %ecx */ |
158 |
12 * 4, /* %edx */ |
159 |
13 * 4, /* %ebx */ |
160 |
14 * 4, /* %esp */ |
161 |
15 * 4, /* %ebp */ |
162 |
16 * 4, /* %esi */ |
163 |
17 * 4, /* %edi */ |
164 |
8 * 4, /* %eip */ |
165 |
9 * 4, /* %eflags */ |
166 |
19 * 4, /* %cs */ |
167 |
20 * 4, /* %ss */ |
168 |
21 * 4, /* %ds */ |
169 |
18 * 4, /* %es */ |
170 |
22 * 4, /* %fs */ |
171 |
23 * 4, /* %gs */ |
172 |
}; |
173 |
|
174 |
/* |
175 |
* If the current thread is executing on a CPU, fetch the common_tss |
176 |
* for that CPU. |
177 |
* |
178 |
* This is painful because 'struct pcpu' is variant sized, so we can't |
179 |
* use it. Instead, we lookup the GDT selector for this CPU and |
180 |
* extract the base of the TSS from there. |
181 |
*/ |
182 |
static CORE_ADDR |
183 |
i386fbsd_fetch_tss(void) |
184 |
{ |
185 |
struct kthr *kt; |
186 |
struct segment_descriptor sd; |
187 |
CORE_ADDR addr, cpu0prvpage, tss; |
188 |
|
189 |
kt = kgdb_thr_lookup_tid(inferior_ptid.tid()); |
190 |
if (kt == NULL || kt->cpu == NOCPU || kt->cpu < 0) |
191 |
return (0); |
192 |
|
193 |
addr = kgdb_lookup("gdt"); |
194 |
if (addr == 0) |
195 |
return (0); |
196 |
addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); |
197 |
if (target_read_memory(addr, (gdb_byte *)&sd, sizeof(sd)) != 0) |
198 |
return (0); |
199 |
if (sd.sd_type != SDT_SYS386BSY) { |
200 |
warning ("descriptor is not a busy TSS"); |
201 |
return (0); |
202 |
} |
203 |
tss = sd.sd_hibase << 24 | sd.sd_lobase; |
204 |
|
205 |
/* |
206 |
* In SMP kernels, the TSS is stored as part of the per-CPU |
207 |
* data. On older kernels, the CPU0's private page |
208 |
* is stored at an address that isn't mapped in minidumps. |
209 |
* However, the data is mapped at the alternate cpu0prvpage |
210 |
* address. Thus, if the TSS is at the invalid address, |
211 |
* change it to be relative to cpu0prvpage instead. |
212 |
*/ |
213 |
if (trunc_page(tss) == 0xffc00000) { |
214 |
TRY { |
215 |
cpu0prvpage = parse_and_eval_address("cpu0prvpage"); |
216 |
} CATCH(e, RETURN_MASK_ERROR) { |
217 |
return (0); |
218 |
} END_CATCH |
219 |
tss = cpu0prvpage + (tss & PAGE_MASK); |
220 |
} |
221 |
return (tss); |
222 |
} |
223 |
|
224 |
static struct trad_frame_cache * |
225 |
i386fbsd_dblfault_cache (struct frame_info *this_frame, void **this_cache) |
226 |
{ |
227 |
struct gdbarch *gdbarch = get_frame_arch (this_frame); |
228 |
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); |
229 |
struct trad_frame_cache *cache; |
230 |
CORE_ADDR addr, func, tss; |
231 |
int i; |
232 |
|
233 |
if (*this_cache != NULL) |
234 |
return (struct trad_frame_cache *)(*this_cache); |
235 |
|
236 |
cache = trad_frame_cache_zalloc (this_frame); |
237 |
*this_cache = cache; |
238 |
|
239 |
func = get_frame_func (this_frame); |
240 |
tss = i386fbsd_fetch_tss (); |
241 |
|
242 |
for (i = 0; i < ARRAY_SIZE (i386fbsd_tss_offset); i++) |
243 |
if (i386fbsd_tss_offset[i] != -1) |
244 |
trad_frame_set_reg_addr (cache, i, tss + i386fbsd_tss_offset[i]); |
245 |
|
246 |
/* Construct the frame ID using the function start. */ |
247 |
/* XXX: Stack address should be dbfault_stack + PAGE_SIZE. */ |
248 |
trad_frame_set_id (cache, frame_id_build (tss + sizeof(struct i386tss), |
249 |
func)); |
250 |
|
251 |
return cache; |
252 |
} |
253 |
|
254 |
static void |
255 |
i386fbsd_dblfault_this_id (struct frame_info *this_frame, |
256 |
void **this_cache, struct frame_id *this_id) |
257 |
{ |
258 |
struct trad_frame_cache *cache = |
259 |
i386fbsd_dblfault_cache (this_frame, this_cache); |
260 |
|
261 |
trad_frame_get_id (cache, this_id); |
262 |
} |
263 |
|
264 |
static struct value * |
265 |
i386fbsd_dblfault_prev_register (struct frame_info *this_frame, |
266 |
void **this_cache, int regnum) |
267 |
{ |
268 |
struct trad_frame_cache *cache = |
269 |
i386fbsd_dblfault_cache (this_frame, this_cache); |
270 |
|
271 |
return trad_frame_get_register (cache, this_frame, regnum); |
272 |
} |
273 |
|
274 |
static int |
275 |
i386fbsd_dblfault_sniffer (const struct frame_unwind *self, |
276 |
struct frame_info *this_frame, |
277 |
void **this_prologue_cache) |
278 |
{ |
279 |
const char *name; |
280 |
|
281 |
find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); |
282 |
return (name && strcmp (name, "dblfault_handler") == 0); |
283 |
} |
284 |
|
285 |
static const struct frame_unwind i386fbsd_dblfault_unwind = { |
286 |
SIGTRAMP_FRAME, |
287 |
default_frame_unwind_stop_reason, |
288 |
i386fbsd_dblfault_this_id, |
289 |
i386fbsd_dblfault_prev_register, |
290 |
NULL, |
291 |
i386fbsd_dblfault_sniffer |
292 |
}; |
293 |
#endif |
294 |
|
295 |
static const int i386fbsd_trapframe_offset[] = { |
296 |
10 * 4, /* %eax */ |
297 |
9 * 4, /* %ecx */ |
298 |
8 * 4, /* %edx */ |
299 |
7 * 4, /* %ebx */ |
300 |
16 * 4, /* %esp */ |
301 |
5 * 4, /* %ebp */ |
302 |
4 * 4, /* %esi */ |
303 |
3 * 4, /* %edi */ |
304 |
13 * 4, /* %eip */ |
305 |
15 * 4, /* %eflags */ |
306 |
14 * 4, /* %cs */ |
307 |
17 * 4, /* %ss */ |
308 |
2 * 4, /* %ds */ |
309 |
1 * 4, /* %es */ |
310 |
0 * 4, /* %fs */ |
311 |
-1 /* %gs */ |
312 |
}; |
313 |
|
314 |
#define TRAPFRAME_SIZE 72 |
315 |
|
316 |
static struct trad_frame_cache * |
317 |
i386fbsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) |
318 |
{ |
319 |
struct gdbarch *gdbarch = get_frame_arch (this_frame); |
320 |
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); |
321 |
struct trad_frame_cache *cache; |
322 |
struct i386fbsd_info *info; |
323 |
CORE_ADDR addr, cs, func, pc, sp; |
324 |
const char *name; |
325 |
int i; |
326 |
|
327 |
if (*this_cache != NULL) |
328 |
return ((struct trad_frame_cache *)*this_cache); |
329 |
|
330 |
info = get_i386fbsd_info(); |
331 |
cache = trad_frame_cache_zalloc (this_frame); |
332 |
*this_cache = cache; |
333 |
|
334 |
func = get_frame_func (this_frame); |
335 |
sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); |
336 |
|
337 |
find_pc_partial_function (func, &name, NULL, NULL); |
338 |
if (strcmp(name, "calltrap") == 0 || |
339 |
strcmp(name, "Xlcall_syscall") == 0 || |
340 |
strcmp(name, "Xint0x80_syscall") == 0) |
341 |
/* Traps in later kernels pass the trap frame by reference. */ |
342 |
sp += info->ofs_fix; |
343 |
else if (strcmp(name, "Xtimerint") == 0) |
344 |
/* Timer interrupts also pass the trap frame by reference. */ |
345 |
sp += info->ofs_fix; |
346 |
else if (strcmp(name, "Xcpustop") == 0 || |
347 |
strcmp(name, "Xrendezvous") == 0 || |
348 |
strcmp(name, "Xipi_intr_bitmap_handler") == 0 || |
349 |
strcmp(name, "Xlazypmap") == 0) |
350 |
/* These handlers push a trap frame only. */ |
351 |
; |
352 |
else if (strcmp(name, "fork_trampoline") == 0) |
353 |
if (get_frame_pc (this_frame) == func) |
354 |
{ |
355 |
/* fork_exit hasn't been called (kthread has never run), so |
356 |
%esp in the pcb points to the word above the trapframe. */ |
357 |
sp += 4; |
358 |
} |
359 |
else |
360 |
{ |
361 |
/* fork_exit has been called, so %esp in fork_exit's |
362 |
frame is &tf - 12. */ |
363 |
sp += 12; |
364 |
} |
365 |
else { |
366 |
/* Interrupt frames pass the IDT vector in addition to the trap frame. */ |
367 |
sp += info->ofs_fix + 4; |
368 |
} |
369 |
|
370 |
addr = sp + i386fbsd_trapframe_offset[I386_CS_REGNUM]; |
371 |
cs = read_memory_unsigned_integer (addr, 4, byte_order); |
372 |
for (i = 0; i < ARRAY_SIZE (i386fbsd_trapframe_offset); i++) |
373 |
{ |
374 |
/* %ss/%esp are only present in the trapframe for a trap from |
375 |
userland. */ |
376 |
if ((cs & I386_SEL_RPL) == I386_SEL_KPL) |
377 |
{ |
378 |
if (i == I386_SS_REGNUM) |
379 |
continue; |
380 |
if (i == I386_ESP_REGNUM) |
381 |
{ |
382 |
trad_frame_set_reg_value (cache, i, sp + TRAPFRAME_SIZE - 8); |
383 |
continue; |
384 |
} |
385 |
} |
386 |
if (i386fbsd_trapframe_offset[i] != -1) |
387 |
trad_frame_set_reg_addr (cache, i, sp + i386fbsd_trapframe_offset[i]); |
388 |
} |
389 |
|
390 |
/* Read %eip from trap frame. */ |
391 |
addr = sp + i386fbsd_trapframe_offset[I386_EIP_REGNUM]; |
392 |
pc = read_memory_unsigned_integer (addr, 4, byte_order); |
393 |
|
394 |
if (pc == 0 && strcmp(name, "fork_trampoline") == 0) |
395 |
{ |
396 |
/* Initial frame of a kthread; terminate backtrace. */ |
397 |
trad_frame_set_id (cache, outer_frame_id); |
398 |
} |
399 |
else |
400 |
{ |
401 |
/* Construct the frame ID using the function start. */ |
402 |
sp += TRAPFRAME_SIZE; |
403 |
if ((cs & I386_SEL_RPL) == I386_SEL_KPL) |
404 |
sp -= 8; |
405 |
trad_frame_set_id (cache, frame_id_build (sp, func)); |
406 |
} |
407 |
|
408 |
return cache; |
409 |
} |
410 |
|
411 |
static void |
412 |
i386fbsd_trapframe_this_id (struct frame_info *this_frame, |
413 |
void **this_cache, struct frame_id *this_id) |
414 |
{ |
415 |
struct trad_frame_cache *cache = |
416 |
i386fbsd_trapframe_cache (this_frame, this_cache); |
417 |
|
418 |
trad_frame_get_id (cache, this_id); |
419 |
} |
420 |
|
421 |
static struct value * |
422 |
i386fbsd_trapframe_prev_register (struct frame_info *this_frame, |
423 |
void **this_cache, int regnum) |
424 |
{ |
425 |
struct trad_frame_cache *cache = |
426 |
i386fbsd_trapframe_cache (this_frame, this_cache); |
427 |
|
428 |
return trad_frame_get_register (cache, this_frame, regnum); |
429 |
} |
430 |
|
431 |
static int |
432 |
i386fbsd_trapframe_sniffer (const struct frame_unwind *self, |
433 |
struct frame_info *this_frame, |
434 |
void **this_prologue_cache) |
435 |
{ |
436 |
const char *name; |
437 |
|
438 |
find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); |
439 |
return (name && ((strcmp (name, "calltrap") == 0) |
440 |
|| (strcmp (name, "fork_trampoline") == 0) |
441 |
|| (name[0] == 'X' && name[1] != '_'))); |
442 |
} |
443 |
|
444 |
static const struct frame_unwind i386fbsd_trapframe_unwind = { |
445 |
SIGTRAMP_FRAME, |
446 |
default_frame_unwind_stop_reason, |
447 |
i386fbsd_trapframe_this_id, |
448 |
i386fbsd_trapframe_prev_register, |
449 |
NULL, |
450 |
i386fbsd_trapframe_sniffer |
451 |
}; |
452 |
|
453 |
static void |
454 |
i386fbsd_kernel_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch) |
455 |
{ |
456 |
|
457 |
i386_elf_init_abi(info, gdbarch); |
458 |
|
459 |
#ifdef __i386__ |
460 |
frame_unwind_prepend_unwinder(gdbarch, &i386fbsd_dblfault_unwind); |
461 |
#endif |
462 |
frame_unwind_prepend_unwinder(gdbarch, &i386fbsd_trapframe_unwind); |
463 |
|
464 |
set_solib_ops(gdbarch, &kld_so_ops); |
465 |
|
466 |
fbsd_vmcore_set_supply_pcb(gdbarch, i386fbsd_supply_pcb); |
467 |
fbsd_vmcore_set_cpu_pcb_addr(gdbarch, kgdb_trgt_stop_pcb); |
468 |
} |
469 |
|
470 |
void |
471 |
_initialize_i386_kgdb_tdep(void) |
472 |
{ |
473 |
/* This is used for both i386 and amd64, but amd64 always |
474 |
includes this target, so just include it here. */ |
475 |
gdbarch_register_osabi_sniffer(bfd_arch_i386, |
476 |
bfd_target_elf_flavour, |
477 |
fbsd_kernel_osabi_sniffer); |
478 |
gdbarch_register_osabi (bfd_arch_i386, 0, |
479 |
GDB_OSABI_FREEBSD_KERNEL, i386fbsd_kernel_init_abi); |
480 |
|
481 |
i386fbsd_pspace_data = register_program_space_data_with_cleanup (NULL, |
482 |
i386fbsd_pspace_data_cleanup); |
483 |
|
484 |
#ifdef __i386__ |
485 |
/* |
486 |
* FreeBSD/i386 kernels prior to the introduction of AVX |
487 |
* support used a different layout for the PCB. If gdb is |
488 |
* compiled on these systems, these asserts will fail. The |
489 |
* package builders build packages on older systems which are |
490 |
* then run on newer systems. These binaries trip over these |
491 |
* assertions even when debugging user programs and even |
492 |
* though the running kernel is new enough. To cope, disable |
493 |
* the assertion checks unless gdb is built against a new |
494 |
* enough world. Note that this means kgdb is not going to |
495 |
* parse PCBs correctly on FreeBSD/i386 kernels before AVX was |
496 |
* merged. |
497 |
*/ |
498 |
#if __FreeBSD_version >= 1001505 |
499 |
gdb_assert(offsetof(struct pcb, pcb_ebx) |
500 |
== i386fbsd_pcb_offset[I386_EBX_REGNUM]); |
501 |
gdb_assert(offsetof(struct pcb, pcb_esp) |
502 |
== i386fbsd_pcb_offset[I386_ESP_REGNUM]); |
503 |
gdb_assert(offsetof(struct pcb, pcb_ebp) |
504 |
== i386fbsd_pcb_offset[I386_EBP_REGNUM]); |
505 |
gdb_assert(offsetof(struct pcb, pcb_esi) |
506 |
== i386fbsd_pcb_offset[I386_ESI_REGNUM]); |
507 |
gdb_assert(offsetof(struct pcb, pcb_edi) |
508 |
== i386fbsd_pcb_offset[I386_EDI_REGNUM]); |
509 |
gdb_assert(offsetof(struct pcb, pcb_eip) |
510 |
== i386fbsd_pcb_offset[I386_EIP_REGNUM]); |
511 |
#endif |
512 |
gdb_assert(CODE_SEL == GSEL(GCODE_SEL, SEL_KPL)); |
513 |
gdb_assert(DATA_SEL == GSEL(GDATA_SEL, SEL_KPL)); |
514 |
gdb_assert(PRIV_SEL == GSEL(GPRIV_SEL, SEL_KPL)); |
515 |
gdb_assert(sizeof(struct trapframe) == TRAPFRAME_SIZE); |
516 |
gdb_assert(offsetof(struct trapframe, tf_eax) |
517 |
== i386fbsd_trapframe_offset[I386_EAX_REGNUM]); |
518 |
gdb_assert(offsetof(struct trapframe, tf_ecx) |
519 |
== i386fbsd_trapframe_offset[I386_ECX_REGNUM]); |
520 |
gdb_assert(offsetof(struct trapframe, tf_edx) |
521 |
== i386fbsd_trapframe_offset[I386_EDX_REGNUM]); |
522 |
gdb_assert(offsetof(struct trapframe, tf_ebx) |
523 |
== i386fbsd_trapframe_offset[I386_EBX_REGNUM]); |
524 |
gdb_assert(offsetof(struct trapframe, tf_esp) |
525 |
== i386fbsd_trapframe_offset[I386_ESP_REGNUM]); |
526 |
gdb_assert(offsetof(struct trapframe, tf_ebp) |
527 |
== i386fbsd_trapframe_offset[I386_EBP_REGNUM]); |
528 |
gdb_assert(offsetof(struct trapframe, tf_esi) |
529 |
== i386fbsd_trapframe_offset[I386_ESI_REGNUM]); |
530 |
gdb_assert(offsetof(struct trapframe, tf_edi) |
531 |
== i386fbsd_trapframe_offset[I386_EDI_REGNUM]); |
532 |
gdb_assert(offsetof(struct trapframe, tf_eip) |
533 |
== i386fbsd_trapframe_offset[I386_EIP_REGNUM]); |
534 |
gdb_assert(offsetof(struct trapframe, tf_eflags) |
535 |
== i386fbsd_trapframe_offset[I386_EFLAGS_REGNUM]); |
536 |
gdb_assert(offsetof(struct trapframe, tf_cs) |
537 |
== i386fbsd_trapframe_offset[I386_CS_REGNUM]); |
538 |
gdb_assert(offsetof(struct trapframe, tf_ss) |
539 |
== i386fbsd_trapframe_offset[I386_SS_REGNUM]); |
540 |
gdb_assert(offsetof(struct trapframe, tf_ds) |
541 |
== i386fbsd_trapframe_offset[I386_DS_REGNUM]); |
542 |
gdb_assert(offsetof(struct trapframe, tf_es) |
543 |
== i386fbsd_trapframe_offset[I386_ES_REGNUM]); |
544 |
gdb_assert(offsetof(struct trapframe, tf_fs) |
545 |
== i386fbsd_trapframe_offset[I386_FS_REGNUM]); |
546 |
|
547 |
gdb_assert(offsetof(struct i386tss, tss_eax) |
548 |
== i386fbsd_tss_offset[I386_EAX_REGNUM]); |
549 |
gdb_assert(offsetof(struct i386tss, tss_ecx) |
550 |
== i386fbsd_tss_offset[I386_ECX_REGNUM]); |
551 |
gdb_assert(offsetof(struct i386tss, tss_edx) |
552 |
== i386fbsd_tss_offset[I386_EDX_REGNUM]); |
553 |
gdb_assert(offsetof(struct i386tss, tss_ebx) |
554 |
== i386fbsd_tss_offset[I386_EBX_REGNUM]); |
555 |
gdb_assert(offsetof(struct i386tss, tss_esp) |
556 |
== i386fbsd_tss_offset[I386_ESP_REGNUM]); |
557 |
gdb_assert(offsetof(struct i386tss, tss_ebp) |
558 |
== i386fbsd_tss_offset[I386_EBP_REGNUM]); |
559 |
gdb_assert(offsetof(struct i386tss, tss_esi) |
560 |
== i386fbsd_tss_offset[I386_ESI_REGNUM]); |
561 |
gdb_assert(offsetof(struct i386tss, tss_edi) |
562 |
== i386fbsd_tss_offset[I386_EDI_REGNUM]); |
563 |
gdb_assert(offsetof(struct i386tss, tss_eip) |
564 |
== i386fbsd_tss_offset[I386_EIP_REGNUM]); |
565 |
gdb_assert(offsetof(struct i386tss, tss_eflags) |
566 |
== i386fbsd_tss_offset[I386_EFLAGS_REGNUM]); |
567 |
gdb_assert(offsetof(struct i386tss, tss_cs) |
568 |
== i386fbsd_tss_offset[I386_CS_REGNUM]); |
569 |
gdb_assert(offsetof(struct i386tss, tss_ss) |
570 |
== i386fbsd_tss_offset[I386_SS_REGNUM]); |
571 |
gdb_assert(offsetof(struct i386tss, tss_ds) |
572 |
== i386fbsd_tss_offset[I386_DS_REGNUM]); |
573 |
gdb_assert(offsetof(struct i386tss, tss_es) |
574 |
== i386fbsd_tss_offset[I386_ES_REGNUM]); |
575 |
gdb_assert(offsetof(struct i386tss, tss_fs) |
576 |
== i386fbsd_tss_offset[I386_FS_REGNUM]); |
577 |
gdb_assert(offsetof(struct i386tss, tss_gs) |
578 |
== i386fbsd_tss_offset[I386_GS_REGNUM]); |
579 |
#endif |
580 |
} |