Bug 444488 - Use glibc.pthread.stack_cache_size tunable
[valgrind.git] / coregrind / m_syswrap / syswrap-main.c
blob5077a7da73f706cbbd2ff7b6b050596bdc2b518f
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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #include "libvex_guest_offsets.h"
30 #include "libvex_trc_values.h"
31 #include "pub_core_basics.h"
32 #include "pub_core_aspacemgr.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_threadstate.h"
36 #include "pub_core_libcbase.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcproc.h" // For VG_(getpid)()
40 #include "pub_core_libcsignal.h"
41 #include "pub_core_scheduler.h" // For VG_({acquire,release}_BigLock),
42 // and VG_(vg_yield)
43 #include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
44 #include "pub_core_tooliface.h"
45 #include "pub_core_options.h"
46 #include "pub_core_signals.h" // For VG_SIGVGKILL, VG_(poll_signals)
47 #include "pub_core_syscall.h"
48 #include "pub_core_machine.h"
49 #include "pub_core_mallocfree.h"
50 #include "pub_core_syswrap.h"
51 #include "pub_core_gdbserver.h" // VG_(gdbserver_report_syscall)
53 #include "priv_types_n_macros.h"
54 #include "priv_syswrap-main.h"
56 #if defined(VGO_darwin)
57 #include "priv_syswrap-darwin.h"
58 #endif
60 /* Useful info which needs to be recorded somewhere:
61 Use of registers in syscalls is:
63 NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
64 LINUX:
65 x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
66 amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
67 ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
68 ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
69 arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
70 mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
71 mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
72 arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
74 FreeBSD:
75 x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
76 amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
78 On s390x the svc instruction is used for system calls. The system call
79 number is encoded in the instruction (8 bit immediate field). Since Linux
80 2.6 it is also allowed to use svc 0 with the system call number in r1.
81 This was introduced for system calls >255, but works for all. It is
82 also possible to see the svc 0 together with an EXecute instruction, that
83 fills in the immediate field.
84 s390x r1/SVC r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1)
86 NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
87 DARWIN:
88 x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
89 amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
91 For x86-darwin and x86-freebsd, "+N" denotes "in memory at N(%esp)";
92 ditto amd64-darwin/amd64-freebsd. Apparently 0(%esp) is some kind of return address
93 (perhaps for syscalls done with "sysenter"?) I don't think it is
94 relevant for syscalls done with "int $0x80/1/2".
96 SOLARIS:
97 x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
98 amd64 rax rdi rsi rdx r10 r8 r9 +8 +16 rdx:rax, rflags.c
100 "+N" denotes "in memory at N(%esp)". Solaris also supports fasttrap
101 syscalls. Fasttraps do not take any parameters (except of the sysno in eax)
102 and never fail (if the sysno is valid).
105 /* This is the top level of the system-call handler module. All
106 system calls are channelled through here, doing two things:
108 * notify the tool of the events (mem/reg reads, writes) happening
110 * perform the syscall, usually by passing it along to the kernel
111 unmodified.
113 A magical piece of assembly code, do_syscall_for_client_WRK, in
114 syscall-$PLATFORM.S does the tricky bit of passing a syscall to the
115 kernel, whilst having the simulator retain control.
118 /* The main function is VG_(client_syscall). The simulation calls it
119 whenever a client thread wants to do a syscall. The following is a
120 sketch of what it does.
122 * Ensures the root thread's stack is suitably mapped. Tedious and
123 arcane. See big big comment in VG_(client_syscall).
125 * First, it rounds up the syscall number and args (which is a
126 platform dependent activity) and puts them in a struct ("args")
127 and also a copy in "orig_args".
129 The pre/post wrappers refer to these structs and so no longer
130 need magic macros to access any specific registers. This struct
131 is stored in thread-specific storage.
134 * The pre-wrapper is called, passing it a pointer to struct
135 "args".
138 * The pre-wrapper examines the args and pokes the tool
139 appropriately. It may modify the args; this is why "orig_args"
140 is also stored.
142 The pre-wrapper may choose to 'do' the syscall itself, and
143 concludes one of three outcomes:
145 Success(N) -- syscall is already complete, with success;
146 result is N
148 Fail(N) -- syscall is already complete, with failure;
149 error code is N
151 HandToKernel -- (the usual case): this needs to be given to
152 the kernel to be done, using the values in
153 the possibly-modified "args" struct.
155 In addition, the pre-wrapper may set some flags:
157 MayBlock -- only applicable when outcome==HandToKernel
159 PostOnFail -- only applicable when outcome==HandToKernel or Fail
162 * If the pre-outcome is HandToKernel, the syscall is duly handed
163 off to the kernel (perhaps involving some thread switchery, but
164 that's not important). This reduces the possible set of outcomes
165 to either Success(N) or Fail(N).
168 * The outcome (Success(N) or Fail(N)) is written back to the guest
169 register(s). This is platform specific:
171 x86: Success(N) ==> eax = N
172 Fail(N) ==> eax = -N
174 ditto amd64
176 ppc32: Success(N) ==> r3 = N, CR0.SO = 0
177 Fail(N) ==> r3 = N, CR0.SO = 1
179 FreeBSD:
180 x86: Success(N) ==> edx:eax = N, cc = 0
181 Fail(N) ==> edx:eax = N, cc = 1
183 ditto amd64
185 Darwin:
186 x86: Success(N) ==> edx:eax = N, cc = 0
187 Fail(N) ==> edx:eax = N, cc = 1
189 s390x: Success(N) ==> r2 = N
190 Fail(N) ==> r2 = -N
192 Solaris:
193 x86: Success(N) ==> edx:eax = N, cc = 0
194 Fail(N) ==> eax = N, cc = 1
195 Same applies for fasttraps except they never fail.
197 * The post wrapper is called if:
199 - it exists, and
200 - outcome==Success or (outcome==Fail and PostOnFail is set)
202 The post wrapper is passed the adulterated syscall args (struct
203 "args"), and the syscall outcome (viz, Success(N) or Fail(N)).
205 There are several other complications, primarily to do with
206 syscalls getting interrupted, explained in comments in the code.
209 /* CAVEATS for writing wrappers. It is important to follow these!
211 The macros defined in priv_types_n_macros.h are designed to help
212 decouple the wrapper logic from the actual representation of
213 syscall args/results, since these wrappers are designed to work on
214 multiple platforms.
216 Sometimes a PRE wrapper will complete the syscall itself, without
217 handing it to the kernel. It will use one of SET_STATUS_Success,
218 SET_STATUS_Failure or SET_STATUS_from_SysRes to set the return
219 value. It is critical to appreciate that use of the macro does not
220 immediately cause the underlying guest state to be updated -- that
221 is done by the driver logic in this file, when the wrapper returns.
223 As a result, PRE wrappers of the following form will malfunction:
225 PRE(fooble)
227 ... do stuff ...
228 SET_STATUS_Somehow(...)
230 // do something that assumes guest state is up to date
233 In particular, direct or indirect calls to VG_(poll_signals) after
234 setting STATUS can cause the guest state to be read (in order to
235 build signal frames). Do not do this. If you want a signal poll
236 after the syscall goes through, do "*flags |= SfPollAfter" and the
237 driver logic will do it for you.
239 -----------
241 Another critical requirement following introduction of new address
242 space manager (JRS, 20050923):
244 In a situation where the mappedness of memory has changed, aspacem
245 should be notified BEFORE the tool. Hence the following is
246 correct:
248 Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start);
249 VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start );
250 if (d)
251 VG_(discard_translations)(s->start, s->end+1 - s->start);
253 whilst this is wrong:
255 VG_TRACK( die_mem_munmap, s->start, s->end+1 - s->start );
256 Bool d = VG_(am_notify_munmap)(s->start, s->end+1 - s->start);
257 if (d)
258 VG_(discard_translations)(s->start, s->end+1 - s->start);
260 The reason is that the tool may itself ask aspacem for more shadow
261 memory as a result of the VG_TRACK call. In such a situation it is
262 critical that aspacem's segment array is up to date -- hence the
263 need to notify aspacem first.
265 -----------
267 Also .. take care to call VG_(discard_translations) whenever
268 memory with execute permissions is unmapped.
272 /* ---------------------------------------------------------------------
273 Do potentially blocking syscall for the client, and mess with
274 signal masks at the same time.
275 ------------------------------------------------------------------ */
277 /* Perform a syscall on behalf of a client thread, using a specific
278 signal mask. On completion, the signal mask is set to restore_mask
279 (which presumably blocks almost everything). If a signal happens
280 during the syscall, the handler should call
281 VG_(fixup_guest_state_after_syscall_interrupted) to adjust the
282 thread's context to do the right thing.
284 The _WRK function is handwritten assembly, implemented per-platform
285 in coregrind/m_syswrap/syscall-$PLAT.S. It has some very magic
286 properties. See comments at the top of
287 VG_(fixup_guest_state_after_syscall_interrupted) below for details.
289 This function (these functions) are required to return zero in case
290 of success (even if the syscall itself failed), and nonzero if the
291 sigprocmask-swizzling calls failed. We don't actually care about
292 the failure values from sigprocmask, although most of the assembly
293 implementations do attempt to return that, using the convention
294 0 for success, or 0x8000 | error-code for failure.
296 #if defined(VGO_linux)
297 extern
298 UWord ML_(do_syscall_for_client_WRK)( Word syscallno,
299 void* guest_state,
300 const vki_sigset_t *syscall_mask,
301 const vki_sigset_t *restore_mask,
302 Word sigsetSzB );
303 #elif defined(VGO_freebsd)
304 extern
305 UWord ML_(do_syscall_for_client_WRK)( Word syscallno,
306 void* guest_state,
307 const vki_sigset_t *syscall_mask,
308 const vki_sigset_t *restore_mask,
309 Word sigsetSzB );
310 #elif defined(VGO_darwin)
311 extern
312 UWord ML_(do_syscall_for_client_unix_WRK)( Word syscallno,
313 void* guest_state,
314 const vki_sigset_t *syscall_mask,
315 const vki_sigset_t *restore_mask,
316 Word sigsetSzB ); /* unused */
317 extern
318 UWord ML_(do_syscall_for_client_mach_WRK)( Word syscallno,
319 void* guest_state,
320 const vki_sigset_t *syscall_mask,
321 const vki_sigset_t *restore_mask,
322 Word sigsetSzB ); /* unused */
323 extern
324 UWord ML_(do_syscall_for_client_mdep_WRK)( Word syscallno,
325 void* guest_state,
326 const vki_sigset_t *syscall_mask,
327 const vki_sigset_t *restore_mask,
328 Word sigsetSzB ); /* unused */
329 #elif defined(VGO_solaris)
330 extern
331 UWord ML_(do_syscall_for_client_WRK)( Word syscallno,
332 void* guest_state,
333 const vki_sigset_t *syscall_mask,
334 const vki_sigset_t *restore_mask,
335 UChar *cflag);
336 UWord ML_(do_syscall_for_client_dret_WRK)( Word syscallno,
337 void* guest_state,
338 const vki_sigset_t *syscall_mask,
339 const vki_sigset_t *restore_mask,
340 UChar *cflag);
341 #else
342 # error "Unknown OS"
343 #endif
346 static
347 void do_syscall_for_client ( Int syscallno,
348 ThreadState* tst,
349 const vki_sigset_t* syscall_mask )
351 vki_sigset_t saved;
352 UWord err;
353 # if defined(VGO_freebsd)
354 Int real_syscallno;
355 # endif
356 # if defined(VGO_linux)
357 err = ML_(do_syscall_for_client_WRK)(
358 syscallno, &tst->arch.vex,
359 syscall_mask, &saved, sizeof(vki_sigset_t)
361 # elif defined(VGO_freebsd)
362 if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL0)
363 real_syscallno = __NR_syscall;
364 else if (tst->arch.vex.guest_SC_CLASS == VG_FREEBSD_SYSCALL198)
365 real_syscallno = __NR___syscall;
366 else
367 real_syscallno = syscallno;
368 err = ML_(do_syscall_for_client_WRK)(
369 real_syscallno, &tst->arch.vex,
370 syscall_mask, &saved, sizeof(vki_sigset_t)
372 # elif defined(VGO_darwin)
373 switch (VG_DARWIN_SYSNO_CLASS(syscallno)) {
374 case VG_DARWIN_SYSCALL_CLASS_UNIX:
375 err = ML_(do_syscall_for_client_unix_WRK)(
376 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
377 syscall_mask, &saved, 0/*unused:sigsetSzB*/
379 break;
380 case VG_DARWIN_SYSCALL_CLASS_MACH:
381 err = ML_(do_syscall_for_client_mach_WRK)(
382 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
383 syscall_mask, &saved, 0/*unused:sigsetSzB*/
385 break;
386 case VG_DARWIN_SYSCALL_CLASS_MDEP:
387 err = ML_(do_syscall_for_client_mdep_WRK)(
388 VG_DARWIN_SYSNO_FOR_KERNEL(syscallno), &tst->arch.vex,
389 syscall_mask, &saved, 0/*unused:sigsetSzB*/
391 break;
392 default:
393 vg_assert(0);
394 /*NOTREACHED*/
395 break;
397 # elif defined(VGO_solaris)
398 UChar cflag;
400 /* Fasttraps or anything else cannot go through this path. */
401 vg_assert(VG_SOLARIS_SYSNO_CLASS(syscallno)
402 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
404 /* If the syscall is a door_return call then it has to be handled very
405 differently. */
406 if (tst->os_state.in_door_return)
407 err = ML_(do_syscall_for_client_dret_WRK)(
408 syscallno, &tst->arch.vex,
409 syscall_mask, &saved, &cflag
411 else
412 err = ML_(do_syscall_for_client_WRK)(
413 syscallno, &tst->arch.vex,
414 syscall_mask, &saved, &cflag
417 /* Save the carry flag. */
418 # if defined(VGP_x86_solaris)
419 LibVEX_GuestX86_put_eflag_c(cflag, &tst->arch.vex);
420 # elif defined(VGP_amd64_solaris)
421 LibVEX_GuestAMD64_put_rflag_c(cflag, &tst->arch.vex);
422 # else
423 # error "Unknown platform"
424 # endif
426 # else
427 # error "Unknown OS"
428 # endif
429 vg_assert2(
430 err == 0,
431 "ML_(do_syscall_for_client_WRK): sigprocmask error %lu",
432 err & 0xFFF
437 /* ---------------------------------------------------------------------
438 Impedance matchers and misc helpers
439 ------------------------------------------------------------------ */
441 static
442 Bool eq_SyscallArgs ( SyscallArgs* a1, SyscallArgs* a2 )
444 return a1->sysno == a2->sysno
445 && a1->arg1 == a2->arg1
446 && a1->arg2 == a2->arg2
447 && a1->arg3 == a2->arg3
448 && a1->arg4 == a2->arg4
449 && a1->arg5 == a2->arg5
450 && a1->arg6 == a2->arg6
451 && a1->arg7 == a2->arg7
452 && a1->arg8 == a2->arg8;
455 static
456 Bool eq_SyscallStatus ( UInt sysno, SyscallStatus* s1, SyscallStatus* s2 )
458 /* was: return s1->what == s2->what && sr_EQ( s1->sres, s2->sres ); */
459 if (s1->what == s2->what && sr_EQ( sysno, s1->sres, s2->sres ))
460 return True;
461 # if defined(VGO_darwin)
462 /* Darwin-specific debugging guff */
463 vg_assert(s1->what == s2->what);
464 VG_(printf)("eq_SyscallStatus:\n");
465 VG_(printf)(" {%lu %lu %u}\n", s1->sres._wLO, s1->sres._wHI, s1->sres._mode);
466 VG_(printf)(" {%lu %lu %u}\n", s2->sres._wLO, s2->sres._wHI, s2->sres._mode);
467 vg_assert(0);
468 # endif
469 return False;
472 /* Convert between SysRes and SyscallStatus, to the extent possible. */
474 static
475 SyscallStatus convert_SysRes_to_SyscallStatus ( SysRes res )
477 SyscallStatus status;
478 status.what = SsComplete;
479 status.sres = res;
480 return status;
484 /* Impedance matchers. These convert syscall arg or result data from
485 the platform-specific in-guest-state format to the canonical
486 formats, and back. */
488 static
489 void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical,
490 /*IN*/ VexGuestArchState* gst_vanilla,
491 /*IN*/ UInt trc )
493 #if defined(VGP_x86_linux)
494 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
495 canonical->sysno = gst->guest_EAX;
496 canonical->arg1 = gst->guest_EBX;
497 canonical->arg2 = gst->guest_ECX;
498 canonical->arg3 = gst->guest_EDX;
499 canonical->arg4 = gst->guest_ESI;
500 canonical->arg5 = gst->guest_EDI;
501 canonical->arg6 = gst->guest_EBP;
502 canonical->arg7 = 0;
503 canonical->arg8 = 0;
505 #elif defined(VGP_amd64_linux)
506 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
507 canonical->sysno = gst->guest_RAX;
508 canonical->arg1 = gst->guest_RDI;
509 canonical->arg2 = gst->guest_RSI;
510 canonical->arg3 = gst->guest_RDX;
511 canonical->arg4 = gst->guest_R10;
512 canonical->arg5 = gst->guest_R8;
513 canonical->arg6 = gst->guest_R9;
514 canonical->arg7 = 0;
515 canonical->arg8 = 0;
517 #elif defined(VGP_ppc32_linux)
518 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
519 canonical->sysno = gst->guest_GPR0;
520 canonical->arg1 = gst->guest_GPR3;
521 canonical->arg2 = gst->guest_GPR4;
522 canonical->arg3 = gst->guest_GPR5;
523 canonical->arg4 = gst->guest_GPR6;
524 canonical->arg5 = gst->guest_GPR7;
525 canonical->arg6 = gst->guest_GPR8;
526 canonical->arg7 = 0;
527 canonical->arg8 = 0;
529 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
530 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
531 canonical->sysno = gst->guest_GPR0;
532 canonical->arg1 = gst->guest_GPR3;
533 canonical->arg2 = gst->guest_GPR4;
534 canonical->arg3 = gst->guest_GPR5;
535 canonical->arg4 = gst->guest_GPR6;
536 canonical->arg5 = gst->guest_GPR7;
537 canonical->arg6 = gst->guest_GPR8;
538 /* ISA 3.0 adds the scv system call instruction.
539 The PPC syscalls have at most 6 args. Arg 7 is being used to pass a
540 flag to indicate which system call instruction is to be used.
541 Arg7 = SC_FLAG for the sc instruction; Arg7 = SCV_FLAG for the scv
542 instruction. The guest register guest_syscall_flag was created to pass
543 the flag so the actual guest state would not be changed. */
544 canonical->arg7 = gst->guest_syscall_flag;
545 canonical->arg8 = 0;
547 #if defined(VGP_ppc64be_linux)
548 /* The sc instruction is currently only supported on LE systems. */
549 vg_assert(gst->guest_syscall_flag == SC_FLAG);
550 #endif
552 #elif defined(VGP_x86_freebsd)
553 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
554 UWord *stack = (UWord *)gst->guest_ESP;
556 // FreeBSD supports different calling conventions
557 switch (gst->guest_EAX) {
558 case __NR_syscall:
559 canonical->klass = VG_FREEBSD_SYSCALL0;
560 canonical->sysno = stack[1];
561 stack += 1;
562 break;
563 case __NR___syscall:
564 canonical->klass = VG_FREEBSD_SYSCALL198;
565 canonical->sysno = stack[1];
566 stack += 2;
567 break;
568 default:
569 canonical->klass = 0;
570 canonical->sysno = gst->guest_EAX;
571 break;
573 // stack[0] is a (fake) return address
574 canonical->arg1 = stack[1];
575 canonical->arg2 = stack[2];
576 canonical->arg3 = stack[3];
577 canonical->arg4 = stack[4];
578 canonical->arg5 = stack[5];
579 canonical->arg6 = stack[6];
580 canonical->arg7 = stack[7];
581 canonical->arg8 = stack[8];
583 #elif defined(VGP_amd64_freebsd)
584 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
585 UWord *stack = (UWord *)gst->guest_RSP;
587 // FreeBSD supports different calling conventions
588 // @todo PJF this all seems over complicated to me
589 // SYSCALL_STD is OK but for the other
590 // two here we overwrite canonical->sysno with
591 // the final syscall number but then in do_syscall_for_client
592 // we switch real_syscallno back to __NR_syscall or __NR___syscall
593 switch (gst->guest_RAX) {
594 case __NR_syscall:
595 canonical->klass = VG_FREEBSD_SYSCALL0;
596 canonical->sysno = gst->guest_RDI;
597 break;
598 case __NR___syscall:
599 canonical->klass = VG_FREEBSD_SYSCALL198;
600 canonical->sysno = gst->guest_RDI;
601 break;
602 default:
603 canonical->klass = VG_FREEBSD_SYSCALL_STD;
604 canonical->sysno = gst->guest_RAX;
605 break;
608 // stack[0] is a (fake) return address
609 if (canonical->klass == VG_FREEBSD_SYSCALL0 || canonical->klass == VG_FREEBSD_SYSCALL198) {
610 // stack[0] is return address
611 canonical->arg1 = gst->guest_RSI;
612 canonical->arg2 = gst->guest_RDX;
613 canonical->arg3 = gst->guest_R10;
614 canonical->arg4 = gst->guest_R8;
615 canonical->arg5 = gst->guest_R9;
616 canonical->arg6 = stack[1];
617 canonical->arg7 = stack[2];
618 canonical->arg8 = stack[3];
619 } else {
620 // stack[0] is return address
621 canonical->arg1 = gst->guest_RDI;
622 canonical->arg2 = gst->guest_RSI;
623 canonical->arg3 = gst->guest_RDX;
624 canonical->arg4 = gst->guest_R10;
625 canonical->arg5 = gst->guest_R8;
626 canonical->arg6 = gst->guest_R9;
627 canonical->arg7 = stack[1];
628 canonical->arg8 = stack[2];
631 #elif defined(VGP_arm_linux)
632 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
633 canonical->sysno = gst->guest_R7;
634 canonical->arg1 = gst->guest_R0;
635 canonical->arg2 = gst->guest_R1;
636 canonical->arg3 = gst->guest_R2;
637 canonical->arg4 = gst->guest_R3;
638 canonical->arg5 = gst->guest_R4;
639 canonical->arg6 = gst->guest_R5;
640 canonical->arg7 = 0;
641 canonical->arg8 = 0;
643 #elif defined(VGP_arm64_linux)
644 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
645 canonical->sysno = gst->guest_X8;
646 canonical->arg1 = gst->guest_X0;
647 canonical->arg2 = gst->guest_X1;
648 canonical->arg3 = gst->guest_X2;
649 canonical->arg4 = gst->guest_X3;
650 canonical->arg5 = gst->guest_X4;
651 canonical->arg6 = gst->guest_X5;
652 canonical->arg7 = 0;
653 canonical->arg8 = 0;
655 #elif defined(VGP_mips32_linux)
656 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
657 canonical->sysno = gst->guest_r2; // v0
658 if (canonical->sysno == __NR_exit) {
659 canonical->arg1 = gst->guest_r4; // a0
660 canonical->arg2 = 0;
661 canonical->arg3 = 0;
662 canonical->arg4 = 0;
663 canonical->arg5 = 0;
664 canonical->arg6 = 0;
665 canonical->arg8 = 0;
666 } else if (canonical->sysno != __NR_syscall) {
667 canonical->arg1 = gst->guest_r4; // a0
668 canonical->arg2 = gst->guest_r5; // a1
669 canonical->arg3 = gst->guest_r6; // a2
670 canonical->arg4 = gst->guest_r7; // a3
671 canonical->arg5 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP)
672 canonical->arg6 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP)
673 canonical->arg7 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP)
674 canonical->arg8 = 0;
675 } else {
676 // Fixme hack handle syscall()
677 canonical->sysno = gst->guest_r4; // a0
678 canonical->arg1 = gst->guest_r5; // a1
679 canonical->arg2 = gst->guest_r6; // a2
680 canonical->arg3 = gst->guest_r7; // a3
681 canonical->arg4 = *((UInt*) (gst->guest_r29 + 16)); // 16(guest_SP/sp)
682 canonical->arg5 = *((UInt*) (gst->guest_r29 + 20)); // 20(guest_SP/sp)
683 canonical->arg6 = *((UInt*) (gst->guest_r29 + 24)); // 24(guest_SP/sp)
684 canonical->arg7 = *((UInt*) (gst->guest_r29 + 28)); // 28(guest_SP/sp)
685 canonical->arg8 = __NR_syscall;
688 #elif defined(VGP_mips64_linux)
689 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
690 canonical->sysno = gst->guest_r2; // v0
691 canonical->arg1 = gst->guest_r4; // a0
692 canonical->arg2 = gst->guest_r5; // a1
693 canonical->arg3 = gst->guest_r6; // a2
694 canonical->arg4 = gst->guest_r7; // a3
695 canonical->arg5 = gst->guest_r8; // a4
696 canonical->arg6 = gst->guest_r9; // a5
697 canonical->arg7 = gst->guest_r10; // a6
698 canonical->arg8 = gst->guest_r11; // a7
700 #elif defined(VGP_nanomips_linux)
701 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
702 canonical->sysno = gst->guest_r2; // t4
703 canonical->arg1 = gst->guest_r4; // a0
704 canonical->arg2 = gst->guest_r5; // a1
705 canonical->arg3 = gst->guest_r6; // a2
706 canonical->arg4 = gst->guest_r7; // a3
707 canonical->arg5 = gst->guest_r8; // a4
708 canonical->arg6 = gst->guest_r9; // a5
709 canonical->arg7 = gst->guest_r10; // a6
710 canonical->arg8 = gst->guest_r11; // a7
711 #elif defined(VGP_x86_darwin)
712 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
713 UWord *stack = (UWord *)gst->guest_ESP;
714 // GrP fixme hope syscalls aren't called with really shallow stacks...
715 canonical->sysno = gst->guest_EAX;
716 if (canonical->sysno != 0) {
717 // stack[0] is return address
718 canonical->arg1 = stack[1];
719 canonical->arg2 = stack[2];
720 canonical->arg3 = stack[3];
721 canonical->arg4 = stack[4];
722 canonical->arg5 = stack[5];
723 canonical->arg6 = stack[6];
724 canonical->arg7 = stack[7];
725 canonical->arg8 = stack[8];
726 } else {
727 // GrP fixme hack handle syscall()
728 // GrP fixme what about __syscall() ?
729 // stack[0] is return address
730 // DDD: the tool can't see that the params have been shifted! Can
731 // lead to incorrect checking, I think, because the PRRAn/PSARn
732 // macros will mention the pre-shifted args.
733 canonical->sysno = stack[1];
734 vg_assert(canonical->sysno != 0);
735 canonical->arg1 = stack[2];
736 canonical->arg2 = stack[3];
737 canonical->arg3 = stack[4];
738 canonical->arg4 = stack[5];
739 canonical->arg5 = stack[6];
740 canonical->arg6 = stack[7];
741 canonical->arg7 = stack[8];
742 canonical->arg8 = stack[9];
744 PRINT("SYSCALL[%d,?](0) syscall(%s, ...); please stand by...\n",
745 VG_(getpid)(), /*tid,*/
746 VG_SYSNUM_STRING(canonical->sysno));
749 // Here we determine what kind of syscall it was by looking at the
750 // interrupt kind, and then encode the syscall number using the 64-bit
751 // encoding for Valgrind's internal use.
753 // DDD: Would it be better to stash the JMP kind into the Darwin
754 // thread state rather than passing in the trc?
755 switch (trc) {
756 case VEX_TRC_JMP_SYS_INT128:
757 // int $0x80 = Unix, 64-bit result
758 vg_assert(canonical->sysno >= 0);
759 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno);
760 break;
761 case VEX_TRC_JMP_SYS_SYSENTER:
762 // syscall = Unix, 32-bit result
763 // OR Mach, 32-bit result
764 if (canonical->sysno >= 0) {
765 // GrP fixme hack: 0xffff == I386_SYSCALL_NUMBER_MASK
766 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(canonical->sysno
767 & 0xffff);
768 } else {
769 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno);
771 break;
772 case VEX_TRC_JMP_SYS_INT129:
773 // int $0x81 = Mach, 32-bit result
774 vg_assert(canonical->sysno < 0);
775 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MACH(-canonical->sysno);
776 break;
777 case VEX_TRC_JMP_SYS_INT130:
778 // int $0x82 = mdep, 32-bit result
779 vg_assert(canonical->sysno >= 0);
780 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_MDEP(canonical->sysno);
781 break;
782 default:
783 vg_assert(0);
784 break;
787 #elif defined(VGP_amd64_darwin)
788 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
789 UWord *stack = (UWord *)gst->guest_RSP;
791 vg_assert(trc == VEX_TRC_JMP_SYS_SYSCALL);
793 // GrP fixme hope syscalls aren't called with really shallow stacks...
794 canonical->sysno = gst->guest_RAX;
795 if (canonical->sysno != __NR_syscall) {
796 // stack[0] is return address
797 canonical->arg1 = gst->guest_RDI;
798 canonical->arg2 = gst->guest_RSI;
799 canonical->arg3 = gst->guest_RDX;
800 canonical->arg4 = gst->guest_R10; // not rcx with syscall insn
801 canonical->arg5 = gst->guest_R8;
802 canonical->arg6 = gst->guest_R9;
803 canonical->arg7 = stack[1];
804 canonical->arg8 = stack[2];
805 } else {
806 // GrP fixme hack handle syscall()
807 // GrP fixme what about __syscall() ?
808 // stack[0] is return address
809 // DDD: the tool can't see that the params have been shifted! Can
810 // lead to incorrect checking, I think, because the PRRAn/PSARn
811 // macros will mention the pre-shifted args.
812 canonical->sysno = VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(gst->guest_RDI);
813 vg_assert(canonical->sysno != __NR_syscall);
814 canonical->arg1 = gst->guest_RSI;
815 canonical->arg2 = gst->guest_RDX;
816 canonical->arg3 = gst->guest_R10; // not rcx with syscall insn
817 canonical->arg4 = gst->guest_R8;
818 canonical->arg5 = gst->guest_R9;
819 canonical->arg6 = stack[1];
820 canonical->arg7 = stack[2];
821 canonical->arg8 = stack[3];
823 PRINT("SYSCALL[%d,?](0) syscall(%s, ...); please stand by...\n",
824 VG_(getpid)(), /*tid,*/
825 VG_SYSNUM_STRING(canonical->sysno));
828 // no canonical->sysno adjustment needed
830 #elif defined(VGP_s390x_linux)
831 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
832 canonical->sysno = gst->guest_SYSNO;
833 canonical->arg1 = gst->guest_r2;
834 canonical->arg2 = gst->guest_r3;
835 canonical->arg3 = gst->guest_r4;
836 canonical->arg4 = gst->guest_r5;
837 canonical->arg5 = gst->guest_r6;
838 canonical->arg6 = gst->guest_r7;
839 canonical->arg7 = 0;
840 canonical->arg8 = 0;
842 #elif defined(VGP_x86_solaris)
843 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
844 UWord *stack = (UWord *)gst->guest_ESP;
845 canonical->sysno = gst->guest_EAX;
846 /* stack[0] is a return address. */
847 canonical->arg1 = stack[1];
848 canonical->arg2 = stack[2];
849 canonical->arg3 = stack[3];
850 canonical->arg4 = stack[4];
851 canonical->arg5 = stack[5];
852 canonical->arg6 = stack[6];
853 canonical->arg7 = stack[7];
854 canonical->arg8 = stack[8];
856 switch (trc) {
857 case VEX_TRC_JMP_SYS_INT145:
858 case VEX_TRC_JMP_SYS_SYSENTER:
859 case VEX_TRC_JMP_SYS_SYSCALL:
860 /* These three are not actually valid syscall instructions on Solaris.
861 Pretend for now that we handle them as normal syscalls. */
862 case VEX_TRC_JMP_SYS_INT128:
863 case VEX_TRC_JMP_SYS_INT129:
864 case VEX_TRC_JMP_SYS_INT130:
865 /* int $0x91, sysenter, syscall = normal syscall */
866 break;
867 case VEX_TRC_JMP_SYS_INT210:
868 /* int $0xD2 = fasttrap */
869 canonical->sysno
870 = VG_SOLARIS_SYSCALL_CONSTRUCT_FASTTRAP(canonical->sysno);
871 break;
872 default:
873 vg_assert(0);
874 break;
877 #elif defined(VGP_amd64_solaris)
878 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
879 UWord *stack = (UWord *)gst->guest_RSP;
880 canonical->sysno = gst->guest_RAX;
881 /* stack[0] is a return address. */
882 canonical->arg1 = gst->guest_RDI;
883 canonical->arg2 = gst->guest_RSI;
884 canonical->arg3 = gst->guest_RDX;
885 canonical->arg4 = gst->guest_R10; /* Not RCX with syscall. */
886 canonical->arg5 = gst->guest_R8;
887 canonical->arg6 = gst->guest_R9;
888 canonical->arg7 = stack[1];
889 canonical->arg8 = stack[2];
891 switch (trc) {
892 case VEX_TRC_JMP_SYS_SYSCALL:
893 /* syscall = normal syscall */
894 break;
895 case VEX_TRC_JMP_SYS_INT210:
896 /* int $0xD2 = fasttrap */
897 canonical->sysno
898 = VG_SOLARIS_SYSCALL_CONSTRUCT_FASTTRAP(canonical->sysno);
899 break;
900 default:
901 vg_assert(0);
902 break;
905 #else
906 # error "getSyscallArgsFromGuestState: unknown arch"
907 #endif
910 static
911 void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical,
912 /*OUT*/VexGuestArchState* gst_vanilla )
914 #if defined(VGP_x86_linux)
915 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
916 gst->guest_EAX = canonical->sysno;
917 gst->guest_EBX = canonical->arg1;
918 gst->guest_ECX = canonical->arg2;
919 gst->guest_EDX = canonical->arg3;
920 gst->guest_ESI = canonical->arg4;
921 gst->guest_EDI = canonical->arg5;
922 gst->guest_EBP = canonical->arg6;
924 #elif defined(VGP_amd64_linux)
925 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
926 gst->guest_RAX = canonical->sysno;
927 gst->guest_RDI = canonical->arg1;
928 gst->guest_RSI = canonical->arg2;
929 gst->guest_RDX = canonical->arg3;
930 gst->guest_R10 = canonical->arg4;
931 gst->guest_R8 = canonical->arg5;
932 gst->guest_R9 = canonical->arg6;
934 #elif defined(VGP_ppc32_linux)
935 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
936 gst->guest_GPR0 = canonical->sysno;
937 gst->guest_GPR3 = canonical->arg1;
938 gst->guest_GPR4 = canonical->arg2;
939 gst->guest_GPR5 = canonical->arg3;
940 gst->guest_GPR6 = canonical->arg4;
941 gst->guest_GPR7 = canonical->arg5;
942 gst->guest_GPR8 = canonical->arg6;
944 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
945 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
946 gst->guest_GPR0 = canonical->sysno;
947 gst->guest_GPR3 = canonical->arg1;
948 gst->guest_GPR4 = canonical->arg2;
949 gst->guest_GPR5 = canonical->arg3;
950 gst->guest_GPR6 = canonical->arg4;
951 gst->guest_GPR7 = canonical->arg5;
952 gst->guest_GPR8 = canonical->arg6;
953 gst->guest_GPR9 = canonical->arg7;
955 #elif defined(VGP_x86_freebsd)
956 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
957 UWord *stack = (UWord *)gst->guest_ESP;
959 // stack[0] is a (fake) return address
960 switch (canonical->klass) {
961 case VG_FREEBSD_SYSCALL0:
962 gst->guest_EAX = __NR_syscall;
963 stack[1] = canonical->sysno;
964 stack++;
965 break;
966 case VG_FREEBSD_SYSCALL198:
967 gst->guest_EAX = __NR___syscall;
968 stack[1] = canonical->sysno;
969 stack += 2;
970 break;
971 default:
972 gst->guest_EAX = canonical->sysno;
973 break;
976 stack[1] = canonical->arg1;
977 stack[2] = canonical->arg2;
978 stack[3] = canonical->arg3;
979 stack[4] = canonical->arg4;
980 stack[5] = canonical->arg5;
981 stack[6] = canonical->arg6;
982 stack[7] = canonical->arg7;
983 stack[8] = canonical->arg8;
985 #elif defined(VGP_amd64_freebsd)
986 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
987 UWord *stack = (UWord *)gst->guest_RSP;
989 // stack[0] is a (fake) return address
990 switch (canonical->klass) {
991 case VG_FREEBSD_SYSCALL0:
992 gst->guest_RAX = __NR_syscall;
993 break;
994 case VG_FREEBSD_SYSCALL198:
995 gst->guest_RAX = __NR___syscall;
996 break;
997 default:
998 gst->guest_RAX = canonical->sysno;
999 break;
1002 if (canonical->klass == VG_FREEBSD_SYSCALL0 || canonical->klass == VG_FREEBSD_SYSCALL198) {
1003 gst->guest_RDI = canonical->sysno;
1004 gst->guest_RSI = canonical->arg1;
1005 gst->guest_RDX = canonical->arg2;
1006 gst->guest_R10 = canonical->arg3;
1007 gst->guest_R8 = canonical->arg4;
1008 gst->guest_R9 = canonical->arg5;
1009 stack[1] = canonical->arg6;
1010 stack[2] = canonical->arg7;
1011 stack[3] = canonical->arg8;
1012 } else {
1013 gst->guest_RDI = canonical->arg1;
1014 gst->guest_RSI = canonical->arg2;
1015 gst->guest_RDX = canonical->arg3;
1016 gst->guest_R10 = canonical->arg4;
1017 gst->guest_R8 = canonical->arg5;
1018 gst->guest_R9 = canonical->arg6;
1019 stack[1] = canonical->arg7;
1020 stack[2] = canonical->arg8;
1023 #elif defined(VGP_arm_linux)
1024 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
1025 gst->guest_R7 = canonical->sysno;
1026 gst->guest_R0 = canonical->arg1;
1027 gst->guest_R1 = canonical->arg2;
1028 gst->guest_R2 = canonical->arg3;
1029 gst->guest_R3 = canonical->arg4;
1030 gst->guest_R4 = canonical->arg5;
1031 gst->guest_R5 = canonical->arg6;
1033 #elif defined(VGP_arm64_linux)
1034 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
1035 gst->guest_X8 = canonical->sysno;
1036 gst->guest_X0 = canonical->arg1;
1037 gst->guest_X1 = canonical->arg2;
1038 gst->guest_X2 = canonical->arg3;
1039 gst->guest_X3 = canonical->arg4;
1040 gst->guest_X4 = canonical->arg5;
1041 gst->guest_X5 = canonical->arg6;
1043 #elif defined(VGP_x86_darwin)
1044 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1045 UWord *stack = (UWord *)gst->guest_ESP;
1047 gst->guest_EAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno);
1049 // GrP fixme? gst->guest_TEMP_EFLAG_C = 0;
1050 // stack[0] is return address
1051 stack[1] = canonical->arg1;
1052 stack[2] = canonical->arg2;
1053 stack[3] = canonical->arg3;
1054 stack[4] = canonical->arg4;
1055 stack[5] = canonical->arg5;
1056 stack[6] = canonical->arg6;
1057 stack[7] = canonical->arg7;
1058 stack[8] = canonical->arg8;
1060 #elif defined(VGP_amd64_darwin)
1061 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1062 UWord *stack = (UWord *)gst->guest_RSP;
1064 gst->guest_RAX = VG_DARWIN_SYSNO_FOR_KERNEL(canonical->sysno);
1065 // GrP fixme? gst->guest_TEMP_EFLAG_C = 0;
1067 // stack[0] is return address
1068 gst->guest_RDI = canonical->arg1;
1069 gst->guest_RSI = canonical->arg2;
1070 gst->guest_RDX = canonical->arg3;
1071 gst->guest_RCX = canonical->arg4;
1072 gst->guest_R8 = canonical->arg5;
1073 gst->guest_R9 = canonical->arg6;
1074 stack[1] = canonical->arg7;
1075 stack[2] = canonical->arg8;
1077 #elif defined(VGP_s390x_linux)
1078 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
1079 gst->guest_SYSNO = canonical->sysno;
1080 gst->guest_r2 = canonical->arg1;
1081 gst->guest_r3 = canonical->arg2;
1082 gst->guest_r4 = canonical->arg3;
1083 gst->guest_r5 = canonical->arg4;
1084 gst->guest_r6 = canonical->arg5;
1085 gst->guest_r7 = canonical->arg6;
1087 #elif defined(VGP_mips32_linux)
1088 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1089 if (canonical->arg8 != __NR_syscall) {
1090 gst->guest_r2 = canonical->sysno;
1091 gst->guest_r4 = canonical->arg1;
1092 gst->guest_r5 = canonical->arg2;
1093 gst->guest_r6 = canonical->arg3;
1094 gst->guest_r7 = canonical->arg4;
1095 *((UInt*) (gst->guest_r29 + 16)) = canonical->arg5; // 16(guest_GPR29/sp)
1096 *((UInt*) (gst->guest_r29 + 20)) = canonical->arg6; // 20(sp)
1097 *((UInt*) (gst->guest_r29 + 24)) = canonical->arg7; // 24(sp)
1098 } else {
1099 canonical->arg8 = 0;
1100 gst->guest_r2 = __NR_syscall;
1101 gst->guest_r4 = canonical->sysno;
1102 gst->guest_r5 = canonical->arg1;
1103 gst->guest_r6 = canonical->arg2;
1104 gst->guest_r7 = canonical->arg3;
1105 *((UInt*) (gst->guest_r29 + 16)) = canonical->arg4; // 16(guest_GPR29/sp)
1106 *((UInt*) (gst->guest_r29 + 20)) = canonical->arg5; // 20(sp)
1107 *((UInt*) (gst->guest_r29 + 24)) = canonical->arg6; // 24(sp)
1108 *((UInt*) (gst->guest_r29 + 28)) = canonical->arg7; // 28(sp)
1111 #elif defined(VGP_nanomips_linux)
1112 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1113 gst->guest_r2 = canonical->sysno;
1114 gst->guest_r4 = canonical->arg1;
1115 gst->guest_r5 = canonical->arg2;
1116 gst->guest_r6 = canonical->arg3;
1117 gst->guest_r7 = canonical->arg4;
1118 gst->guest_r8 = canonical->arg5;
1119 gst->guest_r9 = canonical->arg6;
1120 gst->guest_r10 = canonical->arg7;
1121 gst->guest_r11 = canonical->arg8;
1122 #elif defined(VGP_mips64_linux)
1123 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
1124 gst->guest_r2 = canonical->sysno;
1125 gst->guest_r4 = canonical->arg1;
1126 gst->guest_r5 = canonical->arg2;
1127 gst->guest_r6 = canonical->arg3;
1128 gst->guest_r7 = canonical->arg4;
1129 gst->guest_r8 = canonical->arg5;
1130 gst->guest_r9 = canonical->arg6;
1131 gst->guest_r10 = canonical->arg7;
1132 gst->guest_r11 = canonical->arg8;
1134 #elif defined(VGP_x86_solaris)
1135 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1136 UWord *stack = (UWord *)gst->guest_ESP;
1138 /* Fasttraps or anything else cannot go through this way. */
1139 vg_assert(VG_SOLARIS_SYSNO_CLASS(canonical->sysno)
1140 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
1141 gst->guest_EAX = canonical->sysno;
1142 /* stack[0] is a return address. */
1143 stack[1] = canonical->arg1;
1144 stack[2] = canonical->arg2;
1145 stack[3] = canonical->arg3;
1146 stack[4] = canonical->arg4;
1147 stack[5] = canonical->arg5;
1148 stack[6] = canonical->arg6;
1149 stack[7] = canonical->arg7;
1150 stack[8] = canonical->arg8;
1152 #elif defined(VGP_amd64_solaris)
1153 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1154 UWord *stack = (UWord *)gst->guest_RSP;
1156 /* Fasttraps or anything else cannot go through this way. */
1157 vg_assert(VG_SOLARIS_SYSNO_CLASS(canonical->sysno)
1158 == VG_SOLARIS_SYSCALL_CLASS_CLASSIC);
1159 gst->guest_RAX = canonical->sysno;
1160 /* stack[0] is a return address. */
1161 gst->guest_RDI = canonical->arg1;
1162 gst->guest_RSI = canonical->arg2;
1163 gst->guest_RDX = canonical->arg3;
1164 gst->guest_R10 = canonical->arg4;
1165 gst->guest_R8 = canonical->arg5;
1166 gst->guest_R9 = canonical->arg6;
1167 stack[1] = canonical->arg7;
1168 stack[2] = canonical->arg8;
1170 #else
1171 # error "putSyscallArgsIntoGuestState: unknown arch"
1172 #endif
1175 static
1176 void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical,
1177 /*IN*/ VexGuestArchState* gst_vanilla )
1179 # if defined(VGP_x86_linux)
1180 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1181 canonical->sres = VG_(mk_SysRes_x86_linux)( gst->guest_EAX );
1182 canonical->what = SsComplete;
1184 # elif defined(VGP_amd64_linux)
1185 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1186 canonical->sres = VG_(mk_SysRes_amd64_linux)( gst->guest_RAX );
1187 canonical->what = SsComplete;
1189 # elif defined(VGP_ppc32_linux)
1190 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
1191 UInt cr = LibVEX_GuestPPC32_get_CR( gst );
1192 UInt cr0so = (cr >> 28) & 1;
1193 canonical->sres = VG_(mk_SysRes_ppc32_linux)( gst->guest_GPR3, cr0so );
1194 canonical->what = SsComplete;
1196 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1197 /* There is a Valgrind specific guest state register guest_syscall_flag
1198 that is set to zero to indicate if the sc instruction was used or one
1199 if the scv instruction was used for the system call. */
1200 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
1201 UInt cr = LibVEX_GuestPPC64_get_CR( gst );
1202 UInt cr0so = (cr >> 28) & 1;
1203 UInt flag = gst->guest_syscall_flag;
1205 canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so, flag );
1206 canonical->what = SsComplete;
1208 # elif defined(VGP_x86_freebsd)
1209 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1210 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1211 UInt flags = LibVEX_GuestX86_get_eflags(gst);
1213 canonical->sres = VG_(mk_SysRes_x86_freebsd)(gst->guest_EAX, gst->guest_EDX,
1214 (flags & 1) != 0 ? True : False);
1215 canonical->what = SsComplete;
1217 # elif defined(VGP_arm_linux)
1218 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
1219 canonical->sres = VG_(mk_SysRes_arm_linux)( gst->guest_R0 );
1220 canonical->what = SsComplete;
1222 # elif defined(VGP_arm64_linux)
1223 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
1224 canonical->sres = VG_(mk_SysRes_arm64_linux)( gst->guest_X0 );
1225 canonical->what = SsComplete;
1227 # elif defined(VGP_mips32_linux)
1228 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1229 UInt v0 = gst->guest_r2; // v0
1230 UInt v1 = gst->guest_r3; // v1
1231 UInt a3 = gst->guest_r7; // a3
1232 canonical->sres = VG_(mk_SysRes_mips32_linux)( v0, v1, a3 );
1233 canonical->what = SsComplete;
1235 # elif defined(VGP_mips64_linux)
1236 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
1237 ULong v0 = gst->guest_r2; // v0
1238 ULong v1 = gst->guest_r3; // v1
1239 ULong a3 = gst->guest_r7; // a3
1240 canonical->sres = VG_(mk_SysRes_mips64_linux)(v0, v1, a3);
1241 canonical->what = SsComplete;
1243 # elif defined(VGP_nanomips_linux)
1244 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1245 RegWord a0 = gst->guest_r4; // a0
1246 canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0);
1247 canonical->what = SsComplete;
1248 # elif defined(VGP_amd64_freebsd)
1249 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1250 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1251 ULong flags = LibVEX_GuestAMD64_get_rflags(gst);
1252 canonical->sres = VG_(mk_SysRes_amd64_freebsd)(gst->guest_RAX, gst->guest_RDX,
1253 (flags & 1) != 0 ? True : False);
1254 canonical->what = SsComplete;
1256 # elif defined(VGP_x86_darwin)
1257 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1258 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1259 UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst);
1260 UInt err = 0;
1261 UInt wLO = 0;
1262 UInt wHI = 0;
1263 switch (gst->guest_SC_CLASS) {
1264 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1265 // int $0x80 = Unix, 64-bit result
1266 err = carry;
1267 wLO = gst->guest_EAX;
1268 wHI = gst->guest_EDX;
1269 break;
1270 case VG_DARWIN_SYSCALL_CLASS_MACH:
1271 // int $0x81 = Mach, 32-bit result
1272 wLO = gst->guest_EAX;
1273 break;
1274 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1275 // int $0x82 = mdep, 32-bit result
1276 wLO = gst->guest_EAX;
1277 break;
1278 default:
1279 vg_assert(0);
1280 break;
1282 canonical->sres = VG_(mk_SysRes_x86_darwin)(
1283 gst->guest_SC_CLASS, err ? True : False,
1284 wHI, wLO
1286 canonical->what = SsComplete;
1288 # elif defined(VGP_amd64_darwin)
1289 /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
1290 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1291 ULong carry = 1 & LibVEX_GuestAMD64_get_rflags(gst);
1292 ULong err = 0;
1293 ULong wLO = 0;
1294 ULong wHI = 0;
1295 switch (gst->guest_SC_CLASS) {
1296 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1297 // syscall = Unix, 128-bit result
1298 err = carry;
1299 wLO = gst->guest_RAX;
1300 wHI = gst->guest_RDX;
1301 break;
1302 case VG_DARWIN_SYSCALL_CLASS_MACH:
1303 // syscall = Mach, 64-bit result
1304 wLO = gst->guest_RAX;
1305 break;
1306 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1307 // syscall = mdep, 64-bit result
1308 wLO = gst->guest_RAX;
1309 break;
1310 default:
1311 vg_assert(0);
1312 break;
1314 canonical->sres = VG_(mk_SysRes_amd64_darwin)(
1315 gst->guest_SC_CLASS, err ? True : False,
1316 wHI, wLO
1318 canonical->what = SsComplete;
1320 # elif defined(VGP_s390x_linux)
1321 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
1322 canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 );
1323 canonical->what = SsComplete;
1325 # elif defined(VGP_x86_solaris)
1326 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1327 UInt carry = 1 & LibVEX_GuestX86_get_eflags(gst);
1329 canonical->sres = VG_(mk_SysRes_x86_solaris)(carry ? True : False,
1330 gst->guest_EAX,
1331 carry ? 0 : gst->guest_EDX);
1332 canonical->what = SsComplete;
1334 # elif defined(VGP_amd64_solaris)
1335 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1336 UInt carry = 1 & LibVEX_GuestAMD64_get_rflags(gst);
1338 canonical->sres = VG_(mk_SysRes_amd64_solaris)(carry ? True : False,
1339 gst->guest_RAX,
1340 carry ? 0 : gst->guest_RDX);
1341 canonical->what = SsComplete;
1343 # else
1344 # error "getSyscallStatusFromGuestState: unknown arch"
1345 # endif
1348 static
1349 void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
1350 /*IN*/ SyscallStatus* canonical,
1351 /*OUT*/VexGuestArchState* gst_vanilla )
1353 # if defined(VGP_x86_linux)
1354 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1355 vg_assert(canonical->what == SsComplete);
1356 if (sr_isError(canonical->sres)) {
1357 /* This isn't exactly right, in that really a Failure with res
1358 not in the range 1 .. 4095 is unrepresentable in the
1359 Linux-x86 scheme. Oh well. */
1360 gst->guest_EAX = - (Int)sr_Err(canonical->sres);
1361 } else {
1362 gst->guest_EAX = sr_Res(canonical->sres);
1364 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1365 OFFSET_x86_EAX, sizeof(UWord) );
1367 # elif defined(VGP_amd64_linux)
1368 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1369 vg_assert(canonical->what == SsComplete);
1370 if (sr_isError(canonical->sres)) {
1371 /* This isn't exactly right, in that really a Failure with res
1372 not in the range 1 .. 4095 is unrepresentable in the
1373 Linux-amd64 scheme. Oh well. */
1374 gst->guest_RAX = - (Long)sr_Err(canonical->sres);
1375 } else {
1376 gst->guest_RAX = sr_Res(canonical->sres);
1378 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1379 OFFSET_amd64_RAX, sizeof(UWord) );
1381 # elif defined(VGP_ppc32_linux)
1382 VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla;
1383 UInt old_cr = LibVEX_GuestPPC32_get_CR(gst);
1384 vg_assert(canonical->what == SsComplete);
1385 if (sr_isError(canonical->sres)) {
1386 /* set CR0.SO */
1387 LibVEX_GuestPPC32_put_CR( old_cr | (1<<28), gst );
1388 gst->guest_GPR3 = sr_Err(canonical->sres);
1389 } else {
1390 /* clear CR0.SO */
1391 LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), gst );
1392 gst->guest_GPR3 = sr_Res(canonical->sres);
1394 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1395 OFFSET_ppc32_GPR3, sizeof(UWord) );
1396 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1397 OFFSET_ppc32_CR0_0, sizeof(UChar) );
1399 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1400 VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
1401 UInt old_cr = LibVEX_GuestPPC64_get_CR(gst);
1402 UInt flag = gst->guest_syscall_flag;
1404 vg_assert(canonical->what == SsComplete);
1405 if (flag == SC_FLAG) {
1406 /* sc syscall */
1407 if (sr_isError(canonical->sres)) {
1408 /* set CR0.SO */
1409 LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst );
1410 gst->guest_GPR3 = sr_Err(canonical->sres);
1411 } else {
1412 /* clear CR0.SO */
1413 LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst );
1414 gst->guest_GPR3 = sr_Res(canonical->sres);
1416 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1417 OFFSET_ppc64_GPR3, sizeof(UWord) );
1418 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1419 OFFSET_ppc64_CR0_0, sizeof(UChar) );
1420 } else {
1421 /* scv system call instruction */
1422 if (sr_isError(canonical->sres))
1423 gst->guest_GPR3 = - (Long)canonical->sres._val;
1424 else
1425 gst->guest_GPR3 = canonical->sres._val;
1427 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1428 OFFSET_ppc64_GPR3, sizeof(UWord) );
1431 # elif defined(VGP_arm_linux)
1432 VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
1433 vg_assert(canonical->what == SsComplete);
1434 if (sr_isError(canonical->sres)) {
1435 /* This isn't exactly right, in that really a Failure with res
1436 not in the range 1 .. 4095 is unrepresentable in the
1437 Linux-arm scheme. Oh well. */
1438 gst->guest_R0 = - (Int)sr_Err(canonical->sres);
1439 } else {
1440 gst->guest_R0 = sr_Res(canonical->sres);
1442 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1443 OFFSET_arm_R0, sizeof(UWord) );
1445 # elif defined(VGP_arm64_linux)
1446 VexGuestARM64State* gst = (VexGuestARM64State*)gst_vanilla;
1447 vg_assert(canonical->what == SsComplete);
1448 if (sr_isError(canonical->sres)) {
1449 /* This isn't exactly right, in that really a Failure with res
1450 not in the range 1 .. 4095 is unrepresentable in the
1451 Linux-arm64 scheme. Oh well. */
1452 gst->guest_X0 = - (Long)sr_Err(canonical->sres);
1453 } else {
1454 gst->guest_X0 = sr_Res(canonical->sres);
1456 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1457 OFFSET_arm64_X0, sizeof(UWord) );
1459 #elif defined(VGP_x86_freebsd)
1460 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1461 vg_assert(canonical->what == SsComplete);
1462 if (sr_isError(canonical->sres)) {
1463 gst->guest_EAX = sr_Err(canonical->sres);
1464 LibVEX_GuestX86_put_eflag_c(1, gst);
1465 } else {
1466 gst->guest_EAX = sr_Res(canonical->sres);
1467 gst->guest_EDX = sr_ResHI(canonical->sres);
1468 LibVEX_GuestX86_put_eflag_c(0, gst);
1470 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1471 OFFSET_x86_EAX, sizeof(UInt) );
1472 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1473 OFFSET_x86_EDX, sizeof(UInt) );
1474 // GrP fixme sets defined for entire eflags, not just bit c
1475 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1476 offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) );
1478 #elif defined(VGP_amd64_freebsd)
1479 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1480 vg_assert(canonical->what == SsComplete);
1481 if (sr_isError(canonical->sres)) {
1482 gst->guest_RAX = sr_Err(canonical->sres);
1483 LibVEX_GuestAMD64_put_rflag_c(1, gst);
1484 } else {
1485 gst->guest_RAX = sr_Res(canonical->sres);
1486 gst->guest_RDX = sr_ResHI(canonical->sres);
1487 LibVEX_GuestAMD64_put_rflag_c(0, gst);
1489 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1490 OFFSET_amd64_RAX, sizeof(ULong) );
1491 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1492 OFFSET_amd64_RDX, sizeof(ULong) );
1493 // GrP fixme sets defined for entire eflags, not just bit c
1494 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1495 offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) );
1496 #elif defined(VGP_x86_darwin)
1497 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1498 SysRes sres = canonical->sres;
1499 vg_assert(canonical->what == SsComplete);
1500 /* Unfortunately here we have to break abstraction and look
1501 directly inside 'res', in order to decide what to do. */
1502 switch (sres._mode) {
1503 case SysRes_MACH: // int $0x81 = Mach, 32-bit result
1504 case SysRes_MDEP: // int $0x82 = mdep, 32-bit result
1505 gst->guest_EAX = sres._wLO;
1506 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1507 OFFSET_x86_EAX, sizeof(UInt) );
1508 break;
1509 case SysRes_UNIX_OK: // int $0x80 = Unix, 64-bit result
1510 case SysRes_UNIX_ERR: // int $0x80 = Unix, 64-bit error
1511 gst->guest_EAX = sres._wLO;
1512 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1513 OFFSET_x86_EAX, sizeof(UInt) );
1514 gst->guest_EDX = sres._wHI;
1515 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1516 OFFSET_x86_EDX, sizeof(UInt) );
1517 LibVEX_GuestX86_put_eflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0,
1518 gst );
1519 // GrP fixme sets defined for entire eflags, not just bit c
1520 // DDD: this breaks exp-ptrcheck.
1521 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1522 offsetof(VexGuestX86State, guest_CC_DEP1), sizeof(UInt) );
1523 break;
1524 default:
1525 vg_assert(0);
1526 break;
1529 #elif defined(VGP_amd64_darwin)
1530 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1531 SysRes sres = canonical->sres;
1532 vg_assert(canonical->what == SsComplete);
1533 /* Unfortunately here we have to break abstraction and look
1534 directly inside 'res', in order to decide what to do. */
1535 switch (sres._mode) {
1536 case SysRes_MACH: // syscall = Mach, 64-bit result
1537 case SysRes_MDEP: // syscall = mdep, 64-bit result
1538 gst->guest_RAX = sres._wLO;
1539 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1540 OFFSET_amd64_RAX, sizeof(ULong) );
1541 break;
1542 case SysRes_UNIX_OK: // syscall = Unix, 128-bit result
1543 case SysRes_UNIX_ERR: // syscall = Unix, 128-bit error
1544 gst->guest_RAX = sres._wLO;
1545 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1546 OFFSET_amd64_RAX, sizeof(ULong) );
1547 gst->guest_RDX = sres._wHI;
1548 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1549 OFFSET_amd64_RDX, sizeof(ULong) );
1550 LibVEX_GuestAMD64_put_rflag_c( sres._mode==SysRes_UNIX_ERR ? 1 : 0,
1551 gst );
1552 // GrP fixme sets defined for entire rflags, not just bit c
1553 // DDD: this breaks exp-ptrcheck.
1554 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1555 offsetof(VexGuestAMD64State, guest_CC_DEP1), sizeof(ULong) );
1556 break;
1557 default:
1558 vg_assert(0);
1559 break;
1562 # elif defined(VGP_s390x_linux)
1563 VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
1564 vg_assert(canonical->what == SsComplete);
1565 if (sr_isError(canonical->sres)) {
1566 gst->guest_r2 = - (Long)sr_Err(canonical->sres);
1567 } else {
1568 gst->guest_r2 = sr_Res(canonical->sres);
1571 # elif defined(VGP_mips32_linux)
1572 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1573 vg_assert(canonical->what == SsComplete);
1574 if (sr_isError(canonical->sres)) {
1575 gst->guest_r2 = (Int)sr_Err(canonical->sres);
1576 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1577 } else {
1578 gst->guest_r2 = sr_Res(canonical->sres);
1579 gst->guest_r3 = sr_ResEx(canonical->sres);
1580 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1582 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1583 OFFSET_mips32_r2, sizeof(UWord) );
1584 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1585 OFFSET_mips32_r3, sizeof(UWord) );
1586 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1587 OFFSET_mips32_r7, sizeof(UWord) );
1589 # elif defined(VGP_mips64_linux)
1590 VexGuestMIPS64State* gst = (VexGuestMIPS64State*)gst_vanilla;
1591 vg_assert(canonical->what == SsComplete);
1592 if (sr_isError(canonical->sres)) {
1593 gst->guest_r2 = (Int)sr_Err(canonical->sres);
1594 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1595 } else {
1596 gst->guest_r2 = sr_Res(canonical->sres);
1597 gst->guest_r3 = sr_ResEx(canonical->sres);
1598 gst->guest_r7 = (Int)sr_Err(canonical->sres);
1600 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1601 OFFSET_mips64_r2, sizeof(UWord) );
1602 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1603 OFFSET_mips64_r3, sizeof(UWord) );
1604 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1605 OFFSET_mips64_r7, sizeof(UWord) );
1607 # elif defined(VGP_nanomips_linux)
1608 VexGuestMIPS32State* gst = (VexGuestMIPS32State*)gst_vanilla;
1609 vg_assert(canonical->what == SsComplete);
1610 gst->guest_r4 = canonical->sres._val;
1611 VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
1612 OFFSET_mips32_r4, sizeof(UWord) );
1614 # elif defined(VGP_x86_solaris)
1615 VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
1616 SysRes sres = canonical->sres;
1617 vg_assert(canonical->what == SsComplete);
1619 if (sr_isError(sres)) {
1620 gst->guest_EAX = sr_Err(sres);
1621 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EAX,
1622 sizeof(UInt));
1623 LibVEX_GuestX86_put_eflag_c(1, gst);
1625 else {
1626 gst->guest_EAX = sr_Res(sres);
1627 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EAX,
1628 sizeof(UInt));
1629 gst->guest_EDX = sr_ResHI(sres);
1630 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_x86_EDX,
1631 sizeof(UInt));
1632 LibVEX_GuestX86_put_eflag_c(0, gst);
1634 /* Make CC_DEP1 and CC_DEP2 defined. This is inaccurate because it makes
1635 other eflags defined too (see README.solaris). */
1636 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestX86State,
1637 guest_CC_DEP1), sizeof(UInt));
1638 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestX86State,
1639 guest_CC_DEP2), sizeof(UInt));
1641 # elif defined(VGP_amd64_solaris)
1642 VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
1643 SysRes sres = canonical->sres;
1644 vg_assert(canonical->what == SsComplete);
1646 if (sr_isError(sres)) {
1647 gst->guest_RAX = sr_Err(sres);
1648 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RAX,
1649 sizeof(ULong));
1650 LibVEX_GuestAMD64_put_rflag_c(1, gst);
1652 else {
1653 gst->guest_RAX = sr_Res(sres);
1654 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RAX,
1655 sizeof(ULong));
1656 gst->guest_RDX = sr_ResHI(sres);
1657 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, OFFSET_amd64_RDX,
1658 sizeof(ULong));
1659 LibVEX_GuestAMD64_put_rflag_c(0, gst);
1661 /* Make CC_DEP1 and CC_DEP2 defined. This is inaccurate because it makes
1662 other eflags defined too (see README.solaris). */
1663 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestAMD64State,
1664 guest_CC_DEP1), sizeof(ULong));
1665 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, offsetof(VexGuestAMD64State,
1666 guest_CC_DEP2), sizeof(ULong));
1668 # else
1669 # error "putSyscallStatusIntoGuestState: unknown arch"
1670 # endif
1674 /* Tell me the offsets in the guest state of the syscall params, so
1675 that the scalar argument checkers don't have to have this info
1676 hardwired. */
1678 static
1679 void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
1681 VG_(bzero_inline)(layout, sizeof(*layout));
1683 #if defined(VGP_x86_linux)
1684 layout->o_sysno = OFFSET_x86_EAX;
1685 layout->o_arg1 = OFFSET_x86_EBX;
1686 layout->o_arg2 = OFFSET_x86_ECX;
1687 layout->o_arg3 = OFFSET_x86_EDX;
1688 layout->o_arg4 = OFFSET_x86_ESI;
1689 layout->o_arg5 = OFFSET_x86_EDI;
1690 layout->o_arg6 = OFFSET_x86_EBP;
1691 layout->uu_arg7 = -1; /* impossible value */
1692 layout->uu_arg8 = -1; /* impossible value */
1694 #elif defined(VGP_amd64_linux)
1695 layout->o_sysno = OFFSET_amd64_RAX;
1696 layout->o_arg1 = OFFSET_amd64_RDI;
1697 layout->o_arg2 = OFFSET_amd64_RSI;
1698 layout->o_arg3 = OFFSET_amd64_RDX;
1699 layout->o_arg4 = OFFSET_amd64_R10;
1700 layout->o_arg5 = OFFSET_amd64_R8;
1701 layout->o_arg6 = OFFSET_amd64_R9;
1702 layout->uu_arg7 = -1; /* impossible value */
1703 layout->uu_arg8 = -1; /* impossible value */
1705 #elif defined(VGP_ppc32_linux)
1706 layout->o_sysno = OFFSET_ppc32_GPR0;
1707 layout->o_arg1 = OFFSET_ppc32_GPR3;
1708 layout->o_arg2 = OFFSET_ppc32_GPR4;
1709 layout->o_arg3 = OFFSET_ppc32_GPR5;
1710 layout->o_arg4 = OFFSET_ppc32_GPR6;
1711 layout->o_arg5 = OFFSET_ppc32_GPR7;
1712 layout->o_arg6 = OFFSET_ppc32_GPR8;
1713 layout->uu_arg7 = -1; /* impossible value */
1714 layout->uu_arg8 = -1; /* impossible value */
1716 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1717 layout->o_sysno = OFFSET_ppc64_GPR0;
1718 layout->o_arg1 = OFFSET_ppc64_GPR3;
1719 layout->o_arg2 = OFFSET_ppc64_GPR4;
1720 layout->o_arg3 = OFFSET_ppc64_GPR5;
1721 layout->o_arg4 = OFFSET_ppc64_GPR6;
1722 layout->o_arg5 = OFFSET_ppc64_GPR7;
1723 layout->o_arg6 = OFFSET_ppc64_GPR8;
1724 layout->o_arg7 = OFFSET_ppc64_GPR9;
1725 layout->uu_arg8 = -1; /* impossible value */
1727 #elif defined(VGP_x86_freebsd)
1728 layout->o_sysno = OFFSET_x86_EAX;
1729 // syscall parameters are on stack in C convention
1730 layout->s_arg1 = sizeof(UWord) * 1;
1731 layout->s_arg2 = sizeof(UWord) * 2;
1732 layout->s_arg3 = sizeof(UWord) * 3;
1733 layout->s_arg4 = sizeof(UWord) * 4;
1734 layout->s_arg5 = sizeof(UWord) * 5;
1735 layout->s_arg6 = sizeof(UWord) * 6;
1736 layout->s_arg7 = sizeof(UWord) * 7;
1737 layout->s_arg8 = sizeof(UWord) * 8;
1739 #elif defined(VGP_amd64_freebsd)
1740 layout->o_sysno = OFFSET_amd64_RAX;
1741 layout->o_arg1 = OFFSET_amd64_RDI;
1742 layout->o_arg2 = OFFSET_amd64_RSI;
1743 layout->o_arg3 = OFFSET_amd64_RDX;
1744 layout->o_arg4 = OFFSET_amd64_R10;
1745 layout->o_arg5 = OFFSET_amd64_R8;
1746 layout->o_arg6 = OFFSET_amd64_R9;
1747 layout->s_arg7 = sizeof(UWord) * 1;
1748 layout->s_arg8 = sizeof(UWord) * 2;
1749 layout->arg6_is_reg = True;
1751 #elif defined(VGP_arm_linux)
1752 layout->o_sysno = OFFSET_arm_R7;
1753 layout->o_arg1 = OFFSET_arm_R0;
1754 layout->o_arg2 = OFFSET_arm_R1;
1755 layout->o_arg3 = OFFSET_arm_R2;
1756 layout->o_arg4 = OFFSET_arm_R3;
1757 layout->o_arg5 = OFFSET_arm_R4;
1758 layout->o_arg6 = OFFSET_arm_R5;
1759 layout->uu_arg7 = -1; /* impossible value */
1760 layout->uu_arg8 = -1; /* impossible value */
1762 #elif defined(VGP_arm64_linux)
1763 layout->o_sysno = OFFSET_arm64_X8;
1764 layout->o_arg1 = OFFSET_arm64_X0;
1765 layout->o_arg2 = OFFSET_arm64_X1;
1766 layout->o_arg3 = OFFSET_arm64_X2;
1767 layout->o_arg4 = OFFSET_arm64_X3;
1768 layout->o_arg5 = OFFSET_arm64_X4;
1769 layout->o_arg6 = OFFSET_arm64_X5;
1770 layout->uu_arg7 = -1; /* impossible value */
1771 layout->uu_arg8 = -1; /* impossible value */
1773 #elif defined(VGP_mips32_linux)
1774 layout->o_sysno = OFFSET_mips32_r2;
1775 layout->o_arg1 = OFFSET_mips32_r4;
1776 layout->o_arg2 = OFFSET_mips32_r5;
1777 layout->o_arg3 = OFFSET_mips32_r6;
1778 layout->o_arg4 = OFFSET_mips32_r7;
1779 layout->s_arg5 = sizeof(UWord) * 4;
1780 layout->s_arg6 = sizeof(UWord) * 5;
1781 layout->s_arg7 = sizeof(UWord) * 6;
1782 layout->uu_arg8 = -1; /* impossible value */
1784 #elif defined(VGP_nanomips_linux)
1785 layout->o_sysno = OFFSET_mips32_r2;
1786 layout->o_arg1 = OFFSET_mips32_r4;
1787 layout->o_arg2 = OFFSET_mips32_r5;
1788 layout->o_arg3 = OFFSET_mips32_r6;
1789 layout->o_arg4 = OFFSET_mips32_r7;
1790 layout->o_arg5 = OFFSET_mips32_r8;
1791 layout->o_arg6 = OFFSET_mips32_r9;
1792 layout->uu_arg7 = -1; /* impossible value */
1793 layout->uu_arg8 = -1; /* impossible value */
1795 #elif defined(VGP_mips64_linux)
1796 layout->o_sysno = OFFSET_mips64_r2;
1797 layout->o_arg1 = OFFSET_mips64_r4;
1798 layout->o_arg2 = OFFSET_mips64_r5;
1799 layout->o_arg3 = OFFSET_mips64_r6;
1800 layout->o_arg4 = OFFSET_mips64_r7;
1801 layout->o_arg5 = OFFSET_mips64_r8;
1802 layout->o_arg6 = OFFSET_mips64_r9;
1803 layout->o_arg7 = OFFSET_mips64_r10;
1804 layout->o_arg8 = OFFSET_mips64_r11;
1806 #elif defined(VGP_x86_darwin)
1807 layout->o_sysno = OFFSET_x86_EAX;
1808 // syscall parameters are on stack in C convention
1809 layout->s_arg1 = sizeof(UWord) * 1;
1810 layout->s_arg2 = sizeof(UWord) * 2;
1811 layout->s_arg3 = sizeof(UWord) * 3;
1812 layout->s_arg4 = sizeof(UWord) * 4;
1813 layout->s_arg5 = sizeof(UWord) * 5;
1814 layout->s_arg6 = sizeof(UWord) * 6;
1815 layout->s_arg7 = sizeof(UWord) * 7;
1816 layout->s_arg8 = sizeof(UWord) * 8;
1818 #elif defined(VGP_amd64_darwin)
1819 layout->o_sysno = OFFSET_amd64_RAX;
1820 layout->o_arg1 = OFFSET_amd64_RDI;
1821 layout->o_arg2 = OFFSET_amd64_RSI;
1822 layout->o_arg3 = OFFSET_amd64_RDX;
1823 layout->o_arg4 = OFFSET_amd64_RCX;
1824 layout->o_arg5 = OFFSET_amd64_R8;
1825 layout->o_arg6 = OFFSET_amd64_R9;
1826 layout->s_arg7 = sizeof(UWord) * 1;
1827 layout->s_arg8 = sizeof(UWord) * 2;
1829 #elif defined(VGP_s390x_linux)
1830 layout->o_sysno = OFFSET_s390x_SYSNO;
1831 layout->o_arg1 = OFFSET_s390x_r2;
1832 layout->o_arg2 = OFFSET_s390x_r3;
1833 layout->o_arg3 = OFFSET_s390x_r4;
1834 layout->o_arg4 = OFFSET_s390x_r5;
1835 layout->o_arg5 = OFFSET_s390x_r6;
1836 layout->o_arg6 = OFFSET_s390x_r7;
1837 layout->uu_arg7 = -1; /* impossible value */
1838 layout->uu_arg8 = -1; /* impossible value */
1840 #elif defined(VGP_x86_solaris)
1841 layout->o_sysno = OFFSET_x86_EAX;
1842 /* Syscall parameters are on the stack. */
1843 layout->s_arg1 = sizeof(UWord) * 1;
1844 layout->s_arg2 = sizeof(UWord) * 2;
1845 layout->s_arg3 = sizeof(UWord) * 3;
1846 layout->s_arg4 = sizeof(UWord) * 4;
1847 layout->s_arg5 = sizeof(UWord) * 5;
1848 layout->s_arg6 = sizeof(UWord) * 6;
1849 layout->s_arg7 = sizeof(UWord) * 7;
1850 layout->s_arg8 = sizeof(UWord) * 8;
1852 #elif defined(VGP_amd64_solaris)
1853 layout->o_sysno = OFFSET_amd64_RAX;
1854 layout->o_arg1 = OFFSET_amd64_RDI;
1855 layout->o_arg2 = OFFSET_amd64_RSI;
1856 layout->o_arg3 = OFFSET_amd64_RDX;
1857 layout->o_arg4 = OFFSET_amd64_R10;
1858 layout->o_arg5 = OFFSET_amd64_R8;
1859 layout->o_arg6 = OFFSET_amd64_R9;
1860 layout->s_arg7 = sizeof(UWord) * 1;
1861 layout->s_arg8 = sizeof(UWord) * 2;
1863 #else
1864 # error "getSyscallLayout: unknown arch"
1865 #endif
1868 #if defined(VGP_amd64_freebsd)
1869 static
1870 void getSyscallArgLayout_0_198 ( /*OUT*/SyscallArgLayout* layout )
1872 VG_(bzero_inline)(layout, sizeof(*layout));
1873 layout->o_sysno = OFFSET_amd64_RDI;
1874 layout->o_arg1 = OFFSET_amd64_RSI;
1875 layout->o_arg2 = OFFSET_amd64_RDX;
1876 layout->o_arg3 = OFFSET_amd64_R10;
1877 layout->o_arg4 = OFFSET_amd64_R8;
1878 layout->o_arg5 = OFFSET_amd64_R9;
1879 layout->s_arg6 = sizeof(UWord) * 1;
1880 layout->s_arg7 = sizeof(UWord) * 2;
1881 layout->s_arg8 = sizeof(UWord) * 3;
1882 layout->arg6_is_reg = False;
1884 #endif
1887 /* ---------------------------------------------------------------------
1888 The main driver logic
1889 ------------------------------------------------------------------ */
1891 /* Finding the handlers for a given syscall, or faking up one
1892 when no handler is found. */
1894 static
1895 void bad_before ( ThreadId tid,
1896 SyscallArgLayout* layout,
1897 /*MOD*/SyscallArgs* args,
1898 /*OUT*/SyscallStatus* status,
1899 /*OUT*/UWord* flags )
1901 VG_(dmsg)("WARNING: unhandled %s syscall: %s\n",
1902 VG_PLATFORM, VG_SYSNUM_STRING(args->sysno));
1903 if (VG_(clo_verbosity) > 1) {
1904 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1906 VG_(dmsg)("You may be able to write your own handler.\n");
1907 VG_(dmsg)("Read the file README_MISSING_SYSCALL_OR_IOCTL.\n");
1908 VG_(dmsg)("Nevertheless we consider this a bug. Please report\n");
1909 VG_(dmsg)("it at http://valgrind.org/support/bug_reports.html.\n");
1911 SET_STATUS_Failure(VKI_ENOSYS);
1913 # if defined(VGO_solaris)
1914 VG_(exit)(1);
1915 # endif
1918 static SyscallTableEntry bad_sys =
1919 { bad_before, NULL };
1921 static const SyscallTableEntry* get_syscall_entry ( Int syscallno )
1923 const SyscallTableEntry* sys = NULL;
1925 # if defined(VGO_linux)
1926 sys = ML_(get_linux_syscall_entry)( syscallno );
1928 # elif defined(VGO_freebsd)
1929 sys = ML_(get_freebsd_syscall_entry)( syscallno );
1931 # elif defined(VGO_darwin)
1932 Int idx = VG_DARWIN_SYSNO_INDEX(syscallno);
1934 switch (VG_DARWIN_SYSNO_CLASS(syscallno)) {
1935 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1936 if (idx >= 0 && idx < ML_(syscall_table_size) &&
1937 ML_(syscall_table)[idx].before != NULL)
1938 sys = &ML_(syscall_table)[idx];
1939 break;
1940 case VG_DARWIN_SYSCALL_CLASS_MACH:
1941 if (idx >= 0 && idx < ML_(mach_trap_table_size) &&
1942 ML_(mach_trap_table)[idx].before != NULL)
1943 sys = &ML_(mach_trap_table)[idx];
1944 break;
1945 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1946 if (idx >= 0 && idx < ML_(mdep_trap_table_size) &&
1947 ML_(mdep_trap_table)[idx].before != NULL)
1948 sys = &ML_(mdep_trap_table)[idx];
1949 break;
1950 default:
1951 vg_assert(0);
1952 break;
1955 # elif defined(VGO_solaris)
1956 sys = ML_(get_solaris_syscall_entry)(syscallno);
1958 # else
1959 # error Unknown OS
1960 # endif
1962 return sys == NULL ? &bad_sys : sys;
1966 /* Add and remove signals from mask so that we end up telling the
1967 kernel the state we actually want rather than what the client
1968 wants. */
1969 void VG_(sanitize_client_sigmask)(vki_sigset_t *mask)
1971 VG_(sigdelset)(mask, VKI_SIGKILL);
1972 VG_(sigdelset)(mask, VKI_SIGSTOP);
1973 VG_(sigdelset)(mask, VG_SIGVGKILL); /* never block */
1976 typedef
1977 struct {
1978 SyscallArgs orig_args;
1979 SyscallArgs args;
1980 SyscallStatus status;
1981 UWord flags;
1983 SyscallInfo;
1985 SyscallInfo *syscallInfo;
1987 /* The scheduler needs to be able to zero out these records after a
1988 fork, hence this is exported from m_syswrap. */
1989 void VG_(clear_syscallInfo) ( ThreadId tid )
1991 vg_assert(syscallInfo);
1992 vg_assert(tid >= 0 && tid < VG_N_THREADS);
1993 VG_(memset)( & syscallInfo[tid], 0, sizeof( syscallInfo[tid] ));
1994 syscallInfo[tid].status.what = SsIdle;
1997 Bool VG_(is_in_syscall) ( ThreadId tid )
1999 vg_assert(tid >= 0 && tid < VG_N_THREADS);
2000 return (syscallInfo && syscallInfo[tid].status.what != SsIdle);
2003 Word VG_(is_in_syscall_no) (ThreadId tid )
2005 vg_assert(tid >= 0 && tid < VG_N_THREADS);
2006 return syscallInfo[tid].orig_args.sysno;
2009 static void ensure_initialised ( void )
2011 Int i;
2012 static Bool init_done = False;
2013 if (init_done)
2014 return;
2015 init_done = True;
2017 syscallInfo = VG_(malloc)("scinfo", VG_N_THREADS * sizeof syscallInfo[0]);
2019 for (i = 0; i < VG_N_THREADS; i++) {
2020 VG_(clear_syscallInfo)( i );
2024 /* --- This is the main function of this file. --- */
2026 void VG_(client_syscall) ( ThreadId tid, UInt trc )
2028 Word sysno;
2029 ThreadState* tst;
2030 const SyscallTableEntry* ent;
2031 SyscallArgLayout layout;
2032 SyscallInfo* sci;
2034 ensure_initialised();
2036 vg_assert(VG_(is_valid_tid)(tid));
2037 vg_assert(tid >= 1 && tid < VG_N_THREADS);
2038 vg_assert(VG_(is_running_thread)(tid));
2040 # if !defined(VGO_darwin)
2041 // Resync filtering is meaningless on non-Darwin targets.
2042 vg_assert(VG_(clo_resync_filter) == 0);
2043 # endif
2045 tst = VG_(get_ThreadState)(tid);
2047 /* BEGIN ensure root thread's stack is suitably mapped */
2048 /* In some rare circumstances, we may do the syscall without the
2049 bottom page of the stack being mapped, because the stack pointer
2050 was moved down just a few instructions before the syscall
2051 instruction, and there have been no memory references since
2052 then, that would cause a call to VG_(extend_stack) to have
2053 happened.
2055 In native execution that's OK: the kernel automagically extends
2056 the stack's mapped area down to cover the stack pointer (or sp -
2057 redzone, really). In simulated normal execution that's OK too,
2058 since any signals we get from accessing below the mapped area of
2059 the (guest's) stack lead us to VG_(extend_stack), where we
2060 simulate the kernel's stack extension logic. But that leaves
2061 the problem of entering a syscall with the SP unmapped. Because
2062 the kernel doesn't know that the segment immediately above SP is
2063 supposed to be a grow-down segment, it causes the syscall to
2064 fail, and thereby causes a divergence between native behaviour
2065 (syscall succeeds) and simulated behaviour (syscall fails).
2067 This is quite a rare failure mode. It has only been seen
2068 affecting calls to sys_readlink on amd64-linux, and even then it
2069 requires a certain code sequence around the syscall to trigger
2070 it. Here is one:
2072 extern int my_readlink ( const char* path );
2073 asm(
2074 ".text\n"
2075 ".globl my_readlink\n"
2076 "my_readlink:\n"
2077 "\tsubq $0x1008,%rsp\n"
2078 "\tmovq %rdi,%rdi\n" // path is in rdi
2079 "\tmovq %rsp,%rsi\n" // &buf[0] -> rsi
2080 "\tmovl $0x1000,%edx\n" // sizeof(buf) in rdx
2081 "\tmovl $"__NR_READLINK",%eax\n" // syscall number
2082 "\tsyscall\n"
2083 "\taddq $0x1008,%rsp\n"
2084 "\tret\n"
2085 ".previous\n"
2088 For more details, see bug #156404
2089 (https://bugs.kde.org/show_bug.cgi?id=156404).
2091 The fix is actually very simple. We simply need to call
2092 VG_(extend_stack) for this thread, handing it the lowest
2093 possible valid address for stack (sp - redzone), to ensure the
2094 pages all the way down to that address, are mapped. Because
2095 this is a potentially expensive and frequent operation, we
2096 do the following:
2098 Only the main thread (tid=1) has a growdown stack. So
2099 ignore all others. It is conceivable, although highly unlikely,
2100 that the main thread exits, and later another thread is
2101 allocated tid=1, but that's harmless, I believe;
2102 VG_(extend_stack) will do nothing when applied to a non-root
2103 thread.
2105 All this guff is of course Linux-specific. Hence the ifdef.
2107 # if defined(VGO_linux)
2108 if (tid == 1/*ROOT THREAD*/) {
2109 Addr stackMin = VG_(get_SP)(tid) - VG_STACK_REDZONE_SZB;
2111 /* The precise thing to do here would be to extend the stack only
2112 if the system call can be proven to access unmapped user stack
2113 memory. That is an enormous amount of work even if a proper
2114 spec of system calls was available.
2116 In the case where the system call does not access user memory
2117 the stack pointer here can have any value. A legitimate testcase
2118 that exercises this is none/tests/s390x/stmg.c:
2119 The stack pointer happens to be in the reservation segment near
2120 the end of the addressable memory and there is no SkAnonC segment
2121 above.
2123 So the approximation we're taking here is to extend the stack only
2124 if the client stack pointer does not look bogus. */
2125 if (VG_(am_addr_is_in_extensible_client_stack)(stackMin))
2126 VG_(extend_stack)( tid, stackMin );
2128 # endif
2129 /* END ensure root thread's stack is suitably mapped */
2131 /* First off, get the syscall args and number. This is a
2132 platform-dependent action. */
2134 sci = & syscallInfo[tid];
2135 vg_assert(sci->status.what == SsIdle);
2137 getSyscallArgsFromGuestState( &sci->orig_args, &tst->arch.vex, trc );
2139 /* Copy .orig_args to .args. The pre-handler may modify .args, but
2140 we want to keep the originals too, just in case. */
2141 sci->args = sci->orig_args;
2143 /* Save the syscall number in the thread state in case the syscall
2144 is interrupted by a signal. */
2145 sysno = sci->orig_args.sysno;
2147 # if defined(VGO_freebsd)
2148 tst->arch.vex.guest_SC_CLASS = sci->orig_args.klass;
2149 # endif
2150 /* It's sometimes useful, as a crude debugging hack, to get a
2151 stack trace at each (or selected) syscalls. */
2152 if (0 && sysno == __NR_ioctl) {
2153 VG_(umsg)("\nioctl:\n");
2154 VG_(get_and_pp_StackTrace)(tid, 10);
2155 VG_(umsg)("\n");
2158 # if defined(VGO_darwin)
2159 /* Record syscall class. But why? Because the syscall might be
2160 interrupted by a signal, and in the signal handler (which will
2161 be m_signals.async_signalhandler) we will need to build a SysRes
2162 reflecting the syscall return result. In order to do that we
2163 need to know the syscall class. Hence stash it in the guest
2164 state of this thread. This madness is not needed on Linux
2165 because it only has a single syscall return convention and so
2166 there is no ambiguity involved in converting the post-signal
2167 machine state into a SysRes. */
2168 tst->arch.vex.guest_SC_CLASS = VG_DARWIN_SYSNO_CLASS(sysno);
2169 # endif
2171 /* The default what-to-do-next thing is hand the syscall to the
2172 kernel, so we pre-set that here. Set .sres to something
2173 harmless looking (is irrelevant because .what is not
2174 SsComplete.) */
2175 sci->status.what = SsHandToKernel;
2176 sci->status.sres = VG_(mk_SysRes_Error)(0);
2177 sci->flags = 0;
2179 /* Fetch the syscall's handlers. If no handlers exist for this
2180 syscall, we are given dummy handlers which force an immediate
2181 return with ENOSYS. */
2182 ent = get_syscall_entry(sysno);
2184 /* Fetch the layout information, which tells us where in the guest
2185 state the syscall args reside. This is a platform-dependent
2186 action. This info is needed so that the scalar syscall argument
2187 checks (PRE_REG_READ calls) know which bits of the guest state
2188 they need to inspect. */
2189 #if defined(VGP_amd64_freebsd)
2190 // PJF - somewhat unfortunate uglificaton of the code, but the current code handles two
2191 // types of syscall with different register use. Mixing them up is not good.
2192 // I've avoided modifying the existing function (I could have added
2193 // a FreeBSD amd64-only flag to it for this purpose).
2194 if (sci->orig_args.klass == VG_FREEBSD_SYSCALL0 || sci->orig_args.klass == VG_FREEBSD_SYSCALL198) {
2195 getSyscallArgLayout_0_198( &layout );
2196 } else {
2197 #endif
2199 getSyscallArgLayout( &layout );
2201 #if defined(VGP_amd64_freebsd)
2203 #endif
2206 /* Make sure the tmp signal mask matches the real signal mask;
2207 sigsuspend may change this. */
2208 vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask));
2210 /* Right, we're finally ready to Party. Call the pre-handler and
2211 see what we get back. At this point:
2213 sci->status.what is Unset (we don't know yet).
2214 sci->orig_args contains the original args.
2215 sci->args is the same as sci->orig_args.
2216 sci->flags is zero.
2219 PRINT("SYSCALL[%d,%u](%s) ",
2220 VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno));
2222 /* Do any pre-syscall actions */
2223 if (VG_(needs).syscall_wrapper) {
2224 UWord tmpv[8];
2225 tmpv[0] = sci->orig_args.arg1;
2226 tmpv[1] = sci->orig_args.arg2;
2227 tmpv[2] = sci->orig_args.arg3;
2228 tmpv[3] = sci->orig_args.arg4;
2229 tmpv[4] = sci->orig_args.arg5;
2230 tmpv[5] = sci->orig_args.arg6;
2231 tmpv[6] = sci->orig_args.arg7;
2232 tmpv[7] = sci->orig_args.arg8;
2233 VG_TDICT_CALL(tool_pre_syscall, tid, sysno,
2234 &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0]));
2237 vg_assert(ent);
2238 vg_assert(ent->before);
2239 (ent->before)( tid,
2240 &layout,
2241 &sci->args, &sci->status, &sci->flags );
2243 /* If needed, gdbserver will report syscall entry to GDB */
2244 VG_(gdbserver_report_syscall)(True, sysno, tid);
2246 /* The pre-handler may have modified:
2247 sci->args
2248 sci->status
2249 sci->flags
2250 All else remains unchanged.
2251 Although the args may be modified, pre handlers are not allowed
2252 to change the syscall number.
2254 /* Now we proceed according to what the pre-handler decided. */
2255 vg_assert(sci->status.what == SsHandToKernel
2256 || sci->status.what == SsComplete);
2257 vg_assert(sci->args.sysno == sci->orig_args.sysno);
2259 if (sci->status.what == SsComplete && !sr_isError(sci->status.sres)) {
2260 /* The pre-handler completed the syscall itself, declaring
2261 success. */
2262 if (sci->flags & SfNoWriteResult) {
2263 PRINT(" --> [pre-success] NoWriteResult");
2264 } else {
2265 PRINT(" --> [pre-success] %s", VG_(sr_as_string)(sci->status.sres));
2267 /* In this case the allowable flags are to ask for a signal-poll
2268 and/or a yield after the call. Changing the args isn't
2269 allowed. */
2270 vg_assert(0 == (sci->flags
2271 & ~(SfPollAfter | SfYieldAfter | SfNoWriteResult)));
2272 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
2275 else
2276 if (sci->status.what == SsComplete && sr_isError(sci->status.sres)) {
2277 /* The pre-handler decided to fail syscall itself. */
2278 PRINT(" --> [pre-fail] %s", VG_(sr_as_string)(sci->status.sres));
2279 /* In this case, the pre-handler is also allowed to ask for the
2280 post-handler to be run anyway. Changing the args is not
2281 allowed. */
2282 vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter)));
2283 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
2286 else
2287 if (sci->status.what != SsHandToKernel) {
2288 /* huh?! */
2289 vg_assert(0);
2292 else /* (sci->status.what == HandToKernel) */ {
2293 /* Ok, this is the usual case -- and the complicated one. There
2294 are two subcases: sync and async. async is the general case
2295 and is to be used when there is any possibility that the
2296 syscall might block [a fact that the pre-handler must tell us
2297 via the sci->flags field.] Because the tidying-away /
2298 context-switch overhead of the async case could be large, if
2299 we are sure that the syscall will not block, we fast-track it
2300 by doing it directly in this thread, which is a lot
2301 simpler. */
2303 /* Check that the given flags are allowable: MayBlock, PollAfter
2304 and PostOnFail are ok. */
2305 vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter)));
2307 if (sci->flags & SfMayBlock) {
2309 /* Syscall may block, so run it asynchronously */
2310 vki_sigset_t mask;
2312 PRINT(" --> [async] ... \n");
2314 mask = tst->sig_mask;
2315 VG_(sanitize_client_sigmask)(&mask);
2317 /* Gack. More impedance matching. Copy the possibly
2318 modified syscall args back into the guest state. */
2319 /* JRS 2009-Mar-16: if the syscall args are possibly modified,
2320 then this assertion is senseless:
2321 vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args));
2322 The case that exposed it was sys_posix_spawn on Darwin,
2323 which heavily modifies its arguments but then lets the call
2324 go through anyway, with SfToBlock set, hence we end up here. */
2325 putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex );
2327 /* SfNoWriteResult flag is invalid for blocking signals because
2328 do_syscall_for_client() directly modifies the guest state. */
2329 vg_assert(!(sci->flags & SfNoWriteResult));
2331 /* Drop the bigLock */
2332 VG_(release_BigLock)(tid, VgTs_WaitSys, "VG_(client_syscall)[async]");
2333 /* Urr. We're now in a race against other threads trying to
2334 acquire the bigLock. I guess that doesn't matter provided
2335 that do_syscall_for_client only touches thread-local
2336 state. */
2338 /* Do the call, which operates directly on the guest state,
2339 not on our abstracted copies of the args/result. */
2340 do_syscall_for_client(sysno, tst, &mask);
2342 /* do_syscall_for_client may not return if the syscall was
2343 interrupted by a signal. In that case, flow of control is
2344 first to m_signals.async_sighandler, which calls
2345 VG_(fixup_guest_state_after_syscall_interrupted), which
2346 fixes up the guest state, and possibly calls
2347 VG_(post_syscall). Once that's done, control drops back
2348 to the scheduler. */
2350 /* Darwin: do_syscall_for_client may not return if the
2351 syscall was workq_ops(WQOPS_THREAD_RETURN) and the kernel
2352 responded by starting the thread at wqthread_hijack(reuse=1)
2353 (to run another workqueue item). In that case, wqthread_hijack
2354 calls ML_(wqthread_continue), which is similar to
2355 VG_(fixup_guest_state_after_syscall_interrupted). */
2357 /* Reacquire the lock */
2358 VG_(acquire_BigLock)(tid, "VG_(client_syscall)[async]");
2360 /* Even more impedance matching. Extract the syscall status
2361 from the guest state. */
2362 getSyscallStatusFromGuestState( &sci->status, &tst->arch.vex );
2363 vg_assert(sci->status.what == SsComplete);
2365 /* Be decorative, if required. */
2366 if (VG_(clo_trace_syscalls)) {
2367 PRINT("SYSCALL[%d,%u](%s) ... [async] --> %s",
2368 VG_(getpid)(), tid, VG_SYSNUM_STRING(sysno),
2369 VG_(sr_as_string)(sci->status.sres));
2372 } else {
2374 /* run the syscall directly */
2375 /* The pre-handler may have modified the syscall args, but
2376 since we're passing values in ->args directly to the
2377 kernel, there's no point in flushing them back to the
2378 guest state. Indeed doing so could be construed as
2379 incorrect. */
2380 SysRes sres
2381 = VG_(do_syscall)(sysno, sci->args.arg1, sci->args.arg2,
2382 sci->args.arg3, sci->args.arg4,
2383 sci->args.arg5, sci->args.arg6,
2384 sci->args.arg7, sci->args.arg8 );
2385 sci->status = convert_SysRes_to_SyscallStatus(sres);
2387 /* Be decorative, if required. */
2388 if (VG_(clo_trace_syscalls)) {
2389 PRINT("[sync] --> %s", VG_(sr_as_string)(sci->status.sres));
2394 vg_assert(sci->status.what == SsComplete);
2396 vg_assert(VG_(is_running_thread)(tid));
2398 /* Dump the syscall result back in the guest state. This is
2399 a platform-specific action. */
2400 if (!(sci->flags & SfNoWriteResult))
2401 putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex );
2403 /* If needed, gdbserver will report syscall return to GDB */
2404 VG_(gdbserver_report_syscall)(False, sysno, tid);
2406 /* Situation now:
2407 - the guest state is now correctly modified following the syscall
2408 - modified args, original args and syscall status are still
2409 available in the syscallInfo[] entry for this syscall.
2411 Now go on to do the post-syscall actions (read on down ..)
2413 PRINT(" ");
2414 VG_(post_syscall)(tid);
2415 PRINT("\n");
2419 /* Perform post syscall actions. The expected state on entry is
2420 precisely as at the end of VG_(client_syscall), that is:
2422 - guest state up to date following the syscall
2423 - modified args, original args and syscall status are still
2424 available in the syscallInfo[] entry for this syscall.
2425 - syscall status matches what's in the guest state.
2427 There are two ways to get here: the normal way -- being called by
2428 VG_(client_syscall), and the unusual way, from
2429 VG_(fixup_guest_state_after_syscall_interrupted).
2430 Darwin: there's a third way, ML_(wqthread_continue).
2432 void VG_(post_syscall) (ThreadId tid)
2434 SyscallInfo* sci;
2435 const SyscallTableEntry* ent;
2436 SyscallStatus test_status;
2437 ThreadState* tst;
2438 Word sysno;
2440 /* Preliminaries */
2441 vg_assert(VG_(is_valid_tid)(tid));
2442 vg_assert(tid >= 1 && tid < VG_N_THREADS);
2443 vg_assert(VG_(is_running_thread)(tid));
2445 tst = VG_(get_ThreadState)(tid);
2446 sci = & syscallInfo[tid];
2448 /* m_signals.sigvgkill_handler might call here even when not in
2449 a syscall. */
2450 if (sci->status.what == SsIdle || sci->status.what == SsHandToKernel) {
2451 sci->status.what = SsIdle;
2452 return;
2455 /* Validate current syscallInfo entry. In particular we require
2456 that the current .status matches what's actually in the guest
2457 state. At least in the normal case where we have actually
2458 previously written the result into the guest state. */
2459 vg_assert(sci->status.what == SsComplete);
2461 /* Get the system call number. Because the pre-handler isn't
2462 allowed to mess with it, it should be the same for both the
2463 original and potentially-modified args. */
2464 vg_assert(sci->args.sysno == sci->orig_args.sysno);
2465 sysno = sci->args.sysno;
2467 getSyscallStatusFromGuestState( &test_status, &tst->arch.vex );
2468 if (!(sci->flags & SfNoWriteResult)) {
2469 vg_assert(eq_SyscallStatus( sysno, &sci->status, &test_status ));
2471 /* Failure of the above assertion on Darwin can indicate a problem
2472 in the syscall wrappers that pre-fail or pre-succeed the
2473 syscall, by calling SET_STATUS_Success or SET_STATUS_Failure,
2474 when they really should call SET_STATUS_from_SysRes. The former
2475 create a UNIX-class syscall result on Darwin, which may not be
2476 correct for the syscall; if that's the case then this assertion
2477 fires. See PRE(thread_fast_set_cthread_self) for an example. On
2478 non-Darwin platforms this assertion is should never fail, and this
2479 comment is completely irrelevant. */
2480 /* Ok, looks sane */
2482 /* pre: status == Complete (asserted above) */
2483 /* Consider either success or failure. Now run the post handler if:
2484 - it exists, and
2485 - Success or (Failure and PostOnFail is set)
2487 ent = get_syscall_entry(sysno);
2488 if (ent->after
2489 && ((!sr_isError(sci->status.sres))
2490 || (sr_isError(sci->status.sres)
2491 && (sci->flags & SfPostOnFail) ))) {
2493 (ent->after)( tid, &sci->args, &sci->status );
2496 /* Because the post handler might have changed the status (eg, the
2497 post-handler for sys_open can change the result from success to
2498 failure if the kernel supplied a fd that it doesn't like), once
2499 again dump the syscall result back in the guest state.*/
2500 if (!(sci->flags & SfNoWriteResult))
2501 putSyscallStatusIntoGuestState( tid, &sci->status, &tst->arch.vex );
2503 /* Do any post-syscall actions required by the tool. */
2504 if (VG_(needs).syscall_wrapper) {
2505 UWord tmpv[8];
2506 tmpv[0] = sci->orig_args.arg1;
2507 tmpv[1] = sci->orig_args.arg2;
2508 tmpv[2] = sci->orig_args.arg3;
2509 tmpv[3] = sci->orig_args.arg4;
2510 tmpv[4] = sci->orig_args.arg5;
2511 tmpv[5] = sci->orig_args.arg6;
2512 tmpv[6] = sci->orig_args.arg7;
2513 tmpv[7] = sci->orig_args.arg8;
2514 VG_TDICT_CALL(tool_post_syscall, tid,
2515 sysno,
2516 &tmpv[0], sizeof(tmpv)/sizeof(tmpv[0]),
2517 sci->status.sres);
2520 /* The syscall is done. */
2521 vg_assert(sci->status.what == SsComplete);
2522 sci->status.what = SsIdle;
2524 /* The pre/post wrappers may have concluded that pending signals
2525 might have been created, and will have set SfPollAfter to
2526 request a poll for them once the syscall is done. */
2527 if (sci->flags & SfPollAfter)
2528 VG_(poll_signals)(tid);
2530 /* Similarly, the wrappers might have asked for a yield
2531 afterwards. */
2532 if (sci->flags & SfYieldAfter)
2533 VG_(vg_yield)();
2537 /* ---------------------------------------------------------------------
2538 Dealing with syscalls which get interrupted by a signal:
2539 VG_(fixup_guest_state_after_syscall_interrupted)
2540 ------------------------------------------------------------------ */
2542 /* Syscalls done on behalf of the client are finally handed off to the
2543 kernel in VG_(client_syscall) above, either by calling
2544 do_syscall_for_client (the async case), or by calling
2545 VG_(do_syscall6) (the sync case).
2547 If the syscall is not interrupted by a signal (it may block and
2548 later unblock, but that's irrelevant here) then those functions
2549 eventually return and so control is passed to VG_(post_syscall).
2550 NB: not sure if the sync case can actually get interrupted, as it
2551 operates with all signals masked.
2553 However, the syscall may get interrupted by an async-signal. In
2554 that case do_syscall_for_client/VG_(do_syscall6) do not
2555 return. Instead we wind up in m_signals.async_sighandler. We need
2556 to fix up the guest state to make it look like the syscall was
2557 interrupted for guest. So async_sighandler calls here, and this
2558 does the fixup. Note that from here we wind up calling
2559 VG_(post_syscall) too.
2563 /* These are addresses within ML_(do_syscall_for_client_WRK). See
2564 syscall-$PLAT.S for details.
2566 #if defined(VGO_linux) || defined(VGO_freebsd)
2567 extern const Addr ML_(blksys_setup);
2568 extern const Addr ML_(blksys_restart);
2569 extern const Addr ML_(blksys_complete);
2570 extern const Addr ML_(blksys_committed);
2571 extern const Addr ML_(blksys_finished);
2572 #elif defined(VGO_darwin)
2573 /* Darwin requires extra uglyness */
2574 extern const Addr ML_(blksys_setup_MACH);
2575 extern const Addr ML_(blksys_restart_MACH);
2576 extern const Addr ML_(blksys_complete_MACH);
2577 extern const Addr ML_(blksys_committed_MACH);
2578 extern const Addr ML_(blksys_finished_MACH);
2579 extern const Addr ML_(blksys_setup_MDEP);
2580 extern const Addr ML_(blksys_restart_MDEP);
2581 extern const Addr ML_(blksys_complete_MDEP);
2582 extern const Addr ML_(blksys_committed_MDEP);
2583 extern const Addr ML_(blksys_finished_MDEP);
2584 extern const Addr ML_(blksys_setup_UNIX);
2585 extern const Addr ML_(blksys_restart_UNIX);
2586 extern const Addr ML_(blksys_complete_UNIX);
2587 extern const Addr ML_(blksys_committed_UNIX);
2588 extern const Addr ML_(blksys_finished_UNIX);
2589 #elif defined(VGO_solaris)
2590 extern const Addr ML_(blksys_setup);
2591 extern const Addr ML_(blksys_complete);
2592 extern const Addr ML_(blksys_committed);
2593 extern const Addr ML_(blksys_finished);
2594 extern const Addr ML_(blksys_setup_DRET);
2595 extern const Addr ML_(blksys_complete_DRET);
2596 extern const Addr ML_(blksys_committed_DRET);
2597 extern const Addr ML_(blksys_finished_DRET);
2598 #else
2599 # error "Unknown OS"
2600 #endif
2603 /* Back up guest state to restart a system call. */
2605 void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
2607 #if defined(VGP_x86_linux)
2608 arch->vex.guest_EIP -= 2; // sizeof(int $0x80)
2610 /* Make sure our caller is actually sane, and we're really backing
2611 back over a syscall.
2613 int $0x80 == CD 80
2616 UChar *p = (UChar *)arch->vex.guest_EIP;
2618 if (p[0] != 0xcd || p[1] != 0x80)
2619 VG_(message)(Vg_DebugMsg,
2620 "?! restarting over syscall at %#x %02x %02x\n",
2621 arch->vex.guest_EIP, p[0], p[1]);
2623 vg_assert(p[0] == 0xcd && p[1] == 0x80);
2626 #elif defined(VGP_amd64_linux)
2627 arch->vex.guest_RIP -= 2; // sizeof(syscall)
2629 /* Make sure our caller is actually sane, and we're really backing
2630 back over a syscall.
2632 syscall == 0F 05
2635 UChar *p = (UChar *)arch->vex.guest_RIP;
2637 if (p[0] != 0x0F || p[1] != 0x05)
2638 VG_(message)(Vg_DebugMsg,
2639 "?! restarting over syscall at %#llx %02x %02x\n",
2640 arch->vex.guest_RIP, p[0], p[1]);
2642 vg_assert(p[0] == 0x0F && p[1] == 0x05);
2645 #elif defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux)
2646 arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr)
2648 /* Make sure our caller is actually sane, and we're really backing
2649 back over a syscall.
2651 sc == 44 00 00 02
2654 UChar *p = (UChar *)arch->vex.guest_CIA;
2656 if (p[0] != 0x44 || p[1] != 0x0 || p[2] != 0x0 || p[3] != 0x02)
2657 VG_(message)(Vg_DebugMsg,
2658 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2659 (ULong)arch->vex.guest_CIA, p[0], p[1], p[2], p[3]);
2661 vg_assert(p[0] == 0x44 && p[1] == 0x0 && p[2] == 0x0 && p[3] == 0x2);
2664 #elif defined(VGP_ppc64le_linux)
2665 arch->vex.guest_CIA -= 4; // sizeof(ppc32 instr)
2667 /* Make sure our caller is actually sane, and we're really backing
2668 back over a syscall.
2670 sc == 44 00 00 02
2672 scv == 44 00 00 01
2675 UChar *p = (UChar *)arch->vex.guest_CIA;
2677 if (!(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0
2678 && (p[0] == 0x01 || p[0] == 0x02)))
2679 VG_(message)(Vg_DebugMsg,
2680 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2681 arch->vex.guest_CIA, p[3], p[2], p[1], p[0]);
2683 vg_assert(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0
2684 && (p[0] == 0x1 || p[0] == 0x2));
2687 #elif defined(VGP_arm_linux)
2688 if (arch->vex.guest_R15T & 1) {
2689 // Thumb mode. SVC is a encoded as
2690 // 1101 1111 imm8
2691 // where imm8 is the SVC number, and we only accept 0.
2692 arch->vex.guest_R15T -= 2; // sizeof(thumb 16 bit insn)
2693 UChar* p = (UChar*)(arch->vex.guest_R15T - 1);
2694 Bool valid = p[0] == 0 && p[1] == 0xDF;
2695 if (!valid) {
2696 VG_(message)(Vg_DebugMsg,
2697 "?! restarting over (Thumb) syscall that is not syscall "
2698 "at %#x %02x %02x\n",
2699 arch->vex.guest_R15T - 1, p[0], p[1]);
2701 vg_assert(valid);
2702 // FIXME: NOTE, this really isn't right. We need to back up
2703 // ITSTATE to what it was before the SVC instruction, but we
2704 // don't know what it was. At least assert that it is now
2705 // zero, because if it is nonzero then it must also have
2706 // been nonzero for the SVC itself, which means it was
2707 // conditional. Urk.
2708 vg_assert(arch->vex.guest_ITSTATE == 0);
2709 } else {
2710 // ARM mode. SVC is encoded as
2711 // cond 1111 imm24
2712 // where imm24 is the SVC number, and we only accept 0.
2713 arch->vex.guest_R15T -= 4; // sizeof(arm instr)
2714 UChar* p = (UChar*)arch->vex.guest_R15T;
2715 Bool valid = p[0] == 0 && p[1] == 0 && p[2] == 0
2716 && (p[3] & 0xF) == 0xF;
2717 if (!valid) {
2718 VG_(message)(Vg_DebugMsg,
2719 "?! restarting over (ARM) syscall that is not syscall "
2720 "at %#x %02x %02x %02x %02x\n",
2721 arch->vex.guest_R15T, p[0], p[1], p[2], p[3]);
2723 vg_assert(valid);
2726 #elif defined(VGP_arm64_linux)
2727 arch->vex.guest_PC -= 4; // sizeof(arm64 instr)
2729 /* Make sure our caller is actually sane, and we're really backing
2730 back over a syscall.
2732 svc #0 == d4 00 00 01
2735 UChar *p = (UChar *)arch->vex.guest_PC;
2737 if (p[0] != 0x01 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0xD4)
2738 VG_(message)(
2739 Vg_DebugMsg,
2740 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2741 arch->vex.guest_PC, p[0], p[1], p[2], p[3]
2744 vg_assert(p[0] == 0x01 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0xD4);
2747 #elif defined(VGP_x86_freebsd)
2748 /* XXX: we support different syscall methods. */
2749 arch->vex.guest_EIP -= 2; // sizeof(int $0x80)
2751 /* Make sure our caller is actually sane, and we're really backing
2752 back over a syscall.
2754 int $0x80 == CD 80
2757 UChar *p = (UChar *)arch->vex.guest_EIP;
2759 if (p[0] != 0xcd || p[1] != 0x80)
2760 VG_(message)(Vg_DebugMsg,
2761 "?! restarting over syscall at %#x %02x %02x\n",
2762 arch->vex.guest_EIP, p[0], p[1]);
2764 vg_assert(p[0] == 0xcd && p[1] == 0x80);
2767 #elif defined(VGP_amd64_freebsd)
2768 /* XXX: we support different syscall methods. */
2769 arch->vex.guest_RIP -= 2; // sizeof(syscall)
2771 /* Make sure our caller is actually sane, and we're really backing
2772 back over a syscall.
2774 syscall == 0F 05
2777 UChar *p = (UChar *)arch->vex.guest_RIP;
2779 if (p[0] != 0x0F || p[1] != 0x05)
2780 VG_(message)(Vg_DebugMsg,
2781 "?! restarting over syscall at %#llx %02x %02x\n",
2782 arch->vex.guest_RIP, p[0], p[1]);
2784 vg_assert(p[0] == 0x0F && p[1] == 0x05);
2787 #elif defined(VGP_x86_darwin)
2788 arch->vex.guest_EIP = arch->vex.guest_IP_AT_SYSCALL;
2790 /* Make sure our caller is actually sane, and we're really backing
2791 back over a syscall.
2793 int $0x80 == CD 80 // Used to communicate with BSD syscalls
2794 int $0x81 == CD 81 // Used to communicate with Mach traps
2795 int $0x82 == CD 82 // Used to communicate with "thread" ?
2796 sysenter == 0F 34 // Used to communicate with Unix syscalls
2799 UChar *p = (UChar *)arch->vex.guest_EIP;
2800 Bool ok = (p[0] == 0xCD && p[1] == 0x80)
2801 || (p[0] == 0xCD && p[1] == 0x81)
2802 || (p[0] == 0xCD && p[1] == 0x82)
2803 || (p[0] == 0x0F && p[1] == 0x34);
2804 if (!ok)
2805 VG_(message)(Vg_DebugMsg,
2806 "?! restarting over syscall at %#x %02x %02x\n",
2807 arch->vex.guest_EIP, p[0], p[1]);
2808 vg_assert(ok);
2811 #elif defined(VGP_amd64_darwin)
2812 arch->vex.guest_RIP = arch->vex.guest_IP_AT_SYSCALL;
2814 /* Make sure our caller is actually sane, and we're really backing
2815 back over a syscall.
2817 syscall == 0F 05
2820 UChar *p = (UChar *)arch->vex.guest_RIP;
2822 Bool ok = (p[0] == 0x0F && p[1] == 0x05);
2823 if (!ok)
2824 VG_(message)(Vg_DebugMsg,
2825 "?! restarting over syscall at %#llx %02x %02x\n",
2826 arch->vex.guest_RIP, p[0], p[1]);
2827 vg_assert(ok);
2830 #elif defined(VGP_s390x_linux)
2831 arch->vex.guest_IA -= 2; // sizeof(syscall)
2833 /* Make sure our caller is actually sane, and we're really backing
2834 back over a syscall.
2836 syscall == 0A <num>
2839 UChar *p = (UChar *)arch->vex.guest_IA;
2840 if (p[0] != 0x0A)
2841 VG_(message)(Vg_DebugMsg,
2842 "?! restarting over syscall at %#llx %02x %02x\n",
2843 arch->vex.guest_IA, p[0], p[1]);
2845 vg_assert(p[0] == 0x0A);
2848 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
2850 arch->vex.guest_PC -= 4; // sizeof(mips instr)
2852 /* Make sure our caller is actually sane, and we're really backing
2853 back over a syscall.
2855 syscall == 00 00 00 0C
2856 big endian
2857 syscall == 0C 00 00 00
2860 UChar *p = (UChar *)(Addr)(arch->vex.guest_PC);
2861 # if defined (VG_LITTLEENDIAN)
2862 if (p[0] != 0x0c || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x00)
2863 VG_(message)(Vg_DebugMsg,
2864 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2865 (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
2867 vg_assert(p[0] == 0x0c && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x00);
2868 # elif defined (VG_BIGENDIAN)
2869 if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x00 || p[3] != 0x0c)
2870 VG_(message)(Vg_DebugMsg,
2871 "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
2872 (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
2874 vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c);
2875 # else
2876 # error "Unknown endianness"
2877 # endif
2880 #elif defined(VGP_nanomips_linux)
2882 /* Make sure our caller is actually sane, and we're really backing
2883 back over a syscall.
2885 arch->vex.guest_PC -= 2;
2886 /* PC has to be 16-bit aligned. */
2887 vg_assert((arch->vex.guest_PC & 1) == 0);
2889 UShort *p = ASSUME_ALIGNED(UShort *, (Addr)(arch->vex.guest_PC));
2891 if (((*p) & 0xFFFD) != 0x1008) {
2892 if (((*(p - 1)) & 0xFFFD) != 0x0008) {
2893 VG_(message)(Vg_DebugMsg,
2894 "?! restarting over syscall at %#x %08lx\n",
2895 arch->vex.guest_PC, (UWord)(*p));
2896 vg_assert(0);
2898 arch->vex.guest_PC -= 2;
2901 #elif defined(VGP_x86_solaris)
2902 arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall)
2904 /* Make sure our caller is actually sane, and we're really backing
2905 back over a syscall.
2907 int $0x91 == CD 91
2908 syscall == 0F 05
2909 sysenter == 0F 34
2911 Handle also other syscall instructions because we also handle them in
2912 the scheduler.
2913 int $0x80 == CD 80
2914 int $0x81 == CD 81
2915 int $0x82 == CD 82
2918 UChar *p = (UChar *)arch->vex.guest_EIP;
2920 Bool ok = (p[0] == 0xCD && p[1] == 0x91)
2921 || (p[0] == 0x0F && p[1] == 0x05)
2922 || (p[0] == 0x0F && p[1] == 0x34)
2923 || (p[0] == 0xCD && p[1] == 0x80)
2924 || (p[0] == 0xCD && p[1] == 0x81)
2925 || (p[0] == 0xCD && p[1] == 0x82);
2926 if (!ok)
2927 VG_(message)(Vg_DebugMsg,
2928 "?! restarting over syscall at %#x %02x %02x\n",
2929 arch->vex.guest_EIP, p[0], p[1]);
2930 vg_assert(ok);
2933 #elif defined(VGP_amd64_solaris)
2934 arch->vex.guest_RIP -= 2; // sizeof(syscall)
2936 /* Make sure our caller is actually sane, and we're really backing
2937 back over a syscall.
2939 syscall == 0F 05
2942 UChar *p = (UChar *)arch->vex.guest_RIP;
2944 Bool ok = (p[0] == 0x0F && p[1] == 0x05);
2945 if (!ok)
2946 VG_(message)(Vg_DebugMsg,
2947 "?! restarting over syscall at %#llx %02x %02x\n",
2948 arch->vex.guest_RIP, p[0], p[1]);
2949 vg_assert(ok);
2952 #else
2953 # error "ML_(fixup_guest_state_to_restart_syscall): unknown plat"
2954 #endif
2959 Fix up the guest state when a syscall is interrupted by a signal
2960 and so has been forced to return 'sysret'.
2962 To do this, we determine the precise state of the syscall by
2963 looking at the (real) IP at the time the signal happened. The
2964 syscall sequence looks like:
2966 1. unblock signals
2967 2. perform syscall
2968 3. save result to guest state (EAX, RAX, R3+CR0.SO, R0, V0)
2969 4. re-block signals
2971 If a signal
2972 happens at Then Why?
2973 [1-2) restart nothing has happened (restart syscall)
2974 [2] restart syscall hasn't started, or kernel wants to restart
2975 [2-3) save syscall complete, but results not saved
2976 [3-4) syscall complete, results saved
2978 Sometimes we never want to restart an interrupted syscall (because
2979 sigaction says not to), so we only restart if "restart" is True.
2981 This will also call VG_(post_syscall) if the syscall has actually
2982 completed (either because it was interrupted, or because it
2983 actually finished). It will not call VG_(post_syscall) if the
2984 syscall is set up for restart, which means that the pre-wrapper may
2985 get called multiple times.
2988 void
2989 VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid,
2990 Addr ip,
2991 SysRes sres,
2992 Bool restart,
2993 struct vki_ucontext *uc)
2995 /* Note that we don't know the syscall number here, since (1) in
2996 general there's no reliable way to get hold of it short of
2997 stashing it in the guest state before the syscall, and (2) in
2998 any case we don't need to know it for the actions done by this
2999 routine.
3001 Furthermore, 'sres' is only used in the case where the syscall
3002 is complete, but the result has not been committed to the guest
3003 state yet. In any other situation it will be meaningless and
3004 therefore ignored. */
3006 ThreadState* tst;
3007 SyscallStatus canonical;
3008 ThreadArchState* th_regs;
3009 SyscallInfo* sci;
3011 /* Compute some Booleans indicating which range we're in. */
3012 Bool outside_range,
3013 in_setup_to_restart, // [1,2) in the .S files
3014 at_restart, // [2] in the .S files
3015 in_complete_to_committed, // [3,4) in the .S files
3016 in_committed_to_finished; // [4,5) in the .S files
3018 if (VG_(clo_trace_signals))
3019 VG_(message)( Vg_DebugMsg,
3020 "interrupted_syscall: tid=%u, ip=%#lx, "
3021 "restart=%s, sres.isErr=%s, sres.val=%" FMT_REGWORD "u\n",
3022 tid,
3024 restart ? "True" : "False",
3025 sr_isError(sres) ? "True" : "False",
3026 sr_isError(sres) ? (RegWord)sr_Err(sres) :
3027 (RegWord)sr_Res(sres));
3029 vg_assert(VG_(is_valid_tid)(tid));
3030 vg_assert(tid >= 1 && tid < VG_N_THREADS);
3031 vg_assert(VG_(is_running_thread)(tid));
3033 tst = VG_(get_ThreadState)(tid);
3034 th_regs = &tst->arch;
3035 sci = & syscallInfo[tid];
3037 # if defined(VGO_linux) || defined(VGO_freebsd)
3038 outside_range
3039 = ip < ML_(blksys_setup) || ip >= ML_(blksys_finished);
3040 in_setup_to_restart
3041 = ip >= ML_(blksys_setup) && ip < ML_(blksys_restart);
3043 #if defined(VGP_ppc64le_linux)
3044 /* Starting with ISA 3.0, Power supports two system call instructions sc
3045 and scv. The code in file syscall-ppc64[be|le]-linux.S uses an input
3046 to call the requested system call. The definitions for blksys_restart
3047 and blksys_complete must account for being at either of the two system
3048 calls and account for the branch to lable 3 if the sc instruction was
3049 called. at_restart is true if the ip is at either system call
3050 instruction. in_complete_to_committed is true if the ip is between
3051 blksys_complete and blksys_committed OR at the branch after the sc
3052 instruction. The scv instruction is currently only supported on LE. */
3053 at_restart
3054 = (ip == ML_(blksys_restart)) || ((ip-8) == ML_(blksys_restart));
3055 in_complete_to_committed
3056 = (ip >= ML_(blksys_complete) && ip < ML_(blksys_committed)) ||
3057 ((ip+8) == ML_(blksys_complete));
3058 #else
3059 at_restart
3060 = ip == ML_(blksys_restart);
3061 in_complete_to_committed
3062 = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed);
3063 #endif
3065 in_committed_to_finished
3066 = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished);
3067 # elif defined(VGO_darwin)
3068 outside_range
3069 = (ip < ML_(blksys_setup_MACH) || ip >= ML_(blksys_finished_MACH))
3070 && (ip < ML_(blksys_setup_MDEP) || ip >= ML_(blksys_finished_MDEP))
3071 && (ip < ML_(blksys_setup_UNIX) || ip >= ML_(blksys_finished_UNIX));
3072 in_setup_to_restart
3073 = (ip >= ML_(blksys_setup_MACH) && ip < ML_(blksys_restart_MACH))
3074 || (ip >= ML_(blksys_setup_MDEP) && ip < ML_(blksys_restart_MDEP))
3075 || (ip >= ML_(blksys_setup_UNIX) && ip < ML_(blksys_restart_UNIX));
3076 at_restart
3077 = (ip == ML_(blksys_restart_MACH))
3078 || (ip == ML_(blksys_restart_MDEP))
3079 || (ip == ML_(blksys_restart_UNIX));
3080 in_complete_to_committed
3081 = (ip >= ML_(blksys_complete_MACH) && ip < ML_(blksys_committed_MACH))
3082 || (ip >= ML_(blksys_complete_MDEP) && ip < ML_(blksys_committed_MDEP))
3083 || (ip >= ML_(blksys_complete_UNIX) && ip < ML_(blksys_committed_UNIX));
3084 in_committed_to_finished
3085 = (ip >= ML_(blksys_committed_MACH) && ip < ML_(blksys_finished_MACH))
3086 || (ip >= ML_(blksys_committed_MDEP) && ip < ML_(blksys_finished_MDEP))
3087 || (ip >= ML_(blksys_committed_UNIX) && ip < ML_(blksys_finished_UNIX));
3088 /* Wasn't that just So Much Fun? Does your head hurt yet? Mine does. */
3089 # elif defined(VGO_solaris)
3090 /* The solaris port is never outside the range. */
3091 outside_range = False;
3092 /* The Solaris kernel never restarts syscalls directly! */
3093 at_restart = False;
3094 if (tst->os_state.in_door_return) {
3095 vg_assert(ip >= ML_(blksys_setup_DRET)
3096 && ip < ML_(blksys_finished_DRET));
3098 in_setup_to_restart
3099 = ip >= ML_(blksys_setup_DRET) && ip < ML_(blksys_complete_DRET);
3100 in_complete_to_committed
3101 = ip >= ML_(blksys_complete_DRET) && ip < ML_(blksys_committed_DRET);
3102 in_committed_to_finished
3103 = ip >= ML_(blksys_committed_DRET) && ip < ML_(blksys_finished_DRET);
3105 else {
3106 vg_assert(ip >= ML_(blksys_setup) && ip < ML_(blksys_finished));
3108 in_setup_to_restart
3109 = ip >= ML_(blksys_setup) && ip < ML_(blksys_complete);
3110 in_complete_to_committed
3111 = ip >= ML_(blksys_complete) && ip < ML_(blksys_committed);
3112 in_committed_to_finished
3113 = ip >= ML_(blksys_committed) && ip < ML_(blksys_finished);
3115 # else
3116 # error "Unknown OS"
3117 # endif
3119 #if defined(VGO_freebsd) || defined(VGO_darwin)
3120 if (outside_range)
3122 /* This is not guaranteed to work since the compiler / link editor
3123 could lay out the binary functions in a different order to
3124 the source file. However, it seems to work. */
3126 #if defined (VGA_amd64)
3128 vg_assert((Addr)_______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______ >
3129 (Addr)LibVEX_GuestAMD64_put_rflag_c );
3131 vg_assert(addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______ >
3132 addr_amd64g_calculate_rflags_all_WRK);
3134 if ((ip >= (Addr)LibVEX_GuestAMD64_put_rflag_c &&
3135 ip < (Addr)_______VVVVVVVV_after_GuestAMD64_put_rflag_c_VVVVVVVV_______) ||
3136 (ip >= addr_amd64g_calculate_rflags_all_WRK &&
3137 ip < addr________VVVVVVVV_amd64g_calculate_rflags_all_WRK_VVVVVVVV_______))
3138 #else
3140 vg_assert((Addr)_______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______ >
3141 (Addr)LibVEX_GuestX86_put_eflag_c);
3143 vg_assert(addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______>
3144 addr_x86g_calculate_eflags_all_WRK);
3146 if ((ip >= (Addr)LibVEX_GuestX86_put_eflag_c &&
3147 ip < (Addr)_______VVVVVVVV_after_LibVEX_GuestX86_put_eflag_c_VVVVVVVV_______) ||
3148 (ip >= addr_x86g_calculate_eflags_all_WRK &&
3149 ip < addr________VVVVVVVV_x86g_calculate_eflags_all_WRK_VVVVVVVV_______))
3150 #endif
3152 outside_range = False;
3153 in_complete_to_committed = True;
3156 #endif
3159 /* Figure out what the state of the syscall was by examining the
3160 (real) IP at the time of the signal, and act accordingly. */
3161 if (outside_range) {
3162 if (VG_(clo_trace_signals))
3163 VG_(message)( Vg_DebugMsg,
3164 " not in syscall at all: hmm, very suspicious\n" );
3165 /* Looks like we weren't in a syscall at all. Hmm. */
3166 vg_assert(sci->status.what != SsIdle);
3167 return;
3170 /* We should not be here unless this thread had first started up
3171 the machinery for a syscall by calling VG_(client_syscall).
3172 Hence: */
3173 vg_assert(sci->status.what != SsIdle);
3175 /* now, do one of four fixup actions, depending on where the IP has
3176 got to. */
3178 if (in_setup_to_restart) {
3179 /* syscall hasn't even started; go around again */
3180 if (VG_(clo_trace_signals))
3181 VG_(message)( Vg_DebugMsg, " not started: restarting\n");
3182 vg_assert(sci->status.what == SsHandToKernel);
3183 ML_(fixup_guest_state_to_restart_syscall)(th_regs);
3186 else
3187 if (at_restart) {
3188 # if defined(VGO_solaris)
3189 /* We should never hit this branch on Solaris, see the comment above. */
3190 vg_assert(0);
3191 # endif
3193 /* We're either about to run the syscall, or it was interrupted
3194 and the kernel restarted it. Restart if asked, otherwise
3195 EINTR it. */
3196 if (restart) {
3197 if (VG_(clo_trace_signals))
3198 VG_(message)( Vg_DebugMsg, " at syscall instr: restarting\n");
3199 ML_(fixup_guest_state_to_restart_syscall)(th_regs);
3200 } else {
3201 if (VG_(clo_trace_signals))
3202 VG_(message)( Vg_DebugMsg, " at syscall instr: returning EINTR\n");
3203 canonical = convert_SysRes_to_SyscallStatus(
3204 VG_(mk_SysRes_Error)( VKI_EINTR )
3206 if (!(sci->flags & SfNoWriteResult))
3207 putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex );
3208 sci->status = canonical;
3209 VG_(post_syscall)(tid);
3213 else
3214 if (in_complete_to_committed) {
3215 /* Syscall complete, but result hasn't been written back yet.
3216 Write the SysRes we were supplied with back to the guest
3217 state. */
3218 if (VG_(clo_trace_signals))
3219 VG_(message)( Vg_DebugMsg,
3220 " completed, but uncommitted: committing\n");
3221 canonical = convert_SysRes_to_SyscallStatus( sres );
3222 vg_assert(!(sci->flags & SfNoWriteResult));
3223 putSyscallStatusIntoGuestState( tid, &canonical, &th_regs->vex );
3224 # if defined(VGO_solaris)
3225 if (tst->os_state.in_door_return) {
3226 # if defined(VGP_x86_solaris)
3227 /* Registers %esp and %ebp were also modified by the syscall. */
3228 tst->arch.vex.guest_ESP = uc->uc_mcontext.gregs[VKI_UESP];
3229 tst->arch.vex.guest_EBP = uc->uc_mcontext.gregs[VKI_EBP];
3230 # elif defined(VGP_amd64_solaris)
3231 tst->arch.vex.guest_RSP = uc->uc_mcontext.gregs[VKI_REG_RSP];
3232 tst->arch.vex.guest_RBP = uc->uc_mcontext.gregs[VKI_REG_RBP];
3233 # endif
3235 # endif
3236 sci->status = canonical;
3237 VG_(post_syscall)(tid);
3240 else
3241 if (in_committed_to_finished) {
3242 /* Result committed, but the signal mask has not been restored;
3243 we expect our caller (the signal handler) will have fixed
3244 this up. */
3245 /* XXX: needed? */
3246 #if defined(VGP_x86_freebsd)
3247 /* On FreeBSD, the success/fail status is returned to the caller
3248 and still has to be fixed up here. */
3249 if (!(sci->flags & SfNoWriteResult)) {
3250 if (sr_isError(sres))
3251 LibVEX_GuestX86_put_eflag_c(1, &th_regs->vex);
3252 else
3253 LibVEX_GuestX86_put_eflag_c(0, &th_regs->vex);
3255 #elif defined(VGP_amd64_freebsd)
3256 if (!(sci->flags & SfNoWriteResult)) {
3257 if (sr_isError(sres))
3258 LibVEX_GuestAMD64_put_rflag_c(1, &th_regs->vex);
3259 else
3260 LibVEX_GuestAMD64_put_rflag_c(0, &th_regs->vex);
3262 #endif
3263 if (VG_(clo_trace_signals))
3264 VG_(message)( Vg_DebugMsg,
3265 " completed and committed: nothing to do\n");
3266 # if defined(VGP_x86_solaris)
3267 /* The %eax and %edx values are committed but the carry flag is still
3268 uncommitted. Save it now. */
3269 LibVEX_GuestX86_put_eflag_c(sr_isError(sres), &th_regs->vex);
3270 # elif defined(VGP_amd64_solaris)
3271 LibVEX_GuestAMD64_put_rflag_c(sr_isError(sres), &th_regs->vex);
3272 # endif
3273 getSyscallStatusFromGuestState( &sci->status, &th_regs->vex );
3274 vg_assert(sci->status.what == SsComplete);
3275 VG_(post_syscall)(tid);
3278 else
3279 VG_(core_panic)("?? strange syscall interrupt state?");
3281 /* In all cases, the syscall is now finished (even if we called
3282 ML_(fixup_guest_state_to_restart_syscall), since that just
3283 re-positions the guest's IP for another go at it). So we need
3284 to record that fact. */
3285 sci->status.what = SsIdle;
3289 #if defined(VGO_solaris)
3290 /* Returns True if ip is inside a fixable syscall code in syscall-*-*.S. This
3291 function can be called by a 'non-running' thread! */
3292 Bool VG_(is_ip_in_blocking_syscall)(ThreadId tid, Addr ip)
3294 ThreadState *tst = VG_(get_ThreadState)(tid);
3296 if (tst->os_state.in_door_return)
3297 return ip >= ML_(blksys_setup_DRET) && ip < ML_(blksys_finished_DRET);
3298 else
3299 return ip >= ML_(blksys_setup) && ip < ML_(blksys_finished);
3301 #endif
3304 #if defined(VGO_darwin)
3305 // Clean up after workq_ops(WQOPS_THREAD_RETURN) jumped to wqthread_hijack.
3306 // This is similar to VG_(fixup_guest_state_after_syscall_interrupted).
3307 // This longjmps back to the scheduler.
3308 void ML_(wqthread_continue_NORETURN)(ThreadId tid)
3310 ThreadState* tst;
3311 SyscallInfo* sci;
3313 VG_(acquire_BigLock)(tid, "wqthread_continue_NORETURN");
3315 PRINT("SYSCALL[%d,%u](%s) workq_ops() starting new workqueue item\n",
3316 VG_(getpid)(), tid, VG_SYSNUM_STRING(__NR_workq_ops));
3318 vg_assert(VG_(is_valid_tid)(tid));
3319 vg_assert(tid >= 1 && tid < VG_N_THREADS);
3320 vg_assert(VG_(is_running_thread)(tid));
3322 tst = VG_(get_ThreadState)(tid);
3323 sci = & syscallInfo[tid];
3324 vg_assert(sci->status.what != SsIdle);
3325 vg_assert(tst->os_state.wq_jmpbuf_valid); // check this BEFORE post_syscall
3327 // Pretend the syscall completed normally, but don't touch the thread state.
3328 sci->status = convert_SysRes_to_SyscallStatus( VG_(mk_SysRes_Success)(0) );
3329 sci->flags |= SfNoWriteResult;
3330 VG_(post_syscall)(tid);
3332 ML_(sync_mappings)("in", "ML_(wqthread_continue_NORETURN)", 0);
3334 sci->status.what = SsIdle;
3336 vg_assert(tst->sched_jmpbuf_valid);
3337 VG_MINIMAL_LONGJMP(tst->sched_jmpbuf);
3339 /* NOTREACHED */
3340 vg_assert(0);
3342 #endif
3345 /* ---------------------------------------------------------------------
3346 A place to store the where-to-call-when-really-done pointer
3347 ------------------------------------------------------------------ */
3349 // When the final thread is done, where shall I call to shutdown the
3350 // system cleanly? Is set once at startup (in m_main) and never
3351 // changes after that. Is basically a pointer to the exit
3352 // continuation. This is all just a nasty hack to avoid calling
3353 // directly from m_syswrap to m_main at exit, since that would cause
3354 // m_main to become part of a module cycle, which is silly.
3355 void (* VG_(address_of_m_main_shutdown_actions_NORETURN) )
3356 (ThreadId,VgSchedReturnCode)
3357 = NULL;
3359 /*--------------------------------------------------------------------*/
3360 /*--- end ---*/
3361 /*--------------------------------------------------------------------*/