blob: fe64462d4603689da8c66feda30f35bd6915ee41 [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
10 Copyright (C) 2000-2005 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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njn9abd6082005-06-17 21:31:45 +000032#include "pub_core_syscall.h"
33
34/* ---------------------------------------------------------------------
35 Building syscall return values.
36 ------------------------------------------------------------------ */
37
38/* Make a SysRes value from an syscall return value. This is
39 Linux-specific.
40
41 From:
42 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
43 linux/i386/sysdep.h?
44 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
45
46 Linux uses a negative return value to indicate syscall errors,
47 unlike most Unices, which use the condition codes' carry flag.
48
49 Since version 2.1 the return value of a system call might be
50 negative even if the call succeeded. E.g., the 'lseek' system call
51 might return a large offset. Therefore we must not anymore test
52 for < 0, but test for a real error by making sure the value in %eax
53 is a real error number. Linus said he will make sure the no
54 syscall returns a value in -1 .. -4095 as a valid result so we can
55 safely test with -4095.
56*/
sewardj2c48c7b2005-11-29 13:05:56 +000057SysRes VG_(mk_SysRes_x86_linux) ( UInt val ) {
njn9abd6082005-06-17 21:31:45 +000058 SysRes res;
njn9abd6082005-06-17 21:31:45 +000059 res.isError = val >= -4095 && val <= -1;
60 res.val = res.isError ? -val : val;
njn9abd6082005-06-17 21:31:45 +000061 return res;
62}
63
cerion85665ca2005-06-20 15:51:07 +000064/* Similarly .. */
sewardj2c48c7b2005-11-29 13:05:56 +000065SysRes VG_(mk_SysRes_amd64_linux) ( ULong val ) {
cerion85665ca2005-06-20 15:51:07 +000066 SysRes res;
67 res.isError = val >= -4095 && val <= -1;
68 res.val = res.isError ? -val : val;
69 return res;
70}
71
sewardje5c600e2005-06-20 18:14:27 +000072/* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speke) */
sewardj39a7c1d2005-11-24 03:54:38 +000073/* Note this must be in the bottom bit of the second arg */
74SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
cerion85665ca2005-06-20 15:51:07 +000075 SysRes res;
sewardj39a7c1d2005-11-24 03:54:38 +000076 res.isError = (cr0so & 1) != 0;
cerion85665ca2005-06-20 15:51:07 +000077 res.val = val;
78 return res;
79}
80
sewardj38a88b72006-01-02 16:32:10 +000081/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
82SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
sewardj2c48c7b2005-11-29 13:05:56 +000083 SysRes res;
sewardj38a88b72006-01-02 16:32:10 +000084 res.isError = (cr0so & 1) != 0;
sewardj2c48c7b2005-11-29 13:05:56 +000085 res.val = val;
86 return res;
87}
88
cerion85665ca2005-06-20 15:51:07 +000089
njn9abd6082005-06-17 21:31:45 +000090SysRes VG_(mk_SysRes_Error) ( UWord val ) {
91 SysRes r = { val, True };
92 return r;
93}
94
95SysRes VG_(mk_SysRes_Success) ( UWord val ) {
96 SysRes r = { val, False };
97 return r;
98}
99
100
101/* ---------------------------------------------------------------------
102 A function for doing syscalls.
103 ------------------------------------------------------------------ */
104
njn9abd6082005-06-17 21:31:45 +0000105#if defined(VGP_x86_linux)
106/* Incoming args (syscall number + up to 6 args) come on the stack.
107 (ie. the C calling convention).
108
109 The syscall number goes in %eax. The args are passed to the syscall in
110 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
111 calling convention.
112
113 %eax gets the return value. Not sure which registers the kernel
114 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
115 %ebp).
116*/
sewardj03d8aa82005-10-14 11:25:49 +0000117extern UWord do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000118 UWord syscall_no,
119 UWord a1, UWord a2, UWord a3,
120 UWord a4, UWord a5, UWord a6
121 );
njn9abd6082005-06-17 21:31:45 +0000122asm(
sewardjd9fc3822005-11-18 23:50:43 +0000123".text\n"
njn9abd6082005-06-17 21:31:45 +0000124"do_syscall_WRK:\n"
125" push %esi\n"
126" push %edi\n"
127" push %ebx\n"
128" push %ebp\n"
129" movl 16+ 4(%esp),%eax\n"
130" movl 16+ 8(%esp),%ebx\n"
131" movl 16+12(%esp),%ecx\n"
132" movl 16+16(%esp),%edx\n"
133" movl 16+20(%esp),%esi\n"
134" movl 16+24(%esp),%edi\n"
135" movl 16+28(%esp),%ebp\n"
136" int $0x80\n"
137" popl %ebp\n"
138" popl %ebx\n"
139" popl %edi\n"
140" popl %esi\n"
141" ret\n"
sewardj2fedc642005-11-19 02:02:57 +0000142".previous\n"
njn9abd6082005-06-17 21:31:45 +0000143);
sewardj2c48c7b2005-11-29 13:05:56 +0000144
njn9abd6082005-06-17 21:31:45 +0000145#elif defined(VGP_amd64_linux)
146/* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
147 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
148 calling convention).
149
150 The syscall number goes in %rax. The args are passed to the syscall in
151 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
152 ie. the kernel's syscall calling convention.
153
154 %rax gets the return value. %rcx and %r11 are clobbered by the syscall;
155 no matter, they are caller-save (the syscall clobbers no callee-save
156 regs, so we don't have to do any register saving/restoring).
157*/
sewardj03d8aa82005-10-14 11:25:49 +0000158extern UWord do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000159 UWord syscall_no,
160 UWord a1, UWord a2, UWord a3,
161 UWord a4, UWord a5, UWord a6
162 );
njn9abd6082005-06-17 21:31:45 +0000163asm(
sewardjd9fc3822005-11-18 23:50:43 +0000164".text\n"
njn9abd6082005-06-17 21:31:45 +0000165"do_syscall_WRK:\n"
166 /* Convert function calling convention --> syscall calling
167 convention */
168" movq %rdi, %rax\n"
169" movq %rsi, %rdi\n"
170" movq %rdx, %rsi\n"
171" movq %rcx, %rdx\n"
172" movq %r8, %r10\n"
173" movq %r9, %r8\n"
174" movq 8(%rsp), %r9\n" /* last arg from stack */
175" syscall\n"
176" ret\n"
sewardj2fedc642005-11-19 02:02:57 +0000177".previous\n"
njn9abd6082005-06-17 21:31:45 +0000178);
sewardj2c48c7b2005-11-29 13:05:56 +0000179
cerion85665ca2005-06-20 15:51:07 +0000180#elif defined(VGP_ppc32_linux)
sewardj39a7c1d2005-11-24 03:54:38 +0000181/* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
cerion85665ca2005-06-20 15:51:07 +0000182
183 The syscall number goes in %r0. The args are passed to the syscall in
184 the regs %r3:%r8, i.e. the kernel's syscall calling convention.
185
186 The %cr0.so bit flags an error.
sewardj39a7c1d2005-11-24 03:54:38 +0000187 We return the syscall return value in %r3, and the %cr0.so in
188 the lowest bit of %r4.
cerion85665ca2005-06-20 15:51:07 +0000189 We return a ULong, of which %r3 is the high word, and %r4 the low.
190 No callee-save regs are clobbered, so no saving/restoring is needed.
191*/
sewardj03d8aa82005-10-14 11:25:49 +0000192extern ULong do_syscall_WRK (
cerion85665ca2005-06-20 15:51:07 +0000193 UWord syscall_no,
194 UWord a1, UWord a2, UWord a3,
195 UWord a4, UWord a5, UWord a6
196 );
197asm(
sewardjd9fc3822005-11-18 23:50:43 +0000198".text\n"
cerion85665ca2005-06-20 15:51:07 +0000199"do_syscall_WRK:\n"
200" mr 0,3\n"
201" mr 3,4\n"
202" mr 4,5\n"
203" mr 5,6\n"
204" mr 6,7\n"
205" mr 7,8\n"
206" mr 8,9\n"
207" sc\n" /* syscall: sets %cr0.so on error */
208" mfcr 4\n" /* %cr -> low word of return var */
209" rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
210" blr\n" /* and return */
sewardj2fedc642005-11-19 02:02:57 +0000211".previous\n"
cerion85665ca2005-06-20 15:51:07 +0000212);
sewardj2c48c7b2005-11-29 13:05:56 +0000213
214#elif defined(VGP_ppc64_linux)
215/* Due to the need to return 65 bits of result, this is completely
216 different from the ppc32 case. The single arg register points to a
217 7-word block containing the syscall # and the 6 args. The syscall
218 result proper is put in [0] of the block, and %cr0.so is in the
219 bottom but of [1]. */
220extern void do_syscall_WRK ( ULong* argblock );
221asm(
cerion297c88f2005-12-22 15:53:12 +0000222".align 2\n"
223".globl do_syscall_WRK\n"
224".section \".opd\",\"aw\"\n"
225".align 3\n"
226"do_syscall_WRK:\n"
227".quad .do_syscall_WRK,.TOC.@tocbase,0\n"
228".previous\n"
229".type .do_syscall_WRK,@function\n"
230".globl .do_syscall_WRK\n"
sewardj2c48c7b2005-11-29 13:05:56 +0000231".do_syscall_WRK:\n"
232" std 3,-16(1)\n" /* stash arg */
233" ld 8, 48(3)\n" /* sc arg 6 */
234" ld 7, 40(3)\n" /* sc arg 5 */
235" ld 6, 32(3)\n" /* sc arg 4 */
236" ld 5, 24(3)\n" /* sc arg 3 */
237" ld 4, 16(3)\n" /* sc arg 2 */
238" ld 0, 0(3)\n" /* sc number */
239" ld 3, 8(3)\n" /* sc arg 1 */
240" sc\n" /* result in r3 and cr0.so */
241" ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
242" std 3,0(5)\n" /* argblock[0] = r3 */
sewardj2c48c7b2005-11-29 13:05:56 +0000243" mfcr 3\n"
244" srwi 3,3,28\n"
245" andi. 3,3,1\n"
246" std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
247" blr\n"
sewardj2c48c7b2005-11-29 13:05:56 +0000248);
njn9abd6082005-06-17 21:31:45 +0000249#else
250# error Unknown platform
251#endif
252
253SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
254 UWord a4, UWord a5, UWord a6 )
255{
cerion85665ca2005-06-20 15:51:07 +0000256#if defined(VGP_x86_linux)
257 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
258 return VG_(mk_SysRes_x86_linux)( val );
259#elif defined(VGP_amd64_linux)
260 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
261 return VG_(mk_SysRes_amd64_linux)( val );
262#elif defined(VGP_ppc32_linux)
263 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
264 UInt val = (UInt)(ret>>32);
sewardj39a7c1d2005-11-24 03:54:38 +0000265 UInt cr0so = (UInt)(ret);
266 return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
sewardj2c48c7b2005-11-29 13:05:56 +0000267#elif defined(VGP_ppc64_linux)
268 ULong argblock[7];
269 argblock[0] = sysno;
270 argblock[1] = a1;
271 argblock[2] = a2;
272 argblock[3] = a3;
273 argblock[4] = a4;
274 argblock[5] = a5;
275 argblock[6] = a6;
276 do_syscall_WRK( &argblock[0] );
277 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
cerion85665ca2005-06-20 15:51:07 +0000278#else
279# error Unknown platform
280#endif
njn9abd6082005-06-17 21:31:45 +0000281}
282
sewardj45f4e7c2005-09-27 19:20:21 +0000283/* ---------------------------------------------------------------------
284 Names of errors.
285 ------------------------------------------------------------------ */
286
287/* Return a string which gives the name of an error value. Note,
288 unlike the standard C syserror fn, the returned string is not
289 malloc-allocated or writable -- treat it as a constant.
290 TODO: implement this properly. */
291
292const HChar* VG_(strerror) ( UWord errnum )
293{
294 switch (errnum) {
295 case VKI_EPERM: return "Operation not permitted";
296 case VKI_ENOENT: return "No such file or directory";
297 case VKI_ESRCH: return "No such process";
298 case VKI_EINTR: return "Interrupted system call";
299 case VKI_EBADF: return "Bad file number";
300 case VKI_EAGAIN: return "Try again";
301 case VKI_ENOMEM: return "Out of memory";
302 case VKI_EACCES: return "Permission denied";
303 case VKI_EFAULT: return "Bad address";
304 case VKI_EEXIST: return "File exists";
305 case VKI_EINVAL: return "Invalid argument";
306 case VKI_EMFILE: return "Too many open files";
307 case VKI_ENOSYS: return "Function not implemented";
308 case VKI_ERESTARTSYS: return "ERESTARTSYS";
309 default: return "VG_(strerror): unknown error";
310 }
311}
312
313
njn9abd6082005-06-17 21:31:45 +0000314/*--------------------------------------------------------------------*/
315/*--- end ---*/
316/*--------------------------------------------------------------------*/