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