blob: b8beb770733688128f0308342b00bd7b248692c7 [file] [log] [blame]
cerion85665ca2005-06-20 15:51:07 +00001
2/*--------------------------------------------------------------------*/
3/*--- Platform-specific syscalls stuff. syswrap-ppc32-linux.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
njnbd774032005-08-04 19:26:54 +000010 Copyright (C) 2005 Nicholas Nethercote <njn@valgrind.org>
cerion85665ca2005-06-20 15:51:07 +000011 Copyright (C) 2005 Cerion Armour-Brown <cerion@open-works.co.uk>
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_threadstate.h"
njn899ce732005-06-21 00:28:11 +000033#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
cerion85665ca2005-06-20 15:51:07 +000034#include "pub_core_aspacemgr.h"
njn899ce732005-06-21 00:28:11 +000035#include "pub_core_debuglog.h"
cerion85665ca2005-06-20 15:51:07 +000036#include "pub_core_libcbase.h"
37#include "pub_core_libcassert.h"
38#include "pub_core_libcmman.h"
39#include "pub_core_libcprint.h"
40#include "pub_core_libcproc.h"
41#include "pub_core_libcsignal.h"
42#include "pub_core_main.h" // For VG_(shutdown_actions_NORETURN)()
43#include "pub_core_options.h"
44#include "pub_core_scheduler.h"
45#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
46#include "pub_core_signals.h"
47#include "pub_core_syscall.h"
48#include "pub_core_syswrap.h"
49#include "pub_core_tooliface.h"
50
51#include "priv_types_n_macros.h"
52#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
53#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
54#include "priv_syswrap-main.h"
55
56#include "vki_unistd.h" /* for the __NR_* constants */
57
58
59/* ---------------------------------------------------------------------
60 Stacks, thread wrappers, clone
61 Note. Why is this stuff here?
62 ------------------------------------------------------------------ */
63
64/*
65 Allocate a stack for this thread.
66 They're allocated lazily, but never freed.
67 */
68#define FILL 0xdeadbeef
69
70// Valgrind's stack size, in words.
71#define STACK_SIZE_W 16384
72
73static UWord* allocstack(ThreadId tid)
74{
75 ThreadState *tst = VG_(get_ThreadState)(tid);
76 UWord *sp;
77
78 if (tst->os_state.valgrind_stack_base == 0) {
79 void *stk = VG_(mmap)(0, STACK_SIZE_W * sizeof(UWord) + VKI_PAGE_SIZE,
80 VKI_PROT_READ|VKI_PROT_WRITE,
81 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
82 SF_VALGRIND,
83 -1, 0);
84
85 if (stk != (void *)-1) {
86 VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page */
87 tst->os_state.valgrind_stack_base = ((Addr)stk) + VKI_PAGE_SIZE;
88 tst->os_state.valgrind_stack_szB = STACK_SIZE_W * sizeof(UWord);
89 } else
90 return (UWord*)-1;
91 }
92
93 for (sp = (UWord*) tst->os_state.valgrind_stack_base;
94 sp < (UWord*)(tst->os_state.valgrind_stack_base +
95 tst->os_state.valgrind_stack_szB);
96 sp++)
97 *sp = FILL;
98 /* sp is left at top of stack */
99
100 if (0)
101 VG_(printf)("stack for tid %d at %p (%x); sp=%p\n",
102 tid, tst->os_state.valgrind_stack_base,
103 *(UWord*)(tst->os_state.valgrind_stack_base), sp);
104
105 vg_assert(VG_IS_16_ALIGNED(sp));
106
107 return sp;
108}
109
110/* NB: this is identical the the amd64 version. */
111/* Return how many bytes of this stack have not been used */
njnaf839f52005-06-23 03:27:57 +0000112SSizeT VG_(stack_unused)(ThreadId tid)
cerion85665ca2005-06-20 15:51:07 +0000113{
114 ThreadState *tst = VG_(get_ThreadState)(tid);
115 UWord* p;
116
117 for (p = (UWord*)tst->os_state.valgrind_stack_base;
118 p && (p < (UWord*)(tst->os_state.valgrind_stack_base +
119 tst->os_state.valgrind_stack_szB));
120 p++)
121 if (*p != FILL)
122 break;
123
124 if (0)
125 VG_(printf)("p=%p %x tst->os_state.valgrind_stack_base=%p\n",
126 p, *p, tst->os_state.valgrind_stack_base);
127
128 return ((Addr)p) - tst->os_state.valgrind_stack_base;
129}
130
131
132/* Run a thread all the way to the end, then do appropriate exit actions
133 (this is the last-one-out-turn-off-the-lights bit).
134*/
135static void run_a_thread_NORETURN ( Word tidW )
136{
137 ThreadId tid = (ThreadId)tidW;
138
sewardje23772f2005-07-02 11:27:02 +0000139 VG_(debugLog)(1, "syswrap-ppc32-linux",
cerion85665ca2005-06-20 15:51:07 +0000140 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000141 "ML_(thread_wrapper) called\n",
cerion85665ca2005-06-20 15:51:07 +0000142 (ULong)tidW);
143
144 /* Run the thread all the way through. */
cerion7b2c38c2005-06-23 07:52:54 +0000145 VgSchedReturnCode src = ML_(thread_wrapper)(tid);
cerion85665ca2005-06-20 15:51:07 +0000146
sewardje23772f2005-07-02 11:27:02 +0000147 VG_(debugLog)(1, "syswrap-ppc32-linux",
cerion85665ca2005-06-20 15:51:07 +0000148 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000149 "ML_(thread_wrapper) done\n",
cerion85665ca2005-06-20 15:51:07 +0000150 (ULong)tidW);
151
152 Int c = VG_(count_living_threads)();
153 vg_assert(c >= 1); /* stay sane */
154
155 if (c == 1) {
156
sewardje23772f2005-07-02 11:27:02 +0000157 VG_(debugLog)(1, "syswrap-ppc32-linux",
cerion85665ca2005-06-20 15:51:07 +0000158 "run_a_thread_NORETURN(tid=%lld): "
159 "last one standing\n",
160 (ULong)tidW);
161
162 /* We are the last one standing. Keep hold of the lock and
163 carry on to show final tool results, then exit the entire system. */
164 VG_(shutdown_actions_NORETURN)(tid, src);
165
166 } else {
sewardje23772f2005-07-02 11:27:02 +0000167 VG_(debugLog)(1, "syswrap-ppc32-linux",
cerion85665ca2005-06-20 15:51:07 +0000168 "run_a_thread_NORETURN(tid=%lld): "
169 "not last one standing\n",
170 (ULong)tidW);
171
172 /* OK, thread is dead, but others still exist. Just exit. */
173 ThreadState *tst = VG_(get_ThreadState)(tid);
174
175 /* This releases the run lock */
176 VG_(exit_thread)(tid);
177 vg_assert(tst->status == VgTs_Zombie);
178
179 /* We have to use this sequence to terminate the thread to
180 prevent a subtle race. If VG_(exit_thread)() had left the
181 ThreadState as Empty, then it could have been reallocated,
182 reusing the stack while we're doing these last cleanups.
183 Instead, VG_(exit_thread) leaves it as Zombie to prevent
184 reallocation. We need to make sure we don't touch the stack
185 between marking it Empty and exiting. Hence the
186 assembler. */
187
188 asm volatile (
189 "stw %1,%0\n\t" /* set tst->status = VgTs_Empty */
190 "li 0,%2\n\t" /* set r0 = __NR_exit */
191 "lwz 3,%3\n\t" /* set r3 = tst->os_state.exitcode */
192 "sc\n\t" /* exit(tst->os_state.exitcode) */
193 : "=m" (tst->status)
194 : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
195
196 VG_(core_panic)("Thread exit failed?\n");
197 }
198
199 /*NOTREACHED*/
200 vg_assert(0);
201}
202
203
204/* Call f(arg1), but first switch stacks, using 'stack' as the new
205 stack, and use 'retaddr' as f's return-to address. Also, clear all
206 the integer registers before entering f.*/
207__attribute__((noreturn))
208void call_on_new_stack_0_1 ( Addr stack,
209 Addr retaddr,
210 void (*f)(Word),
211 Word arg1 );
212// r3 = stack
213// r4 = retaddr
214// r5 = f
215// r6 = arg1
216asm(
217"call_on_new_stack_0_1:\n"
218" mr %r1,%r3\n\t" // stack to %sp
219" mtlr %r4\n\t" // retaddr to %lr
220" mtctr %r5\n\t" // f to count reg
221" mr %r3,%r6\n\t" // arg1 to %r3
222" li 0,0\n\t" // zero all GP regs
223" li 4,0\n\t"
224" li 5,0\n\t"
225" li 6,0\n\t"
226" li 7,0\n\t"
227" li 8,0\n\t"
228" li 9,0\n\t"
229" li 10,0\n\t"
230" li 11,0\n\t"
231" li 12,0\n\t"
232" li 13,0\n\t"
233" li 14,0\n\t"
234" li 15,0\n\t"
235" li 16,0\n\t"
236" li 17,0\n\t"
237" li 18,0\n\t"
238" li 19,0\n\t"
239" li 20,0\n\t"
240" li 21,0\n\t"
241" li 22,0\n\t"
242" li 23,0\n\t"
243" li 24,0\n\t"
244" li 25,0\n\t"
245" li 26,0\n\t"
246" li 27,0\n\t"
247" li 28,0\n\t"
248" li 29,0\n\t"
249" li 30,0\n\t"
250" li 31,0\n\t"
251" mtxer 0\n\t" // CAB: Need this?
252" mtcr 0\n\t" // CAB: Need this?
253" bctr\n\t" // jump to dst
254" trap\n" // should never get here
255);
256
257
258/*
259 Allocate a stack for the main thread, and run it all the way to the
260 end.
261 */
njnaf839f52005-06-23 03:27:57 +0000262void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
cerion85665ca2005-06-20 15:51:07 +0000263{
sewardje23772f2005-07-02 11:27:02 +0000264 VG_(debugLog)(1, "syswrap-ppc32-linux",
njnaf839f52005-06-23 03:27:57 +0000265 "entering VG_(main_thread_wrapper_NORETURN)\n");
cerion85665ca2005-06-20 15:51:07 +0000266
267 UWord* sp = allocstack(tid);
268
269 /* make a stack frame */
270 sp -= 16;
271 *(UWord *)sp = 0;
272
273 /* shouldn't be any other threads around yet */
274 vg_assert( VG_(count_living_threads)() == 1 );
275
276 call_on_new_stack_0_1(
277 (Addr)sp, /* stack */
278 0, /*bogus return address*/
279 run_a_thread_NORETURN, /* fn to call */
280 (Word)tid /* arg to give it */
281 );
282
283 /*NOTREACHED*/
284 vg_assert(0);
285}
286
cerion85665ca2005-06-20 15:51:07 +0000287static Int start_thread_NORETURN ( void* arg )
288{
289 ThreadState* tst = (ThreadState*)arg;
290 ThreadId tid = tst->tid;
291
292 run_a_thread_NORETURN ( (Word)tid );
293 /*NOTREACHED*/
294 vg_assert(0);
295}
sewardje23772f2005-07-02 11:27:02 +0000296
cerion85665ca2005-06-20 15:51:07 +0000297
298/* ---------------------------------------------------------------------
299 clone() handling
300 ------------------------------------------------------------------ */
301
302/*
303 Perform a clone system call. clone is strange because it has
304 fork()-like return-twice semantics, so it needs special
305 handling here.
306
307 Upon entry, we have:
308
309 int (fn)(void*) in r3
310 void* child_stack in r4
311 int flags in r5
312 void* arg in r6
313 pid_t* child_tid in r7
314 pid_t* parent_tid in r8
315 void* tls_ptr in r9
316
317 System call requires:
318
319 int $__NR_clone in r0 (sc number)
320 int flags in r3 (sc arg1)
321 void* child_stack in r4 (sc arg2)
322 pid_t* parent_tid in r5 (sc arg3)
323 pid_t* child_tid in r6 (sc arg4)
324 void* tls_ptr in r7 (sc arg5)
325
326 Returns an Int encoded in the linux-ppc32 way, not a SysRes.
327 */
328#define STRINGIFZ(__str) #__str
329#define STRINGIFY(__str) STRINGIFZ(__str)
330#define __NR_CLONE STRINGIFY(__NR_clone)
331#define __NR_EXIT STRINGIFY(__NR_exit)
332
333extern
334ULong do_syscall_clone_ppc32_linux ( Int (*fn)(void *),
335 void* stack,
336 Int flags,
337 void* arg,
338 Int* child_tid,
339 Int* parent_tid,
340 vki_modify_ldt_t * );
341asm(
342"\n"
343"do_syscall_clone_ppc32_linux:\n"
344" stwu 1,-32(1)\n"
345" stw 29,20(1)\n"
346" stw 30,24(1)\n"
347" stw 31,28(1)\n"
348" mr 30,3\n" // preserve fn
349" mr 31,6\n" // preserve arg
350
351 // setup child stack
352" rlwinm 4,4,0,~0xf\n" // trim sp to multiple of 16 bytes
353" li 0,0\n"
354" stwu 0,-16(4)\n" // make initial stack frame
355" mr 29,4\n" // preserve sp
356
357 // setup syscall
358" li 0,"__NR_CLONE"\n" // syscall number
359" mr 3,5\n" // syscall arg1: flags
360 // r4 already setup // syscall arg2: child_stack
361" mr 5,8\n" // syscall arg3: parent_tid
362" mr 6,7\n" // syscall arg4: child_tid
363" mr 7,9\n" // syscall arg5: tls_ptr
364
365" sc\n" // clone()
366
367" mfcr 4\n" // return CR in r4 (low word of ULong)
368" cmpwi 3,0\n" // child if retval == 0
369" bne 1f\n" // jump if !child
370
371 /* CHILD - call thread function */
372 /* Note: 2.4 kernel doesn't set the child stack pointer,
373 so we do it here.
374 That does leave a small window for a signal to be delivered
375 on the wrong stack, unfortunately. */
376" mr 1,29\n"
377" mtctr 30\n" // ctr reg = fn
378" mr 3,31\n" // r3 = arg
379" bctrl\n" // call fn()
380
381 // exit with result
382" li 0,"__NR_EXIT"\n"
383" sc\n"
384
385 // Exit returned?!
386" .long 0\n"
387
388 // PARENT or ERROR - return
389"1: lwz 29,20(1)\n"
390" lwz 30,24(1)\n"
391" lwz 31,28(1)\n"
392" addi 1,1,32\n"
393" blr\n"
394);
395
396#undef __NR_CLONE
397#undef __NR_EXIT
398#undef STRINGIFY
399#undef STRINGIFZ
400
401// forward declarations
sewardje23772f2005-07-02 11:27:02 +0000402static void setup_child ( ThreadArchState*, ThreadArchState* );
cerion85665ca2005-06-20 15:51:07 +0000403
404/*
405 When a client clones, we need to keep track of the new thread. This means:
406 1. allocate a ThreadId+ThreadState+stack for the the thread
407
408 2. initialize the thread's new VCPU state
409
410 3. create the thread using the same args as the client requested,
411 but using the scheduler entrypoint for IP, and a separate stack
412 for SP.
413 */
sewardje23772f2005-07-02 11:27:02 +0000414static SysRes do_clone ( ThreadId ptid,
415 UInt flags, Addr sp,
416 Int *parent_tidptr,
417 Int *child_tidptr,
418 vki_modify_ldt_t *tlsinfo)
419{
420 static const Bool debug = False;
421
422 ThreadId ctid = VG_(alloc_ThreadState)();
423 ThreadState* ptst = VG_(get_ThreadState)(ptid);
424 ThreadState* ctst = VG_(get_ThreadState)(ctid);
425 ULong word64;
426 UWord* stack;
427 Segment* seg;
428 SysRes res;
429 vki_sigset_t blockall, savedmask;
430
431 VG_(sigfillset)(&blockall);
432
433 vg_assert(VG_(is_running_thread)(ptid));
434 vg_assert(VG_(is_valid_tid)(ctid));
435
436 stack = allocstack(ctid);
cerion85665ca2005-06-20 15:51:07 +0000437
438//? /* make a stack frame */
439//? stack -= 16;
440//? *(UWord *)stack = 0;
441
sewardje23772f2005-07-02 11:27:02 +0000442
443 /* Copy register state
444
445 Both parent and child return to the same place, and the code
446 following the clone syscall works out which is which, so we
447 don't need to worry about it.
448
449 The parent gets the child's new tid returned from clone, but the
450 child gets 0.
451
452 If the clone call specifies a NULL SP for the new thread, then
453 it actually gets a copy of the parent's SP.
454 */
455 setup_child( &ctst->arch, &ptst->arch );
456
457 /* Make sys_clone appear to have returned Success(0) in the
458 child. */
459 ctst->arch.vex.guest_GPR3 = 0;
460#warning "fixme: need to clear simulated CR0.SO"
461
462 if (sp != 0)
463 ctst->arch.vex.guest_GPR1 = sp;
464
465 ctst->os_state.parent = ptid;
466
467 /* inherit signal mask */
468 ctst->sig_mask = ptst->sig_mask;
469 ctst->tmp_sig_mask = ptst->sig_mask;
470
471 /* We don't really know where the client stack is, because its
472 allocated by the client. The best we can do is look at the
473 memory mappings and try to derive some useful information. We
474 assume that esp starts near its highest possible value, and can
475 only go down to the start of the mmaped segment. */
476 seg = VG_(find_segment)(sp);
477 if (seg) {
478 ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
479 ctst->client_stack_szB = ctst->client_stack_highest_word - seg->addr;
480
481 if (debug)
482 VG_(printf)("tid %d: guessed client stack range %p-%p\n",
483 ctid, seg->addr, VG_PGROUNDUP(sp));
484 } else {
485 VG_(message)(Vg_UserMsg, "!? New thread %d starts with R1(%p) unmapped\n",
486 ctid, sp);
487 ctst->client_stack_szB = 0;
488 }
489
490 if (flags & VKI_CLONE_SETTLS) {
491 if (debug)
492 VG_(printf)("clone child has SETTLS: tls at %p\n", tlsinfo);
493 vg_assert(0);
494 // ret = VG_(sys_set_thread_area)(ctid, tlsinfo);
495 // if (ret != 0)
496 // goto out;
497 }
498
499 flags &= ~VKI_CLONE_SETTLS;
500
501 /* start the thread with everything blocked */
502 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
503
504 /* Create the new thread */
505 word64 = do_syscall_clone_ppc32_linux(
506 start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
507 child_tidptr, parent_tidptr, NULL
508 );
509 res = VG_(mk_SysRes_ppc32_linux)( (UInt)(word64 >> 32), (UInt)word64 );
510
511 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
512
513 if (res.isError) {
514 /* clone failed */
515 VG_(cleanup_thread)(&ctst->arch);
516 ctst->status = VgTs_Empty;
517 }
518
519 return res;
520}
cerion85665ca2005-06-20 15:51:07 +0000521
522
523/* Do a clone which is really a fork() */
sewardje23772f2005-07-02 11:27:02 +0000524static SysRes do_fork_clone( ThreadId tid,
525 UInt flags, Addr sp,
526 Int* parent_tidptr,
527 Int* child_tidptr )
528{
529 vki_sigset_t fork_saved_mask;
530 vki_sigset_t mask;
531 SysRes res;
cerion85665ca2005-06-20 15:51:07 +0000532
sewardje23772f2005-07-02 11:27:02 +0000533 if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
534 | VKI_CLONE_FILES | VKI_CLONE_VFORK))
535 return VG_(mk_SysRes_Error)( VKI_EINVAL );
cerion85665ca2005-06-20 15:51:07 +0000536
sewardje23772f2005-07-02 11:27:02 +0000537 /* Block all signals during fork, so that we can fix things up in
538 the child without being interrupted. */
539 VG_(sigfillset)(&mask);
540 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
541
542 /* Since this is the fork() form of clone, we don't need all that
543 VG_(clone) stuff */
544 res = VG_(do_syscall5)( __NR_clone, flags,
545 (UWord)NULL, (UWord)parent_tidptr,
546 (UWord)NULL, (UWord)child_tidptr );
547
548 if (!res.isError && res.val == 0) {
549 /* child */
550 VG_(do_atfork_child)(tid);
551
552 /* restore signal mask */
553 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
554 } else
555 if (!res.isError && res.val > 0) {
556 /* parent */
557 if (VG_(clo_trace_syscalls))
558 VG_(printf)(" clone(fork): process %d created child %d\n",
559 VG_(getpid)(), res.val);
560
561 /* restore signal mask */
562 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
563 }
564
565 return res;
566}
cerion85665ca2005-06-20 15:51:07 +0000567
568
569/* ---------------------------------------------------------------------
570 LDT/GDT simulation
571 ------------------------------------------------------------------ */
sewardje23772f2005-07-02 11:27:02 +0000572#warning "Do we need all this LDT/GDT garbage on ppc32? Surely not."
cerion85665ca2005-06-20 15:51:07 +0000573
574/* Details of the LDT simulation
575 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
576
577 When a program runs natively, the linux kernel allows each *thread*
578 in it to have its own LDT. Almost all programs never do this --
579 it's wildly unportable, after all -- and so the kernel never
580 allocates the structure, which is just as well as an LDT occupies
581 64k of memory (8192 entries of size 8 bytes).
582
583 A thread may choose to modify its LDT entries, by doing the
584 __NR_modify_ldt syscall. In such a situation the kernel will then
585 allocate an LDT structure for it. Each LDT entry is basically a
586 (base, limit) pair. A virtual address in a specific segment is
587 translated to a linear address by adding the segment's base value.
588 In addition, the virtual address must not exceed the limit value.
589
590 To use an LDT entry, a thread loads one of the segment registers
591 (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
592 .. 8191) it wants to use. In fact, the required value is (index <<
593 3) + 7, but that's not important right now. Any normal instruction
594 which includes an addressing mode can then be made relative to that
595 LDT entry by prefixing the insn with a so-called segment-override
596 prefix, a byte which indicates which of the 6 segment registers
597 holds the LDT index.
598
599 Now, a key constraint is that valgrind's address checks operate in
600 terms of linear addresses. So we have to explicitly translate
601 virtual addrs into linear addrs, and that means doing a complete
602 LDT simulation.
603
604 Calls to modify_ldt are intercepted. For each thread, we maintain
605 an LDT (with the same normally-never-allocated optimisation that
606 the kernel does). This is updated as expected via calls to
607 modify_ldt.
608
609 When a thread does an amode calculation involving a segment
610 override prefix, the relevant LDT entry for the thread is
611 consulted. It all works.
612
613 There is a conceptual problem, which appears when switching back to
614 native execution, either temporarily to pass syscalls to the
615 kernel, or permanently, when debugging V. Problem at such points
616 is that it's pretty pointless to copy the simulated machine's
617 segment registers to the real machine, because we'd also need to
618 copy the simulated LDT into the real one, and that's prohibitively
619 expensive.
620
621 Fortunately it looks like no syscalls rely on the segment regs or
622 LDT being correct, so we can get away with it. Apart from that the
623 simulation is pretty straightforward. All 6 segment registers are
624 tracked, although only %ds, %es, %fs and %gs are allowed as
625 prefixes. Perhaps it could be restricted even more than that -- I
626 am not sure what is and isn't allowed in user-mode.
627*/
628
629//.. /* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
630//.. the Linux kernel's logic (cut-n-paste of code in
631//.. linux/kernel/ldt.c). */
632//..
633//.. static
634//.. void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
635//.. /* OUT */ VexGuestX86SegDescr* out,
636//.. Int oldmode )
637//.. {
638//.. UInt entry_1, entry_2;
639//.. vg_assert(8 == sizeof(VexGuestX86SegDescr));
640//..
641//.. if (0)
642//.. VG_(printf)("translate_to_hw_format: base %p, limit %d\n",
643//.. inn->base_addr, inn->limit );
644//..
645//.. /* Allow LDTs to be cleared by the user. */
646//.. if (inn->base_addr == 0 && inn->limit == 0) {
647//.. if (oldmode ||
648//.. (inn->contents == 0 &&
649//.. inn->read_exec_only == 1 &&
650//.. inn->seg_32bit == 0 &&
651//.. inn->limit_in_pages == 0 &&
652//.. inn->seg_not_present == 1 &&
653//.. inn->useable == 0 )) {
654//.. entry_1 = 0;
655//.. entry_2 = 0;
656//.. goto install;
657//.. }
658//.. }
659//..
660//.. entry_1 = ((inn->base_addr & 0x0000ffff) << 16) |
661//.. (inn->limit & 0x0ffff);
662//.. entry_2 = (inn->base_addr & 0xff000000) |
663//.. ((inn->base_addr & 0x00ff0000) >> 16) |
664//.. (inn->limit & 0xf0000) |
665//.. ((inn->read_exec_only ^ 1) << 9) |
666//.. (inn->contents << 10) |
667//.. ((inn->seg_not_present ^ 1) << 15) |
668//.. (inn->seg_32bit << 22) |
669//.. (inn->limit_in_pages << 23) |
670//.. 0x7000;
671//.. if (!oldmode)
672//.. entry_2 |= (inn->useable << 20);
673//..
674//.. /* Install the new entry ... */
675//.. install:
676//.. out->LdtEnt.Words.word1 = entry_1;
677//.. out->LdtEnt.Words.word2 = entry_2;
678//.. }
679//..
680//..
681//.. /*
682//.. * linux/kernel/ldt.c
683//.. *
684//.. * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
685//.. * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
686//.. */
687//..
688//.. /*
689//.. * read_ldt() is not really atomic - this is not a problem since
690//.. * synchronization of reads and writes done to the LDT has to be
691//.. * assured by user-space anyway. Writes are atomic, to protect
692//.. * the security checks done on new descriptors.
693//.. */
694//.. static
695//.. Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
696//.. {
697//.. Int err;
698//.. UInt i, size;
699//.. UChar* ldt;
700//..
701//.. if (0)
702//.. VG_(printf)("read_ldt: tid = %d, ptr = %p, bytecount = %d\n",
703//.. tid, ptr, bytecount );
704//..
705//.. vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
706//.. vg_assert(8 == sizeof(VexGuestX86SegDescr));
707//..
708//.. ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
709//.. err = 0;
710//.. if (ldt == NULL)
711//.. /* LDT not allocated, meaning all entries are null */
712//.. goto out;
713//..
714//.. size = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
715//.. if (size > bytecount)
716//.. size = bytecount;
717//..
718//.. err = size;
719//.. for (i = 0; i < size; i++)
720//.. ptr[i] = ldt[i];
721//..
722//.. out:
723//.. return err;
724//.. }
725//..
726//..
727//.. static
728//.. Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
729//.. {
730//.. Int error;
731//.. VexGuestX86SegDescr* ldt;
732//.. vki_modify_ldt_t* ldt_info;
733//..
734//.. if (0)
735//.. VG_(printf)("write_ldt: tid = %d, ptr = %p, "
736//.. "bytecount = %d, oldmode = %d\n",
737//.. tid, ptr, bytecount, oldmode );
738//..
739//.. vg_assert(8 == sizeof(VexGuestX86SegDescr));
740//.. vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
741//..
742//.. ldt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT;
743//.. ldt_info = (vki_modify_ldt_t*)ptr;
744//..
745//.. error = -VKI_EINVAL;
746//.. if (bytecount != sizeof(vki_modify_ldt_t))
747//.. goto out;
748//..
749//.. error = -VKI_EINVAL;
750//.. if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT)
751//.. goto out;
752//.. if (ldt_info->contents == 3) {
753//.. if (oldmode)
754//.. goto out;
755//.. if (ldt_info->seg_not_present == 0)
756//.. goto out;
757//.. }
758//..
759//.. /* If this thread doesn't have an LDT, we'd better allocate it
760//.. now. */
761//.. if (ldt == (HWord)NULL) {
762//.. ldt = VG_(alloc_zeroed_x86_LDT)();
763//.. VG_(threads)[tid].arch.vex.guest_LDT = (HWord)ldt;
764//.. }
765//..
766//.. /* Install the new entry ... */
767//.. translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode );
768//.. error = 0;
769//..
770//.. out:
771//.. return error;
772//.. }
773//..
774//..
775//.. Int VG_(sys_modify_ldt) ( ThreadId tid,
776//.. Int func, void* ptr, UInt bytecount )
777//.. {
778//.. Int ret = -VKI_ENOSYS;
779//..
780//.. switch (func) {
781//.. case 0:
782//.. ret = read_ldt(tid, ptr, bytecount);
783//.. break;
784//.. case 1:
785//.. ret = write_ldt(tid, ptr, bytecount, 1);
786//.. break;
787//.. case 2:
788//.. VG_(unimplemented)("sys_modify_ldt: func == 2");
789//.. /* god knows what this is about */
790//.. /* ret = read_default_ldt(ptr, bytecount); */
791//.. /*UNREACHED*/
792//.. break;
793//.. case 0x11:
794//.. ret = write_ldt(tid, ptr, bytecount, 0);
795//.. break;
796//.. }
797//.. return ret;
798//.. }
799//..
800//..
801//.. Int VG_(sys_set_thread_area) ( ThreadId tid,
802//.. vki_modify_ldt_t* info )
803//.. {
804//.. Int idx;
805//.. VexGuestX86SegDescr* gdt;
806//..
807//.. vg_assert(8 == sizeof(VexGuestX86SegDescr));
808//.. vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
809//..
810//.. if (info == NULL)
811//.. return -VKI_EFAULT;
812//..
813//.. gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
814//..
815//.. /* If the thread doesn't have a GDT, allocate it now. */
816//.. if (!gdt) {
817//.. gdt = VG_(alloc_zeroed_x86_GDT)();
818//.. VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
819//.. }
820//..
821//.. idx = info->entry_number;
822//..
823//.. if (idx == -1) {
824//.. /* Find and use the first free entry. */
825//.. for (idx = 0; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
826//.. if (gdt[idx].LdtEnt.Words.word1 == 0
827//.. && gdt[idx].LdtEnt.Words.word2 == 0)
828//.. break;
829//.. }
830//..
831//.. if (idx == VEX_GUEST_X86_GDT_NENT)
832//.. return -VKI_ESRCH;
833//.. } else if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
834//.. return -VKI_EINVAL;
835//.. }
836//..
837//.. translate_to_hw_format(info, &gdt[idx], 0);
838//..
839//.. VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
840//.. "set_thread_area(info->entry)",
841//.. (Addr) & info->entry_number, sizeof(unsigned int) );
842//.. info->entry_number = idx;
843//.. VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
844//.. (Addr) & info->entry_number, sizeof(unsigned int) );
845//..
846//.. return 0;
847//.. }
848//..
849//..
850//.. Int VG_(sys_get_thread_area) ( ThreadId tid,
851//.. vki_modify_ldt_t* info )
852//.. {
853//.. Int idx;
854//.. VexGuestX86SegDescr* gdt;
855//..
856//.. vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
857//.. vg_assert(8 == sizeof(VexGuestX86SegDescr));
858//..
859//.. if (info == NULL)
860//.. return -VKI_EFAULT;
861//..
862//.. idx = info->entry_number;
863//..
864//.. if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT)
865//.. return -VKI_EINVAL;
866//..
867//.. gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
868//..
869//.. /* If the thread doesn't have a GDT, allocate it now. */
870//.. if (!gdt) {
871//.. gdt = VG_(alloc_zeroed_x86_GDT)();
872//.. VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
873//.. }
874//..
875//.. info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
876//.. ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
877//.. gdt[idx].LdtEnt.Bits.BaseLow;
878//.. info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
879//.. gdt[idx].LdtEnt.Bits.LimitLow;
880//.. info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big;
881//.. info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
882//.. info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
883//.. info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity;
884//.. info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
885//.. info->useable = gdt[idx].LdtEnt.Bits.Sys;
886//.. info->reserved = 0;
887//..
888//.. return 0;
889//.. }
890
891
892
893/* ---------------------------------------------------------------------
894 More thread stuff
895 ------------------------------------------------------------------ */
896
njnaf839f52005-06-23 03:27:57 +0000897void VG_(cleanup_thread) ( ThreadArchState* arch )
cerion85665ca2005-06-20 15:51:07 +0000898{
cerion85665ca2005-06-20 15:51:07 +0000899}
900
sewardje23772f2005-07-02 11:27:02 +0000901void setup_child ( /*OUT*/ ThreadArchState *child,
902 /*IN*/ ThreadArchState *parent )
903{
904 /* We inherit our parent's guest state. */
905 child->vex = parent->vex;
906 child->vex_shadow = parent->vex_shadow;
907}
cerion85665ca2005-06-20 15:51:07 +0000908
909
910/* ---------------------------------------------------------------------
911 PRE/POST wrappers for ppc32/Linux-specific syscalls
912 ------------------------------------------------------------------ */
913
914#define PRE(name) DEFN_PRE_TEMPLATE(ppc32_linux, name)
915#define POST(name) DEFN_POST_TEMPLATE(ppc32_linux, name)
916
917/* Add prototypes for the wrappers declared here, so that gcc doesn't
918 harass us for not having prototypes. Really this is a kludge --
919 the right thing to do is to make these wrappers 'static' since they
920 aren't visible outside this file, but that requires even more macro
921 magic. */
922
cerion508aef52005-06-24 15:26:49 +0000923DECL_TEMPLATE(ppc32_linux, sys_socketcall);
cerion85665ca2005-06-20 15:51:07 +0000924DECL_TEMPLATE(ppc32_linux, sys_stat64);
cerion508aef52005-06-24 15:26:49 +0000925DECL_TEMPLATE(ppc32_linux, sys_lstat64);
cerion85665ca2005-06-20 15:51:07 +0000926DECL_TEMPLATE(ppc32_linux, sys_fstat64);
cerion508aef52005-06-24 15:26:49 +0000927DECL_TEMPLATE(ppc32_linux, sys_ipc);
sewardje23772f2005-07-02 11:27:02 +0000928DECL_TEMPLATE(ppc32_linux, sys_clone);
sewardjb865b162005-07-08 18:26:37 +0000929DECL_TEMPLATE(ppc32_linux, sys_sigreturn);
cerion508aef52005-06-24 15:26:49 +0000930
931PRE(sys_socketcall)
932{
933# define ARG2_0 (((UWord*)ARG2)[0])
934# define ARG2_1 (((UWord*)ARG2)[1])
935# define ARG2_2 (((UWord*)ARG2)[2])
936# define ARG2_3 (((UWord*)ARG2)[3])
937# define ARG2_4 (((UWord*)ARG2)[4])
938# define ARG2_5 (((UWord*)ARG2)[5])
939
940 *flags |= SfMayBlock;
941 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
942 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
943
944 switch (ARG1 /* request */) {
945
946 case VKI_SYS_SOCKETPAIR:
947 /* int socketpair(int d, int type, int protocol, int sv[2]); */
948 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
949 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
950 break;
951
952 case VKI_SYS_SOCKET:
953 /* int socket(int domain, int type, int protocol); */
954 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
955 break;
956
957 case VKI_SYS_BIND:
958 /* int bind(int sockfd, struct sockaddr *my_addr,
959 int addrlen); */
960 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
961 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
962 break;
963
964 case VKI_SYS_LISTEN:
965 /* int listen(int s, int backlog); */
966 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
967 break;
968
969 case VKI_SYS_ACCEPT: {
970 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
971 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
972 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
973 break;
974 }
975
976 case VKI_SYS_SENDTO:
977 /* int sendto(int s, const void *msg, int len,
978 unsigned int flags,
979 const struct sockaddr *to, int tolen); */
980 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
981 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
982 ARG2_3, ARG2_4, ARG2_5 );
983 break;
984
985 case VKI_SYS_SEND:
986 /* int send(int s, const void *msg, size_t len, int flags); */
987 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
988 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
989 break;
990
991 case VKI_SYS_RECVFROM:
992 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
993 struct sockaddr *from, int *fromlen); */
994 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
995 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
996 ARG2_3, ARG2_4, ARG2_5 );
997 break;
998
999 case VKI_SYS_RECV:
1000 /* int recv(int s, void *buf, int len, unsigned int flags); */
1001 /* man 2 recv says:
1002 The recv call is normally used only on a connected socket
1003 (see connect(2)) and is identical to recvfrom with a NULL
1004 from parameter.
1005 */
1006 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
1007 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
1008 break;
1009
1010 case VKI_SYS_CONNECT:
1011 /* int connect(int sockfd,
1012 struct sockaddr *serv_addr, int addrlen ); */
1013 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
1014 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
1015 break;
1016
1017 case VKI_SYS_SETSOCKOPT:
1018 /* int setsockopt(int s, int level, int optname,
1019 const void *optval, int optlen); */
1020 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
1021 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
1022 ARG2_3, ARG2_4 );
1023 break;
1024
1025 case VKI_SYS_GETSOCKOPT:
1026 /* int getsockopt(int s, int level, int optname,
1027 void *optval, socklen_t *optlen); */
1028 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
1029 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
1030 ARG2_3, ARG2_4 );
1031 break;
1032
1033 case VKI_SYS_GETSOCKNAME:
1034 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1035 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
1036 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
1037 break;
1038
1039 case VKI_SYS_GETPEERNAME:
1040 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1041 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
1042 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
1043 break;
1044
1045 case VKI_SYS_SHUTDOWN:
1046 /* int shutdown(int s, int how); */
1047 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1048 break;
1049
1050 case VKI_SYS_SENDMSG: {
1051 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1052
1053 /* this causes warnings, and I don't get why. glibc bug?
1054 * (after all it's glibc providing the arguments array)
1055 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1056 */
1057 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
1058 break;
1059 }
1060
1061 case VKI_SYS_RECVMSG: {
1062 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1063
1064 /* this causes warnings, and I don't get why. glibc bug?
1065 * (after all it's glibc providing the arguments array)
1066 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1067 */
1068 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
1069 break;
1070 }
1071
1072 default:
1073 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1074 SET_STATUS_Failure( VKI_EINVAL );
1075 break;
1076 }
1077# undef ARG2_0
1078# undef ARG2_1
1079# undef ARG2_2
1080# undef ARG2_3
1081# undef ARG2_4
1082# undef ARG2_5
1083}
1084
1085POST(sys_socketcall)
1086{
1087# define ARG2_0 (((UWord*)ARG2)[0])
1088# define ARG2_1 (((UWord*)ARG2)[1])
1089# define ARG2_2 (((UWord*)ARG2)[2])
1090# define ARG2_3 (((UWord*)ARG2)[3])
1091# define ARG2_4 (((UWord*)ARG2)[4])
1092# define ARG2_5 (((UWord*)ARG2)[5])
1093
1094 SysRes r;
1095 vg_assert(SUCCESS);
1096 switch (ARG1 /* request */) {
1097
1098 case VKI_SYS_SOCKETPAIR:
1099 r = ML_(generic_POST_sys_socketpair)(
1100 tid, VG_(mk_SysRes_Success)(RES),
1101 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1102 );
1103 SET_STATUS_from_SysRes(r);
1104 break;
1105
1106 case VKI_SYS_SOCKET:
1107 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
1108 SET_STATUS_from_SysRes(r);
1109 break;
1110
1111 case VKI_SYS_BIND:
1112 /* int bind(int sockfd, struct sockaddr *my_addr,
1113 int addrlen); */
1114 break;
1115
1116 case VKI_SYS_LISTEN:
1117 /* int listen(int s, int backlog); */
1118 break;
1119
1120 case VKI_SYS_ACCEPT:
1121 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1122 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
1123 ARG2_0, ARG2_1, ARG2_2 );
1124 SET_STATUS_from_SysRes(r);
1125 break;
1126
1127 case VKI_SYS_SENDTO:
1128 break;
1129
1130 case VKI_SYS_SEND:
1131 break;
1132
1133 case VKI_SYS_RECVFROM:
1134 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
1135 ARG2_0, ARG2_1, ARG2_2,
1136 ARG2_3, ARG2_4, ARG2_5 );
1137 break;
1138
1139 case VKI_SYS_RECV:
1140 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
1141 break;
1142
1143 case VKI_SYS_CONNECT:
1144 break;
1145
1146 case VKI_SYS_SETSOCKOPT:
1147 break;
1148
1149 case VKI_SYS_GETSOCKOPT:
1150 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
1151 ARG2_0, ARG2_1,
1152 ARG2_2, ARG2_3, ARG2_4 );
1153 break;
1154
1155 case VKI_SYS_GETSOCKNAME:
1156 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
1157 ARG2_0, ARG2_1, ARG2_2 );
1158 break;
1159
1160 case VKI_SYS_GETPEERNAME:
1161 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
1162 ARG2_0, ARG2_1, ARG2_2 );
1163 break;
1164
1165 case VKI_SYS_SHUTDOWN:
1166 break;
1167
1168 case VKI_SYS_SENDMSG:
1169 break;
1170
1171 case VKI_SYS_RECVMSG:
1172 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
1173 break;
1174
1175 default:
1176 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1177 VG_(core_panic)("... bye!\n");
1178 break; /*NOTREACHED*/
1179 }
1180# undef ARG2_0
1181# undef ARG2_1
1182# undef ARG2_2
1183# undef ARG2_3
1184# undef ARG2_4
1185# undef ARG2_5
1186}
cerion85665ca2005-06-20 15:51:07 +00001187
1188// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1189// applicable to every architecture -- I think only to 32-bit archs.
1190// We're going to need something like linux/core_os32.h for such
1191// things, eventually, I think. --njn
1192PRE(sys_stat64)
1193{
1194 PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
1195 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1196 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1197 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
1198}
1199
1200POST(sys_stat64)
1201{
1202 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1203}
1204
cerion508aef52005-06-24 15:26:49 +00001205PRE(sys_lstat64)
1206{
1207 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1208 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1209 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1210 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1211}
1212
1213POST(sys_lstat64)
1214{
1215 vg_assert(SUCCESS);
1216 if (RES == 0) {
1217 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1218 }
1219}
1220
cerion85665ca2005-06-20 15:51:07 +00001221PRE(sys_fstat64)
1222{
1223 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1224 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1225 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1226}
cerion508aef52005-06-24 15:26:49 +00001227
cerion85665ca2005-06-20 15:51:07 +00001228POST(sys_fstat64)
1229{
1230 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1231}
1232
cerion508aef52005-06-24 15:26:49 +00001233static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1234{
1235 Addr* a_p = (Addr*)a;
1236 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1237 return *a_p;
1238}
1239
cerion508aef52005-06-24 15:26:49 +00001240PRE(sys_ipc)
1241{
1242 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1243 // XXX: this is simplistic -- some args are not used in all circumstances.
1244 PRE_REG_READ6(int, "ipc",
1245 vki_uint, call, int, first, int, second, int, third,
1246 void *, ptr, long, fifth)
1247
1248 switch (ARG1 /* call */) {
1249 case VKI_SEMOP:
1250 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
1251 *flags |= SfMayBlock;
1252 break;
1253 case VKI_SEMGET:
1254 break;
1255 case VKI_SEMCTL:
1256 {
1257 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
1258 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
1259 break;
1260 }
1261 case VKI_SEMTIMEDOP:
1262 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
1263 *flags |= SfMayBlock;
1264 break;
1265 case VKI_MSGSND:
1266 ML_(generic_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
1267 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1268 *flags |= SfMayBlock;
1269 break;
1270 case VKI_MSGRCV:
1271 {
1272 Addr msgp;
1273 Word msgtyp;
1274
1275 msgp = deref_Addr( tid,
1276 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1277 "msgrcv(msgp)" );
1278 msgtyp = deref_Addr( tid,
1279 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1280 "msgrcv(msgp)" );
1281
1282 ML_(generic_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
1283
1284 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1285 *flags |= SfMayBlock;
1286 break;
1287 }
1288 case VKI_MSGGET:
1289 break;
1290 case VKI_MSGCTL:
1291 ML_(generic_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
1292 break;
1293 case VKI_SHMAT:
1294 {
1295 UWord w;
1296 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
1297 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
1298 if (w == 0)
1299 SET_STATUS_Failure( VKI_EINVAL );
1300 else
1301 ARG5 = w;
1302 break;
1303 }
1304 case VKI_SHMDT:
1305 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
1306 SET_STATUS_Failure( VKI_EINVAL );
1307 break;
1308 case VKI_SHMGET:
1309 break;
1310 case VKI_SHMCTL: /* IPCOP_shmctl */
1311 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
1312 break;
1313 default:
1314 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1315 VG_(core_panic)("... bye!\n");
1316 break; /*NOTREACHED*/
1317 }
1318}
1319
1320POST(sys_ipc)
1321{
1322 vg_assert(SUCCESS);
1323 switch (ARG1 /* call */) {
1324 case VKI_SEMOP:
1325 case VKI_SEMGET:
1326 break;
1327 case VKI_SEMCTL:
1328 {
1329 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
1330 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
1331 break;
1332 }
1333 case VKI_SEMTIMEDOP:
1334 case VKI_MSGSND:
1335 break;
1336 case VKI_MSGRCV:
1337 {
1338 Addr msgp;
1339 Word msgtyp;
1340
1341 msgp = deref_Addr( tid,
1342 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1343 "msgrcv(msgp)" );
1344 msgtyp = deref_Addr( tid,
1345 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1346 "msgrcv(msgp)" );
1347
1348 ML_(generic_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
1349 break;
1350 }
1351 case VKI_MSGGET:
1352 break;
1353 case VKI_MSGCTL:
1354 ML_(generic_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
1355 break;
1356 case VKI_SHMAT:
1357 {
1358 Addr addr;
1359
1360 /* force readability. before the syscall it is
1361 * indeed uninitialized, as can be seen in
1362 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1363 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
1364
1365 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1366 if ( addr > 0 ) {
1367 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
1368 }
1369 break;
1370 }
1371 case VKI_SHMDT:
1372 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
1373 break;
1374 case VKI_SHMGET:
1375 break;
1376 case VKI_SHMCTL:
1377 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
1378 break;
1379 default:
1380 VG_(message)(Vg_DebugMsg,
1381 "FATAL: unhandled syscall(ipc) %d",
1382 ARG1 );
1383 VG_(core_panic)("... bye!\n");
1384 break; /*NOTREACHED*/
1385 }
1386}
1387
1388
cerion85665ca2005-06-20 15:51:07 +00001389
1390
1391//.. PRE(old_select, MayBlock)
1392//.. {
1393//.. /* struct sel_arg_struct {
1394//.. unsigned long n;
1395//.. fd_set *inp, *outp, *exp;
1396//.. struct timeval *tvp;
1397//.. };
1398//.. */
1399//.. PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
1400//.. PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
1401//..
1402//.. {
1403//.. UInt* arg_struct = (UInt*)ARG1;
1404//.. UInt a1, a2, a3, a4, a5;
1405//..
1406//.. a1 = arg_struct[0];
1407//.. a2 = arg_struct[1];
1408//.. a3 = arg_struct[2];
1409//.. a4 = arg_struct[3];
1410//.. a5 = arg_struct[4];
1411//..
1412//.. PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
1413//.. if (a2 != (Addr)NULL)
1414//.. PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
1415//.. if (a3 != (Addr)NULL)
1416//.. PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
1417//.. if (a4 != (Addr)NULL)
1418//.. PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
1419//.. if (a5 != (Addr)NULL)
1420//.. PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
1421//.. }
1422//.. }
1423
sewardje23772f2005-07-02 11:27:02 +00001424PRE(sys_clone)
1425{
1426 UInt cloneflags;
1427
1428 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
1429 PRE_REG_READ5(int, "clone",
1430 unsigned long, flags,
1431 void *, child_stack,
1432 int *, parent_tidptr,
1433 vki_modify_ldt_t *, tlsinfo,
1434 int *, child_tidptr);
1435
1436 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
1437 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
1438 if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
1439 SET_STATUS_Failure( VKI_EFAULT );
1440 return;
1441 }
1442 }
1443 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
1444 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
1445 if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) {
1446 SET_STATUS_Failure( VKI_EFAULT );
1447 return;
1448 }
1449 }
1450
1451#warning "Is this next check relevant/needed?"
1452 if (ARG1 & VKI_CLONE_SETTLS) {
1453 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
1454 if (!VG_(is_addressable)(ARG4, sizeof(vki_modify_ldt_t), VKI_PROT_READ)) {
1455 SET_STATUS_Failure( VKI_EFAULT );
1456 return;
1457 }
1458 }
1459
1460 cloneflags = ARG1;
1461
1462 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
1463 SET_STATUS_Failure( VKI_EINVAL );
1464 return;
1465 }
1466
1467 /* Only look at the flags we really care about */
1468 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
1469 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
1470 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
1471 /* thread creation */
1472 SET_STATUS_from_SysRes(
1473 do_clone(tid,
1474 ARG1, /* flags */
1475 (Addr)ARG2, /* child SP */
1476 (Int *)ARG3, /* parent_tidptr */
1477 (Int *)ARG5, /* child_tidptr */
1478 (vki_modify_ldt_t *)ARG4)); /* set_tls */
1479 break;
1480
1481 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
1482 /* FALLTHROUGH - assume vfork == fork */
1483 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
1484
1485 case 0: /* plain fork */
1486 SET_STATUS_from_SysRes(
1487 do_fork_clone(tid,
1488 cloneflags, /* flags */
1489 (Addr)ARG2, /* child SP */
1490 (Int *)ARG3, /* parent_tidptr */
1491 (Int *)ARG5)); /* child_tidptr */
1492 break;
1493
1494 default:
1495 /* should we just ENOSYS? */
1496 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
1497 VG_(message)(Vg_UserMsg, "");
1498 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
1499 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
1500 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
1501 VG_(unimplemented)
1502 ("Valgrind does not support general clone().");
1503 }
1504
1505 if (SUCCESS) {
1506 if (ARG1 & VKI_CLONE_PARENT_SETTID)
1507 POST_MEM_WRITE(ARG3, sizeof(Int));
1508 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
1509 POST_MEM_WRITE(ARG5, sizeof(Int));
1510
1511 /* Thread creation was successful; let the child have the chance
1512 to run */
1513 *flags |= SfYieldAfter;
1514 }
1515}
cerion85665ca2005-06-20 15:51:07 +00001516
sewardjb865b162005-07-08 18:26:37 +00001517PRE(sys_sigreturn)
1518{
1519 ThreadState* tst;
1520 PRINT("sigreturn ( )");
1521
1522 vg_assert(VG_(is_valid_tid)(tid));
1523 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1524 vg_assert(VG_(is_running_thread)(tid));
1525
1526 ///* Adjust esp to point to start of frame; skip back up over
1527 // sigreturn sequence's "popl %eax" and handler ret addr */
1528 tst = VG_(get_ThreadState)(tid);
1529 //tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
1530
1531 ///* This is only so that the EIP is (might be) useful to report if
1532 // something goes wrong in the sigreturn */
1533 //ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
1534
1535 VG_(sigframe_destroy)(tid, False);
1536
1537 /* For unclear reasons, it appears we need the syscall to return
1538 without changing %EAX. Since %EAX is the return value, and can
1539 denote either success or failure, we must set up so that the
1540 driver logic copies it back unchanged. Also, note %EAX is of
1541 the guest registers written by VG_(sigframe_destroy). */
1542 //SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
1543 SET_STATUS_from_SysRes(
1544 VG_(mk_SysRes_ppc32_linux)(
1545 tst->arch.vex.guest_GPR3,
sewardj463b3d92005-07-18 11:41:15 +00001546 /* get CR0.SO */
1547 (LibVEX_GuestPPC32_get_CR( &tst->arch.vex ) >> 28) & 1
sewardjb865b162005-07-08 18:26:37 +00001548 )
1549 );
1550
1551 /* Check to see if some any signals arose as a result of this. */
1552 *flags |= SfPollAfter;
1553}
1554
cerion85665ca2005-06-20 15:51:07 +00001555//.. PRE(sys_sigreturn, Special)
1556//.. {
1557//.. PRINT("sigreturn ( )");
1558//..
1559//.. /* Adjust esp to point to start of frame; skip back up over
1560//.. sigreturn sequence's "popl %eax" and handler ret addr */
1561//.. tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
1562//..
1563//.. /* This is only so that the EIP is (might be) useful to report if
1564//.. something goes wrong in the sigreturn */
njnaf839f52005-06-23 03:27:57 +00001565//.. VG_(restart_syscall)(&tst->arch);
cerion85665ca2005-06-20 15:51:07 +00001566//..
1567//.. VG_(sigframe_destroy)(tid, False);
1568//..
1569//.. /* Keep looking for signals until there are none */
1570//.. VG_(poll_signals)(tid);
1571//..
1572//.. /* placate return-must-be-set assertion */
1573//.. SET_RESULT(RES);
1574//.. }
1575
1576//.. PRE(sys_rt_sigreturn, Special)
1577//.. {
1578//.. PRINT("rt_sigreturn ( )");
1579//..
1580//.. /* Adjust esp to point to start of frame; skip back up over handler
1581//.. ret addr */
1582//.. tst->arch.vex.guest_ESP -= sizeof(Addr);
1583//..
1584//.. /* This is only so that the EIP is (might be) useful to report if
1585//.. something goes wrong in the sigreturn */
njnaf839f52005-06-23 03:27:57 +00001586//.. VG_(restart_syscall)(&tst->arch);
cerion85665ca2005-06-20 15:51:07 +00001587//..
1588//.. VG_(sigframe_destroy)(tid, False);
1589//..
1590//.. /* Keep looking for signals until there are none */
1591//.. VG_(poll_signals)(tid);
1592//..
1593//.. /* placate return-must-be-set assertion */
1594//.. SET_RESULT(RES);
1595//.. }
1596
1597//.. PRE(sys_modify_ldt, Special)
1598//.. {
1599//.. PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
1600//.. PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1601//.. unsigned long, bytecount);
1602//..
1603//.. if (ARG1 == 0) {
1604//.. /* read the LDT into ptr */
1605//.. PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
1606//.. }
1607//.. if (ARG1 == 1 || ARG1 == 0x11) {
1608//.. /* write the LDT with the entry pointed at by ptr */
1609//.. PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
1610//.. }
1611//.. /* "do" the syscall ourselves; the kernel never sees it */
1612//.. SET_RESULT( VG_(sys_modify_ldt)( tid, ARG1, (void*)ARG2, ARG3 ) );
1613//..
1614//.. if (ARG1 == 0 && !VG_(is_kerror)(RES) && RES > 0) {
1615//.. POST_MEM_WRITE( ARG2, RES );
1616//.. }
1617//.. }
1618
1619//.. PRE(sys_set_thread_area, Special)
1620//.. {
1621//.. PRINT("sys_set_thread_area ( %p )", ARG1);
1622//.. PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1623//.. PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1624//..
1625//.. /* "do" the syscall ourselves; the kernel never sees it */
1626//.. SET_RESULT( VG_(sys_set_thread_area)( tid, (void *)ARG1 ) );
1627//.. }
1628
1629//.. PRE(sys_get_thread_area, Special)
1630//.. {
1631//.. PRINT("sys_get_thread_area ( %p )", ARG1);
1632//.. PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1633//.. PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1634//..
1635//.. /* "do" the syscall ourselves; the kernel never sees it */
1636//.. SET_RESULT( VG_(sys_get_thread_area)( tid, (void *)ARG1 ) );
1637//..
1638//.. if (!VG_(is_kerror)(RES)) {
1639//.. POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1640//.. }
1641//.. }
1642
1643//.. // Parts of this are ppc32-specific, but the *PEEK* cases are generic.
1644//.. // XXX: Why is the memory pointed to by ARG3 never checked?
1645//.. PRE(sys_ptrace, 0)
1646//.. {
1647//.. PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1648//.. PRE_REG_READ4(int, "ptrace",
1649//.. long, request, long, pid, long, addr, long, data);
1650//.. switch (ARG1) {
1651//.. case VKI_PTRACE_PEEKTEXT:
1652//.. case VKI_PTRACE_PEEKDATA:
1653//.. case VKI_PTRACE_PEEKUSR:
1654//.. PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1655//.. sizeof (long));
1656//.. break;
1657//.. case VKI_PTRACE_GETREGS:
1658//.. PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1659//.. sizeof (struct vki_user_regs_struct));
1660//.. break;
1661//.. case VKI_PTRACE_GETFPREGS:
1662//.. PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1663//.. sizeof (struct vki_user_i387_struct));
1664//.. break;
1665//.. case VKI_PTRACE_GETFPXREGS:
1666//.. PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1667//.. sizeof(struct vki_user_fxsr_struct) );
1668//.. break;
1669//.. case VKI_PTRACE_SETREGS:
1670//.. PRE_MEM_READ( "ptrace(setregs)", ARG4,
1671//.. sizeof (struct vki_user_regs_struct));
1672//.. break;
1673//.. case VKI_PTRACE_SETFPREGS:
1674//.. PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1675//.. sizeof (struct vki_user_i387_struct));
1676//.. break;
1677//.. case VKI_PTRACE_SETFPXREGS:
1678//.. PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1679//.. sizeof(struct vki_user_fxsr_struct) );
1680//.. break;
1681//.. default:
1682//.. break;
1683//.. }
1684//.. }
1685
1686//.. POST(sys_ptrace)
1687//.. {
1688//.. switch (ARG1) {
1689//.. case VKI_PTRACE_PEEKTEXT:
1690//.. case VKI_PTRACE_PEEKDATA:
1691//.. case VKI_PTRACE_PEEKUSR:
1692//.. POST_MEM_WRITE( ARG4, sizeof (long));
1693//.. break;
1694//.. case VKI_PTRACE_GETREGS:
1695//.. POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1696//.. break;
1697//.. case VKI_PTRACE_GETFPREGS:
1698//.. POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1699//.. break;
1700//.. case VKI_PTRACE_GETFPXREGS:
1701//.. POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1702//.. break;
1703//.. default:
1704//.. break;
1705//.. }
1706//.. }
1707
1708//.. // XXX: this duplicates a function in coregrind/vg_syscalls.c, yuk
1709//.. static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1710//.. {
1711//.. Addr* a_p = (Addr*)a;
1712//.. PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1713//.. return *a_p;
1714//.. }
1715
1716//.. // XXX: should use the constants here (eg. SHMAT), not the numbers directly!
1717//.. PRE(sys_ipc, 0)
1718//.. {
1719//.. PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1720//.. // XXX: this is simplistic -- some args are not used in all circumstances.
1721//.. PRE_REG_READ6(int, "ipc",
1722//.. vki_uint, call, int, first, int, second, int, third,
1723//.. void *, ptr, long, fifth)
1724//..
1725//.. switch (ARG1 /* call */) {
1726//.. case VKI_SEMOP:
cerion7b2c38c2005-06-23 07:52:54 +00001727//.. ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001728//.. /* tst->sys_flags |= MayBlock; */
1729//.. break;
1730//.. case VKI_SEMGET:
1731//.. break;
1732//.. case VKI_SEMCTL:
1733//.. {
1734//.. UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
cerion7b2c38c2005-06-23 07:52:54 +00001735//.. ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
cerion85665ca2005-06-20 15:51:07 +00001736//.. break;
1737//.. }
1738//.. case VKI_SEMTIMEDOP:
cerion7b2c38c2005-06-23 07:52:54 +00001739//.. ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
cerion85665ca2005-06-20 15:51:07 +00001740//.. /* tst->sys_flags |= MayBlock; */
1741//.. break;
1742//.. case VKI_MSGSND:
cerion7b2c38c2005-06-23 07:52:54 +00001743//.. ML_(generic_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001744//.. /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1745//.. tst->sys_flags |= MayBlock;
1746//.. */
1747//.. break;
1748//.. case VKI_MSGRCV:
1749//.. {
1750//.. Addr msgp;
1751//.. Word msgtyp;
1752//..
1753//.. msgp = deref_Addr( tid,
1754//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1755//.. "msgrcv(msgp)" );
1756//.. msgtyp = deref_Addr( tid,
1757//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1758//.. "msgrcv(msgp)" );
1759//..
cerion7b2c38c2005-06-23 07:52:54 +00001760//.. ML_(generic_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001761//..
1762//.. /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1763//.. tst->sys_flags |= MayBlock;
1764//.. */
1765//.. break;
1766//.. }
1767//.. case VKI_MSGGET:
1768//.. break;
1769//.. case VKI_MSGCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001770//.. ML_(generic_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001771//.. break;
1772//.. case VKI_SHMAT:
1773//.. PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
cerion7b2c38c2005-06-23 07:52:54 +00001774//.. ARG5 = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001775//.. if (ARG5 == 0)
1776//.. SET_RESULT( -VKI_EINVAL );
1777//.. break;
1778//.. case VKI_SHMDT:
cerion7b2c38c2005-06-23 07:52:54 +00001779//.. if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
cerion85665ca2005-06-20 15:51:07 +00001780//.. SET_RESULT( -VKI_EINVAL );
1781//.. break;
1782//.. case VKI_SHMGET:
1783//.. break;
1784//.. case VKI_SHMCTL: /* IPCOP_shmctl */
cerion7b2c38c2005-06-23 07:52:54 +00001785//.. ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001786//.. break;
1787//.. default:
1788//.. VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1789//.. VG_(core_panic)("... bye!\n");
1790//.. break; /*NOTREACHED*/
1791//.. }
1792//.. }
1793
1794//.. POST(sys_ipc)
1795//.. {
1796//.. switch (ARG1 /* call */) {
1797//.. case VKI_SEMOP:
1798//.. case VKI_SEMGET:
1799//.. break;
1800//.. case VKI_SEMCTL:
1801//.. {
1802//.. UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
cerion7b2c38c2005-06-23 07:52:54 +00001803//.. ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
cerion85665ca2005-06-20 15:51:07 +00001804//.. break;
1805//.. }
1806//.. case VKI_SEMTIMEDOP:
1807//.. case VKI_MSGSND:
1808//.. break;
1809//.. case VKI_MSGRCV:
1810//.. {
1811//.. Addr msgp;
1812//.. Word msgtyp;
1813//..
1814//.. msgp = deref_Addr( tid,
1815//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1816//.. "msgrcv(msgp)" );
1817//.. msgtyp = deref_Addr( tid,
1818//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1819//.. "msgrcv(msgp)" );
1820//..
cerion7b2c38c2005-06-23 07:52:54 +00001821//.. ML_(generic_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001822//.. break;
1823//.. }
1824//.. case VKI_MSGGET:
1825//.. break;
1826//.. case VKI_MSGCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001827//.. ML_(generic_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001828//.. break;
1829//.. case VKI_SHMAT:
1830//.. {
1831//.. Addr addr;
1832//..
1833//.. /* force readability. before the syscall it is
1834//.. * indeed uninitialized, as can be seen in
1835//.. * glibc/sysdeps/unix/sysv/linux/shmat.c */
1836//.. POST_MEM_WRITE( ARG4, sizeof( Addr ) );
1837//..
1838//.. addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1839//.. if ( addr > 0 ) {
cerion7b2c38c2005-06-23 07:52:54 +00001840//.. ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001841//.. }
1842//.. break;
1843//.. }
1844//.. case VKI_SHMDT:
cerion7b2c38c2005-06-23 07:52:54 +00001845//.. ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001846//.. break;
1847//.. case VKI_SHMGET:
1848//.. break;
1849//.. case VKI_SHMCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001850//.. ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001851//.. break;
1852//.. default:
1853//.. VG_(message)(Vg_DebugMsg,
1854//.. "FATAL: unhandled syscall(ipc) %d",
1855//.. ARG1 );
1856//.. VG_(core_panic)("... bye!\n");
1857//.. break; /*NOTREACHED*/
1858//.. }
1859//.. }
1860
1861
1862//.. // jrs 20050207: this is from the svn branch
1863//.. //PRE(sys_sigaction, Special)
1864//.. //{
1865//.. // PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1866//.. // PRE_REG_READ3(int, "sigaction",
1867//.. // int, signum, const struct old_sigaction *, act,
1868//.. // struct old_sigaction *, oldact)
1869//.. // if (ARG2 != 0)
1870//.. // PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction));
1871//.. // if (ARG3 != 0)
1872//.. // PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1873//.. //
1874//.. // VG_(do_sys_sigaction)(tid);
1875//.. //}
1876
1877//.. /* Convert from non-RT to RT sigset_t's */
1878//.. static void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1879//.. {
1880//.. VG_(sigemptyset)(set);
1881//.. set->sig[0] = *oldset;
1882//.. }
1883//.. PRE(sys_sigaction, Special)
1884//.. {
1885//.. struct vki_sigaction new, old;
1886//.. struct vki_sigaction *newp, *oldp;
1887//..
1888//.. PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1889//.. PRE_REG_READ3(int, "sigaction",
1890//.. int, signum, const struct old_sigaction *, act,
1891//.. struct old_sigaction *, oldact);
1892//..
1893//.. newp = oldp = NULL;
1894//..
1895//.. if (ARG2 != 0)
1896//.. PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction));
1897//..
1898//.. if (ARG3 != 0) {
1899//.. PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1900//.. oldp = &old;
1901//.. }
1902//..
1903//.. //jrs 20050207: what?! how can this make any sense?
1904//.. //if (VG_(is_kerror)(SYSRES))
1905//.. // return;
1906//..
1907//.. if (ARG2 != 0) {
1908//.. struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1909//..
1910//.. new.ksa_handler = oldnew->ksa_handler;
1911//.. new.sa_flags = oldnew->sa_flags;
1912//.. new.sa_restorer = oldnew->sa_restorer;
1913//.. convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1914//.. newp = &new;
1915//.. }
1916//..
1917//.. SET_RESULT( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1918//..
1919//.. if (ARG3 != 0 && RES == 0) {
1920//.. struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1921//..
1922//.. oldold->ksa_handler = oldp->ksa_handler;
1923//.. oldold->sa_flags = oldp->sa_flags;
1924//.. oldold->sa_restorer = oldp->sa_restorer;
1925//.. oldold->sa_mask = oldp->sa_mask.sig[0];
1926//.. }
1927//.. }
1928
1929//.. POST(sys_sigaction)
1930//.. {
1931//.. if (RES == 0 && ARG3 != 0)
1932//.. POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1933//.. }
1934
1935#undef PRE
1936#undef POST
1937
1938
1939/* ---------------------------------------------------------------------
1940 The ppc32/Linux syscall table
1941 ------------------------------------------------------------------ */
1942
1943/* Add an ppc32-linux specific wrapper to a syscall table. */
1944#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(ppc32_linux, sysno, name)
1945#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(ppc32_linux, sysno, name)
1946
1947// This table maps from __NR_xxx syscall numbers (from
1948// linux/include/asm-ppc/unistd.h) to the appropriate PRE/POST sys_foo()
1949// wrappers on ppc32 (as per sys_call_table in linux/arch/ppc/kernel/entry.S).
1950//
1951// For those syscalls not handled by Valgrind, the annotation indicate its
1952// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1953// (unknown).
1954
njnaf839f52005-06-23 03:27:57 +00001955const SyscallTableEntry ML_(syscall_table)[] = {
cerion85665ca2005-06-20 15:51:07 +00001956//.. (restart_syscall) // 0
sewardja932d292005-07-08 00:18:25 +00001957 GENX_(__NR_exit, sys_exit), // 1
cerion85665ca2005-06-20 15:51:07 +00001958//.. GENX_(__NR_fork, sys_fork), // 2
sewardja932d292005-07-08 00:18:25 +00001959 GENXY(__NR_read, sys_read), // 3
1960 GENX_(__NR_write, sys_write), // 4
cerion85665ca2005-06-20 15:51:07 +00001961
sewardja932d292005-07-08 00:18:25 +00001962 GENXY(__NR_open, sys_open), // 5
1963 GENXY(__NR_close, sys_close), // 6
1964 GENXY(__NR_waitpid, sys_waitpid), // 7
1965 GENXY(__NR_creat, sys_creat), // 8
sewardjb865b162005-07-08 18:26:37 +00001966 GENX_(__NR_link, sys_link), // 9
1967
sewardja932d292005-07-08 00:18:25 +00001968 GENX_(__NR_unlink, sys_unlink), // 10
1969 GENX_(__NR_execve, sys_execve), // 11
sewardjb865b162005-07-08 18:26:37 +00001970 GENX_(__NR_chdir, sys_chdir), // 12
sewardja932d292005-07-08 00:18:25 +00001971 GENXY(__NR_time, sys_time), // 13
cerion85665ca2005-06-20 15:51:07 +00001972//.. GENX_(__NR_mknod, sys_mknod), // 14
1973//..
sewardja932d292005-07-08 00:18:25 +00001974 GENX_(__NR_chmod, sys_chmod), // 15
cerion85665ca2005-06-20 15:51:07 +00001975//.. // (__NR_lchown, sys_lchown16), // 16 ## P
1976//.. GENX_(__NR_break, sys_ni_syscall), // 17
1977//.. // (__NR_oldstat, sys_stat), // 18 (obsolete)
1978//.. GENX_(__NR_lseek, sys_lseek), // 19
1979//..
sewardja932d292005-07-08 00:18:25 +00001980 GENX_(__NR_getpid, sys_getpid), // 20
cerion85665ca2005-06-20 15:51:07 +00001981//.. LINX_(__NR_mount, sys_mount), // 21
1982//.. LINX_(__NR_umount, sys_oldumount), // 22
sewardja932d292005-07-08 00:18:25 +00001983 GENX_(__NR_setuid, sys_setuid16), // 23 ## P
1984 GENX_(__NR_getuid, sys_getuid16), // 24 ## P
cerion85665ca2005-06-20 15:51:07 +00001985//..
1986//.. // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
1987//.. PLAXY(__NR_ptrace, sys_ptrace), // 26
1988//.. GENX_(__NR_alarm, sys_alarm), // 27
1989//.. // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
sewardja932d292005-07-08 00:18:25 +00001990 GENX_(__NR_pause, sys_pause), // 29
cerion85665ca2005-06-20 15:51:07 +00001991//..
cerion508aef52005-06-24 15:26:49 +00001992 GENX_(__NR_utime, sys_utime), // 30
cerion85665ca2005-06-20 15:51:07 +00001993//.. GENX_(__NR_stty, sys_ni_syscall), // 31
1994//.. GENX_(__NR_gtty, sys_ni_syscall), // 32
sewardja932d292005-07-08 00:18:25 +00001995 GENX_(__NR_access, sys_access), // 33
cerion85665ca2005-06-20 15:51:07 +00001996//.. GENX_(__NR_nice, sys_nice), // 34
1997//..
1998//.. GENX_(__NR_ftime, sys_ni_syscall), // 35
1999//.. GENX_(__NR_sync, sys_sync), // 36
sewardjb865b162005-07-08 18:26:37 +00002000 GENX_(__NR_kill, sys_kill), // 37
2001 GENX_(__NR_rename, sys_rename), // 38
2002 GENX_(__NR_mkdir, sys_mkdir), // 39
2003
cerion85665ca2005-06-20 15:51:07 +00002004//.. GENX_(__NR_rmdir, sys_rmdir), // 40
sewardja932d292005-07-08 00:18:25 +00002005 GENXY(__NR_dup, sys_dup), // 41
2006 GENXY(__NR_pipe, sys_pipe), // 42
cerion85665ca2005-06-20 15:51:07 +00002007//.. GENXY(__NR_times, sys_times), // 43
2008//.. GENX_(__NR_prof, sys_ni_syscall), // 44
2009//..
sewardja932d292005-07-08 00:18:25 +00002010 GENX_(__NR_brk, sys_brk), // 45
2011 GENX_(__NR_setgid, sys_setgid16), // 46
2012 GENX_(__NR_getgid, sys_getgid16), // 47
cerion85665ca2005-06-20 15:51:07 +00002013//.. // (__NR_signal, sys_signal), // 48 */* (ANSI C)
sewardja932d292005-07-08 00:18:25 +00002014 GENX_(__NR_geteuid, sys_geteuid16), // 49
cerion508aef52005-06-24 15:26:49 +00002015
sewardja932d292005-07-08 00:18:25 +00002016 GENX_(__NR_getegid, sys_getegid16), // 50
cerion85665ca2005-06-20 15:51:07 +00002017//.. GENX_(__NR_acct, sys_acct), // 51
2018//.. LINX_(__NR_umount2, sys_umount), // 52
2019//.. GENX_(__NR_lock, sys_ni_syscall), // 53
sewardja932d292005-07-08 00:18:25 +00002020 GENXY(__NR_ioctl, sys_ioctl), // 54
cerion85665ca2005-06-20 15:51:07 +00002021//..
2022//.. GENXY(__NR_fcntl, sys_fcntl), // 55
2023//.. GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardja932d292005-07-08 00:18:25 +00002024 GENX_(__NR_setpgid, sys_setpgid), // 57
cerion85665ca2005-06-20 15:51:07 +00002025//.. GENX_(__NR_ulimit, sys_ni_syscall), // 58
2026//.. // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
sewardjb865b162005-07-08 18:26:37 +00002027
2028 GENX_(__NR_umask, sys_umask), // 60
cerion85665ca2005-06-20 15:51:07 +00002029//.. GENX_(__NR_chroot, sys_chroot), // 61
2030//.. // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
sewardja932d292005-07-08 00:18:25 +00002031 GENXY(__NR_dup2, sys_dup2), // 63
sewardjb865b162005-07-08 18:26:37 +00002032 GENX_(__NR_getppid, sys_getppid), // 64
2033
2034 GENX_(__NR_getpgrp, sys_getpgrp), // 65
2035 GENX_(__NR_setsid, sys_setsid), // 66
cerion85665ca2005-06-20 15:51:07 +00002036//.. PLAXY(__NR_sigaction, sys_sigaction), // 67
2037//.. // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
2038//.. // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
2039//..
2040//.. GENX_(__NR_setreuid, sys_setreuid16), // 70
2041//.. GENX_(__NR_setregid, sys_setregid16), // 71
2042//.. GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
2043//.. GENXY(__NR_sigpending, sys_sigpending), // 73
2044//.. // (__NR_sethostname, sys_sethostname), // 74 */*
2045//..
cerion508aef52005-06-24 15:26:49 +00002046 GENX_(__NR_setrlimit, sys_setrlimit), // 75
cerion85665ca2005-06-20 15:51:07 +00002047//.. GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
2048//.. GENXY(__NR_getrusage, sys_getrusage), // 77
cerion508aef52005-06-24 15:26:49 +00002049 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
cerion85665ca2005-06-20 15:51:07 +00002050//.. GENX_(__NR_settimeofday, sys_settimeofday), // 79
2051//..
sewardjb865b162005-07-08 18:26:37 +00002052 GENXY(__NR_getgroups, sys_getgroups16), // 80
cerion85665ca2005-06-20 15:51:07 +00002053//.. GENX_(__NR_setgroups, sys_setgroups16), // 81
2054//.. PLAX_(__NR_select, old_select), // 82
sewardjb865b162005-07-08 18:26:37 +00002055 GENX_(__NR_symlink, sys_symlink), // 83
cerion85665ca2005-06-20 15:51:07 +00002056//.. // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
2057//..
sewardja932d292005-07-08 00:18:25 +00002058 GENX_(__NR_readlink, sys_readlink), // 85
cerion85665ca2005-06-20 15:51:07 +00002059//.. // (__NR_uselib, sys_uselib), // 86 */Linux
2060//.. // (__NR_swapon, sys_swapon), // 87 */Linux
2061//.. // (__NR_reboot, sys_reboot), // 88 */Linux
2062//.. // (__NR_readdir, old_readdir), // 89 -- superseded
2063
2064 GENXY(__NR_mmap, sys_mmap2), // 90
cerion508aef52005-06-24 15:26:49 +00002065 GENXY(__NR_munmap, sys_munmap), // 91
cerion85665ca2005-06-20 15:51:07 +00002066//.. GENX_(__NR_truncate, sys_truncate), // 92
2067//.. GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj2d7c3962005-07-29 22:01:19 +00002068 GENX_(__NR_fchmod, sys_fchmod), // 94
2069
2070 GENX_(__NR_fchown, sys_fchown16), // 95
cerion85665ca2005-06-20 15:51:07 +00002071//.. GENX_(__NR_getpriority, sys_getpriority), // 96
2072//.. GENX_(__NR_setpriority, sys_setpriority), // 97
2073//.. GENX_(__NR_profil, sys_ni_syscall), // 98
2074//.. GENXY(__NR_statfs, sys_statfs), // 99
2075//..
2076//.. GENXY(__NR_fstatfs, sys_fstatfs), // 100
2077//.. LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja932d292005-07-08 00:18:25 +00002078 PLAXY(__NR_socketcall, sys_socketcall), // 102
cerion85665ca2005-06-20 15:51:07 +00002079//.. LINXY(__NR_syslog, sys_syslog), // 103
sewardja932d292005-07-08 00:18:25 +00002080 GENXY(__NR_setitimer, sys_setitimer), // 104
cerion85665ca2005-06-20 15:51:07 +00002081//..
2082//.. GENXY(__NR_getitimer, sys_getitimer), // 105
sewardja932d292005-07-08 00:18:25 +00002083 GENXY(__NR_stat, sys_newstat), // 106
cerion85665ca2005-06-20 15:51:07 +00002084//.. GENXY(__NR_lstat, sys_newlstat), // 107
2085//.. GENXY(__NR_fstat, sys_newfstat), // 108
2086//.. // (__NR_olduname, sys_uname), // 109 -- obsolete
2087//..
2088//.. GENX_(__NR_iopl, sys_iopl), // 110
2089//.. LINX_(__NR_vhangup, sys_vhangup), // 111
2090//.. GENX_(__NR_idle, sys_ni_syscall), // 112
2091//.. // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
2092//.. GENXY(__NR_wait4, sys_wait4), // 114
2093//..
2094//.. // (__NR_swapoff, sys_swapoff), // 115 */Linux
2095//.. LINXY(__NR_sysinfo, sys_sysinfo), // 116
sewardja932d292005-07-08 00:18:25 +00002096 PLAXY(__NR_ipc, sys_ipc), // 117
cerion85665ca2005-06-20 15:51:07 +00002097//.. GENX_(__NR_fsync, sys_fsync), // 118
sewardjb865b162005-07-08 18:26:37 +00002098 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
cerion85665ca2005-06-20 15:51:07 +00002099//..
sewardja932d292005-07-08 00:18:25 +00002100 PLAX_(__NR_clone, sys_clone), // 120
cerion85665ca2005-06-20 15:51:07 +00002101//.. // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
sewardja932d292005-07-08 00:18:25 +00002102 GENXY(__NR_uname, sys_newuname), // 122
cerion85665ca2005-06-20 15:51:07 +00002103//.. PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
2104//.. LINXY(__NR_adjtimex, sys_adjtimex), // 124
2105//..
sewardja932d292005-07-08 00:18:25 +00002106 GENXY(__NR_mprotect, sys_mprotect), // 125
cerion85665ca2005-06-20 15:51:07 +00002107//.. GENXY(__NR_sigprocmask, sys_sigprocmask), // 126
2108//.. // Nb: create_module() was removed 2.4-->2.6
2109//.. GENX_(__NR_create_module, sys_ni_syscall), // 127
2110//.. GENX_(__NR_init_module, sys_init_module), // 128
2111//.. // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
2112//..
2113//.. // Nb: get_kernel_syms() was removed 2.4-->2.6
2114//.. GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
2115//.. GENX_(__NR_quotactl, sys_quotactl), // 131
sewardja932d292005-07-08 00:18:25 +00002116 GENX_(__NR_getpgid, sys_getpgid), // 132
cerion85665ca2005-06-20 15:51:07 +00002117//.. GENX_(__NR_fchdir, sys_fchdir), // 133
2118//.. // (__NR_bdflush, sys_bdflush), // 134 */Linux
2119//..
2120//.. // (__NR_sysfs, sys_sysfs), // 135 SVr4
2121//.. LINX_(__NR_personality, sys_personality), // 136
2122//.. GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
2123//.. LINX_(__NR_setfsuid, sys_setfsuid16), // 138
2124//.. LINX_(__NR_setfsgid, sys_setfsgid16), // 139
2125//..
sewardja932d292005-07-08 00:18:25 +00002126 LINXY(__NR__llseek, sys_llseek), // 140
cerion85665ca2005-06-20 15:51:07 +00002127//.. GENXY(__NR_getdents, sys_getdents), // 141
sewardja932d292005-07-08 00:18:25 +00002128 GENX_(__NR__newselect, sys_select), // 142
cerion85665ca2005-06-20 15:51:07 +00002129//.. GENX_(__NR_flock, sys_flock), // 143
2130//.. GENX_(__NR_msync, sys_msync), // 144
2131//..
sewardja932d292005-07-08 00:18:25 +00002132 GENXY(__NR_readv, sys_readv), // 145
2133 GENX_(__NR_writev, sys_writev), // 146
cerion85665ca2005-06-20 15:51:07 +00002134//.. GENX_(__NR_getsid, sys_getsid), // 147
2135//.. GENX_(__NR_fdatasync, sys_fdatasync), // 148
sewardja932d292005-07-08 00:18:25 +00002136 LINXY(__NR__sysctl, sys_sysctl), // 149
cerion85665ca2005-06-20 15:51:07 +00002137//..
2138//.. GENX_(__NR_mlock, sys_mlock), // 150
2139//.. GENX_(__NR_munlock, sys_munlock), // 151
2140//.. GENX_(__NR_mlockall, sys_mlockall), // 152
2141//.. GENX_(__NR_munlockall, sys_munlockall), // 153
2142//.. GENXY(__NR_sched_setparam, sys_sched_setparam), // 154
2143//..
2144//.. GENXY(__NR_sched_getparam, sys_sched_getparam), // 155
2145//.. GENX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
2146//.. GENX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
2147//.. GENX_(__NR_sched_yield, sys_sched_yield), // 158
2148//.. GENX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
2149//..
2150//.. GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
2151//.. // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
sewardja932d292005-07-08 00:18:25 +00002152 GENXY(__NR_nanosleep, sys_nanosleep), // 162
2153 GENX_(__NR_mremap, sys_mremap), // 163
cerion85665ca2005-06-20 15:51:07 +00002154//.. LINX_(__NR_setresuid, sys_setresuid16), // 164
2155//..
2156//.. LINXY(__NR_getresuid, sys_getresuid16), // 165
2157
2158//.. GENX_(__NR_query_module, sys_ni_syscall), // 166
sewardjca334052005-07-24 06:30:37 +00002159 GENXY(__NR_poll, sys_poll), // 167
cerion85665ca2005-06-20 15:51:07 +00002160//.. // (__NR_nfsservctl, sys_nfsservctl), // 168 */Linux
2161//..
2162//.. LINX_(__NR_setresgid, sys_setresgid16), // 169
2163//.. LINXY(__NR_getresgid, sys_getresgid16), // 170
sewardjb865b162005-07-08 18:26:37 +00002164 LINX_(__NR_prctl, sys_prctl), // 171
cerion85665ca2005-06-20 15:51:07 +00002165//.. PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 172
sewardja932d292005-07-08 00:18:25 +00002166 GENXY(__NR_rt_sigaction, sys_rt_sigaction), // 173
cerion85665ca2005-06-20 15:51:07 +00002167
sewardja932d292005-07-08 00:18:25 +00002168 GENXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 174
cerion85665ca2005-06-20 15:51:07 +00002169//.. GENXY(__NR_rt_sigpending, sys_rt_sigpending), // 175
2170//.. GENXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait), // 176
2171//.. GENXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), // 177
2172//.. GENX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 178
2173//..
sewardja932d292005-07-08 00:18:25 +00002174 GENXY(__NR_pread64, sys_pread64), // 179
2175 GENX_(__NR_pwrite64, sys_pwrite64), // 180
2176 GENX_(__NR_chown, sys_chown16), // 181
sewardjb865b162005-07-08 18:26:37 +00002177 GENXY(__NR_getcwd, sys_getcwd), // 182
cerion85665ca2005-06-20 15:51:07 +00002178//.. GENXY(__NR_capget, sys_capget), // 183
2179//..
2180//.. GENX_(__NR_capset, sys_capset), // 184
2181//.. GENXY(__NR_sigaltstack, sys_sigaltstack), // 185
2182//.. LINXY(__NR_sendfile, sys_sendfile), // 186
2183//.. GENXY(__NR_getpmsg, sys_getpmsg), // 187
2184//.. GENX_(__NR_putpmsg, sys_putpmsg), // 188
sewardja932d292005-07-08 00:18:25 +00002185
2186 // Nb: we treat vfork as fork
2187 GENX_(__NR_vfork, sys_fork), // 189
2188 GENXY(__NR_ugetrlimit, sys_getrlimit), // 190
cerion85665ca2005-06-20 15:51:07 +00002189//__NR_readahead // 191 ppc/Linux only?
sewardja932d292005-07-08 00:18:25 +00002190 GENXY(__NR_mmap2, sys_mmap2), // 192
cerion85665ca2005-06-20 15:51:07 +00002191//.. GENX_(__NR_truncate64, sys_truncate64), // 193
2192//.. GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2193//..
2194
sewardja932d292005-07-08 00:18:25 +00002195 PLAXY(__NR_stat64, sys_stat64), // 195
2196 PLAXY(__NR_lstat64, sys_lstat64), // 196
2197 PLAXY(__NR_fstat64, sys_fstat64), // 197
cerion85665ca2005-06-20 15:51:07 +00002198
2199// __NR_pciconfig_read // 198
2200// __NR_pciconfig_write // 199
2201// __NR_pciconfig_iobase // 200
2202// __NR_multiplexer // 201
2203
sewardja932d292005-07-08 00:18:25 +00002204 GENXY(__NR_getdents64, sys_getdents64), // 202
cerion85665ca2005-06-20 15:51:07 +00002205//.. // (__NR_pivot_root, sys_pivot_root), // 203 */Linux
sewardja932d292005-07-08 00:18:25 +00002206 GENXY(__NR_fcntl64, sys_fcntl64), // 204
cerion85665ca2005-06-20 15:51:07 +00002207//.. GENX_(__NR_madvise, sys_madvise), // 205
2208//.. GENXY(__NR_mincore, sys_mincore), // 206
2209//.. LINX_(__NR_gettid, sys_gettid), // 207
2210//.. LINX_(__NR_tkill, sys_tkill), // 208 */Linux
2211//.. GENX_(__NR_setxattr, sys_setxattr), // 209
2212//.. GENX_(__NR_lsetxattr, sys_lsetxattr), // 210
2213//.. GENX_(__NR_fsetxattr, sys_fsetxattr), // 211
sewardj1798ecd2005-07-02 10:13:34 +00002214 GENXY(__NR_getxattr, sys_getxattr), // 212
cerion85665ca2005-06-20 15:51:07 +00002215//.. GENXY(__NR_lgetxattr, sys_lgetxattr), // 213
2216//.. GENXY(__NR_fgetxattr, sys_fgetxattr), // 214
2217//.. GENXY(__NR_listxattr, sys_listxattr), // 215
2218//.. GENXY(__NR_llistxattr, sys_llistxattr), // 216
2219//.. GENXY(__NR_flistxattr, sys_flistxattr), // 217
2220//.. GENX_(__NR_removexattr, sys_removexattr), // 218
2221//.. GENX_(__NR_lremovexattr, sys_lremovexattr), // 219
2222//.. GENX_(__NR_fremovexattr, sys_fremovexattr), // 220
2223
cerion508aef52005-06-24 15:26:49 +00002224 LINXY(__NR_futex, sys_futex), // 221
cerion85665ca2005-06-20 15:51:07 +00002225//.. GENX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 222
2226//.. GENXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 223
2227/* 224 currently unused */
2228
2229// __NR_tuxcall // 225
2230
2231//.. LINXY(__NR_sendfile64, sys_sendfile64), // 226
2232//..
2233//.. LINX_(__NR_io_setup, sys_io_setup), // 227
2234//.. LINX_(__NR_io_destroy, sys_io_destroy), // 228
2235//.. LINXY(__NR_io_getevents, sys_io_getevents), // 229
2236//.. LINX_(__NR_io_submit, sys_io_submit), // 230
2237//.. LINXY(__NR_io_cancel, sys_io_cancel), // 231
2238//..
sewardja932d292005-07-08 00:18:25 +00002239 LINX_(__NR_set_tid_address, sys_set_tid_address), // 232
cerion85665ca2005-06-20 15:51:07 +00002240
2241//.. LINX_(__NR_fadvise64, sys_fadvise64), // 233 */(Linux?)
sewardja932d292005-07-08 00:18:25 +00002242 LINX_(__NR_exit_group, sys_exit_group), // 234
cerion85665ca2005-06-20 15:51:07 +00002243//.. GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 235
2244//.. LINXY(__NR_epoll_create, sys_epoll_create), // 236
2245//.. LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 237
2246//.. LINXY(__NR_epoll_wait, sys_epoll_wait), // 238
2247
2248//.. // (__NR_remap_file_pages, sys_remap_file_pages), // 239 */Linux
2249//.. GENXY(__NR_timer_create, sys_timer_create), // 240
2250//.. GENXY(__NR_timer_settime, sys_timer_settime), // 241
2251//.. GENXY(__NR_timer_gettime, sys_timer_gettime), // 242
2252//.. GENX_(__NR_timer_getoverrun, sys_timer_getoverrun), // 243
2253//.. GENX_(__NR_timer_delete, sys_timer_delete), // 244
2254//.. GENX_(__NR_clock_settime, sys_clock_settime), // 245
sewardja932d292005-07-08 00:18:25 +00002255 GENXY(__NR_clock_gettime, sys_clock_gettime), // 246
cerion85665ca2005-06-20 15:51:07 +00002256//.. GENXY(__NR_clock_getres, sys_clock_getres), // 247
2257//.. // (__NR_clock_nanosleep, sys_clock_nanosleep), // 248
2258
2259// __NR_swapcontext // 249
2260
2261//.. LINX_(__NR_tgkill, sys_tgkill), // 250 */Linux
2262//.. GENX_(__NR_utimes, sys_utimes), // 251
2263//.. GENXY(__NR_statfs64, sys_statfs64), // 252
2264//.. GENXY(__NR_fstatfs64, sys_fstatfs64), // 253
2265//.. LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 254 */(Linux?)
2266
2267// __NR_rtas // 255
2268
2269/* Number 256 is reserved for sys_debug_setcontext */
2270/* Number 257 is reserved for vserver */
2271/* Number 258 is reserved for new sys_remap_file_pages */
2272/* Number 259 is reserved for new sys_mbind */
2273/* Number 260 is reserved for new sys_get_mempolicy */
2274/* Number 261 is reserved for new sys_set_mempolicy */
2275
2276//.. GENXY(__NR_mq_open, sys_mq_open), // 262
2277//.. GENX_(__NR_mq_unlink, sys_mq_unlink), // 263
2278//.. GENX_(__NR_mq_timedsend, sys_mq_timedsend), // 264
2279//.. GENXY(__NR_mq_timedreceive, sys_mq_timedreceive), // 265
2280//.. GENX_(__NR_mq_notify, sys_mq_notify), // 266
2281//.. GENXY(__NR_mq_getsetattr, sys_mq_getsetattr), // 267
2282
2283// __NR_kexec_load // 268
2284};
2285
njnaf839f52005-06-23 03:27:57 +00002286const UInt ML_(syscall_table_size) =
2287 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
cerion85665ca2005-06-20 15:51:07 +00002288
2289/*--------------------------------------------------------------------*/
2290/*--- end ---*/
2291/*--------------------------------------------------------------------*/