1
2 /*--------------------------------------------------------------------*/
3 /*--- Doing syscalls. m_syscall.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2013 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_syscall.h"
36
37 /* ---------------------------------------------------------------------
38 Building syscall return values.
39 ------------------------------------------------------------------ */
40
41 #if defined(VGO_linux)
42
43 /* Make a SysRes value from a syscall return value. This is
44 Linux-specific.
45
46 From:
47 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
48 linux/i386/sysdep.h?
49 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
50
51 Linux uses a negative return value to indicate syscall errors,
52 unlike most Unices, which use the condition codes' carry flag.
53
54 Since version 2.1 the return value of a system call might be
55 negative even if the call succeeded. E.g., the 'lseek' system call
56 might return a large offset. Therefore we must not anymore test
57 for < 0, but test for a real error by making sure the value in %eax
58 is a real error number. Linus said he will make sure the no
59 syscall returns a value in -1 .. -4095 as a valid result so we can
60 safely test with -4095.
61 */
62
VG_(mk_SysRes_x86_linux)63 SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
64 SysRes res;
65 res._isError = val >= -4095 && val <= -1;
66 if (res._isError) {
67 res._val = (UInt)(-val);
68 } else {
69 res._val = (UInt)val;
70 }
71 return res;
72 }
73
74 /* Similarly .. */
VG_(mk_SysRes_amd64_linux)75 SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
76 SysRes res;
77 res._isError = val >= -4095 && val <= -1;
78 if (res._isError) {
79 res._val = (ULong)(-val);
80 } else {
81 res._val = (ULong)val;
82 }
83 return res;
84 }
85
VG_(mk_SysRes_tilegx_linux)86 SysRes VG_(mk_SysRes_tilegx_linux) ( Long val ) {
87 SysRes res;
88 res._isError = val >= -4095 && val <= -1;
89 if (res._isError) {
90 res._val = (ULong)(-val);
91 } else {
92 res._val = (ULong)val;
93 }
94 return res;
95 }
96
97 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
98 /* Note this must be in the bottom bit of the second arg */
VG_(mk_SysRes_ppc32_linux)99 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
100 SysRes res;
101 res._isError = (cr0so & 1) != 0;
102 res._val = val;
103 return res;
104 }
105
106 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
VG_(mk_SysRes_ppc64_linux)107 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
108 SysRes res;
109 res._isError = (cr0so & 1) != 0;
110 res._val = val;
111 return res;
112 }
113
VG_(mk_SysRes_s390x_linux)114 SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
115 SysRes res;
116 res._isError = val >= -4095 && val <= -1;
117 if (res._isError) {
118 res._val = -val;
119 } else {
120 res._val = val;
121 }
122 return res;
123 }
124
VG_(mk_SysRes_arm_linux)125 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
126 SysRes res;
127 res._isError = val >= -4095 && val <= -1;
128 if (res._isError) {
129 res._val = (UInt)(-val);
130 } else {
131 res._val = (UInt)val;
132 }
133 return res;
134 }
135
VG_(mk_SysRes_arm64_linux)136 SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
137 SysRes res;
138 res._isError = val >= -4095 && val <= -1;
139 if (res._isError) {
140 res._val = (ULong)(-val);
141 } else {
142 res._val = (ULong)val;
143 }
144 return res;
145 }
146
147 #if defined(VGA_mips64) || defined(VGA_mips32)
148 /* MIPS uses a3 != 0 to flag an error */
VG_(mk_SysRes_mips32_linux)149 SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
150 SysRes res;
151 res._isError = (a3 != (UWord)0);
152 res._val = v0;
153 res._valEx = v1;
154 return res;
155 }
156
157 /* MIPS uses a3 != 0 to flag an error */
VG_(mk_SysRes_mips64_linux)158 SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) {
159 SysRes res;
160 res._isError = (a3 != (ULong)0);
161 res._val = v0;
162 res._valEx = v1;
163 return res;
164 }
165 #endif
166
167 /* Generic constructors. */
VG_(mk_SysRes_Error)168 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
169 SysRes r;
170 #if defined(VGA_mips64) || defined(VGA_mips32)
171 r._valEx = 0;
172 #endif
173 r._isError = True;
174 r._val = err;
175 return r;
176 }
177
VG_(mk_SysRes_Success)178 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
179 SysRes r;
180 #if defined(VGA_mips64) || defined(VGA_mips32)
181 r._valEx = 0;
182 #endif
183 r._isError = False;
184 r._val = res;
185 return r;
186 }
187
188
189 #elif defined(VGO_darwin)
190
191 /* Darwin: Some syscalls return a double-word result. */
VG_(mk_SysRes_x86_darwin)192 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
193 UInt wHI, UInt wLO )
194 {
195 SysRes res;
196 res._wHI = 0;
197 res._wLO = 0;
198 res._mode = 0; /* invalid */
199 vg_assert(isErr == False || isErr == True);
200 vg_assert(sizeof(UWord) == sizeof(UInt));
201 switch (scclass) {
202 case VG_DARWIN_SYSCALL_CLASS_UNIX:
203 res._wLO = wLO;
204 res._wHI = wHI;
205 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
206 break;
207 case VG_DARWIN_SYSCALL_CLASS_MACH:
208 vg_assert(!isErr);
209 vg_assert(wHI == 0);
210 res._wLO = wLO;
211 res._mode = SysRes_MACH;
212 break;
213 case VG_DARWIN_SYSCALL_CLASS_MDEP:
214 vg_assert(!isErr);
215 vg_assert(wHI == 0);
216 res._wLO = wLO;
217 res._mode = SysRes_MDEP;
218 break;
219 default:
220 vg_assert(0);
221 }
222 return res;
223 }
224
VG_(mk_SysRes_amd64_darwin)225 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
226 ULong wHI, ULong wLO )
227 {
228 SysRes res;
229 res._wHI = 0;
230 res._wLO = 0;
231 res._mode = 0; /* invalid */
232 vg_assert(isErr == False || isErr == True);
233 vg_assert(sizeof(UWord) == sizeof(ULong));
234 switch (scclass) {
235 case VG_DARWIN_SYSCALL_CLASS_UNIX:
236 res._wLO = wLO;
237 res._wHI = wHI;
238 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
239 break;
240 case VG_DARWIN_SYSCALL_CLASS_MACH:
241 vg_assert(!isErr);
242 vg_assert(wHI == 0);
243 res._wLO = wLO;
244 res._mode = SysRes_MACH;
245 break;
246 case VG_DARWIN_SYSCALL_CLASS_MDEP:
247 vg_assert(!isErr);
248 vg_assert(wHI == 0);
249 res._wLO = wLO;
250 res._mode = SysRes_MDEP;
251 break;
252 default:
253 vg_assert(0);
254 }
255 return res;
256 }
257
258 /* Generic constructors. We assume (without checking if this makes
259 any sense, from the caller's point of view) that these are for the
260 UNIX style of syscall. */
VG_(mk_SysRes_Error)261 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
262 SysRes r;
263 r._wHI = 0;
264 r._wLO = err;
265 r._mode = SysRes_UNIX_ERR;
266 return r;
267 }
268
VG_(mk_SysRes_Success)269 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
270 SysRes r;
271 r._wHI = 0;
272 r._wLO = res;
273 r._mode = SysRes_UNIX_OK;
274 return r;
275 }
276
277
278 #else
279 # error "Unknown OS"
280 #endif
281
282
283 /* ---------------------------------------------------------------------
284 VG_(do_syscall): A function for doing syscalls.
285 ------------------------------------------------------------------ */
286
287 #if defined(VGP_x86_linux)
288 /* Incoming args (syscall number + up to 6 args) come on the stack.
289 (ie. the C calling convention).
290
291 The syscall number goes in %eax. The args are passed to the syscall in
292 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
293 calling convention.
294
295 %eax gets the return value. Not sure which registers the kernel
296 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
297 %ebp).
298 */
299 extern UWord do_syscall_WRK (
300 UWord syscall_no,
301 UWord a1, UWord a2, UWord a3,
302 UWord a4, UWord a5, UWord a6
303 );
304 asm(
305 ".text\n"
306 ".globl do_syscall_WRK\n"
307 "do_syscall_WRK:\n"
308 " .cfi_startproc\n"
309 " push %esi\n"
310 " .cfi_adjust_cfa_offset 4\n"
311 " .cfi_offset %esi, -8\n"
312 " push %edi\n"
313 " .cfi_adjust_cfa_offset 4\n"
314 " .cfi_offset %edi, -12\n"
315 " push %ebx\n"
316 " .cfi_adjust_cfa_offset 4\n"
317 " .cfi_offset %ebx, -16\n"
318 " push %ebp\n"
319 " .cfi_adjust_cfa_offset 4\n"
320 " .cfi_offset %ebp, -20\n"
321 " movl 16+ 4(%esp),%eax\n"
322 " movl 16+ 8(%esp),%ebx\n"
323 " movl 16+12(%esp),%ecx\n"
324 " movl 16+16(%esp),%edx\n"
325 " movl 16+20(%esp),%esi\n"
326 " movl 16+24(%esp),%edi\n"
327 " movl 16+28(%esp),%ebp\n"
328 " int $0x80\n"
329 " popl %ebp\n"
330 " .cfi_adjust_cfa_offset -4\n"
331 " .cfi_restore %ebp\n"
332 " popl %ebx\n"
333 " .cfi_adjust_cfa_offset -4\n"
334 " .cfi_restore %ebx\n"
335 " popl %edi\n"
336 " .cfi_adjust_cfa_offset -4\n"
337 " .cfi_restore %edi\n"
338 " popl %esi\n"
339 " .cfi_adjust_cfa_offset -4\n"
340 " .cfi_restore %esi\n"
341 " ret\n"
342 " .cfi_endproc\n"
343 ".previous\n"
344 );
345
346 #elif defined(VGP_amd64_linux)
347 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
348 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
349 calling convention).
350
351 The syscall number goes in %rax. The args are passed to the syscall in
352 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
353 ie. the kernel's syscall calling convention.
354
355 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
356 no matter, they are caller-save (the syscall clobbers no callee-save
357 regs, so we don't have to do any register saving/restoring).
358 */
359 extern UWord do_syscall_WRK (
360 UWord syscall_no,
361 UWord a1, UWord a2, UWord a3,
362 UWord a4, UWord a5, UWord a6
363 );
364 asm(
365 ".text\n"
366 ".globl do_syscall_WRK\n"
367 "do_syscall_WRK:\n"
368 /* Convert function calling convention --> syscall calling
369 convention */
370 " movq %rdi, %rax\n"
371 " movq %rsi, %rdi\n"
372 " movq %rdx, %rsi\n"
373 " movq %rcx, %rdx\n"
374 " movq %r8, %r10\n"
375 " movq %r9, %r8\n"
376 " movq 8(%rsp), %r9\n" /* last arg from stack */
377 " syscall\n"
378 " ret\n"
379 ".previous\n"
380 );
381
382 #elif defined(VGP_ppc32_linux)
383 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
384
385 The syscall number goes in %r0. The args are passed to the syscall in
386 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
387
388 The %cr0.so bit flags an error.
389 We return the syscall return value in %r3, and the %cr0.so in
390 the lowest bit of %r4.
391 We return a ULong, of which %r3 is the high word, and %r4 the low.
392 No callee-save regs are clobbered, so no saving/restoring is needed.
393 */
394 extern ULong do_syscall_WRK (
395 UWord syscall_no,
396 UWord a1, UWord a2, UWord a3,
397 UWord a4, UWord a5, UWord a6
398 );
399 asm(
400 ".text\n"
401 ".globl do_syscall_WRK\n"
402 "do_syscall_WRK:\n"
403 " mr 0,3\n"
404 " mr 3,4\n"
405 " mr 4,5\n"
406 " mr 5,6\n"
407 " mr 6,7\n"
408 " mr 7,8\n"
409 " mr 8,9\n"
410 " sc\n" /* syscall: sets %cr0.so on error */
411 " mfcr 4\n" /* %cr -> low word of return var */
412 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
413 " blr\n" /* and return */
414 ".previous\n"
415 );
416
417 #elif defined(VGP_ppc64be_linux)
418 /* Due to the need to return 65 bits of result, this is completely
419 different from the ppc32 case. The single arg register points to a
420 7-word block containing the syscall # and the 6 args. The syscall
421 result proper is put in [0] of the block, and %cr0.so is in the
422 bottom bit of [1]. */
423 extern void do_syscall_WRK ( ULong* argblock );
424 asm(
425 ".align 2\n"
426 ".globl do_syscall_WRK\n"
427 ".section \".opd\",\"aw\"\n"
428 ".align 3\n"
429 "do_syscall_WRK:\n"
430 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
431 ".previous\n"
432 ".type .do_syscall_WRK,@function\n"
433 ".globl .do_syscall_WRK\n"
434 ".do_syscall_WRK:\n"
435 " std 3,-16(1)\n" /* stash arg */
436 " ld 8, 48(3)\n" /* sc arg 6 */
437 " ld 7, 40(3)\n" /* sc arg 5 */
438 " ld 6, 32(3)\n" /* sc arg 4 */
439 " ld 5, 24(3)\n" /* sc arg 3 */
440 " ld 4, 16(3)\n" /* sc arg 2 */
441 " ld 0, 0(3)\n" /* sc number */
442 " ld 3, 8(3)\n" /* sc arg 1 */
443 " sc\n" /* result in r3 and cr0.so */
444 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
445 " std 3,0(5)\n" /* argblock[0] = r3 */
446 " mfcr 3\n"
447 " srwi 3,3,28\n"
448 " andi. 3,3,1\n"
449 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
450 " blr\n"
451 );
452
453 #elif defined(VGP_ppc64le_linux)
454 /* Due to the need to return 65 bits of result, this is completely
455 different from the ppc32 case. The single arg register points to a
456 7-word block containing the syscall # and the 6 args. The syscall
457 result proper is put in [0] of the block, and %cr0.so is in the
458 bottom bit of [1]. */
459 extern void do_syscall_WRK ( ULong* argblock );
460 /* Little Endian supports ELF version 2. In the future, it may support
461 * other versions as well.
462 */
463 asm(
464 ".align 2\n"
465 ".globl do_syscall_WRK\n"
466 ".type do_syscall_WRK,@function\n"
467 "do_syscall_WRK:\n"
468 "#if _CALL_ELF == 2" "\n"
469 "0: addis 2,12,.TOC.-0b@ha\n"
470 " addi 2,2,.TOC.-0b@l\n"
471 " .localentry do_syscall_WRK, .-do_syscall_WRK\n"
472 "#endif" "\n"
473 " std 3,-16(1)\n" /* stash arg */
474 " ld 8, 48(3)\n" /* sc arg 6 */
475 " ld 7, 40(3)\n" /* sc arg 5 */
476 " ld 6, 32(3)\n" /* sc arg 4 */
477 " ld 5, 24(3)\n" /* sc arg 3 */
478 " ld 4, 16(3)\n" /* sc arg 2 */
479 " ld 0, 0(3)\n" /* sc number */
480 " ld 3, 8(3)\n" /* sc arg 1 */
481 " sc\n" /* result in r3 and cr0.so */
482 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
483 " std 3,0(5)\n" /* argblock[0] = r3 */
484 " mfcr 3\n"
485 " srwi 3,3,28\n"
486 " andi. 3,3,1\n"
487 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
488 " blr\n"
489 " .size do_syscall_WRK, .-do_syscall_WRK\n"
490 );
491
492 #elif defined(VGP_arm_linux)
493 /* I think the conventions are:
494 args in r0 r1 r2 r3 r4 r5
495 sysno in r7
496 return value in r0, w/ same conventions as x86-linux, viz r0 in
497 -4096 .. -1 is an error value. All other values are success
498 values.
499 */
500 extern UWord do_syscall_WRK (
501 UWord a1, UWord a2, UWord a3,
502 UWord a4, UWord a5, UWord a6,
503 UWord syscall_no
504 );
505 asm(
506 ".text\n"
507 ".globl do_syscall_WRK\n"
508 "do_syscall_WRK:\n"
509 " push {r4, r5, r7}\n"
510 " ldr r4, [sp, #12]\n"
511 " ldr r5, [sp, #16]\n"
512 " ldr r7, [sp, #20]\n"
513 " svc 0x0\n"
514 " pop {r4, r5, r7}\n"
515 " bx lr\n"
516 ".previous\n"
517 );
518
519 #elif defined(VGP_arm64_linux)
520 /* I think the conventions are:
521 args in r0 r1 r2 r3 r4 r5
522 sysno in r8
523 return value in r0, w/ same conventions as x86-linux, viz r0 in
524 -4096 .. -1 is an error value. All other values are success
525 values.
526
527 r0 to r5 remain unchanged, but syscall_no is in r6 and needs
528 to be moved to r8 (??)
529 */
530 extern UWord do_syscall_WRK (
531 UWord a1, UWord a2, UWord a3,
532 UWord a4, UWord a5, UWord a6,
533 UWord syscall_no
534 );
535 asm(
536 ".text\n"
537 ".globl do_syscall_WRK\n"
538 "do_syscall_WRK:\n"
539 " mov x8, x6\n"
540 " mov x6, 0\n"
541 " mov x7, 0\n"
542 " svc 0\n"
543 " ret\n"
544 ".previous\n"
545 );
546
547 #elif defined(VGP_x86_darwin)
548
549 /* Incoming args (syscall number + up to 8 args) come in on the stack
550
551 The kernel's syscall calling convention is:
552 * the syscall number goes in eax
553 * the args are passed to the syscall on the stack,
554 pushed onto the stack R->L (that is, the usual x86
555 calling conventions, with the leftmost arg at the lowest
556 address)
557 Call instruction:
558 * UNIX: sysenter
559 * UNIX: int $0x80
560 * MACH: int $0x81
561 * MDEP: int $0x82
562 Note that the call type can be determined from the syscall number;
563 there is no need to inspect the actual instruction. Although obviously
564 the instruction must match.
565 Return value:
566 * MACH,MDEP: the return value comes back in eax
567 * UNIX: the return value comes back in edx:eax (hi32:lo32)
568 Error:
569 * MACH,MDEP: no error is returned
570 * UNIX: the carry flag indicates success or failure
571
572 nb here, sizeof(UWord) == sizeof(UInt)
573 */
574
575 __private_extern__ ULong
576 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
577 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
578 UWord a7, UWord a8, /* 28(esp)..32(esp) */
579 UWord syscall_no, /* 36(esp) */
580 /*OUT*/UInt* errflag /* 40(esp) */ );
581 // Unix syscall: 64-bit return in edx:eax, with LSB in eax
582 // error indicated by carry flag: clear=good, set=bad
583 asm(".private_extern _do_syscall_unix_WRK\n"
584 "_do_syscall_unix_WRK:\n"
585 " movl 40(%esp), %ecx \n" /* assume syscall success */
586 " movl $0, (%ecx) \n"
587 " movl 36(%esp), %eax \n"
588 " int $0x80 \n"
589 " jnc 1f \n" /* jump if success */
590 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
591 " movl $1, (%ecx) \n"
592 " 1: ret \n"
593 );
594
595 __private_extern__ UInt
596 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
597 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
598 UWord a7, UWord a8, /* 28(esp)..32(esp) */
599 UWord syscall_no /* 36(esp) */ );
600 // Mach trap: 32-bit result in %eax, no error flag
601 asm(".private_extern _do_syscall_mach_WRK\n"
602 "_do_syscall_mach_WRK:\n"
603 " movl 36(%esp), %eax \n"
604 " int $0x81 \n"
605 " ret \n"
606 );
607
608 __private_extern__ UInt
609 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
610 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
611 UWord a7, UWord a8, /* 28(esp)..32(esp) */
612 UWord syscall_no /* 36(esp) */ );
613 // mdep trap: 32-bit result in %eax, no error flag
614 asm(
615 ".private_extern _do_syscall_mdep_WRK\n"
616 "_do_syscall_mdep_WRK:\n"
617 " movl 36(%esp), %eax \n"
618 " int $0x82 \n"
619 " ret \n"
620 );
621
622
623 #elif defined(VGP_amd64_darwin)
624
625 /* Incoming args (syscall number + up to 8 args) come in registers and stack
626
627 The kernel's syscall calling convention is:
628 * the syscall number goes in rax
629 * the args are passed to the syscall in registers and the stack
630 * the call instruction is 'syscall'
631 Return value:
632 * MACH,MDEP: the return value comes back in rax
633 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
634 Error:
635 * MACH,MDEP: no error is returned
636 * UNIX: the carry flag indicates success or failure
637
638 nb here, sizeof(UWord) == sizeof(ULong)
639 */
640
641 __private_extern__ UWord
642 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
643 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
644 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
645 UWord syscall_no, /* 24(rsp) */
646 /*OUT*/ULong* errflag, /* 32(rsp) */
647 /*OUT*/ULong* res2 ); /* 40(rsp) */
648 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax
649 // error indicated by carry flag: clear=good, set=bad
650 asm(".private_extern _do_syscall_unix_WRK\n"
651 "_do_syscall_unix_WRK:\n"
652 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
653 " movq 32(%rsp), %rax \n" /* assume syscall success */
654 " movq $0, (%rax) \n"
655 " movq 24(%rsp), %rax \n" /* load syscall_no */
656 " syscall \n"
657 " jnc 1f \n" /* jump if success */
658 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
659 " movq $1, (%rcx) \n"
660 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
661 " movq %rdx, (%rcx) \n"
662 " retq \n" /* return 1st result word */
663 );
664
665 __private_extern__ UWord
666 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
667 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
668 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
669 UWord syscall_no ); /* 24(rsp) */
670 // Mach trap: 64-bit result, no error flag
671 asm(".private_extern _do_syscall_mach_WRK\n"
672 "_do_syscall_mach_WRK:\n"
673 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
674 " movq 24(%rsp), %rax \n" /* load syscall_no */
675 " syscall \n"
676 " retq \n"
677 );
678
679 #elif defined(VGP_s390x_linux)
680
do_syscall_WRK(UWord syscall_no,UWord arg1,UWord arg2,UWord arg3,UWord arg4,UWord arg5,UWord arg6)681 static UWord do_syscall_WRK (
682 UWord syscall_no,
683 UWord arg1, UWord arg2, UWord arg3,
684 UWord arg4, UWord arg5, UWord arg6
685 )
686 {
687 register UWord __arg1 asm("2") = arg1;
688 register UWord __arg2 asm("3") = arg2;
689 register UWord __arg3 asm("4") = arg3;
690 register UWord __arg4 asm("5") = arg4;
691 register UWord __arg5 asm("6") = arg5;
692 register UWord __arg6 asm("7") = arg6;
693 register ULong __svcres asm("2");
694
695 __asm__ __volatile__ (
696 "lgr %%r1,%1\n\t"
697 "svc 0\n\t"
698 : "=d" (__svcres)
699 : "a" (syscall_no),
700 "0" (__arg1),
701 "d" (__arg2),
702 "d" (__arg3),
703 "d" (__arg4),
704 "d" (__arg5),
705 "d" (__arg6)
706 : "1", "cc", "memory");
707
708 return (UWord) (__svcres);
709 }
710
711 #elif defined(VGP_mips32_linux)
712 /* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
713
714 The syscall number goes in v0. The args are passed to the syscall in
715 the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
716
717 (a3 != 0) flags an error.
718 We return the syscall return value in v0.
719 MIPS version
720 */
721 extern int do_syscall_WRK (
722 int a1, int a2, int a3,
723 int a4, int a5, int a6, int syscall_no, UWord *err,
724 UWord *valHi, UWord* valLo
725 );
726 asm(
727 ".globl do_syscall_WRK\n"
728 ".ent do_syscall_WRK\n"
729 ".text\n"
730 "do_syscall_WRK:\n"
731 " lw $2, 24($29)\n"
732 " syscall\n"
733 " lw $8, 28($29)\n"
734 " sw $7, ($8)\n"
735 " lw $8, 32($29)\n"
736 " sw $3, ($8)\n" // store valHi
737 " lw $8, 36($29)\n"
738 " sw $2, ($8)\n" // store valLo
739 " jr $31\n"
740 " nop\n"
741 ".previous\n"
742 ".end do_syscall_WRK\n"
743 );
744
745 #elif defined(VGP_mips64_linux)
746 extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
747 UWord a6, UWord syscall_no, ULong* V1_val );
748 asm (
749 ".text\n"
750 ".globl do_syscall_WRK\n"
751 "do_syscall_WRK:\n"
752 " daddiu $29, $29, -8\n"
753 " sd $11, 0($29)\n"
754 " move $2, $10\n"
755 " syscall\n"
756 " ld $11, 0($29)\n"
757 " daddiu $29, $29, 8\n"
758 " sd $3, 0($11)\n" /* store vale of v1 in last param */
759 " sd $7, 8($11)\n" /* store vale of a3 in last param */
760 " jr $31\n"
761 ".previous\n"
762 );
763
764 #elif defined(VGP_tilegx_linux)
765 extern UWord do_syscall_WRK (
766 UWord syscall_no,
767 UWord a1, UWord a2, UWord a3,
768 UWord a4, UWord a5, UWord a6
769 );
770 asm(
771 ".text\n"
772 "do_syscall_WRK:\n"
773 "move r10, r0\n"
774 "move r0, r1\n"
775 "move r1, r2\n"
776 "move r2, r3\n"
777 "move r3, r4\n"
778 "move r4, r5\n"
779 "move r5, r6\n"
780 "swint1\n"
781 "jrp lr\n"
782 ".previous\n"
783 );
784
785 #else
786 # error Unknown platform
787 #endif
788
789
790 /* Finally, the generic code. This sends the call to the right
791 helper. */
792
VG_(do_syscall)793 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
794 UWord a4, UWord a5, UWord a6,
795 UWord a7, UWord a8 )
796 {
797 # if defined(VGP_x86_linux)
798 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
799 return VG_(mk_SysRes_x86_linux)( val );
800
801 # elif defined(VGP_amd64_linux)
802 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
803 return VG_(mk_SysRes_amd64_linux)( val );
804
805 # elif defined(VGP_ppc32_linux)
806 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
807 UInt val = (UInt)(ret>>32);
808 UInt cr0so = (UInt)(ret);
809 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
810
811 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
812 ULong argblock[7];
813 argblock[0] = sysno;
814 argblock[1] = a1;
815 argblock[2] = a2;
816 argblock[3] = a3;
817 argblock[4] = a4;
818 argblock[5] = a5;
819 argblock[6] = a6;
820 do_syscall_WRK( &argblock[0] );
821 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
822
823 # elif defined(VGP_arm_linux)
824 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
825 return VG_(mk_SysRes_arm_linux)( val );
826
827 # elif defined(VGP_arm64_linux)
828 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
829 return VG_(mk_SysRes_arm64_linux)( val );
830
831 # elif defined(VGP_x86_darwin)
832 UInt wLO = 0, wHI = 0, err = 0;
833 ULong u64;
834 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
835 switch (scclass) {
836 case VG_DARWIN_SYSCALL_CLASS_UNIX:
837 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
838 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
839 wLO = (UInt)u64;
840 wHI = (UInt)(u64 >> 32);
841 break;
842 case VG_DARWIN_SYSCALL_CLASS_MACH:
843 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
844 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
845 err = 0;
846 break;
847 case VG_DARWIN_SYSCALL_CLASS_MDEP:
848 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
849 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
850 err = 0;
851 break;
852 default:
853 vg_assert(0);
854 break;
855 }
856 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
857
858 # elif defined(VGP_amd64_darwin)
859 ULong wLO = 0, wHI = 0, err = 0;
860 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
861 switch (scclass) {
862 case VG_DARWIN_SYSCALL_CLASS_UNIX:
863 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
864 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
865 break;
866 case VG_DARWIN_SYSCALL_CLASS_MACH:
867 case VG_DARWIN_SYSCALL_CLASS_MDEP:
868 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
869 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
870 err = 0;
871 break;
872 default:
873 vg_assert(0);
874 break;
875 }
876 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
877
878 #elif defined(VGP_s390x_linux)
879 UWord val;
880
881 if (sysno == __NR_mmap) {
882 ULong argbuf[6];
883
884 argbuf[0] = a1;
885 argbuf[1] = a2;
886 argbuf[2] = a3;
887 argbuf[3] = a4;
888 argbuf[4] = a5;
889 argbuf[5] = a6;
890 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
891 } else {
892 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
893 }
894
895 return VG_(mk_SysRes_s390x_linux)( val );
896
897 #elif defined(VGP_mips32_linux)
898 UWord err = 0;
899 UWord valHi = 0;
900 UWord valLo = 0;
901 (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
902 return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
903
904 #elif defined(VGP_mips64_linux)
905 ULong v1_a3[2];
906 v1_a3[0] = 0xFF00;
907 v1_a3[1] = 0xFF00;
908 ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3);
909 ULong V1 = (ULong)v1_a3[0];
910 ULong A3 = (ULong)v1_a3[1];
911 return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
912
913 # elif defined(VGP_tilegx_linux)
914 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
915
916 return VG_(mk_SysRes_tilegx_linux)( val );
917
918 #else
919 # error Unknown platform
920 #endif
921 }
922
923 /* ---------------------------------------------------------------------
924 Names of errors.
925 ------------------------------------------------------------------ */
926
927 /* Return a string which gives the name of an error value. Note,
928 unlike the standard C syserror fn, the returned string is not
929 malloc-allocated or writable -- treat it as a constant.
930 TODO: implement this properly. */
931
VG_(strerror)932 const HChar* VG_(strerror) ( UWord errnum )
933 {
934 switch (errnum) {
935 case VKI_EPERM: return "Operation not permitted";
936 case VKI_ENOENT: return "No such file or directory";
937 case VKI_ESRCH: return "No such process";
938 case VKI_EINTR: return "Interrupted system call";
939 case VKI_EIO: return "Input/output error";
940 case VKI_ENXIO: return "No such device or address";
941 case VKI_E2BIG: return "Argument list too long";
942 case VKI_ENOEXEC: return "Exec format error";
943 case VKI_EBADF: return "Bad file descriptor";
944 case VKI_ECHILD: return "No child processes";
945 case VKI_EAGAIN: return "Resource temporarily unavailable";
946 case VKI_ENOMEM: return "Cannot allocate memory";
947 case VKI_EACCES: return "Permission denied";
948 case VKI_EFAULT: return "Bad address";
949 case VKI_ENOTBLK: return "Block device required";
950 case VKI_EBUSY: return "Device or resource busy";
951 case VKI_EEXIST: return "File exists";
952 case VKI_EXDEV: return "Invalid cross-device link";
953 case VKI_ENODEV: return "No such device";
954 case VKI_ENOTDIR: return "Not a directory";
955 case VKI_EISDIR: return "Is a directory";
956 case VKI_EINVAL: return "Invalid argument";
957 case VKI_ENFILE: return "Too many open files in system";
958 case VKI_EMFILE: return "Too many open files";
959 case VKI_ENOTTY: return "Inappropriate ioctl for device";
960 case VKI_ETXTBSY: return "Text file busy";
961 case VKI_EFBIG: return "File too large";
962 case VKI_ENOSPC: return "No space left on device";
963 case VKI_ESPIPE: return "Illegal seek";
964 case VKI_EROFS: return "Read-only file system";
965 case VKI_EMLINK: return "Too many links";
966 case VKI_EPIPE: return "Broken pipe";
967 case VKI_EDOM: return "Numerical argument out of domain";
968 case VKI_ERANGE: return "Numerical result out of range";
969
970 case VKI_ENOSYS: return "Function not implemented";
971 case VKI_EOVERFLOW: return "Value too large for defined data type";
972 # if defined(VKI_ERESTARTSYS)
973 case VKI_ERESTARTSYS: return "ERESTARTSYS";
974 # endif
975 default: return "VG_(strerror): unknown error";
976 }
977 }
978
979
980 /*--------------------------------------------------------------------*/
981 /*--- end ---*/
982 /*--------------------------------------------------------------------*/
983