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-2010 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
86 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
87 /* Note this must be in the bottom bit of the second arg */
VG_(mk_SysRes_ppc32_linux)88 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
89 SysRes res;
90 res._isError = (cr0so & 1) != 0;
91 res._val = val;
92 return res;
93 }
94
95 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
VG_(mk_SysRes_ppc64_linux)96 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
97 SysRes res;
98 res._isError = (cr0so & 1) != 0;
99 res._val = val;
100 return res;
101 }
102
VG_(mk_SysRes_arm_linux)103 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
104 SysRes res;
105 res._isError = val >= -4095 && val <= -1;
106 if (res._isError) {
107 res._val = (UInt)(-val);
108 } else {
109 res._val = (UInt)val;
110 }
111 return res;
112 }
113
114 /* Generic constructors. */
VG_(mk_SysRes_Error)115 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
116 SysRes r;
117 r._isError = True;
118 r._val = err;
119 return r;
120 }
121
VG_(mk_SysRes_Success)122 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
123 SysRes r;
124 r._isError = False;
125 r._val = res;
126 return r;
127 }
128
129
130 #elif defined(VGO_aix5)
131
132 /* AIX scheme: we have to record both 'res' (r3) and 'err' (r4). If
133 'err' is nonzero then the call has failed, but it could still be
134 that AIX userspace will ignore 'err' and instead consult 'res' to
135 determine if the call failed. So we have to record both. */
VG_(mk_SysRes_ppc32_aix5)136 SysRes VG_(mk_SysRes_ppc32_aix5) ( UInt res, UInt err ) {
137 SysRes r;
138 r.res = res;
139 r.err = err;
140 r.isError = r.err != 0;
141 return r;
142 }
143
VG_(mk_SysRes_ppc64_aix5)144 SysRes VG_(mk_SysRes_ppc64_aix5) ( ULong res, ULong err ) {
145 SysRes r;
146 r.res = res;
147 r.err = err;
148 r.isError = r.err != 0;
149 return r;
150 }
151
152 /* Generic constructors. */
VG_(mk_SysRes_Error)153 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
154 SysRes r;
155 r._res = 0;
156 r._err = err;
157 r._isError = True;
158 return r;
159 }
160
VG_(mk_SysRes_Success)161 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
162 SysRes r;
163 r._res = res;
164 r._err = 0;
165 r._isError = False;
166 return r;
167 }
168
169
170 #elif defined(VGO_darwin)
171
172 /* Darwin: Some syscalls return a double-word result. */
VG_(mk_SysRes_x86_darwin)173 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
174 UInt wHI, UInt wLO )
175 {
176 SysRes res;
177 res._wHI = 0;
178 res._wLO = 0;
179 res._mode = 0; /* invalid */
180 vg_assert(isErr == False || isErr == True);
181 vg_assert(sizeof(UWord) == sizeof(UInt));
182 switch (scclass) {
183 case VG_DARWIN_SYSCALL_CLASS_UNIX:
184 res._wLO = wLO;
185 res._wHI = wHI;
186 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
187 break;
188 case VG_DARWIN_SYSCALL_CLASS_MACH:
189 vg_assert(!isErr);
190 vg_assert(wHI == 0);
191 res._wLO = wLO;
192 res._mode = SysRes_MACH;
193 break;
194 case VG_DARWIN_SYSCALL_CLASS_MDEP:
195 vg_assert(!isErr);
196 vg_assert(wHI == 0);
197 res._wLO = wLO;
198 res._mode = SysRes_MDEP;
199 break;
200 default:
201 vg_assert(0);
202 }
203 return res;
204 }
205
VG_(mk_SysRes_amd64_darwin)206 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
207 ULong wHI, ULong wLO )
208 {
209 SysRes res;
210 res._wHI = 0;
211 res._wLO = 0;
212 res._mode = 0; /* invalid */
213 vg_assert(isErr == False || isErr == True);
214 vg_assert(sizeof(UWord) == sizeof(ULong));
215 switch (scclass) {
216 case VG_DARWIN_SYSCALL_CLASS_UNIX:
217 res._wLO = wLO;
218 res._wHI = wHI;
219 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
220 break;
221 case VG_DARWIN_SYSCALL_CLASS_MACH:
222 vg_assert(!isErr);
223 vg_assert(wHI == 0);
224 res._wLO = wLO;
225 res._mode = SysRes_MACH;
226 break;
227 case VG_DARWIN_SYSCALL_CLASS_MDEP:
228 vg_assert(!isErr);
229 vg_assert(wHI == 0);
230 res._wLO = wLO;
231 res._mode = SysRes_MDEP;
232 break;
233 default:
234 vg_assert(0);
235 }
236 return res;
237 }
238
239 /* Generic constructors. We assume (without checking if this makes
240 any sense, from the caller's point of view) that these are for the
241 UNIX style of syscall. */
VG_(mk_SysRes_Error)242 SysRes VG_(mk_SysRes_Error) ( UWord err ) {
243 SysRes r;
244 r._wHI = 0;
245 r._wLO = err;
246 r._mode = SysRes_UNIX_ERR;
247 return r;
248 }
249
VG_(mk_SysRes_Success)250 SysRes VG_(mk_SysRes_Success) ( UWord res ) {
251 SysRes r;
252 r._wHI = 0;
253 r._wLO = res;
254 r._mode = SysRes_UNIX_OK;
255 return r;
256 }
257
258
259 #else
260 # error "Unknown OS"
261 #endif
262
263
264 /* ---------------------------------------------------------------------
265 VG_(do_syscall): A function for doing syscalls.
266 ------------------------------------------------------------------ */
267
268 #if defined(VGP_x86_linux)
269 /* Incoming args (syscall number + up to 6 args) come on the stack.
270 (ie. the C calling convention).
271
272 The syscall number goes in %eax. The args are passed to the syscall in
273 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
274 calling convention.
275
276 %eax gets the return value. Not sure which registers the kernel
277 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
278 %ebp).
279 */
280 extern UWord do_syscall_WRK (
281 UWord syscall_no,
282 UWord a1, UWord a2, UWord a3,
283 UWord a4, UWord a5, UWord a6
284 );
285 asm(
286 ".text\n"
287 "do_syscall_WRK:\n"
288 " push %esi\n"
289 " push %edi\n"
290 " push %ebx\n"
291 " push %ebp\n"
292 " movl 16+ 4(%esp),%eax\n"
293 " movl 16+ 8(%esp),%ebx\n"
294 " movl 16+12(%esp),%ecx\n"
295 " movl 16+16(%esp),%edx\n"
296 " movl 16+20(%esp),%esi\n"
297 " movl 16+24(%esp),%edi\n"
298 " movl 16+28(%esp),%ebp\n"
299 " int $0x80\n"
300 " popl %ebp\n"
301 " popl %ebx\n"
302 " popl %edi\n"
303 " popl %esi\n"
304 " ret\n"
305 ".previous\n"
306 );
307
308 #elif defined(VGP_amd64_linux)
309 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
310 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
311 calling convention).
312
313 The syscall number goes in %rax. The args are passed to the syscall in
314 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
315 ie. the kernel's syscall calling convention.
316
317 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
318 no matter, they are caller-save (the syscall clobbers no callee-save
319 regs, so we don't have to do any register saving/restoring).
320 */
321 extern UWord do_syscall_WRK (
322 UWord syscall_no,
323 UWord a1, UWord a2, UWord a3,
324 UWord a4, UWord a5, UWord a6
325 );
326 asm(
327 ".text\n"
328 "do_syscall_WRK:\n"
329 /* Convert function calling convention --> syscall calling
330 convention */
331 " movq %rdi, %rax\n"
332 " movq %rsi, %rdi\n"
333 " movq %rdx, %rsi\n"
334 " movq %rcx, %rdx\n"
335 " movq %r8, %r10\n"
336 " movq %r9, %r8\n"
337 " movq 8(%rsp), %r9\n" /* last arg from stack */
338 " syscall\n"
339 " ret\n"
340 ".previous\n"
341 );
342
343 #elif defined(VGP_ppc32_linux)
344 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
345
346 The syscall number goes in %r0. The args are passed to the syscall in
347 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
348
349 The %cr0.so bit flags an error.
350 We return the syscall return value in %r3, and the %cr0.so in
351 the lowest bit of %r4.
352 We return a ULong, of which %r3 is the high word, and %r4 the low.
353 No callee-save regs are clobbered, so no saving/restoring is needed.
354 */
355 extern ULong do_syscall_WRK (
356 UWord syscall_no,
357 UWord a1, UWord a2, UWord a3,
358 UWord a4, UWord a5, UWord a6
359 );
360 asm(
361 ".text\n"
362 "do_syscall_WRK:\n"
363 " mr 0,3\n"
364 " mr 3,4\n"
365 " mr 4,5\n"
366 " mr 5,6\n"
367 " mr 6,7\n"
368 " mr 7,8\n"
369 " mr 8,9\n"
370 " sc\n" /* syscall: sets %cr0.so on error */
371 " mfcr 4\n" /* %cr -> low word of return var */
372 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
373 " blr\n" /* and return */
374 ".previous\n"
375 );
376
377 #elif defined(VGP_ppc64_linux)
378 /* Due to the need to return 65 bits of result, this is completely
379 different from the ppc32 case. The single arg register points to a
380 7-word block containing the syscall # and the 6 args. The syscall
381 result proper is put in [0] of the block, and %cr0.so is in the
382 bottom bit of [1]. */
383 extern void do_syscall_WRK ( ULong* argblock );
384 asm(
385 ".align 2\n"
386 ".globl do_syscall_WRK\n"
387 ".section \".opd\",\"aw\"\n"
388 ".align 3\n"
389 "do_syscall_WRK:\n"
390 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
391 ".previous\n"
392 ".type .do_syscall_WRK,@function\n"
393 ".globl .do_syscall_WRK\n"
394 ".do_syscall_WRK:\n"
395 " std 3,-16(1)\n" /* stash arg */
396 " ld 8, 48(3)\n" /* sc arg 6 */
397 " ld 7, 40(3)\n" /* sc arg 5 */
398 " ld 6, 32(3)\n" /* sc arg 4 */
399 " ld 5, 24(3)\n" /* sc arg 3 */
400 " ld 4, 16(3)\n" /* sc arg 2 */
401 " ld 0, 0(3)\n" /* sc number */
402 " ld 3, 8(3)\n" /* sc arg 1 */
403 " sc\n" /* result in r3 and cr0.so */
404 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
405 " std 3,0(5)\n" /* argblock[0] = r3 */
406 " mfcr 3\n"
407 " srwi 3,3,28\n"
408 " andi. 3,3,1\n"
409 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
410 " blr\n"
411 );
412
413 #elif defined(VGP_arm_linux)
414 /* I think the conventions are:
415 args in r0 r1 r2 r3 r4 r5
416 sysno in r7
417 return value in r0, w/ same conventions as x86-linux, viz r0 in
418 -4096 .. -1 is an error value. All other values are success
419 values.
420 */
421 extern UWord do_syscall_WRK (
422 UWord a1, UWord a2, UWord a3,
423 UWord a4, UWord a5, UWord a6,
424 UWord syscall_no
425 );
426 asm(
427 ".text\n"
428 "do_syscall_WRK:\n"
429 " push {r4, r5, r7}\n"
430 " ldr r4, [sp, #12]\n"
431 " ldr r5, [sp, #16]\n"
432 " ldr r7, [sp, #20]\n"
433 " svc 0x0\n"
434 " pop {r4, r5, r7}\n"
435 " bx lr\n"
436 ".previous\n"
437 );
438
439 #elif defined(VGP_ppc32_aix5)
do_syscall_WRK(UWord * res_r3,UWord * res_r4,UWord sysno,UWord a1,UWord a2,UWord a3,UWord a4,UWord a5,UWord a6,UWord a7,UWord a8)440 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
441 UWord sysno,
442 UWord a1, UWord a2, UWord a3,
443 UWord a4, UWord a5, UWord a6,
444 UWord a7, UWord a8 )
445 {
446 /* Syscalls on AIX are very similar to function calls:
447 - up to 8 args in r3-r10
448 - syscall number in r2
449 - kernel resumes at 'lr', so must set it appropriately beforehand
450 - r3 holds the result and r4 any applicable error code
451 See http://www.cs.utexas.edu/users/cart/publications/tr00-04.ps
452 and also 'man truss'.
453 */
454 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
455 even though we state it to be trashed. So use r27 instead. */
456 UWord args[9];
457 args[0] = sysno;
458 args[1] = a1; args[2] = a2;
459 args[3] = a3; args[4] = a4;
460 args[5] = a5; args[6] = a6;
461 args[7] = a7; args[8] = a8;
462
463 __asm__ __volatile__(
464
465 // establish base ptr
466 "mr 28,%0\n\t"
467
468 // save r2, lr
469 "mr 27,2\n\t" // save r2 in r27
470 "mflr 30\n\t" // save lr in r30
471
472 // set syscall number and args
473 "lwz 2, 0(28)\n\t"
474 "lwz 3, 4(28)\n\t"
475 "lwz 4, 8(28)\n\t"
476 "lwz 5, 12(28)\n\t"
477 "lwz 6, 16(28)\n\t"
478 "lwz 7, 20(28)\n\t"
479 "lwz 8, 24(28)\n\t"
480 "lwz 9, 28(28)\n\t"
481 "lwz 10, 32(28)\n\t"
482
483 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
484 // wrong address after the sc instruction
485 "crorc 6,6,6\n\t"
486
487 // set up LR to point just after the sc insn
488 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
489 "mflr 29\n\t"
490 "addi 29,29,16\n\t"
491 "mtlr 29\n\t"
492
493 // do it!
494 "sc\n\t"
495
496 // result is now in r3; save it in args[0]
497 "stw 3,0(28)\n\t"
498 // error code in r4; save it in args[1]
499 "stw 4,4(28)\n\t"
500
501 // restore
502 "mr 2,27\n\t"
503 "mtlr 30\n\t"
504
505 : /*out*/
506 : /*in*/ "b" (&args[0])
507 : /*trash*/
508 /*temps*/ "r31","r30","r29","r28","r27",
509 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
510 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
511 "xer","ctr","cr0","cr1","cr2","cr3",
512 "cr4","cr5","cr6","cr7"
513 );
514
515 *res_r3 = args[0];
516 *res_r4 = args[1];
517 }
518
519 #elif defined(VGP_ppc64_aix5)
do_syscall_WRK(UWord * res_r3,UWord * res_r4,UWord sysno,UWord a1,UWord a2,UWord a3,UWord a4,UWord a5,UWord a6,UWord a7,UWord a8)520 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
521 UWord sysno,
522 UWord a1, UWord a2, UWord a3,
523 UWord a4, UWord a5, UWord a6,
524 UWord a7, UWord a8 )
525 {
526 /* Same scheme as ppc32-aix5. */
527 UWord args[9];
528 args[0] = sysno;
529 args[1] = a1; args[2] = a2;
530 args[3] = a3; args[4] = a4;
531 args[5] = a5; args[6] = a6;
532 args[7] = a7; args[8] = a8;
533
534 __asm__ __volatile__(
535
536 // establish base ptr
537 "mr 28,%0\n\t"
538
539 // save r2, lr
540 "mr 27,2\n\t" // save r2 in r27
541 "mflr 30\n\t" // save lr in r30
542
543 // set syscall number and args
544 "ld 2, 0(28)\n\t"
545 "ld 3, 8(28)\n\t"
546 "ld 4, 16(28)\n\t"
547 "ld 5, 24(28)\n\t"
548 "ld 6, 32(28)\n\t"
549 "ld 7, 40(28)\n\t"
550 "ld 8, 48(28)\n\t"
551 "ld 9, 56(28)\n\t"
552 "ld 10, 64(28)\n\t"
553
554 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
555 // wrong address after the sc instruction
556 "crorc 6,6,6\n\t"
557
558 // set up LR to point just after the sc insn
559 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
560 "mflr 29\n\t"
561 "addi 29,29,16\n\t"
562 "mtlr 29\n\t"
563
564 // do it!
565 "sc\n\t"
566
567 // result is now in r3; save it in args[0]
568 "std 3,0(28)\n\t"
569 // error code in r4; save it in args[1]
570 "std 4,8(28)\n\t"
571
572 // restore
573 "mr 2,27\n\t"
574 "mtlr 30\n\t"
575
576 : /*out*/
577 : /*in*/ "b" (&args[0])
578 : /*trash*/
579 /*temps*/ "r31","r30","r29","r28","r27",
580 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
581 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
582 "xer","ctr","cr0","cr1","cr2","cr3",
583 "cr4","cr5","cr6","cr7"
584 );
585
586 *res_r3 = args[0];
587 *res_r4 = args[1];
588 }
589
590 #elif defined(VGP_x86_darwin)
591
592 /* Incoming args (syscall number + up to 8 args) come in on the stack
593
594 The kernel's syscall calling convention is:
595 * the syscall number goes in eax
596 * the args are passed to the syscall on the stack,
597 pushed onto the stack R->L (that is, the usual x86
598 calling conventions, with the leftmost arg at the lowest
599 address)
600 Call instruction:
601 * UNIX: sysenter
602 * UNIX: int $0x80
603 * MACH: int $0x81
604 * MDEP: int $0x82
605 Note that the call type can be determined from the syscall number;
606 there is no need to inspect the actual instruction. Although obviously
607 the instruction must match.
608 Return value:
609 * MACH,MDEP: the return value comes back in eax
610 * UNIX: the return value comes back in edx:eax (hi32:lo32)
611 Error:
612 * MACH,MDEP: no error is returned
613 * UNIX: the carry flag indicates success or failure
614
615 nb here, sizeof(UWord) == sizeof(UInt)
616 */
617
618 __private_extern__ ULong
619 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
620 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
621 UWord a7, UWord a8, /* 28(esp)..32(esp) */
622 UWord syscall_no, /* 36(esp) */
623 /*OUT*/UInt* errflag /* 40(esp) */ );
624 // Unix syscall: 64-bit return in edx:eax, with LSB in eax
625 // error indicated by carry flag: clear=good, set=bad
626 asm(".private_extern _do_syscall_unix_WRK\n"
627 "_do_syscall_unix_WRK:\n"
628 " movl 40(%esp), %ecx \n" /* assume syscall success */
629 " movl $0, (%ecx) \n"
630 " movl 36(%esp), %eax \n"
631 " int $0x80 \n"
632 " jnc 1f \n" /* jump if success */
633 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
634 " movl $1, (%ecx) \n"
635 " 1: ret \n"
636 );
637
638 __private_extern__ UInt
639 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
640 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
641 UWord a7, UWord a8, /* 28(esp)..32(esp) */
642 UWord syscall_no /* 36(esp) */ );
643 // Mach trap: 32-bit result in %eax, no error flag
644 asm(".private_extern _do_syscall_mach_WRK\n"
645 "_do_syscall_mach_WRK:\n"
646 " movl 36(%esp), %eax \n"
647 " int $0x81 \n"
648 " ret \n"
649 );
650
651 __private_extern__ UInt
652 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
653 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
654 UWord a7, UWord a8, /* 28(esp)..32(esp) */
655 UWord syscall_no /* 36(esp) */ );
656 // mdep trap: 32-bit result in %eax, no error flag
657 asm(
658 ".private_extern _do_syscall_mdep_WRK\n"
659 "_do_syscall_mdep_WRK:\n"
660 " movl 36(%esp), %eax \n"
661 " int $0x82 \n"
662 " ret \n"
663 );
664
665
666 #elif defined(VGP_amd64_darwin)
667
668 /* Incoming args (syscall number + up to 8 args) come in registers and stack
669
670 The kernel's syscall calling convention is:
671 * the syscall number goes in rax
672 * the args are passed to the syscall in registers and the stack
673 * the call instruction is 'syscall'
674 Return value:
675 * MACH,MDEP: the return value comes back in rax
676 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
677 Error:
678 * MACH,MDEP: no error is returned
679 * UNIX: the carry flag indicates success or failure
680
681 nb here, sizeof(UWord) == sizeof(ULong)
682 */
683
684 __private_extern__ UWord
685 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
686 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
687 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
688 UWord syscall_no, /* 24(rsp) */
689 /*OUT*/ULong* errflag, /* 32(rsp) */
690 /*OUT*/ULong* res2 ); /* 40(rsp) */
691 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax
692 // error indicated by carry flag: clear=good, set=bad
693 asm(".private_extern _do_syscall_unix_WRK\n"
694 "_do_syscall_unix_WRK:\n"
695 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
696 " movq 32(%rsp), %rax \n" /* assume syscall success */
697 " movq $0, (%rax) \n"
698 " movq 24(%rsp), %rax \n" /* load syscall_no */
699 " syscall \n"
700 " jnc 1f \n" /* jump if success */
701 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
702 " movq $1, (%rcx) \n"
703 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
704 " movq %rdx, (%rcx) \n"
705 " retq \n" /* return 1st result word */
706 );
707
708 __private_extern__ UWord
709 do_syscall_mach_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 // Mach trap: 64-bit result, no error flag
714 asm(".private_extern _do_syscall_mach_WRK\n"
715 "_do_syscall_mach_WRK:\n"
716 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
717 " movq 24(%rsp), %rax \n" /* load syscall_no */
718 " syscall \n"
719 " retq \n"
720 );
721
722 #else
723 # error Unknown platform
724 #endif
725
726
727 /* Finally, the generic code. This sends the call to the right
728 helper. */
729
VG_(do_syscall)730 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
731 UWord a4, UWord a5, UWord a6,
732 UWord a7, UWord a8 )
733 {
734 # if defined(VGP_x86_linux)
735 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
736 return VG_(mk_SysRes_x86_linux)( val );
737
738 # elif defined(VGP_amd64_linux)
739 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
740 return VG_(mk_SysRes_amd64_linux)( val );
741
742 # elif defined(VGP_ppc32_linux)
743 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
744 UInt val = (UInt)(ret>>32);
745 UInt cr0so = (UInt)(ret);
746 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
747
748 # elif defined(VGP_ppc64_linux)
749 ULong argblock[7];
750 argblock[0] = sysno;
751 argblock[1] = a1;
752 argblock[2] = a2;
753 argblock[3] = a3;
754 argblock[4] = a4;
755 argblock[5] = a5;
756 argblock[6] = a6;
757 do_syscall_WRK( &argblock[0] );
758 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
759
760 # elif defined(VGP_arm_linux)
761 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
762 return VG_(mk_SysRes_arm_linux)( val );
763
764 # elif defined(VGP_ppc32_aix5)
765 UWord res;
766 UWord err;
767 do_syscall_WRK( &res, &err,
768 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
769 /* Try to set the error number to zero if the syscall hasn't
770 really failed. */
771 if (sysno == __NR_AIX5_kread
772 || sysno == __NR_AIX5_kwrite) {
773 if (res != (UWord)-1L)
774 err = 0;
775 }
776 else if (sysno == __NR_AIX5_sigprocmask
777 || sysno == __NR_AIX5__sigpending) {
778 if (res == 0)
779 err = 0;
780 }
781 return VG_(mk_SysRes_ppc32_aix5)( res, err );
782
783 # elif defined(VGP_ppc64_aix5)
784 UWord res;
785 UWord err;
786 do_syscall_WRK( &res, &err,
787 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
788 /* Try to set the error number to zero if the syscall hasn't
789 really failed. */
790 if (sysno == __NR_AIX5_kread
791 || sysno == __NR_AIX5_kwrite) {
792 if (res != (UWord)-1L)
793 err = 0;
794 }
795 else if (sysno == __NR_AIX5_sigprocmask
796 || sysno == __NR_AIX5__sigpending) {
797 if (res == 0)
798 err = 0;
799 }
800 return VG_(mk_SysRes_ppc64_aix5)( res, err );
801
802 # elif defined(VGP_x86_darwin)
803 UInt wLO = 0, wHI = 0, err = 0;
804 ULong u64;
805 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
806 switch (scclass) {
807 case VG_DARWIN_SYSCALL_CLASS_UNIX:
808 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
809 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
810 wLO = (UInt)u64;
811 wHI = (UInt)(u64 >> 32);
812 break;
813 case VG_DARWIN_SYSCALL_CLASS_MACH:
814 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
815 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
816 err = 0;
817 break;
818 case VG_DARWIN_SYSCALL_CLASS_MDEP:
819 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
820 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
821 err = 0;
822 break;
823 default:
824 vg_assert(0);
825 break;
826 }
827 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
828
829 # elif defined(VGP_amd64_darwin)
830 ULong wLO = 0, wHI = 0, err = 0;
831 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
832 switch (scclass) {
833 case VG_DARWIN_SYSCALL_CLASS_UNIX:
834 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
835 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
836 break;
837 case VG_DARWIN_SYSCALL_CLASS_MACH:
838 case VG_DARWIN_SYSCALL_CLASS_MDEP:
839 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
840 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
841 err = 0;
842 break;
843 default:
844 vg_assert(0);
845 break;
846 }
847 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
848
849 #else
850 # error Unknown platform
851 #endif
852 }
853
854 /* ---------------------------------------------------------------------
855 Names of errors.
856 ------------------------------------------------------------------ */
857
858 /* Return a string which gives the name of an error value. Note,
859 unlike the standard C syserror fn, the returned string is not
860 malloc-allocated or writable -- treat it as a constant.
861 TODO: implement this properly. */
862
VG_(strerror)863 const HChar* VG_(strerror) ( UWord errnum )
864 {
865 switch (errnum) {
866 case VKI_EPERM: return "Operation not permitted";
867 case VKI_ENOENT: return "No such file or directory";
868 case VKI_ESRCH: return "No such process";
869 case VKI_EINTR: return "Interrupted system call";
870 case VKI_EBADF: return "Bad file number";
871 case VKI_EAGAIN: return "Try again";
872 case VKI_ENOMEM: return "Out of memory";
873 case VKI_EACCES: return "Permission denied";
874 case VKI_EFAULT: return "Bad address";
875 case VKI_EEXIST: return "File exists";
876 case VKI_EINVAL: return "Invalid argument";
877 case VKI_EMFILE: return "Too many open files";
878 case VKI_ENOSYS: return "Function not implemented";
879 case VKI_EOVERFLOW: return "Value too large for defined data type";
880 # if defined(VKI_ERESTARTSYS)
881 case VKI_ERESTARTSYS: return "ERESTARTSYS";
882 # endif
883 default: return "VG_(strerror): unknown error";
884 }
885 }
886
887
888 /*--------------------------------------------------------------------*/
889 /*--- end ---*/
890 /*--------------------------------------------------------------------*/
891