GDBserver
|
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 };