2 /*--------------------------------------------------------------------*/
3 /*--- Doing syscalls. m_syscall.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_syscall.h"
36 #include "pub_core_tooliface.h"
37 #include "pub_tool_tooliface.h"
40 #include "pub_core_threadstate.h"
41 #include "coregrind/m_syswrap/priv_types_n_macros.h"
42 #include "pub_core_debuglog.h"
43 #include "pub_core_libcprint.h"
44 #include "pub_core_aspacemgr.h"
45 #include "pub_tool_options.h"
46 #include "pub_tool_libcbase.h"
47 #include "pub_tool_stacktrace.h"
48 #include <l4/sys/types.h>
49 #include <l4/sys/utcb.h>
50 #include <l4/sys/ipc.h>
52 /* ---------------------------------------------------------------------
53 Building syscall return values.
54 ------------------------------------------------------------------ */
56 #if defined(VGO_linux)
58 /* Make a SysRes value from a syscall return value. This is
62 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
64 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
66 Linux uses a negative return value to indicate syscall errors,
67 unlike most Unices, which use the condition codes' carry flag.
69 Since version 2.1 the return value of a system call might be
70 negative even if the call succeeded. E.g., the 'lseek' system call
71 might return a large offset. Therefore we must not anymore test
72 for < 0, but test for a real error by making sure the value in %eax
73 is a real error number. Linus said he will make sure the no
74 syscall returns a value in -1 .. -4095 as a valid result so we can
75 safely test with -4095.
78 SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
80 res._isError = val >= -4095 && val <= -1;
82 res._val = (UInt)(-val);
90 SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
92 res._isError = val >= -4095 && val <= -1;
94 res._val = (ULong)(-val);
96 res._val = (ULong)val;
101 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
102 /* Note this must be in the bottom bit of the second arg */
103 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
105 res._isError = (cr0so & 1) != 0;
110 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
111 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
113 res._isError = (cr0so & 1) != 0;
118 SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
120 res._isError = val >= -4095 && val <= -1;
129 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
131 res._isError = val >= -4095 && val <= -1;
133 res._val = (UInt)(-val);
135 res._val = (UInt)val;
140 /* Generic constructors. */
141 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
148 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
156 #elif defined(VGO_aix5)
158 /* AIX scheme: we have to record both 'res' (r3) and 'err' (r4). If
159 'err' is nonzero then the call has failed, but it could still be
160 that AIX userspace will ignore 'err' and instead consult 'res' to
161 determine if the call failed. So we have to record both. */
162 SysRes VG_(mk_SysRes_ppc32_aix5) ( UInt res, UInt err ) {
166 r.isError = r.err != 0;
170 SysRes VG_(mk_SysRes_ppc64_aix5) ( ULong res, ULong err ) {
174 r.isError = r.err != 0;
178 /* Generic constructors. */
179 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
187 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
196 #elif defined(VGO_darwin)
198 /* Darwin: Some syscalls return a double-word result. */
199 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
205 res._mode = 0; /* invalid */
206 vg_assert(isErr == False || isErr == True);
207 vg_assert(sizeof(UWord) == sizeof(UInt));
209 case VG_DARWIN_SYSCALL_CLASS_UNIX:
212 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
214 case VG_DARWIN_SYSCALL_CLASS_MACH:
218 res._mode = SysRes_MACH;
220 case VG_DARWIN_SYSCALL_CLASS_MDEP:
224 res._mode = SysRes_MDEP;
232 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
233 ULong wHI, ULong wLO )
238 res._mode = 0; /* invalid */
239 vg_assert(isErr == False || isErr == True);
240 vg_assert(sizeof(UWord) == sizeof(ULong));
242 case VG_DARWIN_SYSCALL_CLASS_UNIX:
245 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
247 case VG_DARWIN_SYSCALL_CLASS_MACH:
251 res._mode = SysRes_MACH;
253 case VG_DARWIN_SYSCALL_CLASS_MDEP:
257 res._mode = SysRes_MDEP;
265 /* Generic constructors. We assume (without checking if this makes
266 any sense, from the caller's point of view) that these are for the
267 UNIX style of syscall. */
268 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
272 r._mode = SysRes_UNIX_ERR;
276 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
280 r._mode = SysRes_UNIX_OK;
284 #elif defined(VGO_l4re)
286 SysRes VG_(mk_SysRes_x86_l4re) ( UInt val ) {
288 res._isError = val >= -4095 && val <= -1;
299 /* Generic constructors. */
300 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
307 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
319 /* ---------------------------------------------------------------------
320 VG_(do_syscall): A function for doing syscalls.
321 ------------------------------------------------------------------ */
323 #if defined(VGP_x86_linux)
324 /* Incoming args (syscall number + up to 6 args) come on the stack.
325 (ie. the C calling convention).
327 The syscall number goes in %eax. The args are passed to the syscall in
328 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
331 %eax gets the return value. Not sure which registers the kernel
332 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
335 extern UWord do_syscall_WRK (
337 UWord a1, UWord a2, UWord a3,
338 UWord a4, UWord a5, UWord a6
347 " movl 16+ 4(%esp),%eax\n"
348 " movl 16+ 8(%esp),%ebx\n"
349 " movl 16+12(%esp),%ecx\n"
350 " movl 16+16(%esp),%edx\n"
351 " movl 16+20(%esp),%esi\n"
352 " movl 16+24(%esp),%edi\n"
353 " movl 16+28(%esp),%ebp\n"
363 #elif defined(VGP_amd64_linux)
364 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
365 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
368 The syscall number goes in %rax. The args are passed to the syscall in
369 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
370 ie. the kernel's syscall calling convention.
372 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
373 no matter, they are caller-save (the syscall clobbers no callee-save
374 regs, so we don't have to do any register saving/restoring).
376 extern UWord do_syscall_WRK (
378 UWord a1, UWord a2, UWord a3,
379 UWord a4, UWord a5, UWord a6
384 /* Convert function calling convention --> syscall calling
392 " movq 8(%rsp), %r9\n" /* last arg from stack */
398 #elif defined(VGP_ppc32_linux)
399 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
401 The syscall number goes in %r0. The args are passed to the syscall in
402 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
404 The %cr0.so bit flags an error.
405 We return the syscall return value in %r3, and the %cr0.so in
406 the lowest bit of %r4.
407 We return a ULong, of which %r3 is the high word, and %r4 the low.
408 No callee-save regs are clobbered, so no saving/restoring is needed.
410 extern ULong do_syscall_WRK (
412 UWord a1, UWord a2, UWord a3,
413 UWord a4, UWord a5, UWord a6
425 " sc\n" /* syscall: sets %cr0.so on error */
426 " mfcr 4\n" /* %cr -> low word of return var */
427 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
428 " blr\n" /* and return */
432 #elif defined(VGP_ppc64_linux)
433 /* Due to the need to return 65 bits of result, this is completely
434 different from the ppc32 case. The single arg register points to a
435 7-word block containing the syscall # and the 6 args. The syscall
436 result proper is put in [0] of the block, and %cr0.so is in the
437 bottom bit of [1]. */
438 extern void do_syscall_WRK ( ULong* argblock );
441 ".globl do_syscall_WRK\n"
442 ".section \".opd\",\"aw\"\n"
445 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
447 ".type .do_syscall_WRK,@function\n"
448 ".globl .do_syscall_WRK\n"
450 " std 3,-16(1)\n" /* stash arg */
451 " ld 8, 48(3)\n" /* sc arg 6 */
452 " ld 7, 40(3)\n" /* sc arg 5 */
453 " ld 6, 32(3)\n" /* sc arg 4 */
454 " ld 5, 24(3)\n" /* sc arg 3 */
455 " ld 4, 16(3)\n" /* sc arg 2 */
456 " ld 0, 0(3)\n" /* sc number */
457 " ld 3, 8(3)\n" /* sc arg 1 */
458 " sc\n" /* result in r3 and cr0.so */
459 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
460 " std 3,0(5)\n" /* argblock[0] = r3 */
464 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
468 #elif defined(VGP_arm_linux)
469 /* I think the conventions are:
470 args in r0 r1 r2 r3 r4 r5
472 return value in r0, w/ same conventions as x86-linux, viz r0 in
473 -4096 .. -1 is an error value. All other values are success
476 extern UWord do_syscall_WRK (
477 UWord a1, UWord a2, UWord a3,
478 UWord a4, UWord a5, UWord a6,
484 " push {r4, r5, r7}\n"
485 " ldr r4, [sp, #12]\n"
486 " ldr r5, [sp, #16]\n"
487 " ldr r7, [sp, #20]\n"
489 " pop {r4, r5, r7}\n"
494 #elif defined(VGP_ppc32_aix5)
495 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
497 UWord a1, UWord a2, UWord a3,
498 UWord a4, UWord a5, UWord a6,
501 /* Syscalls on AIX are very similar to function calls:
502 - up to 8 args in r3-r10
503 - syscall number in r2
504 - kernel resumes at 'lr', so must set it appropriately beforehand
505 - r3 holds the result and r4 any applicable error code
506 See http://www.cs.utexas.edu/users/cart/publications/tr00-04.ps
507 and also 'man truss'.
509 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
510 even though we state it to be trashed. So use r27 instead. */
513 args[1] = a1; args[2] = a2;
514 args[3] = a3; args[4] = a4;
515 args[5] = a5; args[6] = a6;
516 args[7] = a7; args[8] = a8;
518 __asm__ __volatile__(
520 // establish base ptr
524 "mr 27,2\n\t" // save r2 in r27
525 "mflr 30\n\t" // save lr in r30
527 // set syscall number and args
538 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
539 // wrong address after the sc instruction
542 // set up LR to point just after the sc insn
543 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
551 // result is now in r3; save it in args[0]
553 // error code in r4; save it in args[1]
561 : /*in*/ "b" (&args[0])
563 /*temps*/ "r31","r30","r29","r28","r27",
564 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
565 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
566 "xer","ctr","cr0","cr1","cr2","cr3",
567 "cr4","cr5","cr6","cr7"
574 #elif defined(VGP_ppc64_aix5)
575 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
577 UWord a1, UWord a2, UWord a3,
578 UWord a4, UWord a5, UWord a6,
581 /* Same scheme as ppc32-aix5. */
584 args[1] = a1; args[2] = a2;
585 args[3] = a3; args[4] = a4;
586 args[5] = a5; args[6] = a6;
587 args[7] = a7; args[8] = a8;
589 __asm__ __volatile__(
591 // establish base ptr
595 "mr 27,2\n\t" // save r2 in r27
596 "mflr 30\n\t" // save lr in r30
598 // set syscall number and args
609 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
610 // wrong address after the sc instruction
613 // set up LR to point just after the sc insn
614 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
622 // result is now in r3; save it in args[0]
624 // error code in r4; save it in args[1]
632 : /*in*/ "b" (&args[0])
634 /*temps*/ "r31","r30","r29","r28","r27",
635 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
636 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
637 "xer","ctr","cr0","cr1","cr2","cr3",
638 "cr4","cr5","cr6","cr7"
645 #elif defined(VGP_x86_darwin)
647 /* Incoming args (syscall number + up to 8 args) come in on the stack
649 The kernel's syscall calling convention is:
650 * the syscall number goes in eax
651 * the args are passed to the syscall on the stack,
652 pushed onto the stack R->L (that is, the usual x86
653 calling conventions, with the leftmost arg at the lowest
660 Note that the call type can be determined from the syscall number;
661 there is no need to inspect the actual instruction. Although obviously
662 the instruction must match.
664 * MACH,MDEP: the return value comes back in eax
665 * UNIX: the return value comes back in edx:eax (hi32:lo32)
667 * MACH,MDEP: no error is returned
668 * UNIX: the carry flag indicates success or failure
670 nb here, sizeof(UWord) == sizeof(UInt)
673 __private_extern__ ULong
674 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
675 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
676 UWord a7, UWord a8, /* 28(esp)..32(esp) */
677 UWord syscall_no, /* 36(esp) */
678 /*OUT*/UInt* errflag /* 40(esp) */ );
679 // Unix syscall: 64-bit return in edx:eax, with LSB in eax
680 // error indicated by carry flag: clear=good, set=bad
681 asm(".private_extern _do_syscall_unix_WRK\n"
682 "_do_syscall_unix_WRK:\n"
683 " movl 40(%esp), %ecx \n" /* assume syscall success */
684 " movl $0, (%ecx) \n"
685 " movl 36(%esp), %eax \n"
687 " jnc 1f \n" /* jump if success */
688 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
689 " movl $1, (%ecx) \n"
693 __private_extern__ UInt
694 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
695 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
696 UWord a7, UWord a8, /* 28(esp)..32(esp) */
697 UWord syscall_no /* 36(esp) */ );
698 // Mach trap: 32-bit result in %eax, no error flag
699 asm(".private_extern _do_syscall_mach_WRK\n"
700 "_do_syscall_mach_WRK:\n"
701 " movl 36(%esp), %eax \n"
706 __private_extern__ UInt
707 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
708 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
709 UWord a7, UWord a8, /* 28(esp)..32(esp) */
710 UWord syscall_no /* 36(esp) */ );
711 // mdep trap: 32-bit result in %eax, no error flag
713 ".private_extern _do_syscall_mdep_WRK\n"
714 "_do_syscall_mdep_WRK:\n"
715 " movl 36(%esp), %eax \n"
721 #elif defined(VGP_amd64_darwin)
723 /* Incoming args (syscall number + up to 8 args) come in registers and stack
725 The kernel's syscall calling convention is:
726 * the syscall number goes in rax
727 * the args are passed to the syscall in registers and the stack
728 * the call instruction is 'syscall'
730 * MACH,MDEP: the return value comes back in rax
731 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
733 * MACH,MDEP: no error is returned
734 * UNIX: the carry flag indicates success or failure
736 nb here, sizeof(UWord) == sizeof(ULong)
739 __private_extern__ UWord
740 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
741 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
742 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
743 UWord syscall_no, /* 24(rsp) */
744 /*OUT*/ULong* errflag, /* 32(rsp) */
745 /*OUT*/ULong* res2 ); /* 40(rsp) */
746 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax
747 // error indicated by carry flag: clear=good, set=bad
748 asm(".private_extern _do_syscall_unix_WRK\n"
749 "_do_syscall_unix_WRK:\n"
750 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
751 " movq 32(%rsp), %rax \n" /* assume syscall success */
752 " movq $0, (%rax) \n"
753 " movq 24(%rsp), %rax \n" /* load syscall_no */
755 " jnc 1f \n" /* jump if success */
756 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
757 " movq $1, (%rcx) \n"
758 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
759 " movq %rdx, (%rcx) \n"
760 " retq \n" /* return 1st result word */
763 __private_extern__ UWord
764 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
765 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
766 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
767 UWord syscall_no ); /* 24(rsp) */
768 // Mach trap: 64-bit result, no error flag
769 asm(".private_extern _do_syscall_mach_WRK\n"
770 "_do_syscall_mach_WRK:\n"
771 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
772 " movq 24(%rsp), %rax \n" /* load syscall_no */
777 #elif defined(VGP_x86_l4re)
778 /* Incoming args (syscall number + up to 6 args) come on the stack.
779 (ie. the C calling convention).
781 The syscall number goes in %eax. The args are passed to the syscall in
782 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
785 %eax gets the return value. Not sure which registers the kernel
786 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
790 UWord do_l4re_syscall_WRK( SyscallArgs* args )
792 struct { unsigned d,v; } v = {args->arg5, args->arg6};
794 __asm__ __volatile__ (
796 " movl %[arg6], %%ebp \n\t"
797 " movl 4(%%esi), %%edi \n\t"
798 " movl (%%esi), %%esi \n\t"
803 "=a" (args->arg1), // eax
804 "=b" (args->arg2), // ebx
805 "=c" (args->arg3), // ecx
806 "=d" (args->arg4), // edx
807 "=S" (args->arg5), // esi
808 "=D" (args->arg6) // edi
815 [arg6] "m"((int)args->arg7)
823 UWord do_l4re_syscall_debug_WRK( SyscallArgs* args )
825 struct { unsigned d,v; } v = {args->arg5, args->arg6};
827 __asm__ __volatile__ (
830 "=a" (args->arg1), // eax
831 "=d" (args->arg4), // edx
832 "=S" (args->arg5), // esi
833 "=D" (args->arg6) // edi
846 UWord handle_int80(SyscallArgs *args)
848 struct { unsigned d,v; } v = {args->arg5, args->arg6};
849 __asm__ __volatile__ (
851 " movl %[arg6], %%ebp \n\t"
852 " movl 4(%%esi), %%edi \n\t"
853 " movl (%%esi), %%esi \n\t"
857 "=a" (args->arg1), // eax
858 "=b" (args->arg2), // ebx
859 "=c" (args->arg3), // ecx
860 "=d" (args->arg4), // edx
861 "=S" (args->arg5), // esi
862 "=D" (args->arg6) // edi
869 [arg6] "m"((int)args->arg7)
877 UWord do_l4re_syscall_enter_kdebug_WRK( SyscallArgs* args )
879 struct { unsigned d,v; } v = {args->arg5, args->arg6};
880 __asm__ __volatile__ (
888 UWord handle_ud2(SyscallArgs *a)
890 __asm__ __volatile__ (
895 #elif defined(VGP_s390x_linux)
897 static UWord do_syscall_WRK (
899 UWord arg1, UWord arg2, UWord arg3,
900 UWord arg4, UWord arg5, UWord arg6
903 register UWord __arg1 asm("2") = arg1;
904 register UWord __arg2 asm("3") = arg2;
905 register UWord __arg3 asm("4") = arg3;
906 register UWord __arg4 asm("5") = arg4;
907 register UWord __arg5 asm("6") = arg5;
908 register UWord __arg6 asm("7") = arg6;
909 register ULong __svcres asm("2");
911 __asm__ __volatile__ (
922 : "1", "cc", "memory");
924 return (UWord) (__svcres);
928 # error Unknown platform
932 #if defined(VGO_l4re)
933 static void dump_args(char *str, SyscallArgs *args, l4_utcb_t *u, ThreadId tid)
935 // l4_msg_regs_t *v = l4_utcb_mr_u(l4_utcb_wrap());
936 // l4_msg_regs_t *v = l4_utcb_mr_u(VG_(threads)[VG_(get_running_tid)()].utcb);
938 l4_msg_regs_t *v = l4_utcb_mr_u(u);
940 VG_(debugLog)(0, "syscall", "%s\n", str);
941 VG_(debugLog)(0, "syscall", "Registers:\n"
942 "\t\t sysno = %08lx\n"
943 "\t\t a1 = EAX = 0x%08x a1 = EBX = 0x%08x\n"
944 "\t\t a2 = ECX = 0x%08x a3 = EDX = 0x%08x\n"
945 "\t\t a4 = ESI = 0x%08x a5 = EDI = 0x%08x\n"
946 "\t\t a6 = EBP = 0x%08x\n",
947 (int)args->sysno, (int)args->arg1,
948 (int)args->arg2, (int)args->arg3,
949 (int)args->arg4, (int)args->arg5,
950 (int)args->arg6, (int)args->arg7);
953 VG_(debugLog)(0, "syscall", "UTCB contents:\n"
954 "\t\t MR0 = 0x%08x MR1 = 0x%08x\n"
955 "\t\t MR2 = 0x%08x MR2 = 0x%08x\n"
956 "\t\t MR4 = 0x%08x MR4 = 0x%08x\n"
957 "\t\t MR6 = 0x%08x MR6 = 0x%08x\n"
958 "\t\t MR8 = 0x%08x MR8 = 0x%08x\n",
959 (unsigned int) v->mr[0], (unsigned int) v->mr[1],
960 (unsigned int) v->mr[2], (unsigned int) v->mr[3],
961 (unsigned int) v->mr[4], (unsigned int) v->mr[5],
962 (unsigned int) v->mr[6], (unsigned int) v->mr[7],
963 (unsigned int) v->mr[8], (unsigned int) v->mr[9]);
966 static void dump_backtrace(char *str, ThreadId tid)
968 VG_(debugLog)(0, "syscall", "Backtrace of client:\n", str);
969 VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
973 /* Handling for enter_kdebug(text) done
975 * outstring(const char *) done
976 * outnstring(const char *, unsigned) done
985 void handle_kdebug(SyscallArgs *args, ThreadId tid) {
986 #define MAX_STR_LEN 128
987 #define DEBUG_MYSELF 0
988 char str[MAX_STR_LEN];
991 char const *s1 = "\033[35m"; // color magenta
992 char const *s2 = "\033[0m"; // color reset
995 ip = VG_(threads)[tid].arch.vex.guest_EIP;
997 //VG_(debugLog)(0, "syscall", "%02X %02X %02X %02X\n", *ip, *(ip+1), *(ip+2), *(ip+3));
998 l4re_hexdump(ip, 16);
1001 if (*(ip) == 0xEB /* jmp */) {
1002 /* enter_kdebug(text) */
1004 vg_assert(len >= 0 && len < MAX_STR_LEN);
1006 VG_(strncpy)(&str, ip + 2, len);
1009 VG_(printf)("%senter_kdebug via client: %s%s\n", s1, str, s2);
1010 VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
1011 do_l4re_syscall_enter_kdebug_WRK(args);
1012 } else if (*(ip) == 0x3C /* cmp */) {
1014 case 0x0: /* outchar(char) */
1016 Char c = VG_(threads)[tid].arch.vex.guest_EAX & 0x000000ff;
1017 VG_(printf)("%s%c%s", s1, c , s2);
1020 case 0x1: /* outnstring(const char*, unsigned) */
1022 char *_str = VG_(threads)[tid].arch.vex.guest_EAX;
1023 unsigned len = VG_(threads)[tid].arch.vex.guest_ECX;
1024 vg_assert(len >= 0 && len < MAX_STR_LEN);
1025 VG_(strncpy)(&str, _str, len);
1027 VG_(printf)("%s%s%s", s1, str , s2);
1030 case 0x2: /* outstring(const char*) */
1032 char *_str = VG_(threads)[tid].arch.vex.guest_EAX;
1033 VG_(printf)("%s%s%s", s1, _str , s2);
1036 case 0x5: /* outhex32(int) */
1038 int n = VG_(threads)[tid].arch.vex.guest_EAX;
1039 VG_(printf)("%s%x%s", s1, n, s2);
1042 case 0xB /* 11 */: /* outdec(int) */
1044 int n = VG_(threads)[tid].arch.vex.guest_EAX;
1045 VG_(printf)("%s%d%s", s1, n, s2);
1052 VG_(printf)("%sunknown outXY()%s\n", s1, s2);
1053 VG_(debugLog)(0, "syscall", "%x %x %x %x\n", *ip, *(ip+1), *(ip+2), *(ip+3));
1054 do_l4re_syscall_enter_kdebug_WRK(args);
1057 } else { /* everything else */
1058 VG_(printf)("%senter_kdebug via client%s\n", s1, s2);
1059 do_l4re_syscall_enter_kdebug_WRK(args);
1066 Bool dbg_artificial_handling = DEBUG_OFF;
1068 void handle_artificial(SyscallArgs *args)
1070 L4RedirState *s = (L4RedirState *)args->arg1;
1071 switch(s->redir_type) {
1073 if (dbg_artificial_handling) VG_(debugLog)(4, "systrp", "open(file='%s' flags=%08lx) = %d\n",
1074 s->open.path, s->open.flags, s->retval);
1075 vrm_register_filename(s->retval, s->open.path);
1078 if (dbg_artificial_handling) VG_(debugLog)(4, "systrp", "close(fd=%d) = %d\n",
1079 s->close.fd, s->retval);
1080 vrm_unregister_filename(s->close.fd);
1084 if (dbg_artificial_handling) {
1085 VG_(debugLog)(4, "systrp", "mmap(a=%08lx, size = %lx, prot = %08lx\n",
1086 s->mmap.addr, s->mmap.size, s->mmap.prot);
1087 VG_(debugLog)(4, "systrp", " fd = %d offset = %lx) = %lx\n",
1088 s->mmap.fd, s->mmap.offset, s->retval);
1091 /* Modify segment -> SkFileC */
1092 if (s->mmap.fd >= 0) {
1093 extern Int allocate_segname(const HChar *);
1095 HChar buf[VKI_PATH_MAX];
1098 * The segment has already been registered (as anon client)
1099 * by VRM. Now find it and adapt its type.
1101 NSegment *seg = VG_(am_find_nsegment)(s->retval);
1102 seg->kind = SkFileC;
1105 * Also, store file offset and adapt the mapping's
1106 * access rights properly.
1108 seg->offset = s->mmap.offset;
1109 seg->hasR = toBool(s->mmap.prot & VKI_PROT_READ);
1110 seg->hasW = toBool(s->mmap.prot & VKI_PROT_WRITE);
1111 seg->hasX = toBool(s->mmap.prot & VKI_PROT_EXEC);
1113 VG_(strncpy)(buf, vrm_get_filename(s->mmap.fd), VKI_PATH_MAX);
1114 seg->fnIdx = allocate_segname(buf);
1117 * Finally, tell the debug info reader to check if
1118 * it needs information from this.
1120 VG_(di_notify_mmap)(s->mmap.addr, s->mmap.size);
1125 VG_(printf)("Unknown artificial redir type: %lx\n", s->redir_type);
1126 enter_kdebug("unknown artificial redir\n");
1132 SysRes VG_(do_l4re_syscall) ( SyscallArgs *args, ThreadId tid )
1134 #define DEBUG_MYSELF 0
1135 l4_utcb_t *utcb = l4_utcb_wrap();
1137 // we havn't the big look - so malloc is a bad idea!!
1138 //void *vg_utcb = VG_(malloc)("vg_utcb", 512);
1139 char _vg_utcb[L4RE_UTCB_SIZE];
1140 void *vg_utcb = &_vg_utcb[0];
1143 VG_(debugLog)(0, "syscall", "\033[36mThe client makes a syscall tid = %d\033[0m\n"
1144 "\t\t real-utcb @ %p virt-utcb @ %p\n",
1147 ts_utcb(&VG_(threads)[tid]));
1149 dump_args(" -- Before syscall --", args, ts_utcb(&VG_(threads)[tid]), tid);
1150 dump_backtrace(" -- Before syscall --", tid);
1152 // backup valgrinds utcb
1153 VG_(memcpy)(vg_utcb, utcb, L4RE_UTCB_SIZE);
1156 // virt utcb --> real utcb
1157 VG_(memcpy)(utcb, ts_utcb(&VG_(threads)[tid]), L4RE_UTCB_SIZE);
1159 // do syscall for guest
1160 switch (args->sysno) {
1162 do_l4re_syscall_WRK(args);
1165 do_l4re_syscall_debug_WRK(args);
1167 case SYS_ENTER_KDEBUG:
1168 handle_kdebug(args, tid);
1170 case SYS_LINUX_INT80:
1173 case SYS_ARTIFICIAL:
1174 handle_artificial(args);
1180 VG_(printf)("unknown syscall: %lx\n", args->sysno);
1184 // real utcb --> virt utcb
1185 VG_(memcpy)(ts_utcb(&VG_(threads)[tid]), utcb, L4RE_UTCB_SIZE);
1187 // restore valgrinds utcb
1188 VG_(memcpy)(utcb, vg_utcb, L4RE_UTCB_SIZE);
1192 dump_args(" -- After syscall --", args, ts_utcb(&VG_(threads)[tid]), tid);
1195 return VG_(mk_SysRes_Success)(0);
1200 /* Finally, the generic code. This sends the call to the right
1203 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
1204 UWord a4, UWord a5, UWord a6,
1205 UWord a7, UWord a8 )
1207 # if defined(VGP_x86_linux)
1208 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1209 return VG_(mk_SysRes_x86_linux)( val );
1211 # elif defined(VGP_amd64_linux)
1212 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1213 return VG_(mk_SysRes_amd64_linux)( val );
1215 # elif defined(VGP_ppc32_linux)
1216 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1217 UInt val = (UInt)(ret>>32);
1218 UInt cr0so = (UInt)(ret);
1219 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
1221 # elif defined(VGP_ppc64_linux)
1223 argblock[0] = sysno;
1230 do_syscall_WRK( &argblock[0] );
1231 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
1233 # elif defined(VGP_arm_linux)
1234 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
1235 return VG_(mk_SysRes_arm_linux)( val );
1237 # elif defined(VGP_ppc32_aix5)
1240 do_syscall_WRK( &res, &err,
1241 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
1242 /* Try to set the error number to zero if the syscall hasn't
1244 if (sysno == __NR_AIX5_kread
1245 || sysno == __NR_AIX5_kwrite) {
1246 if (res != (UWord)-1L)
1249 else if (sysno == __NR_AIX5_sigprocmask
1250 || sysno == __NR_AIX5__sigpending) {
1254 return VG_(mk_SysRes_ppc32_aix5)( res, err );
1256 # elif defined(VGP_ppc64_aix5)
1259 do_syscall_WRK( &res, &err,
1260 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
1261 /* Try to set the error number to zero if the syscall hasn't
1263 if (sysno == __NR_AIX5_kread
1264 || sysno == __NR_AIX5_kwrite) {
1265 if (res != (UWord)-1L)
1268 else if (sysno == __NR_AIX5_sigprocmask
1269 || sysno == __NR_AIX5__sigpending) {
1273 return VG_(mk_SysRes_ppc64_aix5)( res, err );
1275 # elif defined(VGP_x86_darwin)
1276 UInt wLO = 0, wHI = 0, err = 0;
1278 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
1280 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1281 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1282 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
1284 wHI = (UInt)(u64 >> 32);
1286 case VG_DARWIN_SYSCALL_CLASS_MACH:
1287 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1288 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1291 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1292 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1293 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1300 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
1302 # elif defined(VGP_amd64_darwin)
1303 ULong wLO = 0, wHI = 0, err = 0;
1304 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
1306 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1307 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1308 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
1310 case VG_DARWIN_SYSCALL_CLASS_MACH:
1311 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1312 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1313 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1320 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
1322 #elif defined(VGP_s390x_linux)
1325 if (sysno == __NR_mmap) {
1334 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
1336 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1339 return VG_(mk_SysRes_s390x_linux)( val );
1341 #elif defined(VGO_l4re)
1342 VG_(unimplemented)("unimplemented function VG_(do_syscall)");
1343 return VG_(mk_SysRes_Error)(1);
1345 # error Unknown platform
1349 /* ---------------------------------------------------------------------
1351 ------------------------------------------------------------------ */
1353 /* Return a string which gives the name of an error value. Note,
1354 unlike the standard C syserror fn, the returned string is not
1355 malloc-allocated or writable -- treat it as a constant.
1356 TODO: implement this properly. */
1358 const HChar* VG_(strerror) ( UWord errnum )
1361 case VKI_EPERM: return "Operation not permitted";
1362 case VKI_ENOENT: return "No such file or directory";
1363 case VKI_ESRCH: return "No such process";
1364 case VKI_EINTR: return "Interrupted system call";
1365 case VKI_EBADF: return "Bad file number";
1366 case VKI_EAGAIN: return "Try again";
1367 case VKI_ENOMEM: return "Out of memory";
1368 case VKI_EACCES: return "Permission denied";
1369 case VKI_EFAULT: return "Bad address";
1370 case VKI_EEXIST: return "File exists";
1371 case VKI_EINVAL: return "Invalid argument";
1372 case VKI_EMFILE: return "Too many open files";
1373 case VKI_ENOSYS: return "Function not implemented";
1374 case VKI_EOVERFLOW: return "Value too large for defined data type";
1375 # if defined(VKI_ERESTARTSYS)
1376 case VKI_ERESTARTSYS: return "ERESTARTSYS";
1379 #if defined(VGO_l4re)
1380 VG_(debugLog)(1, "syscall", "%s: unknown errnum: %d\n", __func__, (int) errnum);
1382 return "VG_(strerror): unknown error";
1387 /*--------------------------------------------------------------------*/
1389 /*--------------------------------------------------------------------*/