1 /* Low level interface to valgrind, for the remote server for GDB integrated
4 Free Software Foundation, Inc.
6 This file is part of VALGRIND.
7 It has been inspired from a file from gdbserver in gdb 6.6.
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.
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.
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. */
29 #include "pub_core_machine.h"
30 #include "pub_core_threadstate.h"
31 #include "pub_core_transtab.h"
32 #include "pub_core_gdbserver.h"
34 #include "valgrind_low.h"
36 #include "libvex_guest_x86.h"
37 /* GDBTD: ??? have a cleaner way to get the f80 <> f64 conversion functions */
38 /* below include needed for conversion f80 <> f64 */
39 #include "../../VEX/priv/guest_generic_x87.h"
42 /* below loosely inspired from file generated with gdb regdat.sh */
44 static struct reg regs
[] = {
54 { "eflags", 288, 32 },
69 { "fctrl", 1152, 32 },
70 { "fstat", 1184, 32 },
72 { "fiseg", 1248, 32 },
73 { "fioff", 1280, 32 },
74 { "foseg", 1312, 32 },
75 { "fooff", 1344, 32 },
77 { "xmm0", 1408, 128 },
78 { "xmm1", 1536, 128 },
79 { "xmm2", 1664, 128 },
80 { "xmm3", 1792, 128 },
81 { "xmm4", 1920, 128 },
82 { "xmm5", 2048, 128 },
83 { "xmm6", 2176, 128 },
84 { "xmm7", 2304, 128 },
85 { "mxcsr", 2432, 32 },
86 #if defined(VGO_linux)
87 { "orig_eax", 2464, 32 }
90 static const char *expedite_regs
[] = { "ebp", "esp", "eip", 0 };
91 #define num_regs (sizeof (regs) / sizeof (regs[0]))
94 CORE_ADDR
get_pc (void)
98 collect_register_by_name ("eip", &pc
);
100 dlog(1, "stop pc is %p\n", (void *) pc
);
105 void set_pc (CORE_ADDR newpc
)
107 supply_register_by_name ("eip", &newpc
);
110 /* store registers in the guest state (gdbserver_to_valgrind)
111 or fetch register from the guest state (valgrind_to_gdbserver). */
113 void transfer_register (ThreadId tid
, int abs_regno
, void * buf
,
114 transfer_direction dir
, int size
, Bool
*mod
)
116 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
117 int set
= abs_regno
/ num_regs
;
118 int regno
= abs_regno
% num_regs
;
121 VexGuestX86State
* x86
= (VexGuestX86State
*) get_arch (set
, tst
);
124 // numbers here have to match the order of regs above
125 // Attention: gdb order does not match valgrind order.
126 case 0: VG_(transfer
) (&x86
->guest_EAX
, buf
, dir
, size
, mod
); break;
127 case 1: VG_(transfer
) (&x86
->guest_ECX
, buf
, dir
, size
, mod
); break;
128 case 2: VG_(transfer
) (&x86
->guest_EDX
, buf
, dir
, size
, mod
); break;
129 case 3: VG_(transfer
) (&x86
->guest_EBX
, buf
, dir
, size
, mod
); break;
130 case 4: VG_(transfer
) (&x86
->guest_ESP
, buf
, dir
, size
, mod
); break;
131 case 5: VG_(transfer
) (&x86
->guest_EBP
, buf
, dir
, size
, mod
); break;
132 case 6: VG_(transfer
) (&x86
->guest_ESI
, buf
, dir
, size
, mod
); break;
133 case 7: VG_(transfer
) (&x86
->guest_EDI
, buf
, dir
, size
, mod
); break;
134 case 8: VG_(transfer
) (&x86
->guest_EIP
, buf
, dir
, size
, mod
); break;
136 if (dir
== valgrind_to_gdbserver
) {
138 /* we can only retrieve the real flags (set 0)
139 retrieving shadow flags is not ok */
141 eflags
= LibVEX_GuestX86_get_eflags (x86
);
144 VG_(transfer
) (&eflags
, buf
, dir
, size
, mod
); break;
146 *mod
= False
; //GDBTD? how do we store eflags in libvex_guest_x86.h ???
149 case 10: VG_(transfer
) (&x86
->guest_CS
, buf
, dir
, size
, mod
); break;
150 case 11: VG_(transfer
) (&x86
->guest_SS
, buf
, dir
, size
, mod
); break;
151 case 12: VG_(transfer
) (&x86
->guest_DS
, buf
, dir
, size
, mod
); break;
152 case 13: VG_(transfer
) (&x86
->guest_ES
, buf
, dir
, size
, mod
); break;
153 case 14: VG_(transfer
) (&x86
->guest_FS
, buf
, dir
, size
, mod
); break;
154 case 15: VG_(transfer
) (&x86
->guest_GS
, buf
, dir
, size
, mod
); break;
158 case 19: /* register 16 to 23 are float registers 80 bits but 64 bits in valgrind */
163 if (dir
== valgrind_to_gdbserver
) {
165 convert_f64le_to_f80le ((UChar
*)&x86
->guest_FPREG
[regno
-16],
167 VG_(transfer
) (&fpreg80
, buf
, dir
, sizeof(fpreg80
), mod
);
170 convert_f80le_to_f64le (buf
, (UChar
*)&fpreg64
);
171 VG_(transfer
) (&x86
->guest_FPREG
[regno
-16], &fpreg64
,
172 dir
, sizeof(fpreg64
), mod
);
177 if (dir
== valgrind_to_gdbserver
) {
178 // vex only models the rounding bits (see libvex_guest_x86.h)
179 UWord value
= 0x037f;
180 value
|= x86
->guest_FPROUND
<< 10;
181 VG_(transfer
)(&value
, buf
, dir
, size
, mod
);
183 *mod
= False
; // GDBTD???? VEX { "fctrl", 1152, 32 },
187 if (dir
== valgrind_to_gdbserver
) {
188 UWord value
= x86
->guest_FC3210
;
189 value
|= (x86
->guest_FTOP
& 7) << 11;
190 VG_(transfer
)(&value
, buf
, dir
, size
, mod
);
192 *mod
= False
; // GDBTD???? VEX { "fstat", 1184, 32 },
196 if (dir
== valgrind_to_gdbserver
) {
197 // vex doesn't model these precisely
199 ((x86
->guest_FPTAG
[0] ? 0 : 3) << 0) |
200 ((x86
->guest_FPTAG
[1] ? 0 : 3) << 2) |
201 ((x86
->guest_FPTAG
[2] ? 0 : 3) << 4) |
202 ((x86
->guest_FPTAG
[3] ? 0 : 3) << 6) |
203 ((x86
->guest_FPTAG
[4] ? 0 : 3) << 8) |
204 ((x86
->guest_FPTAG
[5] ? 0 : 3) << 10) |
205 ((x86
->guest_FPTAG
[6] ? 0 : 3) << 12) |
206 ((x86
->guest_FPTAG
[7] ? 0 : 3) << 14);
207 VG_(transfer
)(&value
, buf
, dir
, size
, mod
);
209 *mod
= False
; // GDBTD???? VEX { "ftag", 1216, 32 },
212 case 27: *mod
= False
; break; // GDBTD???? VEX { "fiseg", 1248, 32 },
213 case 28: *mod
= False
; break; // GDBTD???? VEX { "fioff", 1280, 32 },
214 case 29: *mod
= False
; break; // GDBTD???? VEX { "foseg", 1312, 32 },
215 case 30: *mod
= False
; break; // GDBTD???? VEX { "fooff", 1344, 32 },
216 case 31: *mod
= False
; break; // GDBTD???? VEX { "fop", 1376, 32 },
217 case 32: VG_(transfer
) (&x86
->guest_XMM0
, buf
, dir
, size
, mod
); break;
218 case 33: VG_(transfer
) (&x86
->guest_XMM1
, buf
, dir
, size
, mod
); break;
219 case 34: VG_(transfer
) (&x86
->guest_XMM2
, buf
, dir
, size
, mod
); break;
220 case 35: VG_(transfer
) (&x86
->guest_XMM3
, buf
, dir
, size
, mod
); break;
221 case 36: VG_(transfer
) (&x86
->guest_XMM4
, buf
, dir
, size
, mod
); break;
222 case 37: VG_(transfer
) (&x86
->guest_XMM5
, buf
, dir
, size
, mod
); break;
223 case 38: VG_(transfer
) (&x86
->guest_XMM6
, buf
, dir
, size
, mod
); break;
224 case 39: VG_(transfer
) (&x86
->guest_XMM7
, buf
, dir
, size
, mod
); break;
226 if (dir
== valgrind_to_gdbserver
) {
227 // vex only models the rounding bits (see libvex_guest_x86.h)
228 UWord value
= 0x1f80;
229 value
|= x86
->guest_SSEROUND
<< 13;
230 VG_(transfer
)(&value
, buf
, dir
, size
, mod
);
232 *mod
= False
; // GDBTD???? VEX { "mxcsr", 2432, 32 },
235 case 41: *mod
= False
; break; // GDBTD???? VEX { "orig_eax", 2464, 32 },
236 default: vg_assert(0);
241 const char* target_xml (Bool shadow_mode
)
244 #if defined(VGO_linux)
245 return "i386-linux-valgrind.xml";
247 return "i386-coresse-valgrind.xml";
254 static CORE_ADDR
** target_get_dtv (ThreadState
*tst
)
256 VexGuestX86State
* x86
= (VexGuestX86State
*)&tst
->arch
.vex
;
257 // FIXME: should make the below formally visible from VEX.
258 extern ULong
x86g_use_seg_selector ( HWord ldt
, HWord gdt
,
259 UInt seg_selector
, UInt virtual_addr
);
261 ULong dtv_loc_g
= x86g_use_seg_selector (x86
->guest_LDT
,
265 if (dtv_loc_g
== 1ULL << 32) {
266 dlog(0, "Error getting x86 dtv\n");
269 CORE_ADDR dtv_loc
= dtv_loc_g
;
270 return (CORE_ADDR
**)dtv_loc
;
274 static struct valgrind_target_ops low_target
= {
286 void x86_init_architecture (struct valgrind_target_ops
*target
)
288 *target
= low_target
;
289 set_register_cache (regs
, num_regs
);
290 gdbserver_expedite_regs
= expedite_regs
;