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-2015 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
VG_(mk_SysRes_tilegx_linux)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;
141 }
142 return res;
143 }
144
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 */
VG_(mk_SysRes_ppc32_linux)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;
152 }
153
154 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
VG_(mk_SysRes_ppc64_linux)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;
160 }
161
VG_(mk_SysRes_s390x_linux)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;
169 }
170 return res;
171 }
172
VG_(mk_SysRes_arm_linux)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;
180 }
181 return res;
182 }
183
VG_(mk_SysRes_arm64_linux)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;
191 }
192 return res;
193 }
194
195 /* Generic constructors. */
VG_(mk_SysRes_Error)196 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
197 SysRes r;
198 r._isError = True;
199 r._val = err;
200 return r;
201 }
202
VG_(mk_SysRes_Success)203 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
204 SysRes r;
205 r._isError = False;
206 r._val = res;
207 return r;
208 }
209
210
211 #elif defined(VGO_darwin)
212
213 /* Darwin: Some syscalls return a double-word result. */
VG_(mk_SysRes_x86_darwin)214 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
215 UInt wHI, UInt wLO )
216 {
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);
243 }
244 return res;
245 }
246
VG_(mk_SysRes_amd64_darwin)247 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
248 ULong wHI, ULong wLO )
249 {
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);
276 }
277 return res;
278 }
279
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. */
VG_(mk_SysRes_Error)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;
289 }
290
VG_(mk_SysRes_Success)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;
297 }
298
299
300 #elif defined(VGO_solaris)
301
302 /* Generic constructors. */
VG_(mk_SysRes_Error)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;
309 }
310
VG_(mk_SysRes_Success)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;
317 }
318
VG_(mk_SysRes_x86_solaris)319 SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 )
320 {
321 SysRes res;
322
323 // stay sane
324 vg_assert(isErr == True || isErr == False);
325
326 res._val = val;
327 res._val2 = val2;
328 res._isError = isErr;
329 return res;
330 }
331
VG_(mk_SysRes_amd64_solaris)332 SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 )
333 {
334 SysRes res;
335
336 // stay sane
337 vg_assert(isErr == True || isErr == False);
338
339 res._val = val;
340 res._val2 = val2;
341 res._isError = isErr;
342 return res;
343 }
344
345 #else
346 # error "Unknown OS"
347 #endif
348
349
350 /* ---------------------------------------------------------------------
351 VG_(do_syscall): A function for doing syscalls.
352 ------------------------------------------------------------------ */
353
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).
357
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.
361
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).
365 */
366 extern UWord do_syscall_WRK (
367 UWord syscall_no,
368 UWord a1, UWord a2, UWord a3,
369 UWord a4, UWord a5, UWord a6
370 );
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"
411 );
412
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).
417
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.
421
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).
425 */
426 extern UWord do_syscall_WRK (
427 UWord syscall_no,
428 UWord a1, UWord a2, UWord a3,
429 UWord a4, UWord a5, UWord a6
430 );
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"
447 );
448
449 #elif defined(VGP_ppc32_linux)
450 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
451
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.
454
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.
460 */
461 extern ULong do_syscall_WRK (
462 UWord syscall_no,
463 UWord a1, UWord a2, UWord a3,
464 UWord a4, UWord a5, UWord a6
465 );
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"
482 );
483
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"
518 );
519
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.
529 */
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"
557 );
558
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.
566 */
567 extern UWord do_syscall_WRK (
568 UWord a1, UWord a2, UWord a3,
569 UWord a4, UWord a5, UWord a6,
570 UWord syscall_no
571 );
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"
584 );
585
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.
593
594 r0 to r5 remain unchanged, but syscall_no is in r6 and needs
595 to be moved to r8 (??)
596 */
597 extern UWord do_syscall_WRK (
598 UWord a1, UWord a2, UWord a3,
599 UWord a4, UWord a5, UWord a6,
600 UWord syscall_no
601 );
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"
612 );
613
614 #elif defined(VGP_x86_darwin)
615
616 /* Incoming args (syscall number + up to 8 args) come in on the stack
617
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
638
639 nb here, sizeof(UWord) == sizeof(UInt)
640 */
641
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"
660 );
661
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"
673 );
674
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"
687 );
688
689
690 #elif defined(VGP_amd64_darwin)
691
692 /* Incoming args (syscall number + up to 8 args) come in registers and stack
693
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
704
705 nb here, sizeof(UWord) == sizeof(ULong)
706 */
707
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 */
730 );
731
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"
744 );
745
746 #elif defined(VGP_s390x_linux)
747
do_syscall_WRK(UWord syscall_no,UWord arg1,UWord arg2,UWord arg3,UWord arg4,UWord arg5,UWord arg6)748 static UWord do_syscall_WRK (
749 UWord syscall_no,
750 UWord arg1, UWord arg2, UWord arg3,
751 UWord arg4, UWord arg5, UWord arg6
752 )
753 {
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");
761
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");
774
775 return (UWord) (__svcres);
776 }
777
778 #elif defined(VGP_mips32_linux)
779 /* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
780
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.
783
784 (a3 != 0) flags an error.
785 We return the syscall return value in v0.
786 MIPS version
787 */
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
792 );
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"
810 );
811
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"
829 );
830
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
836 );
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"
850 );
851
852 #elif defined(VGP_x86_solaris)
853
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"
876 );
877
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"
890 );
891
892 #elif defined(VGP_amd64_solaris)
893
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"
921 );
922
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"
937 );
938
939 #else
940 # error Unknown platform
941 #endif
942
943
944 /* Finally, the generic code. This sends the call to the right
945 helper. */
946
VG_(do_syscall)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 )
950 {
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 );
954
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 );
958
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 );
964
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] );
976
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 );
980
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 );
984
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;
1009 }
1010 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
1011
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;
1029 }
1030 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
1031
1032 #elif defined(VGP_s390x_linux)
1033 UWord val;
1034
1035 if (sysno == __NR_mmap) {
1036 ULong argbuf[6];
1037
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);
1047 }
1048
1049 return VG_(mk_SysRes_s390x_linux)( val );
1050
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 );
1057
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 );
1066
1067 # elif defined(VGP_tilegx_linux)
1068 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
1069
1070 return VG_(mk_SysRes_tilegx_linux)( val );
1071
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);
1077
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;
1095 }
1096
1097 val = (UInt)u64;
1098 val2 = (UInt)(u64 >> 32);
1099 return VG_(mk_SysRes_x86_solaris)(err ? True : False, val,
1100 err ? 0 : val2);
1101
1102 # elif defined(VGP_amd64_solaris)
1103 ULong val, val2, err = False;
1104 Bool restart;
1105 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno);
1106
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;
1123 }
1124
1125 return VG_(mk_SysRes_amd64_solaris)(err ? True : False, val,
1126 err ? 0 : val2);
1127
1128 #else
1129 # error Unknown platform
1130 #endif
1131 }
1132
1133 /* ---------------------------------------------------------------------
1134 Names of errors.
1135 ------------------------------------------------------------------ */
1136
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. */
1141
VG_(strerror)1142 const HChar* VG_(strerror) ( UWord errnum )
1143 {
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";
1179
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";
1186 }
1187 }
1188
1189
1190 /*--------------------------------------------------------------------*/
1191 /*--- end ---*/
1192 /*--------------------------------------------------------------------*/
1193