drd/test: Fix most gcc 8 compiler warnings
[valgrind.git] / coregrind / m_syswrap / syswrap-main.c
bloba2876c5fb1d8586da12b5dbdbb51b794496a3bb3
2 /*--------------------------------------------------------------------*/
3 /*--- Handle system calls. syswrap-main.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
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
26 02111-1307, USA.
28 The GNU General Public License is contained in the file COPYING.
31 #include "libvex_guest_offsets.h"
32 #include "libvex_trc_values.h"
33 #include "pub_core_basics.h"
34 #include "pub_core_aspacemgr.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_vkiscnums.h"
37 #include "pub_core_threadstate.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcproc.h" // For VG_(getpid)()
42 #include "pub_core_libcsignal.h"
43 #include "pub_core_scheduler.h" // For VG_({acquire,release}_BigLock),
44 // and VG_(vg_yield)
45 #include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
46 #include "pub_core_tooliface.h"
47 #include "pub_core_options.h"
48 #include "pub_core_signals.h" // For VG_SIGVGKILL, VG_(poll_signals)
49 #include "pub_core_syscall.h"
50 #include "pub_core_machine.h"
51 #include "pub_core_mallocfree.h"
52 #include "pub_core_syswrap.h"
53 #include "pub_core_gdbserver.h" // VG_(gdbserver_report_syscall)
55 #include "priv_types_n_macros.h"
56 #include "priv_syswrap-main.h"
58 #if defined(VGO_darwin)
59 #include "priv_syswrap-darwin.h"
60 #endif
62 /* Useful info which needs to be recorded somewhere:
63 Use of registers in syscalls is:
65 NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
66 LINUX:
67 x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
68 amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
69 ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
70 ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
71 arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
72 mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
73 mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
74 arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
76 On s390x the svc instruction is used for system calls. The system call
77 number is encoded in the instruction (8 bit immediate field). Since Linux
78 2.6 it is also allowed to use svc 0 with the system call number in r1.
79 This was introduced for system calls >255, but works for all. It is
80 also possible to see the svc 0 together with an EXecute instruction, that
81 fills in the immediate field.
82 s390x r1/SVC r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1)
84 NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
85 DARWIN:
86 x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
87 amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
89 For x86-darwin, "+N" denotes "in memory at N(%esp)"; ditto
90 amd64-darwin. Apparently 0(%esp) is some kind of return address
91 (perhaps for syscalls done with "sysenter"?) I don't think it is
92 relevant for syscalls done with "int $0x80/1/2".
94 SOLARIS:
95 x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
96 amd64 rax rdi rsi rdx r10 r8 r9 +8 +16 rdx:rax, rflags.c
98 "+N" denotes "in memory at N(%esp)". Solaris also supports fasttrap
99 syscalls. Fasttraps do not take any parameters (except of the sysno in eax)
100 and never fail (if the sysno is valid).
103 /* This is the top level of the system-call handler module. All
104 system calls are channelled through here, doing two things:
106 * notify the tool of the events (mem/reg reads, writes) happening
108 * perform the syscall, usually by passing it along to the kernel
109 unmodified.
111 A magical piece of assembly code, do_syscall_for_client_WRK, in
112 syscall-$PLATFORM.S does the tricky bit of passing a syscall to the
113 kernel, whilst having the simulator retain control.
116 /* The main function is VG_(client_syscall). The simulation calls it
117 whenever a client thread wants to do a syscall. The following is a
118 sketch of what it does.
120 * Ensures the root thread's stack is suitably mapped. Tedious and
121 arcane. See big big comment in VG_(client_syscall).
123 * First, it rounds up the syscall number and args (which is a
124 platform dependent activity) and puts them in a struct ("args")
125 and also a copy in "orig_args".
127 The pre/post wrappers refer to these structs and so no longer
128 need magic macros to access any specific registers. This struct
129 is stored in thread-specific storage.
132 * The pre-wrapper is called, passing it a pointer to struct
133 "args".
136 * The pre-wrapper examines the args and pokes the tool
137 appropriately. It may modify the args; this is why "orig_args"
138 is also stored.
140 The pre-wrapper may choose to 'do' the syscall itself, and
141 concludes one of three outcomes:
143 Success(N) -- syscall is already complete, with success;
144 result is N
146 Fail(N) -- syscall is already complete, with failure;
147 error code is N
149 HandToKernel -- (the usual case): this needs to be given to
150 the kernel to be done, using the values in
151 the possibly-modified "args" struct.
153 In addition, the pre-wrapper may set some flags:
155 MayBlock -- only applicable when outcome==HandToKernel
157 PostOnFail -- only applicable when outcome==HandToKernel or Fail
160 * If the pre-outcome is HandToKernel, the syscall is duly handed
161 off to the kernel (perhaps involving some thread switchery, but
162 that's not important). This reduces the possible set of outcomes
163 to either Success(N) or Fail(N).
166 * The outcome (Success(N) or Fail(N)) is written back to the guest
167 register(s). This is platform specific:
169 x86: Success(N) ==> eax = N
170 Fail(N) ==> eax = -N
172 ditto amd64
174 ppc32: Success(N) ==> r3 = N, CR0.SO = 0
175 Fail(N) ==> r3 = N, CR0.SO = 1
177 Darwin:
178 x86: Success(N) ==> edx:eax = N, cc = 0
179 Fail(N) ==> edx:eax = N, cc = 1
181 s390x: Success(N) ==> r2 = N
182 Fail(N) ==> r2 = -N
184 Solaris:
185 x86: Success(N) ==> edx:eax = N, cc = 0
186 Fail(N) ==> eax = N, cc = 1
187 Same applies for fasttraps except they never fail.
189 * The post wrapper is called if:
191 - it exists, and
192 - outcome==Success or (outcome==Fail and PostOnFail is set)
194 The post wrapper is passed the adulterated syscall args (struct
195 "args"), and the syscall outcome (viz, Success(N) or Fail(N)).
197 There are several other complications, primarily to do with
198 syscalls getting interrupted, explained in comments in the code.
201 /* CAVEATS for writing wrappers. It is important to follow these!
203 The macros defined in priv_types_n_macros.h are designed to help
204 decouple the wrapper logic from the actual representation of
205 syscall args/results, since these wrappers are designed to work on
206 multiple platforms.
208 Sometimes a PRE wrapper will complete the syscall itself, without
209 handing it to the kernel. It will use one of SET_STATUS_Success,
210 SET_STATUS_Failure or SET_STATUS_from_SysRes to set the return
211 value. It is critical to appreciate that use of the macro does not
212 immediately cause the underlying guest state to be updated -- that
213 is done by the driver logic in this file, when the wrapper returns.
215 As a result, PRE wrappers of the following form will malfunction:
217 PRE(fooble)
219 ... do stuff ...
220 SET_STATUS_Somehow(...)
222 // do something that assumes guest state is up to date
225 In particular, direct or indirect calls to VG_(poll_signals) after
226 setting STATUS can cause the guest state to be read (in order to
227 build signal frames). Do not do this. If you want a signal poll
228 after the syscall goes through, do "*flags |= SfPollAfter" and the
229 driver logic will do it for you.
231 -----------
233 Another critical requirement following introduction of new address
234 space manager (JRS, 20050923):
236 In a situation where the mappedness of memory has changed, aspacem
237 should be notified BEFORE the tool. Hence the following is
238 correct:
240 Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start);
241 VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start );
242 if (d)
243 VG_(discard_translations)(s->start, s->end+1 - s->start);
245 whilst this is wrong:
247 VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start );
248 Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start);
249 if (d)
250 VG_(discard_translations)(s->start, s->end+1 - s->start);
252 The reason is that the tool may itself ask aspacem for more shadow
253 memory as a result of the VG_TRACK call. In such a situation it is
254 critical that aspacem's segment array is up to date -- hence the
255 need to notify aspacem first.
257 -----------
259 Also .. take care to call VG_(discard_translations) whenever
260 memory with execute permissions is unmapped.
264 /* ---------------------------------------------------------------------
265 Do potentially blocking syscall for the client, and mess with
266 signal masks at the same time.
267 ------------------------------------------------------------------ */
269 /* Perform a syscall on behalf of a client thread, using a specific
270 signal mask. On completion, the signal mask is set to restore_mask
271 (which presumably blocks almost everything). If a signal happens
272 during the syscall, the handler should call
273 VG_(fixup_guest_state_after_syscall_interrupted) to adjust the
274 thread's context to do the right thing.
276 The _WRK function is handwritten assembly, implemented per-platform
277 in coregrind/m_syswrap/syscall-$PLAT.S. It has some very magic
278 properties. See comments at the top of
279 VG_(fixup_guest_state_after_syscall_interrupted) below for details.
281 This function (these functions) are required to return zero in case
282 of success (even if the syscall itself failed), and nonzero if the
283 sigprocmask-swizzling calls failed. We don't actually care about
284 the failure values from sigprocmask, although most of the assembly
285 implementations do attempt to return that, using the convention
286 0 for success, or 0x8000 | error-code for failure.
288 #if defined(VGO_linux)
289 extern
290 UWord ML_(do_syscall_for_client_WRK)( Word syscallno,
291 void* guest_state,
292 const vki_sigset_t *syscall_mask,
293 const vki_sigset_t *restore_mask,
294 Word sigsetSzB );
295 #elif defined(VGO_darwin)
296 extern
297 UWord ML_(do_syscall_for_client_unix_WRK)( Word syscallno,
298 void* guest_state,
299 const vki_sigset_t *syscall_mask,
300 const vki_sigset_t *restore_mask,
301 Word sigsetSzB ); /* unused */
302 extern
303 UWord ML_(do_syscall_for_client_mach_WRK)( Word syscallno,
304 void* guest_state,
305 const vki_sigset_t *syscall_mask,
306 const vki_sigset_t *restore_mask,
307 Word sigsetSzB ); /* unused */
308 extern
309 UWord ML_(do_syscall_for_client_mdep_WRK)( Word syscallno,
310 void* guest_state,
311 const vki_sigset_t *syscall_mask,
312 const vki_sigset_t *restore_mask,
313 Word sigsetSzB ); /* unused */
314 #elif defined(VGO_solaris)
315 extern
316 UWord ML_(do_syscall_for_client_WRK)( Word syscallno,
317 void* guest_state,
318 const vki_sigset_t *syscall_mask,
319 const vki_sigset_t *restore_mask,
320 UChar *cflag);
321 UWord ML_(do_syscall_for_client_dret_WRK)( Word syscallno,
322 void* guest_state,
323 const vki_sigset_t *syscall_mask,
324 const vki_sigset_t *restore_mask,
325 UChar *cflag);
326 #else
327 # error "Unknown OS"
328 #endif
331 static
332 void do_syscall_for_client ( Int syscallno,
333 ThreadState* tst,
334 const vki_sigset_t* syscall_mask )
336 vki_sigset_t saved;
337 UWord err;
338 # if defined(VGO_linux)
339 err = ML_(do_syscall_for_client_WRK)(
340 syscallno, &tst->arch.vex,
341 syscall_mask, &saved, sizeof(vki_sigset_t)
343 # elif defined(VGO_darwin)
344 switch (VG_DARWIN_SYSNO_CLASS(syscallno)) {
345 case VG_DARWIN_SYSCALL_CLASS_UNIX:
346 err = ML_(do_syscall_for_client_unix_WRK)(
347 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
348 syscall_mask, &saved, 0/*unused:sigsetSzB*/
350 break;
351 case VG_DARWIN_SYSCALL_CLASS_MACH:
352 err = ML_(do_syscall_for_client_mach_WRK)(
353 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
354 syscall_mask, &saved, 0/*unused:sigsetSzB*/
356 break;
357 case VG_DARWIN_SYSCALL_CLASS_MDEP:
358 err = ML_(do_syscall_for_client_mdep_WRK)(
359 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
360 syscall_mask, &saved, 0/*unused:sigsetSzB*/
362 break;
363 default:
364 vg_assert(0);
365 /*NOTREACHED*/
366 break;
368 # elif defined(VGO_solaris)
369 UChar cflag;
371 /* Fasttraps or anything else cannot go through this path. */
372 vg_assert(VG_SOLARIS_SYSNO_CLASS(syscallno)
373 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
375 /* If the syscall is a door_return call then it has to be handled very
376 differently. */
377 if (tst->os_state.in_door_return)
378 err = ML_(do_syscall_for_client_dret_WRK)(
379 syscallno, &tst->arch.vex,
380 syscall_mask, &saved, &cflag
382 else
383 err = ML_(do_syscall_for_client_WRK)(
384 syscallno, &tst->arch.vex,
385 syscall_mask, &saved, &cflag
388 /* Save the carry flag. */
389 # if defined(VGP_x86_solaris)
390 LibVEX_GuestX86_put_eflag_c(cflag, &tst->arch.vex);
391 # elif defined(VGP_amd64_solaris)
392 LibVEX_GuestAMD64_put_rflag_c(cflag, &tst->arch.vex);
393 # else
394 # error "Unknown platform"
395 # endif
397 # else
398 # error "Unknown OS"
399 # endif
400 vg_assert2(
401 err == 0,
402 "ML_(do_syscall_for_client_WRK): sigprocmask error %lu",
403 err & 0xFFF
408 /* ---------------------------------------------------------------------
409 Impedance matchers and misc helpers
410 ------------------------------------------------------------------ */
412 static
413 Bool eq_SyscallArgs ( SyscallArgs* a1, SyscallArgs* a2 )
415 return a1->sysno == a2->sysno
416 && a1->arg1 == a2->arg1
417 && a1->arg2 == a2->arg2
418 && a1->arg3 == a2->arg3
419 && a1->arg4 == a2->arg4
420 && a1->arg5 == a2->arg5
421 && a1->arg6 == a2->arg6
422 && a1->arg7 == a2->arg7
423 && a1->arg8 == a2->arg8;
426 static
427 Bool eq_SyscallStatus ( UInt sysno, SyscallStatus* s1, SyscallStatus* s2 )
429 /* was: return s1->what == s2->what && sr_EQ( s1->sres, s2->sres ); */
430 if (s1->what == s2->what && sr_EQ( sysno, s1->sres, s2->sres ))
431 return True;
432 # if defined(VGO_darwin)
433 /* Darwin-specific debugging guff */
434 vg_assert(s1->what == s2->what);
435 VG_(printf)("eq_SyscallStatus:\n");
436 VG_(printf)(" {%lu %lu %u}\n", s1->sres._wLO, s1->sres._wHI, s1->sres._mode);
437 VG_(printf)(" {%lu %lu %u}\n", s2->sres._wLO, s2->sres._wHI, s2->sres._mode);
438 vg_assert(0);
439 # endif
440 return False;
443 /* Convert between SysRes and SyscallStatus, to the extent possible. */
445 static
446 SyscallStatus convert_SysRes_to_SyscallStatus ( SysRes res )
448 SyscallStatus status;
449 status.what = SsComplete;
450 status.sres = res;
451 return status;
455 /* Impedance matchers. These convert syscall arg or result data from
456 the platform-specific in-guest-state format to the canonical
457 formats, and back. */
459 static
460 void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical,
461 /*IN*/ VexGuestArchState* gst_vanilla,
462 /*IN*/ UInt trc )
464 #if defined(VGP_x86_linux)
465 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
466 canonical->sysno = gst->guest_EAX;
467 canonical->arg1 = gst->guest_EBX;
468 canonical->arg2 = gst->guest_ECX;
469 canonical->arg3 = gst->guest_EDX;
470 canonical->arg4 = gst->guest_ESI;
471 canonical->arg5 = gst->guest_EDI;
472 canonical->arg6 = gst->guest_EBP;
473 canonical->arg7 = 0;
474 canonical->arg8 = 0;
476 #elif defined(VGP_amd64_linux)
477 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
478 canonical->sysno = gst->guest_RAX;
479 canonical->arg1 = gst->guest_RDI;
480 canonical->arg2 = gst->guest_RSI;
481 canonical->arg3 = gst->guest_RDX;
482 canonical->arg4 = gst->guest_R10;
483 canonical->arg5 = gst->guest_R8;
484 canonical->arg6 = gst->guest_R9;
485 canonical->arg7 = 0;
486 canonical->arg8 = 0;
488 #elif defined(VGP_ppc32_linux)
489 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
490 canonical->sysno = gst->guest_GPR0;
491 canonical->arg1 = gst->guest_GPR3;
492 canonical->arg2 = gst->guest_GPR4;
493 canonical->arg3 = gst->guest_GPR5;
494 canonical->arg4 = gst->guest_GPR6;
495 canonical->arg5 = gst->guest_GPR7;
496 canonical->arg6 = gst->guest_GPR8;
497 canonical->arg7 = 0;
498 canonical->arg8 = 0;
500 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
501 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
502 canonical->sysno = gst->guest_GPR0;
503 canonical->arg1 = gst->guest_GPR3;
504 canonical->arg2 = gst->guest_GPR4;
505 canonical->arg3 = gst->guest_GPR5;
506 canonical->arg4 = gst->guest_GPR6;
507 canonical->arg5 = gst->guest_GPR7;
508 canonical->arg6 = gst->guest_GPR8;
509 canonical->arg7 = 0;
510 canonical->arg8 = 0;
512 #elif defined(VGP_arm_linux)
513 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
514 canonical->sysno = gst->guest_R7;
515 canonical->arg1 = gst->guest_R0;
516 canonical->arg2 = gst->guest_R1;
517 canonical->arg3 = gst->guest_R2;
518 canonical->arg4 = gst->guest_R3;
519 canonical->arg5 = gst->guest_R4;
520 canonical->arg6 = gst->guest_R5;
521 canonical->arg7 = 0;
522 canonical->arg8 = 0;
524 #elif defined(VGP_arm64_linux)
525 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
526 canonical->sysno = gst->guest_X8;
527 canonical->arg1 = gst->guest_X0;
528 canonical->arg2 = gst->guest_X1;
529 canonical->arg3 = gst->guest_X2;
530 canonical->arg4 = gst->guest_X3;
531 canonical->arg5 = gst->guest_X4;
532 canonical->arg6 = gst->guest_X5;
533 canonical->arg7 = 0;
534 canonical->arg8 = 0;
536 #elif defined(VGP_mips32_linux)
537 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
538 canonical->sysno = gst->guest_r2; // v0
539 if (canonical->sysno == __NR_exit) {
540 canonical->arg1 = gst->guest_r4; // a0
541 canonical->arg2 = 0;
542 canonical->arg3 = 0;
543 canonical->arg4 = 0;
544 canonical->arg5 = 0;
545 canonical->arg6 = 0;
546 canonical->arg8 = 0;
547 } else if (canonical->sysno != __NR_syscall) {
548 canonical->arg1 = gst->guest_r4; // a0
549 canonical->arg2 = gst->guest_r5; // a1
550 canonical->arg3 = gst->guest_r6; // a2
551 canonical->arg4 = gst->guest_r7; // a3
552 canonical->arg5 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP)
553 canonical->arg6 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP)
554 canonical->arg7 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP)
555 canonical->arg8 = 0;
556 } else {
557 // Fixme hack handle syscall()
558 canonical->sysno = gst->guest_r4; // a0
559 canonical->arg1 = gst->guest_r5; // a1
560 canonical->arg2 = gst->guest_r6; // a2
561 canonical->arg3 = gst->guest_r7; // a3
562 canonical->arg4 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp)
563 canonical->arg5 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP/sp)
564 canonical->arg6 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP/sp)
565 canonical->arg8 = __NR_syscall;
568 #elif defined(VGP_mips64_linux)
569 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
570 canonical->sysno = gst->guest_r2; // v0
571 canonical->arg1 = gst->guest_r4; // a0
572 canonical->arg2 = gst->guest_r5; // a1
573 canonical->arg3 = gst->guest_r6; // a2
574 canonical->arg4 = gst->guest_r7; // a3
575 canonical->arg5 = gst->guest_r8; // a4
576 canonical->arg6 = gst->guest_r9; // a5
578 #elif defined(VGP_x86_darwin)
579 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
580 UWord *stack = (UWord *)gst->guest_ESP;
581 // GrP fixme hope syscalls aren't called with really shallow stacks...
582 canonical->sysno = gst->guest_EAX;
583 if (canonical->sysno != 0) {
584 // stack[0] is return address
585 canonical->arg1 = stack[1];
586 canonical->arg2 = stack[2];
587 canonical->arg3 = stack[3];
588 canonical->arg4 = stack[4];
589 canonical->arg5 = stack[5];
590 canonical->arg6 = stack[6];
591 canonical->arg7 = stack[7];
592 canonical->arg8 = stack[8];
593 } else {
594 // GrP fixme hack handle syscall()
595 // GrP fixme what about __syscall() ?
596 // stack[0] is return address
597 // DDD: the tool can't see that the params have been shifted! Can
598 // lead to incorrect checking, I think, because the PRRAn/PSARn
599 // macros will mention the pre-shifted args.
600 canonical->sysno = stack[1];
601 vg_assert(canonical->sysno != 0);
602 canonical->arg1 = stack[2];
603 canonical->arg2 = stack[3];
604 canonical->arg3 = stack[4];
605 canonical->arg4 = stack[5];
606 canonical->arg5 = stack[6];
607 canonical->arg6 = stack[7];
608 canonical->arg7 = stack[8];
609 canonical->arg8 = stack[9];
611 PRINT("SYSCALL[%d,?](0) syscall(%s, ...); please stand by...\n",
612 VG_(getpid)(), /*tid,*/
613 VG_SYSNUM_STRING(canonical->sysno));
616 // Here we determine what kind of syscall it was by looking at the
617 // interrupt kind, and then encode the syscall number using the 64-bit
618 // encoding for Valgrind's internal use.
620 // DDD: Would it be better to stash the JMP kind into the Darwin
621 // thread state rather than passing in the trc?
622 switch (trc) {
623 case VEX_TRC_JMP_SYS_INT128:
624 // int $0x80 = Unix, 64-bit result
625 vg_assert(canonical->sysno >= 0);
626 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno);
627 break;
628 case VEX_TRC_JMP_SYS_SYSENTER:
629 // syscall = Unix, 32-bit result
630 // OR Mach, 32-bit result
631 if (canonical->sysno >= 0) {
632 // GrP fixme hack: 0xffff == I386_SYSCALL_NUMBER_MASK
633 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno
634 & 0xffff);
635 } else {
636 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno);
638 break;
639 case VEX_TRC_JMP_SYS_INT129:
640 // int $0x81 = Mach, 32-bit result
641 vg_assert(canonical->sysno < 0);
642 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno);
643 break;
644 case VEX_TRC_JMP_SYS_INT130:
645 // int $0x82 = mdep, 32-bit result
646 vg_assert(canonical->sysno >= 0);
647 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MDEP(canonical->sysno);
648 break;
649 default:
650 vg_assert(0);
651 break;
654 #elif defined(VGP_amd64_darwin)
655 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
656 UWord *stack = (UWord *)gst->guest_RSP;
658 vg_assert(trc == VEX_TRC_JMP_SYS_SYSCALL);
660 // GrP fixme hope syscalls aren't called with really shallow stacks...
661 canonical->sysno = gst->guest_RAX;
662 if (canonical->sysno != __NR_syscall) {
663 // stack[0] is return address
664 canonical->arg1 = gst->guest_RDI;
665 canonical->arg2 = gst->guest_RSI;
666 canonical->arg3 = gst->guest_RDX;
667 canonical->arg4 = gst->guest_R10; // not rcx with syscall insn
668 canonical->arg5 = gst->guest_R8;
669 canonical->arg6 = gst->guest_R9;
670 canonical->arg7 = stack[1];
671 canonical->arg8 = stack[2];
672 } else {
673 // GrP fixme hack handle syscall()
674 // GrP fixme what about __syscall() ?
675 // stack[0] is return address
676 // DDD: the tool can't see that the params have been shifted! Can
677 // lead to incorrect checking, I think, because the PRRAn/PSARn
678 // macros will mention the pre-shifted args.
679 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(gst->guest_RDI);
680 vg_assert(canonical->sysno != __NR_syscall);
681 canonical->arg1 = gst->guest_RSI;
682 canonical->arg2 = gst->guest_RDX;
683 canonical->arg3 = gst->guest_R10; // not rcx with syscall insn
684 canonical->arg4 = gst->guest_R8;
685 canonical->arg5 = gst->guest_R9;
686 canonical->arg6 = stack[1];
687 canonical->arg7 = stack[2];
688 canonical->arg8 = stack[3];
690 PRINT("SYSCALL[%d,?](0) syscall(%s, ...); please stand by...\n",
691 VG_(getpid)(), /*tid,*/
692 VG_SYSNUM_STRING(canonical->sysno));
695 // no canonical->sysno adjustment needed
697 #elif defined(VGP_s390x_linux)
698 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
699 canonical->sysno = gst->guest_SYSNO;
700 canonical->arg1 = gst->guest_r2;
701 canonical->arg2 = gst->guest_r3;
702 canonical->arg3 = gst->guest_r4;
703 canonical->arg4 = gst->guest_r5;
704 canonical->arg5 = gst->guest_r6;
705 canonical->arg6 = gst->guest_r7;
706 canonical->arg7 = 0;
707 canonical->arg8 = 0;
709 #elif defined(VGP_x86_solaris)
710 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
711 UWord *stack = (UWord *)gst->guest_ESP;
712 canonical->sysno = gst->guest_EAX;
713 /* stack[0] is a return address. */
714 canonical->arg1 = stack[1];
715 canonical->arg2 = stack[2];
716 canonical->arg3 = stack[3];
717 canonical->arg4 = stack[4];
718 canonical->arg5 = stack[5];
719 canonical->arg6 = stack[6];
720 canonical->arg7 = stack[7];
721 canonical->arg8 = stack[8];
723 switch (trc) {
724 case VEX_TRC_JMP_SYS_INT145:
725 case VEX_TRC_JMP_SYS_SYSENTER:
726 case VEX_TRC_JMP_SYS_SYSCALL:
727 /* These three are not actually valid syscall instructions on Solaris.
728 Pretend for now that we handle them as normal syscalls. */
729 case VEX_TRC_JMP_SYS_INT128:
730 case VEX_TRC_JMP_SYS_INT129:
731 case VEX_TRC_JMP_SYS_INT130:
732 /* int $0x91, sysenter, syscall = normal syscall */
733 break;
734 case VEX_TRC_JMP_SYS_INT210:
735 /* int $0xD2 = fasttrap */
736 canonical->sysno
737 = VG_SOLARIS_SYSCALL_CONSTRUCT_FASTTRAP(canonical->sysno);
738 break;
739 default:
740 vg_assert(0);
741 break;
744 #elif defined(VGP_amd64_solaris)
745 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
746 UWord *stack = (UWord *)gst->guest_RSP;
747 canonical->sysno = gst->guest_RAX;
748 /* stack[0] is a return address. */
749 canonical->arg1 = gst->guest_RDI;
750 canonical->arg2 = gst->guest_RSI;
751 canonical->arg3 = gst->guest_RDX;
752 canonical->arg4 = gst->guest_R10; /* Not RCX with syscall. */
753 canonical->arg5 = gst->guest_R8;
754 canonical->arg6 = gst->guest_R9;
755 canonical->arg7 = stack[1];
756 canonical->arg8 = stack[2];
758 switch (trc) {
759 case VEX_TRC_JMP_SYS_SYSCALL:
760 /* syscall = normal syscall */
761 break;
762 case VEX_TRC_JMP_SYS_INT210:
763 /* int $0xD2 = fasttrap */
764 canonical->sysno
765 = VG_SOLARIS_SYSCALL_CONSTRUCT_FASTTRAP(canonical->sysno);
766 break;
767 default:
768 vg_assert(0);
769 break;
772 #else
773 # error "getSyscallArgsFromGuestState: unknown arch"
774 #endif
777 static
778 void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical,
779 /*OUT*/VexGuestArchState* gst_vanilla )
781 #if defined(VGP_x86_linux)
782 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
783 gst->guest_EAX = canonical->sysno;
784 gst->guest_EBX = canonical->arg1;
785 gst->guest_ECX = canonical->arg2;
786 gst->guest_EDX = canonical->arg3;
787 gst->guest_ESI = canonical->arg4;
788 gst->guest_EDI = canonical->arg5;
789 gst->guest_EBP = canonical->arg6;
791 #elif defined(VGP_amd64_linux)
792 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
793 gst->guest_RAX = canonical->sysno;
794 gst->guest_RDI = canonical->arg1;
795 gst->guest_RSI = canonical->arg2;
796 gst->guest_RDX = canonical->arg3;
797 gst->guest_R10 = canonical->arg4;
798 gst->guest_R8 = canonical->arg5;
799 gst->guest_R9 = canonical->arg6;
801 #elif defined(VGP_ppc32_linux)
802 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
803 gst->guest_GPR0 = canonical->sysno;
804 gst->guest_GPR3 = canonical->arg1;
805 gst->guest_GPR4 = canonical->arg2;
806 gst->guest_GPR5 = canonical->arg3;
807 gst->guest_GPR6 = canonical->arg4;
808 gst->guest_GPR7 = canonical->arg5;
809 gst->guest_GPR8 = canonical->arg6;
811 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
812 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
813 gst->guest_GPR0 = canonical->sysno;
814 gst->guest_GPR3 = canonical->arg1;
815 gst->guest_GPR4 = canonical->arg2;
816 gst->guest_GPR5 = canonical->arg3;
817 gst->guest_GPR6 = canonical->arg4;
818 gst->guest_GPR7 = canonical->arg5;
819 gst->guest_GPR8 = canonical->arg6;
821 #elif defined(VGP_arm_linux)
822 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
823 gst->guest_R7 = canonical->sysno;
824 gst->guest_R0 = canonical->arg1;
825 gst->guest_R1 = canonical->arg2;
826 gst->guest_R2 = canonical->arg3;
827 gst->guest_R3 = canonical->arg4;
828 gst->guest_R4 = canonical->arg5;
829 gst->guest_R5 = canonical->arg6;
831 #elif defined(VGP_arm64_linux)
832 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
833 gst->guest_X8 = canonical->sysno;
834 gst->guest_X0 = canonical->arg1;
835 gst->guest_X1 = canonical->arg2;
836 gst->guest_X2 = canonical->arg3;
837 gst->guest_X3 = canonical->arg4;
838 gst->guest_X4 = canonical->arg5;
839 gst->guest_X5 = canonical->arg6;
841 #elif defined(VGP_x86_darwin)
842 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
843 UWord *stack = (UWord *)gst->guest_ESP;
845 gst->guest_EAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno);
847 // GrP fixme? gst->guest_TEMP_EFLAG_C = 0;
848 // stack[0] is return address
849 stack[1] = canonical->arg1;
850 stack[2] = canonical->arg2;
851 stack[3] = canonical->arg3;
852 stack[4] = canonical->arg4;
853 stack[5] = canonical->arg5;
854 stack[6] = canonical->arg6;
855 stack[7] = canonical->arg7;
856 stack[8] = canonical->arg8;
858 #elif defined(VGP_amd64_darwin)
859 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
860 UWord *stack = (UWord *)gst->guest_RSP;
862 gst->guest_RAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno);
863 // GrP fixme? gst->guest_TEMP_EFLAG_C = 0;
865 // stack[0] is return address
866 gst->guest_RDI = canonical->arg1;
867 gst->guest_RSI = canonical->arg2;
868 gst->guest_RDX = canonical->arg3;
869 gst->guest_RCX = canonical->arg4;
870 gst->guest_R8 = canonical->arg5;
871 gst->guest_R9 = canonical->arg6;
872 stack[1] = canonical->arg7;
873 stack[2] = canonical->arg8;
875 #elif defined(VGP_s390x_linux)
876 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
877 gst->guest_SYSNO = canonical->sysno;
878 gst->guest_r2 = canonical->arg1;
879 gst->guest_r3 = canonical->arg2;
880 gst->guest_r4 = canonical->arg3;
881 gst->guest_r5 = canonical->arg4;
882 gst->guest_r6 = canonical->arg5;
883 gst->guest_r7 = canonical->arg6;
885 #elif defined(VGP_mips32_linux)
886 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
887 if (canonical->arg8 != __NR_syscall) {
888 gst->guest_r2 = canonical->sysno;
889 gst->guest_r4 = canonical->arg1;
890 gst->guest_r5 = canonical->arg2;
891 gst->guest_r6 = canonical->arg3;
892 gst->guest_r7 = canonical->arg4;
893 *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp)
894 *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp)
895 } else {
896 canonical->arg8 = 0;
897 gst->guest_r2 = __NR_syscall;
898 gst->guest_r4 = canonical->sysno;
899 gst->guest_r5 = canonical->arg1;
900 gst->guest_r6 = canonical->arg2;
901 gst->guest_r7 = canonical->arg3;
902 *((UInt*) (gst->guest_r29 + 16)) = canonical->arg4; // 16(guest_GPR29/sp)
903 *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp)
904 *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp)
907 #elif defined(VGP_mips64_linux)
908 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
909 gst->guest_r2 = canonical->sysno;
910 gst->guest_r4 = canonical->arg1;
911 gst->guest_r5 = canonical->arg2;
912 gst->guest_r6 = canonical->arg3;
913 gst->guest_r7 = canonical->arg4;
914 gst->guest_r8 = canonical->arg5;
915 gst->guest_r9 = canonical->arg6;
917 #elif defined(VGP_x86_solaris)
918 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
919 UWord *stack = (UWord *)gst->guest_ESP;
921 /* Fasttraps or anything else cannot go through this way. */
922 vg_assert(VG_SOLARIS_SYSNO_CLASS(canonical->sysno)
923 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
924 gst->guest_EAX = canonical->sysno;
925 /* stack[0] is a return address. */
926 stack[1] = canonical->arg1;
927 stack[2] = canonical->arg2;
928 stack[3] = canonical->arg3;
929 stack[4] = canonical->arg4;
930 stack[5] = canonical->arg5;
931 stack[6] = canonical->arg6;
932 stack[7] = canonical->arg7;
933 stack[8] = canonical->arg8;
935 #elif defined(VGP_amd64_solaris)
936 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
937 UWord *stack = (UWord *)gst->guest_RSP;
939 /* Fasttraps or anything else cannot go through this way. */
940 vg_assert(VG_SOLARIS_SYSNO_CLASS(canonical->sysno)
941 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
942 gst->guest_RAX = canonical->sysno;
943 /* stack[0] is a return address. */
944 gst->guest_RDI = canonical->arg1;
945 gst->guest_RSI = canonical->arg2;
946 gst->guest_RDX = canonical->arg3;
947 gst->guest_R10 = canonical->arg4;
948 gst->guest_R8 = canonical->arg5;
949 gst->guest_R9 = canonical->arg6;
950 stack[1] = canonical->arg7;
951 stack[2] = canonical->arg8;
953 #else
954 # error "putSyscallArgsIntoGuestState: unknown arch"
955 #endif
958 static
959 void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical,
960 /*IN*/ VexGuestArchState* gst_vanilla )
962 # if defined(VGP_x86_linux)
963 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
964 canonical->sres = VG_(mk_SysRes_x86_linux)( gst->guest_EAX );
965 canonical->what = SsComplete;
967 # elif defined(VGP_amd64_linux)
968 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
969 canonical->sres = VG_(mk_SysRes_amd64_linux)( gst->guest_RAX );
970 canonical->what = SsComplete;
972 # elif defined(VGP_ppc32_linux)
973 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
974 UInt cr = LibVEX_GuestPPC32_get_CR( gst );
975 UInt cr0so = (cr >> 28) & 1;
976 canonical->sres = VG_(mk_SysRes_ppc32_linux)( gst->guest_GPR3, cr0so );
977 canonical->what = SsComplete;
979 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
980 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
981 UInt cr = LibVEX_GuestPPC64_get_CR( gst );
982 UInt cr0so = (cr >> 28) & 1;
983 canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so );
984 canonical->what = SsComplete;
986 # elif defined(VGP_arm_linux)
987 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
988 canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 );
989 canonical->what = SsComplete;
991 # elif defined(VGP_arm64_linux)
992 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
993 canonical->sres = VG_(mk_SysRes_arm64_linux)( gst->guest_X0 );
994 canonical->what = SsComplete;
996 # elif defined(VGP_mips32_linux)
997 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
998 UInt v0 = gst->guest_r2; // v0
999 UInt v1 = gst->guest_r3; // v1
1000 UInt a3 = gst->guest_r7; // a3
1001 canonical->sres = VG_(mk_SysRes_mips32_linux)( v0, v1, a3 );
1002 canonical->what = SsComplete;
1004 # elif defined(VGP_mips64_linux)
1005 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
1006 ULong v0 = gst->guest_r2; // v0
1007 ULong v1 = gst->guest_r3; // v1
1008 ULong a3 = gst->guest_r7; // a3
1009 canonical->sres = VG_(mk_SysRes_mips64_linux)(v0, v1, a3);
1010 canonical->what = SsComplete;
1012 # elif defined(VGP_x86_darwin)
1013 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1014 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1015 UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst);
1016 UInt err = 0;
1017 UInt wLO = 0;
1018 UInt wHI = 0;
1019 switch (gst->guest_SC_CLASS) {
1020 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1021 // int $0x80 = Unix, 64-bit result
1022 err = carry;
1023 wLO = gst->guest_EAX;
1024 wHI = gst->guest_EDX;
1025 break;
1026 case VG_DARWIN_SYSCALL_CLASS_MACH:
1027 // int $0x81 = Mach, 32-bit result
1028 wLO = gst->guest_EAX;
1029 break;
1030 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1031 // int $0x82 = mdep, 32-bit result
1032 wLO = gst->guest_EAX;
1033 break;
1034 default:
1035 vg_assert(0);
1036 break;
1038 canonical->sres = VG_(mk_SysRes_x86_darwin)(
1039 gst->guest_SC_CLASS, err ? True : False,
1040 wHI, wLO
1042 canonical->what = SsComplete;
1044 # elif defined(VGP_amd64_darwin)
1045 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1046 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1047 ULong carry = 1 & LibVEX_GuestAMD64_get_rflags(gst);
1048 ULong err = 0;
1049 ULong wLO = 0;
1050 ULong wHI = 0;
1051 switch (gst->guest_SC_CLASS) {
1052 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1053 // syscall = Unix, 128-bit result
1054 err = carry;
1055 wLO = gst->guest_RAX;
1056 wHI = gst->guest_RDX;
1057 break;
1058 case VG_DARWIN_SYSCALL_CLASS_MACH:
1059 // syscall = Mach, 64-bit result
1060 wLO = gst->guest_RAX;
1061 break;
1062 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1063 // syscall = mdep, 64-bit result
1064 wLO = gst->guest_RAX;
1065 break;
1066 default:
1067 vg_assert(0);
1068 break;
1070 canonical->sres = VG_(mk_SysRes_amd64_darwin)(
1071 gst->guest_SC_CLASS, err ? True : False,
1072 wHI, wLO
1074 canonical->what = SsComplete;
1076 # elif defined(VGP_s390x_linux)
1077 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
1078 canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 );
1079 canonical->what = SsComplete;
1081 # elif defined(VGP_x86_solaris)
1082 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1083 UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst);
1085 canonical->sres = VG_(mk_SysRes_x86_solaris)(carry ? True : False,
1086 gst->guest_EAX,
1087 carry ? 0 : gst->guest_EDX);
1088 canonical->what = SsComplete;
1090 # elif defined(VGP_amd64_solaris)
1091 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1092 UInt carry = 1 & LibVEX_GuestAMD64_get_rflags(gst);
1094 canonical->sres = VG_(mk_SysRes_amd64_solaris)(carry ? True : False,
1095 gst->guest_RAX,
1096 carry ? 0 : gst->guest_RDX);
1097 canonical->what = SsComplete;
1099 # else
1100 # error "getSyscallStatusFromGuestState: unknown arch"
1101 # endif
1104 static
1105 void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
1106 /*IN*/ SyscallStatus* canonical,
1107 /*OUT*/VexGuestArchState* gst_vanilla )
1109 # if defined(VGP_x86_linux)
1110 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1111 vg_assert(canonical->what == SsComplete);
1112 if (sr_isError(canonical->sres)) {
1113 /* This isn't exactly right, in that really a Failure with res
1114 not in the range 1 .. 4095 is unrepresentable in the
1115 Linux-x86 scheme. Oh well. */
1116 gst->guest_EAX = - (Int)sr_Err(canonical->sres);
1117 } else {
1118 gst->guest_EAX = sr_Res(canonical->sres);
1120 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1121 OFFSET_x86_EAX, sizeof(UWord) );
1123 # elif defined(VGP_amd64_linux)
1124 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1125 vg_assert(canonical->what == SsComplete);
1126 if (sr_isError(canonical->sres)) {
1127 /* This isn't exactly right, in that really a Failure with res
1128 not in the range 1 .. 4095 is unrepresentable in the
1129 Linux-amd64 scheme. Oh well. */
1130 gst->guest_RAX = - (Long)sr_Err(canonical->sres);
1131 } else {
1132 gst->guest_RAX = sr_Res(canonical->sres);
1134 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1135 OFFSET_amd64_RAX, sizeof(UWord) );
1137 # elif defined(VGP_ppc32_linux)
1138 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
1139 UInt old_cr = LibVEX_GuestPPC32_get_CR(gst);
1140 vg_assert(canonical->what == SsComplete);
1141 if (sr_isError(canonical->sres)) {
1142 /* set CR0.SO */
1143 LibVEX_GuestPPC32_put_CR( old_cr | (1<<28), gst );
1144 gst->guest_GPR3 = sr_Err(canonical->sres);
1145 } else {
1146 /* clear CR0.SO */
1147 LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), gst );
1148 gst->guest_GPR3 = sr_Res(canonical->sres);
1150 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1151 OFFSET_ppc32_GPR3, sizeof(UWord) );
1152 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1153 OFFSET_ppc32_CR0_0, sizeof(UChar) );
1155 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1156 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
1157 UInt old_cr = LibVEX_GuestPPC64_get_CR(gst);
1158 vg_assert(canonical->what == SsComplete);
1159 if (sr_isError(canonical->sres)) {
1160 /* set CR0.SO */
1161 LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst );
1162 gst->guest_GPR3 = sr_Err(canonical->sres);
1163 } else {
1164 /* clear CR0.SO */
1165 LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst );
1166 gst->guest_GPR3 = sr_Res(canonical->sres);
1168 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1169 OFFSET_ppc64_GPR3, sizeof(UWord) );
1170 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1171 OFFSET_ppc64_CR0_0, sizeof(UChar) );
1173 # elif defined(VGP_arm_linux)
1174 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
1175 vg_assert(canonical->what == SsComplete);
1176 if (sr_isError(canonical->sres)) {
1177 /* This isn't exactly right, in that really a Failure with res
1178 not in the range 1 .. 4095 is unrepresentable in the
1179 Linux-arm scheme. Oh well. */
1180 gst->guest_R0 = - (Int)sr_Err(canonical->sres);
1181 } else {
1182 gst->guest_R0 = sr_Res(canonical->sres);
1184 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1185 OFFSET_arm_R0, sizeof(UWord) );
1187 # elif defined(VGP_arm64_linux)
1188 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
1189 vg_assert(canonical->what == SsComplete);
1190 if (sr_isError(canonical->sres)) {
1191 /* This isn't exactly right, in that really a Failure with res
1192 not in the range 1 .. 4095 is unrepresentable in the
1193 Linux-arm64 scheme. Oh well. */
1194 gst->guest_X0 = - (Long)sr_Err(canonical->sres);
1195 } else {
1196 gst->guest_X0 = sr_Res(canonical->sres);
1198 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1199 OFFSET_arm64_X0, sizeof(UWord) );
1201 #elif defined(VGP_x86_darwin)
1202 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1203 SysRes sres = canonical->sres;
1204 vg_assert(canonical->what == SsComplete);
1205 /* Unfortunately here we have to break abstraction and look
1206 directly inside 'res', in order to decide what to do. */
1207 switch (sres._mode) {
1208 case SysRes_MACH: // int $0x81 = Mach, 32-bit result
1209 case SysRes_MDEP: // int $0x82 = mdep, 32-bit result
1210 gst->guest_EAX = sres._wLO;
1211 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1212 OFFSET_x86_EAX, sizeof(UInt) );
1213 break;
1214 case SysRes_UNIX_OK: // int $0x80 = Unix, 64-bit result
1215 case SysRes_UNIX_ERR: // int $0x80 = Unix, 64-bit error
1216 gst->guest_EAX = sres._wLO;
1217 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1218 OFFSET_x86_EAX, sizeof(UInt) );
1219 gst->guest_EDX = sres._wHI;
1220 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1221 OFFSET_x86_EDX, sizeof(UInt) );
1222 LibVEX_GuestX86_put_eflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0,
1223 gst );
1224 // GrP fixme sets defined for entire eflags, not just bit c
1225 // DDD: this breaks exp-ptrcheck.
1226 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1227 offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) );
1228 break;
1229 default:
1230 vg_assert(0);
1231 break;
1234 #elif defined(VGP_amd64_darwin)
1235 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1236 SysRes sres = canonical->sres;
1237 vg_assert(canonical->what == SsComplete);
1238 /* Unfortunately here we have to break abstraction and look
1239 directly inside 'res', in order to decide what to do. */
1240 switch (sres._mode) {
1241 case SysRes_MACH: // syscall = Mach, 64-bit result
1242 case SysRes_MDEP: // syscall = mdep, 64-bit result
1243 gst->guest_RAX = sres._wLO;
1244 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1245 OFFSET_amd64_RAX, sizeof(ULong) );
1246 break;
1247 case SysRes_UNIX_OK: // syscall = Unix, 128-bit result
1248 case SysRes_UNIX_ERR: // syscall = Unix, 128-bit error
1249 gst->guest_RAX = sres._wLO;
1250 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1251 OFFSET_amd64_RAX, sizeof(ULong) );
1252 gst->guest_RDX = sres._wHI;
1253 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1254 OFFSET_amd64_RDX, sizeof(ULong) );
1255 LibVEX_GuestAMD64_put_rflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0,
1256 gst );
1257 // GrP fixme sets defined for entire rflags, not just bit c
1258 // DDD: this breaks exp-ptrcheck.
1259 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1260 offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) );
1261 break;
1262 default:
1263 vg_assert(0);
1264 break;
1267 # elif defined(VGP_s390x_linux)
1268 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
1269 vg_assert(canonical->what == SsComplete);
1270 if (sr_isError(canonical->sres)) {
1271 gst->guest_r2 = - (Long)sr_Err(canonical->sres);
1272 } else {
1273 gst->guest_r2 = sr_Res(canonical->sres);
1276 # elif defined(VGP_mips32_linux)
1277 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1278 vg_assert(canonical->what == SsComplete);
1279 if (sr_isError(canonical->sres)) {
1280 gst->guest_r2 = (Int)sr_Err(canonical->sres);
1281 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1282 } else {
1283 gst->guest_r2 = sr_Res(canonical->sres);
1284 gst->guest_r3 = sr_ResEx(canonical->sres);
1285 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1287 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1288 OFFSET_mips32_r2, sizeof(UWord) );
1289 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1290 OFFSET_mips32_r3, sizeof(UWord) );
1291 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1292 OFFSET_mips32_r7, sizeof(UWord) );
1294 # elif defined(VGP_mips64_linux)
1295 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
1296 vg_assert(canonical->what == SsComplete);
1297 if (sr_isError(canonical->sres)) {
1298 gst->guest_r2 = (Int)sr_Err(canonical->sres);
1299 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1300 } else {
1301 gst->guest_r2 = sr_Res(canonical->sres);
1302 gst->guest_r3 = sr_ResEx(canonical->sres);
1303 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1305 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1306 OFFSET_mips64_r2, sizeof(UWord) );
1307 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1308 OFFSET_mips64_r3, sizeof(UWord) );
1309 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1310 OFFSET_mips64_r7, sizeof(UWord) );
1312 # elif defined(VGP_x86_solaris)
1313 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1314 SysRes sres = canonical->sres;
1315 vg_assert(canonical->what == SsComplete);
1317 if (sr_isError(sres)) {
1318 gst->guest_EAX = sr_Err(sres);
1319 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EAX,
1320 sizeof(UInt));
1321 LibVEX_GuestX86_put_eflag_c(1, gst);
1323 else {
1324 gst->guest_EAX = sr_Res(sres);
1325 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EAX,
1326 sizeof(UInt));
1327 gst->guest_EDX = sr_ResHI(sres);
1328 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EDX,
1329 sizeof(UInt));
1330 LibVEX_GuestX86_put_eflag_c(0, gst);
1332 /* Make CC_DEP1 and CC_DEP2 defined. This is inaccurate because it makes
1333 other eflags defined too (see README.solaris). */
1334 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestX86State,
1335 guest_CC_DEP1), sizeof(UInt));
1336 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestX86State,
1337 guest_CC_DEP2), sizeof(UInt));
1339 # elif defined(VGP_amd64_solaris)
1340 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1341 SysRes sres = canonical->sres;
1342 vg_assert(canonical->what == SsComplete);
1344 if (sr_isError(sres)) {
1345 gst->guest_RAX = sr_Err(sres);
1346 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RAX,
1347 sizeof(ULong));
1348 LibVEX_GuestAMD64_put_rflag_c(1, gst);
1350 else {
1351 gst->guest_RAX = sr_Res(sres);
1352 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RAX,
1353 sizeof(ULong));
1354 gst->guest_RDX = sr_ResHI(sres);
1355 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RDX,
1356 sizeof(ULong));
1357 LibVEX_GuestAMD64_put_rflag_c(0, gst);
1359 /* Make CC_DEP1 and CC_DEP2 defined. This is inaccurate because it makes
1360 other eflags defined too (see README.solaris). */
1361 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestAMD64State,
1362 guest_CC_DEP1), sizeof(ULong));
1363 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestAMD64State,
1364 guest_CC_DEP2), sizeof(ULong));
1366 # else
1367 # error "putSyscallStatusIntoGuestState: unknown arch"
1368 # endif
1372 /* Tell me the offsets in the guest state of the syscall params, so
1373 that the scalar argument checkers don't have to have this info
1374 hardwired. */
1376 static
1377 void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
1379 VG_(bzero_inline)(layout, sizeof(*layout));
1381 #if defined(VGP_x86_linux)
1382 layout->o_sysno = OFFSET_x86_EAX;
1383 layout->o_arg1 = OFFSET_x86_EBX;
1384 layout->o_arg2 = OFFSET_x86_ECX;
1385 layout->o_arg3 = OFFSET_x86_EDX;
1386 layout->o_arg4 = OFFSET_x86_ESI;
1387 layout->o_arg5 = OFFSET_x86_EDI;
1388 layout->o_arg6 = OFFSET_x86_EBP;
1389 layout->uu_arg7 = -1; /* impossible value */
1390 layout->uu_arg8 = -1; /* impossible value */
1392 #elif defined(VGP_amd64_linux)
1393 layout->o_sysno = OFFSET_amd64_RAX;
1394 layout->o_arg1 = OFFSET_amd64_RDI;
1395 layout->o_arg2 = OFFSET_amd64_RSI;
1396 layout->o_arg3 = OFFSET_amd64_RDX;
1397 layout->o_arg4 = OFFSET_amd64_R10;
1398 layout->o_arg5 = OFFSET_amd64_R8;
1399 layout->o_arg6 = OFFSET_amd64_R9;
1400 layout->uu_arg7 = -1; /* impossible value */
1401 layout->uu_arg8 = -1; /* impossible value */
1403 #elif defined(VGP_ppc32_linux)
1404 layout->o_sysno = OFFSET_ppc32_GPR0;
1405 layout->o_arg1 = OFFSET_ppc32_GPR3;
1406 layout->o_arg2 = OFFSET_ppc32_GPR4;
1407 layout->o_arg3 = OFFSET_ppc32_GPR5;
1408 layout->o_arg4 = OFFSET_ppc32_GPR6;
1409 layout->o_arg5 = OFFSET_ppc32_GPR7;
1410 layout->o_arg6 = OFFSET_ppc32_GPR8;
1411 layout->uu_arg7 = -1; /* impossible value */
1412 layout->uu_arg8 = -1; /* impossible value */
1414 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1415 layout->o_sysno = OFFSET_ppc64_GPR0;
1416 layout->o_arg1 = OFFSET_ppc64_GPR3;
1417 layout->o_arg2 = OFFSET_ppc64_GPR4;
1418 layout->o_arg3 = OFFSET_ppc64_GPR5;
1419 layout->o_arg4 = OFFSET_ppc64_GPR6;
1420 layout->o_arg5 = OFFSET_ppc64_GPR7;
1421 layout->o_arg6 = OFFSET_ppc64_GPR8;
1422 layout->uu_arg7 = -1; /* impossible value */
1423 layout->uu_arg8 = -1; /* impossible value */
1425 #elif defined(VGP_arm_linux)
1426 layout->o_sysno = OFFSET_arm_R7;
1427 layout->o_arg1 = OFFSET_arm_R0;
1428 layout->o_arg2 = OFFSET_arm_R1;
1429 layout->o_arg3 = OFFSET_arm_R2;
1430 layout->o_arg4 = OFFSET_arm_R3;
1431 layout->o_arg5 = OFFSET_arm_R4;
1432 layout->o_arg6 = OFFSET_arm_R5;
1433 layout->uu_arg7 = -1; /* impossible value */
1434 layout->uu_arg8 = -1; /* impossible value */
1436 #elif defined(VGP_arm64_linux)
1437 layout->o_sysno = OFFSET_arm64_X8;
1438 layout->o_arg1 = OFFSET_arm64_X0;
1439 layout->o_arg2 = OFFSET_arm64_X1;
1440 layout->o_arg3 = OFFSET_arm64_X2;
1441 layout->o_arg4 = OFFSET_arm64_X3;
1442 layout->o_arg5 = OFFSET_arm64_X4;
1443 layout->o_arg6 = OFFSET_arm64_X5;
1444 layout->uu_arg7 = -1; /* impossible value */
1445 layout->uu_arg8 = -1; /* impossible value */
1447 #elif defined(VGP_mips32_linux)
1448 layout->o_sysno = OFFSET_mips32_r2;
1449 layout->o_arg1 = OFFSET_mips32_r4;
1450 layout->o_arg2 = OFFSET_mips32_r5;
1451 layout->o_arg3 = OFFSET_mips32_r6;
1452 layout->o_arg4 = OFFSET_mips32_r7;
1453 layout->s_arg5 = sizeof(UWord) * 4;
1454 layout->s_arg6 = sizeof(UWord) * 5;
1455 layout->s_arg7 = sizeof(UWord) * 6;
1456 layout->uu_arg8 = -1; /* impossible value */
1458 #elif defined(VGP_mips64_linux)
1459 layout->o_sysno = OFFSET_mips64_r2;
1460 layout->o_arg1 = OFFSET_mips64_r4;
1461 layout->o_arg2 = OFFSET_mips64_r5;
1462 layout->o_arg3 = OFFSET_mips64_r6;
1463 layout->o_arg4 = OFFSET_mips64_r7;
1464 layout->o_arg5 = OFFSET_mips64_r8;
1465 layout->o_arg6 = OFFSET_mips64_r9;
1466 layout->uu_arg7 = -1; /* impossible value */
1467 layout->uu_arg8 = -1; /* impossible value */
1469 #elif defined(VGP_x86_darwin)
1470 layout->o_sysno = OFFSET_x86_EAX;
1471 // syscall parameters are on stack in C convention
1472 layout->s_arg1 = sizeof(UWord) * 1;
1473 layout->s_arg2 = sizeof(UWord) * 2;
1474 layout->s_arg3 = sizeof(UWord) * 3;
1475 layout->s_arg4 = sizeof(UWord) * 4;
1476 layout->s_arg5 = sizeof(UWord) * 5;
1477 layout->s_arg6 = sizeof(UWord) * 6;
1478 layout->s_arg7 = sizeof(UWord) * 7;
1479 layout->s_arg8 = sizeof(UWord) * 8;
1481 #elif defined(VGP_amd64_darwin)
1482 layout->o_sysno = OFFSET_amd64_RAX;
1483 layout->o_arg1 = OFFSET_amd64_RDI;
1484 layout->o_arg2 = OFFSET_amd64_RSI;
1485 layout->o_arg3 = OFFSET_amd64_RDX;
1486 layout->o_arg4 = OFFSET_amd64_RCX;
1487 layout->o_arg5 = OFFSET_amd64_R8;
1488 layout->o_arg6 = OFFSET_amd64_R9;
1489 layout->s_arg7 = sizeof(UWord) * 1;
1490 layout->s_arg8 = sizeof(UWord) * 2;
1492 #elif defined(VGP_s390x_linux)
1493 layout->o_sysno = OFFSET_s390x_SYSNO;
1494 layout->o_arg1 = OFFSET_s390x_r2;
1495 layout->o_arg2 = OFFSET_s390x_r3;
1496 layout->o_arg3 = OFFSET_s390x_r4;
1497 layout->o_arg4 = OFFSET_s390x_r5;
1498 layout->o_arg5 = OFFSET_s390x_r6;
1499 layout->o_arg6 = OFFSET_s390x_r7;
1500 layout->uu_arg7 = -1; /* impossible value */
1501 layout->uu_arg8 = -1; /* impossible value */
1503 #elif defined(VGP_x86_solaris)
1504 layout->o_sysno = OFFSET_x86_EAX;
1505 /* Syscall parameters are on the stack. */
1506 layout->s_arg1 = sizeof(UWord) * 1;
1507 layout->s_arg2 = sizeof(UWord) * 2;
1508 layout->s_arg3 = sizeof(UWord) * 3;
1509 layout->s_arg4 = sizeof(UWord) * 4;
1510 layout->s_arg5 = sizeof(UWord) * 5;
1511 layout->s_arg6 = sizeof(UWord) * 6;
1512 layout->s_arg7 = sizeof(UWord) * 7;
1513 layout->s_arg8 = sizeof(UWord) * 8;
1515 #elif defined(VGP_amd64_solaris)
1516 layout->o_sysno = OFFSET_amd64_RAX;
1517 layout->o_arg1 = OFFSET_amd64_RDI;
1518 layout->o_arg2 = OFFSET_amd64_RSI;
1519 layout->o_arg3 = OFFSET_amd64_RDX;
1520 layout->o_arg4 = OFFSET_amd64_R10;
1521 layout->o_arg5 = OFFSET_amd64_R8;
1522 layout->o_arg6 = OFFSET_amd64_R9;
1523 layout->s_arg7 = sizeof(UWord) * 1;
1524 layout->s_arg8 = sizeof(UWord) * 2;
1526 #else
1527 # error "getSyscallLayout: unknown arch"
1528 #endif
1532 /* ---------------------------------------------------------------------
1533 The main driver logic
1534 ------------------------------------------------------------------ */
1536 /* Finding the handlers for a given syscall, or faking up one
1537 when no handler is found. */
1539 static
1540 void bad_before ( ThreadId tid,
1541 SyscallArgLayout* layout,
1542 /*MOD*/SyscallArgs* args,
1543 /*OUT*/SyscallStatus* status,
1544 /*OUT*/UWord* flags )
1546 VG_(dmsg)("WARNING: unhandled %s syscall: %s\n",
1547 VG_PLATFORM, VG_SYSNUM_STRING(args->sysno));
1548 if (VG_(clo_verbosity) > 1) {
1549 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1551 VG_(dmsg)("You may be able to write your own handler.\n");
1552 VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
1553 VG_(dmsg)("Nevertheless we consider this a bug. Please report\n");
1554 VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html.\n");
1556 SET_STATUS_Failure(VKI_ENOSYS);
1558 # if defined(VGO_solaris)
1559 VG_(exit)(1);
1560 # endif
1563 static SyscallTableEntry bad_sys =
1564 { bad_before, NULL };
1566 static const SyscallTableEntry* get_syscall_entry ( Int syscallno )
1568 const SyscallTableEntry* sys = NULL;
1570 # if defined(VGO_linux)
1571 sys = ML_(get_linux_syscall_entry)( syscallno );
1573 # elif defined(VGO_darwin)
1574 Int idx = VG_DARWIN_SYSNO_INDEX(syscallno);
1576 switch (VG_DARWIN_SYSNO_CLASS(syscallno)) {
1577 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1578 if (idx >= 0 && idx < ML_(syscall_table_size) &&
1579 ML_(syscall_table)[idx].before != NULL)
1580 sys = &ML_(syscall_table)[idx];
1581 break;
1582 case VG_DARWIN_SYSCALL_CLASS_MACH:
1583 if (idx >= 0 && idx < ML_(mach_trap_table_size) &&
1584 ML_(mach_trap_table)[idx].before != NULL)
1585 sys = &ML_(mach_trap_table)[idx];
1586 break;
1587 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1588 if (idx >= 0 && idx < ML_(mdep_trap_table_size) &&
1589 ML_(mdep_trap_table)[idx].before != NULL)
1590 sys = &ML_(mdep_trap_table)[idx];
1591 break;
1592 default:
1593 vg_assert(0);
1594 break;
1597 # elif defined(VGO_solaris)
1598 sys = ML_(get_solaris_syscall_entry)(syscallno);
1600 # else
1601 # error Unknown OS
1602 # endif
1604 return sys == NULL ? &bad_sys : sys;
1608 /* Add and remove signals from mask so that we end up telling the
1609 kernel the state we actually want rather than what the client
1610 wants. */
1611 void VG_(sanitize_client_sigmask)(vki_sigset_t *mask)
1613 VG_(sigdelset)(mask, VKI_SIGKILL);
1614 VG_(sigdelset)(mask, VKI_SIGSTOP);
1615 VG_(sigdelset)(mask, VG_SIGVGKILL); /* never block */
1618 typedef
1619 struct {
1620 SyscallArgs orig_args;
1621 SyscallArgs args;
1622 SyscallStatus status;
1623 UWord flags;
1625 SyscallInfo;
1627 SyscallInfo *syscallInfo;
1629 /* The scheduler needs to be able to zero out these records after a
1630 fork, hence this is exported from m_syswrap. */
1631 void VG_(clear_syscallInfo) ( ThreadId tid )
1633 vg_assert(syscallInfo);
1634 vg_assert(tid >= 0 && tid < VG_N_THREADS);
1635 VG_(memset)( & syscallInfo[tid], 0, sizeof( syscallInfo[tid] ));
1636 syscallInfo[tid].status.what = SsIdle;
1639 Bool VG_(is_in_syscall) ( ThreadId tid )
1641 vg_assert(tid >= 0 && tid < VG_N_THREADS);
1642 return (syscallInfo[tid].status.what != SsIdle);
1645 Word VG_(is_in_syscall_no) (ThreadId tid )
1647 vg_assert(tid >= 0 && tid < VG_N_THREADS);
1648 return syscallInfo[tid].orig_args.sysno;
1651 static void ensure_initialised ( void )
1653 Int i;
1654 static Bool init_done = False;
1655 if (init_done)
1656 return;
1657 init_done = True;
1659 syscallInfo = VG_(malloc)("scinfo", VG_N_THREADS * sizeof syscallInfo[0]);
1661 for (i = 0; i < VG_N_THREADS; i++) {
1662 VG_(clear_syscallInfo)( i );
1666 /* --- This is the main function of this file. --- */
1668 void VG_(client_syscall) ( ThreadId tid, UInt trc )
1670 Word sysno;
1671 ThreadState* tst;
1672 const SyscallTableEntry* ent;
1673 SyscallArgLayout layout;
1674 SyscallInfo* sci;
1676 ensure_initialised();
1678 vg_assert(VG_(is_valid_tid)(tid));
1679 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1680 vg_assert(VG_(is_running_thread)(tid));
1682 # if !defined(VGO_darwin)
1683 // Resync filtering is meaningless on non-Darwin targets.
1684 vg_assert(VG_(clo_resync_filter) == 0);
1685 # endif
1687 tst = VG_(get_ThreadState)(tid);
1689 /* BEGIN ensure root thread's stack is suitably mapped */
1690 /* In some rare circumstances, we may do the syscall without the
1691 bottom page of the stack being mapped, because the stack pointer
1692 was moved down just a few instructions before the syscall
1693 instruction, and there have been no memory references since
1694 then, that would cause a call to VG_(extend_stack) to have
1695 happened.
1697 In native execution that's OK: the kernel automagically extends
1698 the stack's mapped area down to cover the stack pointer (or sp -
1699 redzone, really). In simulated normal execution that's OK too,
1700 since any signals we get from accessing below the mapped area of
1701 the (guest's) stack lead us to VG_(extend_stack), where we
1702 simulate the kernel's stack extension logic. But that leaves
1703 the problem of entering a syscall with the SP unmapped. Because
1704 the kernel doesn't know that the segment immediately above SP is
1705 supposed to be a grow-down segment, it causes the syscall to
1706 fail, and thereby causes a divergence between native behaviour
1707 (syscall succeeds) and simulated behaviour (syscall fails).
1709 This is quite a rare failure mode. It has only been seen
1710 affecting calls to sys_readlink on amd64-linux, and even then it
1711 requires a certain code sequence around the syscall to trigger
1712 it. Here is one:
1714 extern int my_readlink ( const char* path );
1715 asm(
1716 ".text\n"
1717 ".globl my_readlink\n"
1718 "my_readlink:\n"
1719 "\tsubq $0x1008,%rsp\n"
1720 "\tmovq %rdi,%rdi\n" // path is in rdi
1721 "\tmovq %rsp,%rsi\n" // &buf[0] -> rsi
1722 "\tmovl $0x1000,%edx\n" // sizeof(buf) in rdx
1723 "\tmovl $"__NR_READLINK",%eax\n" // syscall number
1724 "\tsyscall\n"
1725 "\taddq $0x1008,%rsp\n"
1726 "\tret\n"
1727 ".previous\n"
1730 For more details, see bug #156404
1731 (https://bugs.kde.org/show_bug.cgi?id=156404).
1733 The fix is actually very simple. We simply need to call
1734 VG_(extend_stack) for this thread, handing it the lowest
1735 possible valid address for stack (sp - redzone), to ensure the
1736 pages all the way down to that address, are mapped. Because
1737 this is a potentially expensive and frequent operation, we
1738 do the following:
1740 Only the main thread (tid=1) has a growdown stack. So
1741 ignore all others. It is conceivable, although highly unlikely,
1742 that the main thread exits, and later another thread is
1743 allocated tid=1, but that's harmless, I believe;
1744 VG_(extend_stack) will do nothing when applied to a non-root
1745 thread.
1747 All this guff is of course Linux-specific. Hence the ifdef.
1749 # if defined(VGO_linux)
1750 if (tid == 1/*ROOT THREAD*/) {
1751 Addr stackMin = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB;
1753 /* The precise thing to do here would be to extend the stack only
1754 if the system call can be proven to access unmapped user stack
1755 memory. That is an enormous amount of work even if a proper
1756 spec of system calls was available.
1758 In the case where the system call does not access user memory
1759 the stack pointer here can have any value. A legitimate testcase
1760 that exercises this is none/tests/s390x/stmg.c:
1761 The stack pointer happens to be in the reservation segment near
1762 the end of the addressable memory and there is no SkAnonC segment
1763 above.
1765 So the approximation we're taking here is to extend the stack only
1766 if the client stack pointer does not look bogus. */
1767 if (VG_(am_addr_is_in_extensible_client_stack)(stackMin))
1768 VG_(extend_stack)( tid, stackMin );
1770 # endif
1771 /* END ensure root thread's stack is suitably mapped */
1773 /* First off, get the syscall args and number. This is a
1774 platform-dependent action. */
1776 sci = & syscallInfo[tid];
1777 vg_assert(sci->status.what == SsIdle);
1779 getSyscallArgsFromGuestState( &sci->orig_args, &tst->arch.vex, trc );
1781 /* Copy .orig_args to .args. The pre-handler may modify .args, but
1782 we want to keep the originals too, just in case. */
1783 sci->args = sci->orig_args;
1785 /* Save the syscall number in the thread state in case the syscall
1786 is interrupted by a signal. */
1787 sysno = sci->orig_args.sysno;
1789 /* It's sometimes useful, as a crude debugging hack, to get a
1790 stack trace at each (or selected) syscalls. */
1791 if (0 && sysno == __NR_ioctl) {
1792 VG_(umsg)("\nioctl:\n");
1793 VG_(get_and_pp_StackTrace)(tid, 10);
1794 VG_(umsg)("\n");
1797 # if defined(VGO_darwin)
1798 /* Record syscall class. But why? Because the syscall might be
1799 interrupted by a signal, and in the signal handler (which will
1800 be m_signals.async_signalhandler) we will need to build a SysRes
1801 reflecting the syscall return result. In order to do that we
1802 need to know the syscall class. Hence stash it in the guest
1803 state of this thread. This madness is not needed on Linux
1804 because it only has a single syscall return convention and so
1805 there is no ambiguity involved in converting the post-signal
1806 machine state into a SysRes. */
1807 tst->arch.vex.guest_SC_CLASS = VG_DARWIN_SYSNO_CLASS(sysno);
1808 # endif
1810 /* The default what-to-do-next thing is hand the syscall to the
1811 kernel, so we pre-set that here. Set .sres to something
1812 harmless looking (is irrelevant because .what is not
1813 SsComplete.) */
1814 sci->status.what = SsHandToKernel;
1815 sci->status.sres = VG_(mk_SysRes_Error)(0);
1816 sci->flags = 0;
1818 /* Fetch the syscall's handlers. If no handlers exist for this
1819 syscall, we are given dummy handlers which force an immediate
1820 return with ENOSYS. */
1821 ent = get_syscall_entry(sysno);
1823 /* Fetch the layout information, which tells us where in the guest
1824 state the syscall args reside. This is a platform-dependent
1825 action. This info is needed so that the scalar syscall argument
1826 checks (PRE_REG_READ calls) know which bits of the guest state
1827 they need to inspect. */
1828 getSyscallArgLayout( &layout );
1830 /* Make sure the tmp signal mask matches the real signal mask;
1831 sigsuspend may change this. */
1832 vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask));
1834 /* Right, we're finally ready to Party. Call the pre-handler and
1835 see what we get back. At this point:
1837 sci->status.what is Unset (we don't know yet).
1838 sci->orig_args contains the original args.
1839 sci->args is the same as sci->orig_args.
1840 sci->flags is zero.
1843 PRINT("SYSCALL[%d,%u](%s) ",
1844 VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno));
1846 /* Do any pre-syscall actions */
1847 if (VG_(needs).syscall_wrapper) {
1848 UWord tmpv[8];
1849 tmpv[0] = sci->orig_args.arg1;
1850 tmpv[1] = sci->orig_args.arg2;
1851 tmpv[2] = sci->orig_args.arg3;
1852 tmpv[3] = sci->orig_args.arg4;
1853 tmpv[4] = sci->orig_args.arg5;
1854 tmpv[5] = sci->orig_args.arg6;
1855 tmpv[6] = sci->orig_args.arg7;
1856 tmpv[7] = sci->orig_args.arg8;
1857 VG_TDICT_CALL(tool_pre_syscall, tid, sysno,
1858 &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0]));
1861 vg_assert(ent);
1862 vg_assert(ent->before);
1863 (ent->before)( tid,
1864 &layout,
1865 &sci->args, &sci->status, &sci->flags );
1867 /* If needed, gdbserver will report syscall entry to GDB */
1868 VG_(gdbserver_report_syscall)(True, sysno, tid);
1870 /* The pre-handler may have modified:
1871 sci->args
1872 sci->status
1873 sci->flags
1874 All else remains unchanged.
1875 Although the args may be modified, pre handlers are not allowed
1876 to change the syscall number.
1878 /* Now we proceed according to what the pre-handler decided. */
1879 vg_assert(sci->status.what == SsHandToKernel
1880 || sci->status.what == SsComplete);
1881 vg_assert(sci->args.sysno == sci->orig_args.sysno);
1883 if (sci->status.what == SsComplete && !sr_isError(sci->status.sres)) {
1884 /* The pre-handler completed the syscall itself, declaring
1885 success. */
1886 if (sci->flags & SfNoWriteResult) {
1887 PRINT(" --> [pre-success] NoWriteResult");
1888 } else {
1889 PRINT(" --> [pre-success] %s", VG_(sr_as_string)(sci->status.sres));
1891 /* In this case the allowable flags are to ask for a signal-poll
1892 and/or a yield after the call. Changing the args isn't
1893 allowed. */
1894 vg_assert(0 == (sci->flags
1895 & ~(SfPollAfter | SfYieldAfter | SfNoWriteResult)));
1896 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
1899 else
1900 if (sci->status.what == SsComplete && sr_isError(sci->status.sres)) {
1901 /* The pre-handler decided to fail syscall itself. */
1902 PRINT(" --> [pre-fail] %s", VG_(sr_as_string)(sci->status.sres));
1903 /* In this case, the pre-handler is also allowed to ask for the
1904 post-handler to be run anyway. Changing the args is not
1905 allowed. */
1906 vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter)));
1907 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
1910 else
1911 if (sci->status.what != SsHandToKernel) {
1912 /* huh?! */
1913 vg_assert(0);
1916 else /* (sci->status.what == HandToKernel) */ {
1917 /* Ok, this is the usual case -- and the complicated one. There
1918 are two subcases: sync and async. async is the general case
1919 and is to be used when there is any possibility that the
1920 syscall might block [a fact that the pre-handler must tell us
1921 via the sci->flags field.] Because the tidying-away /
1922 context-switch overhead of the async case could be large, if
1923 we are sure that the syscall will not block, we fast-track it
1924 by doing it directly in this thread, which is a lot
1925 simpler. */
1927 /* Check that the given flags are allowable: MayBlock, PollAfter
1928 and PostOnFail are ok. */
1929 vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter)));
1931 if (sci->flags & SfMayBlock) {
1933 /* Syscall may block, so run it asynchronously */
1934 vki_sigset_t mask;
1936 PRINT(" --> [async] ... \n");
1938 mask = tst->sig_mask;
1939 VG_(sanitize_client_sigmask)(&mask);
1941 /* Gack. More impedance matching. Copy the possibly
1942 modified syscall args back into the guest state. */
1943 /* JRS 2009-Mar-16: if the syscall args are possibly modified,
1944 then this assertion is senseless:
1945 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
1946 The case that exposed it was sys_posix_spawn on Darwin,
1947 which heavily modifies its arguments but then lets the call
1948 go through anyway, with SfToBlock set, hence we end up here. */
1949 putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex );
1951 /* SfNoWriteResult flag is invalid for blocking signals because
1952 do_syscall_for_client() directly modifies the guest state. */
1953 vg_assert(!(sci->flags & SfNoWriteResult));
1955 /* Drop the bigLock */
1956 VG_(release_BigLock)(tid, VgTs_WaitSys, "VG_(client_syscall)[async]");
1957 /* Urr. We're now in a race against other threads trying to
1958 acquire the bigLock. I guess that doesn't matter provided
1959 that do_syscall_for_client only touches thread-local
1960 state. */
1962 /* Do the call, which operates directly on the guest state,
1963 not on our abstracted copies of the args/result. */
1964 do_syscall_for_client(sysno, tst, &mask);
1966 /* do_syscall_for_client may not return if the syscall was
1967 interrupted by a signal. In that case, flow of control is
1968 first to m_signals.async_sighandler, which calls
1969 VG_(fixup_guest_state_after_syscall_interrupted), which
1970 fixes up the guest state, and possibly calls
1971 VG_(post_syscall). Once that's done, control drops back
1972 to the scheduler. */
1974 /* Darwin: do_syscall_for_client may not return if the
1975 syscall was workq_ops(WQOPS_THREAD_RETURN) and the kernel
1976 responded by starting the thread at wqthread_hijack(reuse=1)
1977 (to run another workqueue item). In that case, wqthread_hijack
1978 calls ML_(wqthread_continue), which is similar to
1979 VG_(fixup_guest_state_after_syscall_interrupted). */
1981 /* Reacquire the lock */
1982 VG_(acquire_BigLock)(tid, "VG_(client_syscall)[async]");
1984 /* Even more impedance matching. Extract the syscall status
1985 from the guest state. */
1986 getSyscallStatusFromGuestState( &sci->status, &tst->arch.vex );
1987 vg_assert(sci->status.what == SsComplete);
1989 /* Be decorative, if required. */
1990 if (VG_(clo_trace_syscalls)) {
1991 PRINT("SYSCALL[%d,%u](%s) ... [async] --> %s",
1992 VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno),
1993 VG_(sr_as_string)(sci->status.sres));
1996 } else {
1998 /* run the syscall directly */
1999 /* The pre-handler may have modified the syscall args, but
2000 since we're passing values in ->args directly to the
2001 kernel, there's no point in flushing them back to the
2002 guest state. Indeed doing so could be construed as
2003 incorrect. */
2004 SysRes sres
2005 = VG_(do_syscall)(sysno, sci->args.arg1, sci->args.arg2,
2006 sci->args.arg3, sci->args.arg4,
2007 sci->args.arg5, sci->args.arg6,
2008 sci->args.arg7, sci->args.arg8 );
2009 sci->status = convert_SysRes_to_SyscallStatus(sres);
2011 /* Be decorative, if required. */
2012 if (VG_(clo_trace_syscalls)) {
2013 PRINT("[sync] --> %s", VG_(sr_as_string)(sci->status.sres));
2018 vg_assert(sci->status.what == SsComplete);
2020 vg_assert(VG_(is_running_thread)(tid));
2022 /* Dump the syscall result back in the guest state. This is
2023 a platform-specific action. */
2024 if (!(sci->flags & SfNoWriteResult))
2025 putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex );
2027 /* If needed, gdbserver will report syscall return to GDB */
2028 VG_(gdbserver_report_syscall)(False, sysno, tid);
2030 /* Situation now:
2031 - the guest state is now correctly modified following the syscall
2032 - modified args, original args and syscall status are still
2033 available in the syscallInfo[] entry for this syscall.
2035 Now go on to do the post-syscall actions (read on down ..)
2037 PRINT(" ");
2038 VG_(post_syscall)(tid);
2039 PRINT("\n");
2043 /* Perform post syscall actions. The expected state on entry is
2044 precisely as at the end of VG_(client_syscall), that is:
2046 - guest state up to date following the syscall
2047 - modified args, original args and syscall status are still
2048 available in the syscallInfo[] entry for this syscall.
2049 - syscall status matches what's in the guest state.
2051 There are two ways to get here: the normal way -- being called by
2052 VG_(client_syscall), and the unusual way, from
2053 VG_(fixup_guest_state_after_syscall_interrupted).
2054 Darwin: there's a third way, ML_(wqthread_continue).
2056 void VG_(post_syscall) (ThreadId tid)
2058 SyscallInfo* sci;
2059 const SyscallTableEntry* ent;
2060 SyscallStatus test_status;
2061 ThreadState* tst;
2062 Word sysno;
2064 /* Preliminaries */
2065 vg_assert(VG_(is_valid_tid)(tid));
2066 vg_assert(tid >= 1 && tid < VG_N_THREADS);
2067 vg_assert(VG_(is_running_thread)(tid));
2069 tst = VG_(get_ThreadState)(tid);
2070 sci = & syscallInfo[tid];
2072 /* m_signals.sigvgkill_handler might call here even when not in
2073 a syscall. */
2074 if (sci->status.what == SsIdle || sci->status.what == SsHandToKernel) {
2075 sci->status.what = SsIdle;
2076 return;
2079 /* Validate current syscallInfo entry. In particular we require
2080 that the current .status matches what's actually in the guest
2081 state. At least in the normal case where we have actually
2082 previously written the result into the guest state. */
2083 vg_assert(sci->status.what == SsComplete);
2085 /* Get the system call number. Because the pre-handler isn't
2086 allowed to mess with it, it should be the same for both the
2087 original and potentially-modified args. */
2088 vg_assert(sci->args.sysno == sci->orig_args.sysno);
2089 sysno = sci->args.sysno;
2091 getSyscallStatusFromGuestState( &test_status, &tst->arch.vex );
2092 if (!(sci->flags & SfNoWriteResult))
2093 vg_assert(eq_SyscallStatus( sysno, &sci->status, &test_status ));
2094 /* Failure of the above assertion on Darwin can indicate a problem
2095 in the syscall wrappers that pre-fail or pre-succeed the
2096 syscall, by calling SET_STATUS_Success or SET_STATUS_Failure,
2097 when they really should call SET_STATUS_from_SysRes. The former
2098 create a UNIX-class syscall result on Darwin, which may not be
2099 correct for the syscall; if that's the case then this assertion
2100 fires. See PRE(thread_fast_set_cthread_self) for an example. On
2101 non-Darwin platforms this assertion is should never fail, and this
2102 comment is completely irrelevant. */
2103 /* Ok, looks sane */
2105 /* pre: status == Complete (asserted above) */
2106 /* Consider either success or failure. Now run the post handler if:
2107 - it exists, and
2108 - Success or (Failure and PostOnFail is set)
2110 ent = get_syscall_entry(sysno);
2111 if (ent->after
2112 && ((!sr_isError(sci->status.sres))
2113 || (sr_isError(sci->status.sres)
2114 && (sci->flags & SfPostOnFail) ))) {
2116 (ent->after)( tid, &sci->args, &sci->status );
2119 /* Because the post handler might have changed the status (eg, the
2120 post-handler for sys_open can change the result from success to
2121 failure if the kernel supplied a fd that it doesn't like), once
2122 again dump the syscall result back in the guest state.*/
2123 if (!(sci->flags & SfNoWriteResult))
2124 putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex );
2126 /* Do any post-syscall actions required by the tool. */
2127 if (VG_(needs).syscall_wrapper) {
2128 UWord tmpv[8];
2129 tmpv[0] = sci->orig_args.arg1;
2130 tmpv[1] = sci->orig_args.arg2;
2131 tmpv[2] = sci->orig_args.arg3;
2132 tmpv[3] = sci->orig_args.arg4;
2133 tmpv[4] = sci->orig_args.arg5;
2134 tmpv[5] = sci->orig_args.arg6;
2135 tmpv[6] = sci->orig_args.arg7;
2136 tmpv[7] = sci->orig_args.arg8;
2137 VG_TDICT_CALL(tool_post_syscall, tid,
2138 sysno,
2139 &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0]),
2140 sci->status.sres);
2143 /* The syscall is done. */
2144 vg_assert(sci->status.what == SsComplete);
2145 sci->status.what = SsIdle;
2147 /* The pre/post wrappers may have concluded that pending signals
2148 might have been created, and will have set SfPollAfter to
2149 request a poll for them once the syscall is done. */
2150 if (sci->flags & SfPollAfter)
2151 VG_(poll_signals)(tid);
2153 /* Similarly, the wrappers might have asked for a yield
2154 afterwards. */
2155 if (sci->flags & SfYieldAfter)
2156 VG_(vg_yield)();
2160 /* ---------------------------------------------------------------------
2161 Dealing with syscalls which get interrupted by a signal:
2162 VG_(fixup_guest_state_after_syscall_interrupted)
2163 ------------------------------------------------------------------ */
2165 /* Syscalls done on behalf of the client are finally handed off to the
2166 kernel in VG_(client_syscall) above, either by calling
2167 do_syscall_for_client (the async case), or by calling
2168 VG_(do_syscall6) (the sync case).
2170 If the syscall is not interrupted by a signal (it may block and
2171 later unblock, but that's irrelevant here) then those functions
2172 eventually return and so control is passed to VG_(post_syscall).
2173 NB: not sure if the sync case can actually get interrupted, as it
2174 operates with all signals masked.
2176 However, the syscall may get interrupted by an async-signal. In
2177 that case do_syscall_for_client/VG_(do_syscall6) do not
2178 return. Instead we wind up in m_signals.async_sighandler. We need
2179 to fix up the guest state to make it look like the syscall was
2180 interrupted for guest. So async_sighandler calls here, and this
2181 does the fixup. Note that from here we wind up calling
2182 VG_(post_syscall) too.
2186 /* These are addresses within ML_(do_syscall_for_client_WRK). See
2187 syscall-$PLAT.S for details.
2189 #if defined(VGO_linux)
2190 extern const Addr ML_(blksys_setup);
2191 extern const Addr ML_(blksys_restart);
2192 extern const Addr ML_(blksys_complete);
2193 extern const Addr ML_(blksys_committed);
2194 extern const Addr ML_(blksys_finished);
2195 #elif defined(VGO_darwin)
2196 /* Darwin requires extra uglyness */
2197 extern const Addr ML_(blksys_setup_MACH);
2198 extern const Addr ML_(blksys_restart_MACH);
2199 extern const Addr ML_(blksys_complete_MACH);
2200 extern const Addr ML_(blksys_committed_MACH);
2201 extern const Addr ML_(blksys_finished_MACH);
2202 extern const Addr ML_(blksys_setup_MDEP);
2203 extern const Addr ML_(blksys_restart_MDEP);
2204 extern const Addr ML_(blksys_complete_MDEP);
2205 extern const Addr ML_(blksys_committed_MDEP);
2206 extern const Addr ML_(blksys_finished_MDEP);
2207 extern const Addr ML_(blksys_setup_UNIX);
2208 extern const Addr ML_(blksys_restart_UNIX);
2209 extern const Addr ML_(blksys_complete_UNIX);
2210 extern const Addr ML_(blksys_committed_UNIX);
2211 extern const Addr ML_(blksys_finished_UNIX);
2212 #elif defined(VGO_solaris)
2213 extern const Addr ML_(blksys_setup);
2214 extern const Addr ML_(blksys_complete);
2215 extern const Addr ML_(blksys_committed);
2216 extern const Addr ML_(blksys_finished);
2217 extern const Addr ML_(blksys_setup_DRET);
2218 extern const Addr ML_(blksys_complete_DRET);
2219 extern const Addr ML_(blksys_committed_DRET);
2220 extern const Addr ML_(blksys_finished_DRET);
2221 #else
2222 # error "Unknown OS"
2223 #endif
2226 /* Back up guest state to restart a system call. */
2228 void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
2230 #if defined(VGP_x86_linux)
2231 arch->vex.guest_EIP -= 2; // sizeof(int $0x80)
2233 /* Make sure our caller is actually sane, and we're really backing
2234 back over a syscall.
2236 int $0x80 == CD 80
2239 UChar *p = (UChar *)arch->vex.guest_EIP;
2241 if (p[0] != 0xcd || p[1] != 0x80)
2242 VG_(message)(Vg_DebugMsg,
2243 "?! restarting over syscall at %#x %02x %02x\n",
2244 arch->vex.guest_EIP, p[0], p[1]);
2246 vg_assert(p[0] == 0xcd && p[1] == 0x80);
2249 #elif defined(VGP_amd64_linux)
2250 arch->vex.guest_RIP -= 2; // sizeof(syscall)
2252 /* Make sure our caller is actually sane, and we're really backing
2253 back over a syscall.
2255 syscall == 0F 05
2258 UChar *p = (UChar *)arch->vex.guest_RIP;
2260 if (p[0] != 0x0F || p[1] != 0x05)
2261 VG_(message)(Vg_DebugMsg,
2262 "?! restarting over syscall at %#llx %02x %02x\n",
2263 arch->vex.guest_RIP, p[0], p[1]);
2265 vg_assert(p[0] == 0x0F && p[1] == 0x05);
2268 #elif defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux)
2269 arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr)
2271 /* Make sure our caller is actually sane, and we're really backing
2272 back over a syscall.
2274 sc == 44 00 00 02
2277 UChar *p = (UChar *)arch->vex.guest_CIA;
2279 if (p[0] != 0x44 || p[1] != 0x0 || p[2] != 0x0 || p[3] != 0x02)
2280 VG_(message)(Vg_DebugMsg,
2281 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2282 (ULong)arch->vex.guest_CIA, p[0], p[1], p[2], p[3]);
2284 vg_assert(p[0] == 0x44 && p[1] == 0x0 && p[2] == 0x0 && p[3] == 0x2);
2287 #elif defined(VGP_ppc64le_linux)
2288 arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr)
2290 /* Make sure our caller is actually sane, and we're really backing
2291 back over a syscall.
2293 sc == 44 00 00 02
2296 UChar *p = (UChar *)arch->vex.guest_CIA;
2298 if (p[3] != 0x44 || p[2] != 0x0 || p[1] != 0x0 || p[0] != 0x02)
2299 VG_(message)(Vg_DebugMsg,
2300 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2301 arch->vex.guest_CIA, p[3], p[2], p[1], p[0]);
2303 vg_assert(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0 && p[0] == 0x2);
2306 #elif defined(VGP_arm_linux)
2307 if (arch->vex.guest_R15T & 1) {
2308 // Thumb mode. SVC is a encoded as
2309 // 1101 1111 imm8
2310 // where imm8 is the SVC number, and we only accept 0.
2311 arch->vex.guest_R15T -= 2; // sizeof(thumb 16 bit insn)
2312 UChar* p = (UChar*)(arch->vex.guest_R15T - 1);
2313 Bool valid = p[0] == 0 && p[1] == 0xDF;
2314 if (!valid) {
2315 VG_(message)(Vg_DebugMsg,
2316 "?! restarting over (Thumb) syscall that is not syscall "
2317 "at %#x %02x %02x\n",
2318 arch->vex.guest_R15T - 1, p[0], p[1]);
2320 vg_assert(valid);
2321 // FIXME: NOTE, this really isn't right. We need to back up
2322 // ITSTATE to what it was before the SVC instruction, but we
2323 // don't know what it was. At least assert that it is now
2324 // zero, because if it is nonzero then it must also have
2325 // been nonzero for the SVC itself, which means it was
2326 // conditional. Urk.
2327 vg_assert(arch->vex.guest_ITSTATE == 0);
2328 } else {
2329 // ARM mode. SVC is encoded as
2330 // cond 1111 imm24
2331 // where imm24 is the SVC number, and we only accept 0.
2332 arch->vex.guest_R15T -= 4; // sizeof(arm instr)
2333 UChar* p = (UChar*)arch->vex.guest_R15T;
2334 Bool valid = p[0] == 0 && p[1] == 0 && p[2] == 0
2335 && (p[3] & 0xF) == 0xF;
2336 if (!valid) {
2337 VG_(message)(Vg_DebugMsg,
2338 "?! restarting over (ARM) syscall that is not syscall "
2339 "at %#x %02x %02x %02x %02x\n",
2340 arch->vex.guest_R15T, p[0], p[1], p[2], p[3]);
2342 vg_assert(valid);
2345 #elif defined(VGP_arm64_linux)
2346 arch->vex.guest_PC -= 4; // sizeof(arm64 instr)
2348 /* Make sure our caller is actually sane, and we're really backing
2349 back over a syscall.
2351 svc #0 == d4 00 00 01
2354 UChar *p = (UChar *)arch->vex.guest_PC;
2356 if (p[0] != 0x01 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0xD4)
2357 VG_(message)(
2358 Vg_DebugMsg,
2359 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2360 arch->vex.guest_PC, p[0], p[1], p[2], p[3]
2363 vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4);
2366 #elif defined(VGP_x86_darwin)
2367 arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL;
2369 /* Make sure our caller is actually sane, and we're really backing
2370 back over a syscall.
2372 int $0x80 == CD 80 // Used to communicate with BSD syscalls
2373 int $0x81 == CD 81 // Used to communicate with Mach traps
2374 int $0x82 == CD 82 // Used to communicate with "thread" ?
2375 sysenter == 0F 34 // Used to communicate with Unix syscalls
2378 UChar *p = (UChar *)arch->vex.guest_EIP;
2379 Bool ok = (p[0] == 0xCD && p[1] == 0x80)
2380 || (p[0] == 0xCD && p[1] == 0x81)
2381 || (p[0] == 0xCD && p[1] == 0x82)
2382 || (p[0] == 0x0F && p[1] == 0x34);
2383 if (!ok)
2384 VG_(message)(Vg_DebugMsg,
2385 "?! restarting over syscall at %#x %02x %02x\n",
2386 arch->vex.guest_EIP, p[0], p[1]);
2387 vg_assert(ok);
2390 #elif defined(VGP_amd64_darwin)
2391 arch->vex.guest_RIP = arch->vex.guest_IP_AT_SYSCALL;
2393 /* Make sure our caller is actually sane, and we're really backing
2394 back over a syscall.
2396 syscall == 0F 05
2399 UChar *p = (UChar *)arch->vex.guest_RIP;
2401 Bool ok = (p[0] == 0x0F && p[1] == 0x05);
2402 if (!ok)
2403 VG_(message)(Vg_DebugMsg,
2404 "?! restarting over syscall at %#llx %02x %02x\n",
2405 arch->vex.guest_RIP, p[0], p[1]);
2406 vg_assert(ok);
2409 #elif defined(VGP_s390x_linux)
2410 arch->vex.guest_IA -= 2; // sizeof(syscall)
2412 /* Make sure our caller is actually sane, and we're really backing
2413 back over a syscall.
2415 syscall == 0A <num>
2418 UChar *p = (UChar *)arch->vex.guest_IA;
2419 if (p[0] != 0x0A)
2420 VG_(message)(Vg_DebugMsg,
2421 "?! restarting over syscall at %#llx %02x %02x\n",
2422 arch->vex.guest_IA, p[0], p[1]);
2424 vg_assert(p[0] == 0x0A);
2427 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
2429 arch->vex.guest_PC -= 4; // sizeof(mips instr)
2431 /* Make sure our caller is actually sane, and we're really backing
2432 back over a syscall.
2434 syscall == 00 00 00 0C
2435 big endian
2436 syscall == 0C 00 00 00
2439 UChar *p = (UChar *)(Addr)(arch->vex.guest_PC);
2440 # if defined (VG_LITTLEENDIAN)
2441 if (p[0] != 0x0c || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00)
2442 VG_(message)(Vg_DebugMsg,
2443 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2444 (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
2446 vg_assert(p[0] == 0x0c && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00);
2447 # elif defined (VG_BIGENDIAN)
2448 if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x0c)
2449 VG_(message)(Vg_DebugMsg,
2450 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2451 (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
2453 vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c);
2454 # else
2455 # error "Unknown endianness"
2456 # endif
2459 #elif defined(VGP_x86_solaris)
2460 arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall)
2462 /* Make sure our caller is actually sane, and we're really backing
2463 back over a syscall.
2465 int $0x91 == CD 91
2466 syscall == 0F 05
2467 sysenter == 0F 34
2469 Handle also other syscall instructions because we also handle them in
2470 the scheduler.
2471 int $0x80 == CD 80
2472 int $0x81 == CD 81
2473 int $0x82 == CD 82
2476 UChar *p = (UChar *)arch->vex.guest_EIP;
2478 Bool ok = (p[0] == 0xCD && p[1] == 0x91)
2479 || (p[0] == 0x0F && p[1] == 0x05)
2480 || (p[0] == 0x0F && p[1] == 0x34)
2481 || (p[0] == 0xCD && p[1] == 0x80)
2482 || (p[0] == 0xCD && p[1] == 0x81)
2483 || (p[0] == 0xCD && p[1] == 0x82);
2484 if (!ok)
2485 VG_(message)(Vg_DebugMsg,
2486 "?! restarting over syscall at %#x %02x %02x\n",
2487 arch->vex.guest_EIP, p[0], p[1]);
2488 vg_assert(ok);
2491 #elif defined(VGP_amd64_solaris)
2492 arch->vex.guest_RIP -= 2; // sizeof(syscall)
2494 /* Make sure our caller is actually sane, and we're really backing
2495 back over a syscall.
2497 syscall == 0F 05
2500 UChar *p = (UChar *)arch->vex.guest_RIP;
2502 Bool ok = (p[0] == 0x0F && p[1] == 0x05);
2503 if (!ok)
2504 VG_(message)(Vg_DebugMsg,
2505 "?! restarting over syscall at %#llx %02x %02x\n",
2506 arch->vex.guest_RIP, p[0], p[1]);
2507 vg_assert(ok);
2510 #else
2511 # error "ML_(fixup_guest_state_to_restart_syscall): unknown plat"
2512 #endif
2517 Fix up the guest state when a syscall is interrupted by a signal
2518 and so has been forced to return 'sysret'.
2520 To do this, we determine the precise state of the syscall by
2521 looking at the (real) IP at the time the signal happened. The
2522 syscall sequence looks like:
2524 1. unblock signals
2525 2. perform syscall
2526 3. save result to guest state (EAX, RAX, R3+CR0.SO, R0, V0)
2527 4. re-block signals
2529 If a signal
2530 happens at Then Why?
2531 [1-2) restart nothing has happened (restart syscall)
2532 [2] restart syscall hasn't started, or kernel wants to restart
2533 [2-3) save syscall complete, but results not saved
2534 [3-4) syscall complete, results saved
2536 Sometimes we never want to restart an interrupted syscall (because
2537 sigaction says not to), so we only restart if "restart" is True.
2539 This will also call VG_(post_syscall) if the syscall has actually
2540 completed (either because it was interrupted, or because it
2541 actually finished). It will not call VG_(post_syscall) if the
2542 syscall is set up for restart, which means that the pre-wrapper may
2543 get called multiple times.
2546 void
2547 VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid,
2548 Addr ip,
2549 SysRes sres,
2550 Bool restart,
2551 struct vki_ucontext *uc)
2553 /* Note that we don't know the syscall number here, since (1) in
2554 general there's no reliable way to get hold of it short of
2555 stashing it in the guest state before the syscall, and (2) in
2556 any case we don't need to know it for the actions done by this
2557 routine.
2559 Furthermore, 'sres' is only used in the case where the syscall
2560 is complete, but the result has not been committed to the guest
2561 state yet. In any other situation it will be meaningless and
2562 therefore ignored. */
2564 ThreadState* tst;
2565 SyscallStatus canonical;
2566 ThreadArchState* th_regs;
2567 SyscallInfo* sci;
2569 /* Compute some Booleans indicating which range we're in. */
2570 Bool outside_range,
2571 in_setup_to_restart, // [1,2) in the .S files
2572 at_restart, // [2] in the .S files
2573 in_complete_to_committed, // [3,4) in the .S files
2574 in_committed_to_finished; // [4,5) in the .S files
2576 if (VG_(clo_trace_signals))
2577 VG_(message)( Vg_DebugMsg,
2578 "interrupted_syscall: tid=%u, ip=%#lx, "
2579 "restart=%s, sres.isErr=%s, sres.val=%" FMT_REGWORD "u\n",
2580 tid,
2582 restart ? "True" : "False",
2583 sr_isError(sres) ? "True" : "False",
2584 sr_isError(sres) ? (RegWord)sr_Err(sres) :
2585 (RegWord)sr_Res(sres));
2587 vg_assert(VG_(is_valid_tid)(tid));
2588 vg_assert(tid >= 1 && tid < VG_N_THREADS);
2589 vg_assert(VG_(is_running_thread)(tid));
2591 tst = VG_(get_ThreadState)(tid);
2592 th_regs = &tst->arch;
2593 sci = & syscallInfo[tid];
2595 # if defined(VGO_linux)
2596 outside_range
2597 = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished);
2598 in_setup_to_restart
2599 = ip >= ML_(blksys_setup) && ip < ML_(blksys_restart);
2600 at_restart
2601 = ip == ML_(blksys_restart);
2602 in_complete_to_committed
2603 = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed);
2604 in_committed_to_finished
2605 = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished);
2606 # elif defined(VGO_darwin)
2607 outside_range
2608 = (ip < ML_(blksys_setup_MACH) || ip >= ML_(blksys_finished_MACH))
2609 && (ip < ML_(blksys_setup_MDEP) || ip >= ML_(blksys_finished_MDEP))
2610 && (ip < ML_(blksys_setup_UNIX) || ip >= ML_(blksys_finished_UNIX));
2611 in_setup_to_restart
2612 = (ip >= ML_(blksys_setup_MACH) && ip < ML_(blksys_restart_MACH))
2613 || (ip >= ML_(blksys_setup_MDEP) && ip < ML_(blksys_restart_MDEP))
2614 || (ip >= ML_(blksys_setup_UNIX) && ip < ML_(blksys_restart_UNIX));
2615 at_restart
2616 = (ip == ML_(blksys_restart_MACH))
2617 || (ip == ML_(blksys_restart_MDEP))
2618 || (ip == ML_(blksys_restart_UNIX));
2619 in_complete_to_committed
2620 = (ip >= ML_(blksys_complete_MACH) && ip < ML_(blksys_committed_MACH))
2621 || (ip >= ML_(blksys_complete_MDEP) && ip < ML_(blksys_committed_MDEP))
2622 || (ip >= ML_(blksys_complete_UNIX) && ip < ML_(blksys_committed_UNIX));
2623 in_committed_to_finished
2624 = (ip >= ML_(blksys_committed_MACH) && ip < ML_(blksys_finished_MACH))
2625 || (ip >= ML_(blksys_committed_MDEP) && ip < ML_(blksys_finished_MDEP))
2626 || (ip >= ML_(blksys_committed_UNIX) && ip < ML_(blksys_finished_UNIX));
2627 /* Wasn't that just So Much Fun? Does your head hurt yet? Mine does. */
2628 # elif defined(VGO_solaris)
2629 /* The solaris port is never outside the range. */
2630 outside_range = False;
2631 /* The Solaris kernel never restarts syscalls directly! */
2632 at_restart = False;
2633 if (tst->os_state.in_door_return) {
2634 vg_assert(ip >= ML_(blksys_setup_DRET)
2635 && ip < ML_(blksys_finished_DRET));
2637 in_setup_to_restart
2638 = ip >= ML_(blksys_setup_DRET) && ip < ML_(blksys_complete_DRET);
2639 in_complete_to_committed
2640 = ip >= ML_(blksys_complete_DRET) && ip < ML_(blksys_committed_DRET);
2641 in_committed_to_finished
2642 = ip >= ML_(blksys_committed_DRET) && ip < ML_(blksys_finished_DRET);
2644 else {
2645 vg_assert(ip >= ML_(blksys_setup) && ip < ML_(blksys_finished));
2647 in_setup_to_restart
2648 = ip >= ML_(blksys_setup) && ip < ML_(blksys_complete);
2649 in_complete_to_committed
2650 = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed);
2651 in_committed_to_finished
2652 = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished);
2654 # else
2655 # error "Unknown OS"
2656 # endif
2658 /* Figure out what the state of the syscall was by examining the
2659 (real) IP at the time of the signal, and act accordingly. */
2660 if (outside_range) {
2661 if (VG_(clo_trace_signals))
2662 VG_(message)( Vg_DebugMsg,
2663 " not in syscall at all: hmm, very suspicious\n" );
2664 /* Looks like we weren't in a syscall at all. Hmm. */
2665 vg_assert(sci->status.what != SsIdle);
2666 return;
2669 /* We should not be here unless this thread had first started up
2670 the machinery for a syscall by calling VG_(client_syscall).
2671 Hence: */
2672 vg_assert(sci->status.what != SsIdle);
2674 /* now, do one of four fixup actions, depending on where the IP has
2675 got to. */
2677 if (in_setup_to_restart) {
2678 /* syscall hasn't even started; go around again */
2679 if (VG_(clo_trace_signals))
2680 VG_(message)( Vg_DebugMsg, " not started: restarting\n");
2681 vg_assert(sci->status.what == SsHandToKernel);
2682 ML_(fixup_guest_state_to_restart_syscall)(th_regs);
2685 else
2686 if (at_restart) {
2687 # if defined(VGO_solaris)
2688 /* We should never hit this branch on Solaris, see the comment above. */
2689 vg_assert(0);
2690 # endif
2692 /* We're either about to run the syscall, or it was interrupted
2693 and the kernel restarted it. Restart if asked, otherwise
2694 EINTR it. */
2695 if (restart) {
2696 if (VG_(clo_trace_signals))
2697 VG_(message)( Vg_DebugMsg, " at syscall instr: restarting\n");
2698 ML_(fixup_guest_state_to_restart_syscall)(th_regs);
2699 } else {
2700 if (VG_(clo_trace_signals))
2701 VG_(message)( Vg_DebugMsg, " at syscall instr: returning EINTR\n");
2702 canonical = convert_SysRes_to_SyscallStatus(
2703 VG_(mk_SysRes_Error)( VKI_EINTR )
2705 if (!(sci->flags & SfNoWriteResult))
2706 putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex );
2707 sci->status = canonical;
2708 VG_(post_syscall)(tid);
2712 else
2713 if (in_complete_to_committed) {
2714 /* Syscall complete, but result hasn't been written back yet.
2715 Write the SysRes we were supplied with back to the guest
2716 state. */
2717 if (VG_(clo_trace_signals))
2718 VG_(message)( Vg_DebugMsg,
2719 " completed, but uncommitted: committing\n");
2720 canonical = convert_SysRes_to_SyscallStatus( sres );
2721 vg_assert(!(sci->flags & SfNoWriteResult));
2722 putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex );
2723 # if defined(VGO_solaris)
2724 if (tst->os_state.in_door_return) {
2725 # if defined(VGP_x86_solaris)
2726 /* Registers %esp and %ebp were also modified by the syscall. */
2727 tst->arch.vex.guest_ESP = uc->uc_mcontext.gregs[VKI_UESP];
2728 tst->arch.vex.guest_EBP = uc->uc_mcontext.gregs[VKI_EBP];
2729 # elif defined(VGP_amd64_solaris)
2730 tst->arch.vex.guest_RSP = uc->uc_mcontext.gregs[VKI_REG_RSP];
2731 tst->arch.vex.guest_RBP = uc->uc_mcontext.gregs[VKI_REG_RBP];
2732 # endif
2734 # endif
2735 sci->status = canonical;
2736 VG_(post_syscall)(tid);
2739 else
2740 if (in_committed_to_finished) {
2741 /* Result committed, but the signal mask has not been restored;
2742 we expect our caller (the signal handler) will have fixed
2743 this up. */
2744 if (VG_(clo_trace_signals))
2745 VG_(message)( Vg_DebugMsg,
2746 " completed and committed: nothing to do\n");
2747 # if defined(VGP_x86_solaris)
2748 /* The %eax and %edx values are committed but the carry flag is still
2749 uncommitted. Save it now. */
2750 LibVEX_GuestX86_put_eflag_c(sr_isError(sres), &th_regs->vex);
2751 # elif defined(VGP_amd64_solaris)
2752 LibVEX_GuestAMD64_put_rflag_c(sr_isError(sres), &th_regs->vex);
2753 # endif
2754 getSyscallStatusFromGuestState( &sci->status, &th_regs->vex );
2755 vg_assert(sci->status.what == SsComplete);
2756 VG_(post_syscall)(tid);
2759 else
2760 VG_(core_panic)("?? strange syscall interrupt state?");
2762 /* In all cases, the syscall is now finished (even if we called
2763 ML_(fixup_guest_state_to_restart_syscall), since that just
2764 re-positions the guest's IP for another go at it). So we need
2765 to record that fact. */
2766 sci->status.what = SsIdle;
2770 #if defined(VGO_solaris)
2771 /* Returns True if ip is inside a fixable syscall code in syscall-*-*.S. This
2772 function can be called by a 'non-running' thread! */
2773 Bool VG_(is_ip_in_blocking_syscall)(ThreadId tid, Addr ip)
2775 ThreadState *tst = VG_(get_ThreadState)(tid);
2777 if (tst->os_state.in_door_return)
2778 return ip >= ML_(blksys_setup_DRET) && ip < ML_(blksys_finished_DRET);
2779 else
2780 return ip >= ML_(blksys_setup) && ip < ML_(blksys_finished);
2782 #endif
2785 #if defined(VGO_darwin)
2786 // Clean up after workq_ops(WQOPS_THREAD_RETURN) jumped to wqthread_hijack.
2787 // This is similar to VG_(fixup_guest_state_after_syscall_interrupted).
2788 // This longjmps back to the scheduler.
2789 void ML_(wqthread_continue_NORETURN)(ThreadId tid)
2791 ThreadState* tst;
2792 SyscallInfo* sci;
2794 VG_(acquire_BigLock)(tid, "wqthread_continue_NORETURN");
2796 PRINT("SYSCALL[%d,%u](%s) workq_ops() starting new workqueue item\n",
2797 VG_(getpid)(), tid, VG_SYSNUM_STRING(__NR_workq_ops));
2799 vg_assert(VG_(is_valid_tid)(tid));
2800 vg_assert(tid >= 1 && tid < VG_N_THREADS);
2801 vg_assert(VG_(is_running_thread)(tid));
2803 tst = VG_(get_ThreadState)(tid);
2804 sci = & syscallInfo[tid];
2805 vg_assert(sci->status.what != SsIdle);
2806 vg_assert(tst->os_state.wq_jmpbuf_valid); // check this BEFORE post_syscall
2808 // Pretend the syscall completed normally, but don't touch the thread state.
2809 sci->status = convert_SysRes_to_SyscallStatus( VG_(mk_SysRes_Success)(0) );
2810 sci->flags |= SfNoWriteResult;
2811 VG_(post_syscall)(tid);
2813 ML_(sync_mappings)("in", "ML_(wqthread_continue_NORETURN)", 0);
2815 sci->status.what = SsIdle;
2817 vg_assert(tst->sched_jmpbuf_valid);
2818 VG_MINIMAL_LONGJMP(tst->sched_jmpbuf);
2820 /* NOTREACHED */
2821 vg_assert(0);
2823 #endif
2826 /* ---------------------------------------------------------------------
2827 A place to store the where-to-call-when-really-done pointer
2828 ------------------------------------------------------------------ */
2830 // When the final thread is done, where shall I call to shutdown the
2831 // system cleanly? Is set once at startup (in m_main) and never
2832 // changes after that. Is basically a pointer to the exit
2833 // continuation. This is all just a nasty hack to avoid calling
2834 // directly from m_syswrap to m_main at exit, since that would cause
2835 // m_main to become part of a module cycle, which is silly.
2836 void (* VG_(address_of_m_main_shutdown_actions_NORETURN) )
2837 (ThreadId,VgSchedReturnCode)
2838 = NULL;
2840 /*--------------------------------------------------------------------*/
2841 /*--- end ---*/
2842 /*--------------------------------------------------------------------*/