Add new exp files to EXTRA_DIST in memcheck/tests/Makefile.am
[valgrind.git] / coregrind / m_syscall.c
blob1e49ed4121b3b987cb13922c9aba8973d38d4885
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-2017 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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics.h"
30 #include "pub_core_libcassert.h"
31 #include "pub_core_vki.h"
32 #include "pub_core_vkiscnums.h"
33 #include "pub_core_syscall.h"
35 /* ---------------------------------------------------------------------
36 Building syscall return values.
37 ------------------------------------------------------------------ */
39 /* Make a SysRes value from a syscall return value. This is
40 platform specific. */
42 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
44 SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
45 /* MIPS uses a3 != 0 to flag an error */
46 SysRes res;
47 res._isError = (a3 != (UWord)0);
48 res._val = v0;
49 res._valEx = v1;
50 return res;
53 SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) {
54 /* MIPS uses a3 != 0 to flag an error */
55 SysRes res;
56 res._isError = (a3 != (ULong)0);
57 res._val = v0;
58 res._valEx = v1;
59 return res;
62 /* Generic constructors. */
63 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
64 SysRes r;
65 r._isError = True;
66 r._val = err;
67 r._valEx = 0;
68 return r;
71 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
72 SysRes r;
73 r._isError = False;
74 r._val = res;
75 r._valEx = 0;
76 return r;
79 SysRes VG_(mk_SysRes_SuccessEx) ( UWord res, UWord resEx ) {
80 SysRes r;
81 r._isError = False;
82 r._val = res;
83 r._valEx = resEx;
84 return r;
88 #elif defined(VGO_linux) \
89 && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux)
92 From:
93 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
94 linux/i386/sysdep.h?
95 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
97 Linux uses a negative return value to indicate syscall errors,
98 unlike most Unices, which use the condition codes' carry flag.
100 Since version 2.1 the return value of a system call might be
101 negative even if the call succeeded. E.g., the 'lseek' system call
102 might return a large offset. Therefore we must not anymore test
103 for < 0, but test for a real error by making sure the value in %eax
104 is a real error number. Linus said he will make sure the no
105 syscall returns a value in -1 .. -4095 as a valid result so we can
106 safely test with -4095.
109 SysRes VG_(mk_SysRes_nanomips_linux) ( UWord a0 ) {
110 SysRes res;
111 res._isError = (a0 > 0xFFFFF000ul);
112 res._val = a0;
113 return res;
116 SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
117 SysRes res;
118 res._isError = val >= -4095 && val <= -1;
119 if (res._isError) {
120 res._val = (UInt)(-val);
121 } else {
122 res._val = (UInt)val;
124 return res;
127 /* Similarly .. */
128 SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
129 SysRes res;
130 res._isError = val >= -4095 && val <= -1;
131 if (res._isError) {
132 res._val = (ULong)(-val);
133 } else {
134 res._val = (ULong)val;
136 return res;
139 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
140 /* Note this must be in the bottom bit of the second arg */
141 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
142 SysRes res;
143 res._isError = (cr0so & 1) != 0;
144 res._val = val;
145 return res;
148 /* As per ppc32 version, for the sc instruction cr0.so must be in
149 l.s.b. of 2nd arg.
150 For the scv 0 instruction, the return value indicates failure if
151 it is -4095..-1 (i.e., it is >= -MAX_ERRNO (-4095) as an unsigned
152 comparison), in which case the error value is the negated return value. */
153 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so, UInt flag ) {
154 SysRes res;
156 if (flag == SC_FLAG) {
157 /* sc instruction */
158 res._isError = (cr0so & 1) != 0;
159 res._val = val;
160 } else if (flag == SCV_FLAG) {
161 /* scv instruction */
162 if ( (Long)val >= -4095 && (Long)val <= -1) {
163 res._isError = True;
164 res._val = (ULong)(-val);
165 } else {
166 res._isError = False;
167 res._val = (ULong)(val);
169 } else
170 vg_assert(0);
171 return res;
174 SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
175 SysRes res;
176 res._isError = val >= -4095 && val <= -1;
177 if (res._isError) {
178 res._val = -val;
179 } else {
180 res._val = val;
182 return res;
185 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
186 SysRes res;
187 res._isError = val >= -4095 && val <= -1;
188 if (res._isError) {
189 res._val = (UInt)(-val);
190 } else {
191 res._val = (UInt)val;
193 return res;
196 SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
197 SysRes res;
198 res._isError = val >= -4095 && val <= -1;
199 if (res._isError) {
200 res._val = (ULong)(-val);
201 } else {
202 res._val = (ULong)val;
204 return res;
207 /* Generic constructors. */
208 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
209 SysRes r;
210 r._isError = False;
211 r._val = res;
212 return r;
215 #if defined(VGP_nanomips_linux)
216 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
217 SysRes r;
218 r._isError = True;
219 r._val = (UWord)(-(Word)err);
220 return r;
222 #else
223 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
224 SysRes r;
225 r._isError = True;
226 r._val = err;
227 return r;
230 #endif
233 #elif defined(VGO_darwin)
235 /* Darwin: Some syscalls return a double-word result. */
236 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
237 UInt wHI, UInt wLO )
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(UInt));
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);
266 return res;
269 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
270 ULong wHI, ULong wLO )
272 SysRes res;
273 res._wHI = 0;
274 res._wLO = 0;
275 res._mode = 0; /* invalid */
276 vg_assert(isErr == False || isErr == True);
277 vg_assert(sizeof(UWord) == sizeof(ULong));
278 switch (scclass) {
279 case VG_DARWIN_SYSCALL_CLASS_UNIX:
280 res._wLO = wLO;
281 res._wHI = wHI;
282 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
283 break;
284 case VG_DARWIN_SYSCALL_CLASS_MACH:
285 vg_assert(!isErr);
286 vg_assert(wHI == 0);
287 res._wLO = wLO;
288 res._mode = SysRes_MACH;
289 break;
290 case VG_DARWIN_SYSCALL_CLASS_MDEP:
291 vg_assert(!isErr);
292 vg_assert(wHI == 0);
293 res._wLO = wLO;
294 res._mode = SysRes_MDEP;
295 break;
296 default:
297 vg_assert(0);
299 return res;
302 /* Generic constructors. We assume (without checking if this makes
303 any sense, from the caller's point of view) that these are for the
304 UNIX style of syscall. */
305 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
306 SysRes r;
307 r._wHI = 0;
308 r._wLO = err;
309 r._mode = SysRes_UNIX_ERR;
310 return r;
313 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
314 SysRes r;
315 r._wHI = 0;
316 r._wLO = res;
317 r._mode = SysRes_UNIX_OK;
318 return r;
322 #elif defined(VGO_solaris)
324 /* Generic constructors. */
325 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
326 SysRes r;
327 r._val = err;
328 r._val2 = 0;
329 r._isError = True;
330 return r;
333 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
334 SysRes r;
335 r._val = res;
336 r._val2 = 0;
337 r._isError = False;
338 return r;
341 SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 )
343 SysRes res;
345 // stay sane
346 vg_assert(isErr == True || isErr == False);
348 res._val = val;
349 res._val2 = val2;
350 res._isError = isErr;
351 return res;
354 SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 )
356 SysRes res;
358 // stay sane
359 vg_assert(isErr == True || isErr == False);
361 res._val = val;
362 res._val2 = val2;
363 res._isError = isErr;
364 return res;
368 #elif defined(VGO_freebsd)
370 SysRes VG_(mk_SysRes_x86_freebsd) ( UInt val, UInt val2, Bool err ) {
371 SysRes r;
372 r._isError = err;
373 r._val = val;
374 r._val2 = val2;
375 return r;
378 SysRes VG_(mk_SysRes_amd64_freebsd) ( ULong val, ULong val2, Bool err ) {
379 SysRes r;
380 r._isError = err;
381 r._val = val;
382 r._val2 = val2;
383 return r;
386 /* Generic constructors. */
387 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
388 SysRes r;
389 r._val = err;
390 r._val2 = 0;
391 r._isError = True;
392 return r;
395 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
396 SysRes r;
397 r._val = res;
398 r._val2 = 0;
399 r._isError = False;
400 return r;
403 #else
404 # error "Unknown OS"
405 #endif
408 /* ---------------------------------------------------------------------
409 VG_(do_syscall): A function for doing syscalls.
410 ------------------------------------------------------------------ */
412 #if defined(VGP_x86_linux)
413 /* Incoming args (syscall number + up to 6 args) come on the stack.
414 (ie. the C calling convention).
416 The syscall number goes in %eax. The args are passed to the syscall in
417 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
418 calling convention.
420 %eax gets the return value. Not sure which registers the kernel
421 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
422 %ebp).
424 extern UWord do_syscall_WRK (
425 UWord syscall_no,
426 UWord a1, UWord a2, UWord a3,
427 UWord a4, UWord a5, UWord a6
429 asm(
430 ".text\n"
431 ".globl do_syscall_WRK\n"
432 "do_syscall_WRK:\n"
433 " .cfi_startproc\n"
434 " push %esi\n"
435 " .cfi_adjust_cfa_offset 4\n"
436 " .cfi_offset %esi, -8\n"
437 " push %edi\n"
438 " .cfi_adjust_cfa_offset 4\n"
439 " .cfi_offset %edi, -12\n"
440 " push %ebx\n"
441 " .cfi_adjust_cfa_offset 4\n"
442 " .cfi_offset %ebx, -16\n"
443 " push %ebp\n"
444 " .cfi_adjust_cfa_offset 4\n"
445 " .cfi_offset %ebp, -20\n"
446 " movl 16+ 4(%esp),%eax\n"
447 " movl 16+ 8(%esp),%ebx\n"
448 " movl 16+12(%esp),%ecx\n"
449 " movl 16+16(%esp),%edx\n"
450 " movl 16+20(%esp),%esi\n"
451 " movl 16+24(%esp),%edi\n"
452 " movl 16+28(%esp),%ebp\n"
453 " int $0x80\n"
454 " popl %ebp\n"
455 " .cfi_adjust_cfa_offset -4\n"
456 " .cfi_restore %ebp\n"
457 " popl %ebx\n"
458 " .cfi_adjust_cfa_offset -4\n"
459 " .cfi_restore %ebx\n"
460 " popl %edi\n"
461 " .cfi_adjust_cfa_offset -4\n"
462 " .cfi_restore %edi\n"
463 " popl %esi\n"
464 " .cfi_adjust_cfa_offset -4\n"
465 " .cfi_restore %esi\n"
466 " ret\n"
467 " .cfi_endproc\n"
468 ".previous\n"
471 #elif defined(VGP_amd64_linux)
472 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
473 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
474 calling convention).
476 The syscall number goes in %rax. The args are passed to the syscall in
477 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
478 ie. the kernel's syscall calling convention.
480 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
481 no matter, they are caller-save (the syscall clobbers no callee-save
482 regs, so we don't have to do any register saving/restoring).
484 extern UWord do_syscall_WRK (
485 UWord syscall_no,
486 UWord a1, UWord a2, UWord a3,
487 UWord a4, UWord a5, UWord a6
489 asm(
490 ".text\n"
491 ".globl do_syscall_WRK\n"
492 "do_syscall_WRK:\n"
493 /* Convert function calling convention --> syscall calling
494 convention */
495 " movq %rdi, %rax\n"
496 " movq %rsi, %rdi\n"
497 " movq %rdx, %rsi\n"
498 " movq %rcx, %rdx\n"
499 " movq %r8, %r10\n"
500 " movq %r9, %r8\n"
501 " movq 8(%rsp), %r9\n" /* last arg from stack */
502 " syscall\n"
503 " ret\n"
504 ".previous\n"
507 #elif defined(VGP_ppc32_linux)
508 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
510 The syscall number goes in %r0. The args are passed to the syscall in
511 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
513 The %cr0.so bit flags an error.
514 We return the syscall return value in %r3, and the %cr0.so in
515 the lowest bit of %r4.
516 We return a ULong, of which %r3 is the high word, and %r4 the low.
517 No callee-save regs are clobbered, so no saving/restoring is needed.
519 extern ULong do_syscall_WRK (
520 UWord syscall_no,
521 UWord a1, UWord a2, UWord a3,
522 UWord a4, UWord a5, UWord a6
524 asm(
525 ".text\n"
526 ".globl do_syscall_WRK\n"
527 "do_syscall_WRK:\n"
528 " mr 0,3\n"
529 " mr 3,4\n"
530 " mr 4,5\n"
531 " mr 5,6\n"
532 " mr 6,7\n"
533 " mr 7,8\n"
534 " mr 8,9\n"
535 " sc\n" /* syscall: sets %cr0.so on error */
536 " mfcr 4\n" /* %cr -> low word of return var */
537 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
538 " blr\n" /* and return */
539 ".previous\n"
542 #elif defined(VGP_ppc64be_linux)
543 /* Due to the need to return 65 bits of result, this is completely
544 different from the ppc32 case. The single arg register points to a
545 7-word block containing the syscall # and the 6 args. The syscall
546 result proper is put in [0] of the block, and %cr0.so is in the
547 bottom bit of [1]. */
548 extern void do_syscall_WRK ( ULong* argblock );
549 asm(
550 ".align 2\n"
551 ".globl do_syscall_WRK\n"
552 ".section \".opd\",\"aw\"\n"
553 ".align 3\n"
554 "do_syscall_WRK:\n"
555 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
556 ".previous\n"
557 ".type .do_syscall_WRK,@function\n"
558 ".globl .do_syscall_WRK\n"
559 ".do_syscall_WRK:\n"
560 " std 3,-16(1)\n" /* stash arg */
561 " ld 8, 48(3)\n" /* sc arg 6 */
562 " ld 7, 40(3)\n" /* sc arg 5 */
563 " ld 6, 32(3)\n" /* sc arg 4 */
564 " ld 5, 24(3)\n" /* sc arg 3 */
565 " ld 4, 16(3)\n" /* sc arg 2 */
566 " ld 0, 0(3)\n" /* sc number */
567 " ld 3, 8(3)\n" /* sc arg 1 */
568 " sc\n" /* result in r3 and cr0.so */
569 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
570 " std 3,0(5)\n" /* argblock[0] = r3 */
571 " mfcr 3\n"
572 " srwi 3,3,28\n"
573 " andi. 3,3,1\n"
574 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
575 " blr\n"
578 #elif defined(VGP_ppc64le_linux)
579 /* Due to the need to return 65 bits of result, this is completely
580 different from the ppc32 case. The single arg register points to a
581 7-word block containing the syscall # and the 6 args. The syscall
582 result proper is put in [0] of the block, and %cr0.so is in the
583 bottom bit of [1]. */
584 extern void do_syscall_WRK ( ULong* argblock );
585 /* Little Endian supports ELF version 2. In the future, it may support
586 * other versions as well.
588 asm(
589 ".align 2\n"
590 ".globl do_syscall_WRK\n"
591 ".type do_syscall_WRK,@function\n"
592 "do_syscall_WRK:\n"
593 "#if _CALL_ELF == 2" "\n"
594 "0: addis 2,12,.TOC.-0b@ha\n"
595 " addi 2,2,.TOC.-0b@l\n"
596 " .localentry do_syscall_WRK, .-do_syscall_WRK\n"
597 "#endif" "\n"
598 /* Check which system call instruction to issue*/
599 " ld 8, 56(3)\n" /* arg 7 holds sc/scv flag */
600 " cmpdi 8,1\n" /* check sc/scv flag not equal to SC_FLAG*/
601 " bne issue_scv\n"
603 /* setup and issue the sc instruction */
604 " std 3,-16(1)\n" /* stash arg */
605 " ld 8, 48(3)\n" /* sc arg 6 */
606 " ld 7, 40(3)\n" /* sc arg 5 */
607 " ld 6, 32(3)\n" /* sc arg 4 */
608 " ld 5, 24(3)\n" /* sc arg 3 */
609 " ld 4, 16(3)\n" /* sc arg 2 */
610 " ld 0, 0(3)\n" /* sc number */
611 " ld 3, 8(3)\n" /* sc arg 1 */
612 " sc\n" /* result in r3 and cr0.so */
613 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
614 " std 3,0(5)\n" /* argblock[0] = r3 */
615 " mfcr 3\n"
616 " srwi 3,3,28\n"
617 " andi. 3,3,1\n"
618 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
619 " blr\n" /* return */
621 /* setup to do scv instruction */
622 "issue_scv: "
623 /* The scv instruction requires a new stack frame */
624 " stdu 1,-80(1)\n"
625 " std 27,40(1)\n" /* save r27 to stack frame */
626 " mflr 27\n" /* Get link register */
627 " std 27,16(1)\n" /* Save link register */
629 /* setup and issue the scv instruction */
630 " std 3,-16(1)\n" /* stash arg */
631 " ld 8, 48(3)\n" /* sc arg 6 */
632 " ld 7, 40(3)\n" /* sc arg 5 */
633 " ld 6, 32(3)\n" /* sc arg 4 */
634 " ld 5, 24(3)\n" /* sc arg 3 */
635 " ld 4, 16(3)\n" /* sc arg 2 */
636 " ld 0, 0(3)\n" /* sc number */
637 " ld 3, 8(3)\n" /* sc arg 1 */
639 " .machine push\n"
640 " .machine \"power9\"\n"
641 " scv 0\n"
642 " .machine pop\n"
643 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
644 " std 3,0(5)\n" /* argblock[0] = r3 */
646 /* pop off stack frame */
647 " ld 27,16(1)\n" /* Fetch LR from frame */
648 " mtlr 27\n" /* restore LR */
649 " ld 27,40(1)\n" /* restore r27 from stack frame */
650 " addi 1,1,80\n"
651 " blr\n"
652 " .size do_syscall_WRK, .-do_syscall_WRK\n"
655 #elif defined(VGP_arm_linux)
656 /* I think the conventions are:
657 args in r0 r1 r2 r3 r4 r5
658 sysno in r7
659 return value in r0, w/ same conventions as x86-linux, viz r0 in
660 -4096 .. -1 is an error value. All other values are success
661 values.
663 extern UWord do_syscall_WRK (
664 UWord a1, UWord a2, UWord a3,
665 UWord a4, UWord a5, UWord a6,
666 UWord syscall_no
668 asm(
669 ".text\n"
670 ".globl do_syscall_WRK\n"
671 "do_syscall_WRK:\n"
672 " push {r4, r5, r7}\n"
673 " ldr r4, [sp, #12]\n"
674 " ldr r5, [sp, #16]\n"
675 " ldr r7, [sp, #20]\n"
676 " svc 0x0\n"
677 " pop {r4, r5, r7}\n"
678 " bx lr\n"
679 ".previous\n"
682 #elif defined(VGP_arm64_linux)
683 /* I think the conventions are:
684 args in r0 r1 r2 r3 r4 r5
685 sysno in r8
686 return value in r0, w/ same conventions as x86-linux, viz r0 in
687 -4096 .. -1 is an error value. All other values are success
688 values.
690 r0 to r5 remain unchanged, but syscall_no is in r6 and needs
691 to be moved to r8 (??)
693 extern UWord do_syscall_WRK (
694 UWord a1, UWord a2, UWord a3,
695 UWord a4, UWord a5, UWord a6,
696 UWord syscall_no
698 asm(
699 ".text\n"
700 ".globl do_syscall_WRK\n"
701 "do_syscall_WRK:\n"
702 " mov x8, x6\n"
703 " mov x6, 0\n"
704 " mov x7, 0\n"
705 " svc 0\n"
706 " ret\n"
707 ".previous\n"
710 #elif defined(VGP_x86_freebsd)
711 /* Incoming args (syscall number + up to 8 args) are on the stack.
712 FreeBSD has a syscall called 'syscall' that takes all args (including
713 the syscall number) off the stack. Since we're called, the return
714 address is on the stack as expected, so we can just call syscall(2)
715 and it Just Works. Error is when carry is set.
717 extern ULong do_syscall_WRK (
718 UWord syscall_no,
719 UWord a1, UWord a2, UWord a3,
720 UWord a4, UWord a5, UWord a6,
721 UWord a7, UWord a8, UInt *flags
723 asm(
724 ".text\n"
725 "do_syscall_WRK:\n"
726 " movl $0,%eax\n" /* syscall number = "syscall" (0) to avoid stack frobbing
728 " int $0x80\n"
729 " jb 1f\n"
730 " ret\n"
731 "1: movl 40(%esp),%ecx\n" /* store carry in *flags */
732 " movl $1,(%ecx)\n"
733 " ret\n"
734 ".previous\n"
737 #elif defined(VGP_amd64_freebsd)
738 /* Convert function calling convention --> SYSCALL_STD calling
739 convention
740 PJF - not sure why we don't use SYSCALL0 convention like x86
742 extern UWord do_syscall_WRK (
743 UWord syscall_no, /* %rdi */
744 UWord a1, /* %rsi */
745 UWord a2, /* %rdx */
746 UWord a3, /* %rcx */
747 UWord a4, /* %r8 */
748 UWord a5, /* %r9 */
749 UWord a6, /* 8(%rsp) */
750 UWord a7, /* 16(%rsp) */
751 UWord a8, /* 24(%rsp) */
752 UInt *flags, /* 32(%rsp) */
753 UWord *rv2 /* 40(%rsp) */
755 asm(
756 ".text\n"
757 "do_syscall_WRK:\n"
758 " pushq %rbp\n"
759 " movq %rsp, %rbp\n"
760 " movq %rdi, %rax\n" /* syscall_no */
761 " movq %rsi, %rdi\n" /* a1 */
762 " movq %rdx, %rsi\n" /* a2 */
763 " movq %rcx, %rdx\n" /* a3 */
764 " movq %r8, %r10\n" /* a4 */
765 " movq %r9, %r8\n" /* a5 */
766 " movq 16(%rbp), %r9\n" /* a6 last arg from stack, account for %rbp */
767 " movq 24(%rbp), %r11\n" /* a7 from stack */
768 " pushq %r11\n"
769 " movq 32(%rbp), %r11\n" /* a8 from stack */
770 " pushq %r11\n"
771 " subq $8,%rsp\n" /* fake return addr */
772 " syscall\n"
773 " jb 1f\n"
774 " movq 48(%rbp),%rsi\n" /* success */
775 " movq %rdx, (%rsi)\n" /* second return value */
776 " movq %rbp, %rsp\n"
777 " popq %rbp\n"
778 " ret\n"
779 "1:\n" /* error path */
780 " movq 40(%rbp), %rsi\n" /* flags */
781 " movl $1,(%rsi)\n"
782 " movq %rbp, %rsp\n"
783 " popq %rbp\n"
784 " ret\n"
785 ".previous\n"
788 #elif defined(VGP_x86_darwin)
790 /* Incoming args (syscall number + up to 8 args) come in on the stack
792 The kernel's syscall calling convention is:
793 * the syscall number goes in eax
794 * the args are passed to the syscall on the stack,
795 pushed onto the stack R->L (that is, the usual x86
796 calling conventions, with the leftmost arg at the lowest
797 address)
798 Call instruction:
799 * UNIX: sysenter
800 * UNIX: int $0x80
801 * MACH: int $0x81
802 * MDEP: int $0x82
803 Note that the call type can be determined from the syscall number;
804 there is no need to inspect the actual instruction. Although obviously
805 the instruction must match.
806 Return value:
807 * MACH,MDEP: the return value comes back in eax
808 * UNIX: the return value comes back in edx:eax (hi32:lo32)
809 Error:
810 * MACH,MDEP: no error is returned
811 * UNIX: the carry flag indicates success or failure
813 nb here, sizeof(UWord) == sizeof(UInt)
816 __private_extern__ ULong
817 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
818 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
819 UWord a7, UWord a8, /* 28(esp)..32(esp) */
820 UWord syscall_no, /* 36(esp) */
821 /*OUT*/UInt* errflag /* 40(esp) */ );
822 // Unix syscall: 64-bit return in edx:eax, with LSB in eax
823 // error indicated by carry flag: clear=good, set=bad
824 asm(".private_extern _do_syscall_unix_WRK\n"
825 "_do_syscall_unix_WRK:\n"
826 " movl 40(%esp), %ecx \n" /* assume syscall success */
827 " movl $0, (%ecx) \n"
828 " movl 36(%esp), %eax \n"
829 " int $0x80 \n"
830 " jnc 1f \n" /* jump if success */
831 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
832 " movl $1, (%ecx) \n"
833 " 1: ret \n"
836 __private_extern__ UInt
837 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
838 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
839 UWord a7, UWord a8, /* 28(esp)..32(esp) */
840 UWord syscall_no /* 36(esp) */ );
841 // Mach trap: 32-bit result in %eax, no error flag
842 asm(".private_extern _do_syscall_mach_WRK\n"
843 "_do_syscall_mach_WRK:\n"
844 " movl 36(%esp), %eax \n"
845 " int $0x81 \n"
846 " ret \n"
849 __private_extern__ UInt
850 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
851 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
852 UWord a7, UWord a8, /* 28(esp)..32(esp) */
853 UWord syscall_no /* 36(esp) */ );
854 // mdep trap: 32-bit result in %eax, no error flag
855 asm(
856 ".private_extern _do_syscall_mdep_WRK\n"
857 "_do_syscall_mdep_WRK:\n"
858 " movl 36(%esp), %eax \n"
859 " int $0x82 \n"
860 " ret \n"
864 #elif defined(VGP_amd64_darwin)
866 /* Incoming args (syscall number + up to 8 args) come in registers and stack
868 The kernel's syscall calling convention is:
869 * the syscall number goes in rax
870 * the args are passed to the syscall in registers and the stack
871 * the call instruction is 'syscall'
872 Return value:
873 * MACH,MDEP: the return value comes back in rax
874 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
875 Error:
876 * MACH,MDEP: no error is returned
877 * UNIX: the carry flag indicates success or failure
879 nb here, sizeof(UWord) == sizeof(ULong)
882 __private_extern__ UWord
883 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
884 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
885 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
886 UWord syscall_no, /* 24(rsp) */
887 /*OUT*/ULong* errflag, /* 32(rsp) */
888 /*OUT*/ULong* res2 ); /* 40(rsp) */
889 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax
890 // error indicated by carry flag: clear=good, set=bad
891 asm(".private_extern _do_syscall_unix_WRK\n"
892 "_do_syscall_unix_WRK:\n"
893 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
894 " movq 32(%rsp), %rax \n" /* assume syscall success */
895 " movq $0, (%rax) \n"
896 " movq 24(%rsp), %rax \n" /* load syscall_no */
897 " syscall \n"
898 " jnc 1f \n" /* jump if success */
899 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
900 " movq $1, (%rcx) \n"
901 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
902 " movq %rdx, (%rcx) \n"
903 " retq \n" /* return 1st result word */
906 __private_extern__ UWord
907 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
908 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
909 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
910 UWord syscall_no ); /* 24(rsp) */
911 // Mach trap: 64-bit result, no error flag
912 asm(".private_extern _do_syscall_mach_WRK\n"
913 "_do_syscall_mach_WRK:\n"
914 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
915 " movq 24(%rsp), %rax \n" /* load syscall_no */
916 " syscall \n"
917 " retq \n"
920 #elif defined(VGP_s390x_linux)
922 static UWord do_syscall_WRK (
923 UWord syscall_no,
924 UWord arg1, UWord arg2, UWord arg3,
925 UWord arg4, UWord arg5, UWord arg6
928 register UWord __arg1 asm("2") = arg1;
929 register UWord __arg2 asm("3") = arg2;
930 register UWord __arg3 asm("4") = arg3;
931 register UWord __arg4 asm("5") = arg4;
932 register UWord __arg5 asm("6") = arg5;
933 register UWord __arg6 asm("7") = arg6;
934 register ULong __svcres asm("2");
936 __asm__ __volatile__ (
937 "lgr %%r1,%1\n\t"
938 "svc 0\n\t"
939 : "=d" (__svcres)
940 : "a" (syscall_no),
941 "0" (__arg1),
942 "d" (__arg2),
943 "d" (__arg3),
944 "d" (__arg4),
945 "d" (__arg5),
946 "d" (__arg6)
947 : "1", "cc", "memory");
949 return (UWord) (__svcres);
952 #elif defined(VGP_mips32_linux)
953 /* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
955 The syscall number goes in v0. The args are passed to the syscall in
956 the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
958 (a3 != 0) flags an error.
959 We return the syscall return value in v0.
960 MIPS version
962 extern int do_syscall_WRK (
963 int a1, int a2, int a3,
964 int a4, int a5, int a6, int a7, int syscall_no, UWord *err,
965 UWord *valHi, UWord* valLo
967 asm (
968 ".text \n\t"
969 ".globl do_syscall_WRK \n\t"
970 ".type do_syscall_WRK, @function \n\t"
971 ".set push \n\t"
972 ".set noreorder \n\t"
973 "do_syscall_WRK: \n\t"
974 " lw $2, 28($29) \n\t"
975 " syscall \n\t"
976 " lw $8, 32($29) \n\t"
977 " sw $7, ($8) \n\t"
978 " lw $8, 36($29) \n\t"
979 " sw $3, ($8) \n\t" /* store valHi */
980 " lw $8, 40($29) \n\t"
981 " jr $31 \n\t"
982 " sw $2, ($8) \n\t" /* store valLo */
983 ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
984 ".set pop \n\t"
985 ".previous \n\t"
988 #elif defined(VGP_mips64_linux)
989 extern RegWord do_syscall_WRK ( RegWord a1, RegWord a2, RegWord a3, RegWord a4,
990 RegWord a5, RegWord a6, RegWord a7, RegWord syscall_no,
991 RegWord* V1_A3_val );
992 asm (
993 ".text \n\t"
994 ".globl do_syscall_WRK \n\t"
995 ".type do_syscall_WRK, @function \n\t"
996 ".set push \n\t"
997 ".set noreorder \n\t"
998 "do_syscall_WRK: \n\t"
999 " move $2, $11 \n\t"
1000 " syscall \n\t"
1001 # if defined(_ABI64)
1002 " ld $12, 0($29) \n\t"
1003 # elif defined(_ABIN32)
1004 " lw $12, 0($29) \n\t"
1005 # endif
1006 " sd $3, 0($12) \n\t" /* store v1 in V1_A3_val */
1007 " jr $31 \n\t"
1008 " sd $7, 8($12) \n\t" /* store a3 in V1_A3_val */
1009 ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
1010 ".set pop \n\t"
1011 ".previous \n\t"
1014 #elif defined(VGP_nanomips_linux)
1015 extern void do_syscall_WRK (
1016 RegWord a1, RegWord a2, RegWord a3,
1017 RegWord a4, RegWord a5, RegWord a6,
1018 RegWord syscall_no, RegWord *res_a0);
1019 asm (
1020 ".text \n\t"
1021 ".globl do_syscall_WRK \n\t"
1022 ".type do_syscall_WRK, @function \n\t"
1023 ".set push \n\t"
1024 ".set noreorder \n\t"
1025 "do_syscall_WRK: \n\t"
1026 " save 32, $a7 \n\t"
1027 " move $t4, $a6 \n\t"
1028 " syscall[32] \n\t"
1029 " restore 32, $a7 \n\t"
1030 " sw $a0, 0($a7) \n\t"
1031 " jrc $ra \n\t"
1032 ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
1033 ".set pop \n\t"
1034 ".previous \n\t"
1037 #elif defined(VGP_x86_solaris)
1039 extern ULong
1040 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
1041 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
1042 UWord a7, UWord a8, /* 28(esp)..32(esp) */
1043 UWord syscall_no, /* 36(esp) */
1044 /*OUT*/UInt *errflag); /* 40(esp) */
1045 /* Classic unix syscall.. parameters on the stack, an unused (by the kernel)
1046 return address at 0(esp), a sysno in eax, a result in edx:eax, the carry
1047 flag set on error. */
1048 __asm__ (
1049 ".text\n"
1050 ".globl do_syscall_WRK\n"
1051 "do_syscall_WRK:\n"
1052 " movl 40(%esp), %ecx\n" /* assume syscall success */
1053 " movl $0, (%ecx)\n"
1054 " movl 36(%esp), %eax\n"
1055 " int $0x91\n"
1056 " jnc 1f\n" /* jump if success */
1057 " movl 40(%esp), %ecx\n" /* syscall failed - set *errflag */
1058 " movl $1, (%ecx)\n"
1059 "1: ret\n"
1060 ".previous\n"
1063 extern ULong
1064 do_syscall_fast_WRK(UWord syscall_no); /* 4(esp) */
1065 /* Fasttrap syscall.. no parameters, a sysno in eax, a result in edx:eax,
1066 never fails (if the sysno is valid). */
1067 __asm__ (
1068 ".text\n"
1069 ".globl do_syscall_fast_WRK\n"
1070 "do_syscall_fast_WRK:\n"
1071 " movl 4(%esp), %eax\n"
1072 " int $0xD2\n"
1073 " ret\n"
1074 ".previous\n"
1077 #elif defined(VGP_amd64_solaris)
1079 extern ULong
1080 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
1081 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
1082 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
1083 UWord syscall_no, /* 24(rsp) */
1084 /*OUT*/ULong *errflag, /* 32(rsp) */
1085 /*OUT*/ULong *res2); /* 40(rsp) */
1086 /* First 6 parameters in registers rdi, rsi, rdx, r10, r8, r9, next
1087 2 parameters on the stack, an unused (by the kernel) return address at
1088 0(rsp), a sysno in rax, a result in rdx:rax, the carry flag set on
1089 error. */
1090 __asm__ (
1091 ".text\n"
1092 ".globl do_syscall_WRK\n"
1093 "do_syscall_WRK:\n"
1094 " movq %rcx, %r10\n" /* pass rcx in r10 instead */
1095 " movq 32(%rsp), %rcx\n" /* assume syscall success */
1096 " movq $0, (%rcx)\n"
1097 " movq 24(%rsp), %rax\n"
1098 " syscall\n"
1099 " jnc 1f\n" /* jump if success */
1100 " movq 32(%rsp), %rcx\n" /* syscall failed - set *errflag */
1101 " movq $1, (%rcx)\n"
1102 "1: movq 40(%rsp), %rcx\n" /* save 2nd result word */
1103 " movq %rdx, (%rcx)\n"
1104 " ret\n"
1105 ".previous\n"
1108 extern ULong
1109 do_syscall_fast_WRK(UWord syscall_no, /* rdi */
1110 /*OUT*/ULong *res2); /* rsi */
1111 /* Fasttrap syscall.. no parameters, a sysno in rax, a result in rdx:rax,
1112 never fails (if the sysno is valid). */
1113 __asm__ (
1114 ".text\n"
1115 ".globl do_syscall_fast_WRK\n"
1116 "do_syscall_fast_WRK:\n"
1117 " movq %rdi, %rax\n"
1118 " int $0xD2\n"
1119 " movq %rdx, (%rsi)\n" /* save 2nd result word */
1120 " ret\n"
1121 ".previous\n"
1124 #else
1125 # error Unknown platform
1126 #endif
1129 /* Finally, the generic code. This sends the call to the right
1130 helper. */
1132 SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3,
1133 RegWord a4, RegWord a5, RegWord a6,
1134 RegWord a7, RegWord a8 )
1136 # if defined(VGP_x86_linux)
1137 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1138 return VG_(mk_SysRes_x86_linux)( val );
1140 # elif defined(VGP_amd64_linux)
1141 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1142 return VG_(mk_SysRes_amd64_linux)( val );
1144 # elif defined(VGP_x86_freebsd)
1145 ULong val;
1146 UInt err = 0;
1147 val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5,
1148 a6, a7, a8, &err);
1149 return VG_(mk_SysRes_x86_freebsd)( (UInt)val, (UInt)(val>>32), (err & 1) != 0 ? True : False);
1151 # elif defined(VGP_amd64_freebsd)
1152 UWord val;
1153 UWord val2 = 0;
1154 UInt err = 0;
1155 val = do_syscall_WRK(sysno, a1, a2, a3, a4, a5,
1156 a6, a7, a8, &err, &val2);
1157 return VG_(mk_SysRes_amd64_freebsd)( val, val2, (err & 1) != 0 ? True : False);
1159 # elif defined(VGP_ppc32_linux)
1160 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1161 UInt val = (UInt)(ret>>32);
1162 UInt cr0so = (UInt)(ret);
1163 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
1165 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
1166 ULong argblock[8];
1167 /* PPC system calls have at most 6 arguments. The Valgrind infrastructure
1168 supports 8 system call arguments. Argument 7 is used on PPC LE to pass
1169 the flag indicating if the sc or scv instruction should be used for the
1170 system call. */
1171 argblock[0] = sysno;
1172 argblock[1] = a1;
1173 argblock[2] = a2;
1174 argblock[3] = a3;
1175 argblock[4] = a4;
1176 argblock[5] = a5;
1177 argblock[6] = a6;
1178 argblock[7] = a7;
1179 do_syscall_WRK( &argblock[0] );
1180 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1], a7 );
1182 # elif defined(VGP_arm_linux)
1183 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
1184 return VG_(mk_SysRes_arm_linux)( val );
1186 # elif defined(VGP_arm64_linux)
1187 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
1188 return VG_(mk_SysRes_arm64_linux)( val );
1190 # elif defined(VGP_x86_darwin)
1191 UInt wLO = 0, wHI = 0, err = 0;
1192 ULong u64;
1193 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
1194 switch (scclass) {
1195 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1196 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1197 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
1198 wLO = (UInt)u64;
1199 wHI = (UInt)(u64 >> 32);
1200 break;
1201 case VG_DARWIN_SYSCALL_CLASS_MACH:
1202 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1203 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1204 err = 0;
1205 break;
1206 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1207 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1208 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1209 err = 0;
1210 break;
1211 default:
1212 vg_assert(0);
1213 break;
1215 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
1217 # elif defined(VGP_amd64_darwin)
1218 ULong wLO = 0, wHI = 0, err = 0;
1219 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
1220 switch (scclass) {
1221 case VG_DARWIN_SYSCALL_CLASS_UNIX:
1222 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1223 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
1224 break;
1225 case VG_DARWIN_SYSCALL_CLASS_MACH:
1226 case VG_DARWIN_SYSCALL_CLASS_MDEP:
1227 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1228 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
1229 err = 0;
1230 break;
1231 default:
1232 vg_assert(0);
1233 break;
1235 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
1237 #elif defined(VGP_s390x_linux)
1238 UWord val;
1240 if (sysno == __NR_mmap) {
1241 ULong argbuf[6];
1243 argbuf[0] = a1;
1244 argbuf[1] = a2;
1245 argbuf[2] = a3;
1246 argbuf[3] = a4;
1247 argbuf[4] = a5;
1248 argbuf[5] = a6;
1249 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
1250 } else {
1251 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1254 return VG_(mk_SysRes_s390x_linux)( val );
1256 #elif defined(VGP_mips32_linux)
1257 UWord err = 0;
1258 UWord valHi = 0;
1259 UWord valLo = 0;
1260 (void) do_syscall_WRK(a1, a2, a3, a4, a5, a6, a7, sysno, &err, &valHi, &valLo);
1261 return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
1263 #elif defined(VGP_mips64_linux)
1264 RegWord v1_a3[2];
1265 v1_a3[0] = 0xFF00;
1266 v1_a3[1] = 0xFF00;
1267 RegWord V0 = do_syscall_WRK(a1, a2, a3, a4, a5, a6, a7, sysno, v1_a3);
1268 RegWord V1 = (RegWord)v1_a3[0];
1269 RegWord A3 = (RegWord)v1_a3[1];
1270 return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
1272 #elif defined(VGP_nanomips_linux)
1273 RegWord reg_a0 = 0;
1274 do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, &reg_a0);
1275 return VG_(mk_SysRes_nanomips_linux)(reg_a0);
1277 # elif defined(VGP_x86_solaris)
1278 UInt val, val2, err = False;
1279 Bool restart;
1280 ULong u64;
1281 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno);
1283 switch (ssclass) {
1284 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
1285 /* The Solaris kernel does not restart syscalls automatically so it
1286 is done here. */
1287 do {
1288 u64 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1289 VG_SOLARIS_SYSNO_INDEX(sysno), &err);
1290 val = (UInt)u64;
1291 restart = err && (val == VKI_EINTR || val == VKI_ERESTART);
1292 } while (restart);
1293 break;
1294 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
1295 u64 = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno));
1296 break;
1297 default:
1298 vg_assert(0);
1299 break;
1302 val = (UInt)u64;
1303 val2 = (UInt)(u64 >> 32);
1304 return VG_(mk_SysRes_x86_solaris)(err ? True : False, val,
1305 err ? 0 : val2);
1307 # elif defined(VGP_amd64_solaris)
1308 ULong val, val2, err = False;
1309 Bool restart;
1310 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno);
1312 switch (ssclass) {
1313 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
1314 /* The Solaris kernel does not restart syscalls automatically so it
1315 is done here. */
1316 do {
1317 val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
1318 VG_SOLARIS_SYSNO_INDEX(sysno), &err, &val2);
1319 restart = err && (val == VKI_EINTR || val == VKI_ERESTART);
1320 } while (restart);
1321 break;
1322 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
1323 val = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno), &val2);
1324 break;
1325 default:
1326 vg_assert(0);
1327 break;
1330 return VG_(mk_SysRes_amd64_solaris)(err ? True : False, val,
1331 err ? 0 : val2);
1333 #else
1334 # error Unknown platform
1335 #endif
1338 /* ---------------------------------------------------------------------
1339 Names of errors.
1340 ------------------------------------------------------------------ */
1342 /* Return a string which gives the name of an error value. Note,
1343 unlike the standard C syserror fn, the returned string is not
1344 malloc-allocated or writable -- treat it as a constant.
1345 TODO: implement this properly. */
1347 const HChar* VG_(strerror) ( UWord errnum )
1349 switch (errnum) {
1350 case VKI_EPERM: return "Operation not permitted";
1351 case VKI_ENOENT: return "No such file or directory";
1352 case VKI_ESRCH: return "No such process";
1353 case VKI_EINTR: return "Interrupted system call";
1354 case VKI_EIO: return "Input/output error";
1355 case VKI_ENXIO: return "No such device or address";
1356 case VKI_E2BIG: return "Argument list too long";
1357 case VKI_ENOEXEC: return "Exec format error";
1358 case VKI_EBADF: return "Bad file descriptor";
1359 case VKI_ECHILD: return "No child processes";
1360 case VKI_EAGAIN: return "Resource temporarily unavailable";
1361 case VKI_ENOMEM: return "Cannot allocate memory";
1362 case VKI_EACCES: return "Permission denied";
1363 case VKI_EFAULT: return "Bad address";
1364 case VKI_ENOTBLK: return "Block device required";
1365 case VKI_EBUSY: return "Device or resource busy";
1366 case VKI_EEXIST: return "File exists";
1367 case VKI_EXDEV: return "Invalid cross-device link";
1368 case VKI_ENODEV: return "No such device";
1369 case VKI_ENOTDIR: return "Not a directory";
1370 case VKI_EISDIR: return "Is a directory";
1371 case VKI_EINVAL: return "Invalid argument";
1372 case VKI_ENFILE: return "Too many open files in system";
1373 case VKI_EMFILE: return "Too many open files";
1374 case VKI_ENOTTY: return "Inappropriate ioctl for device";
1375 case VKI_ETXTBSY: return "Text file busy";
1376 case VKI_EFBIG: return "File too large";
1377 case VKI_ENOSPC: return "No space left on device";
1378 case VKI_ESPIPE: return "Illegal seek";
1379 case VKI_EROFS: return "Read-only file system";
1380 case VKI_EMLINK: return "Too many links";
1381 case VKI_EPIPE: return "Broken pipe";
1382 case VKI_EDOM: return "Numerical argument out of domain";
1383 case VKI_ERANGE: return "Numerical result out of range";
1385 case VKI_ENOSYS: return "Function not implemented";
1386 case VKI_EOVERFLOW: return "Value too large for defined data type";
1387 # if defined(VKI_ERESTARTSYS)
1388 case VKI_ERESTARTSYS: return "ERESTARTSYS";
1389 # endif
1390 # if defined(VKI_ERESTART)
1391 case VKI_ERESTART: return "ERESTART";
1392 # endif
1393 default: return "VG_(strerror): unknown error";
1398 /*--------------------------------------------------------------------*/
1399 /*--- end ---*/
1400 /*--------------------------------------------------------------------*/