1
2/*--------------------------------------------------------------------*/
3/*--- Doing syscalls.                                  m_syscall.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2000-2013 Julian Seward
11      jseward@acm.org
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26   02111-1307, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29*/
30
31#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
37/* ---------------------------------------------------------------------
38   Building syscall return values.
39   ------------------------------------------------------------------ */
40
41#if defined(VGO_linux)
42
43/* Make a SysRes value from a syscall return value.  This is
44   Linux-specific.
45
46   From:
47   http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
48   linux/i386/sysdep.h?
49   rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
50
51   Linux uses a negative return value to indicate syscall errors,
52   unlike most Unices, which use the condition codes' carry flag.
53
54   Since version 2.1 the return value of a system call might be
55   negative even if the call succeeded.  E.g., the 'lseek' system call
56   might return a large offset.  Therefore we must not anymore test
57   for < 0, but test for a real error by making sure the value in %eax
58   is a real error number.  Linus said he will make sure the no
59   syscall returns a value in -1 .. -4095 as a valid result so we can
60   safely test with -4095.
61*/
62
63SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
64   SysRes res;
65   res._isError = val >= -4095 && val <= -1;
66   if (res._isError) {
67      res._val = (UInt)(-val);
68   } else {
69      res._val = (UInt)val;
70   }
71   return res;
72}
73
74/* Similarly .. */
75SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
76   SysRes res;
77   res._isError = val >= -4095 && val <= -1;
78   if (res._isError) {
79      res._val = (ULong)(-val);
80   } else {
81      res._val = (ULong)val;
82   }
83   return res;
84}
85
86SysRes VG_(mk_SysRes_tilegx_linux) ( Long val ) {
87  SysRes res;
88  res._isError = val >= -4095 && val <= -1;
89  if (res._isError) {
90    res._val = (ULong)(-val);
91  } else {
92    res._val = (ULong)val;
93  }
94  return res;
95}
96
97/* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
98/* Note this must be in the bottom bit of the second arg */
99SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
100   SysRes res;
101   res._isError = (cr0so & 1) != 0;
102   res._val     = val;
103   return res;
104}
105
106/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
107SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
108   SysRes res;
109   res._isError = (cr0so & 1) != 0;
110   res._val     = val;
111   return res;
112}
113
114SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
115   SysRes res;
116   res._isError = val >= -4095 && val <= -1;
117   if (res._isError) {
118      res._val = -val;
119   } else {
120      res._val = val;
121   }
122   return res;
123}
124
125SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
126   SysRes res;
127   res._isError = val >= -4095 && val <= -1;
128   if (res._isError) {
129      res._val = (UInt)(-val);
130   } else {
131      res._val = (UInt)val;
132   }
133   return res;
134}
135
136SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
137   SysRes res;
138   res._isError = val >= -4095 && val <= -1;
139   if (res._isError) {
140      res._val = (ULong)(-val);
141   } else {
142      res._val = (ULong)val;
143   }
144   return res;
145}
146
147#if defined(VGA_mips64) || defined(VGA_mips32)
148/* MIPS uses a3 != 0 to flag an error */
149SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
150   SysRes res;
151   res._isError = (a3 != (UWord)0);
152   res._val     = v0;
153   res._valEx   = v1;
154   return res;
155}
156
157/* MIPS uses a3 != 0 to flag an error */
158SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) {
159   SysRes res;
160   res._isError = (a3 != (ULong)0);
161   res._val     = v0;
162   res._valEx   = v1;
163   return res;
164}
165#endif
166
167/* Generic constructors. */
168SysRes VG_(mk_SysRes_Error) ( UWord err ) {
169   SysRes r;
170#if defined(VGA_mips64) || defined(VGA_mips32)
171   r._valEx   = 0;
172#endif
173   r._isError = True;
174   r._val     = err;
175   return r;
176}
177
178SysRes VG_(mk_SysRes_Success) ( UWord res ) {
179   SysRes r;
180#if defined(VGA_mips64) || defined(VGA_mips32)
181   r._valEx   = 0;
182#endif
183   r._isError = False;
184   r._val     = res;
185   return r;
186}
187
188
189#elif defined(VGO_darwin)
190
191/* Darwin: Some syscalls return a double-word result. */
192SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
193                                   UInt wHI, UInt wLO )
194{
195   SysRes res;
196   res._wHI  = 0;
197   res._wLO  = 0;
198   res._mode = 0; /* invalid */
199   vg_assert(isErr == False || isErr == True);
200   vg_assert(sizeof(UWord) == sizeof(UInt));
201   switch (scclass) {
202      case VG_DARWIN_SYSCALL_CLASS_UNIX:
203         res._wLO  = wLO;
204         res._wHI  = wHI;
205         res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
206         break;
207      case VG_DARWIN_SYSCALL_CLASS_MACH:
208         vg_assert(!isErr);
209         vg_assert(wHI == 0);
210         res._wLO  = wLO;
211         res._mode = SysRes_MACH;
212         break;
213      case VG_DARWIN_SYSCALL_CLASS_MDEP:
214         vg_assert(!isErr);
215         vg_assert(wHI == 0);
216         res._wLO  = wLO;
217         res._mode = SysRes_MDEP;
218         break;
219      default:
220         vg_assert(0);
221   }
222   return res;
223}
224
225SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
226                                     ULong wHI, ULong wLO )
227{
228   SysRes res;
229   res._wHI  = 0;
230   res._wLO  = 0;
231   res._mode = 0; /* invalid */
232   vg_assert(isErr == False || isErr == True);
233   vg_assert(sizeof(UWord) == sizeof(ULong));
234   switch (scclass) {
235      case VG_DARWIN_SYSCALL_CLASS_UNIX:
236         res._wLO  = wLO;
237         res._wHI  = wHI;
238         res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
239         break;
240      case VG_DARWIN_SYSCALL_CLASS_MACH:
241         vg_assert(!isErr);
242         vg_assert(wHI == 0);
243         res._wLO  = wLO;
244         res._mode = SysRes_MACH;
245         break;
246      case VG_DARWIN_SYSCALL_CLASS_MDEP:
247         vg_assert(!isErr);
248         vg_assert(wHI == 0);
249         res._wLO  = wLO;
250         res._mode = SysRes_MDEP;
251         break;
252      default:
253         vg_assert(0);
254   }
255   return res;
256}
257
258/* Generic constructors.  We assume (without checking if this makes
259   any sense, from the caller's point of view) that these are for the
260   UNIX style of syscall. */
261SysRes VG_(mk_SysRes_Error) ( UWord err ) {
262   SysRes r;
263   r._wHI  = 0;
264   r._wLO  = err;
265   r._mode = SysRes_UNIX_ERR;
266   return r;
267}
268
269SysRes VG_(mk_SysRes_Success) ( UWord res ) {
270   SysRes r;
271   r._wHI  = 0;
272   r._wLO  = res;
273   r._mode = SysRes_UNIX_OK;
274   return r;
275}
276
277
278#else
279#  error "Unknown OS"
280#endif
281
282
283/* ---------------------------------------------------------------------
284   VG_(do_syscall): A function for doing syscalls.
285   ------------------------------------------------------------------ */
286
287#if defined(VGP_x86_linux)
288/* Incoming args (syscall number + up to 6 args) come on the stack.
289   (ie. the C calling convention).
290
291   The syscall number goes in %eax.  The args are passed to the syscall in
292   the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
293   calling convention.
294
295   %eax gets the return value.  Not sure which registers the kernel
296   clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
297   %ebp).
298*/
299extern UWord do_syscall_WRK (
300          UWord syscall_no,
301          UWord a1, UWord a2, UWord a3,
302          UWord a4, UWord a5, UWord a6
303       );
304asm(
305".text\n"
306".globl do_syscall_WRK\n"
307"do_syscall_WRK:\n"
308"	.cfi_startproc\n"
309"	push	%esi\n"
310"	.cfi_adjust_cfa_offset 4\n"
311"	.cfi_offset %esi, -8\n"
312"	push	%edi\n"
313"	.cfi_adjust_cfa_offset 4\n"
314"	.cfi_offset %edi, -12\n"
315"	push	%ebx\n"
316"	.cfi_adjust_cfa_offset 4\n"
317"	.cfi_offset %ebx, -16\n"
318"	push	%ebp\n"
319"	.cfi_adjust_cfa_offset 4\n"
320"	.cfi_offset %ebp, -20\n"
321"	movl	16+ 4(%esp),%eax\n"
322"	movl	16+ 8(%esp),%ebx\n"
323"	movl	16+12(%esp),%ecx\n"
324"	movl	16+16(%esp),%edx\n"
325"	movl	16+20(%esp),%esi\n"
326"	movl	16+24(%esp),%edi\n"
327"	movl	16+28(%esp),%ebp\n"
328"	int	$0x80\n"
329"	popl	%ebp\n"
330"	.cfi_adjust_cfa_offset -4\n"
331"	.cfi_restore %ebp\n"
332"	popl	%ebx\n"
333"	.cfi_adjust_cfa_offset -4\n"
334"	.cfi_restore %ebx\n"
335"	popl	%edi\n"
336"	.cfi_adjust_cfa_offset -4\n"
337"	.cfi_restore %edi\n"
338"	popl	%esi\n"
339"	.cfi_adjust_cfa_offset -4\n"
340"	.cfi_restore %esi\n"
341"	ret\n"
342"	.cfi_endproc\n"
343".previous\n"
344);
345
346#elif defined(VGP_amd64_linux)
347/* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
348   %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
349   calling convention).
350
351   The syscall number goes in %rax.  The args are passed to the syscall in
352   the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
353   ie. the kernel's syscall calling convention.
354
355   %rax gets the return value.  %rcx and %r11 are clobbered by the syscall;
356   no matter, they are caller-save (the syscall clobbers no callee-save
357   regs, so we don't have to do any register saving/restoring).
358*/
359extern UWord do_syscall_WRK (
360          UWord syscall_no,
361          UWord a1, UWord a2, UWord a3,
362          UWord a4, UWord a5, UWord a6
363       );
364asm(
365".text\n"
366".globl do_syscall_WRK\n"
367"do_syscall_WRK:\n"
368        /* Convert function calling convention --> syscall calling
369           convention */
370"	movq	%rdi, %rax\n"
371"	movq	%rsi, %rdi\n"
372"	movq	%rdx, %rsi\n"
373"	movq	%rcx, %rdx\n"
374"	movq	%r8,  %r10\n"
375"	movq	%r9,  %r8\n"
376"	movq    8(%rsp), %r9\n"	 /* last arg from stack */
377"	syscall\n"
378"	ret\n"
379".previous\n"
380);
381
382#elif defined(VGP_ppc32_linux)
383/* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
384
385   The syscall number goes in %r0.  The args are passed to the syscall in
386   the regs %r3:%r8, i.e. the kernel's syscall calling convention.
387
388   The %cr0.so bit flags an error.
389   We return the syscall return value in %r3, and the %cr0.so in
390   the lowest bit of %r4.
391   We return a ULong, of which %r3 is the high word, and %r4 the low.
392   No callee-save regs are clobbered, so no saving/restoring is needed.
393*/
394extern ULong do_syscall_WRK (
395          UWord syscall_no,
396          UWord a1, UWord a2, UWord a3,
397          UWord a4, UWord a5, UWord a6
398       );
399asm(
400".text\n"
401".globl do_syscall_WRK\n"
402"do_syscall_WRK:\n"
403"        mr      0,3\n"
404"        mr      3,4\n"
405"        mr      4,5\n"
406"        mr      5,6\n"
407"        mr      6,7\n"
408"        mr      7,8\n"
409"        mr      8,9\n"
410"        sc\n"                  /* syscall: sets %cr0.so on error         */
411"        mfcr    4\n"           /* %cr -> low word of return var          */
412"        rlwinm  4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
413"        blr\n"                 /* and return                             */
414".previous\n"
415);
416
417#elif defined(VGP_ppc64be_linux)
418/* Due to the need to return 65 bits of result, this is completely
419   different from the ppc32 case.  The single arg register points to a
420   7-word block containing the syscall # and the 6 args.  The syscall
421   result proper is put in [0] of the block, and %cr0.so is in the
422   bottom bit of [1]. */
423extern void do_syscall_WRK ( ULong* argblock );
424asm(
425".align   2\n"
426".globl   do_syscall_WRK\n"
427".section \".opd\",\"aw\"\n"
428".align   3\n"
429"do_syscall_WRK:\n"
430".quad    .do_syscall_WRK,.TOC.@tocbase,0\n"
431".previous\n"
432".type    .do_syscall_WRK,@function\n"
433".globl   .do_syscall_WRK\n"
434".do_syscall_WRK:\n"
435"        std  3,-16(1)\n"  /* stash arg */
436"        ld   8, 48(3)\n"  /* sc arg 6 */
437"        ld   7, 40(3)\n"  /* sc arg 5 */
438"        ld   6, 32(3)\n"  /* sc arg 4 */
439"        ld   5, 24(3)\n"  /* sc arg 3 */
440"        ld   4, 16(3)\n"  /* sc arg 2 */
441"        ld   0,  0(3)\n"  /* sc number */
442"        ld   3,  8(3)\n"  /* sc arg 1 */
443"        sc\n"             /* result in r3 and cr0.so */
444"        ld   5,-16(1)\n"  /* reacquire argblock ptr (r5 is caller-save) */
445"        std  3,0(5)\n"    /* argblock[0] = r3 */
446"        mfcr 3\n"
447"        srwi 3,3,28\n"
448"        andi. 3,3,1\n"
449"        std  3,8(5)\n"    /* argblock[1] = cr0.s0 & 1 */
450"        blr\n"
451);
452
453#elif defined(VGP_ppc64le_linux)
454/* Due to the need to return 65 bits of result, this is completely
455   different from the ppc32 case.  The single arg register points to a
456   7-word block containing the syscall # and the 6 args.  The syscall
457   result proper is put in [0] of the block, and %cr0.so is in the
458   bottom bit of [1]. */
459extern void do_syscall_WRK ( ULong* argblock );
460/* Little Endian supports ELF version 2.  In the future, it may support
461 * other versions as well.
462 */
463asm(
464".align   2\n"
465".globl   do_syscall_WRK\n"
466".type    do_syscall_WRK,@function\n"
467"do_syscall_WRK:\n"
468"#if  _CALL_ELF == 2"               "\n"
469"0:      addis        2,12,.TOC.-0b@ha\n"
470"        addi         2,2,.TOC.-0b@l\n"
471"        .localentry do_syscall_WRK, .-do_syscall_WRK\n"
472"#endif"                            "\n"
473"        std  3,-16(1)\n"  /* stash arg */
474"        ld   8, 48(3)\n"  /* sc arg 6 */
475"        ld   7, 40(3)\n"  /* sc arg 5 */
476"        ld   6, 32(3)\n"  /* sc arg 4 */
477"        ld   5, 24(3)\n"  /* sc arg 3 */
478"        ld   4, 16(3)\n"  /* sc arg 2 */
479"        ld   0,  0(3)\n"  /* sc number */
480"        ld   3,  8(3)\n"  /* sc arg 1 */
481"        sc\n"             /* result in r3 and cr0.so */
482"        ld   5,-16(1)\n"  /* reacquire argblock ptr (r5 is caller-save) */
483"        std  3,0(5)\n"    /* argblock[0] = r3 */
484"        mfcr 3\n"
485"        srwi 3,3,28\n"
486"        andi. 3,3,1\n"
487"        std  3,8(5)\n"    /* argblock[1] = cr0.s0 & 1 */
488"        blr\n"
489"        .size do_syscall_WRK, .-do_syscall_WRK\n"
490);
491
492#elif defined(VGP_arm_linux)
493/* I think the conventions are:
494   args  in r0 r1 r2 r3 r4 r5
495   sysno in r7
496   return value in r0, w/ same conventions as x86-linux, viz r0 in
497   -4096 .. -1 is an error value.  All other values are success
498   values.
499*/
500extern UWord do_syscall_WRK (
501          UWord a1, UWord a2, UWord a3,
502          UWord a4, UWord a5, UWord a6,
503          UWord syscall_no
504       );
505asm(
506".text\n"
507".globl do_syscall_WRK\n"
508"do_syscall_WRK:\n"
509"         push    {r4, r5, r7}\n"
510"         ldr     r4, [sp, #12]\n"
511"         ldr     r5, [sp, #16]\n"
512"         ldr     r7, [sp, #20]\n"
513"         svc     0x0\n"
514"         pop     {r4, r5, r7}\n"
515"         bx      lr\n"
516".previous\n"
517);
518
519#elif defined(VGP_arm64_linux)
520/* I think the conventions are:
521   args  in r0 r1 r2 r3 r4 r5
522   sysno in r8
523   return value in r0, w/ same conventions as x86-linux, viz r0 in
524   -4096 .. -1 is an error value.  All other values are success
525   values.
526
527   r0 to r5 remain unchanged, but syscall_no is in r6 and needs
528   to be moved to r8 (??)
529*/
530extern UWord do_syscall_WRK (
531          UWord a1, UWord a2, UWord a3,
532          UWord a4, UWord a5, UWord a6,
533          UWord syscall_no
534       );
535asm(
536".text\n"
537".globl do_syscall_WRK\n"
538"do_syscall_WRK:\n"
539"        mov x8, x6\n"
540"        mov x6, 0\n"
541"        mov x7, 0\n"
542"        svc 0\n"
543"        ret\n"
544".previous\n"
545);
546
547#elif defined(VGP_x86_darwin)
548
549/* Incoming args (syscall number + up to 8 args) come in on the stack
550
551   The kernel's syscall calling convention is:
552   * the syscall number goes in eax
553   * the args are passed to the syscall on the stack,
554     pushed onto the stack R->L (that is, the usual x86
555     calling conventions, with the leftmost arg at the lowest
556     address)
557   Call instruction:
558   * UNIX: sysenter
559   * UNIX: int $0x80
560   * MACH: int $0x81
561   * MDEP: int $0x82
562   Note that the call type can be determined from the syscall number;
563   there is no need to inspect the actual instruction.  Although obviously
564   the instruction must match.
565   Return value:
566   * MACH,MDEP: the return value comes back in eax
567   * UNIX: the return value comes back in edx:eax (hi32:lo32)
568   Error:
569   * MACH,MDEP: no error is returned
570   * UNIX: the carry flag indicates success or failure
571
572   nb here, sizeof(UWord) == sizeof(UInt)
573*/
574
575__private_extern__ ULong
576do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
577                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
578                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
579                      UWord syscall_no, /* 36(esp) */
580                      /*OUT*/UInt* errflag /* 40(esp) */ );
581// Unix syscall: 64-bit return in edx:eax, with LSB in eax
582// error indicated by carry flag: clear=good, set=bad
583asm(".private_extern _do_syscall_unix_WRK\n"
584    "_do_syscall_unix_WRK:\n"
585    "        movl    40(%esp), %ecx   \n"  /* assume syscall success */
586    "        movl    $0, (%ecx)       \n"
587    "        movl    36(%esp), %eax   \n"
588    "        int     $0x80            \n"
589    "        jnc     1f               \n"  /* jump if success */
590    "        movl    40(%esp), %ecx   \n"  /* syscall failed - set *errflag */
591    "        movl    $1, (%ecx)       \n"
592    "    1:  ret                      \n"
593    );
594
595__private_extern__ UInt
596do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
597                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
598                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
599                      UWord syscall_no /* 36(esp) */ );
600// Mach trap: 32-bit result in %eax, no error flag
601asm(".private_extern _do_syscall_mach_WRK\n"
602    "_do_syscall_mach_WRK:\n"
603    "        movl    36(%esp), %eax   \n"
604    "        int     $0x81            \n"
605    "        ret                      \n"
606    );
607
608__private_extern__ UInt
609do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
610                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
611                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
612                      UWord syscall_no /* 36(esp) */ );
613// mdep trap: 32-bit result in %eax, no error flag
614asm(
615    ".private_extern _do_syscall_mdep_WRK\n"
616    "_do_syscall_mdep_WRK:\n"
617    "        movl    36(%esp), %eax   \n"
618    "        int     $0x82            \n"
619    "        ret                      \n"
620    );
621
622
623#elif defined(VGP_amd64_darwin)
624
625/* Incoming args (syscall number + up to 8 args) come in registers and stack
626
627   The kernel's syscall calling convention is:
628   * the syscall number goes in rax
629   * the args are passed to the syscall in registers and the stack
630   * the call instruction is 'syscall'
631   Return value:
632   * MACH,MDEP: the return value comes back in rax
633   * UNIX: the return value comes back in rdx:rax (hi64:lo64)
634   Error:
635   * MACH,MDEP: no error is returned
636   * UNIX: the carry flag indicates success or failure
637
638   nb here, sizeof(UWord) == sizeof(ULong)
639*/
640
641__private_extern__ UWord
642do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
643                      UWord a4, UWord a5, UWord a6, /* rcx, r8,  r9 */
644                      UWord a7, UWord a8,           /* 8(rsp), 16(rsp) */
645                      UWord syscall_no,             /* 24(rsp) */
646                      /*OUT*/ULong* errflag,        /* 32(rsp) */
647                      /*OUT*/ULong* res2 );         /* 40(rsp) */
648// Unix syscall: 128-bit return in rax:rdx, with LSB in rax
649// error indicated by carry flag: clear=good, set=bad
650asm(".private_extern _do_syscall_unix_WRK\n"
651    "_do_syscall_unix_WRK:\n"
652    "        movq    %rcx, %r10       \n"  /* pass rcx in r10 instead */
653    "        movq    32(%rsp), %rax   \n"  /* assume syscall success */
654    "        movq    $0, (%rax)       \n"
655    "        movq    24(%rsp), %rax   \n"  /* load syscall_no */
656    "        syscall                  \n"
657    "        jnc     1f               \n"  /* jump if success */
658    "        movq    32(%rsp), %rcx   \n"  /* syscall failed - set *errflag */
659    "        movq    $1, (%rcx)       \n"
660    "    1:  movq    40(%rsp), %rcx   \n"  /* save 2nd result word */
661    "        movq    %rdx, (%rcx)     \n"
662    "        retq                     \n"  /* return 1st result word */
663    );
664
665__private_extern__ UWord
666do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
667                      UWord a4, UWord a5, UWord a6, /* rcx, r8,  r9 */
668                      UWord a7, UWord a8,           /* 8(rsp), 16(rsp) */
669                      UWord syscall_no );           /* 24(rsp) */
670// Mach trap: 64-bit result, no error flag
671asm(".private_extern _do_syscall_mach_WRK\n"
672    "_do_syscall_mach_WRK:\n"
673    "        movq    %rcx, %r10       \n"  /* pass rcx in r10 instead */
674    "        movq    24(%rsp), %rax   \n"  /* load syscall_no */
675    "        syscall                  \n"
676    "        retq                     \n"
677    );
678
679#elif defined(VGP_s390x_linux)
680
681static UWord do_syscall_WRK (
682   UWord syscall_no,
683   UWord arg1, UWord arg2, UWord arg3,
684   UWord arg4, UWord arg5, UWord arg6
685   )
686{
687   register UWord __arg1 asm("2") = arg1;
688   register UWord __arg2 asm("3") = arg2;
689   register UWord __arg3 asm("4") = arg3;
690   register UWord __arg4 asm("5") = arg4;
691   register UWord __arg5 asm("6") = arg5;
692   register UWord __arg6 asm("7") = arg6;
693   register ULong __svcres asm("2");
694
695   __asm__ __volatile__ (
696                 "lgr %%r1,%1\n\t"
697                 "svc 0\n\t"
698		: "=d" (__svcres)
699		: "a" (syscall_no),
700		  "0" (__arg1),
701		  "d" (__arg2),
702		  "d" (__arg3),
703		  "d" (__arg4),
704		  "d" (__arg5),
705		  "d" (__arg6)
706		: "1", "cc", "memory");
707
708   return (UWord) (__svcres);
709}
710
711#elif defined(VGP_mips32_linux)
712/* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
713
714   The syscall number goes in v0.  The args are passed to the syscall in
715   the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
716
717   (a3 != 0) flags an error.
718   We return the syscall return value in v0.
719   MIPS version
720*/
721extern int do_syscall_WRK (
722          int a1, int a2, int a3,
723          int a4, int a5, int a6, int syscall_no, UWord *err,
724          UWord *valHi, UWord* valLo
725       );
726asm(
727".globl do_syscall_WRK\n"
728".ent do_syscall_WRK\n"
729".text\n"
730"do_syscall_WRK:\n"
731"   lw $2, 24($29)\n"
732"   syscall\n"
733"   lw $8, 28($29)\n"
734"   sw $7, ($8)\n"
735"   lw $8, 32($29)\n"
736"   sw $3, ($8)\n"   // store valHi
737"   lw $8, 36($29)\n"
738"   sw $2, ($8)\n"   // store valLo
739"   jr $31\n"
740"   nop\n"
741".previous\n"
742".end do_syscall_WRK\n"
743);
744
745#elif defined(VGP_mips64_linux)
746extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
747                              UWord a6, UWord syscall_no, ULong* V1_val );
748asm (
749".text\n"
750".globl do_syscall_WRK\n"
751"do_syscall_WRK:\n"
752"   daddiu $29, $29, -8\n"
753"   sd $11, 0($29)\n"
754"   move $2, $10\n"
755"   syscall\n"
756"   ld $11, 0($29)\n"
757"   daddiu $29, $29, 8\n"
758"   sd $3, 0($11)\n"  /* store vale of v1 in last param */
759"   sd $7, 8($11)\n"  /* store vale of a3 in last param */
760"   jr $31\n"
761".previous\n"
762);
763
764#elif defined(VGP_tilegx_linux)
765extern UWord do_syscall_WRK (
766          UWord syscall_no,
767          UWord a1, UWord a2, UWord a3,
768          UWord a4, UWord a5, UWord a6
769       );
770asm(
771    ".text\n"
772    "do_syscall_WRK:\n"
773    "move  r10, r0\n"
774    "move  r0,  r1\n"
775    "move  r1,  r2\n"
776    "move  r2,  r3\n"
777    "move  r3,  r4\n"
778    "move  r4,  r5\n"
779    "move  r5,  r6\n"
780    "swint1\n"
781    "jrp   lr\n"
782    ".previous\n"
783    );
784
785#else
786#  error Unknown platform
787#endif
788
789
790/* Finally, the generic code.  This sends the call to the right
791   helper. */
792
793SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
794                                      UWord a4, UWord a5, UWord a6,
795                                      UWord a7, UWord a8 )
796{
797#  if defined(VGP_x86_linux)
798   UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
799   return VG_(mk_SysRes_x86_linux)( val );
800
801#  elif defined(VGP_amd64_linux)
802   UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
803   return VG_(mk_SysRes_amd64_linux)( val );
804
805#  elif defined(VGP_ppc32_linux)
806   ULong ret     = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
807   UInt  val     = (UInt)(ret>>32);
808   UInt  cr0so   = (UInt)(ret);
809   return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
810
811#  elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
812   ULong argblock[7];
813   argblock[0] = sysno;
814   argblock[1] = a1;
815   argblock[2] = a2;
816   argblock[3] = a3;
817   argblock[4] = a4;
818   argblock[5] = a5;
819   argblock[6] = a6;
820   do_syscall_WRK( &argblock[0] );
821   return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
822
823#  elif defined(VGP_arm_linux)
824   UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
825   return VG_(mk_SysRes_arm_linux)( val );
826
827#  elif defined(VGP_arm64_linux)
828   UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
829   return VG_(mk_SysRes_arm64_linux)( val );
830
831#  elif defined(VGP_x86_darwin)
832   UInt  wLO = 0, wHI = 0, err = 0;
833   ULong u64;
834   UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
835   switch (scclass) {
836      case VG_DARWIN_SYSCALL_CLASS_UNIX:
837         u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
838                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
839         wLO = (UInt)u64;
840         wHI = (UInt)(u64 >> 32);
841         break;
842      case VG_DARWIN_SYSCALL_CLASS_MACH:
843         wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
844                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
845         err = 0;
846         break;
847      case VG_DARWIN_SYSCALL_CLASS_MDEP:
848         wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
849                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
850         err = 0;
851         break;
852      default:
853         vg_assert(0);
854         break;
855   }
856   return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
857
858#  elif defined(VGP_amd64_darwin)
859   ULong wLO = 0, wHI = 0, err = 0;
860   UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
861   switch (scclass) {
862      case VG_DARWIN_SYSCALL_CLASS_UNIX:
863         wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
864                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
865         break;
866      case VG_DARWIN_SYSCALL_CLASS_MACH:
867      case VG_DARWIN_SYSCALL_CLASS_MDEP:
868         wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
869                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
870         err = 0;
871         break;
872      default:
873         vg_assert(0);
874         break;
875   }
876   return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
877
878#elif defined(VGP_s390x_linux)
879   UWord val;
880
881   if (sysno == __NR_mmap) {
882     ULong argbuf[6];
883
884     argbuf[0] = a1;
885     argbuf[1] = a2;
886     argbuf[2] = a3;
887     argbuf[3] = a4;
888     argbuf[4] = a5;
889     argbuf[5] = a6;
890     val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
891   } else {
892     val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
893   }
894
895   return VG_(mk_SysRes_s390x_linux)( val );
896
897#elif defined(VGP_mips32_linux)
898   UWord err   = 0;
899   UWord valHi = 0;
900   UWord valLo = 0;
901   (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
902   return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
903
904#elif defined(VGP_mips64_linux)
905   ULong v1_a3[2];
906   v1_a3[0] = 0xFF00;
907   v1_a3[1] = 0xFF00;
908   ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3);
909   ULong V1 = (ULong)v1_a3[0];
910   ULong A3 = (ULong)v1_a3[1];
911   return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
912
913#  elif defined(VGP_tilegx_linux)
914   UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
915
916   return VG_(mk_SysRes_tilegx_linux)( val );
917
918#else
919#  error Unknown platform
920#endif
921}
922
923/* ---------------------------------------------------------------------
924   Names of errors.
925   ------------------------------------------------------------------ */
926
927/* Return a string which gives the name of an error value.  Note,
928   unlike the standard C syserror fn, the returned string is not
929   malloc-allocated or writable -- treat it as a constant.
930   TODO: implement this properly. */
931
932const HChar* VG_(strerror) ( UWord errnum )
933{
934   switch (errnum) {
935   case VKI_EPERM:       return "Operation not permitted";
936   case VKI_ENOENT:      return "No such file or directory";
937   case VKI_ESRCH:       return "No such process";
938   case VKI_EINTR:       return "Interrupted system call";
939   case VKI_EIO:         return "Input/output error";
940   case VKI_ENXIO:       return "No such device or address";
941   case VKI_E2BIG:       return "Argument list too long";
942   case VKI_ENOEXEC:     return "Exec format error";
943   case VKI_EBADF:       return "Bad file descriptor";
944   case VKI_ECHILD:      return "No child processes";
945   case VKI_EAGAIN:      return "Resource temporarily unavailable";
946   case VKI_ENOMEM:      return "Cannot allocate memory";
947   case VKI_EACCES:      return "Permission denied";
948   case VKI_EFAULT:      return "Bad address";
949   case VKI_ENOTBLK:     return "Block device required";
950   case VKI_EBUSY:       return "Device or resource busy";
951   case VKI_EEXIST:      return "File exists";
952   case VKI_EXDEV:       return "Invalid cross-device link";
953   case VKI_ENODEV:      return "No such device";
954   case VKI_ENOTDIR:     return "Not a directory";
955   case VKI_EISDIR:      return "Is a directory";
956   case VKI_EINVAL:      return "Invalid argument";
957   case VKI_ENFILE:      return "Too many open files in system";
958   case VKI_EMFILE:      return "Too many open files";
959   case VKI_ENOTTY:      return "Inappropriate ioctl for device";
960   case VKI_ETXTBSY:     return "Text file busy";
961   case VKI_EFBIG:       return "File too large";
962   case VKI_ENOSPC:      return "No space left on device";
963   case VKI_ESPIPE:      return "Illegal seek";
964   case VKI_EROFS:       return "Read-only file system";
965   case VKI_EMLINK:      return "Too many links";
966   case VKI_EPIPE:       return "Broken pipe";
967   case VKI_EDOM:        return "Numerical argument out of domain";
968   case VKI_ERANGE:      return "Numerical result out of range";
969
970   case VKI_ENOSYS:      return "Function not implemented";
971   case VKI_EOVERFLOW:   return "Value too large for defined data type";
972#     if defined(VKI_ERESTARTSYS)
973      case VKI_ERESTARTSYS: return "ERESTARTSYS";
974#     endif
975   default:              return "VG_(strerror): unknown error";
976   }
977}
978
979
980/*--------------------------------------------------------------------*/
981/*--- end                                                          ---*/
982/*--------------------------------------------------------------------*/
983