blob: 296a74daad83b9b25065972f20e7cd6d21f75bd3 [file] [log] [blame]
njn9abd6082005-06-17 21:31:45 +00001
2/*--------------------------------------------------------------------*/
3/*--- Doing syscalls. m_syscall.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 Julian Seward
njn9abd6082005-06-17 21:31:45 +000011 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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njnf76d27a2009-05-28 01:53:07 +000032#include "pub_core_libcassert.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
sewardj17edf032006-10-17 01:53:34 +000034#include "pub_core_vkiscnums.h"
njn9abd6082005-06-17 21:31:45 +000035#include "pub_core_syscall.h"
36
37/* ---------------------------------------------------------------------
38 Building syscall return values.
39 ------------------------------------------------------------------ */
40
njncda2f0f2009-05-18 02:12:08 +000041#if defined(VGO_linux)
42
43/* Make a SysRes value from a syscall return value. This is
njn9abd6082005-06-17 21:31:45 +000044 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*/
njncda2f0f2009-05-18 02:12:08 +000062
63SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
njn9abd6082005-06-17 21:31:45 +000064 SysRes res;
njncda2f0f2009-05-18 02:12:08 +000065 res._isError = val >= -4095 && val <= -1;
66 if (res._isError) {
67 res._val = (UInt)(-val);
sewardj17edf032006-10-17 01:53:34 +000068 } else {
njncda2f0f2009-05-18 02:12:08 +000069 res._val = (UInt)val;
sewardj17edf032006-10-17 01:53:34 +000070 }
njn9abd6082005-06-17 21:31:45 +000071 return res;
72}
73
cerion85665ca2005-06-20 15:51:07 +000074/* Similarly .. */
njncda2f0f2009-05-18 02:12:08 +000075SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
cerion85665ca2005-06-20 15:51:07 +000076 SysRes res;
njncda2f0f2009-05-18 02:12:08 +000077 res._isError = val >= -4095 && val <= -1;
78 if (res._isError) {
79 res._val = (ULong)(-val);
sewardj17edf032006-10-17 01:53:34 +000080 } else {
njncda2f0f2009-05-18 02:12:08 +000081 res._val = (ULong)val;
sewardj17edf032006-10-17 01:53:34 +000082 }
cerion85665ca2005-06-20 15:51:07 +000083 return res;
84}
85
sewardj17edf032006-10-17 01:53:34 +000086/* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
sewardj39a7c1d2005-11-24 03:54:38 +000087/* Note this must be in the bottom bit of the second arg */
88SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
cerion85665ca2005-06-20 15:51:07 +000089 SysRes res;
njncda2f0f2009-05-18 02:12:08 +000090 res._isError = (cr0so & 1) != 0;
91 res._val = val;
cerion85665ca2005-06-20 15:51:07 +000092 return res;
93}
94
sewardj38a88b72006-01-02 16:32:10 +000095/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
96SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
sewardj2c48c7b2005-11-29 13:05:56 +000097 SysRes res;
njncda2f0f2009-05-18 02:12:08 +000098 res._isError = (cr0so & 1) != 0;
99 res._val = val;
sewardj2c48c7b2005-11-29 13:05:56 +0000100 return res;
101}
102
sewardjb5b87402011-03-07 16:05:35 +0000103SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
104 SysRes res;
105 res._isError = val >= -4095 && val <= -1;
106 if (res._isError) {
107 res._val = -val;
108 } else {
109 res._val = val;
110 }
111 return res;
112}
113
sewardj59570ff2010-01-01 11:59:33 +0000114SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
115 SysRes res;
116 res._isError = val >= -4095 && val <= -1;
117 if (res._isError) {
118 res._val = (UInt)(-val);
119 } else {
120 res._val = (UInt)val;
121 }
122 return res;
123}
124
njncda2f0f2009-05-18 02:12:08 +0000125/* Generic constructors. */
126SysRes VG_(mk_SysRes_Error) ( UWord err ) {
127 SysRes r;
128 r._isError = True;
129 r._val = err;
130 return r;
131}
132
133SysRes VG_(mk_SysRes_Success) ( UWord res ) {
134 SysRes r;
135 r._isError = False;
136 r._val = res;
137 return r;
138}
139
140
141#elif defined(VGO_aix5)
142
sewardj17edf032006-10-17 01:53:34 +0000143/* AIX scheme: we have to record both 'res' (r3) and 'err' (r4). If
144 'err' is nonzero then the call has failed, but it could still be
145 that AIX userspace will ignore 'err' and instead consult 'res' to
146 determine if the call failed. So we have to record both. */
147SysRes VG_(mk_SysRes_ppc32_aix5) ( UInt res, UInt err ) {
148 SysRes r;
149 r.res = res;
150 r.err = err;
151 r.isError = r.err != 0;
njn9abd6082005-06-17 21:31:45 +0000152 return r;
153}
154
sewardj17edf032006-10-17 01:53:34 +0000155SysRes VG_(mk_SysRes_ppc64_aix5) ( ULong res, ULong err ) {
156 SysRes r;
157 r.res = res;
158 r.err = err;
159 r.isError = r.err != 0;
160 return r;
161}
162
163/* Generic constructors. */
164SysRes VG_(mk_SysRes_Error) ( UWord err ) {
165 SysRes r;
njncda2f0f2009-05-18 02:12:08 +0000166 r._res = 0;
167 r._err = err;
168 r._isError = True;
sewardj17edf032006-10-17 01:53:34 +0000169 return r;
170}
171
172SysRes VG_(mk_SysRes_Success) ( UWord res ) {
173 SysRes r;
njncda2f0f2009-05-18 02:12:08 +0000174 r._res = res;
175 r._err = 0;
176 r._isError = False;
njn9abd6082005-06-17 21:31:45 +0000177 return r;
178}
179
180
njnf76d27a2009-05-28 01:53:07 +0000181#elif defined(VGO_darwin)
182
183/* Darwin: Some syscalls return a double-word result. */
184SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
185 UInt wHI, UInt wLO )
186{
187 SysRes res;
188 res._wHI = 0;
189 res._wLO = 0;
190 res._mode = 0; /* invalid */
191 vg_assert(isErr == False || isErr == True);
192 vg_assert(sizeof(UWord) == sizeof(UInt));
193 switch (scclass) {
194 case VG_DARWIN_SYSCALL_CLASS_UNIX:
195 res._wLO = wLO;
196 res._wHI = wHI;
197 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
198 break;
199 case VG_DARWIN_SYSCALL_CLASS_MACH:
200 vg_assert(!isErr);
201 vg_assert(wHI == 0);
202 res._wLO = wLO;
203 res._mode = SysRes_MACH;
204 break;
205 case VG_DARWIN_SYSCALL_CLASS_MDEP:
206 vg_assert(!isErr);
207 vg_assert(wHI == 0);
208 res._wLO = wLO;
209 res._mode = SysRes_MDEP;
210 break;
211 default:
212 vg_assert(0);
213 }
214 return res;
215}
216
217SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
218 ULong wHI, ULong wLO )
219{
220 SysRes res;
221 res._wHI = 0;
222 res._wLO = 0;
223 res._mode = 0; /* invalid */
224 vg_assert(isErr == False || isErr == True);
225 vg_assert(sizeof(UWord) == sizeof(ULong));
226 switch (scclass) {
227 case VG_DARWIN_SYSCALL_CLASS_UNIX:
228 res._wLO = wLO;
229 res._wHI = wHI;
230 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
231 break;
232 case VG_DARWIN_SYSCALL_CLASS_MACH:
233 vg_assert(!isErr);
234 vg_assert(wHI == 0);
235 res._wLO = wLO;
236 res._mode = SysRes_MACH;
237 break;
238 case VG_DARWIN_SYSCALL_CLASS_MDEP:
239 vg_assert(!isErr);
240 vg_assert(wHI == 0);
241 res._wLO = wLO;
242 res._mode = SysRes_MDEP;
243 break;
244 default:
245 vg_assert(0);
246 }
247 return res;
248}
249
250/* Generic constructors. We assume (without checking if this makes
251 any sense, from the caller's point of view) that these are for the
252 UNIX style of syscall. */
253SysRes VG_(mk_SysRes_Error) ( UWord err ) {
254 SysRes r;
255 r._wHI = 0;
256 r._wLO = err;
257 r._mode = SysRes_UNIX_ERR;
258 return r;
259}
260
261SysRes VG_(mk_SysRes_Success) ( UWord res ) {
262 SysRes r;
263 r._wHI = 0;
264 r._wLO = res;
265 r._mode = SysRes_UNIX_OK;
266 return r;
267}
268
269
njncda2f0f2009-05-18 02:12:08 +0000270#else
271# error "Unknown OS"
272#endif
273
274
njn9abd6082005-06-17 21:31:45 +0000275/* ---------------------------------------------------------------------
njncda2f0f2009-05-18 02:12:08 +0000276 VG_(do_syscall): A function for doing syscalls.
njn9abd6082005-06-17 21:31:45 +0000277 ------------------------------------------------------------------ */
278
njn9abd6082005-06-17 21:31:45 +0000279#if defined(VGP_x86_linux)
280/* Incoming args (syscall number + up to 6 args) come on the stack.
281 (ie. the C calling convention).
282
283 The syscall number goes in %eax. The args are passed to the syscall in
284 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
285 calling convention.
286
287 %eax gets the return value. Not sure which registers the kernel
288 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
289 %ebp).
290*/
sewardj03d8aa82005-10-14 11:25:49 +0000291extern UWord do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000292 UWord syscall_no,
293 UWord a1, UWord a2, UWord a3,
294 UWord a4, UWord a5, UWord a6
295 );
njn9abd6082005-06-17 21:31:45 +0000296asm(
sewardjd9fc3822005-11-18 23:50:43 +0000297".text\n"
njn9abd6082005-06-17 21:31:45 +0000298"do_syscall_WRK:\n"
299" push %esi\n"
300" push %edi\n"
301" push %ebx\n"
302" push %ebp\n"
303" movl 16+ 4(%esp),%eax\n"
304" movl 16+ 8(%esp),%ebx\n"
305" movl 16+12(%esp),%ecx\n"
306" movl 16+16(%esp),%edx\n"
307" movl 16+20(%esp),%esi\n"
308" movl 16+24(%esp),%edi\n"
309" movl 16+28(%esp),%ebp\n"
310" int $0x80\n"
311" popl %ebp\n"
312" popl %ebx\n"
313" popl %edi\n"
314" popl %esi\n"
315" ret\n"
sewardj2fedc642005-11-19 02:02:57 +0000316".previous\n"
njn9abd6082005-06-17 21:31:45 +0000317);
sewardj2c48c7b2005-11-29 13:05:56 +0000318
njn9abd6082005-06-17 21:31:45 +0000319#elif defined(VGP_amd64_linux)
320/* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
321 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
322 calling convention).
323
324 The syscall number goes in %rax. The args are passed to the syscall in
325 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
326 ie. the kernel's syscall calling convention.
327
328 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
329 no matter, they are caller-save (the syscall clobbers no callee-save
330 regs, so we don't have to do any register saving/restoring).
331*/
sewardj03d8aa82005-10-14 11:25:49 +0000332extern UWord do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000333 UWord syscall_no,
334 UWord a1, UWord a2, UWord a3,
335 UWord a4, UWord a5, UWord a6
336 );
njn9abd6082005-06-17 21:31:45 +0000337asm(
sewardjd9fc3822005-11-18 23:50:43 +0000338".text\n"
njn9abd6082005-06-17 21:31:45 +0000339"do_syscall_WRK:\n"
340 /* Convert function calling convention --> syscall calling
341 convention */
342" movq %rdi, %rax\n"
343" movq %rsi, %rdi\n"
344" movq %rdx, %rsi\n"
345" movq %rcx, %rdx\n"
346" movq %r8, %r10\n"
347" movq %r9, %r8\n"
348" movq 8(%rsp), %r9\n" /* last arg from stack */
349" syscall\n"
350" ret\n"
sewardj2fedc642005-11-19 02:02:57 +0000351".previous\n"
njn9abd6082005-06-17 21:31:45 +0000352);
sewardj2c48c7b2005-11-29 13:05:56 +0000353
cerion85665ca2005-06-20 15:51:07 +0000354#elif defined(VGP_ppc32_linux)
sewardj39a7c1d2005-11-24 03:54:38 +0000355/* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
cerion85665ca2005-06-20 15:51:07 +0000356
357 The syscall number goes in %r0. The args are passed to the syscall in
358 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
359
360 The %cr0.so bit flags an error.
sewardj39a7c1d2005-11-24 03:54:38 +0000361 We return the syscall return value in %r3, and the %cr0.so in
362 the lowest bit of %r4.
cerion85665ca2005-06-20 15:51:07 +0000363 We return a ULong, of which %r3 is the high word, and %r4 the low.
364 No callee-save regs are clobbered, so no saving/restoring is needed.
365*/
sewardj03d8aa82005-10-14 11:25:49 +0000366extern ULong do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000367 UWord syscall_no,
368 UWord a1, UWord a2, UWord a3,
369 UWord a4, UWord a5, UWord a6
370 );
371asm(
sewardjd9fc3822005-11-18 23:50:43 +0000372".text\n"
cerion85665ca2005-06-20 15:51:07 +0000373"do_syscall_WRK:\n"
374" mr 0,3\n"
375" mr 3,4\n"
376" mr 4,5\n"
377" mr 5,6\n"
378" mr 6,7\n"
379" mr 7,8\n"
380" mr 8,9\n"
381" sc\n" /* syscall: sets %cr0.so on error */
382" mfcr 4\n" /* %cr -> low word of return var */
383" rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
384" blr\n" /* and return */
sewardj2fedc642005-11-19 02:02:57 +0000385".previous\n"
cerion85665ca2005-06-20 15:51:07 +0000386);
sewardj2c48c7b2005-11-29 13:05:56 +0000387
388#elif defined(VGP_ppc64_linux)
389/* Due to the need to return 65 bits of result, this is completely
390 different from the ppc32 case. The single arg register points to a
391 7-word block containing the syscall # and the 6 args. The syscall
392 result proper is put in [0] of the block, and %cr0.so is in the
njncda2f0f2009-05-18 02:12:08 +0000393 bottom bit of [1]. */
sewardj2c48c7b2005-11-29 13:05:56 +0000394extern void do_syscall_WRK ( ULong* argblock );
395asm(
cerion297c88f2005-12-22 15:53:12 +0000396".align 2\n"
397".globl do_syscall_WRK\n"
398".section \".opd\",\"aw\"\n"
399".align 3\n"
400"do_syscall_WRK:\n"
401".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
402".previous\n"
403".type .do_syscall_WRK,@function\n"
404".globl .do_syscall_WRK\n"
sewardj2c48c7b2005-11-29 13:05:56 +0000405".do_syscall_WRK:\n"
406" std 3,-16(1)\n" /* stash arg */
407" ld 8, 48(3)\n" /* sc arg 6 */
408" ld 7, 40(3)\n" /* sc arg 5 */
409" ld 6, 32(3)\n" /* sc arg 4 */
410" ld 5, 24(3)\n" /* sc arg 3 */
411" ld 4, 16(3)\n" /* sc arg 2 */
412" ld 0, 0(3)\n" /* sc number */
413" ld 3, 8(3)\n" /* sc arg 1 */
414" sc\n" /* result in r3 and cr0.so */
415" ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
416" std 3,0(5)\n" /* argblock[0] = r3 */
sewardj2c48c7b2005-11-29 13:05:56 +0000417" mfcr 3\n"
418" srwi 3,3,28\n"
419" andi. 3,3,1\n"
420" std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
421" blr\n"
sewardj2c48c7b2005-11-29 13:05:56 +0000422);
sewardj17edf032006-10-17 01:53:34 +0000423
sewardj59570ff2010-01-01 11:59:33 +0000424#elif defined(VGP_arm_linux)
425/* I think the conventions are:
426 args in r0 r1 r2 r3 r4 r5
427 sysno in r7
428 return value in r0, w/ same conventions as x86-linux, viz r0 in
429 -4096 .. -1 is an error value. All other values are success
430 values.
431*/
432extern UWord do_syscall_WRK (
433 UWord a1, UWord a2, UWord a3,
434 UWord a4, UWord a5, UWord a6,
435 UWord syscall_no
436 );
437asm(
438".text\n"
439"do_syscall_WRK:\n"
440" push {r4, r5, r7}\n"
441" ldr r4, [sp, #12]\n"
442" ldr r5, [sp, #16]\n"
443" ldr r7, [sp, #20]\n"
444" svc 0x0\n"
445" pop {r4, r5, r7}\n"
446" bx lr\n"
447".previous\n"
448);
449
sewardj17edf032006-10-17 01:53:34 +0000450#elif defined(VGP_ppc32_aix5)
451static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
452 UWord sysno,
453 UWord a1, UWord a2, UWord a3,
454 UWord a4, UWord a5, UWord a6,
455 UWord a7, UWord a8 )
456{
457 /* Syscalls on AIX are very similar to function calls:
458 - up to 8 args in r3-r10
459 - syscall number in r2
460 - kernel resumes at 'lr', so must set it appropriately beforehand
461 - r3 holds the result and r4 any applicable error code
462 See http://www.cs.utexas.edu/users/cart/publications/tr00-04.ps
463 and also 'man truss'.
464 */
465 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
466 even though we state it to be trashed. So use r27 instead. */
467 UWord args[9];
468 args[0] = sysno;
469 args[1] = a1; args[2] = a2;
470 args[3] = a3; args[4] = a4;
471 args[5] = a5; args[6] = a6;
472 args[7] = a7; args[8] = a8;
473
474 __asm__ __volatile__(
475
476 // establish base ptr
477 "mr 28,%0\n\t"
478
479 // save r2, lr
480 "mr 27,2\n\t" // save r2 in r27
481 "mflr 30\n\t" // save lr in r30
482
483 // set syscall number and args
484 "lwz 2, 0(28)\n\t"
485 "lwz 3, 4(28)\n\t"
486 "lwz 4, 8(28)\n\t"
487 "lwz 5, 12(28)\n\t"
488 "lwz 6, 16(28)\n\t"
489 "lwz 7, 20(28)\n\t"
490 "lwz 8, 24(28)\n\t"
491 "lwz 9, 28(28)\n\t"
492 "lwz 10, 32(28)\n\t"
493
sewardj17edf032006-10-17 01:53:34 +0000494 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
495 // wrong address after the sc instruction
496 "crorc 6,6,6\n\t"
497
sewardj13552642006-11-10 22:47:27 +0000498 // set up LR to point just after the sc insn
499 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
500 "mflr 29\n\t"
501 "addi 29,29,16\n\t"
502 "mtlr 29\n\t"
503
sewardj17edf032006-10-17 01:53:34 +0000504 // do it!
505 "sc\n\t"
506
507 // result is now in r3; save it in args[0]
508 "stw 3,0(28)\n\t"
509 // error code in r4; save it in args[1]
510 "stw 4,4(28)\n\t"
511
512 // restore
513 "mr 2,27\n\t"
514 "mtlr 30\n\t"
515
516 : /*out*/
517 : /*in*/ "b" (&args[0])
518 : /*trash*/
519 /*temps*/ "r31","r30","r29","r28","r27",
520 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
521 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
522 "xer","ctr","cr0","cr1","cr2","cr3",
523 "cr4","cr5","cr6","cr7"
524 );
525
526 *res_r3 = args[0];
527 *res_r4 = args[1];
528}
529
530#elif defined(VGP_ppc64_aix5)
531static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4,
532 UWord sysno,
533 UWord a1, UWord a2, UWord a3,
534 UWord a4, UWord a5, UWord a6,
535 UWord a7, UWord a8 )
536{
537 /* Same scheme as ppc32-aix5. */
538 UWord args[9];
539 args[0] = sysno;
540 args[1] = a1; args[2] = a2;
541 args[3] = a3; args[4] = a4;
542 args[5] = a5; args[6] = a6;
543 args[7] = a7; args[8] = a8;
544
545 __asm__ __volatile__(
546
547 // establish base ptr
548 "mr 28,%0\n\t"
549
550 // save r2, lr
551 "mr 27,2\n\t" // save r2 in r27
552 "mflr 30\n\t" // save lr in r30
553
554 // set syscall number and args
555 "ld 2, 0(28)\n\t"
556 "ld 3, 8(28)\n\t"
557 "ld 4, 16(28)\n\t"
558 "ld 5, 24(28)\n\t"
559 "ld 6, 32(28)\n\t"
560 "ld 7, 40(28)\n\t"
561 "ld 8, 48(28)\n\t"
562 "ld 9, 56(28)\n\t"
563 "ld 10, 64(28)\n\t"
564
sewardj17edf032006-10-17 01:53:34 +0000565 // set bit 3 of CR1 otherwise AIX 5.1 returns to the
566 // wrong address after the sc instruction
567 "crorc 6,6,6\n\t"
568
sewardj13552642006-11-10 22:47:27 +0000569 // set up LR to point just after the sc insn
570 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn
571 "mflr 29\n\t"
572 "addi 29,29,16\n\t"
573 "mtlr 29\n\t"
574
sewardj17edf032006-10-17 01:53:34 +0000575 // do it!
576 "sc\n\t"
577
578 // result is now in r3; save it in args[0]
579 "std 3,0(28)\n\t"
580 // error code in r4; save it in args[1]
581 "std 4,8(28)\n\t"
582
583 // restore
584 "mr 2,27\n\t"
585 "mtlr 30\n\t"
586
587 : /*out*/
588 : /*in*/ "b" (&args[0])
589 : /*trash*/
590 /*temps*/ "r31","r30","r29","r28","r27",
591 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
592 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
593 "xer","ctr","cr0","cr1","cr2","cr3",
594 "cr4","cr5","cr6","cr7"
595 );
596
597 *res_r3 = args[0];
598 *res_r4 = args[1];
599}
600
njnf76d27a2009-05-28 01:53:07 +0000601#elif defined(VGP_x86_darwin)
602
603/* Incoming args (syscall number + up to 8 args) come in on the stack
604
605 The kernel's syscall calling convention is:
606 * the syscall number goes in eax
607 * the args are passed to the syscall on the stack,
608 pushed onto the stack R->L (that is, the usual x86
609 calling conventions, with the leftmost arg at the lowest
610 address)
611 Call instruction:
612 * UNIX: sysenter
613 * UNIX: int $0x80
614 * MACH: int $0x81
615 * MDEP: int $0x82
616 Note that the call type can be determined from the syscall number;
617 there is no need to inspect the actual instruction. Although obviously
618 the instruction must match.
619 Return value:
620 * MACH,MDEP: the return value comes back in eax
621 * UNIX: the return value comes back in edx:eax (hi32:lo32)
622 Error:
623 * MACH,MDEP: no error is returned
624 * UNIX: the carry flag indicates success or failure
625
626 nb here, sizeof(UWord) == sizeof(UInt)
627*/
628
629__private_extern__ ULong
630do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
631 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
632 UWord a7, UWord a8, /* 28(esp)..32(esp) */
633 UWord syscall_no, /* 36(esp) */
634 /*OUT*/UInt* errflag /* 40(esp) */ );
635// Unix syscall: 64-bit return in edx:eax, with LSB in eax
636// error indicated by carry flag: clear=good, set=bad
637asm(".private_extern _do_syscall_unix_WRK\n"
638 "_do_syscall_unix_WRK:\n"
639 " movl 40(%esp), %ecx \n" /* assume syscall success */
640 " movl $0, (%ecx) \n"
641 " movl 36(%esp), %eax \n"
642 " int $0x80 \n"
643 " jnc 1f \n" /* jump if success */
644 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */
645 " movl $1, (%ecx) \n"
646 " 1: ret \n"
647 );
648
649__private_extern__ UInt
650do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
651 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
652 UWord a7, UWord a8, /* 28(esp)..32(esp) */
653 UWord syscall_no /* 36(esp) */ );
654// Mach trap: 32-bit result in %eax, no error flag
655asm(".private_extern _do_syscall_mach_WRK\n"
656 "_do_syscall_mach_WRK:\n"
657 " movl 36(%esp), %eax \n"
658 " int $0x81 \n"
659 " ret \n"
660 );
661
662__private_extern__ UInt
663do_syscall_mdep_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// mdep trap: 32-bit result in %eax, no error flag
668asm(
669 ".private_extern _do_syscall_mdep_WRK\n"
670 "_do_syscall_mdep_WRK:\n"
671 " movl 36(%esp), %eax \n"
672 " int $0x82 \n"
673 " ret \n"
674 );
675
676
677#elif defined(VGP_amd64_darwin)
678
679/* Incoming args (syscall number + up to 8 args) come in registers and stack
680
681 The kernel's syscall calling convention is:
682 * the syscall number goes in rax
683 * the args are passed to the syscall in registers and the stack
684 * the call instruction is 'syscall'
685 Return value:
686 * MACH,MDEP: the return value comes back in rax
687 * UNIX: the return value comes back in rdx:rax (hi64:lo64)
688 Error:
689 * MACH,MDEP: no error is returned
690 * UNIX: the carry flag indicates success or failure
691
692 nb here, sizeof(UWord) == sizeof(ULong)
693*/
694
695__private_extern__ UWord
696do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
697 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
698 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
699 UWord syscall_no, /* 24(rsp) */
700 /*OUT*/ULong* errflag, /* 32(rsp) */
701 /*OUT*/ULong* res2 ); /* 40(rsp) */
702// Unix syscall: 128-bit return in rax:rdx, with LSB in rax
703// error indicated by carry flag: clear=good, set=bad
704asm(".private_extern _do_syscall_unix_WRK\n"
705 "_do_syscall_unix_WRK:\n"
706 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
707 " movq 32(%rsp), %rax \n" /* assume syscall success */
708 " movq $0, (%rax) \n"
709 " movq 24(%rsp), %rax \n" /* load syscall_no */
710 " syscall \n"
711 " jnc 1f \n" /* jump if success */
712 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */
713 " movq $1, (%rcx) \n"
714 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */
715 " movq %rdx, (%rcx) \n"
716 " retq \n" /* return 1st result word */
717 );
718
719__private_extern__ UWord
720do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
721 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */
722 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */
723 UWord syscall_no ); /* 24(rsp) */
724// Mach trap: 64-bit result, no error flag
725asm(".private_extern _do_syscall_mach_WRK\n"
726 "_do_syscall_mach_WRK:\n"
727 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */
728 " movq 24(%rsp), %rax \n" /* load syscall_no */
729 " syscall \n"
730 " retq \n"
731 );
732
sewardjb5b87402011-03-07 16:05:35 +0000733#elif defined(VGP_s390x_linux)
734
735static UWord do_syscall_WRK (
736 UWord syscall_no,
737 UWord arg1, UWord arg2, UWord arg3,
738 UWord arg4, UWord arg5, UWord arg6
739 )
740{
741 register UWord __arg1 asm("2") = arg1;
742 register UWord __arg2 asm("3") = arg2;
743 register UWord __arg3 asm("4") = arg3;
744 register UWord __arg4 asm("5") = arg4;
745 register UWord __arg5 asm("6") = arg5;
746 register UWord __arg6 asm("7") = arg6;
747 register ULong __svcres asm("2");
748
749 __asm__ __volatile__ (
750 "lgr %%r1,%1\n\t"
751 "svc 0\n\t"
752 : "=d" (__svcres)
753 : "a" (syscall_no),
754 "0" (__arg1),
755 "d" (__arg2),
756 "d" (__arg3),
757 "d" (__arg4),
758 "d" (__arg5),
759 "d" (__arg6)
760 : "1", "cc", "memory");
761
762 return (UWord) (__svcres);
763}
764
njn9abd6082005-06-17 21:31:45 +0000765#else
766# error Unknown platform
767#endif
768
sewardj17edf032006-10-17 01:53:34 +0000769
njncda2f0f2009-05-18 02:12:08 +0000770/* Finally, the generic code. This sends the call to the right
771 helper. */
772
njn9abd6082005-06-17 21:31:45 +0000773SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
sewardj17edf032006-10-17 01:53:34 +0000774 UWord a4, UWord a5, UWord a6,
775 UWord a7, UWord a8 )
njn9abd6082005-06-17 21:31:45 +0000776{
njncda2f0f2009-05-18 02:12:08 +0000777# if defined(VGP_x86_linux)
778 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
779 return VG_(mk_SysRes_x86_linux)( val );
sewardj17edf032006-10-17 01:53:34 +0000780
njncda2f0f2009-05-18 02:12:08 +0000781# elif defined(VGP_amd64_linux)
782 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
783 return VG_(mk_SysRes_amd64_linux)( val );
sewardj17edf032006-10-17 01:53:34 +0000784
njncda2f0f2009-05-18 02:12:08 +0000785# elif defined(VGP_ppc32_linux)
786 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
787 UInt val = (UInt)(ret>>32);
788 UInt cr0so = (UInt)(ret);
789 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
sewardj17edf032006-10-17 01:53:34 +0000790
njncda2f0f2009-05-18 02:12:08 +0000791# elif defined(VGP_ppc64_linux)
792 ULong argblock[7];
793 argblock[0] = sysno;
794 argblock[1] = a1;
795 argblock[2] = a2;
796 argblock[3] = a3;
797 argblock[4] = a4;
798 argblock[5] = a5;
799 argblock[6] = a6;
800 do_syscall_WRK( &argblock[0] );
801 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
sewardj17edf032006-10-17 01:53:34 +0000802
sewardj59570ff2010-01-01 11:59:33 +0000803# elif defined(VGP_arm_linux)
804 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
805 return VG_(mk_SysRes_arm_linux)( val );
806
njncda2f0f2009-05-18 02:12:08 +0000807# elif defined(VGP_ppc32_aix5)
sewardj17edf032006-10-17 01:53:34 +0000808 UWord res;
809 UWord err;
810 do_syscall_WRK( &res, &err,
811 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
812 /* Try to set the error number to zero if the syscall hasn't
813 really failed. */
814 if (sysno == __NR_AIX5_kread
815 || sysno == __NR_AIX5_kwrite) {
816 if (res != (UWord)-1L)
817 err = 0;
818 }
819 else if (sysno == __NR_AIX5_sigprocmask
820 || sysno == __NR_AIX5__sigpending) {
821 if (res == 0)
822 err = 0;
823 }
sewardj17edf032006-10-17 01:53:34 +0000824 return VG_(mk_SysRes_ppc32_aix5)( res, err );
825
njncda2f0f2009-05-18 02:12:08 +0000826# elif defined(VGP_ppc64_aix5)
sewardj17edf032006-10-17 01:53:34 +0000827 UWord res;
828 UWord err;
829 do_syscall_WRK( &res, &err,
830 sysno, a1, a2, a3, a4, a5, a6, a7, a8);
831 /* Try to set the error number to zero if the syscall hasn't
832 really failed. */
833 if (sysno == __NR_AIX5_kread
834 || sysno == __NR_AIX5_kwrite) {
835 if (res != (UWord)-1L)
836 err = 0;
837 }
838 else if (sysno == __NR_AIX5_sigprocmask
839 || sysno == __NR_AIX5__sigpending) {
840 if (res == 0)
841 err = 0;
842 }
sewardj17edf032006-10-17 01:53:34 +0000843 return VG_(mk_SysRes_ppc64_aix5)( res, err );
844
njnf76d27a2009-05-28 01:53:07 +0000845# elif defined(VGP_x86_darwin)
846 UInt wLO = 0, wHI = 0, err = 0;
847 ULong u64;
848 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
849 switch (scclass) {
850 case VG_DARWIN_SYSCALL_CLASS_UNIX:
851 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
njn1a1e95c2009-06-03 06:50:06 +0000852 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
njnf76d27a2009-05-28 01:53:07 +0000853 wLO = (UInt)u64;
854 wHI = (UInt)(u64 >> 32);
855 break;
856 case VG_DARWIN_SYSCALL_CLASS_MACH:
857 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
njn1a1e95c2009-06-03 06:50:06 +0000858 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +0000859 err = 0;
860 break;
861 case VG_DARWIN_SYSCALL_CLASS_MDEP:
862 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
njn1a1e95c2009-06-03 06:50:06 +0000863 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +0000864 err = 0;
865 break;
866 default:
867 vg_assert(0);
868 break;
869 }
870 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
871
872# elif defined(VGP_amd64_darwin)
873 ULong wLO = 0, wHI = 0, err = 0;
874 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
875 switch (scclass) {
876 case VG_DARWIN_SYSCALL_CLASS_UNIX:
877 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
njn1a1e95c2009-06-03 06:50:06 +0000878 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
njnf76d27a2009-05-28 01:53:07 +0000879 break;
880 case VG_DARWIN_SYSCALL_CLASS_MACH:
881 case VG_DARWIN_SYSCALL_CLASS_MDEP:
882 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
njn1a1e95c2009-06-03 06:50:06 +0000883 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +0000884 err = 0;
885 break;
886 default:
887 vg_assert(0);
888 break;
889 }
890 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
891
sewardjb5b87402011-03-07 16:05:35 +0000892#elif defined(VGP_s390x_linux)
893 UWord val;
894
895 if (sysno == __NR_mmap) {
896 ULong argbuf[6];
897
898 argbuf[0] = a1;
899 argbuf[1] = a2;
900 argbuf[2] = a3;
901 argbuf[3] = a4;
902 argbuf[4] = a5;
903 argbuf[5] = a6;
904 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
905 } else {
906 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
907 }
908
909 return VG_(mk_SysRes_s390x_linux)( val );
cerion85665ca2005-06-20 15:51:07 +0000910#else
911# error Unknown platform
912#endif
njn9abd6082005-06-17 21:31:45 +0000913}
914
sewardj45f4e7c2005-09-27 19:20:21 +0000915/* ---------------------------------------------------------------------
916 Names of errors.
917 ------------------------------------------------------------------ */
918
919/* Return a string which gives the name of an error value. Note,
920 unlike the standard C syserror fn, the returned string is not
921 malloc-allocated or writable -- treat it as a constant.
922 TODO: implement this properly. */
923
924const HChar* VG_(strerror) ( UWord errnum )
925{
926 switch (errnum) {
927 case VKI_EPERM: return "Operation not permitted";
928 case VKI_ENOENT: return "No such file or directory";
929 case VKI_ESRCH: return "No such process";
930 case VKI_EINTR: return "Interrupted system call";
931 case VKI_EBADF: return "Bad file number";
932 case VKI_EAGAIN: return "Try again";
933 case VKI_ENOMEM: return "Out of memory";
934 case VKI_EACCES: return "Permission denied";
935 case VKI_EFAULT: return "Bad address";
936 case VKI_EEXIST: return "File exists";
937 case VKI_EINVAL: return "Invalid argument";
938 case VKI_EMFILE: return "Too many open files";
939 case VKI_ENOSYS: return "Function not implemented";
tomaf8a6a82006-05-24 12:51:17 +0000940 case VKI_EOVERFLOW: return "Value too large for defined data type";
njncda2f0f2009-05-18 02:12:08 +0000941# if defined(VKI_ERESTARTSYS)
sewardj45f4e7c2005-09-27 19:20:21 +0000942 case VKI_ERESTARTSYS: return "ERESTARTSYS";
njncda2f0f2009-05-18 02:12:08 +0000943# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000944 default: return "VG_(strerror): unknown error";
945 }
946}
947
948
njn9abd6082005-06-17 21:31:45 +0000949/*--------------------------------------------------------------------*/
950/*--- end ---*/
951/*--------------------------------------------------------------------*/