tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_syscall.c
blob8cc0564ab403ccb8ef568f2d936519d237392e7e
2 /*--------------------------------------------------------------------*/
3 /*--- Doing syscalls. m_syscall.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2013 Julian Seward
11 jseward@acm.org
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_syscall.h"
37 /* ---------------------------------------------------------------------
38 Building syscall return values.
39 ------------------------------------------------------------------ */
41 /* Make a SysRes value from a syscall return value. This is
42 platform specific. */
44 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
46 SysRes 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;
55 SysRes 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;
64 /* Generic constructors. */
65 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
66 SysRes r;
67 r._isError = True;
68 r._val = err;
69 r._valEx = 0;
70 return r;
73 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
74 SysRes r;
75 r._isError = False;
76 r._val = res;
77 r._valEx = 0;
78 return r;
81 SysRes 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;
90 #elif defined(VGO_linux) \
91 && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux)
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
99 Linux uses a negative return value to indicate syscall errors,
100 unlike most Unices, which use the condition codes' carry flag.
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.
111 SysRes 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;
119 return res;
122 /* Similarly .. */
123 SysRes 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;
131 return res;
134 SysRes VG_(mk_SysRes_tilegx_linux) ( Long val ) {
135 SysRes res;
136 res._isError = val >= -4095 && val <= -1;
137 if (res._isError) {
138 res._val = (ULong)(-val);
139 } else {
140 res._val = (ULong)val;
142 return res;
145 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
146 /* Note this must be in the bottom bit of the second arg */
147 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
148 SysRes res;
149 res._isError = (cr0so & 1) != 0;
150 res._val = val;
151 return res;
154 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
155 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
156 SysRes res;
157 res._isError = (cr0so & 1) != 0;
158 res._val = val;
159 return res;
162 SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
163 SysRes res;
164 res._isError = val >= -4095 && val <= -1;
165 if (res._isError) {
166 res._val = -val;
167 } else {
168 res._val = val;
170 return res;
173 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
174 SysRes res;
175 res._isError = val >= -4095 && val <= -1;
176 if (res._isError) {
177 res._val = (UInt)(-val);
178 } else {
179 res._val = (UInt)val;
181 return res;
184 SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
185 SysRes res;
186 res._isError = val >= -4095 && val <= -1;
187 if (res._isError) {
188 res._val = (ULong)(-val);
189 } else {
190 res._val = (ULong)val;
192 return res;
195 /* Generic constructors. */
196 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
197 SysRes r;
198 r._isError = True;
199 r._val = err;
200 return r;
203 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
204 SysRes r;
205 r._isError = False;
206 r._val = res;
207 return r;
211 #elif defined(VGO_darwin)
213 /* Darwin: Some syscalls return a double-word result. */
214 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
215 UInt wHI, UInt wLO )
217 SysRes res;
218 res._wHI = 0;
219 res._wLO = 0;
220 res._mode = 0; /* invalid */
221 vg_assert(isErr == False || isErr == True);
222 vg_assert(sizeof(UWord) == sizeof(UInt));
223 switch (scclass) {
224 case VG_DARWIN_SYSCALL_CLASS_UNIX:
225 res._wLO = wLO;
226 res._wHI = wHI;
227 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
228 break;
229 case VG_DARWIN_SYSCALL_CLASS_MACH:
230 vg_assert(!isErr);
231 vg_assert(wHI == 0);
232 res._wLO = wLO;
233 res._mode = SysRes_MACH;
234 break;
235 case VG_DARWIN_SYSCALL_CLASS_MDEP:
236 vg_assert(!isErr);
237 vg_assert(wHI == 0);
238 res._wLO = wLO;
239 res._mode = SysRes_MDEP;
240 break;
241 default:
242 vg_assert(0);
244 return res;
247 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
248 ULong wHI, ULong wLO )
250 SysRes res;
251 res._wHI = 0;
252 res._wLO = 0;
253 res._mode = 0; /* invalid */
254 vg_assert(isErr == False || isErr == True);
255 vg_assert(sizeof(UWord) == sizeof(ULong));
256 switch (scclass) {
257 case VG_DARWIN_SYSCALL_CLASS_UNIX:
258 res._wLO = wLO;
259 res._wHI = wHI;
260 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
261 break;
262 case VG_DARWIN_SYSCALL_CLASS_MACH:
263 vg_assert(!isErr);
264 vg_assert(wHI == 0);
265 res._wLO = wLO;
266 res._mode = SysRes_MACH;
267 break;
268 case VG_DARWIN_SYSCALL_CLASS_MDEP:
269 vg_assert(!isErr);
270 vg_assert(wHI == 0);
271 res._wLO = wLO;
272 res._mode = SysRes_MDEP;
273 break;
274 default:
275 vg_assert(0);
277 return res;
280 /* Generic constructors. We assume (without checking if this makes
281 any sense, from the caller's point of view) that these are for the
282 UNIX style of syscall. */
283 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
284 SysRes r;
285 r._wHI = 0;
286 r._wLO = err;
287 r._mode = SysRes_UNIX_ERR;
288 return r;
291 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
292 SysRes r;
293 r._wHI = 0;
294 r._wLO = res;
295 r._mode = SysRes_UNIX_OK;
296 return r;
300 #elif defined(VGO_solaris)
302 /* Generic constructors. */
303 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
304 SysRes r;
305 r._val = err;
306 r._val2 = 0;
307 r._isError = True;
308 return r;
311 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
312 SysRes r;
313 r._val = res;
314 r._val2 = 0;
315 r._isError = False;
316 return r;
319 SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 )
321 SysRes res;
323 // stay sane
324 vg_assert(isErr == True || isErr == False);
326 res._val = val;
327 res._val2 = val2;
328 res._isError = isErr;
329 return res;
332 SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 )
334 SysRes res;
336 // stay sane
337 vg_assert(isErr == True || isErr == False);
339 res._val = val;
340 res._val2 = val2;
341 res._isError = isErr;
342 return res;
345 #else
346 # error "Unknown OS"
347 #endif
350 /* ---------------------------------------------------------------------
351 VG_(do_syscall): A function for doing syscalls.
352 ------------------------------------------------------------------ */
354 #if defined(VGP_x86_linux)
355 /* Incoming args (syscall number + up to 6 args) come on the stack.
356 (ie. the C calling convention).
358 The syscall number goes in %eax. The args are passed to the syscall in
359 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
360 calling convention.
362 %eax gets the return value. Not sure which registers the kernel
363 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
364 %ebp).
366 extern UWord do_syscall_WRK (
367 UWord syscall_no,
368 UWord a1, UWord a2, UWord a3,
369 UWord a4, UWord a5, UWord a6
371 asm(
372 ".text\n"
373 ".globl do_syscall_WRK\n"
374 "do_syscall_WRK:\n"
375 " .cfi_startproc\n"
376 " push %esi\n"
377 " .cfi_adjust_cfa_offset 4\n"
378 " .cfi_offset %esi, -8\n"
379 " push %edi\n"
380 " .cfi_adjust_cfa_offset 4\n"
381 " .cfi_offset %edi, -12\n"
382 " push %ebx\n"
383 " .cfi_adjust_cfa_offset 4\n"
384 " .cfi_offset %ebx, -16\n"
385 " push %ebp\n"
386 " .cfi_adjust_cfa_offset 4\n"
387 " .cfi_offset %ebp, -20\n"
388 " movl 16+ 4(%esp),%eax\n"
389 " movl 16+ 8(%esp),%ebx\n"
390 " movl 16+12(%esp),%ecx\n"
391 " movl 16+16(%esp),%edx\n"
392 " movl 16+20(%esp),%esi\n"
393 " movl 16+24(%esp),%edi\n"
394 " movl 16+28(%esp),%ebp\n"
395 " int $0x80\n"
396 " popl %ebp\n"
397 " .cfi_adjust_cfa_offset -4\n"
398 " .cfi_restore %ebp\n"
399 " popl %ebx\n"
400 " .cfi_adjust_cfa_offset -4\n"
401 " .cfi_restore %ebx\n"
402 " popl %edi\n"
403 " .cfi_adjust_cfa_offset -4\n"
404 " .cfi_restore %edi\n"
405 " popl %esi\n"
406 " .cfi_adjust_cfa_offset -4\n"
407 " .cfi_restore %esi\n"
408 " ret\n"
409 " .cfi_endproc\n"
410 ".previous\n"
413 #elif defined(VGP_amd64_linux)
414 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
415 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
416 calling convention).
418 The syscall number goes in %rax. The args are passed to the syscall in
419 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
420 ie. the kernel's syscall calling convention.
422 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
423 no matter, they are caller-save (the syscall clobbers no callee-save
424 regs, so we don't have to do any register saving/restoring).
426 extern UWord do_syscall_WRK (
427 UWord syscall_no,
428 UWord a1, UWord a2, UWord a3,
429 UWord a4, UWord a5, UWord a6
431 asm(
432 ".text\n"
433 ".globl do_syscall_WRK\n"
434 "do_syscall_WRK:\n"
435 /* Convert function calling convention --> syscall calling
436 convention */
437 " movq %rdi, %rax\n"
438 " movq %rsi, %rdi\n"
439 " movq %rdx, %rsi\n"
440 " movq %rcx, %rdx\n"
441 " movq %r8, %r10\n"
442 " movq %r9, %r8\n"
443 " movq 8(%rsp), %r9\n" /* last arg from stack */
444 " syscall\n"
445 " ret\n"
446 ".previous\n"
449 #elif defined(VGP_ppc32_linux)
450 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
452 The syscall number goes in %r0. The args are passed to the syscall in
453 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
455 The %cr0.so bit flags an error.
456 We return the syscall return value in %r3, and the %cr0.so in
457 the lowest bit of %r4.
458 We return a ULong, of which %r3 is the high word, and %r4 the low.
459 No callee-save regs are clobbered, so no saving/restoring is needed.
461 extern ULong do_syscall_WRK (
462 UWord syscall_no,
463 UWord a1, UWord a2, UWord a3,
464 UWord a4, UWord a5, UWord a6
466 asm(
467 ".text\n"
468 ".globl do_syscall_WRK\n"
469 "do_syscall_WRK:\n"
470 " mr 0,3\n"
471 " mr 3,4\n"
472 " mr 4,5\n"
473 " mr 5,6\n"
474 " mr 6,7\n"
475 " mr 7,8\n"
476 " mr 8,9\n"
477 " sc\n" /* syscall: sets %cr0.so on error */
478 " mfcr 4\n" /* %cr -> low word of return var */
479 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
480 " blr\n" /* and return */
481 ".previous\n"
484 #elif defined(VGP_ppc64be_linux)
485 /* Due to the need to return 65 bits of result, this is completely
486 different from the ppc32 case. The single arg register points to a
487 7-word block containing the syscall # and the 6 args. The syscall
488 result proper is put in [0] of the block, and %cr0.so is in the
489 bottom bit of [1]. */
490 extern void do_syscall_WRK ( ULong* argblock );
491 asm(
492 ".align 2\n"
493 ".globl do_syscall_WRK\n"
494 ".section \".opd\",\"aw\"\n"
495 ".align 3\n"
496 "do_syscall_WRK:\n"
497 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
498 ".previous\n"
499 ".type .do_syscall_WRK,@function\n"
500 ".globl .do_syscall_WRK\n"
501 ".do_syscall_WRK:\n"
502 " std 3,-16(1)\n" /* stash arg */
503 " ld 8, 48(3)\n" /* sc arg 6 */
504 " ld 7, 40(3)\n" /* sc arg 5 */
505 " ld 6, 32(3)\n" /* sc arg 4 */
506 " ld 5, 24(3)\n" /* sc arg 3 */
507 " ld 4, 16(3)\n" /* sc arg 2 */
508 " ld 0, 0(3)\n" /* sc number */
509 " ld 3, 8(3)\n" /* sc arg 1 */
510 " sc\n" /* result in r3 and cr0.so */
511 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
512 " std 3,0(5)\n" /* argblock[0] = r3 */
513 " mfcr 3\n"
514 " srwi 3,3,28\n"
515 " andi. 3,3,1\n"
516 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
517 " blr\n"
520 #elif defined(VGP_ppc64le_linux)
521 /* Due to the need to return 65 bits of result, this is completely
522 different from the ppc32 case. The single arg register points to a
523 7-word block containing the syscall # and the 6 args. The syscall
524 result proper is put in [0] of the block, and %cr0.so is in the
525 bottom bit of [1]. */
526 extern void do_syscall_WRK ( ULong* argblock );
527 /* Little Endian supports ELF version 2. In the future, it may support
528 * other versions as well.
530 asm(
531 ".align 2\n"
532 ".globl do_syscall_WRK\n"
533 ".type do_syscall_WRK,@function\n"
534 "do_syscall_WRK:\n"
535 "#if _CALL_ELF == 2" "\n"
536 "0: addis 2,12,.TOC.-0b@ha\n"
537 " addi 2,2,.TOC.-0b@l\n"
538 " .localentry do_syscall_WRK, .-do_syscall_WRK\n"
539 "#endif" "\n"
540 " std 3,-16(1)\n" /* stash arg */
541 " ld 8, 48(3)\n" /* sc arg 6 */
542 " ld 7, 40(3)\n" /* sc arg 5 */
543 " ld 6, 32(3)\n" /* sc arg 4 */
544 " ld 5, 24(3)\n" /* sc arg 3 */
545 " ld 4, 16(3)\n" /* sc arg 2 */
546 " ld 0, 0(3)\n" /* sc number */
547 " ld 3, 8(3)\n" /* sc arg 1 */
548 " sc\n" /* result in r3 and cr0.so */
549 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
550 " std 3,0(5)\n" /* argblock[0] = r3 */
551 " mfcr 3\n"
552 " srwi 3,3,28\n"
553 " andi. 3,3,1\n"
554 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
555 " blr\n"
556 " .size do_syscall_WRK, .-do_syscall_WRK\n"
559 #elif defined(VGP_arm_linux)
560 /* I think the conventions are:
561 args in r0 r1 r2 r3 r4 r5
562 sysno in r7
563 return value in r0, w/ same conventions as x86-linux, viz r0 in
564 -4096 .. -1 is an error value. All other values are success
565 values.
567 extern UWord do_syscall_WRK (
568 UWord a1, UWord a2, UWord a3,
569 UWord a4, UWord a5, UWord a6,
570 UWord syscall_no
572 asm(
573 ".text\n"
574 ".globl do_syscall_WRK\n"
575 "do_syscall_WRK:\n"
576 " push {r4, r5, r7}\n"
577 " ldr r4, [sp, #12]\n"
578 " ldr r5, [sp, #16]\n"
579 " ldr r7, [sp, #20]\n"
580 " svc 0x0\n"
581 " pop {r4, r5, r7}\n"
582 " bx lr\n"
583 ".previous\n"
586 #elif defined(VGP_arm64_linux)
587 /* I think the conventions are:
588 args in r0 r1 r2 r3 r4 r5
589 sysno in r8
590 return value in r0, w/ same conventions as x86-linux, viz r0 in
591 -4096 .. -1 is an error value. All other values are success
592 values.
594 r0 to r5 remain unchanged, but syscall_no is in r6 and needs
595 to be moved to r8 (??)
597 extern UWord do_syscall_WRK (
598 UWord a1, UWord a2, UWord a3,
599 UWord a4, UWord a5, UWord a6,
600 UWord syscall_no
602 asm(
603 ".text\n"
604 ".globl do_syscall_WRK\n"
605 "do_syscall_WRK:\n"
606 " mov x8, x6\n"
607 " mov x6, 0\n"
608 " mov x7, 0\n"
609 " svc 0\n"
610 " ret\n"
611 ".previous\n"
614 #elif defined(VGP_x86_darwin)
616 /* Incoming args (syscall number + up to 8 args) come in on the stack
618 The kernel's syscall calling convention is:
619 * the syscall number goes in eax
620 * the args are passed to the syscall on the stack,
621 pushed onto the stack R->L (that is, the usual x86
622 calling conventions, with the leftmost arg at the lowest
623 address)
624 Call instruction:
625 * UNIX: sysenter
626 * UNIX: int $0x80
627 * MACH: int $0x81
628 * MDEP: int $0x82
629 Note that the call type can be determined from the syscall number;
630 there is no need to inspect the actual instruction. Although obviously
631 the instruction must match.
632 Return value:
633 * MACH,MDEP: the return value comes back in eax
634 * UNIX: the return value comes back in edx:eax (hi32:lo32)
635 Error:
636 * MACH,MDEP: no error is returned
637 * UNIX: the carry flag indicates success or failure
639 nb here, sizeof(UWord) == sizeof(UInt)
642 __private_extern__ ULong
643 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
644 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
645 UWord a7, UWord a8, /* 28(esp)..32(esp) */
646 UWord syscall_no, /* 36(esp) */
647 /*OUT*/UInt* errflag /* 40(esp) */ );
648 // Unix syscall: 64-bit return in edx:eax, with LSB in eax
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 " movl 40(%esp), %ecx \n" /* assume syscall success */
653 " movl $0, (%ecx) \n"
654 " movl 36(%esp), %eax \n"
655 " int $0x80 \n"
656 " jnc 1f \n" /* jump if success */
657 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
658 " movl $1, (%ecx) \n"
659 " 1: ret \n"
662 __private_extern__ UInt
663 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
664 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
665 UWord a7, UWord a8, /* 28(esp)..32(esp) */
666 UWord syscall_no /* 36(esp) */ );
667 // Mach trap: 32-bit result in %eax, no error flag
668 asm(".private_extern _do_syscall_mach_WRK\n"
669 "_do_syscall_mach_WRK:\n"
670 " movl 36(%esp), %eax \n"
671 " int $0x81 \n"
672 " ret \n"
675 __private_extern__ UInt
676 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
677 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
678 UWord a7, UWord a8, /* 28(esp)..32(esp) */
679 UWord syscall_no /* 36(esp) */ );
680 // mdep trap: 32-bit result in %eax, no error flag
681 asm(
682 ".private_extern _do_syscall_mdep_WRK\n"
683 "_do_syscall_mdep_WRK:\n"
684 " movl 36(%esp), %eax \n"
685 " int $0x82 \n"
686 " ret \n"
690 #elif defined(VGP_amd64_darwin)
692 /* Incoming args (syscall number + up to 8 args) come in registers and stack
694 The kernel's syscall calling convention is:
695 * the syscall number goes in rax
696 * the args are passed to the syscall in registers and the stack
697 * the call instruction is 'syscall'
698 Return value:
699 * MACH,MDEP: the return value comes back in rax
700 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
701 Error:
702 * MACH,MDEP: no error is returned
703 * UNIX: the carry flag indicates success or failure
705 nb here, sizeof(UWord) == sizeof(ULong)
708 __private_extern__ UWord
709 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
710 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
711 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
712 UWord syscall_no, /* 24(rsp) */
713 /*OUT*/ULong* errflag, /* 32(rsp) */
714 /*OUT*/ULong* res2 ); /* 40(rsp) */
715 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax
716 // error indicated by carry flag: clear=good, set=bad
717 asm(".private_extern _do_syscall_unix_WRK\n"
718 "_do_syscall_unix_WRK:\n"
719 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
720 " movq 32(%rsp), %rax \n" /* assume syscall success */
721 " movq $0, (%rax) \n"
722 " movq 24(%rsp), %rax \n" /* load syscall_no */
723 " syscall \n"
724 " jnc 1f \n" /* jump if success */
725 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
726 " movq $1, (%rcx) \n"
727 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
728 " movq %rdx, (%rcx) \n"
729 " retq \n" /* return 1st result word */
732 __private_extern__ UWord
733 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
734 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
735 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
736 UWord syscall_no ); /* 24(rsp) */
737 // Mach trap: 64-bit result, no error flag
738 asm(".private_extern _do_syscall_mach_WRK\n"
739 "_do_syscall_mach_WRK:\n"
740 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
741 " movq 24(%rsp), %rax \n" /* load syscall_no */
742 " syscall \n"
743 " retq \n"
746 #elif defined(VGP_s390x_linux)
748 static UWord do_syscall_WRK (
749 UWord syscall_no,
750 UWord arg1, UWord arg2, UWord arg3,
751 UWord arg4, UWord arg5, UWord arg6
754 register UWord __arg1 asm("2") = arg1;
755 register UWord __arg2 asm("3") = arg2;
756 register UWord __arg3 asm("4") = arg3;
757 register UWord __arg4 asm("5") = arg4;
758 register UWord __arg5 asm("6") = arg5;
759 register UWord __arg6 asm("7") = arg6;
760 register ULong __svcres asm("2");
762 __asm__ __volatile__ (
763 "lgr %%r1,%1\n\t"
764 "svc 0\n\t"
765 : "=d" (__svcres)
766 : "a" (syscall_no),
767 "0" (__arg1),
768 "d" (__arg2),
769 "d" (__arg3),
770 "d" (__arg4),
771 "d" (__arg5),
772 "d" (__arg6)
773 : "1", "cc", "memory");
775 return (UWord) (__svcres);
778 #elif defined(VGP_mips32_linux)
779 /* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
781 The syscall number goes in v0. The args are passed to the syscall in
782 the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
784 (a3 != 0) flags an error.
785 We return the syscall return value in v0.
786 MIPS version
788 extern int do_syscall_WRK (
789 int a1, int a2, int a3,
790 int a4, int a5, int a6, int syscall_no, UWord *err,
791 UWord *valHi, UWord* valLo
793 asm(
794 ".globl do_syscall_WRK\n"
795 ".ent do_syscall_WRK\n"
796 ".text\n"
797 "do_syscall_WRK:\n"
798 " lw $2, 24($29)\n"
799 " syscall\n"
800 " lw $8, 28($29)\n"
801 " sw $7, ($8)\n"
802 " lw $8, 32($29)\n"
803 " sw $3, ($8)\n" // store valHi
804 " lw $8, 36($29)\n"
805 " sw $2, ($8)\n" // store valLo
806 " jr $31\n"
807 " nop\n"
808 ".previous\n"
809 ".end do_syscall_WRK\n"
812 #elif defined(VGP_mips64_linux)
813 extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
814 UWord a6, UWord syscall_no, ULong* V1_val );
815 asm (
816 ".text\n"
817 ".globl do_syscall_WRK\n"
818 "do_syscall_WRK:\n"
819 " daddiu $29, $29, -8\n"
820 " sd $11, 0($29)\n"
821 " move $2, $10\n"
822 " syscall\n"
823 " ld $11, 0($29)\n"
824 " daddiu $29, $29, 8\n"
825 " sd $3, 0($11)\n" /* store vale of v1 in last param */
826 " sd $7, 8($11)\n" /* store vale of a3 in last param */
827 " jr $31\n"
828 ".previous\n"
831 #elif defined(VGP_tilegx_linux)
832 extern UWord do_syscall_WRK (
833 UWord syscall_no,
834 UWord a1, UWord a2, UWord a3,
835 UWord a4, UWord a5, UWord a6
837 asm(
838 ".text\n"
839 "do_syscall_WRK:\n"
840 "move r10, r0\n"
841 "move r0, r1\n"
842 "move r1, r2\n"
843 "move r2, r3\n"
844 "move r3, r4\n"
845 "move r4, r5\n"
846 "move r5, r6\n"
847 "swint1\n"
848 "jrp lr\n"
849 ".previous\n"
852 #elif defined(VGP_x86_solaris)
854 extern ULong
855 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
856 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
857 UWord a7, UWord a8, /* 28(esp)..32(esp) */
858 UWord syscall_no, /* 36(esp) */
859 /*OUT*/UInt *errflag); /* 40(esp) */
860 /* Classic unix syscall.. parameters on the stack, an unused (by the kernel)
861 return address at 0(esp), a sysno in eax, a result in edx:eax, the carry
862 flag set on error. */
863 __asm__ (
864 ".text\n"
865 ".globl do_syscall_WRK\n"
866 "do_syscall_WRK:\n"
867 " movl 40(%esp), %ecx\n" /* assume syscall success */
868 " movl $0, (%ecx)\n"
869 " movl 36(%esp), %eax\n"
870 " int $0x91\n"
871 " jnc 1f\n" /* jump if success */
872 " movl 40(%esp), %ecx\n" /* syscall failed - set *errflag */
873 " movl $1, (%ecx)\n"
874 "1: ret\n"
875 ".previous\n"
878 extern ULong
879 do_syscall_fast_WRK(UWord syscall_no); /* 4(esp) */
880 /* Fasttrap syscall.. no parameters, a sysno in eax, a result in edx:eax,
881 never fails (if the sysno is valid). */
882 __asm__ (
883 ".text\n"
884 ".globl do_syscall_fast_WRK\n"
885 "do_syscall_fast_WRK:\n"
886 " movl 4(%esp), %eax\n"
887 " int $0xD2\n"
888 " ret\n"
889 ".previous\n"
892 #elif defined(VGP_amd64_solaris)
894 extern ULong
895 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
896 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
897 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
898 UWord syscall_no, /* 24(rsp) */
899 /*OUT*/ULong *errflag, /* 32(rsp) */
900 /*OUT*/ULong *res2); /* 40(rsp) */
901 /* First 6 parameters in registers rdi, rsi, rdx, r10, r8, r9, next
902 2 parameters on the stack, an unused (by the kernel) return address at
903 0(rsp), a sysno in rax, a result in rdx:rax, the carry flag set on
904 error. */
905 __asm__ (
906 ".text\n"
907 ".globl do_syscall_WRK\n"
908 "do_syscall_WRK:\n"
909 " movq %rcx, %r10\n" /* pass rcx in r10 instead */
910 " movq 32(%rsp), %rcx\n" /* assume syscall success */
911 " movq $0, (%rcx)\n"
912 " movq 24(%rsp), %rax\n"
913 " syscall\n"
914 " jnc 1f\n" /* jump if success */
915 " movq 32(%rsp), %rcx\n" /* syscall failed - set *errflag */
916 " movq $1, (%rcx)\n"
917 "1: movq 40(%rsp), %rcx\n" /* save 2nd result word */
918 " movq %rdx, (%rcx)\n"
919 " ret\n"
920 ".previous\n"
923 extern ULong
924 do_syscall_fast_WRK(UWord syscall_no, /* rdi */
925 /*OUT*/ULong *res2); /* rsi */
926 /* Fasttrap syscall.. no parameters, a sysno in rax, a result in rdx:rax,
927 never fails (if the sysno is valid). */
928 __asm__ (
929 ".text\n"
930 ".globl do_syscall_fast_WRK\n"
931 "do_syscall_fast_WRK:\n"
932 " movq %rdi, %rax\n"
933 " int $0xD2\n"
934 " movq %rdx, (%rsi)\n" /* save 2nd result word */
935 " ret\n"
936 ".previous\n"
939 #else
940 # error Unknown platform
941 #endif
944 /* Finally, the generic code. This sends the call to the right
945 helper. */
947 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
948 UWord a4, UWord a5, UWord a6,
949 UWord a7, UWord a8 )
951 # if defined(VGP_x86_linux)
952 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
953 return VG_(mk_SysRes_x86_linux)( val );
955 # elif defined(VGP_amd64_linux)
956 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
957 return VG_(mk_SysRes_amd64_linux)( val );
959 # elif defined(VGP_ppc32_linux)
960 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
961 UInt val = (UInt)(ret>>32);
962 UInt cr0so = (UInt)(ret);
963 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
965 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
966 ULong argblock[7];
967 argblock[0] = sysno;
968 argblock[1] = a1;
969 argblock[2] = a2;
970 argblock[3] = a3;
971 argblock[4] = a4;
972 argblock[5] = a5;
973 argblock[6] = a6;
974 do_syscall_WRK( &argblock[0] );
975 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
977 # elif defined(VGP_arm_linux)
978 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
979 return VG_(mk_SysRes_arm_linux)( val );
981 # elif defined(VGP_arm64_linux)
982 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
983 return VG_(mk_SysRes_arm64_linux)( val );
985 # elif defined(VGP_x86_darwin)
986 UInt wLO = 0, wHI = 0, err = 0;
987 ULong u64;
988 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
989 switch (scclass) {
990 case VG_DARWIN_SYSCALL_CLASS_UNIX:
991 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
992 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
993 wLO = (UInt)u64;
994 wHI = (UInt)(u64 >> 32);
995 break;
996 case VG_DARWIN_SYSCALL_CLASS_MACH:
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 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1002 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1003 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1004 err = 0;
1005 break;
1006 default:
1007 vg_assert(0);
1008 break;
1010 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
1012 # elif defined(VGP_amd64_darwin)
1013 ULong wLO = 0, wHI = 0, err = 0;
1014 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
1015 switch (scclass) {
1016 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1017 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1018 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
1019 break;
1020 case VG_DARWIN_SYSCALL_CLASS_MACH:
1021 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1022 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1023 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1024 err = 0;
1025 break;
1026 default:
1027 vg_assert(0);
1028 break;
1030 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
1032 #elif defined(VGP_s390x_linux)
1033 UWord val;
1035 if (sysno == __NR_mmap) {
1036 ULong argbuf[6];
1038 argbuf[0] = a1;
1039 argbuf[1] = a2;
1040 argbuf[2] = a3;
1041 argbuf[3] = a4;
1042 argbuf[4] = a5;
1043 argbuf[5] = a6;
1044 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
1045 } else {
1046 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1049 return VG_(mk_SysRes_s390x_linux)( val );
1051 #elif defined(VGP_mips32_linux)
1052 UWord err = 0;
1053 UWord valHi = 0;
1054 UWord valLo = 0;
1055 (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
1056 return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
1058 #elif defined(VGP_mips64_linux)
1059 ULong v1_a3[2];
1060 v1_a3[0] = 0xFF00;
1061 v1_a3[1] = 0xFF00;
1062 ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3);
1063 ULong V1 = (ULong)v1_a3[0];
1064 ULong A3 = (ULong)v1_a3[1];
1065 return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
1067 # elif defined(VGP_tilegx_linux)
1068 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1070 return VG_(mk_SysRes_tilegx_linux)( val );
1072 # elif defined(VGP_x86_solaris)
1073 UInt val, val2, err = False;
1074 Bool restart;
1075 ULong u64;
1076 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno);
1078 switch (ssclass) {
1079 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
1080 /* The Solaris kernel does not restart syscalls automatically so it
1081 is done here. */
1082 do {
1083 u64 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1084 VG_SOLARIS_SYSNO_INDEX(sysno), &err);
1085 val = (UInt)u64;
1086 restart = err && (val == VKI_EINTR || val == VKI_ERESTART);
1087 } while (restart);
1088 break;
1089 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
1090 u64 = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno));
1091 break;
1092 default:
1093 vg_assert(0);
1094 break;
1097 val = (UInt)u64;
1098 val2 = (UInt)(u64 >> 32);
1099 return VG_(mk_SysRes_x86_solaris)(err ? True : False, val,
1100 err ? 0 : val2);
1102 # elif defined(VGP_amd64_solaris)
1103 ULong val, val2, err = False;
1104 Bool restart;
1105 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno);
1107 switch (ssclass) {
1108 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
1109 /* The Solaris kernel does not restart syscalls automatically so it
1110 is done here. */
1111 do {
1112 val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1113 VG_SOLARIS_SYSNO_INDEX(sysno), &err, &val2);
1114 restart = err && (val == VKI_EINTR || val == VKI_ERESTART);
1115 } while (restart);
1116 break;
1117 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
1118 val = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno), &val2);
1119 break;
1120 default:
1121 vg_assert(0);
1122 break;
1125 return VG_(mk_SysRes_amd64_solaris)(err ? True : False, val,
1126 err ? 0 : val2);
1128 #else
1129 # error Unknown platform
1130 #endif
1133 /* ---------------------------------------------------------------------
1134 Names of errors.
1135 ------------------------------------------------------------------ */
1137 /* Return a string which gives the name of an error value. Note,
1138 unlike the standard C syserror fn, the returned string is not
1139 malloc-allocated or writable -- treat it as a constant.
1140 TODO: implement this properly. */
1142 const HChar* VG_(strerror) ( UWord errnum )
1144 switch (errnum) {
1145 case VKI_EPERM: return "Operation not permitted";
1146 case VKI_ENOENT: return "No such file or directory";
1147 case VKI_ESRCH: return "No such process";
1148 case VKI_EINTR: return "Interrupted system call";
1149 case VKI_EIO: return "Input/output error";
1150 case VKI_ENXIO: return "No such device or address";
1151 case VKI_E2BIG: return "Argument list too long";
1152 case VKI_ENOEXEC: return "Exec format error";
1153 case VKI_EBADF: return "Bad file descriptor";
1154 case VKI_ECHILD: return "No child processes";
1155 case VKI_EAGAIN: return "Resource temporarily unavailable";
1156 case VKI_ENOMEM: return "Cannot allocate memory";
1157 case VKI_EACCES: return "Permission denied";
1158 case VKI_EFAULT: return "Bad address";
1159 case VKI_ENOTBLK: return "Block device required";
1160 case VKI_EBUSY: return "Device or resource busy";
1161 case VKI_EEXIST: return "File exists";
1162 case VKI_EXDEV: return "Invalid cross-device link";
1163 case VKI_ENODEV: return "No such device";
1164 case VKI_ENOTDIR: return "Not a directory";
1165 case VKI_EISDIR: return "Is a directory";
1166 case VKI_EINVAL: return "Invalid argument";
1167 case VKI_ENFILE: return "Too many open files in system";
1168 case VKI_EMFILE: return "Too many open files";
1169 case VKI_ENOTTY: return "Inappropriate ioctl for device";
1170 case VKI_ETXTBSY: return "Text file busy";
1171 case VKI_EFBIG: return "File too large";
1172 case VKI_ENOSPC: return "No space left on device";
1173 case VKI_ESPIPE: return "Illegal seek";
1174 case VKI_EROFS: return "Read-only file system";
1175 case VKI_EMLINK: return "Too many links";
1176 case VKI_EPIPE: return "Broken pipe";
1177 case VKI_EDOM: return "Numerical argument out of domain";
1178 case VKI_ERANGE: return "Numerical result out of range";
1180 case VKI_ENOSYS: return "Function not implemented";
1181 case VKI_EOVERFLOW: return "Value too large for defined data type";
1182 # if defined(VKI_ERESTARTSYS)
1183 case VKI_ERESTARTSYS: return "ERESTARTSYS";
1184 # endif
1185 default: return "VG_(strerror): unknown error";
1190 /*--------------------------------------------------------------------*/
1191 /*--- end ---*/
1192 /*--------------------------------------------------------------------*/