Changeset View
Changeset View
Standalone View
Standalone View
head/devel/gdb/files/kgdb/i386fbsd-kern.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/* | |||||
* Copyright (c) 2004 Marcel Moolenaar | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/proc.h> | |||||
#ifdef __i386__ | |||||
#include <machine/pcb.h> | |||||
#include <machine/frame.h> | |||||
#include <machine/segments.h> | |||||
#include <machine/tss.h> | |||||
#endif | |||||
#include <string.h> | |||||
#include <defs.h> | |||||
#include <frame-unwind.h> | |||||
#include "gdbcore.h" | |||||
#include <inferior.h> | |||||
#include "osabi.h" | |||||
#include <regcache.h> | |||||
#include "progspace.h" | |||||
#include "solib.h" | |||||
#include "trad-frame.h" | |||||
#include <i386-tdep.h> | |||||
#include "kgdb.h" | |||||
struct i386fbsd_info { | |||||
int ofs_fix; | |||||
}; | |||||
/* Per-program-space data key. */ | |||||
static const struct program_space_data *i386fbsd_pspace_data; | |||||
static void | |||||
i386fbsd_pspace_data_cleanup (struct program_space *pspace, void *arg) | |||||
{ | |||||
struct i386fbsd_info *info = arg; | |||||
xfree (info); | |||||
} | |||||
/* Get the current i386fbsd data. If none is found yet, add it now. This | |||||
function always returns a valid object. */ | |||||
static struct i386fbsd_info * | |||||
get_i386fbsd_info (void) | |||||
{ | |||||
struct i386fbsd_info *info; | |||||
info = program_space_data (current_program_space, i386fbsd_pspace_data); | |||||
if (info != NULL) | |||||
return info; | |||||
info = XCNEW (struct i386fbsd_info); | |||||
set_program_space_data (current_program_space, i386fbsd_pspace_data, info); | |||||
/* | |||||
* In revision 1.117 of i386/i386/exception.S trap handlers | |||||
* were changed to pass trapframes by reference rather than | |||||
* by value. Detect this by seeing if the first instruction | |||||
* at the 'calltrap' label is a "push %esp" which has the | |||||
* opcode 0x54. | |||||
*/ | |||||
if (parse_and_eval_long("((char *)calltrap)[0]") == 0x54) | |||||
info->ofs_fix = 4; | |||||
else | |||||
info->ofs_fix = 0; | |||||
return info; | |||||
} | |||||
/* | |||||
* Even though the pcb contains fields for the segment selectors, only | |||||
* %gs is updated on each context switch. The other selectors are | |||||
* saved in stoppcbs[], but we just hardcode their known values rather | |||||
* than handling that special case. | |||||
*/ | |||||
static const int i386fbsd_pcb_offset[] = { | |||||
-1, /* %eax */ | |||||
-1, /* %ecx */ | |||||
-1, /* %edx */ | |||||
4 * 4, /* %ebx */ | |||||
3 * 4, /* %esp */ | |||||
2 * 4, /* %ebp */ | |||||
1 * 4, /* %esi */ | |||||
0 * 4, /* %edi */ | |||||
5 * 4, /* %eip */ | |||||
-1, /* %eflags */ | |||||
-1, /* %cs */ | |||||
-1, /* %ss */ | |||||
-1, /* %ds */ | |||||
-1, /* %es */ | |||||
-1, /* %fs */ | |||||
-1, /* %gs */ | |||||
}; | |||||
#define CODE_SEL (4 << 3) | |||||
#define DATA_SEL (5 << 3) | |||||
#define PRIV_SEL (1 << 3) | |||||
static void | |||||
i386fbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr) | |||||
{ | |||||
gdb_byte buf[4]; | |||||
int i; | |||||
for (i = 0; i < ARRAY_SIZE (i386fbsd_pcb_offset); i++) | |||||
if (i386fbsd_pcb_offset[i] != -1) { | |||||
if (target_read_memory(pcb_addr + i386fbsd_pcb_offset[i], buf, sizeof buf) | |||||
!= 0) | |||||
continue; | |||||
regcache_raw_supply(regcache, i, buf); | |||||
} | |||||
regcache_raw_supply_unsigned(regcache, I386_CS_REGNUM, CODE_SEL); | |||||
regcache_raw_supply_unsigned(regcache, I386_DS_REGNUM, DATA_SEL); | |||||
regcache_raw_supply_unsigned(regcache, I386_ES_REGNUM, DATA_SEL); | |||||
regcache_raw_supply_unsigned(regcache, I386_FS_REGNUM, PRIV_SEL); | |||||
regcache_raw_supply_unsigned(regcache, I386_GS_REGNUM, DATA_SEL); | |||||
regcache_raw_supply_unsigned(regcache, I386_SS_REGNUM, DATA_SEL); | |||||
} | |||||
#ifdef __i386__ | |||||
/* TODO: Make this cross-debugger friendly. */ | |||||
static const int i386fbsd_tss_offset[] = { | |||||
10 * 4, /* %eax */ | |||||
11 * 4, /* %ecx */ | |||||
12 * 4, /* %edx */ | |||||
13 * 4, /* %ebx */ | |||||
14 * 4, /* %esp */ | |||||
15 * 4, /* %ebp */ | |||||
16 * 4, /* %esi */ | |||||
17 * 4, /* %edi */ | |||||
8 * 4, /* %eip */ | |||||
9 * 4, /* %eflags */ | |||||
19 * 4, /* %cs */ | |||||
20 * 4, /* %ss */ | |||||
21 * 4, /* %ds */ | |||||
18 * 4, /* %es */ | |||||
22 * 4, /* %fs */ | |||||
23 * 4, /* %gs */ | |||||
}; | |||||
/* | |||||
* If the current thread is executing on a CPU, fetch the common_tss | |||||
* for that CPU. | |||||
* | |||||
* This is painful because 'struct pcpu' is variant sized, so we can't | |||||
* use it. Instead, we lookup the GDT selector for this CPU and | |||||
* extract the base of the TSS from there. | |||||
*/ | |||||
static CORE_ADDR | |||||
i386fbsd_fetch_tss(void) | |||||
{ | |||||
struct kthr *kt; | |||||
struct segment_descriptor sd; | |||||
CORE_ADDR addr, cpu0prvpage, tss; | |||||
kt = kgdb_thr_lookup_tid(ptid_get_tid(inferior_ptid)); | |||||
if (kt == NULL || kt->cpu == NOCPU || kt->cpu < 0) | |||||
return (0); | |||||
addr = kgdb_lookup("gdt"); | |||||
if (addr == 0) | |||||
return (0); | |||||
addr += (kt->cpu * NGDT + GPROC0_SEL) * sizeof(sd); | |||||
if (target_read_memory(addr, (void *)&sd, sizeof(sd)) != 0) | |||||
return (0); | |||||
if (sd.sd_type != SDT_SYS386BSY) { | |||||
warning ("descriptor is not a busy TSS"); | |||||
return (0); | |||||
} | |||||
tss = sd.sd_hibase << 24 | sd.sd_lobase; | |||||
/* | |||||
* In SMP kernels, the TSS is stored as part of the per-CPU | |||||
* data. On older kernels, the CPU0's private page | |||||
* is stored at an address that isn't mapped in minidumps. | |||||
* However, the data is mapped at the alternate cpu0prvpage | |||||
* address. Thus, if the TSS is at the invalid address, | |||||
* change it to be relative to cpu0prvpage instead. | |||||
*/ | |||||
if (trunc_page(tss) == 0xffc00000) { | |||||
TRY { | |||||
cpu0prvpage = parse_and_eval_address("cpu0prvpage"); | |||||
} CATCH(e, RETURN_MASK_ERROR) { | |||||
return (0); | |||||
} END_CATCH | |||||
tss = cpu0prvpage + (tss & PAGE_MASK); | |||||
} | |||||
return (tss); | |||||
} | |||||
static struct trad_frame_cache * | |||||
i386fbsd_dblfault_cache (struct frame_info *this_frame, void **this_cache) | |||||
{ | |||||
struct gdbarch *gdbarch = get_frame_arch (this_frame); | |||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | |||||
struct trad_frame_cache *cache; | |||||
CORE_ADDR addr, func, tss; | |||||
int i; | |||||
if (*this_cache != NULL) | |||||
return (*this_cache); | |||||
cache = trad_frame_cache_zalloc (this_frame); | |||||
*this_cache = cache; | |||||
func = get_frame_func (this_frame); | |||||
tss = i386fbsd_fetch_tss (); | |||||
for (i = 0; i < ARRAY_SIZE (i386fbsd_tss_offset); i++) | |||||
if (i386fbsd_tss_offset[i] != -1) | |||||
trad_frame_set_reg_addr (cache, i, tss + i386fbsd_tss_offset[i]); | |||||
/* Construct the frame ID using the function start. */ | |||||
/* XXX: Stack address should be dbfault_stack + PAGE_SIZE. */ | |||||
trad_frame_set_id (cache, frame_id_build (tss + sizeof(struct i386tss), | |||||
func)); | |||||
return cache; | |||||
} | |||||
static void | |||||
i386fbsd_dblfault_this_id (struct frame_info *this_frame, | |||||
void **this_cache, struct frame_id *this_id) | |||||
{ | |||||
struct trad_frame_cache *cache = | |||||
i386fbsd_dblfault_cache (this_frame, this_cache); | |||||
trad_frame_get_id (cache, this_id); | |||||
} | |||||
static struct value * | |||||
i386fbsd_dblfault_prev_register (struct frame_info *this_frame, | |||||
void **this_cache, int regnum) | |||||
{ | |||||
struct trad_frame_cache *cache = | |||||
i386fbsd_dblfault_cache (this_frame, this_cache); | |||||
return trad_frame_get_register (cache, this_frame, regnum); | |||||
} | |||||
static int | |||||
i386fbsd_dblfault_sniffer (const struct frame_unwind *self, | |||||
struct frame_info *this_frame, | |||||
void **this_prologue_cache) | |||||
{ | |||||
const char *name; | |||||
find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); | |||||
return (name && strcmp (name, "dblfault_handler") == 0); | |||||
} | |||||
static const struct frame_unwind i386fbsd_dblfault_unwind = { | |||||
NORMAL_FRAME, | |||||
default_frame_unwind_stop_reason, | |||||
i386fbsd_dblfault_this_id, | |||||
i386fbsd_dblfault_prev_register, | |||||
NULL, | |||||
i386fbsd_dblfault_sniffer | |||||
}; | |||||
#endif | |||||
static const int i386fbsd_trapframe_offset[] = { | |||||
10 * 4, /* %eax */ | |||||
9 * 4, /* %ecx */ | |||||
8 * 4, /* %edx */ | |||||
7 * 4, /* %ebx */ | |||||
16 * 4, /* %esp */ | |||||
5 * 4, /* %ebp */ | |||||
4 * 4, /* %esi */ | |||||
3 * 4, /* %edi */ | |||||
13 * 4, /* %eip */ | |||||
15 * 4, /* %eflags */ | |||||
14 * 4, /* %cs */ | |||||
17 * 4, /* %ss */ | |||||
2 * 4, /* %ds */ | |||||
1 * 4, /* %es */ | |||||
0 * 4, /* %fs */ | |||||
-1 /* %gs */ | |||||
}; | |||||
#define TRAPFRAME_SIZE 72 | |||||
static struct trad_frame_cache * | |||||
i386fbsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) | |||||
{ | |||||
struct gdbarch *gdbarch = get_frame_arch (this_frame); | |||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | |||||
struct trad_frame_cache *cache; | |||||
struct i386fbsd_info *info; | |||||
CORE_ADDR addr, cs, func, pc, sp; | |||||
const char *name; | |||||
int i; | |||||
if (*this_cache != NULL) | |||||
return (*this_cache); | |||||
info = get_i386fbsd_info(); | |||||
cache = trad_frame_cache_zalloc (this_frame); | |||||
*this_cache = cache; | |||||
func = get_frame_func (this_frame); | |||||
sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); | |||||
find_pc_partial_function (func, &name, NULL, NULL); | |||||
if (strcmp(name, "calltrap") == 0 || | |||||
strcmp(name, "Xlcall_syscall") == 0 || | |||||
strcmp(name, "Xint0x80_syscall") == 0) | |||||
/* Traps in later kernels pass the trap frame by reference. */ | |||||
sp += info->ofs_fix; | |||||
else if (strcmp(name, "Xtimerint") == 0) | |||||
/* Timer interrupts also pass the trap frame by reference. */ | |||||
sp += info->ofs_fix; | |||||
else if (strcmp(name, "Xcpustop") == 0 || | |||||
strcmp(name, "Xrendezvous") == 0 || | |||||
strcmp(name, "Xipi_intr_bitmap_handler") == 0 || | |||||
strcmp(name, "Xlazypmap") == 0) | |||||
/* These handlers push a trap frame only. */ | |||||
; | |||||
else if (strcmp(name, "fork_trampoline") == 0) | |||||
if (get_frame_pc (this_frame) == func) | |||||
{ | |||||
/* fork_exit hasn't been called (kthread has never run), so | |||||
%esp in the pcb points to the word above the trapframe. */ | |||||
sp += 4; | |||||
} | |||||
else | |||||
{ | |||||
/* fork_exit has been called, so %esp in fork_exit's | |||||
frame is &tf - 12. */ | |||||
sp += 12; | |||||
} | |||||
else { | |||||
/* Interrupt frames pass the IDT vector in addition to the trap frame. */ | |||||
sp += info->ofs_fix + 4; | |||||
} | |||||
addr = sp + i386fbsd_trapframe_offset[I386_CS_REGNUM]; | |||||
cs = read_memory_unsigned_integer (addr, 4, byte_order); | |||||
for (i = 0; i < ARRAY_SIZE (i386fbsd_trapframe_offset); i++) | |||||
{ | |||||
/* %ss/%esp are only present in the trapframe for a trap from | |||||
userland. */ | |||||
if ((cs & I386_SEL_RPL) == I386_SEL_KPL) | |||||
{ | |||||
if (i == I386_SS_REGNUM) | |||||
continue; | |||||
if (i == I386_ESP_REGNUM) | |||||
{ | |||||
trad_frame_set_reg_value (cache, i, sp + TRAPFRAME_SIZE - 8); | |||||
continue; | |||||
} | |||||
} | |||||
if (i386fbsd_trapframe_offset[i] != -1) | |||||
trad_frame_set_reg_addr (cache, i, sp + i386fbsd_trapframe_offset[i]); | |||||
} | |||||
/* Read %eip from trap frame. */ | |||||
addr = sp + i386fbsd_trapframe_offset[I386_EIP_REGNUM]; | |||||
pc = read_memory_unsigned_integer (addr, 4, byte_order); | |||||
if (pc == 0 && strcmp(name, "fork_trampoline") == 0) | |||||
{ | |||||
/* Initial frame of a kthread; terminate backtrace. */ | |||||
trad_frame_set_id (cache, outer_frame_id); | |||||
} | |||||
else | |||||
{ | |||||
/* Construct the frame ID using the function start. */ | |||||
sp += TRAPFRAME_SIZE; | |||||
if ((cs & I386_SEL_RPL) == I386_SEL_KPL) | |||||
sp -= 8; | |||||
trad_frame_set_id (cache, frame_id_build (sp, func)); | |||||
} | |||||
return cache; | |||||
} | |||||
static void | |||||
i386fbsd_trapframe_this_id (struct frame_info *this_frame, | |||||
void **this_cache, struct frame_id *this_id) | |||||
{ | |||||
struct trad_frame_cache *cache = | |||||
i386fbsd_trapframe_cache (this_frame, this_cache); | |||||
trad_frame_get_id (cache, this_id); | |||||
} | |||||
static struct value * | |||||
i386fbsd_trapframe_prev_register (struct frame_info *this_frame, | |||||
void **this_cache, int regnum) | |||||
{ | |||||
struct trad_frame_cache *cache = | |||||
i386fbsd_trapframe_cache (this_frame, this_cache); | |||||
return trad_frame_get_register (cache, this_frame, regnum); | |||||
} | |||||
static int | |||||
i386fbsd_trapframe_sniffer (const struct frame_unwind *self, | |||||
struct frame_info *this_frame, | |||||
void **this_prologue_cache) | |||||
{ | |||||
const char *name; | |||||
find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); | |||||
return (name && ((strcmp (name, "calltrap") == 0) | |||||
|| (strcmp (name, "fork_trampoline") == 0) | |||||
|| (name[0] == 'X' && name[1] != '_'))); | |||||
} | |||||
static const struct frame_unwind i386fbsd_trapframe_unwind = { | |||||
NORMAL_FRAME, | |||||
default_frame_unwind_stop_reason, | |||||
i386fbsd_trapframe_this_id, | |||||
i386fbsd_trapframe_prev_register, | |||||
NULL, | |||||
i386fbsd_trapframe_sniffer | |||||
}; | |||||
static void | |||||
i386fbsd_kernel_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch) | |||||
{ | |||||
i386_elf_init_abi(info, gdbarch); | |||||
#ifdef __i386__ | |||||
frame_unwind_prepend_unwinder(gdbarch, &i386fbsd_dblfault_unwind); | |||||
#endif | |||||
frame_unwind_prepend_unwinder(gdbarch, &i386fbsd_trapframe_unwind); | |||||
set_solib_ops(gdbarch, &kld_so_ops); | |||||
fbsd_vmcore_set_supply_pcb(gdbarch, i386fbsd_supply_pcb); | |||||
fbsd_vmcore_set_cpu_pcb_addr(gdbarch, kgdb_trgt_stop_pcb); | |||||
} | |||||
void _initialize_i386_kgdb_tdep(void); | |||||
void | |||||
_initialize_i386_kgdb_tdep(void) | |||||
{ | |||||
/* This is used for both i386 and amd64, but amd64 always | |||||
includes this target, so just include it here. */ | |||||
gdbarch_register_osabi_sniffer(bfd_arch_i386, | |||||
bfd_target_elf_flavour, | |||||
fbsd_kernel_osabi_sniffer); | |||||
gdbarch_register_osabi (bfd_arch_i386, 0, | |||||
GDB_OSABI_FREEBSD_ELF_KERNEL, i386fbsd_kernel_init_abi); | |||||
i386fbsd_pspace_data = register_program_space_data_with_cleanup (NULL, | |||||
i386fbsd_pspace_data_cleanup); | |||||
#ifdef __i386__ | |||||
gdb_assert(offsetof(struct pcb, pcb_ebx) | |||||
== i386fbsd_pcb_offset[I386_EBX_REGNUM]); | |||||
gdb_assert(offsetof(struct pcb, pcb_esp) | |||||
== i386fbsd_pcb_offset[I386_ESP_REGNUM]); | |||||
gdb_assert(offsetof(struct pcb, pcb_ebp) | |||||
== i386fbsd_pcb_offset[I386_EBP_REGNUM]); | |||||
gdb_assert(offsetof(struct pcb, pcb_esi) | |||||
== i386fbsd_pcb_offset[I386_ESI_REGNUM]); | |||||
gdb_assert(offsetof(struct pcb, pcb_edi) | |||||
== i386fbsd_pcb_offset[I386_EDI_REGNUM]); | |||||
gdb_assert(offsetof(struct pcb, pcb_eip) | |||||
== i386fbsd_pcb_offset[I386_EIP_REGNUM]); | |||||
gdb_assert(CODE_SEL == GSEL(GCODE_SEL, SEL_KPL)); | |||||
gdb_assert(DATA_SEL == GSEL(GDATA_SEL, SEL_KPL)); | |||||
gdb_assert(PRIV_SEL == GSEL(GPRIV_SEL, SEL_KPL)); | |||||
gdb_assert(sizeof(struct trapframe) == TRAPFRAME_SIZE); | |||||
gdb_assert(offsetof(struct trapframe, tf_eax) | |||||
== i386fbsd_trapframe_offset[I386_EAX_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_ecx) | |||||
== i386fbsd_trapframe_offset[I386_ECX_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_edx) | |||||
== i386fbsd_trapframe_offset[I386_EDX_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_ebx) | |||||
== i386fbsd_trapframe_offset[I386_EBX_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_esp) | |||||
== i386fbsd_trapframe_offset[I386_ESP_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_ebp) | |||||
== i386fbsd_trapframe_offset[I386_EBP_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_esi) | |||||
== i386fbsd_trapframe_offset[I386_ESI_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_edi) | |||||
== i386fbsd_trapframe_offset[I386_EDI_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_eip) | |||||
== i386fbsd_trapframe_offset[I386_EIP_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_eflags) | |||||
== i386fbsd_trapframe_offset[I386_EFLAGS_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_cs) | |||||
== i386fbsd_trapframe_offset[I386_CS_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_ss) | |||||
== i386fbsd_trapframe_offset[I386_SS_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_ds) | |||||
== i386fbsd_trapframe_offset[I386_DS_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_es) | |||||
== i386fbsd_trapframe_offset[I386_ES_REGNUM]); | |||||
gdb_assert(offsetof(struct trapframe, tf_fs) | |||||
== i386fbsd_trapframe_offset[I386_FS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_eax) | |||||
== i386fbsd_tss_offset[I386_EAX_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_ecx) | |||||
== i386fbsd_tss_offset[I386_ECX_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_edx) | |||||
== i386fbsd_tss_offset[I386_EDX_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_ebx) | |||||
== i386fbsd_tss_offset[I386_EBX_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_esp) | |||||
== i386fbsd_tss_offset[I386_ESP_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_ebp) | |||||
== i386fbsd_tss_offset[I386_EBP_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_esi) | |||||
== i386fbsd_tss_offset[I386_ESI_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_edi) | |||||
== i386fbsd_tss_offset[I386_EDI_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_eip) | |||||
== i386fbsd_tss_offset[I386_EIP_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_eflags) | |||||
== i386fbsd_tss_offset[I386_EFLAGS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_cs) | |||||
== i386fbsd_tss_offset[I386_CS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_ss) | |||||
== i386fbsd_tss_offset[I386_SS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_ds) | |||||
== i386fbsd_tss_offset[I386_DS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_es) | |||||
== i386fbsd_tss_offset[I386_ES_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_fs) | |||||
== i386fbsd_tss_offset[I386_FS_REGNUM]); | |||||
gdb_assert(offsetof(struct i386tss, tss_gs) | |||||
== i386fbsd_tss_offset[I386_GS_REGNUM]); | |||||
#endif | |||||
} |