blob: 308fcfef7cd845821d537f77bcb1e45b51c71205 [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
sewardjb3a1e4b2015-08-21 11:32:26 +000010 Copyright (C) 2000-2015 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/* Make a SysRes value from a syscall return value. This is
sewardjbd664fd2015-07-08 17:08:23 +000042 platform specific. */
njn9abd6082005-06-17 21:31:45 +000043
sewardjbd664fd2015-07-08 17:08:23 +000044#if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
45
46SysRes 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
55SysRes 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. */
65SysRes 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
73SysRes 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
81SysRes 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/*
njn9abd6082005-06-17 21:31:45 +000094 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*/
njncda2f0f2009-05-18 02:12:08 +0000110
111SysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
njn9abd6082005-06-17 21:31:45 +0000112 SysRes res;
njncda2f0f2009-05-18 02:12:08 +0000113 res._isError = val >= -4095 && val <= -1;
114 if (res._isError) {
115 res._val = (UInt)(-val);
sewardj17edf032006-10-17 01:53:34 +0000116 } else {
njncda2f0f2009-05-18 02:12:08 +0000117 res._val = (UInt)val;
sewardj17edf032006-10-17 01:53:34 +0000118 }
njn9abd6082005-06-17 21:31:45 +0000119 return res;
120}
121
cerion85665ca2005-06-20 15:51:07 +0000122/* Similarly .. */
njncda2f0f2009-05-18 02:12:08 +0000123SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
cerion85665ca2005-06-20 15:51:07 +0000124 SysRes res;
njncda2f0f2009-05-18 02:12:08 +0000125 res._isError = val >= -4095 && val <= -1;
126 if (res._isError) {
127 res._val = (ULong)(-val);
sewardj17edf032006-10-17 01:53:34 +0000128 } else {
njncda2f0f2009-05-18 02:12:08 +0000129 res._val = (ULong)val;
sewardj17edf032006-10-17 01:53:34 +0000130 }
cerion85665ca2005-06-20 15:51:07 +0000131 return res;
132}
133
sewardj112711a2015-04-10 12:30:09 +0000134SysRes VG_(mk_SysRes_tilegx_linux) ( Long val ) {
135 SysRes res;
sewardj112711a2015-04-10 12:30:09 +0000136 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
sewardj17edf032006-10-17 01:53:34 +0000145/* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
sewardj39a7c1d2005-11-24 03:54:38 +0000146/* Note this must be in the bottom bit of the second arg */
147SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
cerion85665ca2005-06-20 15:51:07 +0000148 SysRes res;
njncda2f0f2009-05-18 02:12:08 +0000149 res._isError = (cr0so & 1) != 0;
150 res._val = val;
cerion85665ca2005-06-20 15:51:07 +0000151 return res;
152}
153
sewardj38a88b72006-01-02 16:32:10 +0000154/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
155SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
sewardj2c48c7b2005-11-29 13:05:56 +0000156 SysRes res;
njncda2f0f2009-05-18 02:12:08 +0000157 res._isError = (cr0so & 1) != 0;
158 res._val = val;
sewardj2c48c7b2005-11-29 13:05:56 +0000159 return res;
160}
161
sewardjb5b87402011-03-07 16:05:35 +0000162SysRes 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
sewardj59570ff2010-01-01 11:59:33 +0000173SysRes 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
sewardjf0c12502014-01-12 12:54:00 +0000184SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
185 SysRes res;
sewardjf0c12502014-01-12 12:54:00 +0000186 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
njncda2f0f2009-05-18 02:12:08 +0000195/* Generic constructors. */
196SysRes VG_(mk_SysRes_Error) ( UWord err ) {
197 SysRes r;
198 r._isError = True;
199 r._val = err;
200 return r;
201}
202
203SysRes VG_(mk_SysRes_Success) ( UWord res ) {
204 SysRes r;
205 r._isError = False;
206 r._val = res;
207 return r;
208}
209
210
njnf76d27a2009-05-28 01:53:07 +0000211#elif defined(VGO_darwin)
212
213/* Darwin: Some syscalls return a double-word result. */
214SysRes 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
247SysRes 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. */
283SysRes 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
291SysRes 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
sewardj8eb8bab2015-07-21 14:44:28 +0000300#elif defined(VGO_solaris)
301
302/* Generic constructors. */
303SysRes 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
311SysRes 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
319SysRes 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
332SysRes 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
njncda2f0f2009-05-18 02:12:08 +0000345#else
346# error "Unknown OS"
347#endif
348
349
njn9abd6082005-06-17 21:31:45 +0000350/* ---------------------------------------------------------------------
njncda2f0f2009-05-18 02:12:08 +0000351 VG_(do_syscall): A function for doing syscalls.
njn9abd6082005-06-17 21:31:45 +0000352 ------------------------------------------------------------------ */
353
njn9abd6082005-06-17 21:31:45 +0000354#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*/
sewardj03d8aa82005-10-14 11:25:49 +0000366extern UWord 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 );
njn9abd6082005-06-17 21:31:45 +0000371asm(
sewardjd9fc3822005-11-18 23:50:43 +0000372".text\n"
philippe9fdca562012-04-16 22:06:47 +0000373".globl do_syscall_WRK\n"
njn9abd6082005-06-17 21:31:45 +0000374"do_syscall_WRK:\n"
philippe4ed95fc2015-05-08 21:37:18 +0000375" .cfi_startproc\n"
njn9abd6082005-06-17 21:31:45 +0000376" push %esi\n"
philippe4ed95fc2015-05-08 21:37:18 +0000377" .cfi_adjust_cfa_offset 4\n"
philippe2d616332015-05-17 08:24:40 +0000378" .cfi_offset %esi, -8\n"
njn9abd6082005-06-17 21:31:45 +0000379" push %edi\n"
philippe4ed95fc2015-05-08 21:37:18 +0000380" .cfi_adjust_cfa_offset 4\n"
philippe2d616332015-05-17 08:24:40 +0000381" .cfi_offset %edi, -12\n"
njn9abd6082005-06-17 21:31:45 +0000382" push %ebx\n"
philippe4ed95fc2015-05-08 21:37:18 +0000383" .cfi_adjust_cfa_offset 4\n"
philippe2d616332015-05-17 08:24:40 +0000384" .cfi_offset %ebx, -16\n"
njn9abd6082005-06-17 21:31:45 +0000385" push %ebp\n"
philippe4ed95fc2015-05-08 21:37:18 +0000386" .cfi_adjust_cfa_offset 4\n"
philippe2d616332015-05-17 08:24:40 +0000387" .cfi_offset %ebp, -20\n"
njn9abd6082005-06-17 21:31:45 +0000388" 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"
philippe4ed95fc2015-05-08 21:37:18 +0000397" .cfi_adjust_cfa_offset -4\n"
philippe2d616332015-05-17 08:24:40 +0000398" .cfi_restore %ebp\n"
njn9abd6082005-06-17 21:31:45 +0000399" popl %ebx\n"
philippe4ed95fc2015-05-08 21:37:18 +0000400" .cfi_adjust_cfa_offset -4\n"
philippe2d616332015-05-17 08:24:40 +0000401" .cfi_restore %ebx\n"
njn9abd6082005-06-17 21:31:45 +0000402" popl %edi\n"
philippe4ed95fc2015-05-08 21:37:18 +0000403" .cfi_adjust_cfa_offset -4\n"
philippe2d616332015-05-17 08:24:40 +0000404" .cfi_restore %edi\n"
njn9abd6082005-06-17 21:31:45 +0000405" popl %esi\n"
philippe4ed95fc2015-05-08 21:37:18 +0000406" .cfi_adjust_cfa_offset -4\n"
philippe2d616332015-05-17 08:24:40 +0000407" .cfi_restore %esi\n"
njn9abd6082005-06-17 21:31:45 +0000408" ret\n"
philippe4ed95fc2015-05-08 21:37:18 +0000409" .cfi_endproc\n"
sewardj2fedc642005-11-19 02:02:57 +0000410".previous\n"
njn9abd6082005-06-17 21:31:45 +0000411);
sewardj2c48c7b2005-11-29 13:05:56 +0000412
njn9abd6082005-06-17 21:31:45 +0000413#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*/
sewardj03d8aa82005-10-14 11:25:49 +0000426extern UWord do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000427 UWord syscall_no,
428 UWord a1, UWord a2, UWord a3,
429 UWord a4, UWord a5, UWord a6
430 );
njn9abd6082005-06-17 21:31:45 +0000431asm(
sewardjd9fc3822005-11-18 23:50:43 +0000432".text\n"
philippe9fdca562012-04-16 22:06:47 +0000433".globl do_syscall_WRK\n"
njn9abd6082005-06-17 21:31:45 +0000434"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"
sewardj2fedc642005-11-19 02:02:57 +0000446".previous\n"
njn9abd6082005-06-17 21:31:45 +0000447);
sewardj2c48c7b2005-11-29 13:05:56 +0000448
cerion85665ca2005-06-20 15:51:07 +0000449#elif defined(VGP_ppc32_linux)
sewardj39a7c1d2005-11-24 03:54:38 +0000450/* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
cerion85665ca2005-06-20 15:51:07 +0000451
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.
sewardj39a7c1d2005-11-24 03:54:38 +0000456 We return the syscall return value in %r3, and the %cr0.so in
457 the lowest bit of %r4.
cerion85665ca2005-06-20 15:51:07 +0000458 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*/
sewardj03d8aa82005-10-14 11:25:49 +0000461extern ULong do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000462 UWord syscall_no,
463 UWord a1, UWord a2, UWord a3,
464 UWord a4, UWord a5, UWord a6
465 );
466asm(
sewardjd9fc3822005-11-18 23:50:43 +0000467".text\n"
philippe9fdca562012-04-16 22:06:47 +0000468".globl do_syscall_WRK\n"
cerion85665ca2005-06-20 15:51:07 +0000469"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 */
sewardj2fedc642005-11-19 02:02:57 +0000481".previous\n"
cerion85665ca2005-06-20 15:51:07 +0000482);
sewardj2c48c7b2005-11-29 13:05:56 +0000483
carllcae0cc22014-08-07 23:17:29 +0000484#elif defined(VGP_ppc64be_linux)
sewardj2c48c7b2005-11-29 13:05:56 +0000485/* 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
njncda2f0f2009-05-18 02:12:08 +0000489 bottom bit of [1]. */
sewardj2c48c7b2005-11-29 13:05:56 +0000490extern void do_syscall_WRK ( ULong* argblock );
491asm(
cerion297c88f2005-12-22 15:53:12 +0000492".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"
sewardj2c48c7b2005-11-29 13:05:56 +0000501".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 */
sewardj2c48c7b2005-11-29 13:05:56 +0000513" 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"
sewardj2c48c7b2005-11-29 13:05:56 +0000518);
sewardj17edf032006-10-17 01:53:34 +0000519
carll582d5822014-08-07 23:35:54 +0000520#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]. */
526extern 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 */
530asm(
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
sewardj59570ff2010-01-01 11:59:33 +0000559#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*/
567extern UWord do_syscall_WRK (
568 UWord a1, UWord a2, UWord a3,
569 UWord a4, UWord a5, UWord a6,
570 UWord syscall_no
571 );
572asm(
573".text\n"
philippe9fdca562012-04-16 22:06:47 +0000574".globl do_syscall_WRK\n"
sewardj59570ff2010-01-01 11:59:33 +0000575"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
sewardjf0c12502014-01-12 12:54:00 +0000586#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*/
597extern UWord do_syscall_WRK (
598 UWord a1, UWord a2, UWord a3,
599 UWord a4, UWord a5, UWord a6,
600 UWord syscall_no
601 );
602asm(
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
njnf76d27a2009-05-28 01:53:07 +0000614#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
643do_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
650asm(".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
663do_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
668asm(".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
676do_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
681asm(
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
709do_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
717asm(".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
733do_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
738asm(".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
sewardjb5b87402011-03-07 16:05:35 +0000746#elif defined(VGP_s390x_linux)
747
748static 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
sewardj5db15402012-06-07 09:13:21 +0000778#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*/
788extern 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 );
793asm(
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
petarj4df0bfc2013-02-27 23:17:33 +0000812#elif defined(VGP_mips64_linux)
813extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
814 UWord a6, UWord syscall_no, ULong* V1_val );
815asm (
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
sewardj112711a2015-04-10 12:30:09 +0000831#elif defined(VGP_tilegx_linux)
832extern UWord do_syscall_WRK (
833 UWord syscall_no,
834 UWord a1, UWord a2, UWord a3,
835 UWord a4, UWord a5, UWord a6
836 );
837asm(
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
sewardj8eb8bab2015-07-21 14:44:28 +0000852#elif defined(VGP_x86_solaris)
853
854extern ULong
855do_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
878extern ULong
879do_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
894extern ULong
895do_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
923extern ULong
924do_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
njn9abd6082005-06-17 21:31:45 +0000939#else
940# error Unknown platform
941#endif
942
sewardj17edf032006-10-17 01:53:34 +0000943
njncda2f0f2009-05-18 02:12:08 +0000944/* Finally, the generic code. This sends the call to the right
945 helper. */
946
njn9abd6082005-06-17 21:31:45 +0000947SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
sewardj17edf032006-10-17 01:53:34 +0000948 UWord a4, UWord a5, UWord a6,
949 UWord a7, UWord a8 )
njn9abd6082005-06-17 21:31:45 +0000950{
njncda2f0f2009-05-18 02:12:08 +0000951# 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 );
sewardj17edf032006-10-17 01:53:34 +0000954
njncda2f0f2009-05-18 02:12:08 +0000955# 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 );
sewardj17edf032006-10-17 01:53:34 +0000958
njncda2f0f2009-05-18 02:12:08 +0000959# 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 );
sewardj17edf032006-10-17 01:53:34 +0000964
carllcae0cc22014-08-07 23:17:29 +0000965# elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
njncda2f0f2009-05-18 02:12:08 +0000966 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] );
sewardj17edf032006-10-17 01:53:34 +0000976
sewardj59570ff2010-01-01 11:59:33 +0000977# 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
sewardjf0c12502014-01-12 12:54:00 +0000981# 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
njnf76d27a2009-05-28 01:53:07 +0000985# 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,
njn1a1e95c2009-06-03 06:50:06 +0000992 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
njnf76d27a2009-05-28 01:53:07 +0000993 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,
njn1a1e95c2009-06-03 06:50:06 +0000998 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +0000999 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,
njn1a1e95c2009-06-03 06:50:06 +00001003 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +00001004 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,
njn1a1e95c2009-06-03 06:50:06 +00001018 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
njnf76d27a2009-05-28 01:53:07 +00001019 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,
njn1a1e95c2009-06-03 06:50:06 +00001023 VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
njnf76d27a2009-05-28 01:53:07 +00001024 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
sewardjb5b87402011-03-07 16:05:35 +00001032#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 );
sewardj5db15402012-06-07 09:13:21 +00001050
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 );
petarj4df0bfc2013-02-27 23:17:33 +00001057
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
sewardj112711a2015-04-10 12:30:09 +00001067# 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
sewardj8eb8bab2015-07-21 14:44:28 +00001072# 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
cerion85665ca2005-06-20 15:51:07 +00001128#else
1129# error Unknown platform
1130#endif
njn9abd6082005-06-17 21:31:45 +00001131}
1132
sewardj45f4e7c2005-09-27 19:20:21 +00001133/* ---------------------------------------------------------------------
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
1142const HChar* VG_(strerror) ( UWord errnum )
1143{
1144 switch (errnum) {
florian59451642011-12-24 21:50:53 +00001145 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";
njncda2f0f2009-05-18 02:12:08 +00001182# if defined(VKI_ERESTARTSYS)
sewardj45f4e7c2005-09-27 19:20:21 +00001183 case VKI_ERESTARTSYS: return "ERESTARTSYS";
njncda2f0f2009-05-18 02:12:08 +00001184# endif
florian59451642011-12-24 21:50:53 +00001185 default: return "VG_(strerror): unknown error";
sewardj45f4e7c2005-09-27 19:20:21 +00001186 }
1187}
1188
1189
njn9abd6082005-06-17 21:31:45 +00001190/*--------------------------------------------------------------------*/
florian59451642011-12-24 21:50:53 +00001191/*--- end ---*/
njn9abd6082005-06-17 21:31:45 +00001192/*--------------------------------------------------------------------*/