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