]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_syswrap/syswrap-aix5.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_syswrap / syswrap-aix5.c
1
2 /*--------------------------------------------------------------------*/
3 /*--- AIX5-specific syscalls.                       syswrap-aix5.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9
10    Copyright (C) 2006-2010 OpenWorks LLP
11       info@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    Neither the names of the U.S. Department of Energy nor the
31    University of California nor the names of its contributors may be
32    used to endorse or promote products derived from this software
33    without prior written permission.
34 */
35
36 #if defined(VGO_aix5)
37
38 #include "pub_core_basics.h"
39 #include "pub_core_vki.h"
40 #include "pub_core_vkiscnums.h"
41 #include "pub_core_threadstate.h"
42 #include "pub_core_aspacemgr.h"
43 #include "pub_core_debuginfo.h"    // VG_(di_notify_*)
44 #include "pub_core_transtab.h"     // VG_(discard_translations)
45 #include "pub_core_xarray.h"
46 #include "pub_core_clientstate.h"
47 #include "pub_core_debuglog.h"
48 #include "pub_tool_gdbserver.h"     // VG_(gdbserver)
49 #include "pub_core_libcbase.h"
50 #include "pub_core_libcassert.h"
51 #include "pub_core_libcfile.h"
52 #include "pub_core_libcprint.h"
53 #include "pub_core_libcproc.h"
54 #include "pub_core_libcsignal.h"
55 #include "pub_core_mallocfree.h"
56 #include "pub_core_tooliface.h"
57 #include "pub_core_options.h"
58 #include "pub_core_scheduler.h"
59 #include "pub_core_signals.h"
60 #include "pub_core_syscall.h"
61 #include "pub_core_sigframe.h"     // VG_(sigframe_destroy)
62 #include "pub_core_syswrap.h"
63 #include "pub_core_stacktrace.h"
64
65 #include "priv_types_n_macros.h"
66 #include "priv_syswrap-aix5.h"
67
68
69
70 /* ---------------------------------------------------------------------
71    Misc helpers
72    ------------------------------------------------------------------ */
73
74 /* Allocate a stack for this thread, if it doesn't already have one.
75    They're allocated lazily, and never freed.  Returns the initial stack
76    pointer value to use, or 0 if allocation failed. */
77 Addr ML_(allocstack)(ThreadId tid)
78 {
79    ThreadState* tst = VG_(get_ThreadState)(tid);
80    VgStack*     stack;
81    Addr         initial_SP;
82
83    /* Either the stack_base and stack_init_SP are both zero (in which
84       case a stack hasn't been allocated) or they are both non-zero,
85       in which case it has. */
86
87    if (tst->os_state.valgrind_stack_base == 0)
88       vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
89
90    if (tst->os_state.valgrind_stack_base != 0)
91       vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
92
93    /* If no stack is present, allocate one. */
94    if (tst->os_state.valgrind_stack_base == 0) {
95       stack = VG_(am_alloc_VgStack)( &initial_SP );
96       if (stack) {
97          /* Leave some space above SP because AIX's ABI stores
98             stuff there. */
99          initial_SP -= 256;
100          vg_assert(initial_SP > (Addr)stack);
101          tst->os_state.valgrind_stack_base    = (Addr)stack;
102          tst->os_state.valgrind_stack_init_SP = initial_SP;
103       } else {
104          return 0; /* allocation of stack failed */
105       }
106    }
107
108    if (0)
109       VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
110                    tid,
111                    (void*)tst->os_state.valgrind_stack_base,
112                    (void*)tst->os_state.valgrind_stack_init_SP );
113
114    return tst->os_state.valgrind_stack_init_SP;
115 }
116
117
118 /* If we know or believe a module load/unload event has happened, get
119    aspacem to re-read /proc/../map to update its picture of what text
120    and data segments are present.  This also notifies all the usual
121    parties that need to know about address space changes. */
122
123 void ML_(aix5_rescan_procmap_after_load_or_unload) ( void )
124 {
125    AixCodeSegChange* changes;
126    Int changes_size, changes_used, i;
127
128    /* Find out how many AixCodeSegChange records we will need, and
129       acquire them. */
130    changes_size = VG_(am_aix5_reread_procmap_howmany_directives)(); 
131    changes = VG_(arena_malloc)(VG_AR_CORE, "syswrap-aix5.arpalou.1",
132                                changes_size * sizeof(AixCodeSegChange));
133    vg_assert(changes);
134
135    /* Now re-read /proc/<pid>/map and acquire a change set */
136    VG_(am_aix5_reread_procmap)( changes, &changes_used );
137    vg_assert(changes_used >= 0 && changes_used <= changes_size);
138
139    /* And notify all parties of the changes. */
140    for (i = 0; i < changes_used; i++) {
141       ULong di_handle = VG_(di_aix5_notify_segchange)(
142                            changes[i].code_start,
143                            changes[i].code_len,
144                            changes[i].data_start,
145                            changes[i].data_len,
146                            changes[i].file_name,
147                            changes[i].mem_name,
148                            changes[i].is_mainexe,
149                            changes[i].acquire
150                         );
151
152       if (changes[i].acquire) {
153          VG_TRACK( new_mem_mmap, 
154                    changes[i].code_start, changes[i].code_len, 
155                    /*r*/True, /*w*/False, /*x*/True, di_handle );
156          VG_TRACK( new_mem_mmap, 
157                    changes[i].data_start, changes[i].data_len, 
158                    /*r*/True, /*w*/True, /*x*/False, 0/*or di_handle?*/ );
159       } else {
160          VG_TRACK( die_mem_munmap, 
161                    changes[i].code_start, changes[i].code_len );
162          VG_TRACK( die_mem_munmap, 
163                    changes[i].data_start, changes[i].data_len );
164          VG_(discard_translations)(
165                    changes[i].code_start, changes[i].code_len,
166                    "POST(sys___loadx/sys__kload)(code)" );
167          VG_(discard_translations)(
168                     changes[i].data_start, changes[i].data_len,
169                    "POST(sys___loadx/sys__kload)(data)" );
170       }
171    }
172
173    VG_(arena_free)(VG_AR_CORE, changes);
174 }
175
176
177 /* Mess with the given thread's pc/toc so that it is entering
178    pthread_exit() with argument PTHREAD_CANCELED.  Returns True if ok,
179    False if it failed to do so, due to not being able to find
180    pthread_exit() by searching symbol tables. */
181 Bool ML_(aix5_force_thread_into_pthread_exit)( ThreadId tid )
182 {
183    Addr ent = 0, toc = 0;
184    Bool found;
185    ThreadState* tst = VG_(get_ThreadState)(tid);
186    found = VG_(lookup_symbol_SLOW)("libpthread*.a(*.o)", "pthread_exit", 
187                                    &ent, &toc);
188    if (found) {
189       if (0) 
190          VG_(printf)("THREAD CANCELED, new cia,toc = %#lx,%#lx\n", ent, toc);
191       tst->arch.vex.guest_CIA  = ent;
192       tst->arch.vex.guest_GPR2 = toc;
193       tst->arch.vex.guest_GPR3 = (Word)(-1); /* == PTHREAD_CANCELED */
194       /* If the thread is blocked in a syscall, we better bop it on
195          the head with SIGVGKILL in order to get it out of said
196          syscall. */
197       if (tst->status == VgTs_WaitSys) {
198          if (VG_(clo_trace_syscalls))
199             VG_(printf)("(sending SIGVGKILL to tid %d)", (Int)tid);
200          VG_(get_thread_out_of_syscall)( tid  );
201       }
202       return True; /* ok */
203    } else {
204       // urk.  Now we're hosed.  Let the caller figure out what to do.
205       return False; /* failed */
206    }
207 }
208
209
210 /* For various reasons, on AIX we may have to just give up if
211    continuing is too difficult (eg, risk of future deadlock).  This
212    sets up the process state to exit straight away, but does not
213    actually itself exit. */
214 void ML_(aix5_set_threadstate_for_emergency_exit)(ThreadId tid, HChar* why)
215 {
216    ThreadState* tst = VG_(get_ThreadState)(tid);
217    /* Set the thread's status to be exiting and taking out the
218       entire process, then claim that the syscall succeeded. */
219    tst->exitreason = VgSrc_ExitProcess;
220    tst->os_state.exitcode = 1;
221    if (!VG_(clo_xml)) {
222       VG_(message)(Vg_UserMsg, 
223          "WARNING: AIX: %s\n", why);
224       VG_(message)(Vg_UserMsg, 
225          "WARNING: (too difficult to continue past this point).\n");
226       VG_(get_and_pp_StackTrace)(tid, 10);
227    }
228 }
229
230
231 /* Update aspacem etc on conclusion of a successful sbrk/__libc_sbrk
232    call.  2006-08-24: this was not completed because I don't 
233    understand what sbrk/__libc_sbrk are doing. */
234
235 static void handle_sbrk ( Word delta )
236 {
237    return;
238    /*NOTREACHED*/
239    if (delta > 0) {
240       /* Map in VG_(brk_limit) for delta */
241       /* using notify_mmap ? */
242       VG_(brk_limit) += delta;
243    }
244    if (delta < 0) {
245      Addr tmp = VG_(brk_limit);
246      VG_(brk_limit) += delta;
247      /* Can't move below original starting point */
248      if (VG_(brk_limit) < VG_(brk_base))
249         VG_(brk_limit) = VG_(brk_base);
250      if (VG_(brk_limit) < tmp)
251         /* Unmap VG_(brk_limit) for tmp - VG_(brk_limit) */
252         /* using notify_munmap ? */
253         ;
254    }
255    if (VG_(clo_trace_syscalls))
256       VG_(printf)("new brk: 0x%010llx-0x%010llx (size %lld)\n",
257                   (ULong)VG_(brk_base),
258                   (ULong)VG_(brk_limit),
259                   (ULong)VG_(brk_limit) - (ULong)VG_(brk_base));
260 }
261
262
263 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
264 #include <sys/thread.h>
265 #include <sys/poll.h>
266 #include <sys/times.h>
267 #include <sys/shm.h>
268 #include <semaphore.h>
269 #include <sys/statfs.h>
270 #include <sys/utsname.h>
271 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
272
273 HChar* ML_(aix5debugstuff_pc_to_fnname) ( Addr pc )
274 {
275    Bool ok;
276    static HChar name[100];
277    ok = VG_(get_fnname_w_offset)(pc, name, 100);
278    if (!ok) VG_(strcpy)(name, "???");
279    return &name[0];
280 }
281
282 static void aix5debugstuff_show_sigset ( vki_sigset_t* set )
283 {
284   Int i;
285   UChar* p = (UChar*)set;
286   for (i = 0; i < sizeof(vki_sigset_t); i++)
287      VG_(printf)("%02x", (Int)p[i]);
288 }
289
290 static HChar* aix5debugstuff_name_of_tstate_flag ( UWord flag )
291 {
292    Int i, nset;
293    nset = 0;
294    for (i = 0; i < 8*sizeof(UWord); i++)
295       if (flag & (1U << i))
296          nset++;
297    vg_assert(nset == 1);
298    switch (flag) {
299       case TSTATE_LOCAL:           return "LOCAL";
300       case TSTATE_CANCEL_DEFER:    return "CANCEL_DEFER";
301       case TSTATE_CANCEL_DISABLE:  return "CANCEL_DISABLE";
302       case TSTATE_CANCEL_PENDING:  return "CANCEL_PENDING";
303       case TSTATE_CANCEL_CHKPT:    return "CANCEL_CHKPT";
304       case TSTATE_INTR:            return "INTR";
305       case TSTATE_EXEMPT:          return "EXEMPT";
306 #ifdef TSTATE_PROFILING_OFF
307       case TSTATE_PROFILING_OFF:   return "PROFILING_OFF";
308 #endif
309       case TSTATE_SUSPEND:         return "SUSPEND";
310       case TSTATE_CONT:            return "CONT";
311 #ifdef TSTATE_CREDS
312       case TSTATE_CREDS:           return "CREDS";
313 #endif
314 #ifdef TSTATE_PROCHANDLERS
315       case TSTATE_PROCHANDLERS:    return "PROCHANDLERS";
316 #endif
317       case TSTATE_ADVH:            return "ADVH";
318       case TSTATE_SYNCH:           return "SYNCH";
319       case TSTATE_USCHED:          return "USCHED";
320       case TSTATE_DEFAULT_SCHED:   return "DEFAULT_SCHED";
321 #ifdef TSTATE_INHERIT_SCHED
322       case TSTATE_INHERIT_SCHED:   return "INHERIT_SCHED";
323 #endif
324 #ifdef TSTATE_LOCAL_INIT
325       case TSTATE_LOCAL_INIT:      return "LOCAL_INIT";
326 #endif
327 #ifdef TSTATE_LOCAL_TERM
328       case TSTATE_LOCAL_TERM:      return "LOCAL_TERM";
329 #endif
330 #ifdef TSTATE_LOCAL_MCHANGE
331       case TSTATE_LOCAL_MCHANGE:   return "LOCAL_MCHANGE";
332 #endif
333       case TSTATE_CHANGE_ALL:      return "CHANGE_ALL";
334 #ifdef TSTATE_CHANGE_PTID
335       case TSTATE_CHANGE_PTID:     return "CHANGE_PTID";
336 #endif
337 #ifdef TSTATE_CHANGE_PROFILE
338       case TSTATE_CHANGE_PROFILE:  return "CHANGE_PROFILE";
339 #endif
340 #ifdef TSTATE_CHANGE_SSTACK
341       case TSTATE_CHANGE_SSTACK:   return "CHANGE_SSTACK";
342 #endif
343       case TSTATE_CHANGE_ERRNOP:   return "CHANGE_ERRNOP";
344       case TSTATE_CHANGE_SIGMASK:  return "CHANGE_SIGMASK";
345       case TSTATE_CHANGE_PSIG:     return "CHANGE_PSIG";
346       case TSTATE_CHANGE_SCHED:    return "CHANGE_SCHED";
347       case TSTATE_CHANGE_FLAGS:    return "CHANGE_FLAGS";
348       case TSTATE_CHANGE_USERDATA: return "CHANGE_USERDATA";
349       default: return "???";
350    }
351 }
352
353 void ML_(aix5debugstuff_show_tstate_flags) ( UWord w )
354 {
355    const Int step = 5;
356    Int i, j;
357    UWord m;
358    j = 0;
359    for (i = 0; i < 8*sizeof(UWord); i++) {
360       m = 1U << i;
361       if ((w & m) == 0)
362          continue;
363       if ((j % step) == 0)
364          VG_(printf)("  ");
365       VG_(printf)("%s ", aix5debugstuff_name_of_tstate_flag(w & m));
366       if ((j % step) == step-1 && j > 0)
367          VG_(printf)("\n");
368       j++;
369    }
370    if (((j-1) % step) != step-1 && j > 0)
371       VG_(printf)("\n");
372 }
373
374 void ML_(aix5debugstuff_show_tstate) ( Addr tsA, HChar* who )
375 {
376    Int i;
377    const Int step = sizeof(void*)==8  ? 3 : 5;
378    struct tstate* ts = (struct tstate*)tsA;
379    VG_(printf)("\n{ ========= %s =========\n", who);
380    for (i = 0; i < _NGPRS; i++) {
381       if ((i % step) == 0) 
382          VG_(printf)("  [%2d]  ", i);
383       if (sizeof(void*)==8)
384          VG_(printf)("%016llx  ", (ULong)ts->mst.gpr[i]);
385       else
386          VG_(printf)("%08llx  ", (ULong)ts->mst.gpr[i]);
387       if ((i == _NGPRS-1) || ((i % step) == step-1 && i > 0)) 
388          VG_(printf)("\n");
389    }
390    VG_(printf)("  [iar] %#llx %s\n", (ULong)ts->mst.iar, 
391                ML_(aix5debugstuff_pc_to_fnname)(ts->mst.iar));
392
393    VG_(printf)("  errnop_addr      %p\n", ts->errnop_addr);
394
395    VG_(printf)("  sigmask          ");
396    aix5debugstuff_show_sigset( (vki_sigset_t*)&ts->sigmask );
397    VG_(printf)("\n");
398
399    VG_(printf)("  psig             ");
400    aix5debugstuff_show_sigset( (vki_sigset_t*)&ts->psig );
401    VG_(printf)("\n");
402
403    VG_(printf)("  policy           %d\n", ts->policy);
404    VG_(printf)("  priority         %d\n", ts->priority);
405    VG_(printf)("  flags            0x%x\n", ts->flags);
406    ML_(aix5debugstuff_show_tstate_flags)( (UWord)ts->flags );
407    VG_(printf)("  flagmask         0x%x\n", ts->flagmask);
408    VG_(printf)("  userdata         %p\n", (void*)ts->userdata);
409    VG_(printf)("  fpinfo           %d\n", ts->fpinfo);
410    VG_(printf)("  fpscrx           %d\n", ts->fpscrx);
411    VG_(printf)("  sigaltstack      ??\n");
412    VG_(printf)("  thread_control_p 0x%llx\n", (ULong)ts->thread_control_p);
413 //   AIX 5.1 does not seem to have these members
414 //   VG_(printf)("  prbase           %p\n", (void*)ts->prbase);
415 //   VG_(printf)("  credp            %p\n", (void*)ts->credp);
416 //   VG_(printf)("  ptid             %d\n", (int)ts->ptid);
417 //   VG_(printf)("  tct_clock        %d\n", (int)ts->tct_clock);
418    UInt* p = (UInt*)tsA;
419    for (i = 0; i < sizeof(struct tstate)/sizeof(UInt); i++) {
420       HChar* s = ML_(aix5debugstuff_pc_to_fnname)( (Addr)p[i] );
421       if (0==VG_(strcmp)(s,"???"))
422          continue;
423       VG_(printf)("  [%d] %x %s\n", i, p[i], s);
424    }
425    VG_(printf)("}\n");
426 }
427
428 /* ---------------------------------------------------------------------
429    PRE/POST wrappers for arch-generic, AIX5-specific syscalls.  Note:
430    in fact AIX5 doesn't share any wrappers with Linux since it's
431    difficult to get syswrap-generic.c to compile on AIX.  Hence in
432    fact this file also serves the role of syswrap-generic.c for AIX.
433    This could probably be improved at the cost of some extra effort.
434    ------------------------------------------------------------------ */
435
436 // Nb: See the comment above the generic PRE/POST wrappers in
437 // m_syswrap/syswrap-generic.c for notes about how they work.
438
439 #define PRE(name)       DEFN_PRE_TEMPLATE(aix5, name)
440 #define POST(name)      DEFN_POST_TEMPLATE(aix5, name)
441
442
443 // How to make __libc_sbrk appear to fail, from libc's point of view:
444 //  SysRes r;
445 //  r.res = -1; /* significant to libc */
446 //  r.err = VKI_ENOMEM; /* not significant to libc */
447 //  SET_STATUS_from_SysRes( r );
448 //  return;
449
450 PRE(sys___libc_sbrk)
451 {
452    PRINT("__libc_sbrk (BOGUS HANDLER)( %#lx )",ARG1);
453    PRE_REG_READ1(long, "__libc_sbrk", long, arg1);
454    /* After a zero sbrk, disallow aspacem from doing sbrk, since libc
455       might rely on the value returned by this syscall. */
456    /* 1 Oct 06: not currently used (aspacemgr-aix5.c ignores it) */
457    VG_(am_aix5_sbrk_allowed) = toBool(ARG1 != 0);
458    /* Disallow libc from moving the brk backwards as that might trash
459       SkPreAlloc sections acquired by aspacem from previous uses of
460       sbrk. */
461    if (ARG1 < 0)
462       ARG1 = 0;
463    /* Do this as a sync syscall, so the sbrk_allowed flag gets turned
464       back on ASAP.  Typically libc does sbrk(0) and then sbrk(x > 0)
465       in quick succession.  Although surely it should hold some kind
466       of lock at that point, else it cannot safely use the result from
467       the first sbrk call to influence the second one? */
468    *flags &= ~SfMayBlock;
469 }
470 POST(sys___libc_sbrk)
471 {
472    vg_assert(SUCCESS);
473    handle_sbrk(ARG1);
474 }
475
476 /* __loadx is handled in the platform-specific files. */
477
478 PRE(sys___msleep)
479 {
480    PRINT("__msleep (BOGUS HANDLER) ( %#lx )", ARG1);
481    PRE_REG_READ1(long, "msleep", void*, arg1);
482 }
483
484 /* __unload is handled in the platform-specific files. */
485
486 PRE(sys__clock_settime)
487 {
488    PRINT("_clock_settime (UNDOCUMENTED) ( %ld, %#lx )", ARG1, ARG2);
489    PRE_REG_READ2(int, "_clock_settime", int, arg1, int, arg2);
490 }
491
492 PRE(sys__exit)
493 {
494    ThreadState* tst;
495    /* simple; just make this thread exit */
496    PRINT("_exit( %ld )", ARG1);
497    PRE_REG_READ1(void, "exit", int, exitcode);
498
499    tst = VG_(get_ThreadState)(tid);
500    /* Set the thread's status to be exiting and taking out the entire
501       process, then claim that the syscall succeeded. */
502    tst->exitreason = VgSrc_ExitProcess;
503    tst->os_state.exitcode = ARG1;
504    SET_STATUS_Success(0);
505 }
506
507 PRE(sys__fp_fpscrx_sc)
508 {
509    PRINT("_fp_fpscrx_sc (BOGUS HANDLER)");
510 }
511
512 PRE(sys__getpgrp)
513 {
514    PRINT("_getpgrp (BOGUS HANDLER)");
515 }
516
517 PRE(sys__getpid)
518 {
519    PRINT("_getpid ( )");
520 }
521
522 PRE(sys__getppid)
523 {
524    PRINT("_getppid ( )");
525 }
526
527 PRE(sys__getpriority)
528 {
529    PRINT("_getpriority (BOGUS HANDLER)");
530 }
531
532 PRE(sys__nsleep)
533 {
534    *flags |= SfMayBlock;
535    PRINT("_nsleep( %#lx, %#lx )", ARG1, ARG2);
536    PRE_REG_READ2(void, "_nsleep", struct timestruc_t*, arg1,
537                                   struct timestruc_t*, arg2);
538    /* In 64-bit mode, struct ends in 4 padding bytes.  Hence: */
539    if (ARG1)
540       PRE_MEM_READ("_nsleep(arg1)", 
541                    ARG1, 
542                    sizeof(void*)==4 ? sizeof(struct timestruc_t)
543                                     : sizeof(struct timestruc_t)-4 );
544    if (ARG2)
545       PRE_MEM_WRITE("_nsleep(arg2)", ARG2, sizeof(struct timestruc_t));
546 }
547 POST(sys__nsleep)
548 {
549    if (ARG2)
550       POST_MEM_WRITE(ARG2, sizeof(struct timestruc_t));
551 }
552
553 PRE(sys__pause)
554 {
555   *flags |= SfMayBlock;
556   PRINT("_pause ( )");
557   PRE_REG_READ0(long, "pause");
558 }
559
560 PRE(sys__poll)
561 {
562    UInt i;
563    struct pollfd* ufds = (struct pollfd *)ARG1;
564    *flags |= SfMayBlock;
565    PRINT("_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3);
566    PRE_REG_READ3(long, "_poll",
567                  struct pollfd *, ufds, unsigned int, nfds, long, timeout);
568
569    for (i = 0; i < ARG2; i++) {
570       PRE_MEM_READ( "poll(ufds.fd)",
571                     (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
572       PRE_MEM_READ( "poll(ufds.events)",
573                     (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
574       PRE_MEM_WRITE( "poll(ufds.reventss)",
575                       (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
576    }
577 }
578 POST(sys__poll)
579 {
580    if (RES > 0) {
581       UInt i;
582       struct pollfd* ufds = (struct pollfd *)ARG1;
583       for (i = 0; i < ARG2; i++)
584          POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
585    }
586 }
587
588 PRE(sys__select)
589 {
590    UInt nfds, nmqids;
591    *flags |= SfMayBlock;
592    /* XXX: copy of generic; I don't know if this is right or not. */
593    PRINT("_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
594    PRE_REG_READ5(long, "_select",
595                  int, n, struct sellist *, readfds, 
596                          struct sellist *, writefds,
597                          struct sellist *, exceptfds, 
598                          struct timeval *, timeout);
599    nfds   = ((UInt)ARG1) & 0xFFFF;
600    nmqids = (((UInt)ARG1) >> 16) & 0xFFFF;
601
602    // XXX: this possibly understates how much memory is read.
603    if (ARG2 != 0)
604      PRE_MEM_READ( "select(readfds)",   
605                    ARG2, nfds/8 /* __FD_SETSIZE/8 */ );
606    if (ARG3 != 0)
607      PRE_MEM_READ( "select(writefds)",  
608                    ARG3, nfds/8 /* __FD_SETSIZE/8 */ );
609    if (ARG4 != 0)
610      PRE_MEM_READ( "select(exceptfds)", 
611                    ARG4, nfds/8 /* __FD_SETSIZE/8 */ );
612    if (ARG5 != 0)
613      PRE_MEM_READ( "select(timeout)", ARG5, 
614                    /* in 64-bit mode, struct timeval has 4 bytes of
615                       padding at the end, which tend to not be
616                       initialised. */
617                    sizeof(void*)==4  ? sizeof(struct timeval)
618                                      : sizeof(struct timeval)-4
619      );
620 }
621
622 PRE(sys__sem_wait)
623 {
624    *flags |= SfMayBlock;
625    PRINT("_sem_wait (BOGUS HANDLER) ( %#lx, %#lx, %ld )", ARG1, ARG2, ARG3);
626    PRE_REG_READ3(long, "_sem_wait", void*, arg1, void*, arg2, long, arg3 );
627    /* Not sure what the two pointer args are.  Hence no proper handler.*/
628 }
629
630 PRE(sys__setpgid)
631 {
632    PRINT("setpgid ( %ld, %ld )", ARG1, ARG2);
633    PRE_REG_READ2(int, "setpgid", int, pid, int, pgid);
634 }
635
636 PRE(sys__setsid)
637 {
638    PRINT("setsid ( )");
639 }
640
641 PRE(sys__sigaction) /* COL, more or less */
642 {
643    PRINT("_sigaction ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
644    PRE_REG_READ3(long, "_sigaction",
645                  int, signum, const struct sigaction *, act,
646                  struct sigaction *, oldact);
647
648    if (ARG2 != 0) {
649       struct vki_sigaction *sa = (struct vki_sigaction *)ARG2;
650       PRE_MEM_READ( "_sigaction(act->sa_handler)", 
651                     (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
652       PRE_MEM_READ( "_sigaction(act->sa_mask)", 
653                     (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
654       PRE_MEM_READ( "rt_sigaction(act->sa_flags)", 
655                     (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
656    }
657    if (ARG3 != 0)
658       PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(struct vki_sigaction));
659
660    SET_STATUS_from_SysRes(
661       VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2,
662                                   (struct vki_sigaction *)ARG3)
663    );
664 }
665 POST(sys__sigaction)
666 {
667    vg_assert(SUCCESS);
668    if (RES == 0 && ARG3 != 0)
669       POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction));
670 }
671
672 PRE(sys__thread_self)
673 {
674    PRINT("_thread_self ( )");
675 }
676
677 PRE(sys__thread_setsched)
678 {
679    PRINT("_thread_setsched ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
680    PRE_REG_READ3(long, "_thread_setsched", long, arg1, long, arg2, long, arg3);
681 }
682
683 PRE(sys_access)
684 {
685    PRINT("access ( %#lx(%s), %ld )", ARG1,(Char*)ARG1, ARG2);
686    PRE_REG_READ2(int, "access", char*, pathname, int, mode);
687    PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
688 }
689
690 PRE(sys_accessx)
691 {
692    PRINT("accessx ( %#lx(%s), %ld, %ld )", ARG1,(Char*)ARG1, ARG2, ARG3);
693    PRE_REG_READ3(int, "accessx", char*, pathname, int, mode, int, who);
694    PRE_MEM_RASCIIZ( "accessx(pathname)", ARG1 );
695 }
696
697 PRE(sys_appgetrlimit)
698 {
699    /* Note: assumes kernel struct == libc struct */
700    PRINT("appgetrlimit ( %ld, %#lx )", ARG1, ARG2);
701    PRE_REG_READ2(int, "appgetrlimit", int, arg1, struct rlimit*, arg2);
702    PRE_MEM_WRITE( "appgetrlimit(buf)", ARG2, sizeof(struct rlimit) );
703 }
704 POST(sys_appgetrlimit)
705 {
706    POST_MEM_WRITE( ARG2, sizeof(struct rlimit) );
707 }
708
709 PRE(sys_appgetrusage)
710 {
711    /* Note: assumes kernel struct == libc struct */
712    PRINT("appgetrusage ( %ld, %#lx )", ARG1, ARG2);
713    PRE_REG_READ2(int, "appgetrusage", int, arg1, struct rusage*, arg2);
714    PRE_MEM_WRITE( "appgetrusage(buf)", ARG2, sizeof(struct rusage) );
715 }
716 POST(sys_appgetrusage)
717 {
718    POST_MEM_WRITE( ARG2, sizeof(struct rusage) );
719 }
720
721 PRE(sys_apprestimer)
722 {
723    PRINT("apprestimer (BOGUS HANDLER)");
724 }
725
726 PRE(sys_appsetrlimit)
727 {
728    PRINT("appsetrlimit (BOGUS HANDLER)");
729 }
730
731 PRE(sys_appulimit)
732 {
733    PRINT("appulimit ( %ld, %ld )", ARG1, ARG2);
734    PRE_REG_READ2(long, "appulimit", long, arg1, long, arg2);
735 }
736
737 PRE(sys_bind)
738 {
739    PRINT("bind ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
740    PRE_REG_READ3(int, "bind", int, socket, 
741                               void*, address, int, addresslen);
742    /* Hmm.  This isn't really right - see pre_mem_read_sockaddr. */
743    PRE_MEM_READ( "bind(address)", ARG2, ARG3 );
744 }
745
746 PRE(sys_chdir)
747 {
748   PRINT("chdir ( %#lx(%s) )", ARG1,(Char*)ARG1);
749   PRE_REG_READ1(long, "chdir", const char *, path);
750   PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
751 }
752
753 PRE(sys_chmod)
754 {
755    PRINT("chmod ( %#lx(%s), 0x%lx )", ARG1,(Char*)ARG1, ARG2 );
756    PRE_REG_READ2(int, "chmod", char*, path, int, mode);
757    PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
758 }
759
760 PRE(sys_chown)
761 {
762    PRINT("chown ( %#lx(%s), %ld, %ld )", ARG1,(Char*)ARG1, ARG2, ARG3 );
763    PRE_REG_READ3(int, "chown", char*, path, int, owner, int, group);
764    PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
765 }
766
767 PRE(sys_close)
768 {
769    PRINT("close ( %ld )", ARG1);
770    PRE_REG_READ1(void, "close", UInt, fd);
771    /* If doing -d style logging (which is to fd=2), don't allow that
772       to be closed. */
773    if (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0)
774       SET_STATUS_Failure( VKI_EBADF );
775 }
776
777 PRE(sys_connext)
778 {
779    /* apparently undocumented.  I don't know what it does. */
780    /* Although /usr/include/net/proto_uipc.h does mention it.
781       Args are apparently (int, caddr_t, int).  I suspect the
782       first arg is a fd and the third a flags value. */
783    PRINT("connext (UNDOCUMENTED)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
784    PRE_REG_READ3(int, "connext", int, arg1, caddr_t*, arg2, int, arg3);
785 }
786
787 //--- PRE(sys_execve) ---//
788 // Pre_read a char** argument.
789 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
790 {
791    while (True) {
792       Addr a_deref;
793       Addr* a_p = (Addr*)a;
794       PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
795       a_deref = *a_p;
796       if (0 == a_deref)
797          break;
798       PRE_MEM_RASCIIZ( s2, a_deref );
799       a += sizeof(char*);
800    }
801 }
802 static SysRes simple_pre_exec_check ( const HChar* exe_name,
803                                       Bool trace_this_child )
804 {
805    Int fd, ret;
806    SysRes res;
807    Bool setuid_allowed;
808
809    // Check it's readable
810    res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
811    if (res.isError) {
812       return res;
813    }
814    fd = res.res;
815    VG_(close)(fd);
816
817    // Check we have execute permissions.  We allow setuid executables
818    // to be run only in the case when we are not simulating them, that
819    // is, they to be run natively.
820    setuid_allowed = trace_this_child  ? False  : True;
821    ret = VG_(check_executable)(NULL/*&is_setuid*/,
822                                (HChar*)exe_name, setuid_allowed);
823    if (0 != ret) {
824       return VG_(mk_SysRes_Error)(ret);
825    }
826    return VG_(mk_SysRes_Success)(0);
827 }
828 PRE(sys_execve)
829 {
830    Char*        path = NULL;       /* path to executable */
831    Char**       envp = NULL;
832    Char**       argv = NULL;
833    Char**       arg2copy;
834    Char*        launcher_basename = NULL;
835    ThreadState* tst;
836    Int          i, j, tot_args;
837    SysRes       res;
838    Bool         trace_this_child;
839
840    PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (Char*)ARG1, ARG2, ARG3);
841    PRE_REG_READ3(vki_off_t, "execve",
842                  char *, filename, char **, argv, char **, envp);
843    PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
844    if (ARG2 != 0)
845       pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
846    if (ARG3 != 0)
847       pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
848
849    vg_assert(VG_(is_valid_tid)(tid));
850    tst = VG_(get_ThreadState)(tid);
851
852    /* Erk.  If the exec fails, then the following will have made a
853       mess of things which makes it hard for us to continue.  The
854       right thing to do is piece everything together again in
855       POST(execve), but that's close to impossible.  Instead, we make
856       an effort to check that the execve will work before actually
857       doing it. */
858
859    /* Check that the name at least begins in client-accessible storage. */
860    /* XXX: causes execve to fail for non-memcheck tools, presumably
861       because ARG1 is thought to not to being in client-accessible
862       storage due to inadequate address space tracking.  May or may
863       not be due to non-tracking of brk. */
864    //if (!VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
865    //   SET_STATUS_Failure( VKI_EFAULT );
866    //   return;
867    //}
868    if (ARG1 == 0 /* obviously bogus */) {
869       SET_STATUS_Failure( VKI_EFAULT );
870    }
871
872    // Decide whether or not we want to follow along
873    trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1 );
874
875    // Do the important checks:  it is a file, is executable, permissions are
876    // ok, etc.
877    res = simple_pre_exec_check( (const HChar*)ARG1, trace_this_child );
878    if (res.isError) {
879       SET_STATUS_Failure( res.err );
880       return;
881    }
882
883    /* If we're tracing the child, and the launcher name looks bogus
884       (possibly because launcher.c couldn't figure it out, see
885       comments therein) then we have no option but to fail. */
886    if (trace_this_child 
887        && (VG_(name_of_launcher) == NULL
888            || VG_(name_of_launcher)[0] != '/')) {
889       SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
890       return;
891    }
892
893    /* After this point, we can't recover if the execve fails. */
894    VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
895
896    // Terminate gdbserver if it is active.
897    if (VG_(clo_vgdb)  != Vg_VgdbNo) {
898       // If the child will not be traced, we need to terminate gdbserver
899       // to cleanup the gdbserver resources (e.g. the FIFO files).
900       // If child will be traced, we also terminate gdbserver: the new 
901       // Valgrind will start a fresh gdbserver after exec.
902       VG_(gdbserver) (0);
903    }
904
905    /* Resistance is futile.  Nuke all other threads.  POSIX mandates
906       this. (Really, nuke them all, since the new process will make
907       its own new thread.) */
908    VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread );
909    VG_(reap_threads)(tid);
910
911    // Set up the child's exe path.
912    //
913    if (trace_this_child) {
914
915       // We want to exec the launcher.  Get its pre-remembered path.
916       path = VG_(name_of_launcher);
917       // VG_(name_of_launcher) should have been acquired by m_main at
918       // startup.
919       vg_assert(path);
920
921       launcher_basename = VG_(strrchr)(path, '/');
922       if (launcher_basename == NULL || launcher_basename[1] == 0) {
923          launcher_basename = path;  // hmm, tres dubious
924       } else {
925          launcher_basename++;
926       }
927
928    } else {
929       path = (Char*)ARG1;
930    }
931
932    // Set up the child's environment.
933    //
934    // Remove the valgrind-specific stuff from the environment so the
935    // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.  
936    // This is done unconditionally, since if we are tracing the child,
937    // the child valgrind will set up the appropriate client environment.
938    // Nb: we make a copy of the environment before trying to mangle it
939    // as it might be in read-only memory (this was bug #101881).
940    //
941    // Then, if tracing the child, set VALGRIND_LIB for it.
942    //
943    if (ARG3 == 0) {
944       envp = NULL;
945    } else {
946       envp = VG_(env_clone)( (Char**)ARG3 );
947       if (envp == NULL) goto hosed;
948       VG_(env_remove_valgrind_env_stuff)( envp );
949    }
950
951    if (trace_this_child) {
952       // Set VALGRIND_LIB in ARG3 (the environment)
953       VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
954    }
955
956    // Set up the child's args.  If not tracing it, they are
957    // simply ARG2.  Otherwise, they are
958    //
959    // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
960    //
961    // except that the first VG_(args_for_valgrind_noexecpass) args
962    // are omitted.
963    //
964    if (!trace_this_child) {
965       argv = (Char**)ARG2;
966    } else {
967       vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
968       vg_assert( VG_(args_for_valgrind_noexecpass) 
969                    <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
970       /* how many args in total will there be? */
971       // launcher basename
972       tot_args = 1;
973       // V's args
974       tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
975       tot_args -= VG_(args_for_valgrind_noexecpass);
976       // name of client exe
977       tot_args++;
978       // args for client exe, skipping [0]
979       arg2copy = (Char**)ARG2;
980       if (arg2copy && arg2copy[0]) {
981          for (i = 1; arg2copy[i]; i++)
982             tot_args++;
983       }
984       // allocate
985       argv = VG_(malloc)( "syswrap-aix5.pre_sys_execve.1",
986                           (tot_args+1) * sizeof(HChar*) );
987       if (argv == 0) goto hosed;
988       // copy
989       j = 0;
990       argv[j++] = launcher_basename;
991       for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
992          if (i < VG_(args_for_valgrind_noexecpass))
993             continue;
994          argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
995       }
996       argv[j++] = (Char*)ARG1;
997       if (arg2copy && arg2copy[0])
998          for (i = 1; arg2copy[i]; i++)
999             argv[j++] = arg2copy[i];
1000       argv[j++] = NULL;
1001       // check
1002       vg_assert(j == tot_args+1);
1003    }
1004
1005    /* restore the DATA rlimit for the child */
1006    VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1007
1008    /*
1009       Set the signal state up for exec.
1010
1011       We need to set the real signal state to make sure the exec'd
1012       process gets SIG_IGN properly.
1013
1014       Also set our real sigmask to match the client's sigmask so that
1015       the exec'd child will get the right mask.  First we need to
1016       clear out any pending signals so they they don't get delivered,
1017       which would confuse things.
1018
1019       XXX This is a bug - the signals should remain pending, and be
1020       delivered to the new process after exec.  There's also a
1021       race-condition, since if someone delivers us a signal between
1022       the sigprocmask and the execve, we'll still get the signal. Oh
1023       well.
1024    */
1025    {
1026       vki_sigset_t allsigs;
1027       vki_siginfo_t info;
1028
1029       for (i = 1; i < VG_(max_signal); i++) {
1030          struct vki_sigaction sa;
1031          VG_(do_sys_sigaction)(i, NULL, &sa);
1032          if (sa.ksa_handler == VKI_SIG_IGN)
1033             VG_(sigaction)(i, &sa, NULL);
1034          else {
1035             sa.ksa_handler = VKI_SIG_DFL;
1036             VG_(sigaction)(i, &sa, NULL);
1037          }
1038       }
1039
1040       VG_(sigfillset)(&allsigs);
1041       while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
1042          ;
1043
1044       VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
1045    }
1046
1047    if (0) {
1048       Char **cpp;
1049       VG_(printf)("exec: %s\n", path);
1050       for (cpp = argv; cpp && *cpp; cpp++)
1051          VG_(printf)("argv: %s\n", *cpp);
1052       if (0)
1053          for (cpp = envp; cpp && *cpp; cpp++)
1054             VG_(printf)("env: %s\n", *cpp);
1055    }
1056
1057    SET_STATUS_from_SysRes( 
1058       VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp) 
1059    );
1060
1061    /* If we got here, then the execve failed.  We've already made way
1062       too much of a mess to continue, so we have to abort. */
1063   hosed:
1064    vg_assert(FAILURE);
1065    VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n",
1066                 ARG1, (Char*)ARG1, ARG2, ARG3, ERR);
1067    VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
1068                             "execve() failing, so I'm dying.\n");
1069    VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
1070                             "or work out how to recover.\n");
1071    VG_(exit)(101);
1072 }
1073
1074 PRE(sys_finfo)
1075 {
1076    PRINT("finfo ( %#lx(%s), %ld, %#lx, %ld )",
1077           ARG1,(Char*)ARG1, ARG2, ARG3, ARG4);
1078    PRE_REG_READ4(int, "finfo", 
1079                       char*, Path1, int, cmd, void*, buffer, int, length);
1080    PRE_MEM_RASCIIZ( "finfo(Path1)", ARG1 );
1081    PRE_MEM_WRITE( "finfo(buffer)", ARG3, ARG4 );
1082 }
1083 POST(sys_finfo)
1084 {
1085    POST_MEM_WRITE( ARG3, ARG4 );
1086 }
1087
1088 PRE(sys_fstatfs)
1089 {
1090    PRINT("sys_fstatfs ( %ld, %#lx )", ARG1, ARG2);
1091    PRE_REG_READ2(UWord, "fstatfs", UWord, fd, struct statfs *, buf);
1092    PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct statfs) );
1093 }
1094 POST(sys_fstatfs)
1095 {
1096    POST_MEM_WRITE( ARG2, sizeof(struct statfs) );
1097 }
1098
1099 PRE(sys_fstatx)
1100 {
1101    PRINT("fstatx ( %ld, %#lx, %ld, %ld )", ARG1, ARG2, ARG3, ARG4 );
1102    PRE_REG_READ4(Word, "fstatx", UWord, fd, void*, buf,
1103                                  UWord, len, UWord, cmd);
1104    PRE_MEM_WRITE( "fstatx(buf)", ARG2, ARG3 );
1105 }
1106 POST(sys_fstatx)
1107 {
1108    POST_MEM_WRITE( ARG2, ARG3 );
1109 }
1110
1111 PRE(sys_fsync)
1112 {
1113    PRINT("fsync ( %ld )", ARG1);
1114    PRE_REG_READ1(int, "fsync", int, fd);
1115 }
1116
1117 PRE(sys_getdirent)
1118 {
1119    *flags |= SfMayBlock;
1120    /* this is pretty much like 'read':
1121       getdirent(fd, buffer, nbytes) -> # actually read */
1122    PRINT("getdirent ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
1123    PRE_REG_READ3(Word, "getdirent", UWord, fd, UChar*, buf, UWord, count);
1124    PRE_MEM_WRITE( "getdirent(buf)", ARG2, ARG3 );
1125 }
1126 POST(sys_getdirent)
1127 {
1128    vg_assert(SUCCESS);
1129    POST_MEM_WRITE( ARG2, RES );
1130 }
1131
1132 PRE(sys_getdirent64)
1133 {
1134    /* same as getdirent, from our point of view? */
1135    *flags |= SfMayBlock;
1136    /* this is pretty much like 'read':
1137       getdirent(fd, buffer, nbytes) -> # actually read */
1138    PRINT("getdirent64 ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
1139    PRE_REG_READ3(Word, "getdirent64", UWord, fd, UChar*, buf, UWord, count);
1140    PRE_MEM_WRITE( "getdirent64(buf)", ARG2, ARG3 );
1141 }
1142 POST(sys_getdirent64)
1143 {
1144    vg_assert(SUCCESS);
1145    POST_MEM_WRITE( ARG2, RES );
1146 }
1147
1148 PRE(sys_getdomainname)
1149 {
1150    PRINT("getdomainname ( %#lx, %ld )", ARG1, ARG2 );
1151    PRE_MEM_WRITE( "getdomainname(buf)", ARG1, ARG2 );
1152 }
1153 POST(sys_getdomainname)
1154 {
1155    POST_MEM_WRITE( ARG1, ARG2 );
1156 }
1157
1158 PRE(sys_getgidx)
1159 {
1160    PRINT("getgidx ( %ld )", ARG1);
1161    PRE_REG_READ1(UInt, "getgidx", long, arg1);
1162 }
1163
1164 PRE(sys_getgroups)
1165 {
1166    PRINT("getgroups ( %ld, %#lx )", ARG1, ARG2);
1167    PRE_REG_READ2(long, "getgroups", int, size, gid_t *, list);
1168    if (ARG1 > 0)
1169       PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(gid_t) );
1170 }
1171 POST(sys_getgroups)
1172 {
1173    vg_assert(SUCCESS);
1174    if (ARG1 > 0 && RES > 0)
1175       POST_MEM_WRITE( ARG2, RES * sizeof(gid_t) );
1176 }
1177
1178 PRE(sys_gethostname)
1179 {
1180    PRINT("gethostname ( %#lx, %ld )", ARG1, ARG2);
1181    PRE_MEM_WRITE( "gethostname(buf)", ARG1, ARG2 );
1182 }
1183 POST(sys_gethostname)
1184 {
1185    POST_MEM_WRITE( ARG1, ARG2 );
1186 }
1187
1188 PRE(sys_getpriv)
1189 {
1190    PRINT("getpriv (UNDOCUMENTED)(%ld, %#lx, %ld)", ARG1, ARG2, ARG3);
1191    PRE_REG_READ3(int, "getpriv", int, arg1, void*, arg2, int, arg3);
1192    PRE_MEM_WRITE( "getpriv(arg2)", ARG2, 8 );
1193 }
1194 POST(sys_getpriv)
1195 {
1196    if (ARG2)
1197       POST_MEM_WRITE(ARG2, 8);
1198 }
1199
1200 /* Note that this is used for both sys_getprocs and sys_getprocs64.  I
1201    think that's correct - from the man page, the calling conventions
1202    look identical. */
1203 PRE(sys_getprocs)
1204 {
1205    PRINT("getprocs ( %#lx, %ld, %#lx, %ld, %#lx, %ld )",
1206          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
1207    PRE_REG_READ6(int, "getprocs", 
1208                  void*, processbuffer, long, processize, 
1209                  void*, filebuffer, long, filesize,
1210                  void*, indexpointer, long, count);
1211
1212    /* (processbuffer, processsize, filebuffer, filesize,
1213       indexpointer, count) */
1214    PRE_MEM_READ( "getprocs(IndexPointer)", ARG5, sizeof(UInt) );
1215    if (ARG1)
1216       PRE_MEM_WRITE( "getprocs(ProcessBuffer)", ARG1, ARG2 * ARG6 );
1217    if (ARG3)
1218       PRE_MEM_WRITE( "getprocs(FileBuffer)", ARG3, ARG4 * ARG6 );
1219 }
1220 POST(sys_getprocs)
1221 {
1222    vg_assert(SUCCESS);
1223    if (ARG1)
1224       POST_MEM_WRITE( ARG1, ARG2 * ARG6 );
1225    if (ARG3)
1226       POST_MEM_WRITE( ARG3, ARG4 * ARG6 );
1227 }
1228
1229 PRE(sys_getrpid)
1230 {
1231    PRINT("getrpid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
1232    PRE_REG_READ3(long, "getrpid", long, arg1, long, arg2, long, arg3);
1233 }
1234
1235 PRE(sys_getsockopt)
1236 {
1237    PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )", 
1238          ARG1, ARG2, ARG3, ARG4, ARG5);
1239    PRE_REG_READ5(int, "getsockopt", int, socket, int, level, 
1240                                     int, optionname, 
1241                                     void*, optionval, int*, optionlen);
1242    if (ARG5) {
1243       PRE_MEM_READ( "getsockopt(optionlen)", ARG5, sizeof(UInt) );
1244       PRE_MEM_WRITE( "getsockopt(optionval)", ARG4, *(UInt*)ARG5 );
1245    }
1246 }
1247 POST(sys_getsockopt)
1248 {
1249    if (ARG5) {
1250       POST_MEM_WRITE( ARG5, sizeof(UInt) );
1251       POST_MEM_WRITE( ARG4, *(UInt*)ARG5 );
1252    }
1253 }
1254
1255 PRE(sys_gettimerid)
1256 {
1257    PRINT("gettimerid ( %ld, %ld )", ARG1, ARG2);
1258    PRE_REG_READ2(int, "gettimerid", int, timertype, int, notifytype);
1259 }
1260
1261 PRE(sys_getuidx)
1262 {
1263    PRINT("getuidx ( %ld )", ARG1);
1264    PRE_REG_READ1(UInt, "getuidx", UInt, arg1);
1265 }
1266
1267 PRE(sys_incinterval)
1268 {
1269    PRINT("incinterval ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
1270    PRE_REG_READ3(int, "incinterval", int, timerid, 
1271                       struct itimerstruc_t*, value,
1272                       struct itimerstruc_t*, ovalue);
1273    if (ARG2)
1274       PRE_MEM_READ( "incinterval(value)", 
1275                     ARG2, sizeof(struct itimerstruc_t));
1276    if (ARG3)
1277       PRE_MEM_WRITE( "incinterval(value)", 
1278                      ARG3, sizeof(struct itimerstruc_t));
1279 }
1280 POST(sys_incinterval)
1281 {
1282    if (ARG3)
1283       POST_MEM_WRITE( ARG3, sizeof(struct itimerstruc_t));
1284 }
1285
1286 PRE(sys_kfcntl)
1287 {
1288    *flags |= SfMayBlock;
1289    switch (ARG2) {
1290       // These ones ignore ARG3.
1291       case F_GETFD:
1292       case F_GETFL:
1293       case F_GETOWN:
1294          PRINT("kfcntl ( %ld, %ld )", ARG1,ARG2);
1295          PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1296          break;
1297
1298       // These ones use ARG3 as "arg".
1299       case F_DUPFD:
1300       case F_SETFD:
1301       case F_SETFL:
1302       case F_SETOWN:
1303          PRINT("kfcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1304          PRE_REG_READ3(long, "fcntl",
1305                        unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1306          break;
1307
1308       // These ones use ARG3 as "lock".
1309 #     if !defined(VGP_ppc64_aix5)
1310       case F_GETLK:
1311       case F_SETLK:
1312       case F_SETLKW:
1313 #     endif
1314       case F_GETLK64:
1315       case F_SETLK64:
1316       case F_SETLKW64:
1317          PRINT("kfcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1318          PRE_REG_READ3(long, "fcntl",
1319                        unsigned int, fd, unsigned int, cmd,
1320                        struct flock64 *, lock);
1321          if (ARG3 && (ARG2 == F_GETLK || ARG2 == F_GETLK64))
1322             PRE_MEM_READ( "kfcntl(F_GETLK)", ARG3, sizeof(struct flock64) );
1323          break;
1324    }
1325 }
1326 POST(sys_kfcntl)
1327 {
1328   //  if (ARG2 == VKI_F_DUPFD) {
1329   //   if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1330   //    VG_(close)(RES);
1331   //    SET_STATUS_Failure( VKI_EMFILE );
1332   //  } else {
1333   //    if (VG_(clo_track_fds))
1334   //    record_fd_open_named(tid, RES);
1335   //  }
1336   // }
1337    if (ARG3 && (ARG2 == F_GETLK || ARG2 == F_GETLK64))
1338       POST_MEM_WRITE( ARG3, sizeof(struct flock64) );
1339 }
1340
1341 /* COG; can this be moved inside the pre-handler? */
1342 static vki_sigset_t fork_saved_mask; 
1343 PRE(sys_kfork) /* COPY OF GENERIC */
1344 {
1345    vki_sigset_t mask;
1346
1347    PRINT("kfork ( )");
1348    PRE_REG_READ0(long, "fork");
1349
1350    /* Block all signals during fork, so that we can fix things up in
1351       the child without being interrupted. */
1352    VG_(sigfillset)(&mask);
1353    VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
1354
1355    VG_(do_atfork_pre)(tid);
1356
1357    SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
1358
1359    if (SUCCESS && RES == 0) {
1360       /* child */
1361       VG_(do_atfork_child)(tid);
1362
1363       /* restore signal mask */
1364       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
1365
1366       /* If --child-silent-after-fork=yes was specified, set the
1367          logging file descriptor to an 'impossible' value.  This is
1368          noticed by send_bytes_to_logging_sink in m_libcprint.c, which
1369          duly stops writing any further logging output. */
1370       if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
1371          VG_(clo_log_fd) = -1;
1372    } 
1373    else 
1374    if (SUCCESS && RES > 0) {
1375       /* parent */
1376       VG_(do_atfork_parent)(tid);
1377
1378       PRINT("   fork: process %d created child %lu\n", VG_(getpid)(), RES);
1379
1380       /* restore signal mask */
1381       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
1382    }
1383 }
1384
1385 PRE(sys_kftruncate)
1386 {
1387    PRINT("kftruncate (BOGUS HANDLER)");
1388 }
1389
1390 PRE(sys_kgetsidx)
1391 {
1392    PRINT("kgetsidx ( %ld )", ARG1);
1393    PRE_REG_READ1(Word, "kgetsidx", Word, arg1);
1394 }
1395
1396 PRE(sys_kill)
1397 {
1398    PRINT("kill ( %ld, %ld )", ARG1, ARG2);
1399    PRE_REG_READ2(int, "kill", int, pid, int, signal);
1400 }
1401
1402 PRE(sys_kioctl)
1403 {
1404    *flags |= SfMayBlock;
1405    PRINT("kioctl ( %ld, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4);
1406    PRE_REG_READ4(Word, "ioctl", Word, fd, 
1407                                 Word, command, Word, arg, Word, ext);
1408    switch (ARG2 /* request */) {
1409       case 0x5800/*TXISATTY*/:
1410       case 0x5801/*TXTTYNAME*/:
1411          break;
1412       case 0x412:/*no idea what any of these are*/
1413       case 0x430:
1414       case 0x431:
1415       case 0x432:
1416       case 0x441:
1417       case 0x442:
1418       case 0x462:
1419       case 0x480:
1420       case 0x482:
1421       case 0x738:
1422       case 0x736:
1423       case 0x73B:
1424       case 0x73C:
1425       case 0x73D:
1426       case 0x73E:
1427       case 0x5401:
1428       case 0x5403:
1429       case 0xFF01/*no_idea_at_all_what_this_is*/:
1430           break;
1431       /* We don't have any specific information on it, so
1432          try to do something reasonable based on direction and
1433          size bits.
1434
1435          According to Simon Hausmann, _IOC_READ means the kernel
1436          writes a value to the ioctl value passed from the user
1437          space and the other way around with _IOC_WRITE. */
1438       default: {
1439          UInt dir  = _VKI_IOC_DIR(ARG2);
1440          UInt size = _VKI_IOC_SIZE(ARG2);
1441          if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) {
1442             /* 
1443              * Be very lax about ioctl handling; the only
1444              * assumption is that the size is correct. Doesn't
1445              * require the full buffer to be initialized when
1446              * writing.  Without this, using some device
1447              * drivers with a large number of strange ioctl
1448              * commands becomes very tiresome.
1449              */
1450          } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
1451             static Int moans = 5;
1452             if (moans > 0 && !VG_(clo_xml)) {
1453                moans--;
1454                VG_(message)(Vg_UserMsg, 
1455                             "Warning: noted but unhandled ioctl 0x%lx"
1456                             " with no size/direction hints\n",
1457                             ARG2); 
1458                VG_(message)(Vg_UserMsg, 
1459                             "   This could cause spurious value errors"
1460                             " to appear.\n");
1461                VG_(message)(Vg_UserMsg, 
1462                             "   See README_MISSING_SYSCALL_OR_IOCTL for "
1463                             "guidance on writing a proper wrapper.\n" );
1464             }
1465          } else {
1466             if ((dir & _VKI_IOC_WRITE) && size > 0)
1467                PRE_MEM_READ( "ioctl(generic)", ARG3, size);
1468             if ((dir & _VKI_IOC_READ) && size > 0)
1469                PRE_MEM_WRITE( "ioctl(generic)", ARG3, size);
1470          }
1471          break;
1472       }
1473    } /* switch */ 
1474 }
1475 POST(sys_kioctl)
1476 {
1477    switch (ARG2 /*request*/) {
1478       case 0xFF01:
1479          /* 100% kludge.  I have no idea what this ioctl is.  IOCINFO
1480             ?  But at a guess I'd say it returns some kind of info
1481             from the kernel. */
1482          if (ARG3) POST_MEM_WRITE(ARG3, 16);
1483          break;
1484       case 0x738: /* Shows up in MPI applications. */
1485          if (ARG3) POST_MEM_WRITE(ARG3, 4*sizeof(Word));
1486          break;
1487       case 0x736: /* Shows up in MPI applications. */
1488       case 0x73B: /* Shows up in MPI applications. */
1489       case 0x73C: /* Shows up in MPI applications. */
1490          if (ARG3) POST_MEM_WRITE(ARG3, 16);
1491          /* in fact only 4 needed, but being conservative */
1492          break;
1493
1494       case 0x5401:
1495         /* some kind of tty thing */
1496         if (ARG3) POST_MEM_WRITE(ARG3, 32);
1497         break;
1498
1499       case 0x5801/*TXTTYNAME*/:
1500         /* who knows if this is right.  Presumably an ascii string is
1501            written into the buffer specified by ARG3, but how long is
1502            that buffer? */
1503         if (ARG3) POST_MEM_WRITE(ARG3, 16);
1504         break;
1505
1506       case 0x412:
1507       case 0x430:
1508       case 0x431:
1509       case 0x432:
1510       case 0x441:
1511       case 0x442:
1512       case 0x462:
1513       case 0x480:
1514       case 0x482:
1515       case 0x73D:
1516       case 0x73E:
1517       case 0x5800/*TXISATTY*/:
1518       case 0x5403:
1519          break;
1520       /* We don't have any specific information on it, so
1521          try to do something reasonable based on direction and
1522          size bits.
1523
1524          According to Simon Hausmann, _IOC_READ means the kernel
1525          writes a value to the ioctl value passed from the user
1526          space and the other way around with _IOC_WRITE. */
1527       default: {
1528          UInt dir  = _VKI_IOC_DIR(ARG2);
1529          UInt size = _VKI_IOC_SIZE(ARG2);
1530          if (size > 0 && (dir & _VKI_IOC_READ)
1531              && RES == 0 
1532              && ARG3 != (Addr)NULL)
1533             POST_MEM_WRITE(ARG3, size);
1534          break;
1535       }
1536    }
1537 }
1538
1539 PRE(sys_klseek)
1540 {
1541    PRINT("klseek ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
1542    PRE_REG_READ4(long, "klseek", 
1543                  long, fd, long, offset, long, whence, void*, arg4);
1544    /* XXX: looks like 4th arg is a pointer to something.  Is it
1545       read or written by the kernel? */
1546 }
1547
1548 PRE(sys_knlist)
1549 {
1550    PRINT("knlist (BOGUS HANDLER)");
1551 }
1552
1553 PRE(sys_kpread)
1554 {
1555    *flags |= SfMayBlock;
1556    PRINT("sys_kpread ( %ld, %#lx, %llu, %lld )",
1557          ARG1, ARG2, (ULong)ARG3, (ULong)ARG4);
1558    PRE_REG_READ4(ssize_t, "kpread",
1559                  unsigned int, fd, char *, buf,
1560                  vki_size_t, count, long, offset);
1561    PRE_MEM_WRITE( "kpread(buf)", ARG2, ARG3 );
1562 }
1563 POST(sys_kpread)
1564 {
1565    vg_assert(SUCCESS);
1566    if (RES > 0) {
1567       POST_MEM_WRITE( ARG2, RES );
1568    }
1569 }
1570
1571 PRE(sys_kread)
1572 {
1573    *flags |= SfMayBlock;
1574    PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
1575    PRE_REG_READ3(ssize_t, "read",
1576                  unsigned int, fd, char *, buf, vki_size_t, count);
1577    //zz   if (!ML_(fd_allowed)(ARG1, "read", tid, False))
1578    //zz      SET_STATUS_Failure( VKI_EBADF );
1579    //zz   else
1580       PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
1581 }
1582 POST(sys_kread)
1583 {
1584   vg_assert(SUCCESS);
1585   POST_MEM_WRITE( ARG2, RES );
1586 }
1587
1588 PRE(sys_kreadv)
1589 {
1590    Int i;
1591    struct vki_iovec * vec;
1592    *flags |= SfMayBlock;
1593    /* ssize_t readvx ( int fd, struct iovec*, int iovCount, int extension ) */
1594    PRINT("kreadv ( %ld, %#lx, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4);
1595    PRE_REG_READ4(ssize_t, "kreadv",
1596                  unsigned long, fd, const struct iovec *, vector,
1597                  unsigned long, iovCount, unsigned long, extension);
1598    //zz   if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
1599    //zz      SET_STATUS_Failure( VKI_EBADF );
1600    //zz   } else {
1601       PRE_MEM_READ( "kreadv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
1602       if (ARG2 != 0) {
1603          /* ToDo: don't do any of the following if the vector is invalid */
1604          vec = (struct vki_iovec *)ARG2;
1605          for (i = 0; i < (Int)ARG3; i++)
1606             PRE_MEM_WRITE( "kreadv(vector[...])",
1607                            (Addr)vec[i].iov_base, vec[i].iov_len );
1608       }
1609    //zz }
1610 }
1611 POST(sys_kreadv)
1612 {
1613    vg_assert(SUCCESS);
1614    if (RES > 0) {
1615       Int i;
1616       struct vki_iovec * vec = (struct vki_iovec *)ARG2;
1617       Int remains = RES;
1618
1619       /* RES holds the number of bytes read. */
1620       for (i = 0; i < (Int)ARG3; i++) {
1621          Int nReadThisBuf = vec[i].iov_len;
1622          if (nReadThisBuf > remains) nReadThisBuf = remains;
1623          POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
1624          remains -= nReadThisBuf;
1625          if (remains < 0) VG_(core_panic)("readv: remains < 0");
1626       }
1627    }
1628 }
1629
1630 PRE(sys_kthread_ctl)
1631 {
1632    *flags |= SfMayBlock;
1633    PRINT("kthread_ctl (BOGUS HANDLER)");
1634 }
1635
1636 PRE(sys_ktruncate)
1637 {
1638    PRINT("ktruncate( %#lx(%s), %lx, %lx )", ARG1,(Char*)ARG1, ARG2, ARG3 );
1639    PRE_REG_READ3(int, "ktruncate", char*, path, long, arg2, long, arg3 );
1640    PRE_MEM_RASCIIZ( "ktruncate(path)", ARG1 );
1641 }
1642
1643 PRE(sys_kwaitpid)
1644 {
1645    /* Note: args 1 and 2 (status, pid) opposite way round
1646       from generic handler */
1647    *flags |= SfMayBlock;
1648    PRINT("kwaitpid ( %#lx, %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
1649    PRE_REG_READ3(long, "waitpid", 
1650                  unsigned int *, status, int, pid, int, options);
1651
1652    if (ARG1 != (Addr)NULL)
1653       PRE_MEM_WRITE( "kwaitpid(status)", ARG1, sizeof(int) );
1654 }
1655 POST(sys_kwaitpid)
1656 {
1657    if (ARG1 != (Addr)NULL)
1658       POST_MEM_WRITE( ARG1, sizeof(int) );
1659 }
1660
1661 PRE(sys_kwrite)
1662 {
1663    //zz   Bool ok;
1664    *flags |= SfMayBlock;
1665    PRINT("sys_kwrite ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
1666    PRE_REG_READ3(ssize_t, "kwrite",
1667                  unsigned int, fd, const char *, buf, vki_size_t, count);
1668    /* check to see if it is allowed.  If not, try for an exemption from
1669       --sim-hints=enable-outer (used for self hosting). */
1670    //zz   ok = ML_(fd_allowed)(ARG1, "write", tid, False);
1671    //zz   if (!ok && ARG1 == 2/*stderr*/ 
1672    //zz           && VG_(strstr)(VG_(clo_sim_hints),"enable-outer"))
1673    //zz      ok = True;
1674    //zz   if (!ok)
1675    //zz      SET_STATUS_Failure( VKI_EBADF );
1676    //zz   else
1677       PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
1678 }
1679
1680 PRE(sys_kwritev)
1681 {
1682    PRINT("kwritev (BOGUS HANDLER)");
1683 }
1684
1685 PRE(sys_listen)
1686 {
1687    PRINT("listen (BOGUS HANDLER)");
1688 }
1689
1690 PRE(sys_loadbind)
1691 {
1692    PRINT("loadbind( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
1693    PRE_REG_READ3(int, "loadbind", int, flag,
1694                       void*, ExportPointer, void*, ImportPointer);
1695 }
1696
1697 PRE(sys_loadquery)
1698 {
1699    /* loadquery ( int flags, void* buffer, unsigned int bufferlength ) */
1700    PRINT("loadquery ( %#lx, %#lx, %ld )", ARG1, ARG2, ARG3);
1701    PRE_MEM_WRITE( "loadquery(buf)", ARG2, ARG3 );
1702 }
1703 POST(sys_loadquery)
1704 {
1705    vg_assert(SUCCESS);
1706    POST_MEM_WRITE( ARG2, ARG3 );
1707 }
1708
1709 PRE(sys_lseek)
1710 {
1711    PRINT("lseek (%ld, %ld, %ld)", ARG1, ARG2, ARG3);
1712    PRE_REG_READ3(long, "lseek", long, fd, long, offset, long, whence);
1713 }
1714
1715 PRE(sys_mkdir)
1716 {
1717    PRINT("mkdir (%#lx(%s), %#lx)", ARG1,(Char*)ARG1, ARG2);
1718    PRE_REG_READ2(int, "mkdir", char*, path, int, mode);
1719    PRE_MEM_RASCIIZ( "mkdir(path)", ARG1 );
1720 }
1721
1722 PRE(sys_mmap)
1723 {
1724    PRINT("mmap ( %#lx, %ld, %#lx, %#lx, %ld, %ld )",
1725          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1726    PRE_REG_READ6(void*, "mmap", void*, addr, int, len, 
1727                         int, prot, int, flags, int, fd, int, off);
1728 }
1729 POST(sys_mmap)
1730 {
1731    vg_assert(SUCCESS);
1732    Addr  addr  = (Addr)RES;
1733    UWord len   = (UWord)ARG2;
1734    UWord prot  = (UWord)ARG3;
1735    UWord flags = (UWord)ARG4;
1736    Bool r = (prot & VKI_PROT_READ) > 0;
1737    Bool w = (prot & VKI_PROT_WRITE) > 0;
1738    Bool x = (prot & VKI_PROT_EXEC) > 0;
1739    VG_TRACK( new_mem_mmap, addr, len, r,w,x, 0/*di_handle*/ );
1740    Bool d = VG_(am_notify_client_mmap)( addr, len, prot, flags, 
1741                                         0/*fake fd*/, 0/*fake offset*/);
1742    if (d) 
1743       VG_(discard_translations)( addr, len, "POST(sys_mmap)" );
1744 }
1745
1746 PRE(sys_mntctl)
1747 {
1748    PRINT("mntctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 );
1749    PRE_REG_READ3(long, "mntctl", long, command, long, size, char*, buffer);
1750    PRE_MEM_WRITE( "mntctl(buffer)", ARG3, ARG2 );
1751 }
1752 POST(sys_mntctl)
1753 {
1754    vg_assert(SUCCESS);
1755    if (RES == 0) {
1756       /* Buffer too small.  First word is the real required size. */
1757       POST_MEM_WRITE( ARG3, sizeof(Word) );
1758    } else {
1759       /* RES is the number of struct vmount's written to the buf.  But
1760          these are variable length and to find the end would require
1761          inspecting each in turn.  So be simple and just mark the
1762          entire buffer as defined. */
1763       POST_MEM_WRITE( ARG3, ARG2 );
1764    }
1765 }
1766
1767 PRE(sys_mprotect)
1768 {
1769    PRINT("mprotect (BOGUS HANDLER)( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
1770    PRE_REG_READ3(int, "mprotect", void*, addr, long, len, long, prot);
1771 }
1772 POST(sys_mprotect)
1773 {
1774    Bool d;
1775    vg_assert(SUCCESS);
1776    Addr  addr = ARG1;
1777    UWord len  = ARG2;
1778    UWord prot = ARG3;
1779    d = VG_(am_notify_mprotect)( addr, len, prot );
1780    if (d)
1781       VG_(discard_translations)( addr, len, "POST(sys_mprotect)" );
1782 }
1783
1784 PRE(sys_munmap)
1785 {
1786    PRINT("munmap ( %#lx, %ld )", ARG1, ARG2);
1787    PRE_REG_READ2(int, "munmap", void*, addr, long, len);
1788 }
1789 POST(sys_munmap)
1790 {
1791    Bool d;
1792    vg_assert(SUCCESS);
1793    Addr  addr = ARG1;
1794    UWord len  = ARG2;
1795    VG_TRACK( die_mem_munmap, addr, len );
1796    d = VG_(am_notify_munmap)( addr, len );
1797    if (d)
1798       VG_(discard_translations)( addr, len, "POST(sys_munmap)" );
1799 }
1800
1801 PRE(sys_naccept)
1802 {
1803    PRINT("naccept (%ld, %#lx, %#lx)", ARG1, ARG2, ARG3);
1804    PRE_REG_READ3(int, "naccept", int, socket, char*, addr, int*, addrlen);
1805    PRE_MEM_READ( "naccept(addrlen)", ARG3, sizeof(UInt) );
1806    PRE_MEM_WRITE( "naccept(addr)", ARG2, *(UInt*)ARG3 );
1807 }
1808 POST(sys_naccept)
1809 {
1810    POST_MEM_WRITE( ARG3, sizeof(UInt) );
1811    POST_MEM_WRITE( ARG2, *(UInt*)ARG3 );
1812 }
1813
1814 PRE(sys_ngetpeername)
1815 {
1816    PRINT("ngetpeername ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
1817    PRE_REG_READ3(int, "ngetpeername", int, fd, char*, name, int*, namelen);
1818    PRE_MEM_READ( "ngetpeername(namelen)", ARG3, sizeof(UInt) );
1819    PRE_MEM_WRITE( "ngetpeername(name)", ARG2, *(UInt*)ARG3 );
1820 }
1821 POST(sys_ngetpeername)
1822 {
1823    POST_MEM_WRITE( ARG3, sizeof(UInt) );
1824    POST_MEM_WRITE( ARG2, *(UInt*)ARG3 );
1825 }
1826
1827 PRE(sys_ngetsockname)
1828 {
1829    PRINT("ngetsockname ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
1830    PRE_REG_READ3(int, "ngetsockname", int, fd, char*, name, int*, namelen);
1831    PRE_MEM_READ( "ngetsockname(namelen)", ARG3, sizeof(UInt) );
1832    PRE_MEM_WRITE( "ngetsockname(name)", ARG2, *(UInt*)ARG3 );
1833 }
1834 POST(sys_ngetsockname)
1835 {
1836    POST_MEM_WRITE( ARG3, sizeof(UInt) );
1837    POST_MEM_WRITE( ARG2, *(UInt*)ARG3 );
1838 }
1839
1840 PRE(sys_nrecvfrom)
1841 {
1842    *flags |= SfMayBlock;
1843    PRINT("nrecvfrom ( %ld, %#lx, %ld, %ld, %#lx, %#lx )",
1844          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
1845    PRE_REG_READ6(ssize_t, "nrecvfrom",
1846                  int, s, void*, buf, size_t, len, int, flags,
1847                  void*, from, UInt*, fromlen);
1848    PRE_MEM_WRITE( "nrecvfrom(buf)", ARG2, ARG3 );
1849    if (ARG5) {
1850       PRE_MEM_READ( "nrecvfrom(fromlen)", ARG6, sizeof(UInt) );
1851       PRE_MEM_WRITE( "nrecvfrom(from)", ARG5, *(UInt*)ARG6 );
1852    }
1853 }
1854 POST(sys_nrecvfrom)
1855 {
1856    POST_MEM_WRITE( ARG2, RES );
1857    if (ARG5) {
1858       POST_MEM_WRITE(ARG6, sizeof(UInt));
1859       POST_MEM_WRITE(ARG5, *(UInt*)ARG6);
1860    }
1861 }
1862
1863 PRE(sys_nrecvmsg)
1864 {
1865    *flags |= SfMayBlock;
1866    PRINT("nrecvmsg(BOGUS HANDLER)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
1867    PRE_REG_READ3(long, "nrecvmsg", long, arg1, void*, arg2, long, arg3);
1868 }
1869
1870 PRE(sys_nsendmsg)
1871 {
1872    *flags |= SfMayBlock;
1873    PRINT("nsendmsg(BOGUS HANDLER)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
1874 }
1875
1876 PRE(sys_open) /* XXX CoG */
1877 {
1878    //zz   HChar  name[30];
1879    //zz   SysRes sres;
1880
1881    if (ARG2 & VKI_O_CREAT) {
1882       // 3-arg version
1883       PRINT("sys_open ( %#lx(%s), %#lx, %ld )",ARG1,(Char*)ARG1,ARG2,ARG3);
1884       PRE_REG_READ3(long, "open",
1885                     const char *, filename, int, flags, int, mode);
1886    } else {
1887       // 2-arg version
1888       PRINT("sys_open ( %#lx(%s), %#lx )",ARG1,(Char*)ARG1,ARG2);
1889       PRE_REG_READ2(long, "open",
1890                     const char *, filename, int, flags);
1891    }
1892    PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
1893
1894    //zz   /* Handle the case where the open is of /proc/self/cmdline or
1895    //zz      /proc/<pid>/cmdline, and just give it a copy of the fd for the
1896    //zz      fake file we cooked up at startup (in m_main).  Also, seek the
1897    //zz      cloned fd back to the start. */
1898    //zz
1899    //zz   VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
1900    //zz   if (ML_(safe_to_deref)( (void*)ARG1, 1 )
1901    //zz       && (VG_(strcmp)((Char *)ARG1, name) == 0 
1902    //zz           || VG_(strcmp)((Char *)ARG1, "/proc/self/cmdline") == 0)) {
1903    //zz      sres = VG_(dup)( VG_(cl_cmdline_fd) );
1904    //zz      SET_STATUS_from_SysRes( sres );
1905    //zz      if (!sres.isError) {
1906    //zz         OffT off = VG_(lseek)( sres.res, 0, VKI_SEEK_SET );
1907    //zz         if (off < 0)
1908    //zz            SET_STATUS_Failure( VKI_EMFILE );
1909    //zz      }
1910    //zz      return;
1911    //zz   }
1912
1913    /* Otherwise handle normally */
1914    *flags |= SfMayBlock;
1915 }
1916 POST(sys_open)
1917 {
1918    vg_assert(SUCCESS);
1919    //zz   if (!ML_(fd_allowed)(RES, "open", tid, True)) {
1920    //zz      VG_(close)(RES);
1921    //zz      SET_STATUS_Failure( VKI_EMFILE );
1922    //zz   } else {
1923    //zz      if (VG_(clo_track_fds))
1924    //zz         ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
1925    //zz   }
1926 }
1927
1928 PRE(sys_pipe)
1929 {
1930    PRINT("sys_pipe ( %#lx )", ARG1);
1931    PRE_REG_READ1(int, "pipe", int *, filedes);
1932    PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) );
1933 }
1934 POST(sys_pipe)
1935 {
1936   //zz   Int *p = (Int *)ARG1;
1937
1938   //zz  if (!ML_(fd_allowed)(p[0], "pipe", tid, True) ||
1939   //zz      !ML_(fd_allowed)(p[1], "pipe", tid, True)) {
1940   //zz    VG_(close)(p[0]);
1941   //zz    VG_(close)(p[1]);
1942   //zz    SET_STATUS_Failure( VKI_EMFILE );
1943   //zz  } else {
1944     POST_MEM_WRITE( ARG1, 2*sizeof(int) );
1945     //zz    if (VG_(clo_track_fds)) {
1946     //zz      ML_(record_fd_open_nameless)(tid, p[0]);
1947     //zz      ML_(record_fd_open_nameless)(tid, p[1]);
1948     //zz    }
1949     //zz  }
1950 }
1951
1952 PRE(sys_privcheck)
1953 {
1954    PRINT("privcheck ( %ld )", ARG1);
1955    PRE_REG_READ1(int, "privcheck", int, arg1);
1956 }
1957
1958 PRE(sys_readlink)
1959 {
1960    PRINT("readlink ( 0x%lx(%s),0x%lx,%ld )", ARG1,(Char*)ARG1, ARG2, ARG3);
1961    PRE_REG_READ3(long, "readlink",
1962                  const char *, path, char *, buf, int, bufsiz);
1963    PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
1964    PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
1965 }
1966 POST(sys_readlink)
1967 {
1968    POST_MEM_WRITE( ARG2, RES + 1 );
1969 }
1970
1971 PRE(sys_recv)
1972 {
1973    *flags |= SfMayBlock;
1974    PRINT("recv ( %ld, %#lx, %ld, %ld )",
1975          ARG1, ARG2, ARG3, ARG4);
1976    PRE_REG_READ4(int, "recv", int, fd, void*, buf, int, len, int, flags);
1977    PRE_MEM_WRITE( "recv(buf)", ARG2, ARG3);
1978 }
1979 POST(sys_recv)
1980 {
1981    if (RES > 0)
1982       POST_MEM_WRITE(ARG2, RES);
1983 }
1984
1985 PRE(sys_rename)
1986 {
1987    *flags |= SfMayBlock;
1988    PRINT( "rename ( %#lx(%s), %#lx(%s) )", ARG1,(Char*)ARG1, ARG2,(Char*)ARG2 );
1989    PRE_REG_READ2(int, "rename", char*, frompath, char*, topath);
1990    PRE_MEM_RASCIIZ( "rename(frompath)", ARG1 );
1991    PRE_MEM_RASCIIZ( "rename(topath)", ARG2 );
1992 }
1993
1994 PRE(sys_sbrk)
1995 {
1996    PRINT("sbrk (BOGUS HANDLER)( %#lx )", ARG1);
1997    PRE_REG_READ1(long, "sbrk", long, arg1);
1998    /* After a zero sbrk, disallow aspacem from doing sbrk, since libc
1999       might rely on the value returned by this syscall. */
2000    /* 1 Oct 06: not currently used (aspacemgr-aix5.c ignores it) */
2001    VG_(am_aix5_sbrk_allowed) = toBool(ARG1 != 0);
2002    /* Disallow libc from moving the brk backwards as that might trash
2003       SkPreAlloc sections acquired by aspacem from previous uses of
2004       sbrk. */
2005    if (ARG1 < 0)
2006       ARG1 = 0;
2007    /* Do this as a sync syscall, so the sbrk_allowed flag gets turned
2008       back on ASAP.  Typically libc does sbrk(0) and then sbrk(x > 0)
2009       in quick succession.  Although surely it should hold some kind
2010       of lock at that point, else it cannot safely use the result from
2011       the first sbrk call to influence the second one? */
2012    *flags &= ~SfMayBlock;
2013 }
2014 POST(sys_sbrk)
2015 {
2016    vg_assert(SUCCESS);
2017    handle_sbrk(ARG1);
2018 }
2019
2020 PRE(sys_sched_get_priority_max)
2021 {
2022    PRINT("sched_get_priority_max ( %ld )", ARG1);
2023    PRE_REG_READ1(int, "sched_get_priority_max", int, arg1);
2024 }
2025
2026 PRE(sys_sem_destroy)
2027 {
2028    PRINT("sem_destroy ( %#lx )", ARG1);
2029    PRE_REG_READ1(int, "sem_destroy", sem_t*, sem);
2030    PRE_MEM_READ( "sem_destroy(sem)", ARG1, sizeof(sem_t) );
2031 }
2032
2033 PRE(sys_sem_init)
2034 {
2035    PRINT("sem_init ( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
2036    PRE_REG_READ3(int, "sem_init", sem_t*, sem, int, pshared, int, value);
2037    PRE_MEM_WRITE( "sem_init(sem)", ARG1, sizeof(sem_t) );
2038 }
2039 POST(sys_sem_init)
2040 {
2041    POST_MEM_WRITE( ARG1, sizeof(sem_t) );
2042 }
2043
2044 PRE(sys_sem_post)
2045 {
2046    PRINT("sem_post ( %#lx )", ARG1);
2047    PRE_REG_READ1(int, "sem_post", sem_t*, sem);
2048    PRE_MEM_READ("sem_post(sem)", ARG1, sizeof(sem_t));
2049 }
2050 POST(sys_sem_post)
2051 {
2052    POST_MEM_WRITE(ARG1, sizeof(sem_t));
2053 }
2054
2055 PRE(sys_send)
2056 {
2057    *flags |= SfMayBlock;
2058    PRINT("send (BOGUS HANDLER)( %ld, %#lx, %ld, %ld )", 
2059          ARG1, ARG2, ARG3, ARG4);
2060 }
2061
2062 PRE(sys_setgid)
2063 {
2064    PRINT("setgid ( %ld )", ARG1);
2065    PRE_REG_READ1(void, "setgid", int, uid);
2066 }
2067
2068 PRE(sys_setsockopt)
2069 {
2070    PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )", 
2071          ARG1,ARG2,ARG3,ARG4,ARG5 );
2072    PRE_REG_READ5(long, "setsockopt", 
2073                  long, socket, long, level, long, optionname, 
2074                  void*, optionvalue, long, optlen);
2075    if (ARG4)
2076       PRE_MEM_READ( "setsockopt(optionvalue)", ARG4, ARG5 );
2077 }
2078
2079 PRE(sys_setuid)
2080 {
2081    PRINT("setuid ( %ld )", ARG1);
2082    PRE_REG_READ1(void, "setuid", int, uid);
2083 }
2084
2085 static UWord get_shm_size ( Word shmid )
2086 {
2087    SysRes res;
2088    struct shmid_ds buf;
2089    vg_assert(__NR_AIX5_shmctl != __NR_AIX5_UNKNOWN);
2090    res = VG_(do_syscall3)(__NR_AIX5_shmctl, shmid, IPC_STAT, (UWord)&buf);
2091    if (0) 
2092       VG_(printf)("XXX: shm_size(%ld) = %ld %ld\n", shmid, res.res, res.err);
2093    if (res.isError) {
2094       if (0)
2095          VG_(printf)("XXX: shm_size(shmid = %ld): FAILED\n", shmid);
2096       return 0* 4096;
2097    } else {
2098       return buf.shm_segsz;
2099    }
2100    /* fails with 22 and 13 (22 = EINVAL, Invalid argument,
2101       13 = EACCES, Permission denied) */
2102    /* shmat (4, 0x0, 0x1800) --> Success(0x40000000)
2103       XXX: shm_size(4) = -1 22
2104       shmat: seg size = 0
2105       XXX: shm_size(4) = -1 22
2106
2107       shmat (5, 0x0, 0x1800) --> Success(0x50000000)
2108       XXX: shm_size(5) = -1 13
2109       shmat: seg size = 0
2110       XXX: shm_size(5) = -1 13
2111
2112       shmat (4, 0x0, 0x1800) --> Success(0x40000000)
2113       XXX: shm_size(4) = -1 22
2114       shmat: seg size = 0
2115       XXX: shm_size(4) = -1 22
2116    */
2117 }
2118 PRE(sys_shmat)
2119 {
2120    UWord segmentSize;
2121    /* void* shmat ( int shmid, const void* shmaddr, int flags ) */
2122    PRINT("shmat (%ld, %#lx, %#lx)", ARG1, ARG2, ARG3);
2123    PRE_REG_READ3(void*, "shmat", int, shmid, void*, shmaddr, int, flags);
2124    segmentSize = get_shm_size( ARG1 );
2125    if (0) VG_(printf)("shmat: seg size = %lu\n", segmentSize);
2126 }
2127 POST(sys_shmat)
2128 {
2129    UInt segmentSize;
2130    vg_assert(SUCCESS);
2131    vg_assert(RES != -1L);
2132    segmentSize = get_shm_size ( ARG1 );
2133    if ( segmentSize > 0 ) {
2134       UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
2135       Bool d;
2136
2137       if (ARG2 & SHM_RDONLY)
2138          prot &= ~VKI_PROT_WRITE;
2139
2140       d = VG_(am_notify_client_shmat)( RES, VG_PGROUNDUP(segmentSize), prot );
2141
2142       /* we don't distinguish whether it's read-only or
2143        * read-write -- it doesn't matter really. */
2144       VG_TRACK( new_mem_mmap, RES, segmentSize, True, True, False, 0/*di_handle*/ );
2145       if (d)
2146          VG_(discard_translations)( (Addr64)RES, 
2147                                     (ULong)VG_PGROUNDUP(segmentSize),
2148                                     "ML_(generic_POST_sys_shmat)" );
2149    }
2150 }
2151
2152 PRE(sys_shmctl)
2153 {
2154    PRINT("shmctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 );
2155    PRE_REG_READ3(int, "shmctl", int, shmid, int, command, void*, buffer);
2156    if (ARG3)
2157       PRE_MEM_WRITE( "shmctl(buffer)", ARG3, sizeof(struct shmid_ds) );
2158 }
2159 POST(sys_shmctl)
2160 {
2161    if ((ARG3) && ARG2 == IPC_STAT)
2162       POST_MEM_WRITE( ARG3, sizeof(struct shmid_ds) );
2163 }
2164
2165 PRE(sys_shmdt)
2166 {
2167    PRINT("shmdt ( %#lx )", ARG1);
2168    PRE_REG_READ1(long, "shmdt", void*, address);
2169 }
2170 POST(sys_shmdt)
2171 {
2172    NSegment const*const s = VG_(am_find_nsegment)(ARG1);
2173
2174    if (s != NULL) {
2175       Addr  s_start = s->start;
2176       SizeT s_len   = s->end+1 - s->start;
2177       Bool  d;
2178
2179       vg_assert(s->kind == SkShmC && s->start == ARG1);
2180
2181       d = VG_(am_notify_munmap)(s_start, s_len);
2182       /* s is now invalid; do not use after here */
2183       VG_TRACK( die_mem_munmap, s_start, s_len );
2184       if (d)
2185          VG_(discard_translations)( (Addr64)s_start,
2186                                     (ULong)s_len,
2187                                     "ML_(generic_POST_sys_shmdt)" );
2188    }
2189 }
2190
2191 PRE(sys_shmget)
2192 {
2193    PRINT("shmget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3 );
2194    PRE_REG_READ3(int, "shmget", key_t, key, size_t, size, int, shmFlag);
2195 }
2196
2197 PRE(sys_shutdown)
2198 {
2199    PRINT("shutdown (BOGUS HANDLER)");
2200 }
2201
2202 PRE(sys_sigcleanup)
2203 {
2204    PRINT("sigcleanup (UNDOCUMENTED)");
2205 }
2206
2207 PRE(sys_sigprocmask)
2208 {
2209    PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
2210    PRE_REG_READ3(long, "sigprocmask", 
2211                  int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
2212    if (ARG2 != 0)
2213       PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
2214    if (ARG3 != 0)
2215       PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
2216
2217    SET_STATUS_from_SysRes(
2218       VG_(do_sys_sigprocmask) ( tid, ARG1, (vki_sigset_t*)ARG2, 
2219                                            (vki_sigset_t*)ARG3 )
2220    );
2221
2222    if (SUCCESS)
2223      *flags |= SfPollAfter;
2224 }
2225 POST(sys_sigprocmask)
2226 {
2227    vg_assert(SUCCESS);
2228    if (RES == 0 && ARG3 != 0)
2229       POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2230 }
2231
2232 PRE(sys_socket)
2233 {
2234    PRINT("socket ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
2235    PRE_REG_READ3(int, "socket", int, domain, int, type, int, protocol);
2236 }
2237
2238 PRE(sys_statfs)
2239 {
2240    PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(Char*)ARG1,ARG2);
2241    PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
2242    PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
2243    PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct statfs) );
2244 }
2245 POST(sys_statfs)
2246 {
2247    POST_MEM_WRITE( ARG2, sizeof(struct statfs) );
2248 }
2249
2250 PRE(sys_statx)
2251 {
2252    PRINT("statx ( %#lx(%s), %#lx, %ld, %ld )", ARG1,(Char*)ARG1,ARG2,ARG3,ARG4);
2253    PRE_MEM_RASCIIZ( "statx(file_name)", ARG1 );
2254    PRE_REG_READ4(Word, "statx", UWord, fd, void*, buf,
2255                                 UWord, len, UWord, cmd);
2256    PRE_MEM_WRITE( "statx(buf)", ARG2, ARG3 );
2257 }
2258 POST(sys_statx)
2259 {
2260    POST_MEM_WRITE( ARG2, ARG3 );
2261 }
2262
2263 PRE(sys_symlink)
2264 {
2265    PRINT("symlink (BOGUS HANDLER)");
2266 }
2267
2268 PRE(sys_sys_parm)
2269 {
2270    PRINT("sys_parm (%ld, %ld, %#lx)", ARG1, ARG2, ARG3);
2271    PRE_REG_READ3(int, "sys_parm", int, cmd, int, cmdflag, 
2272                       struct vario*, parmp);
2273    /* this is a bit of a kludge, but if parmp has uninitialised areas
2274       and we're doing SYSP_SET, lots of errors will be tiresomely
2275       reported.  Hence just ignore the definedness of the area and
2276       only check addressability. */
2277    PRE_MEM_WRITE( "sys_parm(parmp)", ARG3, sizeof(struct vario));
2278 }
2279 POST(sys_sys_parm)
2280 {
2281    if (ARG1 == SYSP_GET)
2282       POST_MEM_WRITE( ARG3, sizeof(struct vario) );
2283 }
2284
2285 PRE(sys_sysconfig)
2286 {
2287    PRINT("sysconfig ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
2288    PRE_REG_READ3(int, "sysconfig", int, cmd, void*, parmp, int, parmlen);
2289    /* It may be that the area is read sometimes as well as written,
2290       but for the same reasons as sys_parm, just check addressibility,
2291       not definedness. */
2292    PRE_MEM_WRITE( "sysconfig(parmp)", ARG2, ARG3 );
2293 }
2294 POST(sys_sysconfig)
2295 {
2296    POST_MEM_WRITE( ARG2, ARG3 );
2297 }
2298
2299 PRE(sys_thread_create)
2300 {
2301    *flags |= SfMayBlock;
2302    PRINT("thread_create ( )");
2303 }
2304 POST(sys_thread_create)
2305 {
2306    vg_assert(SUCCESS);
2307    if (0) VG_(printf)("new lwpid is %ld\n", RES);
2308
2309    /* Allocate a new thread slot (which sets it to VgTs_Init), and
2310       record the lwpid in it, so can later find it again when handling
2311       sys_thread_setstate for that lwpid. */
2312
2313    ThreadId     ctid = VG_(alloc_ThreadState)();
2314    ThreadState* ctst = VG_(get_ThreadState)(ctid);
2315
2316    vg_assert(ctst->status == VgTs_Init);
2317
2318    { /* Clear all os_state fields except for the vg stack ones, so any
2319         existing stack gets reused. */
2320      Addr v_s_b    = ctst->os_state.valgrind_stack_base;
2321      Addr v_s_i_SP = ctst->os_state.valgrind_stack_init_SP;
2322      VG_(memset)(&ctst->os_state, 0, sizeof(ThreadOSstate));
2323      ctst->os_state.valgrind_stack_base    = v_s_b;
2324      ctst->os_state.valgrind_stack_init_SP = v_s_i_SP;
2325    }
2326    ctst->os_state.lwpid = RES;
2327 }
2328
2329 PRE(sys_thread_init)
2330 {
2331    *flags |= SfMayBlock;
2332    PRE_REG_READ2(long, "thread_init", long, arg1, long, arg2);
2333    PRINT("thread_init (BOGUS HANDLER) ( %#lx, %#lx )", ARG1, ARG2);
2334 }
2335
2336 PRE(sys_thread_kill)
2337 {
2338    Int target_lwpid, my_lwpid;
2339    PRINT("thread_kill ( %ld, %ld )", ARG1, ARG2);
2340
2341    if ( ((Word)ARG1) == (Word)(-1)
2342         && ARG2 == VKI_SIGSEGV ) {
2343       /* too difficult to continue; give up. */
2344       ML_(aix5_set_threadstate_for_emergency_exit)
2345          (tid, "exiting due to thread_kill(..,SIGSEGV) to process");
2346       SET_STATUS_Success(0);
2347       return;
2348    }
2349
2350    /* Check to see if this kill gave us a pending signal */
2351    *flags |= SfPollAfter;
2352
2353    target_lwpid = (Int)ARG1;
2354    my_lwpid     = VG_(gettid)();
2355    /* we still hold the lock.  Do deadlock-avoidance stuff. */
2356    if (target_lwpid == my_lwpid) {
2357       /* sending a signal to myself, which may be fatal.  Therefore
2358          drop the lock so that if the signal kills me, some other
2359          thread can pick it up. */
2360       *flags |= SfMayBlock;
2361    } else {
2362       /* sending a signal to some other thread, which may kill it;
2363          therefore I'd better hold on to the lock to ensure that the
2364          target doesn't get killed whilst holding it. */
2365    }
2366 }
2367
2368 /* thread_setmymask_fast is handled on a per platform basis */
2369
2370 PRE(sys_thread_setmystate)
2371 {
2372    *flags |= SfMayBlock;
2373    /* args: struct tstate *, struct tstate * 
2374       I assume: first is new state, if not NULL.  
2375       Second is place to write the previous state, if not NULL.
2376       (in the style of sigaction) */
2377    PRINT("thread_setmystate (BOGUS HANDLER) ( %#lx, %#lx )",
2378          ARG1, ARG2 );
2379    PRE_REG_READ2(long, "thread_setmystate", 
2380                        struct tstate *, newstate, 
2381                        struct tstate *, oldstate );
2382    if (ARG1)
2383       PRE_MEM_READ( "thread_setmystate(arg1)", ARG1, sizeof(struct tstate) );
2384    if (ARG2)
2385       PRE_MEM_WRITE( "thread_setmystate(arg2)", ARG2, sizeof(struct tstate) );
2386    if (1 && VG_(clo_trace_syscalls) && ARG1)
2387       ML_(aix5debugstuff_show_tstate)(ARG1, "thread_setmystate (NEW)");
2388
2389    struct tstate* newts  = (struct tstate*)ARG1;
2390    struct tstate* oldts  = (struct tstate*)ARG2;
2391
2392    /* Are we just messing with the signal mask?  If so intercept it
2393       and do it ourselves.  Same idea as handling for
2394       thread_setmymask_fast in 32-bit mode. */
2395    if (newts && newts->flags == TSTATE_CHANGE_SIGMASK) {
2396       vki_sigset_t* newset = newts ? (vki_sigset_t*)&newts->sigmask : NULL;
2397       vki_sigset_t* oldset = oldts ? (vki_sigset_t*)&oldts->sigmask : NULL;
2398       SET_STATUS_from_SysRes(
2399          VG_(do_sys_sigprocmask) ( tid, VKI_SIG_SETMASK, newset, oldset )
2400       );
2401       *flags &= ~SfMayBlock;
2402       return;
2403    }
2404 }
2405 POST(sys_thread_setmystate)
2406 {
2407    if (ARG2)
2408       POST_MEM_WRITE( ARG2, sizeof(struct tstate) );
2409    if (0 && VG_(clo_trace_syscalls) && ARG2)
2410       ML_(aix5debugstuff_show_tstate)(ARG2, "thread_setmystate (OLD)");
2411 }
2412
2413 PRE(sys_thread_setmystate_fast)
2414 {
2415    UWord how = ARG1;
2416    /* args: ?? */
2417    PRINT("thread_setmystate_fast (BOGUS HANDLER)"
2418          "(%#lx,%#lx(%s),%#lx(%s))", 
2419          ARG1,
2420          ARG2, ML_(aix5debugstuff_pc_to_fnname)(ARG2),
2421          ARG3, ML_(aix5debugstuff_pc_to_fnname)(ARG3)
2422         );
2423    PRE_REG_READ3(long, "thread_setmystate_fast", 
2424                        long, arg1, long, arg2, long, arg3);
2425    if (1 && VG_(clo_trace_syscalls))
2426       ML_(aix5debugstuff_show_tstate_flags)( how );
2427
2428    if (how & TSTATE_CHANGE_FLAGS) {
2429       /* Messing with cancellation type/state.  Pay attention. */
2430       Bool async    = (how & TSTATE_CANCEL_DEFER) == 0;
2431       Bool disabled = (how & TSTATE_CANCEL_DISABLE) > 0;
2432       ThreadState* tst = VG_(get_ThreadState)(tid);
2433       if (VG_(clo_trace_syscalls))
2434          VG_(printf)("(cancellation state -> %s %s)",
2435                      async ? "ASYNC" : "DEFER",
2436                      disabled ? "DISABLED" : " ENABLED");
2437       tst->os_state.cancel_async    = async;
2438       tst->os_state.cancel_disabled = disabled;
2439       /* If cancellation has been enabled for this thread and there is
2440          a request outstanding, honour it now. */
2441       if ((!disabled)
2442           && tst->os_state.cancel_progress == Canc_Requested) {
2443          if (VG_(clo_trace_syscalls))
2444             VG_(printf)("(honouring previous cancellation request)");
2445          tst->os_state.cancel_progress = Canc_Actioned;
2446          Bool ok = ML_(aix5_force_thread_into_pthread_exit)(tid);
2447          if (!ok) {
2448             /* now at serious risk of deadlock/livelock.  Give up
2449                rather than continue. */
2450             ML_(aix5_set_threadstate_for_emergency_exit)
2451                (tid, "pthread_cancel(case1): "
2452                      "cannot find pthread_exit; aborting");
2453             SET_STATUS_Success(0);
2454             return;
2455          }
2456       }
2457       SET_STATUS_Success(0);
2458       return;
2459    }
2460
2461    /* In all other cases, hand to kernel. */
2462    *flags |= SfMayBlock;
2463 }
2464
2465 /* thread_setstate is handled in syswrap-ppc{32,64}-aix5.c. */
2466
2467 PRE(sys_thread_terminate_unlock)
2468 {
2469    ThreadState* tst;
2470    /* simple; just make this thread exit */
2471    PRINT("thread_terminate_unlock( %#lx )", ARG1);
2472    PRE_REG_READ1(void, "thread_terminate_unlock", void*, exitcode);
2473    tst = VG_(get_ThreadState)(tid);
2474    /* Drop the lock we were holding, since we're not really going to
2475       exit the host thread with thread_terminate_unlock. */
2476    if (0) VG_(printf)("XXXXX dropping lock\n");
2477    if (1) VG_(do_syscall1)(__NR_AIX5_thread_unlock, ARG1);
2478    /* Set the thread's status to be exiting, then claim that the
2479       syscall succeeded. */
2480    tst->exitreason = VgSrc_ExitThread;
2481    tst->os_state.exitcode = 0;
2482    SET_STATUS_Success(0);
2483 }
2484
2485 PRE(sys_thread_tsleep)
2486 {
2487    *flags |= SfMayBlock;
2488    PRINT("thread_tsleep (BOGUS HANDLER)( %ld, %#lx, %#lx, %#lx )", 
2489          ARG1, ARG2, ARG3, ARG4 );
2490 }
2491
2492 PRE(sys_thread_tsleep_event)
2493 {
2494    *flags |= SfMayBlock;
2495    PRINT("thread_tsleep_event (UNDOCUMENTED)( %#lx, %#lx, %ld, %#lx )", 
2496          ARG1, ARG2, ARG3, ARG4 );
2497 }
2498
2499 PRE(sys_thread_twakeup)
2500 {
2501    *flags |= SfMayBlock;
2502    PRINT("thread_twakeup (BOGUS HANDLER)( tid=%ld, val=%#lx )", ARG1, ARG2 );
2503 }
2504
2505 PRE(sys_thread_twakeup_event)
2506 {
2507    *flags |= SfMayBlock;
2508    PRINT("thread_twakeup_event (BOGUS HANDLER)( %#lx, %ld, %ld )", 
2509          ARG1, ARG2, ARG3 );
2510 }
2511
2512 PRE(sys_thread_unlock)
2513 {
2514    *flags |= SfMayBlock;
2515    PRINT("thread_unlock (BOGUS HANDLER)" );
2516 }
2517
2518 PRE(sys_thread_waitlock)
2519 {
2520    *flags |= SfMayBlock;
2521    PRINT("thread_waitlock (BOGUS HANDLER)" );
2522 }
2523
2524 PRE(sys_thread_waitlock_)
2525 {
2526    *flags |= SfMayBlock;
2527    PRINT("thread_waitlock_ (BOGUS HANDLER)" );
2528 }
2529
2530 PRE(sys_times)
2531 {
2532    PRINT("times ( %#lx )", ARG1);
2533    PRE_REG_READ1(long, "times", struct tms *, buffer);
2534    PRE_MEM_WRITE("times(buf)", ARG1, sizeof(struct tms) );
2535 }
2536 POST(sys_times)
2537 {
2538    POST_MEM_WRITE( ARG1, sizeof(struct tms) );
2539 }
2540
2541 PRE(sys_umask)
2542 {
2543    PRINT("umask (BOGUS HANDLER)");
2544 }
2545
2546 PRE(sys_uname)
2547 {
2548    PRINT("uname ( %#lx )", ARG1);
2549    PRE_MEM_WRITE( "uname(Name)", ARG1, sizeof(struct utsname));
2550 }
2551 POST(sys_uname)
2552 {
2553    vg_assert(SUCCESS);
2554    POST_MEM_WRITE( ARG1, sizeof(struct utsname));
2555 }
2556
2557 PRE(sys_unlink)
2558 {
2559    PRINT("unlink ( %#lx(%s) )", ARG1, (Char*)ARG1 );
2560    PRE_REG_READ1(int, "unlink", char*, path);
2561    PRE_MEM_RASCIIZ( "unlink(path)", ARG1 );
2562 }
2563
2564 PRE(sys_utimes)
2565 {
2566    PRINT("utimes ( %#lx(%s), %#lx )", ARG1,(Char*)ARG1, ARG2);
2567    PRE_REG_READ2(int, "utimes", char*, path, struct timeval*, times);
2568    PRE_MEM_RASCIIZ( "utimes(path)", ARG1 );
2569    PRE_MEM_READ( "utimes(times)", ARG2, 2 * sizeof(struct vki_timeval) );
2570 }
2571
2572 PRE(sys_vmgetinfo)
2573 {
2574    PRINT("vmgetinfo ( %#lx, %ld, %ld )", ARG1, ARG2, ARG3 );
2575    PRE_REG_READ3(int, "vmgetinfo", void*, out, int, command, int, arg);
2576    /* It looks like libc's vmgetinfo just hands stuff through to the
2577       syscall.  The man page says that the interpretation of ARG3(arg)
2578       depends on ARG2(cmd); nevertheless in all cases basically this
2579       writes the buffer (ARG1, ARG3). */
2580    PRE_MEM_WRITE("vmgetinfo(buf)", ARG1, ARG3);
2581 }
2582 POST(sys_vmgetinfo)
2583 {
2584    vg_assert(SUCCESS);
2585    POST_MEM_WRITE(ARG1, ARG3);
2586 }
2587
2588 PRE(sys_yield)
2589 {
2590    *flags |= SfMayBlock;
2591    PRINT("yield ( )");
2592 }
2593
2594 #undef PRE
2595 #undef POST
2596
2597 #endif // defined(VGO_aix5)
2598
2599 /*--------------------------------------------------------------------*/
2600 /*--- end                                                          ---*/
2601 /*--------------------------------------------------------------------*/