1 /* Low level interface to valgrind, for the remote server for GDB integrated 2 in valgrind. 3 Copyright (C) 2011 4 Free Software Foundation, Inc. 5 6 This file is part of VALGRIND. 7 It has been inspired from a file from gdbserver in gdb 6.6. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 Boston, MA 02110-1301, USA. */ 23 24 #include "server.h" 25 #include "target.h" 26 #include "regdef.h" 27 #include "regcache.h" 28 29 #include "pub_core_aspacemgr.h" 30 #include "pub_tool_machine.h" 31 #include "pub_core_threadstate.h" 32 #include "pub_core_transtab.h" 33 #include "pub_core_gdbserver.h" 34 35 #include "valgrind_low.h" 36 37 #include "libvex_guest_amd64.h" 38 /* GDBTD: ??? have a cleaner way to get the f80 <> f64 conversion functions */ 39 /* below include needed for conversion f80 <> f64 */ 40 #include "../../VEX/priv/guest_generic_x87.h" 41 42 /* below loosely inspired from file generated with gdb regdat.sh */ 43 44 struct reg regs[] = { 45 { "rax", 0, 64 }, 46 { "rbx", 64, 64 }, 47 { "rcx", 128, 64 }, 48 { "rdx", 192, 64 }, 49 { "rsi", 256, 64 }, 50 { "rdi", 320, 64 }, 51 { "rbp", 384, 64 }, 52 { "rsp", 448, 64 }, 53 { "r8", 512, 64 }, 54 { "r9", 576, 64 }, 55 { "r10", 640, 64 }, 56 { "r11", 704, 64 }, 57 { "r12", 768, 64 }, 58 { "r13", 832, 64 }, 59 { "r14", 896, 64 }, 60 { "r15", 960, 64 }, 61 { "rip", 1024, 64 }, 62 { "eflags", 1088, 32 }, 63 { "cs", 1120, 32 }, 64 { "ss", 1152, 32 }, 65 { "ds", 1184, 32 }, 66 { "es", 1216, 32 }, 67 { "fs", 1248, 32 }, 68 { "gs", 1280, 32 }, 69 { "st0", 1312, 80 }, 70 { "st1", 1392, 80 }, 71 { "st2", 1472, 80 }, 72 { "st3", 1552, 80 }, 73 { "st4", 1632, 80 }, 74 { "st5", 1712, 80 }, 75 { "st6", 1792, 80 }, 76 { "st7", 1872, 80 }, 77 { "fctrl", 1952, 32 }, 78 { "fstat", 1984, 32 }, 79 { "ftag", 2016, 32 }, 80 { "fiseg", 2048, 32 }, 81 { "fioff", 2080, 32 }, 82 { "foseg", 2112, 32 }, 83 { "fooff", 2144, 32 }, 84 { "fop", 2176, 32 }, 85 { "xmm0", 2208, 128 }, 86 { "xmm1", 2336, 128 }, 87 { "xmm2", 2464, 128 }, 88 { "xmm3", 2592, 128 }, 89 { "xmm4", 2720, 128 }, 90 { "xmm5", 2848, 128 }, 91 { "xmm6", 2976, 128 }, 92 { "xmm7", 3104, 128 }, 93 { "xmm8", 3232, 128 }, 94 { "xmm9", 3360, 128 }, 95 { "xmm10", 3488, 128 }, 96 { "xmm11", 3616, 128 }, 97 { "xmm12", 3744, 128 }, 98 { "xmm13", 3872, 128 }, 99 { "xmm14", 4000, 128 }, 100 { "xmm15", 4128, 128 }, 101 { "mxcsr", 4256, 32 }, 102 #if defined(VGO_linux) 103 { "orig_rax", 4288, 64 } 104 #endif 105 }; 106 static const char *expedite_regs[] = { "rbp", "rsp", "rip", 0 }; 107 #define num_regs (sizeof (regs) / sizeof (regs[0])) 108 109 static 110 CORE_ADDR get_pc (void) 111 { 112 unsigned long pc; 113 114 collect_register_by_name ("rip", &pc); 115 116 dlog(1, "stop pc is %p\n", (void *) pc); 117 return pc; 118 } 119 120 static 121 void set_pc (CORE_ADDR newpc) 122 { 123 Bool mod; 124 supply_register_by_name ("rip", &newpc, &mod); 125 if (mod) 126 dlog(1, "set pc to %p\n", C2v (newpc)); 127 else 128 dlog(1, "set pc not changed %p\n", C2v (newpc)); 129 } 130 131 /* store registers in the guest state (gdbserver_to_valgrind) 132 or fetch register from the guest state (valgrind_to_gdbserver). */ 133 static 134 void transfer_register (ThreadId tid, int abs_regno, void * buf, 135 transfer_direction dir, int size, Bool *mod) 136 { 137 ThreadState* tst = VG_(get_ThreadState)(tid); 138 int set = abs_regno / num_regs; 139 int regno = abs_regno % num_regs; 140 *mod = False; 141 142 VexGuestAMD64State* amd64 = (VexGuestAMD64State*) get_arch (set, tst); 143 144 switch (regno) { 145 // numbers here have to match the order of regs above. 146 // Attention: gdb order does not match valgrind order. 147 case 0: VG_(transfer) (&amd64->guest_RAX, buf, dir, size, mod); break; 148 case 1: VG_(transfer) (&amd64->guest_RBX, buf, dir, size, mod); break; 149 case 2: VG_(transfer) (&amd64->guest_RCX, buf, dir, size, mod); break; 150 case 3: VG_(transfer) (&amd64->guest_RDX, buf, dir, size, mod); break; 151 case 4: VG_(transfer) (&amd64->guest_RSI, buf, dir, size, mod); break; 152 case 5: VG_(transfer) (&amd64->guest_RDI, buf, dir, size, mod); break; 153 case 6: VG_(transfer) (&amd64->guest_RBP, buf, dir, size, mod); break; 154 case 7: VG_(transfer) (&amd64->guest_RSP, buf, dir, size, mod); break; 155 case 8: VG_(transfer) (&amd64->guest_R8, buf, dir, size, mod); break; 156 case 9: VG_(transfer) (&amd64->guest_R9, buf, dir, size, mod); break; 157 case 10: VG_(transfer) (&amd64->guest_R10, buf, dir, size, mod); break; 158 case 11: VG_(transfer) (&amd64->guest_R11, buf, dir, size, mod); break; 159 case 12: VG_(transfer) (&amd64->guest_R12, buf, dir, size, mod); break; 160 case 13: VG_(transfer) (&amd64->guest_R13, buf, dir, size, mod); break; 161 case 14: VG_(transfer) (&amd64->guest_R14, buf, dir, size, mod); break; 162 case 15: VG_(transfer) (&amd64->guest_R15, buf, dir, size, mod); break; 163 case 16: 164 VG_(transfer) (&amd64->guest_RIP, buf, dir, size, mod); 165 if (*mod && VG_(debugLog_getLevel)() > 2) { 166 char bufimage [2*sizeof(amd64->guest_IP_AT_SYSCALL) + 1]; 167 heximage (bufimage, 168 (char *) &amd64->guest_IP_AT_SYSCALL, 169 sizeof(amd64->guest_IP_AT_SYSCALL)); 170 dlog(3, "guest_IP_AT_SYSCALL %s\n", bufimage); 171 } 172 break; 173 case 17: 174 if (dir == valgrind_to_gdbserver) { 175 ULong rflags; 176 /* we can only retrieve the real flags (set 0) 177 retrieving shadow flags is not ok */ 178 if (set == 0) 179 rflags = LibVEX_GuestAMD64_get_rflags (amd64); 180 else 181 rflags = 0; 182 VG_(transfer) (&rflags, buf, dir, size, mod); 183 } else { 184 *mod = False; //GDBTD? how do we store rflags in libvex_guest_amd64.h ??? 185 } 186 break; 187 case 18: *mod = False; break; //GDBTD VG_(transfer) (&amd64->guest_CS, buf, dir, size, mod); 188 case 19: *mod = False; break; //GDBTD VG_(transfer) (&amd64->guest_SS, buf, dir, size, mod); 189 case 20: *mod = False; break; //GDBTD VG_(transfer) (&amd64->guest_DS, buf, dir, size, mod); 190 case 21: *mod = False; break; //GDBTD VG_(transfer) (&amd64->guest_ES, buf, dir, size, mod); 191 case 22: *mod = False; break; //GDBTD VG_(transfer) (&amd64->guest_FS, buf, dir, size, mod); 192 case 23: VG_(transfer) (&amd64->guest_GS_0x60, buf, dir, size, mod); break; 193 case 24: 194 case 25: 195 case 26: 196 case 27: /* register 24 to 31 are float registers 80 bits but 64 bits in valgrind */ 197 case 28: 198 case 29: 199 case 30: 200 case 31: 201 if (dir == valgrind_to_gdbserver) { 202 UChar fpreg80[10]; 203 convert_f64le_to_f80le ((UChar *)&amd64->guest_FPREG[regno-16], 204 fpreg80); 205 VG_(transfer) (&fpreg80, buf, dir, sizeof(fpreg80), mod); 206 } else { 207 ULong fpreg64; 208 convert_f80le_to_f64le (buf, (UChar *)&fpreg64); 209 VG_(transfer) (&amd64->guest_FPREG[regno-16], &fpreg64, 210 dir, sizeof(fpreg64), mod); 211 } 212 break; 213 case 32: 214 if (dir == valgrind_to_gdbserver) { 215 // vex only models the rounding bits (see libvex_guest_amd64.h) 216 UWord value = 0x037f; 217 value |= amd64->guest_FPROUND << 10; 218 VG_(transfer)(&value, buf, dir, size, mod); 219 } else { 220 *mod = False; // GDBTD???? VEX equivalent fcrtl 221 } 222 break; 223 case 33: 224 if (dir == valgrind_to_gdbserver) { 225 UWord value = amd64->guest_FC3210; 226 value |= (amd64->guest_FTOP & 7) << 11; 227 VG_(transfer)(&value, buf, dir, size, mod); 228 } else { 229 *mod = False; // GDBTD???? VEX equivalent fstat 230 } 231 break; 232 case 34: 233 if (dir == valgrind_to_gdbserver) { 234 // vex doesn't model these precisely 235 UWord value = 236 ((amd64->guest_FPTAG[0] ? 0 : 3) << 0) | 237 ((amd64->guest_FPTAG[1] ? 0 : 3) << 2) | 238 ((amd64->guest_FPTAG[2] ? 0 : 3) << 4) | 239 ((amd64->guest_FPTAG[3] ? 0 : 3) << 6) | 240 ((amd64->guest_FPTAG[4] ? 0 : 3) << 8) | 241 ((amd64->guest_FPTAG[5] ? 0 : 3) << 10) | 242 ((amd64->guest_FPTAG[6] ? 0 : 3) << 12) | 243 ((amd64->guest_FPTAG[7] ? 0 : 3) << 14); 244 VG_(transfer)(&value, buf, dir, size, mod); 245 } else { 246 *mod = False; // GDBTD???? VEX equivalent ftag 247 } 248 break; 249 case 35: *mod = False; break; // GDBTD ??? equivalent of fiseg 250 case 36: *mod = False; break; // GDBTD ??? equivalent of fioff 251 case 37: *mod = False; break; // GDBTD ??? equivalent of foseg 252 case 38: *mod = False; break; // GDBTD ??? equivalent of fooff 253 case 39: *mod = False; break; // GDBTD ??? equivalent of fop 254 case 40: VG_(transfer) (&amd64->guest_XMM0, buf, dir, size, mod); break; 255 case 41: VG_(transfer) (&amd64->guest_XMM1, buf, dir, size, mod); break; 256 case 42: VG_(transfer) (&amd64->guest_XMM2, buf, dir, size, mod); break; 257 case 43: VG_(transfer) (&amd64->guest_XMM3, buf, dir, size, mod); break; 258 case 44: VG_(transfer) (&amd64->guest_XMM4, buf, dir, size, mod); break; 259 case 45: VG_(transfer) (&amd64->guest_XMM5, buf, dir, size, mod); break; 260 case 46: VG_(transfer) (&amd64->guest_XMM6, buf, dir, size, mod); break; 261 case 47: VG_(transfer) (&amd64->guest_XMM7, buf, dir, size, mod); break; 262 case 48: VG_(transfer) (&amd64->guest_XMM8, buf, dir, size, mod); break; 263 case 49: VG_(transfer) (&amd64->guest_XMM9, buf, dir, size, mod); break; 264 case 50: VG_(transfer) (&amd64->guest_XMM10, buf, dir, size, mod); break; 265 case 51: VG_(transfer) (&amd64->guest_XMM11, buf, dir, size, mod); break; 266 case 52: VG_(transfer) (&amd64->guest_XMM12, buf, dir, size, mod); break; 267 case 53: VG_(transfer) (&amd64->guest_XMM13, buf, dir, size, mod); break; 268 case 54: VG_(transfer) (&amd64->guest_XMM14, buf, dir, size, mod); break; 269 case 55: VG_(transfer) (&amd64->guest_XMM15, buf, dir, size, mod); break; 270 case 56: 271 if (dir == valgrind_to_gdbserver) { 272 // vex only models the rounding bits (see libvex_guest_x86.h) 273 UWord value = 0x1f80; 274 value |= amd64->guest_SSEROUND << 13; 275 VG_(transfer)(&value, buf, dir, size, mod); 276 } else { 277 *mod = False; // GDBTD???? VEX equivalent mxcsr 278 } 279 break; 280 case 57: *mod = False; break; // GDBTD???? VEX equivalent { "orig_rax"}, 281 default: vg_assert(0); 282 } 283 } 284 285 static struct valgrind_target_ops low_target = { 286 num_regs, 287 regs, 288 7, //RSP 289 transfer_register, 290 get_pc, 291 set_pc, 292 "amd64", 293 NULL, // target_xml not needed. 294 #if defined(VGO_linux) 295 "amd64-linux-valgrind.xml" 296 #else 297 "amd64-coresse-valgrind.xml" 298 #endif 299 }; 300 301 void amd64_init_architecture (struct valgrind_target_ops *target) 302 { 303 *target = low_target; 304 set_register_cache (regs, num_regs); 305 gdbserver_expedite_regs = expedite_regs; 306 } 307