1
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
10   Copyright (C) 2014-2015 Petr Pavlu
11      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 "
431                             "explicitly set value in thread %u.\n", tid);
432            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 "
449                                "restored in thread %u.\n", tid);
450               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 "
471                             "%u.\n", tid);
472      }
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,
542                      "Error restoring FP state in thread %u: %s.\n",
543                      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/*--------------------------------------------------------------------*/
565