blob: ffe6d16eff4c9e0f1542e878a70af18cb22c8c1b [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
10 Copyright (C) 2005 Nicholas Nethercote <njn25@cam.ac.uk>
11 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,
1546 (LibVEX_GuestPPC32_get_cr7( &tst->arch.vex ) >> 28) & 1
1547 )
1548 );
1549
1550 /* Check to see if some any signals arose as a result of this. */
1551 *flags |= SfPollAfter;
1552}
1553
cerion85665ca2005-06-20 15:51:07 +00001554//.. PRE(sys_sigreturn, Special)
1555//.. {
1556//.. PRINT("sigreturn ( )");
1557//..
1558//.. /* Adjust esp to point to start of frame; skip back up over
1559//.. sigreturn sequence's "popl %eax" and handler ret addr */
1560//.. tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
1561//..
1562//.. /* This is only so that the EIP is (might be) useful to report if
1563//.. something goes wrong in the sigreturn */
njnaf839f52005-06-23 03:27:57 +00001564//.. VG_(restart_syscall)(&tst->arch);
cerion85665ca2005-06-20 15:51:07 +00001565//..
1566//.. VG_(sigframe_destroy)(tid, False);
1567//..
1568//.. /* Keep looking for signals until there are none */
1569//.. VG_(poll_signals)(tid);
1570//..
1571//.. /* placate return-must-be-set assertion */
1572//.. SET_RESULT(RES);
1573//.. }
1574
1575//.. PRE(sys_rt_sigreturn, Special)
1576//.. {
1577//.. PRINT("rt_sigreturn ( )");
1578//..
1579//.. /* Adjust esp to point to start of frame; skip back up over handler
1580//.. ret addr */
1581//.. tst->arch.vex.guest_ESP -= sizeof(Addr);
1582//..
1583//.. /* This is only so that the EIP is (might be) useful to report if
1584//.. something goes wrong in the sigreturn */
njnaf839f52005-06-23 03:27:57 +00001585//.. VG_(restart_syscall)(&tst->arch);
cerion85665ca2005-06-20 15:51:07 +00001586//..
1587//.. VG_(sigframe_destroy)(tid, False);
1588//..
1589//.. /* Keep looking for signals until there are none */
1590//.. VG_(poll_signals)(tid);
1591//..
1592//.. /* placate return-must-be-set assertion */
1593//.. SET_RESULT(RES);
1594//.. }
1595
1596//.. PRE(sys_modify_ldt, Special)
1597//.. {
1598//.. PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
1599//.. PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1600//.. unsigned long, bytecount);
1601//..
1602//.. if (ARG1 == 0) {
1603//.. /* read the LDT into ptr */
1604//.. PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
1605//.. }
1606//.. if (ARG1 == 1 || ARG1 == 0x11) {
1607//.. /* write the LDT with the entry pointed at by ptr */
1608//.. PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
1609//.. }
1610//.. /* "do" the syscall ourselves; the kernel never sees it */
1611//.. SET_RESULT( VG_(sys_modify_ldt)( tid, ARG1, (void*)ARG2, ARG3 ) );
1612//..
1613//.. if (ARG1 == 0 && !VG_(is_kerror)(RES) && RES > 0) {
1614//.. POST_MEM_WRITE( ARG2, RES );
1615//.. }
1616//.. }
1617
1618//.. PRE(sys_set_thread_area, Special)
1619//.. {
1620//.. PRINT("sys_set_thread_area ( %p )", ARG1);
1621//.. PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1622//.. PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1623//..
1624//.. /* "do" the syscall ourselves; the kernel never sees it */
1625//.. SET_RESULT( VG_(sys_set_thread_area)( tid, (void *)ARG1 ) );
1626//.. }
1627
1628//.. PRE(sys_get_thread_area, Special)
1629//.. {
1630//.. PRINT("sys_get_thread_area ( %p )", ARG1);
1631//.. PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1632//.. PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1633//..
1634//.. /* "do" the syscall ourselves; the kernel never sees it */
1635//.. SET_RESULT( VG_(sys_get_thread_area)( tid, (void *)ARG1 ) );
1636//..
1637//.. if (!VG_(is_kerror)(RES)) {
1638//.. POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1639//.. }
1640//.. }
1641
1642//.. // Parts of this are ppc32-specific, but the *PEEK* cases are generic.
1643//.. // XXX: Why is the memory pointed to by ARG3 never checked?
1644//.. PRE(sys_ptrace, 0)
1645//.. {
1646//.. PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1647//.. PRE_REG_READ4(int, "ptrace",
1648//.. long, request, long, pid, long, addr, long, data);
1649//.. switch (ARG1) {
1650//.. case VKI_PTRACE_PEEKTEXT:
1651//.. case VKI_PTRACE_PEEKDATA:
1652//.. case VKI_PTRACE_PEEKUSR:
1653//.. PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1654//.. sizeof (long));
1655//.. break;
1656//.. case VKI_PTRACE_GETREGS:
1657//.. PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1658//.. sizeof (struct vki_user_regs_struct));
1659//.. break;
1660//.. case VKI_PTRACE_GETFPREGS:
1661//.. PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1662//.. sizeof (struct vki_user_i387_struct));
1663//.. break;
1664//.. case VKI_PTRACE_GETFPXREGS:
1665//.. PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1666//.. sizeof(struct vki_user_fxsr_struct) );
1667//.. break;
1668//.. case VKI_PTRACE_SETREGS:
1669//.. PRE_MEM_READ( "ptrace(setregs)", ARG4,
1670//.. sizeof (struct vki_user_regs_struct));
1671//.. break;
1672//.. case VKI_PTRACE_SETFPREGS:
1673//.. PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1674//.. sizeof (struct vki_user_i387_struct));
1675//.. break;
1676//.. case VKI_PTRACE_SETFPXREGS:
1677//.. PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1678//.. sizeof(struct vki_user_fxsr_struct) );
1679//.. break;
1680//.. default:
1681//.. break;
1682//.. }
1683//.. }
1684
1685//.. POST(sys_ptrace)
1686//.. {
1687//.. switch (ARG1) {
1688//.. case VKI_PTRACE_PEEKTEXT:
1689//.. case VKI_PTRACE_PEEKDATA:
1690//.. case VKI_PTRACE_PEEKUSR:
1691//.. POST_MEM_WRITE( ARG4, sizeof (long));
1692//.. break;
1693//.. case VKI_PTRACE_GETREGS:
1694//.. POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1695//.. break;
1696//.. case VKI_PTRACE_GETFPREGS:
1697//.. POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1698//.. break;
1699//.. case VKI_PTRACE_GETFPXREGS:
1700//.. POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1701//.. break;
1702//.. default:
1703//.. break;
1704//.. }
1705//.. }
1706
1707//.. // XXX: this duplicates a function in coregrind/vg_syscalls.c, yuk
1708//.. static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1709//.. {
1710//.. Addr* a_p = (Addr*)a;
1711//.. PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1712//.. return *a_p;
1713//.. }
1714
1715//.. // XXX: should use the constants here (eg. SHMAT), not the numbers directly!
1716//.. PRE(sys_ipc, 0)
1717//.. {
1718//.. PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1719//.. // XXX: this is simplistic -- some args are not used in all circumstances.
1720//.. PRE_REG_READ6(int, "ipc",
1721//.. vki_uint, call, int, first, int, second, int, third,
1722//.. void *, ptr, long, fifth)
1723//..
1724//.. switch (ARG1 /* call */) {
1725//.. case VKI_SEMOP:
cerion7b2c38c2005-06-23 07:52:54 +00001726//.. ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001727//.. /* tst->sys_flags |= MayBlock; */
1728//.. break;
1729//.. case VKI_SEMGET:
1730//.. break;
1731//.. case VKI_SEMCTL:
1732//.. {
1733//.. UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
cerion7b2c38c2005-06-23 07:52:54 +00001734//.. ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
cerion85665ca2005-06-20 15:51:07 +00001735//.. break;
1736//.. }
1737//.. case VKI_SEMTIMEDOP:
cerion7b2c38c2005-06-23 07:52:54 +00001738//.. ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
cerion85665ca2005-06-20 15:51:07 +00001739//.. /* tst->sys_flags |= MayBlock; */
1740//.. break;
1741//.. case VKI_MSGSND:
cerion7b2c38c2005-06-23 07:52:54 +00001742//.. ML_(generic_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001743//.. /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1744//.. tst->sys_flags |= MayBlock;
1745//.. */
1746//.. break;
1747//.. case VKI_MSGRCV:
1748//.. {
1749//.. Addr msgp;
1750//.. Word msgtyp;
1751//..
1752//.. msgp = deref_Addr( tid,
1753//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1754//.. "msgrcv(msgp)" );
1755//.. msgtyp = deref_Addr( tid,
1756//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1757//.. "msgrcv(msgp)" );
1758//..
cerion7b2c38c2005-06-23 07:52:54 +00001759//.. ML_(generic_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001760//..
1761//.. /* if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1762//.. tst->sys_flags |= MayBlock;
1763//.. */
1764//.. break;
1765//.. }
1766//.. case VKI_MSGGET:
1767//.. break;
1768//.. case VKI_MSGCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001769//.. ML_(generic_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001770//.. break;
1771//.. case VKI_SHMAT:
1772//.. PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
cerion7b2c38c2005-06-23 07:52:54 +00001773//.. ARG5 = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001774//.. if (ARG5 == 0)
1775//.. SET_RESULT( -VKI_EINVAL );
1776//.. break;
1777//.. case VKI_SHMDT:
cerion7b2c38c2005-06-23 07:52:54 +00001778//.. if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
cerion85665ca2005-06-20 15:51:07 +00001779//.. SET_RESULT( -VKI_EINVAL );
1780//.. break;
1781//.. case VKI_SHMGET:
1782//.. break;
1783//.. case VKI_SHMCTL: /* IPCOP_shmctl */
cerion7b2c38c2005-06-23 07:52:54 +00001784//.. ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001785//.. break;
1786//.. default:
1787//.. VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1788//.. VG_(core_panic)("... bye!\n");
1789//.. break; /*NOTREACHED*/
1790//.. }
1791//.. }
1792
1793//.. POST(sys_ipc)
1794//.. {
1795//.. switch (ARG1 /* call */) {
1796//.. case VKI_SEMOP:
1797//.. case VKI_SEMGET:
1798//.. break;
1799//.. case VKI_SEMCTL:
1800//.. {
1801//.. UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
cerion7b2c38c2005-06-23 07:52:54 +00001802//.. ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
cerion85665ca2005-06-20 15:51:07 +00001803//.. break;
1804//.. }
1805//.. case VKI_SEMTIMEDOP:
1806//.. case VKI_MSGSND:
1807//.. break;
1808//.. case VKI_MSGRCV:
1809//.. {
1810//.. Addr msgp;
1811//.. Word msgtyp;
1812//..
1813//.. msgp = deref_Addr( tid,
1814//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1815//.. "msgrcv(msgp)" );
1816//.. msgtyp = deref_Addr( tid,
1817//.. (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1818//.. "msgrcv(msgp)" );
1819//..
cerion7b2c38c2005-06-23 07:52:54 +00001820//.. ML_(generic_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
cerion85665ca2005-06-20 15:51:07 +00001821//.. break;
1822//.. }
1823//.. case VKI_MSGGET:
1824//.. break;
1825//.. case VKI_MSGCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001826//.. ML_(generic_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001827//.. break;
1828//.. case VKI_SHMAT:
1829//.. {
1830//.. Addr addr;
1831//..
1832//.. /* force readability. before the syscall it is
1833//.. * indeed uninitialized, as can be seen in
1834//.. * glibc/sysdeps/unix/sysv/linux/shmat.c */
1835//.. POST_MEM_WRITE( ARG4, sizeof( Addr ) );
1836//..
1837//.. addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1838//.. if ( addr > 0 ) {
cerion7b2c38c2005-06-23 07:52:54 +00001839//.. ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
cerion85665ca2005-06-20 15:51:07 +00001840//.. }
1841//.. break;
1842//.. }
1843//.. case VKI_SHMDT:
cerion7b2c38c2005-06-23 07:52:54 +00001844//.. ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001845//.. break;
1846//.. case VKI_SHMGET:
1847//.. break;
1848//.. case VKI_SHMCTL:
cerion7b2c38c2005-06-23 07:52:54 +00001849//.. ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
cerion85665ca2005-06-20 15:51:07 +00001850//.. break;
1851//.. default:
1852//.. VG_(message)(Vg_DebugMsg,
1853//.. "FATAL: unhandled syscall(ipc) %d",
1854//.. ARG1 );
1855//.. VG_(core_panic)("... bye!\n");
1856//.. break; /*NOTREACHED*/
1857//.. }
1858//.. }
1859
1860
1861//.. // jrs 20050207: this is from the svn branch
1862//.. //PRE(sys_sigaction, Special)
1863//.. //{
1864//.. // PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1865//.. // PRE_REG_READ3(int, "sigaction",
1866//.. // int, signum, const struct old_sigaction *, act,
1867//.. // struct old_sigaction *, oldact)
1868//.. // if (ARG2 != 0)
1869//.. // PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction));
1870//.. // if (ARG3 != 0)
1871//.. // PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1872//.. //
1873//.. // VG_(do_sys_sigaction)(tid);
1874//.. //}
1875
1876//.. /* Convert from non-RT to RT sigset_t's */
1877//.. static void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1878//.. {
1879//.. VG_(sigemptyset)(set);
1880//.. set->sig[0] = *oldset;
1881//.. }
1882//.. PRE(sys_sigaction, Special)
1883//.. {
1884//.. struct vki_sigaction new, old;
1885//.. struct vki_sigaction *newp, *oldp;
1886//..
1887//.. PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1888//.. PRE_REG_READ3(int, "sigaction",
1889//.. int, signum, const struct old_sigaction *, act,
1890//.. struct old_sigaction *, oldact);
1891//..
1892//.. newp = oldp = NULL;
1893//..
1894//.. if (ARG2 != 0)
1895//.. PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction));
1896//..
1897//.. if (ARG3 != 0) {
1898//.. PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1899//.. oldp = &old;
1900//.. }
1901//..
1902//.. //jrs 20050207: what?! how can this make any sense?
1903//.. //if (VG_(is_kerror)(SYSRES))
1904//.. // return;
1905//..
1906//.. if (ARG2 != 0) {
1907//.. struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1908//..
1909//.. new.ksa_handler = oldnew->ksa_handler;
1910//.. new.sa_flags = oldnew->sa_flags;
1911//.. new.sa_restorer = oldnew->sa_restorer;
1912//.. convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1913//.. newp = &new;
1914//.. }
1915//..
1916//.. SET_RESULT( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1917//..
1918//.. if (ARG3 != 0 && RES == 0) {
1919//.. struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1920//..
1921//.. oldold->ksa_handler = oldp->ksa_handler;
1922//.. oldold->sa_flags = oldp->sa_flags;
1923//.. oldold->sa_restorer = oldp->sa_restorer;
1924//.. oldold->sa_mask = oldp->sa_mask.sig[0];
1925//.. }
1926//.. }
1927
1928//.. POST(sys_sigaction)
1929//.. {
1930//.. if (RES == 0 && ARG3 != 0)
1931//.. POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1932//.. }
1933
1934#undef PRE
1935#undef POST
1936
1937
1938/* ---------------------------------------------------------------------
1939 The ppc32/Linux syscall table
1940 ------------------------------------------------------------------ */
1941
1942/* Add an ppc32-linux specific wrapper to a syscall table. */
1943#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(ppc32_linux, sysno, name)
1944#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(ppc32_linux, sysno, name)
1945
1946// This table maps from __NR_xxx syscall numbers (from
1947// linux/include/asm-ppc/unistd.h) to the appropriate PRE/POST sys_foo()
1948// wrappers on ppc32 (as per sys_call_table in linux/arch/ppc/kernel/entry.S).
1949//
1950// For those syscalls not handled by Valgrind, the annotation indicate its
1951// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1952// (unknown).
1953
njnaf839f52005-06-23 03:27:57 +00001954const SyscallTableEntry ML_(syscall_table)[] = {
cerion85665ca2005-06-20 15:51:07 +00001955//.. (restart_syscall) // 0
sewardja932d292005-07-08 00:18:25 +00001956 GENX_(__NR_exit, sys_exit), // 1
cerion85665ca2005-06-20 15:51:07 +00001957//.. GENX_(__NR_fork, sys_fork), // 2
sewardja932d292005-07-08 00:18:25 +00001958 GENXY(__NR_read, sys_read), // 3
1959 GENX_(__NR_write, sys_write), // 4
cerion85665ca2005-06-20 15:51:07 +00001960
sewardja932d292005-07-08 00:18:25 +00001961 GENXY(__NR_open, sys_open), // 5
1962 GENXY(__NR_close, sys_close), // 6
1963 GENXY(__NR_waitpid, sys_waitpid), // 7
1964 GENXY(__NR_creat, sys_creat), // 8
sewardjb865b162005-07-08 18:26:37 +00001965 GENX_(__NR_link, sys_link), // 9
1966
sewardja932d292005-07-08 00:18:25 +00001967 GENX_(__NR_unlink, sys_unlink), // 10
1968 GENX_(__NR_execve, sys_execve), // 11
sewardjb865b162005-07-08 18:26:37 +00001969 GENX_(__NR_chdir, sys_chdir), // 12
sewardja932d292005-07-08 00:18:25 +00001970 GENXY(__NR_time, sys_time), // 13
cerion85665ca2005-06-20 15:51:07 +00001971//.. GENX_(__NR_mknod, sys_mknod), // 14
1972//..
sewardja932d292005-07-08 00:18:25 +00001973 GENX_(__NR_chmod, sys_chmod), // 15
cerion85665ca2005-06-20 15:51:07 +00001974//.. // (__NR_lchown, sys_lchown16), // 16 ## P
1975//.. GENX_(__NR_break, sys_ni_syscall), // 17
1976//.. // (__NR_oldstat, sys_stat), // 18 (obsolete)
1977//.. GENX_(__NR_lseek, sys_lseek), // 19
1978//..
sewardja932d292005-07-08 00:18:25 +00001979 GENX_(__NR_getpid, sys_getpid), // 20
cerion85665ca2005-06-20 15:51:07 +00001980//.. LINX_(__NR_mount, sys_mount), // 21
1981//.. LINX_(__NR_umount, sys_oldumount), // 22
sewardja932d292005-07-08 00:18:25 +00001982 GENX_(__NR_setuid, sys_setuid16), // 23 ## P
1983 GENX_(__NR_getuid, sys_getuid16), // 24 ## P
cerion85665ca2005-06-20 15:51:07 +00001984//..
1985//.. // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
1986//.. PLAXY(__NR_ptrace, sys_ptrace), // 26
1987//.. GENX_(__NR_alarm, sys_alarm), // 27
1988//.. // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
sewardja932d292005-07-08 00:18:25 +00001989 GENX_(__NR_pause, sys_pause), // 29
cerion85665ca2005-06-20 15:51:07 +00001990//..
cerion508aef52005-06-24 15:26:49 +00001991 GENX_(__NR_utime, sys_utime), // 30
cerion85665ca2005-06-20 15:51:07 +00001992//.. GENX_(__NR_stty, sys_ni_syscall), // 31
1993//.. GENX_(__NR_gtty, sys_ni_syscall), // 32
sewardja932d292005-07-08 00:18:25 +00001994 GENX_(__NR_access, sys_access), // 33
cerion85665ca2005-06-20 15:51:07 +00001995//.. GENX_(__NR_nice, sys_nice), // 34
1996//..
1997//.. GENX_(__NR_ftime, sys_ni_syscall), // 35
1998//.. GENX_(__NR_sync, sys_sync), // 36
sewardjb865b162005-07-08 18:26:37 +00001999 GENX_(__NR_kill, sys_kill), // 37
2000 GENX_(__NR_rename, sys_rename), // 38
2001 GENX_(__NR_mkdir, sys_mkdir), // 39
2002
cerion85665ca2005-06-20 15:51:07 +00002003//.. GENX_(__NR_rmdir, sys_rmdir), // 40
sewardja932d292005-07-08 00:18:25 +00002004 GENXY(__NR_dup, sys_dup), // 41
2005 GENXY(__NR_pipe, sys_pipe), // 42
cerion85665ca2005-06-20 15:51:07 +00002006//.. GENXY(__NR_times, sys_times), // 43
2007//.. GENX_(__NR_prof, sys_ni_syscall), // 44
2008//..
sewardja932d292005-07-08 00:18:25 +00002009 GENX_(__NR_brk, sys_brk), // 45
2010 GENX_(__NR_setgid, sys_setgid16), // 46
2011 GENX_(__NR_getgid, sys_getgid16), // 47
cerion85665ca2005-06-20 15:51:07 +00002012//.. // (__NR_signal, sys_signal), // 48 */* (ANSI C)
sewardja932d292005-07-08 00:18:25 +00002013 GENX_(__NR_geteuid, sys_geteuid16), // 49
cerion508aef52005-06-24 15:26:49 +00002014
sewardja932d292005-07-08 00:18:25 +00002015 GENX_(__NR_getegid, sys_getegid16), // 50
cerion85665ca2005-06-20 15:51:07 +00002016//.. GENX_(__NR_acct, sys_acct), // 51
2017//.. LINX_(__NR_umount2, sys_umount), // 52
2018//.. GENX_(__NR_lock, sys_ni_syscall), // 53
sewardja932d292005-07-08 00:18:25 +00002019 GENXY(__NR_ioctl, sys_ioctl), // 54
cerion85665ca2005-06-20 15:51:07 +00002020//..
2021//.. GENXY(__NR_fcntl, sys_fcntl), // 55
2022//.. GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardja932d292005-07-08 00:18:25 +00002023 GENX_(__NR_setpgid, sys_setpgid), // 57
cerion85665ca2005-06-20 15:51:07 +00002024//.. GENX_(__NR_ulimit, sys_ni_syscall), // 58
2025//.. // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
sewardjb865b162005-07-08 18:26:37 +00002026
2027 GENX_(__NR_umask, sys_umask), // 60
cerion85665ca2005-06-20 15:51:07 +00002028//.. GENX_(__NR_chroot, sys_chroot), // 61
2029//.. // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
sewardja932d292005-07-08 00:18:25 +00002030 GENXY(__NR_dup2, sys_dup2), // 63
sewardjb865b162005-07-08 18:26:37 +00002031 GENX_(__NR_getppid, sys_getppid), // 64
2032
2033 GENX_(__NR_getpgrp, sys_getpgrp), // 65
2034 GENX_(__NR_setsid, sys_setsid), // 66
cerion85665ca2005-06-20 15:51:07 +00002035//.. PLAXY(__NR_sigaction, sys_sigaction), // 67
2036//.. // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
2037//.. // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
2038//..
2039//.. GENX_(__NR_setreuid, sys_setreuid16), // 70
2040//.. GENX_(__NR_setregid, sys_setregid16), // 71
2041//.. GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
2042//.. GENXY(__NR_sigpending, sys_sigpending), // 73
2043//.. // (__NR_sethostname, sys_sethostname), // 74 */*
2044//..
cerion508aef52005-06-24 15:26:49 +00002045 GENX_(__NR_setrlimit, sys_setrlimit), // 75
cerion85665ca2005-06-20 15:51:07 +00002046//.. GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
2047//.. GENXY(__NR_getrusage, sys_getrusage), // 77
cerion508aef52005-06-24 15:26:49 +00002048 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
cerion85665ca2005-06-20 15:51:07 +00002049//.. GENX_(__NR_settimeofday, sys_settimeofday), // 79
2050//..
sewardjb865b162005-07-08 18:26:37 +00002051 GENXY(__NR_getgroups, sys_getgroups16), // 80
cerion85665ca2005-06-20 15:51:07 +00002052//.. GENX_(__NR_setgroups, sys_setgroups16), // 81
2053//.. PLAX_(__NR_select, old_select), // 82
sewardjb865b162005-07-08 18:26:37 +00002054 GENX_(__NR_symlink, sys_symlink), // 83
cerion85665ca2005-06-20 15:51:07 +00002055//.. // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
2056//..
sewardja932d292005-07-08 00:18:25 +00002057 GENX_(__NR_readlink, sys_readlink), // 85
cerion85665ca2005-06-20 15:51:07 +00002058//.. // (__NR_uselib, sys_uselib), // 86 */Linux
2059//.. // (__NR_swapon, sys_swapon), // 87 */Linux
2060//.. // (__NR_reboot, sys_reboot), // 88 */Linux
2061//.. // (__NR_readdir, old_readdir), // 89 -- superseded
2062
2063 GENXY(__NR_mmap, sys_mmap2), // 90
cerion508aef52005-06-24 15:26:49 +00002064 GENXY(__NR_munmap, sys_munmap), // 91
cerion85665ca2005-06-20 15:51:07 +00002065//.. GENX_(__NR_truncate, sys_truncate), // 92
2066//.. GENX_(__NR_ftruncate, sys_ftruncate), // 93
2067//.. GENX_(__NR_fchmod, sys_fchmod), // 94
2068//..
2069//.. GENX_(__NR_fchown, sys_fchown16), // 95
2070//.. GENX_(__NR_getpriority, sys_getpriority), // 96
2071//.. GENX_(__NR_setpriority, sys_setpriority), // 97
2072//.. GENX_(__NR_profil, sys_ni_syscall), // 98
2073//.. GENXY(__NR_statfs, sys_statfs), // 99
2074//..
2075//.. GENXY(__NR_fstatfs, sys_fstatfs), // 100
2076//.. LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja932d292005-07-08 00:18:25 +00002077 PLAXY(__NR_socketcall, sys_socketcall), // 102
cerion85665ca2005-06-20 15:51:07 +00002078//.. LINXY(__NR_syslog, sys_syslog), // 103
sewardja932d292005-07-08 00:18:25 +00002079 GENXY(__NR_setitimer, sys_setitimer), // 104
cerion85665ca2005-06-20 15:51:07 +00002080//..
2081//.. GENXY(__NR_getitimer, sys_getitimer), // 105
sewardja932d292005-07-08 00:18:25 +00002082 GENXY(__NR_stat, sys_newstat), // 106
cerion85665ca2005-06-20 15:51:07 +00002083//.. GENXY(__NR_lstat, sys_newlstat), // 107
2084//.. GENXY(__NR_fstat, sys_newfstat), // 108
2085//.. // (__NR_olduname, sys_uname), // 109 -- obsolete
2086//..
2087//.. GENX_(__NR_iopl, sys_iopl), // 110
2088//.. LINX_(__NR_vhangup, sys_vhangup), // 111
2089//.. GENX_(__NR_idle, sys_ni_syscall), // 112
2090//.. // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
2091//.. GENXY(__NR_wait4, sys_wait4), // 114
2092//..
2093//.. // (__NR_swapoff, sys_swapoff), // 115 */Linux
2094//.. LINXY(__NR_sysinfo, sys_sysinfo), // 116
sewardja932d292005-07-08 00:18:25 +00002095 PLAXY(__NR_ipc, sys_ipc), // 117
cerion85665ca2005-06-20 15:51:07 +00002096//.. GENX_(__NR_fsync, sys_fsync), // 118
sewardjb865b162005-07-08 18:26:37 +00002097 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
cerion85665ca2005-06-20 15:51:07 +00002098//..
sewardja932d292005-07-08 00:18:25 +00002099 PLAX_(__NR_clone, sys_clone), // 120
cerion85665ca2005-06-20 15:51:07 +00002100//.. // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
sewardja932d292005-07-08 00:18:25 +00002101 GENXY(__NR_uname, sys_newuname), // 122
cerion85665ca2005-06-20 15:51:07 +00002102//.. PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
2103//.. LINXY(__NR_adjtimex, sys_adjtimex), // 124
2104//..
sewardja932d292005-07-08 00:18:25 +00002105 GENXY(__NR_mprotect, sys_mprotect), // 125
cerion85665ca2005-06-20 15:51:07 +00002106//.. GENXY(__NR_sigprocmask, sys_sigprocmask), // 126
2107//.. // Nb: create_module() was removed 2.4-->2.6
2108//.. GENX_(__NR_create_module, sys_ni_syscall), // 127
2109//.. GENX_(__NR_init_module, sys_init_module), // 128
2110//.. // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
2111//..
2112//.. // Nb: get_kernel_syms() was removed 2.4-->2.6
2113//.. GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
2114//.. GENX_(__NR_quotactl, sys_quotactl), // 131
sewardja932d292005-07-08 00:18:25 +00002115 GENX_(__NR_getpgid, sys_getpgid), // 132
cerion85665ca2005-06-20 15:51:07 +00002116//.. GENX_(__NR_fchdir, sys_fchdir), // 133
2117//.. // (__NR_bdflush, sys_bdflush), // 134 */Linux
2118//..
2119//.. // (__NR_sysfs, sys_sysfs), // 135 SVr4
2120//.. LINX_(__NR_personality, sys_personality), // 136
2121//.. GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
2122//.. LINX_(__NR_setfsuid, sys_setfsuid16), // 138
2123//.. LINX_(__NR_setfsgid, sys_setfsgid16), // 139
2124//..
sewardja932d292005-07-08 00:18:25 +00002125 LINXY(__NR__llseek, sys_llseek), // 140
cerion85665ca2005-06-20 15:51:07 +00002126//.. GENXY(__NR_getdents, sys_getdents), // 141
sewardja932d292005-07-08 00:18:25 +00002127 GENX_(__NR__newselect, sys_select), // 142
cerion85665ca2005-06-20 15:51:07 +00002128//.. GENX_(__NR_flock, sys_flock), // 143
2129//.. GENX_(__NR_msync, sys_msync), // 144
2130//..
sewardja932d292005-07-08 00:18:25 +00002131 GENXY(__NR_readv, sys_readv), // 145
2132 GENX_(__NR_writev, sys_writev), // 146
cerion85665ca2005-06-20 15:51:07 +00002133//.. GENX_(__NR_getsid, sys_getsid), // 147
2134//.. GENX_(__NR_fdatasync, sys_fdatasync), // 148
sewardja932d292005-07-08 00:18:25 +00002135 LINXY(__NR__sysctl, sys_sysctl), // 149
cerion85665ca2005-06-20 15:51:07 +00002136//..
2137//.. GENX_(__NR_mlock, sys_mlock), // 150
2138//.. GENX_(__NR_munlock, sys_munlock), // 151
2139//.. GENX_(__NR_mlockall, sys_mlockall), // 152
2140//.. GENX_(__NR_munlockall, sys_munlockall), // 153
2141//.. GENXY(__NR_sched_setparam, sys_sched_setparam), // 154
2142//..
2143//.. GENXY(__NR_sched_getparam, sys_sched_getparam), // 155
2144//.. GENX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
2145//.. GENX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
2146//.. GENX_(__NR_sched_yield, sys_sched_yield), // 158
2147//.. GENX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
2148//..
2149//.. GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
2150//.. // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
sewardja932d292005-07-08 00:18:25 +00002151 GENXY(__NR_nanosleep, sys_nanosleep), // 162
2152 GENX_(__NR_mremap, sys_mremap), // 163
cerion85665ca2005-06-20 15:51:07 +00002153//.. LINX_(__NR_setresuid, sys_setresuid16), // 164
2154//..
2155//.. LINXY(__NR_getresuid, sys_getresuid16), // 165
2156
2157//.. GENX_(__NR_query_module, sys_ni_syscall), // 166
2158//.. GENXY(__NR_poll, sys_poll), // 167
2159//.. // (__NR_nfsservctl, sys_nfsservctl), // 168 */Linux
2160//..
2161//.. LINX_(__NR_setresgid, sys_setresgid16), // 169
2162//.. LINXY(__NR_getresgid, sys_getresgid16), // 170
sewardjb865b162005-07-08 18:26:37 +00002163 LINX_(__NR_prctl, sys_prctl), // 171
cerion85665ca2005-06-20 15:51:07 +00002164//.. PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 172
sewardja932d292005-07-08 00:18:25 +00002165 GENXY(__NR_rt_sigaction, sys_rt_sigaction), // 173
cerion85665ca2005-06-20 15:51:07 +00002166
sewardja932d292005-07-08 00:18:25 +00002167 GENXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 174
cerion85665ca2005-06-20 15:51:07 +00002168//.. GENXY(__NR_rt_sigpending, sys_rt_sigpending), // 175
2169//.. GENXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait), // 176
2170//.. GENXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), // 177
2171//.. GENX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 178
2172//..
sewardja932d292005-07-08 00:18:25 +00002173 GENXY(__NR_pread64, sys_pread64), // 179
2174 GENX_(__NR_pwrite64, sys_pwrite64), // 180
2175 GENX_(__NR_chown, sys_chown16), // 181
sewardjb865b162005-07-08 18:26:37 +00002176 GENXY(__NR_getcwd, sys_getcwd), // 182
cerion85665ca2005-06-20 15:51:07 +00002177//.. GENXY(__NR_capget, sys_capget), // 183
2178//..
2179//.. GENX_(__NR_capset, sys_capset), // 184
2180//.. GENXY(__NR_sigaltstack, sys_sigaltstack), // 185
2181//.. LINXY(__NR_sendfile, sys_sendfile), // 186
2182//.. GENXY(__NR_getpmsg, sys_getpmsg), // 187
2183//.. GENX_(__NR_putpmsg, sys_putpmsg), // 188
sewardja932d292005-07-08 00:18:25 +00002184
2185 // Nb: we treat vfork as fork
2186 GENX_(__NR_vfork, sys_fork), // 189
2187 GENXY(__NR_ugetrlimit, sys_getrlimit), // 190
cerion85665ca2005-06-20 15:51:07 +00002188//__NR_readahead // 191 ppc/Linux only?
sewardja932d292005-07-08 00:18:25 +00002189 GENXY(__NR_mmap2, sys_mmap2), // 192
cerion85665ca2005-06-20 15:51:07 +00002190//.. GENX_(__NR_truncate64, sys_truncate64), // 193
2191//.. GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2192//..
2193
sewardja932d292005-07-08 00:18:25 +00002194 PLAXY(__NR_stat64, sys_stat64), // 195
2195 PLAXY(__NR_lstat64, sys_lstat64), // 196
2196 PLAXY(__NR_fstat64, sys_fstat64), // 197
cerion85665ca2005-06-20 15:51:07 +00002197
2198// __NR_pciconfig_read // 198
2199// __NR_pciconfig_write // 199
2200// __NR_pciconfig_iobase // 200
2201// __NR_multiplexer // 201
2202
sewardja932d292005-07-08 00:18:25 +00002203 GENXY(__NR_getdents64, sys_getdents64), // 202
cerion85665ca2005-06-20 15:51:07 +00002204//.. // (__NR_pivot_root, sys_pivot_root), // 203 */Linux
sewardja932d292005-07-08 00:18:25 +00002205 GENXY(__NR_fcntl64, sys_fcntl64), // 204
cerion85665ca2005-06-20 15:51:07 +00002206//.. GENX_(__NR_madvise, sys_madvise), // 205
2207//.. GENXY(__NR_mincore, sys_mincore), // 206
2208//.. LINX_(__NR_gettid, sys_gettid), // 207
2209//.. LINX_(__NR_tkill, sys_tkill), // 208 */Linux
2210//.. GENX_(__NR_setxattr, sys_setxattr), // 209
2211//.. GENX_(__NR_lsetxattr, sys_lsetxattr), // 210
2212//.. GENX_(__NR_fsetxattr, sys_fsetxattr), // 211
sewardj1798ecd2005-07-02 10:13:34 +00002213 GENXY(__NR_getxattr, sys_getxattr), // 212
cerion85665ca2005-06-20 15:51:07 +00002214//.. GENXY(__NR_lgetxattr, sys_lgetxattr), // 213
2215//.. GENXY(__NR_fgetxattr, sys_fgetxattr), // 214
2216//.. GENXY(__NR_listxattr, sys_listxattr), // 215
2217//.. GENXY(__NR_llistxattr, sys_llistxattr), // 216
2218//.. GENXY(__NR_flistxattr, sys_flistxattr), // 217
2219//.. GENX_(__NR_removexattr, sys_removexattr), // 218
2220//.. GENX_(__NR_lremovexattr, sys_lremovexattr), // 219
2221//.. GENX_(__NR_fremovexattr, sys_fremovexattr), // 220
2222
cerion508aef52005-06-24 15:26:49 +00002223 LINXY(__NR_futex, sys_futex), // 221
cerion85665ca2005-06-20 15:51:07 +00002224//.. GENX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 222
2225//.. GENXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 223
2226/* 224 currently unused */
2227
2228// __NR_tuxcall // 225
2229
2230//.. LINXY(__NR_sendfile64, sys_sendfile64), // 226
2231//..
2232//.. LINX_(__NR_io_setup, sys_io_setup), // 227
2233//.. LINX_(__NR_io_destroy, sys_io_destroy), // 228
2234//.. LINXY(__NR_io_getevents, sys_io_getevents), // 229
2235//.. LINX_(__NR_io_submit, sys_io_submit), // 230
2236//.. LINXY(__NR_io_cancel, sys_io_cancel), // 231
2237//..
sewardja932d292005-07-08 00:18:25 +00002238 LINX_(__NR_set_tid_address, sys_set_tid_address), // 232
cerion85665ca2005-06-20 15:51:07 +00002239
2240//.. LINX_(__NR_fadvise64, sys_fadvise64), // 233 */(Linux?)
sewardja932d292005-07-08 00:18:25 +00002241 LINX_(__NR_exit_group, sys_exit_group), // 234
cerion85665ca2005-06-20 15:51:07 +00002242//.. GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 235
2243//.. LINXY(__NR_epoll_create, sys_epoll_create), // 236
2244//.. LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 237
2245//.. LINXY(__NR_epoll_wait, sys_epoll_wait), // 238
2246
2247//.. // (__NR_remap_file_pages, sys_remap_file_pages), // 239 */Linux
2248//.. GENXY(__NR_timer_create, sys_timer_create), // 240
2249//.. GENXY(__NR_timer_settime, sys_timer_settime), // 241
2250//.. GENXY(__NR_timer_gettime, sys_timer_gettime), // 242
2251//.. GENX_(__NR_timer_getoverrun, sys_timer_getoverrun), // 243
2252//.. GENX_(__NR_timer_delete, sys_timer_delete), // 244
2253//.. GENX_(__NR_clock_settime, sys_clock_settime), // 245
sewardja932d292005-07-08 00:18:25 +00002254 GENXY(__NR_clock_gettime, sys_clock_gettime), // 246
cerion85665ca2005-06-20 15:51:07 +00002255//.. GENXY(__NR_clock_getres, sys_clock_getres), // 247
2256//.. // (__NR_clock_nanosleep, sys_clock_nanosleep), // 248
2257
2258// __NR_swapcontext // 249
2259
2260//.. LINX_(__NR_tgkill, sys_tgkill), // 250 */Linux
2261//.. GENX_(__NR_utimes, sys_utimes), // 251
2262//.. GENXY(__NR_statfs64, sys_statfs64), // 252
2263//.. GENXY(__NR_fstatfs64, sys_fstatfs64), // 253
2264//.. LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 254 */(Linux?)
2265
2266// __NR_rtas // 255
2267
2268/* Number 256 is reserved for sys_debug_setcontext */
2269/* Number 257 is reserved for vserver */
2270/* Number 258 is reserved for new sys_remap_file_pages */
2271/* Number 259 is reserved for new sys_mbind */
2272/* Number 260 is reserved for new sys_get_mempolicy */
2273/* Number 261 is reserved for new sys_set_mempolicy */
2274
2275//.. GENXY(__NR_mq_open, sys_mq_open), // 262
2276//.. GENX_(__NR_mq_unlink, sys_mq_unlink), // 263
2277//.. GENX_(__NR_mq_timedsend, sys_mq_timedsend), // 264
2278//.. GENXY(__NR_mq_timedreceive, sys_mq_timedreceive), // 265
2279//.. GENX_(__NR_mq_notify, sys_mq_notify), // 266
2280//.. GENXY(__NR_mq_getsetattr, sys_mq_getsetattr), // 267
2281
2282// __NR_kexec_load // 268
2283};
2284
njnaf839f52005-06-23 03:27:57 +00002285const UInt ML_(syscall_table_size) =
2286 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
cerion85665ca2005-06-20 15:51:07 +00002287
2288/*--------------------------------------------------------------------*/
2289/*--- end ---*/
2290/*--------------------------------------------------------------------*/