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