From fa1bd1e4fbf2669cc29d75e23050eba264968aab Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Mon, 13 Sep 2010 19:11:03 +0000 Subject: [PATCH] Add support for x86 LynxOS This patch adds support for x86 LynxOS (tested on LynxOS 5.0). gdb/gdbserver/ChangeLog: * lynx-i386-low.c: New file. * configure.srv: Add handling of i[34567]86-*-lynxos* targets. --- gdb/gdbserver/ChangeLog | 5 + gdb/gdbserver/configure.srv | 4 + gdb/gdbserver/lynx-i386-low.c | 319 ++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 gdb/gdbserver/lynx-i386-low.c diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index f1568385472..d769dd3c23f 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,8 @@ +2010-09-13 Joel Brobecker + + * lynx-i386-low.c: New file. + * configure.srv: Add handling of i[34567]86-*-lynxos* targets. + 2010-09-13 Joel Brobecker * lynx-low.c (ptrace_request_to_str): Remove handling for diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 8a147594220..1e8fa305918 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -93,6 +93,10 @@ case "${target}" in srv_linux_thread_db=yes ipa_obj="${ipa_i386_linux_regobj} linux-i386-ipa.o" ;; + i[34567]86-*-lynxos*) srv_regobj="i386.o" + srv_tgtobj="lynx-low.o lynx-i386-low.o" + srv_lynxos=yes + ;; i[34567]86-*-mingw32ce*) srv_regobj="$srv_i386_regobj" srv_tgtobj="i386-low.o win32-low.o win32-i386-low.o" diff --git a/gdb/gdbserver/lynx-i386-low.c b/gdb/gdbserver/lynx-i386-low.c new file mode 100644 index 00000000000..1ea334b7bf2 --- /dev/null +++ b/gdb/gdbserver/lynx-i386-low.c @@ -0,0 +1,319 @@ +/* Copyright (C) 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "server.h" +#include "lynx-low.h" + +#include +#include +#include + +/* The following two typedefs are defined in a .h file which is not + in the standard include path (/sys/include/family/x86/ucontext.h), + so we just duplicate them here. */ + +/* General register context */ +typedef struct usr_econtext { + + uint32_t uec_fault; + uint32_t uec_es; + uint32_t uec_ds; + uint32_t uec_edi; + uint32_t uec_esi; + uint32_t uec_ebp; + uint32_t uec_temp; + uint32_t uec_ebx; + uint32_t uec_edx; + uint32_t uec_ecx; + uint32_t uec_eax; + uint32_t uec_inum; + uint32_t uec_ecode; + uint32_t uec_eip; + uint32_t uec_cs; + uint32_t uec_eflags; + uint32_t uec_esp; + uint32_t uec_ss; + uint32_t uec_fs; + uint32_t uec_gs; +} usr_econtext_t; + +/* Floating point and SIMD register context */ +typedef struct usr_fcontext { + uint16_t ufc_control; + uint16_t ufc_status; + uint16_t ufc_tag; + uint16_t ufc_opcode; + uint8_t *ufc_inst_off; + uint32_t ufc_inst_sel; + uint8_t *ufc_data_off; + uint32_t ufc_data_sel; + uint32_t usse_mxcsr; + uint32_t usse_mxcsr_mask; + struct ufp387_real { + uint16_t umant4; + uint16_t umant3; + uint16_t umant2; + uint16_t umant1; + uint16_t us_and_e; + uint16_t ureserved_1; + uint16_t ureserved_2; + uint16_t ureserved_3; + } ufc_reg[8]; + struct uxmm_register { + uint16_t uchunk_1; + uint16_t uchunk_2; + uint16_t uchunk_3; + uint16_t uchunk_4; + uint16_t uchunk_5; + uint16_t uchunk_6; + uint16_t uchunk_7; + uint16_t uchunk_8; + } uxmm_reg[8]; + char ureserved[16][14]; +} usr_fcontext_t; + +/* The index of various registers inside the regcache. */ + +enum lynx_i386_gdb_regnum +{ + I386_EAX_REGNUM, + I386_ECX_REGNUM, + I386_EDX_REGNUM, + I386_EBX_REGNUM, + I386_ESP_REGNUM, + I386_EBP_REGNUM, + I386_ESI_REGNUM, + I386_EDI_REGNUM, + I386_EIP_REGNUM, + I386_EFLAGS_REGNUM, + I386_CS_REGNUM, + I386_SS_REGNUM, + I386_DS_REGNUM, + I386_ES_REGNUM, + I386_FS_REGNUM, + I386_GS_REGNUM, + I386_ST0_REGNUM, + I386_FCTRL_REGNUM = I386_ST0_REGNUM + 8, + I386_FSTAT_REGNUM, + I386_FTAG_REGNUM, + I386_FISEG_REGNUM, + I386_FIOFF_REGNUM, + I386_FOSEG_REGNUM, + I386_FOOFF_REGNUM, + I386_FOP_REGNUM, + I386_XMM0_REGNUM = 32, + I386_MXCSR_REGNUM = I386_XMM0_REGNUM + 8, + I386_SENTINEL_REGUM +}; + +/* Defined in auto-generated file i386.c. */ +extern void init_registers_i386 (void); + +/* The fill_function for the general-purpose register set. */ + +static void +lynx_i386_fill_gregset (struct regcache *regcache, char *buf) +{ +#define lynx_i386_collect_gp(regnum, fld) \ + collect_register (regcache, regnum, \ + buf + offsetof (usr_econtext_t, uec_##fld)) + + lynx_i386_collect_gp (I386_EAX_REGNUM, eax); + lynx_i386_collect_gp (I386_ECX_REGNUM, ecx); + lynx_i386_collect_gp (I386_EDX_REGNUM, edx); + lynx_i386_collect_gp (I386_EBX_REGNUM, ebx); + lynx_i386_collect_gp (I386_ESP_REGNUM, esp); + lynx_i386_collect_gp (I386_EBP_REGNUM, ebp); + lynx_i386_collect_gp (I386_ESI_REGNUM, esi); + lynx_i386_collect_gp (I386_EDI_REGNUM, edi); + lynx_i386_collect_gp (I386_EIP_REGNUM, eip); + lynx_i386_collect_gp (I386_EFLAGS_REGNUM, eflags); + lynx_i386_collect_gp (I386_CS_REGNUM, cs); + lynx_i386_collect_gp (I386_SS_REGNUM, ss); + lynx_i386_collect_gp (I386_DS_REGNUM, ds); + lynx_i386_collect_gp (I386_ES_REGNUM, es); + lynx_i386_collect_gp (I386_FS_REGNUM, fs); + lynx_i386_collect_gp (I386_GS_REGNUM, gs); +} + +/* The store_function for the general-purpose register set. */ + +static void +lynx_i386_store_gregset (struct regcache *regcache, const char *buf) +{ +#define lynx_i386_supply_gp(regnum, fld) \ + supply_register (regcache, regnum, \ + buf + offsetof (usr_econtext_t, uec_##fld)) + + lynx_i386_supply_gp (I386_EAX_REGNUM, eax); + lynx_i386_supply_gp (I386_ECX_REGNUM, ecx); + lynx_i386_supply_gp (I386_EDX_REGNUM, edx); + lynx_i386_supply_gp (I386_EBX_REGNUM, ebx); + lynx_i386_supply_gp (I386_ESP_REGNUM, esp); + lynx_i386_supply_gp (I386_EBP_REGNUM, ebp); + lynx_i386_supply_gp (I386_ESI_REGNUM, esi); + lynx_i386_supply_gp (I386_EDI_REGNUM, edi); + lynx_i386_supply_gp (I386_EIP_REGNUM, eip); + lynx_i386_supply_gp (I386_EFLAGS_REGNUM, eflags); + lynx_i386_supply_gp (I386_CS_REGNUM, cs); + lynx_i386_supply_gp (I386_SS_REGNUM, ss); + lynx_i386_supply_gp (I386_DS_REGNUM, ds); + lynx_i386_supply_gp (I386_ES_REGNUM, es); + lynx_i386_supply_gp (I386_FS_REGNUM, fs); + lynx_i386_supply_gp (I386_GS_REGNUM, gs); +} + +/* Extract the first 16 bits of register REGNUM in the REGCACHE, + and store these 2 bytes at DEST. + + This is useful to collect certain 16bit registers which are known + by GDBserver as 32bit registers (such as the Control Register + for instance). */ + +static void +collect_16bit_register (struct regcache *regcache, int regnum, char *dest) +{ + gdb_byte word[4]; + + collect_register (regcache, regnum, word); + memcpy (dest, word, 2); +} + +/* The fill_function for the floating-point register set. */ + +static void +lynx_i386_fill_fpregset (struct regcache *regcache, char *buf) +{ + int i; + + /* Collect %st0 .. %st7. */ + for (i = 0; i < 8; i++) + collect_register (regcache, I386_ST0_REGNUM + i, + buf + offsetof (usr_fcontext_t, ufc_reg) + + i * sizeof (struct ufp387_real)); + + /* Collect the other FPU registers. */ + collect_16bit_register (regcache, I386_FCTRL_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_control)); + collect_16bit_register (regcache, I386_FSTAT_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_status)); + collect_16bit_register (regcache, I386_FTAG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_tag)); + collect_register (regcache, I386_FISEG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_inst_sel)); + collect_register (regcache, I386_FIOFF_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_inst_off)); + collect_register (regcache, I386_FOSEG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_data_sel)); + collect_register (regcache, I386_FOOFF_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_data_off)); + collect_16bit_register (regcache, I386_FOP_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_opcode)); + + /* Collect the XMM registers. */ + for (i = 0; i < 8; i++) + collect_register (regcache, I386_XMM0_REGNUM + i, + buf + offsetof (usr_fcontext_t, uxmm_reg) + + i * sizeof (struct uxmm_register)); + collect_register (regcache, I386_MXCSR_REGNUM, + buf + offsetof (usr_fcontext_t, usse_mxcsr)); +} + +/* This is the supply counterpart for collect_16bit_register: + It extracts a 2byte value from BUF, and uses that value to + set REGNUM's value in the regcache. + + This is useful to supply the value of certain 16bit registers + which are known by GDBserver as 32bit registers (such as the Control + Register for instance). */ + +static void +supply_16bit_register (struct regcache *regcache, int regnum, const char *buf) +{ + gdb_byte word[4]; + + memcpy (word, buf, 2); + memset (word + 2, 0, 2); + supply_register (regcache, regnum, word); +} + +/* The store_function for the floating-point register set. */ + +static void +lynx_i386_store_fpregset (struct regcache *regcache, const char *buf) +{ + int i; + + /* Store the %st0 .. %st7 registers. */ + for (i = 0; i < 8; i++) + supply_register (regcache, I386_ST0_REGNUM + i, + buf + offsetof (usr_fcontext_t, ufc_reg) + + i * sizeof (struct ufp387_real)); + + /* Store the other FPU registers. */ + supply_16bit_register (regcache, I386_FCTRL_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_control)); + supply_16bit_register (regcache, I386_FSTAT_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_status)); + supply_16bit_register (regcache, I386_FTAG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_tag)); + supply_register (regcache, I386_FISEG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_inst_sel)); + supply_register (regcache, I386_FIOFF_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_inst_off)); + supply_register (regcache, I386_FOSEG_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_data_sel)); + supply_register (regcache, I386_FOOFF_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_data_off)); + supply_16bit_register (regcache, I386_FOP_REGNUM, + buf + offsetof (usr_fcontext_t, ufc_opcode)); + + /* Store the XMM registers. */ + for (i = 0; i < 8; i++) + supply_register (regcache, I386_XMM0_REGNUM + i, + buf + offsetof (usr_fcontext_t, uxmm_reg) + + i * sizeof (struct uxmm_register)); + supply_register (regcache, I386_MXCSR_REGNUM, + buf + offsetof (usr_fcontext_t, usse_mxcsr)); +} + +/* Implements the lynx_target_ops.arch_setup routine. */ + +static void +lynx_i386_arch_setup (void) +{ + init_registers_i386 (); +} + +/* Description of all the x86-lynx register sets. */ + +struct lynx_regset_info lynx_target_regsets[] = { + /* General Purpose Registers. */ + {PTRACE_GETREGS, PTRACE_SETREGS, sizeof(usr_econtext_t), + lynx_i386_fill_gregset, lynx_i386_store_gregset}, + /* Floating Point Registers. */ + { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof(usr_fcontext_t), + lynx_i386_fill_fpregset, lynx_i386_store_fpregset }, + /* End of list marker. */ + {0, 0, -1, NULL, NULL } +}; + +/* The lynx_target_ops vector for x86-lynx. */ + +struct lynx_target_ops the_low_target = { + lynx_i386_arch_setup, +}; -- 2.30.2