sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame^] | 10 | Copyright (C) 2014-2017 Petr Pavlu |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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)) |
| 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 */ |
| 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). */ |
| 86 | void 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). */ |
| 110 | void 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). */ |
| 313 | void 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 " |
florian | b26101c | 2015-08-08 21:45:33 +0000 | [diff] [blame] | 431 | "explicitly set value in thread %u.\n", tid); |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 " |
florian | b26101c | 2015-08-08 21:45:33 +0000 | [diff] [blame] | 449 | "restored in thread %u.\n", tid); |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 " |
florian | b26101c | 2015-08-08 21:45:33 +0000 | [diff] [blame] | 471 | "%u.\n", tid); |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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, |
florian | b26101c | 2015-08-08 21:45:33 +0000 | [diff] [blame] | 542 | "Error restoring FP state in thread %u: %s.\n", |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 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 | /*--------------------------------------------------------------------*/ |