blob: a6ddf531d60481a974a69acddc8b2bd83f887fac [file] [log] [blame]
sewardj8eb8bab2015-07-21 14:44:28 +00001
2/*--------------------------------------------------------------------*/
3/*--- Platform-specific syscalls stuff. syswrap-amd64-solaris.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2014-2017 Petr Pavlu
sewardj8eb8bab2015-07-21 14:44:28 +000011 setup@dagobah.cz
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#if defined(VGP_amd64_solaris)
32
33#include "libvex_guest_offsets.h"
34#include "pub_core_basics.h"
35#include "pub_core_debuglog.h"
36#include "pub_core_vki.h"
37#include "pub_core_libcassert.h"
38#include "pub_core_libcbase.h"
39#include "pub_core_libcprint.h"
40#include "pub_core_libcsignal.h"
41#include "pub_core_tooliface.h"
42#include "pub_core_syswrap.h"
43
44#include "priv_types_n_macros.h"
45#include "priv_syswrap-generic.h"
46#include "priv_syswrap-solaris.h"
47
48
49/* Call f(arg1), but first switch stacks, using 'stack' as the new stack, and
50 use 'retaddr' as f's return-to address. Also, clear all the integer
51 registers before entering f. */
52__attribute__((noreturn))
53void ML_(call_on_new_stack_0_1)(Addr stack, /* %rdi */
54 Addr retaddr, /* %rsi */
55 void (*f)(Word), /* %rdx */
56 Word arg1); /* %rcx */
57__asm__ (
58".text\n"
59".globl vgModuleLocal_call_on_new_stack_0_1\n"
60"vgModuleLocal_call_on_new_stack_0_1:\n"
61" movq %rdi, %rsp\n" /* set stack */
62" movq %rcx, %rdi\n" /* set arg1 */
63" pushq %rsi\n" /* retaddr to stack */
64" pushq %rdx\n" /* f to stack */
65" movq $0, %rax\n" /* zero all GP regs (except %rdi) */
66" movq $0, %rbx\n"
67" movq $0, %rcx\n"
68" movq $0, %rdx\n"
69" movq $0, %rsi\n"
70" movq $0, %rbp\n"
71" movq $0, %r8\n"
72" movq $0, %r9\n"
73" movq $0, %r10\n"
74" movq $0, %r11\n"
75" movq $0, %r12\n"
76" movq $0, %r13\n"
77" movq $0, %r14\n"
78" movq $0, %r15\n"
79" ret\n" /* jump to f */
80" ud2\n" /* should never get here */
81".previous\n"
82);
83
84/* This function is called to setup a context of a new Valgrind thread (which
85 will run the client code). */
86void ML_(setup_start_thread_context)(ThreadId tid, vki_ucontext_t *uc)
87{
88 ThreadState *tst = VG_(get_ThreadState)(tid);
89 UWord *stack = (UWord*)tst->os_state.valgrind_stack_init_SP;
90
91 VG_(memset)(uc, 0, sizeof(*uc));
92 uc->uc_flags = VKI_UC_CPU | VKI_UC_SIGMASK;
93
94 /* Start the thread with everything blocked. */
95 VG_(sigfillset)(&uc->uc_sigmask);
96
97 /* Set up the stack, it should be always 16-byte aligned before doing
98 a function call, i.e. the first parameter is also 16-byte aligned. */
99 vg_assert(VG_IS_16_ALIGNED(stack));
100 stack -= 1;
101 stack[0] = 0; /* bogus return value */
102
103 /* Set up the registers. */
104 uc->uc_mcontext.gregs[VKI_REG_RDI] = (UWord)tst; /* the parameter */
105 uc->uc_mcontext.gregs[VKI_REG_RIP] = (UWord)ML_(start_thread_NORETURN);
106 uc->uc_mcontext.gregs[VKI_REG_RSP] = (UWord)stack;
107}
108
109/* Architecture-specific part of VG_(save_context). */
110void ML_(save_machine_context)(ThreadId tid, vki_ucontext_t *uc,
111 CorePart part)
112{
113 ThreadState *tst = VG_(get_ThreadState)(tid);
114 struct vki_fpchip_state *fs
115 = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state;
116 SizeT i;
117
118 /* CPU */
119 /* Common registers */
120 uc->uc_mcontext.gregs[VKI_REG_RIP] = tst->arch.vex.guest_RIP;
121 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RIP,
122 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RIP], sizeof(UWord));
123 uc->uc_mcontext.gregs[VKI_REG_RAX] = tst->arch.vex.guest_RAX;
124 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RAX,
125 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RAX], sizeof(UWord));
126 uc->uc_mcontext.gregs[VKI_REG_RBX] = tst->arch.vex.guest_RBX;
127 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RBX,
128 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RBX], sizeof(UWord));
129 uc->uc_mcontext.gregs[VKI_REG_RCX] = tst->arch.vex.guest_RCX;
130 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RCX,
131 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RCX], sizeof(UWord));
132 uc->uc_mcontext.gregs[VKI_REG_RDX] = tst->arch.vex.guest_RDX;
133 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RDX,
134 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RDX], sizeof(UWord));
135 uc->uc_mcontext.gregs[VKI_REG_RBP] = tst->arch.vex.guest_RBP;
136 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RBP,
137 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RBP], sizeof(UWord));
138 uc->uc_mcontext.gregs[VKI_REG_RSI] = tst->arch.vex.guest_RSI;
139 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RSI,
140 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RSI], sizeof(UWord));
141 uc->uc_mcontext.gregs[VKI_REG_RDI] = tst->arch.vex.guest_RDI;
142 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RDI,
143 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RDI], sizeof(UWord));
144 uc->uc_mcontext.gregs[VKI_REG_R8] = tst->arch.vex.guest_R8;
145 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R8,
146 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R8], sizeof(UWord));
147 uc->uc_mcontext.gregs[VKI_REG_R9] = tst->arch.vex.guest_R9;
148 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R9,
149 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R9], sizeof(UWord));
150 uc->uc_mcontext.gregs[VKI_REG_R10] = tst->arch.vex.guest_R10;
151 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R10,
152 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R10], sizeof(UWord));
153 uc->uc_mcontext.gregs[VKI_REG_R11] = tst->arch.vex.guest_R11;
154 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R11,
155 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R11], sizeof(UWord));
156 uc->uc_mcontext.gregs[VKI_REG_R12] = tst->arch.vex.guest_R12;
157 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R12,
158 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R12], sizeof(UWord));
159 uc->uc_mcontext.gregs[VKI_REG_R13] = tst->arch.vex.guest_R13;
160 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R13,
161 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R13], sizeof(UWord));
162 uc->uc_mcontext.gregs[VKI_REG_R14] = tst->arch.vex.guest_R14;
163 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R14,
164 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R14], sizeof(UWord));
165 uc->uc_mcontext.gregs[VKI_REG_R15] = tst->arch.vex.guest_R15;
166 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_R15,
167 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R15], sizeof(UWord));
168 uc->uc_mcontext.gregs[VKI_REG_RSP] = tst->arch.vex.guest_RSP;
169 VG_TRACK(copy_reg_to_mem, part, tid, OFFSET_amd64_RSP,
170 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RSP], sizeof(UWord));
171
172 /* ERR and TRAPNO */
173 uc->uc_mcontext.gregs[VKI_REG_ERR] = 0;
174 VG_TRACK(post_mem_write, part, tid,
175 (Addr)&uc->uc_mcontext.gregs[VKI_REG_ERR], sizeof(UWord));
176 uc->uc_mcontext.gregs[VKI_REG_TRAPNO] = 0;
177 VG_TRACK(post_mem_write, part, tid,
178 (Addr)&uc->uc_mcontext.gregs[VKI_REG_TRAPNO], sizeof(UWord));
179
180 /* Segment registers */
181 /* Valgrind does not support moves from/to segment registers on AMD64. The
182 values returned below are the ones that are set by the kernel when
183 a program is started. */
184 uc->uc_mcontext.gregs[VKI_REG_CS] = VKI_UCS_SEL;
185 VG_TRACK(post_mem_write, part, tid,
186 (Addr)&uc->uc_mcontext.gregs[VKI_REG_CS], sizeof(UWord));
187 uc->uc_mcontext.gregs[VKI_REG_DS] = 0;
188 VG_TRACK(post_mem_write, part, tid,
189 (Addr)&uc->uc_mcontext.gregs[VKI_REG_DS], sizeof(UWord));
190 uc->uc_mcontext.gregs[VKI_REG_SS] = VKI_UDS_SEL;
191 VG_TRACK(post_mem_write, part, tid,
192 (Addr)&uc->uc_mcontext.gregs[VKI_REG_SS], sizeof(UWord));
193 uc->uc_mcontext.gregs[VKI_REG_ES] = 0;
194 VG_TRACK(post_mem_write, part, tid,
195 (Addr)&uc->uc_mcontext.gregs[VKI_REG_ES], sizeof(UWord));
196 uc->uc_mcontext.gregs[VKI_REG_FS] = 0;
197 VG_TRACK(post_mem_write, part, tid,
198 (Addr)&uc->uc_mcontext.gregs[VKI_REG_FS], sizeof(UWord));
199 uc->uc_mcontext.gregs[VKI_REG_GS] = 0;
200 VG_TRACK(post_mem_write, part, tid,
201 (Addr)&uc->uc_mcontext.gregs[VKI_REG_GS], sizeof(UWord));
202
203 /* Segment bases */
204 uc->uc_mcontext.gregs[VKI_REG_FSBASE] = tst->arch.vex.guest_FS_CONST;
205 VG_TRACK(post_mem_write, part, tid,
206 (Addr)&uc->uc_mcontext.gregs[VKI_REG_FSBASE], sizeof(UWord));
207 uc->uc_mcontext.gregs[VKI_REG_GSBASE] = 0;
208 VG_TRACK(post_mem_write, part, tid,
209 (Addr)&uc->uc_mcontext.gregs[VKI_REG_GSBASE], sizeof(UWord));
210
211 /* Handle rflags. Refer to the x86-solaris variant of this code for
212 a detailed description. */
213 uc->uc_mcontext.gregs[VKI_REG_RFL] =
214 LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
215 VG_TRACK(post_mem_write, part, tid,
216 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RFL], sizeof(UWord));
217 VKI_UC_GUEST_CC_OP(uc) = tst->arch.vex.guest_CC_OP;
218 VKI_UC_GUEST_CC_NDEP(uc) = tst->arch.vex.guest_CC_NDEP;
219 VKI_UC_GUEST_CC_DEP1(uc) = tst->arch.vex.guest_CC_DEP1;
220 VG_TRACK(copy_reg_to_mem, part, tid,
221 offsetof(VexGuestAMD64State, guest_CC_DEP1),
222 (Addr)&VKI_UC_GUEST_CC_DEP1(uc), sizeof(UWord));
223 VKI_UC_GUEST_CC_DEP2(uc) = tst->arch.vex.guest_CC_DEP2;
224 VG_TRACK(copy_reg_to_mem, part, tid,
225 offsetof(VexGuestAMD64State, guest_CC_DEP2),
226 (Addr)&VKI_UC_GUEST_CC_DEP2(uc), sizeof(UWord));
227 VKI_UC_GUEST_RFLAGS_NEG(uc) = ~uc->uc_mcontext.gregs[VKI_REG_RFL];
228 /* Calculate a checksum. */
229 {
230 ULong buf[5];
231 ULong checksum;
232
233 buf[0] = VKI_UC_GUEST_CC_OP(uc);
234 buf[1] = VKI_UC_GUEST_CC_NDEP(uc);
235 buf[2] = VKI_UC_GUEST_CC_DEP1(uc);
236 buf[3] = VKI_UC_GUEST_CC_DEP2(uc);
237 buf[4] = uc->uc_mcontext.gregs[VKI_REG_RFL];
238 checksum = ML_(fletcher64)((UInt*)&buf, sizeof(buf) / sizeof(UInt));
239 VKI_UC_GUEST_RFLAGS_CHECKSUM(uc) = checksum;
240 }
241
242 /* FPU */
243 /* The fpregset_t structure on amd64 follows the layout that is used by the
244 FXSAVE instruction, therefore it is only necessary to call a VEX
245 function that simulates this instruction. */
246 LibVEX_GuestAMD64_fxsave(&tst->arch.vex, (HWord)fs);
247
248 /* Control word */
249 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->cw, sizeof(fs->cw));
250 /* Status word */
251 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->sw, sizeof(fs->sw));
252 /* Compressed tag word */
253 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->fctw, sizeof(fs->fctw));
254 /* Unused */
255 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->__fx_rsvd,
256 sizeof(fs->__fx_rsvd));
257 vg_assert(fs->__fx_rsvd == 0);
258 /* Last x87 opcode */
259 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->fop, sizeof(fs->fop));
260 vg_assert(fs->fop == 0);
261 /* Last x87 instruction pointer */
262 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->rip, sizeof(fs->rip));
263 vg_assert(fs->rip == 0);
264 /* Last x87 data pointer */
265 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->rdp, sizeof(fs->rdp));
266 vg_assert(fs->rdp == 0);
267 /* Media-instruction control and status register */
268 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->mxcsr, sizeof(fs->mxcsr));
269 /* Supported features in MXCSR */
270 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->mxcsr_mask,
271 sizeof(fs->mxcsr_mask));
272
273 /* ST registers */
274 for (i = 0; i < 8; i++) {
275 Addr addr = (Addr)&fs->st[i];
276 /* x87 uses 80b FP registers but VEX uses only 64b registers, thus we
277 have to lie here. :< */
278 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
279 guest_FPREG[i]), addr, sizeof(ULong));
280 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
281 guest_FPREG[i]), addr + 8, sizeof(UShort));
282 }
283
284 /* XMM registers */
285 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
286 guest_YMM0), (Addr)&fs->xmm[0], sizeof(U128));
287 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
288 guest_YMM1), (Addr)&fs->xmm[1], sizeof(U128));
289 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
290 guest_YMM2), (Addr)&fs->xmm[2], sizeof(U128));
291 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
292 guest_YMM3), (Addr)&fs->xmm[3], sizeof(U128));
293 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
294 guest_YMM4), (Addr)&fs->xmm[4], sizeof(U128));
295 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
296 guest_YMM5), (Addr)&fs->xmm[5], sizeof(U128));
297 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
298 guest_YMM6), (Addr)&fs->xmm[6], sizeof(U128));
299 VG_TRACK(copy_reg_to_mem, part, tid, offsetof(VexGuestAMD64State,
300 guest_YMM7), (Addr)&fs->xmm[7], sizeof(U128));
301
302 /* Status word (sw) at exception */
303 fs->status = 0;
304 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->status, sizeof(fs->status));
305
306 /* MXCSR at exception */
307 fs->xstatus = 0;
308 VG_TRACK(post_mem_write, part, tid, (Addr)&fs->xstatus,
309 sizeof(fs->xstatus));
310}
311
312/* Architecture-specific part of VG_(restore_context). */
313void ML_(restore_machine_context)(ThreadId tid, vki_ucontext_t *uc,
314 CorePart part, Bool esp_is_thrptr)
315{
316 ThreadState *tst = VG_(get_ThreadState)(tid);
317 struct vki_fpchip_state *fs
318 = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state;
319
320 /* CPU */
321 if (uc->uc_flags & VKI_UC_CPU) {
322 /* Common registers */
323 tst->arch.vex.guest_RIP = uc->uc_mcontext.gregs[VKI_REG_RIP];
324 VG_TRACK(copy_mem_to_reg, part, tid,
325 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RIP], OFFSET_amd64_RIP,
326 sizeof(UWord));
327 tst->arch.vex.guest_RAX = uc->uc_mcontext.gregs[VKI_REG_RAX];
328 VG_TRACK(copy_mem_to_reg, part, tid,
329 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RAX], OFFSET_amd64_RAX,
330 sizeof(UWord));
331 tst->arch.vex.guest_RBX = uc->uc_mcontext.gregs[VKI_REG_RBX];
332 VG_TRACK(copy_mem_to_reg, part, tid,
333 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RBX], OFFSET_amd64_RBX,
334 sizeof(UWord));
335 tst->arch.vex.guest_RCX = uc->uc_mcontext.gregs[VKI_REG_RCX];
336 VG_TRACK(copy_mem_to_reg, part, tid,
337 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RCX], OFFSET_amd64_RCX,
338 sizeof(UWord));
339 tst->arch.vex.guest_RDX = uc->uc_mcontext.gregs[VKI_REG_RDX];
340 VG_TRACK(copy_mem_to_reg, part, tid,
341 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RDX], OFFSET_amd64_RDX,
342 sizeof(UWord));
343 tst->arch.vex.guest_RBP = uc->uc_mcontext.gregs[VKI_REG_RBP];
344 VG_TRACK(copy_mem_to_reg, part, tid,
345 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RBP], OFFSET_amd64_RBP,
346 sizeof(UWord));
347 tst->arch.vex.guest_RSI = uc->uc_mcontext.gregs[VKI_REG_RSI];
348 VG_TRACK(copy_mem_to_reg, part, tid,
349 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RSI], OFFSET_amd64_RSI,
350 sizeof(UWord));
351 tst->arch.vex.guest_RDI = uc->uc_mcontext.gregs[VKI_REG_RDI];
352 VG_TRACK(copy_mem_to_reg, part, tid,
353 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RDI], OFFSET_amd64_RDI,
354 sizeof(UWord));
355 tst->arch.vex.guest_R8 = uc->uc_mcontext.gregs[VKI_REG_R8];
356 VG_TRACK(copy_mem_to_reg, part, tid,
357 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R8], OFFSET_amd64_R8,
358 sizeof(UWord));
359 tst->arch.vex.guest_R9 = uc->uc_mcontext.gregs[VKI_REG_R9];
360 VG_TRACK(copy_mem_to_reg, part, tid,
361 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R9], OFFSET_amd64_R9,
362 sizeof(UWord));
363 tst->arch.vex.guest_R10 = uc->uc_mcontext.gregs[VKI_REG_R10];
364 VG_TRACK(copy_mem_to_reg, part, tid,
365 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R10], OFFSET_amd64_R10,
366 sizeof(UWord));
367 tst->arch.vex.guest_R11 = uc->uc_mcontext.gregs[VKI_REG_R11];
368 VG_TRACK(copy_mem_to_reg, part, tid,
369 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R11], OFFSET_amd64_R11,
370 sizeof(UWord));
371 tst->arch.vex.guest_R12 = uc->uc_mcontext.gregs[VKI_REG_R12];
372 VG_TRACK(copy_mem_to_reg, part, tid,
373 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R12], OFFSET_amd64_R12,
374 sizeof(UWord));
375 tst->arch.vex.guest_R13 = uc->uc_mcontext.gregs[VKI_REG_R13];
376 VG_TRACK(copy_mem_to_reg, part, tid,
377 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R13], OFFSET_amd64_R13,
378 sizeof(UWord));
379 tst->arch.vex.guest_R14 = uc->uc_mcontext.gregs[VKI_REG_R14];
380 VG_TRACK(copy_mem_to_reg, part, tid,
381 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R14], OFFSET_amd64_R14,
382 sizeof(UWord));
383 tst->arch.vex.guest_R15 = uc->uc_mcontext.gregs[VKI_REG_R15];
384 VG_TRACK(copy_mem_to_reg, part, tid,
385 (Addr)&uc->uc_mcontext.gregs[VKI_REG_R15], OFFSET_amd64_R15,
386 sizeof(UWord));
387 tst->arch.vex.guest_RSP = uc->uc_mcontext.gregs[VKI_REG_RSP];
388 VG_TRACK(copy_mem_to_reg, part, tid,
389 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RSP], OFFSET_amd64_RSP,
390 sizeof(UWord));
391
392 /* Ignore ERR and TRAPNO. */
393
394 /* Ignore segment registers. */
395
396 /* Segment bases */
397 tst->arch.vex.guest_FS_CONST = uc->uc_mcontext.gregs[VKI_REG_FSBASE];
398 VG_TRACK(copy_mem_to_reg, part, tid,
399 (Addr)&uc->uc_mcontext.gregs[VKI_REG_FSBASE],
400 offsetof(VexGuestAMD64State, guest_FS_CONST), sizeof(UWord));
401
402 /* Rflags. Refer to the x86-solaris variant of this code for a detailed
403 description. */
404 {
405 ULong rflags;
406 ULong orig_rflags;
407 ULong new_rflags;
408 Bool ok_restore = False;
409
410 VG_TRACK(pre_mem_read, part, tid,
411 "restore_machine_context(uc->uc_mcontext.gregs[VKI_REG_RFL])",
412 (Addr)&uc->uc_mcontext.gregs[VKI_REG_RFL], sizeof(UWord));
413 rflags = uc->uc_mcontext.gregs[VKI_REG_RFL];
414 orig_rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
415 new_rflags = rflags;
416 /* The kernel disallows the ID flag to be changed via the setcontext
417 call, thus do the same. */
418 if (orig_rflags & VKI_RFLAGS_ID_BIT)
419 new_rflags |= VKI_RFLAGS_ID_BIT;
420 else
421 new_rflags &= ~VKI_RFLAGS_ID_BIT;
422 LibVEX_GuestAMD64_put_rflags(new_rflags, &tst->arch.vex);
423 VG_TRACK(post_reg_write, part, tid,
424 offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(UWord));
425 VG_TRACK(post_reg_write, part, tid,
426 offsetof(VexGuestAMD64State, guest_CC_DEP2), sizeof(UWord));
427
428 if (rflags != ~VKI_UC_GUEST_RFLAGS_NEG(uc)) {
429 VG_(debugLog)(1, "syswrap-solaris",
430 "The rflags value was restored from an "
florianb26101c2015-08-08 21:45:33 +0000431 "explicitly set value in thread %u.\n", tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000432 ok_restore = True;
433 }
434 else {
435 ULong buf[5];
436 ULong checksum;
437
438 buf[0] = VKI_UC_GUEST_CC_OP(uc);
439 buf[1] = VKI_UC_GUEST_CC_NDEP(uc);
440 buf[2] = VKI_UC_GUEST_CC_DEP1(uc);
441 buf[3] = VKI_UC_GUEST_CC_DEP2(uc);
442 buf[4] = rflags;
443 checksum = ML_(fletcher64)((UInt*)&buf,
444 sizeof(buf) / sizeof(UInt));
445 if (checksum == VKI_UC_GUEST_RFLAGS_CHECKSUM(uc)) {
446 /* Check ok, the full restoration is possible. */
447 VG_(debugLog)(1, "syswrap-solaris",
448 "The CC_* guest state values were fully "
florianb26101c2015-08-08 21:45:33 +0000449 "restored in thread %u.\n", tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000450 ok_restore = True;
451
452 tst->arch.vex.guest_CC_OP = VKI_UC_GUEST_CC_OP(uc);
453 tst->arch.vex.guest_CC_NDEP = VKI_UC_GUEST_CC_NDEP(uc);
454 tst->arch.vex.guest_CC_DEP1 = VKI_UC_GUEST_CC_DEP1(uc);
455 VG_TRACK(copy_mem_to_reg, part, tid,
456 (Addr)&VKI_UC_GUEST_CC_DEP1(uc),
457 offsetof(VexGuestAMD64State, guest_CC_DEP1),
458 sizeof(UWord));
459 tst->arch.vex.guest_CC_DEP2 = VKI_UC_GUEST_CC_DEP2(uc);
460 VG_TRACK(copy_mem_to_reg, part, tid,
461 (Addr)&VKI_UC_GUEST_CC_DEP2(uc),
462 offsetof(VexGuestAMD64State, guest_CC_DEP2),
463 sizeof(UWord));
464 }
465 }
466
467 if (!ok_restore)
468 VG_(debugLog)(1, "syswrap-solaris",
469 "Cannot fully restore the CC_* guest state "
470 "values, using approximate rflags in thread "
florianb26101c2015-08-08 21:45:33 +0000471 "%u.\n", tid);
sewardj8eb8bab2015-07-21 14:44:28 +0000472 }
473 }
474
475 if (uc->uc_flags & VKI_UC_FPU) {
476 /* FPU */
477 VexEmNote note;
478 SizeT i;
479
480 /* x87 */
481 /* Control word */
482 VG_TRACK(pre_mem_read, part, tid,
483 "restore_machine_context(uc->uc_mcontext.fpregs..cw)",
484 (Addr)&fs->cw, sizeof(fs->cw));
485 /* Status word */
486 VG_TRACK(pre_mem_read, part, tid,
487 "restore_machine_context(uc->uc_mcontext.fpregs..sw)",
488 (Addr)&fs->sw, sizeof(fs->sw));
489 /* Compressed tag word */
490 VG_TRACK(pre_mem_read, part, tid,
491 "restore_machine_context(uc->uc_mcontext.fpregs..fctw)",
492 (Addr)&fs->fctw, sizeof(fs->fctw));
493 /* Last x87 opcode */
494 VG_TRACK(pre_mem_read, part, tid,
495 "restore_machine_context(uc->uc_mcontext.fpregs..fop)",
496 (Addr)&fs->fop, sizeof(fs->fop));
497 /* Last x87 instruction pointer */
498 VG_TRACK(pre_mem_read, part, tid,
499 "restore_machine_context(uc->uc_mcontext.fpregs..rip)",
500 (Addr)&fs->rip, sizeof(fs->rip));
501 /* Last x87 data pointer */
502 VG_TRACK(pre_mem_read, part, tid,
503 "restore_machine_context(uc->uc_mcontext.fpregs..rdp)",
504 (Addr)&fs->rdp, sizeof(fs->rdp));
505 /* Media-instruction control and status register */
506 VG_TRACK(pre_mem_read, part, tid,
507 "restore_machine_context(uc->uc_mcontext.fpregs..mxcsr)",
508 (Addr)&fs->mxcsr, sizeof(fs->mxcsr));
509 /* Supported features in MXCSR */
510 VG_TRACK(pre_mem_read, part, tid,
511 "restore_machine_context(uc->uc_mcontext.fpregs..mxcsr_mask)",
512 (Addr)&fs->mxcsr_mask, sizeof(fs->mxcsr_mask));
513
514 /* ST registers */
515 for (i = 0; i < 8; i++) {
516 Addr addr = (Addr)&fs->st[i];
517 VG_TRACK(copy_mem_to_reg, part, tid, addr,
518 offsetof(VexGuestAMD64State, guest_FPREG[i]), sizeof(ULong));
519 }
520
521 /* XMM registers */
522 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[0],
523 offsetof(VexGuestAMD64State, guest_YMM0), sizeof(U128));
524 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[1],
525 offsetof(VexGuestAMD64State, guest_YMM1), sizeof(U128));
526 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[2],
527 offsetof(VexGuestAMD64State, guest_YMM2), sizeof(U128));
528 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[3],
529 offsetof(VexGuestAMD64State, guest_YMM3), sizeof(U128));
530 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[4],
531 offsetof(VexGuestAMD64State, guest_YMM4), sizeof(U128));
532 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[5],
533 offsetof(VexGuestAMD64State, guest_YMM5), sizeof(U128));
534 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[6],
535 offsetof(VexGuestAMD64State, guest_YMM6), sizeof(U128));
536 VG_TRACK(copy_mem_to_reg, part, tid, (Addr)&fs->xmm[7],
537 offsetof(VexGuestAMD64State, guest_YMM7), sizeof(U128));
538
539 note = LibVEX_GuestAMD64_fxrstor((HWord)fs, &tst->arch.vex);
540 if (note != EmNote_NONE)
541 VG_(message)(Vg_UserMsg,
florianb26101c2015-08-08 21:45:33 +0000542 "Error restoring FP state in thread %u: %s.\n",
sewardj8eb8bab2015-07-21 14:44:28 +0000543 tid, LibVEX_EmNote_string(note));
544 }
545}
546
547
548/* ---------------------------------------------------------------------
549 PRE/POST wrappers for AMD64/Solaris-specific syscalls
550 ------------------------------------------------------------------ */
551
552#define PRE(name) DEFN_PRE_TEMPLATE(amd64_solaris, name)
553#define POST(name) DEFN_POST_TEMPLATE(amd64_solaris, name)
554
555/* implementation */
556
557#undef PRE
558#undef POST
559
560#endif // defined(VGP_amd64_solaris)
561
562/*--------------------------------------------------------------------*/
563/*--- end ---*/
564/*--------------------------------------------------------------------*/