2 /*--------------------------------------------------------------------*/
3 /*--- Platform-specific syscalls stuff. syswrap-amd64-solaris.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2014-2017 Petr Pavlu
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGP_amd64_solaris)
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"
44 #include "priv_types_n_macros.h"
45 #include "priv_syswrap-generic.h"
46 #include "priv_syswrap-solaris.h"
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
))
53 void ML_(call_on_new_stack_0_1
)(Addr stack
, /* %rdi */
54 Addr retaddr
, /* %rsi */
55 void (*f
)(Word
), /* %rdx */
56 Word arg1
); /* %rcx */
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) */
79 " ret\n" /* jump to f */
80 " ud2\n" /* should never get here */
84 /* This function is called to setup a context of a new Valgrind thread (which
85 will run the client code). */
86 void ML_(setup_start_thread_context
)(ThreadId tid
, vki_ucontext_t
*uc
)
88 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
89 UWord
*stack
= (UWord
*)tst
->os_state
.valgrind_stack_init_SP
;
91 VG_(memset
)(uc
, 0, sizeof(*uc
));
92 uc
->uc_flags
= VKI_UC_CPU
| VKI_UC_SIGMASK
;
94 /* Start the thread with everything blocked. */
95 VG_(sigfillset
)(&uc
->uc_sigmask
);
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
));
101 stack
[0] = 0; /* bogus return value */
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
;
109 /* Architecture-specific part of VG_(save_context). */
110 void ML_(save_machine_context
)(ThreadId tid
, vki_ucontext_t
*uc
,
113 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
114 struct vki_fpchip_state
*fs
115 = &uc
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
;
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
));
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
));
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
));
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
));
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. */
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
;
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
);
249 VG_TRACK(post_mem_write
, part
, tid
, (Addr
)&fs
->cw
, sizeof(fs
->cw
));
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
));
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
));
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
));
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
));
302 /* Status word (sw) at exception */
304 VG_TRACK(post_mem_write
, part
, tid
, (Addr
)&fs
->status
, sizeof(fs
->status
));
306 /* MXCSR at exception */
308 VG_TRACK(post_mem_write
, part
, tid
, (Addr
)&fs
->xstatus
,
309 sizeof(fs
->xstatus
));
312 /* Architecture-specific part of VG_(restore_context). */
313 void ML_(restore_machine_context
)(ThreadId tid
, vki_ucontext_t
*uc
,
314 CorePart part
, Bool esp_is_thrptr
)
316 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
317 struct vki_fpchip_state
*fs
318 = &uc
->uc_mcontext
.fpregs
.fp_reg_set
.fpchip_state
;
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
392 /* Ignore ERR and TRAPNO. */
394 /* Ignore segment registers. */
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
));
402 /* Rflags. Refer to the x86-solaris variant of this code for a detailed
408 Bool ok_restore
= False
;
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
);
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
;
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
));
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
);
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
);
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
);
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
),
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
),
468 VG_(debugLog
)(1, "syswrap-solaris",
469 "Cannot fully restore the CC_* guest state "
470 "values, using approximate rflags in thread "
475 if (uc
->uc_flags
& VKI_UC_FPU
) {
482 VG_TRACK(pre_mem_read
, part
, tid
,
483 "restore_machine_context(uc->uc_mcontext.fpregs..cw)",
484 (Addr
)&fs
->cw
, sizeof(fs
->cw
));
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
));
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
));
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
));
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
));
548 /* ---------------------------------------------------------------------
549 PRE/POST wrappers for AMD64/Solaris-specific syscalls
550 ------------------------------------------------------------------ */
552 #define PRE(name) DEFN_PRE_TEMPLATE(amd64_solaris, name)
553 #define POST(name) DEFN_POST_TEMPLATE(amd64_solaris, name)
560 #endif // defined(VGP_amd64_solaris)
562 /*--------------------------------------------------------------------*/
564 /*--------------------------------------------------------------------*/