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 
VG_(mk_SysRes_x86_linux)63 SysRes 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 .. */
VG_(mk_SysRes_amd64_linux)75 SysRes 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 
VG_(mk_SysRes_tilegx_linux)86 SysRes 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 */
VG_(mk_SysRes_ppc32_linux)99 SysRes 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 */
VG_(mk_SysRes_ppc64_linux)107 SysRes 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 
VG_(mk_SysRes_s390x_linux)114 SysRes 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 
VG_(mk_SysRes_arm_linux)125 SysRes 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 
VG_(mk_SysRes_arm64_linux)136 SysRes 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 */
VG_(mk_SysRes_mips32_linux)149 SysRes 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 */
VG_(mk_SysRes_mips64_linux)158 SysRes 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. */
VG_(mk_SysRes_Error)168 SysRes 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 
VG_(mk_SysRes_Success)178 SysRes 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. */
VG_(mk_SysRes_x86_darwin)192 SysRes 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 
VG_(mk_SysRes_amd64_darwin)225 SysRes 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. */
VG_(mk_SysRes_Error)261 SysRes 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 
VG_(mk_SysRes_Success)269 SysRes 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 */
299 extern UWord do_syscall_WRK (
300           UWord syscall_no,
301           UWord a1, UWord a2, UWord a3,
302           UWord a4, UWord a5, UWord a6
303        );
304 asm(
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 */
359 extern UWord do_syscall_WRK (
360           UWord syscall_no,
361           UWord a1, UWord a2, UWord a3,
362           UWord a4, UWord a5, UWord a6
363        );
364 asm(
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 */
394 extern ULong do_syscall_WRK (
395           UWord syscall_no,
396           UWord a1, UWord a2, UWord a3,
397           UWord a4, UWord a5, UWord a6
398        );
399 asm(
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]. */
423 extern void do_syscall_WRK ( ULong* argblock );
424 asm(
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]. */
459 extern 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  */
463 asm(
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 */
500 extern UWord do_syscall_WRK (
501           UWord a1, UWord a2, UWord a3,
502           UWord a4, UWord a5, UWord a6,
503           UWord syscall_no
504        );
505 asm(
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 */
530 extern UWord do_syscall_WRK (
531           UWord a1, UWord a2, UWord a3,
532           UWord a4, UWord a5, UWord a6,
533           UWord syscall_no
534        );
535 asm(
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
576 do_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
583 asm(".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
596 do_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
601 asm(".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
609 do_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
614 asm(
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
642 do_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
650 asm(".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
666 do_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
671 asm(".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 
do_syscall_WRK(UWord syscall_no,UWord arg1,UWord arg2,UWord arg3,UWord arg4,UWord arg5,UWord arg6)681 static 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 */
721 extern 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        );
726 asm(
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)
746 extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
747                               UWord a6, UWord syscall_no, ULong* V1_val );
748 asm (
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)
765 extern UWord do_syscall_WRK (
766           UWord syscall_no,
767           UWord a1, UWord a2, UWord a3,
768           UWord a4, UWord a5, UWord a6
769        );
770 asm(
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 
VG_(do_syscall)793 SysRes 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 
VG_(strerror)932 const 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