GDBserver
/home/stan/gdb/src/gdb/gdbserver/lynx-i386-low.c
Go to the documentation of this file.
00001 /* Copyright (C) 2010-2013 Free Software Foundation, Inc.
00002 
00003    This file is part of GDB.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 #include "server.h"
00019 #include "lynx-low.h"
00020 
00021 #include <stdint.h>
00022 #include <limits.h>
00023 #include <sys/ptrace.h>
00024 
00025 /* The following two typedefs are defined in a .h file which is not
00026    in the standard include path (/sys/include/family/x86/ucontext.h),
00027    so we just duplicate them here.  */
00028 
00029 /* General register context */
00030 typedef struct usr_econtext {
00031 
00032     uint32_t    uec_fault;
00033     uint32_t    uec_es;
00034     uint32_t    uec_ds;
00035     uint32_t    uec_edi;
00036     uint32_t    uec_esi;
00037     uint32_t    uec_ebp;
00038     uint32_t    uec_temp;
00039     uint32_t    uec_ebx;
00040     uint32_t    uec_edx;
00041     uint32_t    uec_ecx;
00042     uint32_t    uec_eax;
00043     uint32_t    uec_inum;
00044     uint32_t    uec_ecode;
00045     uint32_t    uec_eip;
00046     uint32_t    uec_cs;
00047     uint32_t    uec_eflags;
00048     uint32_t    uec_esp;
00049     uint32_t    uec_ss;
00050     uint32_t    uec_fs;
00051     uint32_t    uec_gs;
00052 } usr_econtext_t;
00053 
00054 /* Floating point and SIMD register context */
00055 typedef struct usr_fcontext {
00056         uint16_t         ufc_control;
00057         uint16_t         ufc_status;
00058         uint16_t         ufc_tag;
00059         uint16_t         ufc_opcode;
00060         uint8_t         *ufc_inst_off;
00061         uint32_t         ufc_inst_sel;
00062         uint8_t         *ufc_data_off;
00063         uint32_t         ufc_data_sel;
00064         uint32_t         usse_mxcsr;
00065         uint32_t         usse_mxcsr_mask;
00066         struct ufp387_real {
00067                 uint16_t umant4;
00068                 uint16_t umant3;
00069                 uint16_t umant2;
00070                 uint16_t umant1;
00071                 uint16_t us_and_e;
00072                 uint16_t ureserved_1;
00073                 uint16_t ureserved_2;
00074                 uint16_t ureserved_3;
00075         } ufc_reg[8];
00076         struct uxmm_register {
00077                 uint16_t uchunk_1;
00078                 uint16_t uchunk_2;
00079                 uint16_t uchunk_3;
00080                 uint16_t uchunk_4;
00081                 uint16_t uchunk_5;
00082                 uint16_t uchunk_6;
00083                 uint16_t uchunk_7;
00084                 uint16_t uchunk_8;
00085         } uxmm_reg[8];
00086         char ureserved[16][14];
00087 } usr_fcontext_t;
00088 
00089 /* The index of various registers inside the regcache.  */
00090 
00091 enum lynx_i386_gdb_regnum
00092 {
00093   I386_EAX_REGNUM,
00094   I386_ECX_REGNUM,
00095   I386_EDX_REGNUM,
00096   I386_EBX_REGNUM,
00097   I386_ESP_REGNUM,
00098   I386_EBP_REGNUM,
00099   I386_ESI_REGNUM,
00100   I386_EDI_REGNUM,
00101   I386_EIP_REGNUM,
00102   I386_EFLAGS_REGNUM,
00103   I386_CS_REGNUM,
00104   I386_SS_REGNUM,
00105   I386_DS_REGNUM,
00106   I386_ES_REGNUM,
00107   I386_FS_REGNUM,
00108   I386_GS_REGNUM,
00109   I386_ST0_REGNUM,
00110   I386_FCTRL_REGNUM = I386_ST0_REGNUM + 8,
00111   I386_FSTAT_REGNUM,
00112   I386_FTAG_REGNUM,
00113   I386_FISEG_REGNUM,
00114   I386_FIOFF_REGNUM,
00115   I386_FOSEG_REGNUM,
00116   I386_FOOFF_REGNUM,
00117   I386_FOP_REGNUM,
00118   I386_XMM0_REGNUM = 32,
00119   I386_MXCSR_REGNUM = I386_XMM0_REGNUM + 8,
00120   I386_SENTINEL_REGUM
00121 };
00122 
00123 /* Defined in auto-generated file i386.c.  */
00124 extern void init_registers_i386 (void);
00125 extern const struct target_desc *tdesc_i386;
00126 
00127 /* The fill_function for the general-purpose register set.  */
00128 
00129 static void
00130 lynx_i386_fill_gregset (struct regcache *regcache, char *buf)
00131 {
00132 #define lynx_i386_collect_gp(regnum, fld) \
00133   collect_register (regcache, regnum, \
00134                     buf + offsetof (usr_econtext_t, uec_##fld))
00135 
00136   lynx_i386_collect_gp (I386_EAX_REGNUM, eax);
00137   lynx_i386_collect_gp (I386_ECX_REGNUM, ecx);
00138   lynx_i386_collect_gp (I386_EDX_REGNUM, edx);
00139   lynx_i386_collect_gp (I386_EBX_REGNUM, ebx);
00140   lynx_i386_collect_gp (I386_ESP_REGNUM, esp);
00141   lynx_i386_collect_gp (I386_EBP_REGNUM, ebp);
00142   lynx_i386_collect_gp (I386_ESI_REGNUM, esi);
00143   lynx_i386_collect_gp (I386_EDI_REGNUM, edi);
00144   lynx_i386_collect_gp (I386_EIP_REGNUM, eip);
00145   lynx_i386_collect_gp (I386_EFLAGS_REGNUM, eflags);
00146   lynx_i386_collect_gp (I386_CS_REGNUM, cs);
00147   lynx_i386_collect_gp (I386_SS_REGNUM, ss);
00148   lynx_i386_collect_gp (I386_DS_REGNUM, ds);
00149   lynx_i386_collect_gp (I386_ES_REGNUM, es);
00150   lynx_i386_collect_gp (I386_FS_REGNUM, fs);
00151   lynx_i386_collect_gp (I386_GS_REGNUM, gs);
00152 }
00153 
00154 /* The store_function for the general-purpose register set.  */
00155 
00156 static void
00157 lynx_i386_store_gregset (struct regcache *regcache, const char *buf)
00158 {
00159 #define lynx_i386_supply_gp(regnum, fld) \
00160   supply_register (regcache, regnum, \
00161                    buf + offsetof (usr_econtext_t, uec_##fld))
00162 
00163   lynx_i386_supply_gp (I386_EAX_REGNUM, eax);
00164   lynx_i386_supply_gp (I386_ECX_REGNUM, ecx);
00165   lynx_i386_supply_gp (I386_EDX_REGNUM, edx);
00166   lynx_i386_supply_gp (I386_EBX_REGNUM, ebx);
00167   lynx_i386_supply_gp (I386_ESP_REGNUM, esp);
00168   lynx_i386_supply_gp (I386_EBP_REGNUM, ebp);
00169   lynx_i386_supply_gp (I386_ESI_REGNUM, esi);
00170   lynx_i386_supply_gp (I386_EDI_REGNUM, edi);
00171   lynx_i386_supply_gp (I386_EIP_REGNUM, eip);
00172   lynx_i386_supply_gp (I386_EFLAGS_REGNUM, eflags);
00173   lynx_i386_supply_gp (I386_CS_REGNUM, cs);
00174   lynx_i386_supply_gp (I386_SS_REGNUM, ss);
00175   lynx_i386_supply_gp (I386_DS_REGNUM, ds);
00176   lynx_i386_supply_gp (I386_ES_REGNUM, es);
00177   lynx_i386_supply_gp (I386_FS_REGNUM, fs);
00178   lynx_i386_supply_gp (I386_GS_REGNUM, gs);
00179 }
00180 
00181 /* Extract the first 16 bits of register REGNUM in the REGCACHE,
00182    and store these 2 bytes at DEST.
00183 
00184    This is useful to collect certain 16bit registers which are known
00185    by GDBserver as 32bit registers (such as the Control Register
00186    for instance).  */
00187 
00188 static void
00189 collect_16bit_register (struct regcache *regcache, int regnum, char *dest)
00190 {
00191   gdb_byte word[4];
00192 
00193   collect_register (regcache, regnum, word);
00194   memcpy (dest, word, 2);
00195 }
00196 
00197 /* The fill_function for the floating-point register set.  */
00198 
00199 static void
00200 lynx_i386_fill_fpregset (struct regcache *regcache, char *buf)
00201 {
00202   int i;
00203 
00204   /* Collect %st0 .. %st7.  */
00205   for (i = 0; i < 8; i++)
00206     collect_register (regcache, I386_ST0_REGNUM + i,
00207                       buf + offsetof (usr_fcontext_t, ufc_reg)
00208                       + i * sizeof (struct ufp387_real));
00209 
00210   /* Collect the other FPU registers.  */
00211   collect_16bit_register (regcache, I386_FCTRL_REGNUM,
00212                           buf + offsetof (usr_fcontext_t, ufc_control));
00213   collect_16bit_register (regcache, I386_FSTAT_REGNUM,
00214                           buf + offsetof (usr_fcontext_t, ufc_status));
00215   collect_16bit_register (regcache, I386_FTAG_REGNUM,
00216                           buf + offsetof (usr_fcontext_t, ufc_tag));
00217   collect_register (regcache, I386_FISEG_REGNUM,
00218                     buf + offsetof (usr_fcontext_t, ufc_inst_sel));
00219   collect_register (regcache, I386_FIOFF_REGNUM,
00220                     buf + offsetof (usr_fcontext_t, ufc_inst_off));
00221   collect_register (regcache, I386_FOSEG_REGNUM,
00222                     buf + offsetof (usr_fcontext_t, ufc_data_sel));
00223   collect_register (regcache, I386_FOOFF_REGNUM,
00224                     buf + offsetof (usr_fcontext_t, ufc_data_off));
00225   collect_16bit_register (regcache, I386_FOP_REGNUM,
00226                           buf + offsetof (usr_fcontext_t, ufc_opcode));
00227 
00228   /* Collect the XMM registers.  */
00229   for (i = 0; i < 8; i++)
00230     collect_register (regcache, I386_XMM0_REGNUM + i,
00231                       buf + offsetof (usr_fcontext_t, uxmm_reg)
00232                       + i * sizeof (struct uxmm_register));
00233   collect_register (regcache, I386_MXCSR_REGNUM,
00234                     buf + offsetof (usr_fcontext_t, usse_mxcsr));
00235 }
00236 
00237 /* This is the supply counterpart for collect_16bit_register:
00238    It extracts a 2byte value from BUF, and uses that value to
00239    set REGNUM's value in the regcache.
00240 
00241    This is useful to supply the value of certain 16bit registers
00242    which are known by GDBserver as 32bit registers (such as the Control
00243    Register for instance).  */
00244 
00245 static void
00246 supply_16bit_register (struct regcache *regcache, int regnum, const char *buf)
00247 {
00248   gdb_byte word[4];
00249 
00250   memcpy (word, buf, 2);
00251   memset (word + 2, 0, 2);
00252   supply_register (regcache, regnum, word);
00253 }
00254 
00255 /* The store_function for the floating-point register set.  */
00256 
00257 static void
00258 lynx_i386_store_fpregset (struct regcache *regcache, const char *buf)
00259 {
00260   int i;
00261 
00262   /* Store the %st0 .. %st7 registers.  */
00263   for (i = 0; i < 8; i++)
00264     supply_register (regcache, I386_ST0_REGNUM + i,
00265                      buf + offsetof (usr_fcontext_t, ufc_reg)
00266                      + i * sizeof (struct ufp387_real));
00267 
00268   /* Store the other FPU registers.  */
00269   supply_16bit_register (regcache, I386_FCTRL_REGNUM,
00270                          buf + offsetof (usr_fcontext_t, ufc_control));
00271   supply_16bit_register (regcache, I386_FSTAT_REGNUM,
00272                          buf + offsetof (usr_fcontext_t, ufc_status));
00273   supply_16bit_register (regcache, I386_FTAG_REGNUM,
00274                          buf + offsetof (usr_fcontext_t, ufc_tag));
00275   supply_register (regcache, I386_FISEG_REGNUM,
00276                    buf + offsetof (usr_fcontext_t, ufc_inst_sel));
00277   supply_register (regcache, I386_FIOFF_REGNUM,
00278                    buf + offsetof (usr_fcontext_t, ufc_inst_off));
00279   supply_register (regcache, I386_FOSEG_REGNUM,
00280                    buf + offsetof (usr_fcontext_t, ufc_data_sel));
00281   supply_register (regcache, I386_FOOFF_REGNUM,
00282                    buf + offsetof (usr_fcontext_t, ufc_data_off));
00283   supply_16bit_register (regcache, I386_FOP_REGNUM,
00284                          buf + offsetof (usr_fcontext_t, ufc_opcode));
00285 
00286   /* Store the XMM registers.  */
00287   for (i = 0; i < 8; i++)
00288     supply_register (regcache, I386_XMM0_REGNUM + i,
00289                      buf + offsetof (usr_fcontext_t, uxmm_reg)
00290                      + i * sizeof (struct uxmm_register));
00291   supply_register (regcache, I386_MXCSR_REGNUM,
00292                    buf + offsetof (usr_fcontext_t, usse_mxcsr));
00293 }
00294 
00295 /* Implements the lynx_target_ops.arch_setup routine.  */
00296 
00297 static void
00298 lynx_i386_arch_setup (void)
00299 {
00300   init_registers_i386 ();
00301   lynx_tdesc = tdesc_i386;
00302 }
00303 
00304 /* Description of all the x86-lynx register sets.  */
00305 
00306 struct lynx_regset_info lynx_target_regsets[] = {
00307   /* General Purpose Registers.  */
00308   {PTRACE_GETREGS, PTRACE_SETREGS, sizeof(usr_econtext_t),
00309    lynx_i386_fill_gregset, lynx_i386_store_gregset},
00310   /* Floating Point Registers.  */
00311   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof(usr_fcontext_t),
00312     lynx_i386_fill_fpregset, lynx_i386_store_fpregset },
00313   /* End of list marker.  */
00314   {0, 0, -1, NULL, NULL }
00315 };
00316 
00317 /* The lynx_target_ops vector for x86-lynx.  */
00318 
00319 struct lynx_target_ops the_low_target = {
00320   lynx_i386_arch_setup,
00321 };
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines