195f1037b50883fa81420116d7a694be0099ab015florian/* -*- mode: C; c-basic-offset: 3; -*- */
2de4a1d01951937632098a6cda45859afa587a06fsewardj
3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
46e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj/*--- Wrappers for generic Unix system calls                       ---*/
58b68b64759254d514d98328c496cbd88cde4c9a5njn/*---                                            syswrap-generic.c ---*/
6de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
7de4a1d01951937632098a6cda45859afa587a06fsewardj
8de4a1d01951937632098a6cda45859afa587a06fsewardj/*
9b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   This file is part of Valgrind, a dynamic binary instrumentation
10b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   framework.
11de4a1d01951937632098a6cda45859afa587a06fsewardj
120f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 Julian Seward
13de4a1d01951937632098a6cda45859afa587a06fsewardj      jseward@acm.org
14de4a1d01951937632098a6cda45859afa587a06fsewardj
15de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is free software; you can redistribute it and/or
16de4a1d01951937632098a6cda45859afa587a06fsewardj   modify it under the terms of the GNU General Public License as
17de4a1d01951937632098a6cda45859afa587a06fsewardj   published by the Free Software Foundation; either version 2 of the
18de4a1d01951937632098a6cda45859afa587a06fsewardj   License, or (at your option) any later version.
19de4a1d01951937632098a6cda45859afa587a06fsewardj
20de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is distributed in the hope that it will be useful, but
21de4a1d01951937632098a6cda45859afa587a06fsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
22de4a1d01951937632098a6cda45859afa587a06fsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23de4a1d01951937632098a6cda45859afa587a06fsewardj   General Public License for more details.
24de4a1d01951937632098a6cda45859afa587a06fsewardj
25de4a1d01951937632098a6cda45859afa587a06fsewardj   You should have received a copy of the GNU General Public License
26de4a1d01951937632098a6cda45859afa587a06fsewardj   along with this program; if not, write to the Free Software
27de4a1d01951937632098a6cda45859afa587a06fsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28de4a1d01951937632098a6cda45859afa587a06fsewardj   02111-1307, USA.
29de4a1d01951937632098a6cda45859afa587a06fsewardj
30e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   The GNU General Public License is contained in the file COPYING.
31de4a1d01951937632098a6cda45859afa587a06fsewardj*/
32de4a1d01951937632098a6cda45859afa587a06fsewardj
338b68b64759254d514d98328c496cbd88cde4c9a5njn#if defined(VGO_linux) || defined(VGO_darwin)
348b68b64759254d514d98328c496cbd88cde4c9a5njn
35c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_basics.h"
364cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vki.h"
374cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_core_vkiscnums.h"
38c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_threadstate.h"
3945f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_debuginfo.h"     // VG_(di_notify_*)
4055f9d1a56f3542c68f5b24006c14b1f9aaefff6fsewardj#include "pub_core_aspacemgr.h"
4145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_transtab.h"      // VG_(discard_translations)
4214c7cc5a5fbe9526329f058116f921988efe679esewardj#include "pub_core_xarray.h"
4345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_clientstate.h"   // VG_(brk_base), VG_(brk_limit)
44899ce73b9eb1f679562e93f8e5c162aa049413f1njn#include "pub_core_debuglog.h"
450087c501c6356fb083c0ea12d87263aca7abf25anjn#include "pub_core_errormgr.h"
46c91f58449e6fc2a4ce0851639a342c4277612fbbflorian#include "pub_core_gdbserver.h"     // VG_(gdbserver)
4797405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h"
48a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#include "pub_core_libcassert.h"
49de62cbf607eb0e2dccb8bd6c7caf34180f528badnjn#include "pub_core_libcfile.h"
50de62cbf607eb0e2dccb8bd6c7caf34180f528badnjn#include "pub_core_libcprint.h"
51f39e9a36dca9642668a66c6b054f81c88650bcb9njn#include "pub_core_libcproc.h"
52de62cbf607eb0e2dccb8bd6c7caf34180f528badnjn#include "pub_core_libcsignal.h"
53f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_machine.h"       // VG_(get_SP)
54af1d7dfc9412c09d24ea10118f3fd1082f92e49dnjn#include "pub_core_mallocfree.h"
55a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#include "pub_core_options.h"
56c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_scheduler.h"
57a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#include "pub_core_signals.h"
58419bbcb905b239dc209da742f976f1c45abf16d0njn#include "pub_core_stacktrace.h"    // For VG_(get_and_pp_StackTrace)()
599abd608244d8123868d027f616fa928156615d5anjn#include "pub_core_syscall.h"
60c1b0181cbd6f296401daa6ff0e6e14d3a8ab91a0njn#include "pub_core_syswrap.h"
61419bbcb905b239dc209da742f976f1c45abf16d0njn#include "pub_core_tooliface.h"
627375061f0ecd9534a27ade9bb4fbe47ddce41298njn#include "pub_core_ume.h"
6338a74d2cc4670e3eb559adff51a376cd6ec98005philippe#include "pub_core_stacks.h"
64855d93d2e9940890b28874520fa4c1677bf825e2jsgf
65a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#include "priv_types_n_macros.h"
66c1b0181cbd6f296401daa6ff0e6e14d3a8ab91a0njn#include "priv_syswrap-generic.h"
67855d93d2e9940890b28874520fa4c1677bf825e2jsgf
68870f7451dcc5ff1ec6c84e8bb2832bd5834459c2bart#include "config.h"
69870f7451dcc5ff1ec6c84e8bb2832bd5834459c2bart
70855d93d2e9940890b28874520fa4c1677bf825e2jsgf
7138a74d2cc4670e3eb559adff51a376cd6ec98005philippevoid ML_(guess_and_register_stack) (Addr sp, ThreadState* tst)
7238a74d2cc4670e3eb559adff51a376cd6ec98005philippe{
7338a74d2cc4670e3eb559adff51a376cd6ec98005philippe   Bool debug = False;
7438a74d2cc4670e3eb559adff51a376cd6ec98005philippe   NSegment const* seg;
7538a74d2cc4670e3eb559adff51a376cd6ec98005philippe
7638a74d2cc4670e3eb559adff51a376cd6ec98005philippe   /* We don't really know where the client stack is, because its
7738a74d2cc4670e3eb559adff51a376cd6ec98005philippe      allocated by the client.  The best we can do is look at the
7838a74d2cc4670e3eb559adff51a376cd6ec98005philippe      memory mappings and try to derive some useful information.  We
7938a74d2cc4670e3eb559adff51a376cd6ec98005philippe      assume that sp starts near its highest possible value, and can
8038a74d2cc4670e3eb559adff51a376cd6ec98005philippe      only go down to the start of the mmaped segment. */
8138a74d2cc4670e3eb559adff51a376cd6ec98005philippe   seg = VG_(am_find_nsegment)(sp);
82a2aaa408af37939d4a1db943f8d0d0d232de5186florian   if (seg &&
83a2aaa408af37939d4a1db943f8d0d0d232de5186florian       VG_(am_is_valid_for_client)(sp, 1, VKI_PROT_READ | VKI_PROT_WRITE)) {
8438a74d2cc4670e3eb559adff51a376cd6ec98005philippe      tst->client_stack_highest_byte = (Addr)VG_PGROUNDUP(sp)-1;
8538a74d2cc4670e3eb559adff51a376cd6ec98005philippe      tst->client_stack_szB = tst->client_stack_highest_byte - seg->start + 1;
8638a74d2cc4670e3eb559adff51a376cd6ec98005philippe
8738a74d2cc4670e3eb559adff51a376cd6ec98005philippe      VG_(register_stack)(seg->start, tst->client_stack_highest_byte);
8838a74d2cc4670e3eb559adff51a376cd6ec98005philippe
8938a74d2cc4670e3eb559adff51a376cd6ec98005philippe      if (debug)
9038a74d2cc4670e3eb559adff51a376cd6ec98005philippe	 VG_(printf)("tid %d: guessed client stack range [%#lx-%#lx]\n",
9138a74d2cc4670e3eb559adff51a376cd6ec98005philippe		     tst->tid, seg->start, tst->client_stack_highest_byte);
9238a74d2cc4670e3eb559adff51a376cd6ec98005philippe   } else {
9338a74d2cc4670e3eb559adff51a376cd6ec98005philippe      VG_(message)(Vg_UserMsg,
9438a74d2cc4670e3eb559adff51a376cd6ec98005philippe                   "!? New thread %d starts with SP(%#lx) unmapped\n",
9538a74d2cc4670e3eb559adff51a376cd6ec98005philippe		   tst->tid, sp);
9638a74d2cc4670e3eb559adff51a376cd6ec98005philippe      tst->client_stack_highest_byte = 0;
9738a74d2cc4670e3eb559adff51a376cd6ec98005philippe      tst->client_stack_szB  = 0;
9838a74d2cc4670e3eb559adff51a376cd6ec98005philippe   }
9938a74d2cc4670e3eb559adff51a376cd6ec98005philippe}
10038a74d2cc4670e3eb559adff51a376cd6ec98005philippe
10145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Returns True iff address range is something the client can
10245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   plausibly mess with: all of it is either already belongs to the
10345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   client or is free or a reservation. */
10445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1057eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjBool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
106e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                                   const HChar *syscallname)
1071a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge{
1081a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge   Bool ret;
1091a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
1101a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge   if (size == 0)
1111a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge      return True;
1121a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
11345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ret = VG_(am_is_valid_for_client_or_free_or_resvn)
11445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            (start,size,VKI_PROT_NONE);
1151a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
1161a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge   if (0)
117a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("%s: test=%#lx-%#lx ret=%d\n",
11845f4e7c91119c7d01a59f5e827c67841632c9314sewardj		  syscallname, start, start+size-1, (Int)ret);
1191a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
1201543adfbbb9bf65687148d2c8d5dd7e883dd7769nethercote   if (!ret && syscallname != NULL) {
121a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
122738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                               "to modify addresses %#lx-%#lx\n",
123a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                               syscallname, start, start+size-1);
1241a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge      if (VG_(clo_verbosity) > 1) {
125d01fef7de693582a6ce32bdbef7c9040ad6b356bnjn         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1261a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge      }
1271a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge   }
1281a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
1291a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge   return ret;
1301a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge}
1311a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
13245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1337eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjBool ML_(client_signal_OK)(Int sigNo)
134419bbcb905b239dc209da742f976f1c45abf16d0njn{
135419bbcb905b239dc209da742f976f1c45abf16d0njn   /* signal 0 is OK for kill */
136351d006b8fa2d3ab8cabc362954c42de19aab3c7njn   Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
137419bbcb905b239dc209da742f976f1c45abf16d0njn
138419bbcb905b239dc209da742f976f1c45abf16d0njn   //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
139419bbcb905b239dc209da742f976f1c45abf16d0njn
140419bbcb905b239dc209da742f976f1c45abf16d0njn   return ret;
141419bbcb905b239dc209da742f976f1c45abf16d0njn}
142419bbcb905b239dc209da742f976f1c45abf16d0njn
14345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
14445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Handy small function to help stop wrappers from segfaulting when
14545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   presented with bogus client addresses.  Is not used for generating
14645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   user-visible errors. */
14745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
14845f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool ML_(safe_to_deref) ( void* start, SizeT size )
14945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
150143377eab2ef89c9806a16580c6bf0ae3f8b0834njn   return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_READ );
15145f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
15245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
15345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
154e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* ---------------------------------------------------------------------
15527ea8bc6721add61e6284cbbf684b7d06a4bd2eenethercote   Doing mmap, mremap
156e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   ------------------------------------------------------------------ */
157de4a1d01951937632098a6cda45859afa587a06fsewardj
158e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
159e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   munmap, mprotect (and mremap??) work at the page level.  So addresses
160e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   and lengths must be adjusted for this. */
161e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
162e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* Mash around start and length so that the area exactly covers
163e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   an integral number of pages.  If we don't do that, memcheck's
164e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   idea of addressible memory diverges from that of the
165e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   kernel's, which causes the leak detector to crash. */
166e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjnstatic
16745f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid page_align_addr_and_len( Addr* a, SizeT* len)
168de4a1d01951937632098a6cda45859afa587a06fsewardj{
16998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge   Addr ra;
17098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
17113bfd85dfab2cd301c92e308b274ebd17de830d2njn   ra = VG_PGROUNDDN(*a);
17213bfd85dfab2cd301c92e308b274ebd17de830d2njn   *len = VG_PGROUNDUP(*a + *len) - ra;
17398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge   *a = ra;
174de4a1d01951937632098a6cda45859afa587a06fsewardj}
175de4a1d01951937632098a6cda45859afa587a06fsewardj
176dd3725800151572d32df10ad4df4c8aad0d3d088njnstatic void notify_core_of_mmap(Addr a, SizeT len, UInt prot,
177dd3725800151572d32df10ad4df4c8aad0d3d088njn                                UInt flags, Int fd, Off64T offset)
178510521e3ad8afb569be39ba46794dbe6e7b65a72bart{
179510521e3ad8afb569be39ba46794dbe6e7b65a72bart   Bool d;
18098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
18145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* 'a' is the return value from a real kernel mmap, hence: */
18245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(VG_IS_PAGE_ALIGNED(a));
18345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* whereas len is whatever the syscall supplied.  So: */
18445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   len = VG_PGROUNDUP(len);
185e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
18645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
187e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
188510521e3ad8afb569be39ba46794dbe6e7b65a72bart   if (d)
189ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(discard_translations)( a, (ULong)len,
190dd3725800151572d32df10ad4df4c8aad0d3d088njn                                 "notify_core_of_mmap" );
191510521e3ad8afb569be39ba46794dbe6e7b65a72bart}
192510521e3ad8afb569be39ba46794dbe6e7b65a72bart
193dd3725800151572d32df10ad4df4c8aad0d3d088njnstatic void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, ULong di_handle)
194510521e3ad8afb569be39ba46794dbe6e7b65a72bart{
195510521e3ad8afb569be39ba46794dbe6e7b65a72bart   Bool rr, ww, xx;
196510521e3ad8afb569be39ba46794dbe6e7b65a72bart
197510521e3ad8afb569be39ba46794dbe6e7b65a72bart   /* 'a' is the return value from a real kernel mmap, hence: */
198510521e3ad8afb569be39ba46794dbe6e7b65a72bart   vg_assert(VG_IS_PAGE_ALIGNED(a));
199510521e3ad8afb569be39ba46794dbe6e7b65a72bart   /* whereas len is whatever the syscall supplied.  So: */
200510521e3ad8afb569be39ba46794dbe6e7b65a72bart   len = VG_PGROUNDUP(len);
201510521e3ad8afb569be39ba46794dbe6e7b65a72bart
20245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   rr = toBool(prot & VKI_PROT_READ);
20345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ww = toBool(prot & VKI_PROT_WRITE);
20445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   xx = toBool(prot & VKI_PROT_EXEC);
205e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
2069c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj   VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle );
207de4a1d01951937632098a6cda45859afa587a06fsewardj}
208de4a1d01951937632098a6cda45859afa587a06fsewardj
209dd3725800151572d32df10ad4df4c8aad0d3d088njn
210dd3725800151572d32df10ad4df4c8aad0d3d088njn/* When a client mmap has been successfully done, this function must
211dd3725800151572d32df10ad4df4c8aad0d3d088njn   be called.  It notifies both aspacem and the tool of the new
212dd3725800151572d32df10ad4df4c8aad0d3d088njn   mapping.
213dd3725800151572d32df10ad4df4c8aad0d3d088njn
214dd3725800151572d32df10ad4df4c8aad0d3d088njn   JRS 2008-Aug-14: But notice this is *very* obscure.  The only place
215dd3725800151572d32df10ad4df4c8aad0d3d088njn   it is called from is POST(sys_io_setup).  In particular,
216dd3725800151572d32df10ad4df4c8aad0d3d088njn   ML_(generic_PRE_sys_mmap), in m_syswrap, is the "normal case" handler for
217dd3725800151572d32df10ad4df4c8aad0d3d088njn   client mmap.  But it doesn't call this function; instead it does the
218dd3725800151572d32df10ad4df4c8aad0d3d088njn   relevant notifications itself.  Here, we just pass di_handle=0 to
219dd3725800151572d32df10ad4df4c8aad0d3d088njn   notify_tool_of_mmap as we have no better information.  But really this
220dd3725800151572d32df10ad4df4c8aad0d3d088njn   function should be done away with; problem is I don't understand what
221dd3725800151572d32df10ad4df4c8aad0d3d088njn   POST(sys_io_setup) does or how it works.
222dd3725800151572d32df10ad4df4c8aad0d3d088njn
223dd3725800151572d32df10ad4df4c8aad0d3d088njn   [However, this function is used lots for Darwin, because
224dd3725800151572d32df10ad4df4c8aad0d3d088njn    ML_(generic_PRE_sys_mmap) cannot be used for Darwin.]
225dd3725800151572d32df10ad4df4c8aad0d3d088njn */
226dd3725800151572d32df10ad4df4c8aad0d3d088njnvoid
227dd3725800151572d32df10ad4df4c8aad0d3d088njnML_(notify_core_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
228dd3725800151572d32df10ad4df4c8aad0d3d088njn                                    UInt flags, Int fd, Off64T offset )
229dd3725800151572d32df10ad4df4c8aad0d3d088njn{
230dd3725800151572d32df10ad4df4c8aad0d3d088njn   // XXX: unlike the other notify_core_and_tool* functions, this one doesn't
231dd3725800151572d32df10ad4df4c8aad0d3d088njn   // do anything with debug info (ie. it doesn't call VG_(di_notify_mmap)).
232dd3725800151572d32df10ad4df4c8aad0d3d088njn   // Should it?  --njn
233dd3725800151572d32df10ad4df4c8aad0d3d088njn   notify_core_of_mmap(a, len, prot, flags, fd, offset);
234dd3725800151572d32df10ad4df4c8aad0d3d088njn   notify_tool_of_mmap(a, len, prot, 0/*di_handle*/);
235dd3725800151572d32df10ad4df4c8aad0d3d088njn}
236dd3725800151572d32df10ad4df4c8aad0d3d088njn
237dd3725800151572d32df10ad4df4c8aad0d3d088njnvoid
238dd3725800151572d32df10ad4df4c8aad0d3d088njnML_(notify_core_and_tool_of_munmap) ( Addr a, SizeT len )
239dd3725800151572d32df10ad4df4c8aad0d3d088njn{
240dd3725800151572d32df10ad4df4c8aad0d3d088njn   Bool d;
241dd3725800151572d32df10ad4df4c8aad0d3d088njn
242dd3725800151572d32df10ad4df4c8aad0d3d088njn   page_align_addr_and_len(&a, &len);
243dd3725800151572d32df10ad4df4c8aad0d3d088njn   d = VG_(am_notify_munmap)(a, len);
244dd3725800151572d32df10ad4df4c8aad0d3d088njn   VG_TRACK( die_mem_munmap, a, len );
245dd3725800151572d32df10ad4df4c8aad0d3d088njn   VG_(di_notify_munmap)( a, len );
246dd3725800151572d32df10ad4df4c8aad0d3d088njn   if (d)
247ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(discard_translations)( a, (ULong)len,
248dd3725800151572d32df10ad4df4c8aad0d3d088njn                                 "ML_(notify_core_and_tool_of_munmap)" );
249dd3725800151572d32df10ad4df4c8aad0d3d088njn}
250dd3725800151572d32df10ad4df4c8aad0d3d088njn
251dd3725800151572d32df10ad4df4c8aad0d3d088njnvoid
252dd3725800151572d32df10ad4df4c8aad0d3d088njnML_(notify_core_and_tool_of_mprotect) ( Addr a, SizeT len, Int prot )
253dd3725800151572d32df10ad4df4c8aad0d3d088njn{
254dd3725800151572d32df10ad4df4c8aad0d3d088njn   Bool rr = toBool(prot & VKI_PROT_READ);
255dd3725800151572d32df10ad4df4c8aad0d3d088njn   Bool ww = toBool(prot & VKI_PROT_WRITE);
256dd3725800151572d32df10ad4df4c8aad0d3d088njn   Bool xx = toBool(prot & VKI_PROT_EXEC);
257dd3725800151572d32df10ad4df4c8aad0d3d088njn   Bool d;
258dd3725800151572d32df10ad4df4c8aad0d3d088njn
259dd3725800151572d32df10ad4df4c8aad0d3d088njn   page_align_addr_and_len(&a, &len);
260dd3725800151572d32df10ad4df4c8aad0d3d088njn   d = VG_(am_notify_mprotect)(a, len, prot);
261dd3725800151572d32df10ad4df4c8aad0d3d088njn   VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
262dd3725800151572d32df10ad4df4c8aad0d3d088njn   VG_(di_notify_mprotect)( a, len, prot );
263dd3725800151572d32df10ad4df4c8aad0d3d088njn   if (d)
264ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(discard_translations)( a, (ULong)len,
265dd3725800151572d32df10ad4df4c8aad0d3d088njn                                 "ML_(notify_core_and_tool_of_mprotect)" );
266dd3725800151572d32df10ad4df4c8aad0d3d088njn}
267dd3725800151572d32df10ad4df4c8aad0d3d088njn
268dd3725800151572d32df10ad4df4c8aad0d3d088njn
269dd3725800151572d32df10ad4df4c8aad0d3d088njn
270f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if HAVE_MREMAP
27145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Expand (or shrink) an existing mapping, potentially moving it at
27245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   the same time (controlled by the MREMAP_MAYMOVE flag).  Nightmare.
27345f4e7c91119c7d01a59f5e827c67841632c9314sewardj*/
27445f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic
27545f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes do_mremap( Addr old_addr, SizeT old_len,
27645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  Addr new_addr, SizeT new_len,
27745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  UWord flags, ThreadId tid )
2781a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge{
27945f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
2801a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
28145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool      ok, d;
282ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   NSegment const* old_seg;
28345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr      advised;
28445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool      f_fixed   = toBool(flags & VKI_MREMAP_FIXED);
28545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool      f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
2861a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
28745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0)
288a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("do_remap (old %#lx %ld) (new %#lx %ld) %s %s\n",
28945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  old_addr,old_len,new_addr,new_len,
29045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
29145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  flags & VKI_MREMAP_FIXED ? "FIXED" : "");
29263a622f4da0254c435348f2c78b31aa66f4549c8sewardj   if (0)
29363a622f4da0254c435348f2c78b31aa66f4549c8sewardj      VG_(am_show_nsegments)(0, "do_remap: before");
2941a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
29545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
29645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
2971a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
29845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(old_addr))
29945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3001a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
30145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   old_len = VG_PGROUNDUP(old_len);
30245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   new_len = VG_PGROUNDUP(new_len);
3031a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
30445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (new_len == 0)
30545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3061a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
30745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* kernel doesn't reject this, but we do. */
30845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (old_len == 0)
30945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3101a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
31145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* reject wraparounds */
312a5e13dd485bb5d5a39bcb595715eaaa11653b544tom   if (old_addr + old_len < old_addr)
313a5e13dd485bb5d5a39bcb595715eaaa11653b544tom      goto eINVAL;
314a5e13dd485bb5d5a39bcb595715eaaa11653b544tom   if (f_fixed == True && new_addr + new_len < new_len)
31545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3161a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
31745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* kernel rejects all fixed, no-move requests (which are
31845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      meaningless). */
31945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (f_fixed == True && f_maymove == False)
32045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3211a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
32245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Stay away from non-client areas. */
32345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
32445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3251a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
32645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* In all remaining cases, if the old range does not fall within a
32745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      single segment, fail. */
32845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   old_seg = VG_(am_find_nsegment)( old_addr );
32945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
33045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
331c290b883f9a9386a925a8c24f4dc2e59a8851c5aflorian   if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC &&
332c290b883f9a9386a925a8c24f4dc2e59a8851c5aflorian       old_seg->kind != SkShmC)
33345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
3341a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
33545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(old_len > 0);
33645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(new_len > 0);
33745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(VG_IS_PAGE_ALIGNED(old_len));
33845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(VG_IS_PAGE_ALIGNED(new_len));
33945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
3401a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
34145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* There are 3 remaining cases:
3421a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
34345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      * maymove == False
3441a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
34545f4e7c91119c7d01a59f5e827c67841632c9314sewardj        new space has to be at old address, so:
34645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - shrink    -> unmap end
34745f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - same size -> do nothing
34845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - grow      -> if can grow in-place, do so, else fail
3491a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
35045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      * maymove == True, fixed == False
3511a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
35245f4e7c91119c7d01a59f5e827c67841632c9314sewardj        new space can be anywhere, so:
35345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - shrink    -> unmap end
35445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - same size -> do nothing
35545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - grow      -> if can grow in-place, do so, else
35645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                           move to anywhere large enough, else fail
357e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
35845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      * maymove == True, fixed == True
3591a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
36045f4e7c91119c7d01a59f5e827c67841632c9314sewardj        new space must be at new address, so:
3611a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
36245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - if new address is not page aligned, fail
36345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - if new address range overlaps old one, fail
36445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - if new address range cannot be allocated, fail
36545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - else move to new address range with new size
36645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            - else fail
36745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   */
3681a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
36945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (f_maymove == False) {
37045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* new space has to be at old address */
37145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_len < old_len)
37245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto shrink_in_place;
37345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_len > old_len)
37445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto grow_in_place_or_fail;
37545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto same_in_place;
37645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
3771a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
37845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (f_maymove == True && f_fixed == False) {
37945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* new space can be anywhere */
38045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_len < old_len)
38145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto shrink_in_place;
38245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_len > old_len)
38345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto grow_in_place_or_move_anywhere_or_fail;
38445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto same_in_place;
38545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
3861a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
38745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (f_maymove == True && f_fixed == True) {
38845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* new space can only be at the new address */
38945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (!VG_IS_PAGE_ALIGNED(new_addr))
39045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eINVAL;
39145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
39245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* no overlap */
3931a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge      } else {
39445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eINVAL;
39545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
39645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (new_addr == 0)
39745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eINVAL;
39845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* VG_(am_get_advisory_client_simple) interprets zero to mean
39945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            non-fixed, which is not what we want */
40045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
40145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (!ok || advised != new_addr)
40245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eNOMEM;
40345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      ok = VG_(am_relocate_nooverlap_client)
40445f4e7c91119c7d01a59f5e827c67841632c9314sewardj              ( &d, old_addr, old_len, new_addr, new_len );
40545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (ok) {
40645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_TRACK( copy_mem_remap, old_addr, new_addr,
40745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                   MIN_SIZET(old_len,new_len) );
40845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (new_len > old_len)
40945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
4109c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                      old_seg->hasR, old_seg->hasW, old_seg->hasX,
4119c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                      0/*di_handle*/ );
41245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_TRACK(die_mem_munmap, old_addr, old_len);
41345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (d) {
41445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
41545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
41645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
41745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return VG_(mk_SysRes_Success)( new_addr );
41845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
41945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eNOMEM;
42045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
4211a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
42245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* end of the 3 cases */
42345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/ vg_assert(0);
42445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
42545f4e7c91119c7d01a59f5e827c67841632c9314sewardj  grow_in_place_or_move_anywhere_or_fail:
42645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   {
42745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* try growing it in-place */
42845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr   needA = old_addr + old_len;
42945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SSizeT needL = new_len - old_len;
43045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
43145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(needL > 0);
4320b41f3210759573ae126ca1e84e1dd6fb939ab15florian   vg_assert(needA > 0);
4330b41f3210759573ae126ca1e84e1dd6fb939ab15florian
43445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
43563a622f4da0254c435348f2c78b31aa66f4549c8sewardj   if (ok) {
43615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      /* Fixes bug #129866. */
43715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
43863a622f4da0254c435348f2c78b31aa66f4549c8sewardj   }
43945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (ok && advised == needA) {
440dd7318bea2a008f15085e12e026a78a6802e2e9cflorian      const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
441dd7318bea2a008f15085e12e026a78a6802e2e9cflorian      if (new_seg) {
44245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_TRACK( new_mem_mmap, needA, needL,
443dd7318bea2a008f15085e12e026a78a6802e2e9cflorian                                 new_seg->hasR,
444dd7318bea2a008f15085e12e026a78a6802e2e9cflorian                                 new_seg->hasW, new_seg->hasX,
4459c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                                 0/*di_handle*/ );
44645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return VG_(mk_SysRes_Success)( old_addr );
44745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
44845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
4491a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
45045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* that failed.  Look elsewhere. */
45145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
45245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (ok) {
4535484f384b88050235e204ce5aa5d3cf72d7c5580tom      Bool oldR = old_seg->hasR;
4545484f384b88050235e204ce5aa5d3cf72d7c5580tom      Bool oldW = old_seg->hasW;
4555484f384b88050235e204ce5aa5d3cf72d7c5580tom      Bool oldX = old_seg->hasX;
45645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* assert new area does not overlap old */
45745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      vg_assert(advised+new_len-1 < old_addr
45845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                || advised > old_addr+old_len-1);
45945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      ok = VG_(am_relocate_nooverlap_client)
46045f4e7c91119c7d01a59f5e827c67841632c9314sewardj              ( &d, old_addr, old_len, advised, new_len );
46145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (ok) {
46245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_TRACK( copy_mem_remap, old_addr, advised,
46345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                   MIN_SIZET(old_len,new_len) );
46445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (new_len > old_len)
46545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
4665484f384b88050235e204ce5aa5d3cf72d7c5580tom                      oldR, oldW, oldX, 0/*di_handle*/ );
46745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_TRACK(die_mem_munmap, old_addr, old_len);
46845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (d) {
46945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
47045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_(discard_translations)( advised, new_len, "do_remap(5)" );
47145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
47245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return VG_(mk_SysRes_Success)( advised );
47345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
47445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
47545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   goto eNOMEM;
47645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
47745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/ vg_assert(0);
4781a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
47945f4e7c91119c7d01a59f5e827c67841632c9314sewardj  grow_in_place_or_fail:
48045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   {
48145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr  needA = old_addr + old_len;
48245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SizeT needL = new_len - old_len;
4830b41f3210759573ae126ca1e84e1dd6fb939ab15florian
4840b41f3210759573ae126ca1e84e1dd6fb939ab15florian   vg_assert(needA > 0);
4850b41f3210759573ae126ca1e84e1dd6fb939ab15florian
48645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
48763a622f4da0254c435348f2c78b31aa66f4549c8sewardj   if (ok) {
48815e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      /* Fixes bug #129866. */
48915e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
49063a622f4da0254c435348f2c78b31aa66f4549c8sewardj   }
49145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok || advised != needA)
49245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eNOMEM;
493dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
494dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   if (!new_seg)
49545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eNOMEM;
49645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_TRACK( new_mem_mmap, needA, needL,
497dd7318bea2a008f15085e12e026a78a6802e2e9cflorian                           new_seg->hasR, new_seg->hasW, new_seg->hasX,
4989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                           0/*di_handle*/ );
499dd7318bea2a008f15085e12e026a78a6802e2e9cflorian
50045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Success)( old_addr );
50145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
50245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/ vg_assert(0);
5031a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
50445f4e7c91119c7d01a59f5e827c67841632c9314sewardj  shrink_in_place:
50545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   {
50645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
507cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
50845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
50945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
51045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (d)
51145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(discard_translations)( old_addr+new_len, old_len-new_len,
51245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 "do_remap(7)" );
51345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Success)( old_addr );
514e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   }
51545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/ vg_assert(0);
5161a30304e41211cac4b0f368e1a419925a9a38774fitzhardinge
51745f4e7c91119c7d01a59f5e827c67841632c9314sewardj  same_in_place:
51845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Success)( old_addr );
51945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/ vg_assert(0);
52045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
52145f4e7c91119c7d01a59f5e827c67841632c9314sewardj  eINVAL:
52245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Error)( VKI_EINVAL );
52345f4e7c91119c7d01a59f5e827c67841632c9314sewardj  eNOMEM:
52445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Error)( VKI_ENOMEM );
52545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
52645f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  undef MIN_SIZET
527de4a1d01951937632098a6cda45859afa587a06fsewardj}
528f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif /* HAVE_MREMAP */
529de4a1d01951937632098a6cda45859afa587a06fsewardj
530de4a1d01951937632098a6cda45859afa587a06fsewardj
531a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj/* ---------------------------------------------------------------------
532a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   File-descriptor tracking
533a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   ------------------------------------------------------------------ */
534de4a1d01951937632098a6cda45859afa587a06fsewardj
535f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* One of these is allocated for each open file descriptor.  */
536f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshtypedef struct OpenFd
537f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
538f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   Int fd;                        /* The file descriptor */
53919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar *pathname;               /* NULL if not a regular file or unknown */
540f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   ExeContext *where;             /* NULL if inherited from parent */
541f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   struct OpenFd *next, *prev;
542f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh} OpenFd;
543f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
544f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* List of allocated file descriptors. */
5451aa40211ec688cb47df0341e770fb59e933d5b5csewardjstatic OpenFd *allocated_fds = NULL;
546f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
547f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* Count of open file descriptors. */
5480a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardjstatic Int fd_count = 0;
549f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
550f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
551f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* Note the fact that a file descriptor was just closed. */
552f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshstatic
5531dcee097db02f9ef3ba355162c4373d90d0e895cnjnvoid record_fd_close(Int fd)
554f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
555f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   OpenFd *i = allocated_fds;
556f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
557ad1c9563ffd6bbc7d617776256b65a924fd0130ethughes   if (fd >= VG_(fd_hard_limit))
55802665ba6d0b25f8e0685ead136173091ceaa2701rjwalsh      return;			/* Valgrind internal */
55902665ba6d0b25f8e0685ead136173091ceaa2701rjwalsh
560f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   while(i) {
561f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      if(i->fd == fd) {
562f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         if(i->prev)
563f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh            i->prev->next = i->next;
564f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         else
565f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh            allocated_fds = i->next;
566f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         if(i->next)
567f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh            i->next->prev = i->prev;
568f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         if(i->pathname)
56977eb20b3865e7b17c7695c7e7a526b52935f593eflorian            VG_(free) (i->pathname);
57077eb20b3865e7b17c7695c7e7a526b52935f593eflorian         VG_(free) (i);
571f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         fd_count--;
572f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         break;
573f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
574f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      i = i->next;
575f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
576f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
577f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
578f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* Note the fact that a file descriptor was just opened.  If the
579f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   tid is -1, this indicates an inherited fd.  If the pathname is NULL,
580f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   this either indicates a non-standard file (i.e. a pipe or socket or
581f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   some such thing) or that we don't know the filename.  If the fd is
582f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   already open, then we're probably doing a dup2() to an existing fd,
583f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   so just overwrite the existing one. */
5843130eab8c67d0c720cb1a86906cc057daa9700ccflorianvoid ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd,
5853130eab8c67d0c720cb1a86906cc057daa9700ccflorian                                         const HChar *pathname)
586f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
587f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   OpenFd *i;
588f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
589ad1c9563ffd6bbc7d617776256b65a924fd0130ethughes   if (fd >= VG_(fd_hard_limit))
5900e8bfcfee9fbbe6ab13f5c6ebe7ffd1098e21ff9fitzhardinge      return;			/* Valgrind internal */
5910e8bfcfee9fbbe6ab13f5c6ebe7ffd1098e21ff9fitzhardinge
592f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   /* Check to see if this fd is already open. */
593f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   i = allocated_fds;
594f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   while (i) {
595f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      if (i->fd == fd) {
59677eb20b3865e7b17c7695c7e7a526b52935f593eflorian         if (i->pathname) VG_(free)(i->pathname);
597f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         break;
598f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
599f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      i = i->next;
600f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
601f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
602f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   /* Not already one: allocate an OpenFd */
603f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   if (i == NULL) {
60477eb20b3865e7b17c7695c7e7a526b52935f593eflorian      i = VG_(malloc)("syswrap.rfdowgn.1", sizeof(OpenFd));
605f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
606f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      i->prev = NULL;
607f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      i->next = allocated_fds;
608f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      if(allocated_fds) allocated_fds->prev = i;
609f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      allocated_fds = i;
610f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      fd_count++;
611f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
612f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
613f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   i->fd = fd;
61477eb20b3865e7b17c7695c7e7a526b52935f593eflorian   i->pathname = VG_(strdup)("syswrap.rfdowgn.2", pathname);
615d01b5983189559779de756e32d15d9926b9f61f3sewardj   i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
616f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
617f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
618f845f8ffb1d2fac86714e32f4e279700b07722dfnjn// Record opening of an fd, and find its name.
619096ccdd670d4e4eabdafb18598b1cd06d790fda8njnvoid ML_(record_fd_open_named)(ThreadId tid, Int fd)
620f845f8ffb1d2fac86714e32f4e279700b07722dfnjn{
6213130eab8c67d0c720cb1a86906cc057daa9700ccflorian   const HChar* buf;
6223130eab8c67d0c720cb1a86906cc057daa9700ccflorian   const HChar* name;
623a175ffb9ffa4fd250611582a611333d11c835de2florian   if (VG_(resolve_filename)(fd, &buf))
624f845f8ffb1d2fac86714e32f4e279700b07722dfnjn      name = buf;
625f845f8ffb1d2fac86714e32f4e279700b07722dfnjn   else
626f845f8ffb1d2fac86714e32f4e279700b07722dfnjn      name = NULL;
627f845f8ffb1d2fac86714e32f4e279700b07722dfnjn
6284279a8884ad1aee46dfe34b5df5950b51e93532cnjn   ML_(record_fd_open_with_given_name)(tid, fd, name);
629f845f8ffb1d2fac86714e32f4e279700b07722dfnjn}
630f845f8ffb1d2fac86714e32f4e279700b07722dfnjn
631f845f8ffb1d2fac86714e32f4e279700b07722dfnjn// Record opening of a nameless fd.
632f845f8ffb1d2fac86714e32f4e279700b07722dfnjnvoid ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
633f845f8ffb1d2fac86714e32f4e279700b07722dfnjn{
6344279a8884ad1aee46dfe34b5df5950b51e93532cnjn   ML_(record_fd_open_with_given_name)(tid, fd, NULL);
635f845f8ffb1d2fac86714e32f4e279700b07722dfnjn}
636f845f8ffb1d2fac86714e32f4e279700b07722dfnjn
637f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshstatic
6383995526f11b6633bdf3eed0255c62a42f50461b4tomHChar *unix_to_name(struct vki_sockaddr_un *sa, UInt len, HChar *name)
639f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
64073b526fb4af0f60634f0078583d92b931d5c0eebnethercote   if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
641f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      VG_(sprintf)(name, "<unknown>");
642f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
643f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      VG_(sprintf)(name, "%s", sa->sun_path);
644f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
645f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
646f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   return name;
647f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
648f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
649f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshstatic
6503995526f11b6633bdf3eed0255c62a42f50461b4tomHChar *inet_to_name(struct vki_sockaddr_in *sa, UInt len, HChar *name)
651f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
65273b526fb4af0f60634f0078583d92b931d5c0eebnethercote   if (sa == NULL || len == 0) {
653f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      VG_(sprintf)(name, "<unknown>");
6543995526f11b6633bdf3eed0255c62a42f50461b4tom   } else if (sa->sin_port == 0) {
6553995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(name, "<unbound>");
656f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
657329af4bc87f417b5ce3d770da3ebfbadb88904f2tom      UInt addr = VG_(ntohl)(sa->sin_addr.s_addr);
6583995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(name, "%u.%u.%u.%u:%u",
6593995526f11b6633bdf3eed0255c62a42f50461b4tom                   (addr>>24) & 0xFF, (addr>>16) & 0xFF,
6603995526f11b6633bdf3eed0255c62a42f50461b4tom                   (addr>>8) & 0xFF, addr & 0xFF,
6613995526f11b6633bdf3eed0255c62a42f50461b4tom                   VG_(ntohs)(sa->sin_port));
6623995526f11b6633bdf3eed0255c62a42f50461b4tom   }
6633995526f11b6633bdf3eed0255c62a42f50461b4tom
6643995526f11b6633bdf3eed0255c62a42f50461b4tom   return name;
6653995526f11b6633bdf3eed0255c62a42f50461b4tom}
6663995526f11b6633bdf3eed0255c62a42f50461b4tom
6673995526f11b6633bdf3eed0255c62a42f50461b4tomstatic
6683995526f11b6633bdf3eed0255c62a42f50461b4tomvoid inet6_format(HChar *s, const UChar ip[16])
6693995526f11b6633bdf3eed0255c62a42f50461b4tom{
6703995526f11b6633bdf3eed0255c62a42f50461b4tom   static const unsigned char V4mappedprefix[12] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
6713995526f11b6633bdf3eed0255c62a42f50461b4tom
6723995526f11b6633bdf3eed0255c62a42f50461b4tom   if (!VG_(memcmp)(ip, V4mappedprefix, 12)) {
6738eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian      const struct vki_in_addr *sin_addr =
6748eebf23c35d97489c0d3c8b41dd542e00ae6acbdflorian          (const struct vki_in_addr *)(ip + 12);
6753995526f11b6633bdf3eed0255c62a42f50461b4tom      UInt addr = VG_(ntohl)(sin_addr->s_addr);
6763995526f11b6633bdf3eed0255c62a42f50461b4tom
6773995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(s, "::ffff:%u.%u.%u.%u",
6783995526f11b6633bdf3eed0255c62a42f50461b4tom                   (addr>>24) & 0xFF, (addr>>16) & 0xFF,
6793995526f11b6633bdf3eed0255c62a42f50461b4tom                   (addr>>8) & 0xFF, addr & 0xFF);
6803995526f11b6633bdf3eed0255c62a42f50461b4tom   } else {
6813995526f11b6633bdf3eed0255c62a42f50461b4tom      Bool compressing = False;
6823995526f11b6633bdf3eed0255c62a42f50461b4tom      Bool compressed = False;
6833995526f11b6633bdf3eed0255c62a42f50461b4tom      Int len = 0;
6843995526f11b6633bdf3eed0255c62a42f50461b4tom      Int i;
6853995526f11b6633bdf3eed0255c62a42f50461b4tom
6863995526f11b6633bdf3eed0255c62a42f50461b4tom      for (i = 0; i < 16; i += 2) {
6873995526f11b6633bdf3eed0255c62a42f50461b4tom         UInt word = ((UInt)ip[i] << 8) | (UInt)ip[i+1];
6883995526f11b6633bdf3eed0255c62a42f50461b4tom         if (word == 0 && !compressed) {
6893995526f11b6633bdf3eed0255c62a42f50461b4tom            compressing = True;
6903995526f11b6633bdf3eed0255c62a42f50461b4tom         } else {
6913995526f11b6633bdf3eed0255c62a42f50461b4tom            if (compressing) {
6923995526f11b6633bdf3eed0255c62a42f50461b4tom               compressing = False;
6933995526f11b6633bdf3eed0255c62a42f50461b4tom               compressed = True;
6943995526f11b6633bdf3eed0255c62a42f50461b4tom               s[len++] = ':';
6953995526f11b6633bdf3eed0255c62a42f50461b4tom            }
6963995526f11b6633bdf3eed0255c62a42f50461b4tom            if (i > 0) {
6973995526f11b6633bdf3eed0255c62a42f50461b4tom               s[len++] = ':';
6983995526f11b6633bdf3eed0255c62a42f50461b4tom            }
6993995526f11b6633bdf3eed0255c62a42f50461b4tom            len += VG_(sprintf)(s + len, "%x", word);
7003995526f11b6633bdf3eed0255c62a42f50461b4tom         }
7013995526f11b6633bdf3eed0255c62a42f50461b4tom      }
7023995526f11b6633bdf3eed0255c62a42f50461b4tom
7033995526f11b6633bdf3eed0255c62a42f50461b4tom      if (compressing) {
7043995526f11b6633bdf3eed0255c62a42f50461b4tom         s[len++] = ':';
7053995526f11b6633bdf3eed0255c62a42f50461b4tom         s[len++] = ':';
706f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
7073995526f11b6633bdf3eed0255c62a42f50461b4tom
7083995526f11b6633bdf3eed0255c62a42f50461b4tom      s[len++] = 0;
7093995526f11b6633bdf3eed0255c62a42f50461b4tom   }
7103995526f11b6633bdf3eed0255c62a42f50461b4tom
7113995526f11b6633bdf3eed0255c62a42f50461b4tom   return;
7123995526f11b6633bdf3eed0255c62a42f50461b4tom}
7133995526f11b6633bdf3eed0255c62a42f50461b4tom
7143995526f11b6633bdf3eed0255c62a42f50461b4tomstatic
7153995526f11b6633bdf3eed0255c62a42f50461b4tomHChar *inet6_to_name(struct vki_sockaddr_in6 *sa, UInt len, HChar *name)
7163995526f11b6633bdf3eed0255c62a42f50461b4tom{
7173995526f11b6633bdf3eed0255c62a42f50461b4tom   if (sa == NULL || len == 0) {
7183995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(name, "<unknown>");
7193995526f11b6633bdf3eed0255c62a42f50461b4tom   } else if (sa->sin6_port == 0) {
7203995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(name, "<unbound>");
7213995526f11b6633bdf3eed0255c62a42f50461b4tom   } else {
722f44ff62031a5344468774ada6f1b7375dfd85e7bflorian      HChar addr[100];    // large enough
7233995526f11b6633bdf3eed0255c62a42f50461b4tom      inet6_format(addr, (void *)&(sa->sin6_addr));
7243995526f11b6633bdf3eed0255c62a42f50461b4tom      VG_(sprintf)(name, "[%s]:%u", addr, VG_(ntohs)(sa->sin6_port));
725f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
726f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
727f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   return name;
728f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
729f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
730f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/*
731f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh * Try get some details about a socket.
732f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh */
733f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshstatic void
7340a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardjgetsockdetails(Int fd)
735f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
736f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   union u {
73773b526fb4af0f60634f0078583d92b931d5c0eebnethercote      struct vki_sockaddr a;
73873b526fb4af0f60634f0078583d92b931d5c0eebnethercote      struct vki_sockaddr_in in;
7393995526f11b6633bdf3eed0255c62a42f50461b4tom      struct vki_sockaddr_in6 in6;
74073b526fb4af0f60634f0078583d92b931d5c0eebnethercote      struct vki_sockaddr_un un;
741f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } laddr;
7421636d33c13958b9c0e7d3059cdd5005746418eb2florian   Int llen;
743f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
744f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   llen = sizeof(laddr);
745f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   VG_(memset)(&laddr, 0, llen);
746f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
747f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
748f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      switch(laddr.a.sa_family) {
74973b526fb4af0f60634f0078583d92b931d5c0eebnethercote      case VKI_AF_INET: {
750f44ff62031a5344468774ada6f1b7375dfd85e7bflorian         HChar lname[32];   // large enough
751f44ff62031a5344468774ada6f1b7375dfd85e7bflorian         HChar pname[32];   // large enough
75273b526fb4af0f60634f0078583d92b931d5c0eebnethercote         struct vki_sockaddr_in paddr;
7531636d33c13958b9c0e7d3059cdd5005746418eb2florian         Int plen = sizeof(struct vki_sockaddr_in);
754f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
755738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
756738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s\n", fd,
7573995526f11b6633bdf3eed0255c62a42f50461b4tom                         inet_to_name(&(laddr.in), llen, lname),
7583995526f11b6633bdf3eed0255c62a42f50461b4tom                         inet_to_name(&paddr, plen, pname));
759f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         } else {
760738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound\n",
7613995526f11b6633bdf3eed0255c62a42f50461b4tom                         fd, inet_to_name(&(laddr.in), llen, lname));
7623995526f11b6633bdf3eed0255c62a42f50461b4tom         }
7633995526f11b6633bdf3eed0255c62a42f50461b4tom         return;
7643995526f11b6633bdf3eed0255c62a42f50461b4tom         }
7653995526f11b6633bdf3eed0255c62a42f50461b4tom      case VKI_AF_INET6: {
766f44ff62031a5344468774ada6f1b7375dfd85e7bflorian         HChar lname[128];  // large enough
767f44ff62031a5344468774ada6f1b7375dfd85e7bflorian         HChar pname[128];  // large enough
7683995526f11b6633bdf3eed0255c62a42f50461b4tom         struct vki_sockaddr_in6 paddr;
7693995526f11b6633bdf3eed0255c62a42f50461b4tom         Int plen = sizeof(struct vki_sockaddr_in6);
7703995526f11b6633bdf3eed0255c62a42f50461b4tom
7713995526f11b6633bdf3eed0255c62a42f50461b4tom         if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
7723995526f11b6633bdf3eed0255c62a42f50461b4tom            VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> %s\n", fd,
7733995526f11b6633bdf3eed0255c62a42f50461b4tom                         inet6_to_name(&(laddr.in6), llen, lname),
7743995526f11b6633bdf3eed0255c62a42f50461b4tom                         inet6_to_name(&paddr, plen, pname));
7753995526f11b6633bdf3eed0255c62a42f50461b4tom         } else {
7763995526f11b6633bdf3eed0255c62a42f50461b4tom            VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> unbound\n",
7773995526f11b6633bdf3eed0255c62a42f50461b4tom                         fd, inet6_to_name(&(laddr.in6), llen, lname));
778f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         }
779f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         return;
780f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         }
78173b526fb4af0f60634f0078583d92b931d5c0eebnethercote      case VKI_AF_UNIX: {
782f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         static char lname[256];
783738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s\n", fd,
7843995526f11b6633bdf3eed0255c62a42f50461b4tom                      unix_to_name(&(laddr.un), llen, lname));
785f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         return;
786f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         }
787f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      default:
788738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:\n",
789f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh                      laddr.a.sa_family, fd);
790f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         return;
791f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
792f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
793f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
794738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   VG_(message)(Vg_UserMsg, "Open socket %d:\n", fd);
795f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
796f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
797f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
7983a42fb88cfb660772c77ef010708a2b21f501980nethercote/* Dump out a summary, and a more detailed list, of open file descriptors. */
799e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianvoid VG_(show_open_fds) (const HChar* when)
800f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
801f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   OpenFd *i = allocated_fds;
802f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
803c3360388cc73eff2327d40d5f3ed313b9e548591philippe   VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open %s.\n", fd_count, when);
804f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
805738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   while (i) {
806738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (i->pathname) {
807738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd,
808f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh                      i->pathname);
809f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      } else {
8100a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj         Int val;
8111636d33c13958b9c0e7d3059cdd5005746418eb2florian         Int len = sizeof(val);
812f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
813738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len)
814738856f99eea33d86ce91dcb1d6cd5b151e307casewardj             == -1) {
815738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            VG_(message)(Vg_UserMsg, "Open file descriptor %d:\n", i->fd);
816f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         } else {
817f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh            getsockdetails(i->fd);
818f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         }
819f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
820f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
821f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      if(i->where) {
822f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         VG_(pp_ExeContext)(i->where);
823738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "\n");
824f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      } else {
825738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "   <inherited from parent>\n");
826738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_UserMsg, "\n");
827f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
828f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
829f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      i = i->next;
830f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
831f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
832738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   VG_(message)(Vg_UserMsg, "\n");
833f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
834f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
83581b975ce84471039f9d668274fd544419541ebabnjn/* If /proc/self/fd doesn't exist (e.g. you've got a Linux kernel that doesn't
83681b975ce84471039f9d668274fd544419541ebabnjn   have /proc support compiled in, or a non-Linux kernel), then we need to
83781b975ce84471039f9d668274fd544419541ebabnjn   find out what file descriptors we inherited from our parent process the
83881b975ce84471039f9d668274fd544419541ebabnjn   hard way - by checking each fd in turn. */
839f5f536f398c082b8c92b2789a90d83b34ab98660rjwalshstatic
84081b975ce84471039f9d668274fd544419541ebabnjnvoid init_preopened_fds_without_proc_self_fd(void)
841f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
842f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   struct vki_rlimit lim;
8430a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj   UInt count;
8440a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj   Int i;
845f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
846620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
847f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      /* Hmm.  getrlimit() failed.  Now we're screwed, so just choose
848f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         an arbitrarily high number.  1024 happens to be the limit in
84981b975ce84471039f9d668274fd544419541ebabnjn         the 2.4 Linux kernels. */
850f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      count = 1024;
851f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
852f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      count = lim.rlim_cur;
853f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
854f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
855f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   for (i = 0; i < count; i++)
85681b975ce84471039f9d668274fd544419541ebabnjn      if (VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
85781b975ce84471039f9d668274fd544419541ebabnjn         ML_(record_fd_open_named)(-1, i);
858f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
859f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
860f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh/* Initialize the list of open file descriptors with the file descriptors
861f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   we inherited from out parent process. */
862f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
8631aa40211ec688cb47df0341e770fb59e933d5b5csewardjvoid VG_(init_preopened_fds)(void)
864f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
865f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// DDD: should probably use HAVE_PROC here or similar, instead.
86681b975ce84471039f9d668274fd544419541ebabnjn#if defined(VGO_linux)
8670a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj   Int ret;
868495c6563114d60a67caa5824a03dc4892cc86adbmjw   struct vki_dirent64 d;
8699264559eba4aa5d397a278b4e1a50c03de30693fsewardj   SysRes f;
870f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
871f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
872cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(f)) {
87381b975ce84471039f9d668274fd544419541ebabnjn      init_preopened_fds_without_proc_self_fd();
874f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      return;
875f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
876f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
877495c6563114d60a67caa5824a03dc4892cc86adbmjw   while ((ret = VG_(getdents64)(sr_Res(f), &d, sizeof(d))) != 0) {
878f845f8ffb1d2fac86714e32f4e279700b07722dfnjn      if (ret == -1)
879f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         goto out;
880f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
881f845f8ffb1d2fac86714e32f4e279700b07722dfnjn      if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
88219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         HChar* s;
88383df0b67a14425c484d8dda42b53f3ff0b598894njn         Int fno = VG_(strtoll10)(d.d_name, &s);
88483df0b67a14425c484d8dda42b53f3ff0b598894njn         if (*s == '\0') {
885cda2f0fbda4c4b2644babc830244be8aed95de1dnjn            if (fno != sr_Res(f))
88683df0b67a14425c484d8dda42b53f3ff0b598894njn               if (VG_(clo_track_fds))
88783df0b67a14425c484d8dda42b53f3ff0b598894njn                  ML_(record_fd_open_named)(-1, fno);
88883df0b67a14425c484d8dda42b53f3ff0b598894njn         } else {
88983df0b67a14425c484d8dda42b53f3ff0b598894njn            VG_(message)(Vg_DebugMsg,
890738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               "Warning: invalid file name in /proc/self/fd: %s\n",
891738856f99eea33d86ce91dcb1d6cd5b151e307casewardj               d.d_name);
89283df0b67a14425c484d8dda42b53f3ff0b598894njn         }
893f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
894f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
895cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET);
896f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
897f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
8989264559eba4aa5d397a278b4e1a50c03de30693fsewardj  out:
899cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   VG_(close)(sr_Res(f));
90081b975ce84471039f9d668274fd544419541ebabnjn
901f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
902f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   init_preopened_fds_without_proc_self_fd();
903f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
90481b975ce84471039f9d668274fd544419541ebabnjn#else
90581b975ce84471039f9d668274fd544419541ebabnjn#  error Unknown OS
90681b975ce84471039f9d668274fd544419541ebabnjn#endif
907f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
908f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
909de4a1d01951937632098a6cda45859afa587a06fsewardjstatic
910e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianHChar *strdupcat ( const HChar* cc, const HChar *s1, const HChar *s2,
911e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                   ArenaId aid )
912de4a1d01951937632098a6cda45859afa587a06fsewardj{
913de4a1d01951937632098a6cda45859afa587a06fsewardj   UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
914e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   HChar *result = VG_(arena_malloc) ( aid, cc, len );
915de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(strcpy) ( result, s1 );
916de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(strcat) ( result, s2 );
917de4a1d01951937632098a6cda45859afa587a06fsewardj   return result;
918de4a1d01951937632098a6cda45859afa587a06fsewardj}
919de4a1d01951937632098a6cda45859afa587a06fsewardj
920de4a1d01951937632098a6cda45859afa587a06fsewardjstatic
92156e1c849d0f28d66b58843d8c3463c0d2e8409eatomvoid pre_mem_read_sendmsg ( ThreadId tid, Bool read,
922e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                            const HChar *msg, Addr base, SizeT size )
923de4a1d01951937632098a6cda45859afa587a06fsewardj{
924e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   HChar *outmsg = strdupcat ( "di.syswrap.pmrs.1",
925e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                               "sendmsg", msg, VG_AR_CORE );
926ef0c7663cb71101c7b718108253444cb75402cbbnethercote   PRE_MEM_READ( outmsg, base, size );
92777eb20b3865e7b17c7695c7e7a526b52935f593eflorian   VG_(free) ( outmsg );
928de4a1d01951937632098a6cda45859afa587a06fsewardj}
929de4a1d01951937632098a6cda45859afa587a06fsewardj
930de4a1d01951937632098a6cda45859afa587a06fsewardjstatic
93156e1c849d0f28d66b58843d8c3463c0d2e8409eatomvoid pre_mem_write_recvmsg ( ThreadId tid, Bool read,
932e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                             const HChar *msg, Addr base, SizeT size )
933de4a1d01951937632098a6cda45859afa587a06fsewardj{
934e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   HChar *outmsg = strdupcat ( "di.syswrap.pmwr.1",
935e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                               "recvmsg", msg, VG_AR_CORE );
93656e1c849d0f28d66b58843d8c3463c0d2e8409eatom   if ( read )
93756e1c849d0f28d66b58843d8c3463c0d2e8409eatom      PRE_MEM_READ( outmsg, base, size );
93856e1c849d0f28d66b58843d8c3463c0d2e8409eatom   else
93956e1c849d0f28d66b58843d8c3463c0d2e8409eatom      PRE_MEM_WRITE( outmsg, base, size );
94077eb20b3865e7b17c7695c7e7a526b52935f593eflorian   VG_(free) ( outmsg );
941de4a1d01951937632098a6cda45859afa587a06fsewardj}
942de4a1d01951937632098a6cda45859afa587a06fsewardj
943de4a1d01951937632098a6cda45859afa587a06fsewardjstatic
94456e1c849d0f28d66b58843d8c3463c0d2e8409eatomvoid post_mem_write_recvmsg ( ThreadId tid, Bool read,
945e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                              const HChar *fieldName, Addr base, SizeT size )
946de4a1d01951937632098a6cda45859afa587a06fsewardj{
94756e1c849d0f28d66b58843d8c3463c0d2e8409eatom   if ( !read )
94856e1c849d0f28d66b58843d8c3463c0d2e8409eatom      POST_MEM_WRITE( base, size );
949de4a1d01951937632098a6cda45859afa587a06fsewardj}
950de4a1d01951937632098a6cda45859afa587a06fsewardj
951de4a1d01951937632098a6cda45859afa587a06fsewardjstatic
9528c824516728858da07809e6023ebb0fe4118b629sewardjvoid msghdr_foreachfield (
953a4991237861dd834a58620b6a9eeca0e6e843f24tom        ThreadId tid,
954e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian        const HChar *name,
9558b3a6094d817ca6677592ce7f1147eb24c1a94f4tom        struct vki_msghdr *msg,
9568b3a6094d817ca6677592ce7f1147eb24c1a94f4tom        UInt length,
957fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom        void (*foreach_func)( ThreadId, Bool, const HChar *, Addr, SizeT ),
9586822be8ce58da00ecf03ec28ed6e81c8f283ed68sewardj        Bool rekv /* "recv" apparently shadows some header decl on OSX108 */
9598c824516728858da07809e6023ebb0fe4118b629sewardj     )
960de4a1d01951937632098a6cda45859afa587a06fsewardj{
961e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   HChar *fieldName;
962a4991237861dd834a58620b6a9eeca0e6e843f24tom
963de4a1d01951937632098a6cda45859afa587a06fsewardj   if ( !msg )
964de4a1d01951937632098a6cda45859afa587a06fsewardj      return;
965de4a1d01951937632098a6cda45859afa587a06fsewardj
96677eb20b3865e7b17c7695c7e7a526b52935f593eflorian   fieldName = VG_(malloc) ( "di.syswrap.mfef", VG_(strlen)(name) + 32 );
967a4991237861dd834a58620b6a9eeca0e6e843f24tom
968a4991237861dd834a58620b6a9eeca0e6e843f24tom   VG_(sprintf) ( fieldName, "(%s)", name );
969a4991237861dd834a58620b6a9eeca0e6e843f24tom
970a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
971a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
972a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
973a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
974a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
975a4991237861dd834a58620b6a9eeca0e6e843f24tom   foreach_func ( tid, True, fieldName, (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
976fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom
977fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom   /* msg_flags is completely ignored for send_mesg, recv_mesg doesn't read
978fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom      the field, but does write to it. */
9796822be8ce58da00ecf03ec28ed6e81c8f283ed68sewardj   if ( rekv )
980fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom      foreach_func ( tid, False, fieldName, (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
981a4991237861dd834a58620b6a9eeca0e6e843f24tom
982aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw   if ( ML_(safe_to_deref)(&msg->msg_name, sizeof (void *))
983aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw        && msg->msg_name ) {
984a4991237861dd834a58620b6a9eeca0e6e843f24tom      VG_(sprintf) ( fieldName, "(%s.msg_name)", name );
985a4991237861dd834a58620b6a9eeca0e6e843f24tom      foreach_func ( tid, False, fieldName,
986de4a1d01951937632098a6cda45859afa587a06fsewardj                     (Addr)msg->msg_name, msg->msg_namelen );
987a4991237861dd834a58620b6a9eeca0e6e843f24tom   }
988de4a1d01951937632098a6cda45859afa587a06fsewardj
989aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw   if ( ML_(safe_to_deref)(&msg->msg_iov, sizeof (void *))
990aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw        && msg->msg_iov ) {
99173b526fb4af0f60634f0078583d92b931d5c0eebnethercote      struct vki_iovec *iov = msg->msg_iov;
992de4a1d01951937632098a6cda45859afa587a06fsewardj      UInt i;
993de4a1d01951937632098a6cda45859afa587a06fsewardj
994a4991237861dd834a58620b6a9eeca0e6e843f24tom      VG_(sprintf) ( fieldName, "(%s.msg_iov)", name );
995a4991237861dd834a58620b6a9eeca0e6e843f24tom
996a4991237861dd834a58620b6a9eeca0e6e843f24tom      foreach_func ( tid, True, fieldName,
99773b526fb4af0f60634f0078583d92b931d5c0eebnethercote                     (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
998de4a1d01951937632098a6cda45859afa587a06fsewardj
999a4991237861dd834a58620b6a9eeca0e6e843f24tom      for ( i = 0; i < msg->msg_iovlen; ++i, ++iov ) {
10008b3a6094d817ca6677592ce7f1147eb24c1a94f4tom         UInt iov_len = iov->iov_len <= length ? iov->iov_len : length;
1001a4991237861dd834a58620b6a9eeca0e6e843f24tom         VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i );
1002a4991237861dd834a58620b6a9eeca0e6e843f24tom         foreach_func ( tid, False, fieldName,
10038b3a6094d817ca6677592ce7f1147eb24c1a94f4tom                        (Addr)iov->iov_base, iov_len );
10048b3a6094d817ca6677592ce7f1147eb24c1a94f4tom         length = length - iov_len;
1005a4991237861dd834a58620b6a9eeca0e6e843f24tom      }
1006de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1007de4a1d01951937632098a6cda45859afa587a06fsewardj
1008aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw   if ( ML_(safe_to_deref) (&msg->msg_control, sizeof (void *))
1009aa02f66b9fd8cc55f28f37d97e04a3ebb025382bmjw        && msg->msg_control )
1010a4991237861dd834a58620b6a9eeca0e6e843f24tom   {
1011a4991237861dd834a58620b6a9eeca0e6e843f24tom      VG_(sprintf) ( fieldName, "(%s.msg_control)", name );
1012a4991237861dd834a58620b6a9eeca0e6e843f24tom      foreach_func ( tid, False, fieldName,
1013de4a1d01951937632098a6cda45859afa587a06fsewardj                     (Addr)msg->msg_control, msg->msg_controllen );
1014a4991237861dd834a58620b6a9eeca0e6e843f24tom   }
1015a4991237861dd834a58620b6a9eeca0e6e843f24tom
101677eb20b3865e7b17c7695c7e7a526b52935f593eflorian   VG_(free) ( fieldName );
1017de4a1d01951937632098a6cda45859afa587a06fsewardj}
1018de4a1d01951937632098a6cda45859afa587a06fsewardj
1019b5f6f51ebcac183818061bf53427a3e7808ef10dsewardjstatic void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
1020f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
102173b526fb4af0f60634f0078583d92b931d5c0eebnethercote   struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
1022f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
1023f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   while (cm) {
102473b526fb4af0f60634f0078583d92b931d5c0eebnethercote      if (cm->cmsg_level == VKI_SOL_SOCKET &&
102573b526fb4af0f60634f0078583d92b931d5c0eebnethercote          cm->cmsg_type == VKI_SCM_RIGHTS ) {
10260a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj         Int *fds = (Int *) VKI_CMSG_DATA(cm);
10270a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj         Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
1028f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh                         / sizeof(int);
10290a400c7a4f8c6b5e9d431a453703096fbb2c076bsewardj         Int i;
1030f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
1031f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh         for (i = 0; i < fdc; i++)
1032f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh            if(VG_(clo_track_fds))
1033493dd18a6344fcb2a017a7b888d33b7fbe8b1519nethercote               // XXX: must we check the range on these fds with
10347b2c38c2ed00b4214d199184a50837a009e1acc0cerion               //      ML_(fd_allowed)()?
1035096ccdd670d4e4eabdafb18598b1cd06d790fda8njn               ML_(record_fd_open_named)(tid, fds[i]);
1036f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh      }
1037f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
103873b526fb4af0f60634f0078583d92b931d5c0eebnethercote      cm = VKI_CMSG_NXTHDR(msg, cm);
1039f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   }
1040f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
1041f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh
1042f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* GrP kernel ignores sa_len (at least on Darwin); this checks the rest */
1043c483e8fb94d84a57ac6df5e18f38465134d215bdsewardjstatic
1044855d93d2e9940890b28874520fa4c1677bf825e2jsgfvoid pre_mem_read_sockaddr ( ThreadId tid,
1045e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                             const HChar *description,
1046a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                             struct vki_sockaddr *sa, UInt salen )
1047c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj{
1048e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   HChar *outmsg;
1049ff42447f71582b9b56370f81cfe6c62811a57897njn   struct vki_sockaddr_un*  sun  = (struct vki_sockaddr_un *)sa;
1050ff42447f71582b9b56370f81cfe6c62811a57897njn   struct vki_sockaddr_in*  sin  = (struct vki_sockaddr_in *)sa;
1051ff42447f71582b9b56370f81cfe6c62811a57897njn   struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
105219ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#  ifdef VKI_AF_BLUETOOTH
1053ada5ad79e5d8ecf47838319a46ea4671079e6291mjw   struct vki_sockaddr_rc*  rc   = (struct vki_sockaddr_rc *)sa;
105419ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#  endif
105519ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#  ifdef VKI_AF_NETLINK
105619ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj   struct vki_sockaddr_nl*  nl   = (struct vki_sockaddr_nl *)sa;
105719ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#  endif
1058ff7c1ab3c10c5a7cf2aacb554f76fc1e40bf1901sewardj
1059ff7c1ab3c10c5a7cf2aacb554f76fc1e40bf1901sewardj   /* NULL/zero-length sockaddrs are legal */
1060ff7c1ab3c10c5a7cf2aacb554f76fc1e40bf1901sewardj   if ( sa == NULL || salen == 0 ) return;
1061ff7c1ab3c10c5a7cf2aacb554f76fc1e40bf1901sewardj
106277eb20b3865e7b17c7695c7e7a526b52935f593eflorian   outmsg = VG_(malloc) ( "di.syswrap.pmr_sockaddr.1",
106377eb20b3865e7b17c7695c7e7a526b52935f593eflorian                          VG_(strlen)( description ) + 30 );
1064c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
1065ff42447f71582b9b56370f81cfe6c62811a57897njn   VG_(sprintf) ( outmsg, description, "sa_family" );
1066ef0c7663cb71101c7b718108253444cb75402cbbnethercote   PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
1067855d93d2e9940890b28874520fa4c1677bf825e2jsgf
1068c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj   switch (sa->sa_family) {
1069c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
107073b526fb4af0f60634f0078583d92b931d5c0eebnethercote      case VKI_AF_UNIX:
1071ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sun_path" );
1072ff42447f71582b9b56370f81cfe6c62811a57897njn         PRE_MEM_RASCIIZ( outmsg, (Addr) sun->sun_path );
1073f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         // GrP fixme max of sun_len-2? what about nul char?
1074c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj         break;
1075c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
107673b526fb4af0f60634f0078583d92b931d5c0eebnethercote      case VKI_AF_INET:
1077ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin_port" );
1078ff42447f71582b9b56370f81cfe6c62811a57897njn         PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) );
1079ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin_addr" );
1080ff42447f71582b9b56370f81cfe6c62811a57897njn         PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) );
1081c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj         break;
1082c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
108373b526fb4af0f60634f0078583d92b931d5c0eebnethercote      case VKI_AF_INET6:
1084ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin6_port" );
1085ef0c7663cb71101c7b718108253444cb75402cbbnethercote         PRE_MEM_READ( outmsg,
1086ff42447f71582b9b56370f81cfe6c62811a57897njn            (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) );
1087ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin6_flowinfo" );
1088ef0c7663cb71101c7b718108253444cb75402cbbnethercote         PRE_MEM_READ( outmsg,
1089ff42447f71582b9b56370f81cfe6c62811a57897njn            (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) );
1090ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin6_addr" );
1091ef0c7663cb71101c7b718108253444cb75402cbbnethercote         PRE_MEM_READ( outmsg,
1092ff42447f71582b9b56370f81cfe6c62811a57897njn            (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) );
1093ff42447f71582b9b56370f81cfe6c62811a57897njn         VG_(sprintf) ( outmsg, description, "sin6_scope_id" );
1094ef0c7663cb71101c7b718108253444cb75402cbbnethercote         PRE_MEM_READ( outmsg,
1095ff42447f71582b9b56370f81cfe6c62811a57897njn            (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) );
1096c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj         break;
10974cb663fdaa2a63efc447f7251270446c4e8c9611mjw
109819ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#     ifdef VKI_AF_BLUETOOTH
1099ada5ad79e5d8ecf47838319a46ea4671079e6291mjw      case VKI_AF_BLUETOOTH:
1100ada5ad79e5d8ecf47838319a46ea4671079e6291mjw         VG_(sprintf) ( outmsg, description, "rc_bdaddr" );
1101ada5ad79e5d8ecf47838319a46ea4671079e6291mjw         PRE_MEM_READ( outmsg, (Addr) &rc->rc_bdaddr, sizeof (rc->rc_bdaddr) );
1102ada5ad79e5d8ecf47838319a46ea4671079e6291mjw         VG_(sprintf) ( outmsg, description, "rc_channel" );
1103ada5ad79e5d8ecf47838319a46ea4671079e6291mjw         PRE_MEM_READ( outmsg, (Addr) &rc->rc_channel, sizeof (rc->rc_channel) );
1104ada5ad79e5d8ecf47838319a46ea4671079e6291mjw         break;
110519ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#     endif
110619ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj
110719ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#     ifdef VKI_AF_NETLINK
110819ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj      case VKI_AF_NETLINK:
110919ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj         VG_(sprintf)(outmsg, description, "nl_pid");
111019ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj         PRE_MEM_READ(outmsg, (Addr)&nl->nl_pid, sizeof(nl->nl_pid));
111119ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj         VG_(sprintf)(outmsg, description, "nl_groups");
111219ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj         PRE_MEM_READ(outmsg, (Addr)&nl->nl_groups, sizeof(nl->nl_groups));
111319ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj         break;
111419ce5d572999bbccb6e380cf8bafb50d880c91f4sewardj#     endif
1115ada5ad79e5d8ecf47838319a46ea4671079e6291mjw
1116aa62d8484d5414a997c06a06ca3d03ab69855a60sewardj#     ifdef VKI_AF_UNSPEC
1117aa62d8484d5414a997c06a06ca3d03ab69855a60sewardj      case VKI_AF_UNSPEC:
1118aa62d8484d5414a997c06a06ca3d03ab69855a60sewardj         break;
1119aa62d8484d5414a997c06a06ca3d03ab69855a60sewardj#     endif
1120aa62d8484d5414a997c06a06ca3d03ab69855a60sewardj
1121c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj      default:
1122c06f684badc0701961e68dbc206fbf1757f7fd68philippe         /* No specific information about this address family.
1123c06f684badc0701961e68dbc206fbf1757f7fd68philippe            Let's just check the full data following the family.
1124c06f684badc0701961e68dbc206fbf1757f7fd68philippe            Note that this can give false positive if this (unknown)
1125c06f684badc0701961e68dbc206fbf1757f7fd68philippe            struct sockaddr_???? has padding bytes between its elements. */
1126c06f684badc0701961e68dbc206fbf1757f7fd68philippe         VG_(sprintf) ( outmsg, description, "sa_data" );
1127c06f684badc0701961e68dbc206fbf1757f7fd68philippe         PRE_MEM_READ( outmsg, (Addr)&sa->sa_family + sizeof(sa->sa_family),
112890a707399e43f1d8dfd0b8a4539d3beb7ec20420philippe                       salen -  sizeof(sa->sa_family));
1129c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj         break;
1130c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj   }
1131c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
113277eb20b3865e7b17c7695c7e7a526b52935f593eflorian   VG_(free) ( outmsg );
1133c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj}
1134c483e8fb94d84a57ac6df5e18f38465134d215bdsewardj
1135e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* Dereference a pointer to a UInt. */
1136e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianstatic UInt deref_UInt ( ThreadId tid, Addr a, const HChar* s )
1137e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn{
1138e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   UInt* a_p = (UInt*)a;
1139ef0c7663cb71101c7b718108253444cb75402cbbnethercote   PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
1140e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   if (a_p == NULL)
1141e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      return 0;
1142e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   else
1143e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      return *a_p;
1144e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn}
1145de4a1d01951937632098a6cda45859afa587a06fsewardj
1146f37a81bac9893b05fdb7166be94734babc7ad2c4njnvoid ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p,
1147e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                                  const HChar* buf_s, const HChar* buflen_s )
1148e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn{
114951d827bcd88ce045a383ea1ca81768757df2d1fanjn   if (VG_(tdict).track_pre_mem_write) {
115072718649e68c7eaf3d0b8cd3deebde198b2ea84dnjn      UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
1151e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      if (buflen_in > 0) {
1152cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(tdict).track_pre_mem_write(
1153cda2f0fbda4c4b2644babc830244be8aed95de1dnjn            Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
1154e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      }
1155e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   }
1156e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn}
1157de4a1d01951937632098a6cda45859afa587a06fsewardj
1158f37a81bac9893b05fdb7166be94734babc7ad2c4njnvoid ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res,
1159e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                                   Addr buf_p, Addr buflen_p, const HChar* s )
1160e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn{
1161cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!sr_isError(res) && VG_(tdict).track_post_mem_write) {
116272718649e68c7eaf3d0b8cd3deebde198b2ea84dnjn      UInt buflen_out = deref_UInt( tid, buflen_p, s);
1163e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      if (buflen_out > 0 && buf_p != (Addr)NULL) {
116451d827bcd88ce045a383ea1ca81768757df2d1fanjn         VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
1165e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      }
1166e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   }
1167e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn}
1168de4a1d01951937632098a6cda45859afa587a06fsewardj
1169e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* ---------------------------------------------------------------------
1170e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   Data seg end, for brk()
1171e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   ------------------------------------------------------------------ */
11722e93c50dc50235189661b70e3f27a4098d5cccccsewardj
117345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*   +--------+------------+
117445f4e7c91119c7d01a59f5e827c67841632c9314sewardj     | anon   |    resvn   |
117545f4e7c91119c7d01a59f5e827c67841632c9314sewardj     +--------+------------+
117645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
117745f4e7c91119c7d01a59f5e827c67841632c9314sewardj     ^     ^  ^
117845f4e7c91119c7d01a59f5e827c67841632c9314sewardj     |     |  boundary is page aligned
117945f4e7c91119c7d01a59f5e827c67841632c9314sewardj     |     VG_(brk_limit) -- no alignment constraint
118045f4e7c91119c7d01a59f5e827c67841632c9314sewardj     VG_(brk_base) -- page aligned -- does not move
118145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
118245f4e7c91119c7d01a59f5e827c67841632c9314sewardj     Both the anon part and the reservation part are always at least
118345f4e7c91119c7d01a59f5e827c67841632c9314sewardj     one page.
118445f4e7c91119c7d01a59f5e827c67841632c9314sewardj*/
1185ce47126a7eb32765c5700c8adc3f5958aabc6394nethercote
118645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Set the new data segment end to NEWBRK.  If this succeeds, return
118745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NEWBRK, else return the current data segment end. */
118845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1189981abb5e4a0f43049ed7efac90cfa52ac61b5140florianstatic Addr do_brk ( Addr newbrk, ThreadId tid )
119045f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
1191ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   NSegment const* aseg;
119245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr newbrkP;
119345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SizeT delta;
119445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool debug = False;
119598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
119698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge   if (debug)
1197a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      VG_(printf)("\ndo_brk: brk_base=%#lx brk_limit=%#lx newbrk=%#lx\n",
119898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge		  VG_(brk_base), VG_(brk_limit), newbrk);
119998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
120095f1037b50883fa81420116d7a694be0099ab015florian   if (0) VG_(am_show_nsegments)(0, "in_brk");
1201548be6d64c58729588a559b1512ad7625bc1b86esewardj
120245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (newbrk < VG_(brk_base))
120345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Clearly impossible. */
120445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto bad;
120545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
120695f1037b50883fa81420116d7a694be0099ab015florian   if (newbrk < VG_(brk_limit)) {
120745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* shrinking the data segment.  Be lazy and don't munmap the
120845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         excess area. */
1209ef1cf8b3583107c7d918c60895937f09969d5b3esewardj      NSegment const * seg = VG_(am_find_nsegment)(newbrk);
121095f1037b50883fa81420116d7a694be0099ab015florian      vg_assert(seg);
121195f1037b50883fa81420116d7a694be0099ab015florian
121295f1037b50883fa81420116d7a694be0099ab015florian      if (seg->hasT)
121345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
121445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                    "do_brk(shrink)" );
1215d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj      /* Since we're being lazy and not unmapping pages, we have to
1216d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         zero out the area, so that if the area later comes back into
1217d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         circulation, it will be filled with zeroes, as if it really
1218d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         had been unmapped and later remapped.  Be a bit paranoid and
1219d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         try hard to ensure we're not going to segfault by doing the
1220d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         write - check both ends of the range are in the same segment
1221d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj         and that segment is writable. */
122295f1037b50883fa81420116d7a694be0099ab015florian      NSegment const * seg2;
122395f1037b50883fa81420116d7a694be0099ab015florian
1224e787fcafaaa6bb8e794b27522f2038a3e128164cflorian      seg2 = VG_(am_find_nsegment)( VG_(brk_limit) - 1 );
122595f1037b50883fa81420116d7a694be0099ab015florian      vg_assert(seg2);
122695f1037b50883fa81420116d7a694be0099ab015florian
122795f1037b50883fa81420116d7a694be0099ab015florian      if (seg == seg2 && seg->hasW)
122895f1037b50883fa81420116d7a694be0099ab015florian         VG_(memset)( (void*)newbrk, 0, VG_(brk_limit) - newbrk );
1229d2d241b62cf81f3f0c2dbd14190a24f25c17e50fsewardj
123045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(brk_limit) = newbrk;
123145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return newbrk;
123245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
123398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
123445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* otherwise we're expanding the brk segment. */
12358e5963ddf24d3164b7de52f73fff090d9fc72d6atom   if (VG_(brk_limit) > VG_(brk_base))
12368e5963ddf24d3164b7de52f73fff090d9fc72d6atom      aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
12378e5963ddf24d3164b7de52f73fff090d9fc72d6atom   else
12388e5963ddf24d3164b7de52f73fff090d9fc72d6atom      aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
123945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
124045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* These should be assured by setup_client_dataseg in m_main. */
124145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(aseg);
124245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(aseg->kind == SkAnonC);
124345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
124495f1037b50883fa81420116d7a694be0099ab015florian   if (newbrk <= aseg->end + 1) {
124545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* still fits within the anon segment. */
124645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(brk_limit) = newbrk;
124745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return newbrk;
124845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
124998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
125045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   newbrkP = VG_PGROUNDUP(newbrk);
125195f1037b50883fa81420116d7a694be0099ab015florian   delta = newbrkP - (aseg->end + 1);
125245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(delta > 0);
125345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   vg_assert(VG_IS_PAGE_ALIGNED(delta));
125445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1255981abb5e4a0f43049ed7efac90cfa52ac61b5140florian   Bool overflow;
125615fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian   if (! VG_(am_extend_into_adjacent_reservation_client)( aseg->start, delta,
1257981abb5e4a0f43049ed7efac90cfa52ac61b5140florian                                                          &overflow)) {
1258981abb5e4a0f43049ed7efac90cfa52ac61b5140florian      if (overflow)
1259981abb5e4a0f43049ed7efac90cfa52ac61b5140florian         VG_(umsg)("brk segment overflow in thread #%d: can't grow to %#lx\n",
1260981abb5e4a0f43049ed7efac90cfa52ac61b5140florian                   tid, newbrkP);
1261981abb5e4a0f43049ed7efac90cfa52ac61b5140florian      else
1262981abb5e4a0f43049ed7efac90cfa52ac61b5140florian         VG_(umsg)("Cannot map memory to grow brk segment in thread #%d "
1263981abb5e4a0f43049ed7efac90cfa52ac61b5140florian                   "to %#lx\n", tid, newbrkP);
1264888b8159535580b30550f99cb7361f62edd83100florian      goto bad;
1265981abb5e4a0f43049ed7efac90cfa52ac61b5140florian   }
126698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
126745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(brk_limit) = newbrk;
126845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return newbrk;
126998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
127045f4e7c91119c7d01a59f5e827c67841632c9314sewardj  bad:
127145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(brk_limit);
127298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
1273e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
127498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
1275e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn/* ---------------------------------------------------------------------
1276855d93d2e9940890b28874520fa4c1677bf825e2jsgf   Vet file descriptors for sanity
1277e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   ------------------------------------------------------------------ */
127804236905926acaf6288177f23d75c85a7540120esewardj/*
127904236905926acaf6288177f23d75c85a7540120esewardj> - what does the "Bool soft" parameter mean?
128004236905926acaf6288177f23d75c85a7540120esewardj
128104236905926acaf6288177f23d75c85a7540120esewardj(Tom Hughes, 3 Oct 05):
128204236905926acaf6288177f23d75c85a7540120esewardj
128304236905926acaf6288177f23d75c85a7540120esewardjWhether or not to consider a file descriptor invalid if it is above
128404236905926acaf6288177f23d75c85a7540120esewardjthe current soft limit.
128504236905926acaf6288177f23d75c85a7540120esewardj
128604236905926acaf6288177f23d75c85a7540120esewardjBasically if we are testing whether a newly created file descriptor is
128704236905926acaf6288177f23d75c85a7540120esewardjvalid (in a post handler) then we set soft to true, and if we are
128804236905926acaf6288177f23d75c85a7540120esewardjtesting whether a file descriptor that is about to be used (in a pre
128904236905926acaf6288177f23d75c85a7540120esewardjhandler) is valid [viz, an already-existing fd] then we set it to false.
129004236905926acaf6288177f23d75c85a7540120esewardj
129104236905926acaf6288177f23d75c85a7540120esewardjThe point is that if the (virtual) soft limit is lowered then any
129204236905926acaf6288177f23d75c85a7540120esewardjexisting descriptors can still be read/written/closed etc (so long as
129304236905926acaf6288177f23d75c85a7540120esewardjthey are below the valgrind reserved descriptors) but no new
129404236905926acaf6288177f23d75c85a7540120esewardjdescriptors can be created above the new soft limit.
129504236905926acaf6288177f23d75c85a7540120esewardj
129604236905926acaf6288177f23d75c85a7540120esewardj(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
129704236905926acaf6288177f23d75c85a7540120esewardj*/
1298de4a1d01951937632098a6cda45859afa587a06fsewardj
1299855d93d2e9940890b28874520fa4c1677bf825e2jsgf/* Return true if we're allowed to use or create this fd */
1300e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianBool ML_(fd_allowed)(Int fd, const HChar *syscallname, ThreadId tid,
1301e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                     Bool isNewFd)
1302de4a1d01951937632098a6cda45859afa587a06fsewardj{
130304236905926acaf6288177f23d75c85a7540120esewardj   Bool allowed = True;
130404236905926acaf6288177f23d75c85a7540120esewardj
130504236905926acaf6288177f23d75c85a7540120esewardj   /* hard limits always apply */
130604236905926acaf6288177f23d75c85a7540120esewardj   if (fd < 0 || fd >= VG_(fd_hard_limit))
130704236905926acaf6288177f23d75c85a7540120esewardj      allowed = False;
130804236905926acaf6288177f23d75c85a7540120esewardj
1309738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   /* hijacking the output fds is never allowed */
1310738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd)
131104236905926acaf6288177f23d75c85a7540120esewardj      allowed = False;
131204236905926acaf6288177f23d75c85a7540120esewardj
131304236905926acaf6288177f23d75c85a7540120esewardj   /* if creating a new fd (rather than using an existing one), the
131404236905926acaf6288177f23d75c85a7540120esewardj      soft limit must also be observed */
131504236905926acaf6288177f23d75c85a7540120esewardj   if (isNewFd && fd >= VG_(fd_soft_limit))
131604236905926acaf6288177f23d75c85a7540120esewardj      allowed = False;
131704236905926acaf6288177f23d75c85a7540120esewardj
131804236905926acaf6288177f23d75c85a7540120esewardj   /* this looks like it ought to be included, but causes problems: */
131904236905926acaf6288177f23d75c85a7540120esewardj   /*
132004236905926acaf6288177f23d75c85a7540120esewardj   if (fd == 2 && VG_(debugLog_getLevel)() > 0)
132104236905926acaf6288177f23d75c85a7540120esewardj      allowed = False;
132204236905926acaf6288177f23d75c85a7540120esewardj   */
132304236905926acaf6288177f23d75c85a7540120esewardj   /* The difficulty is as follows: consider a program P which expects
132404236905926acaf6288177f23d75c85a7540120esewardj      to be able to mess with (redirect) its own stderr (fd 2).
132504236905926acaf6288177f23d75c85a7540120esewardj      Usually to deal with P we would issue command line flags to send
132604236905926acaf6288177f23d75c85a7540120esewardj      logging somewhere other than stderr, so as not to disrupt P.
132704236905926acaf6288177f23d75c85a7540120esewardj      The problem is that -d unilaterally hijacks stderr with no
132804236905926acaf6288177f23d75c85a7540120esewardj      consultation with P.  And so, if this check is enabled, P will
132904236905926acaf6288177f23d75c85a7540120esewardj      work OK normally but fail if -d is issued.
133004236905926acaf6288177f23d75c85a7540120esewardj
133104236905926acaf6288177f23d75c85a7540120esewardj      Basically -d is a hack and you take your chances when using it.
133204236905926acaf6288177f23d75c85a7540120esewardj      It's very useful for low level debugging -- particularly at
133304236905926acaf6288177f23d75c85a7540120esewardj      startup -- and having its presence change the behaviour of the
133404236905926acaf6288177f23d75c85a7540120esewardj      client is exactly what we don't want.  */
133504236905926acaf6288177f23d75c85a7540120esewardj
133604236905926acaf6288177f23d75c85a7540120esewardj   /* croak? */
133704236905926acaf6288177f23d75c85a7540120esewardj   if ((!allowed) && VG_(showing_core_errors)() ) {
1338d9320a4a43b89ef5fc3b81a308816884ce92c0e9jseward      VG_(message)(Vg_UserMsg,
1339738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "Warning: invalid file descriptor %d in syscall %s()\n",
13401543adfbbb9bf65687148d2c8d5dd7e883dd7769nethercote         fd, syscallname);
1341738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (fd == VG_(log_output_sink).fd && VG_(log_output_sink).fd >= 0)
1342d9320a4a43b89ef5fc3b81a308816884ce92c0e9jseward	 VG_(message)(Vg_UserMsg,
1343738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            "   Use --log-fd=<number> to select an alternative log fd.\n");
1344738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (fd == VG_(xml_output_sink).fd && VG_(xml_output_sink).fd >= 0)
1345738856f99eea33d86ce91dcb1d6cd5b151e307casewardj	 VG_(message)(Vg_UserMsg,
1346738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            "   Use --xml-fd=<number> to select an alternative XML "
1347738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            "output fd.\n");
1348eb04c8904805cd38872b0ca3134254570c943a30njn      // DDD: consider always printing this stack trace, it's useful.
1349eb04c8904805cd38872b0ca3134254570c943a30njn      // Also consider also making this a proper core error, ie.
1350eb04c8904805cd38872b0ca3134254570c943a30njn      // suppressible and all that.
1351855d93d2e9940890b28874520fa4c1677bf825e2jsgf      if (VG_(clo_verbosity) > 1) {
1352d01fef7de693582a6ce32bdbef7c9040ad6b356bnjn         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1353855d93d2e9940890b28874520fa4c1677bf825e2jsgf      }
13541075931fcc5bf309074e478ac8369873a5a51bbesewardj   }
135504236905926acaf6288177f23d75c85a7540120esewardj
135604236905926acaf6288177f23d75c85a7540120esewardj   return allowed;
1357855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
1358de4a1d01951937632098a6cda45859afa587a06fsewardj
1359de4a1d01951937632098a6cda45859afa587a06fsewardj
1360855d93d2e9940890b28874520fa4c1677bf825e2jsgf/* ---------------------------------------------------------------------
13619efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Deal with a bunch of socket-related syscalls
13629efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   ------------------------------------------------------------------ */
13639efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
13649efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
13659efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1366987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
13677eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_socketpair) ( ThreadId tid,
13689efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                  UWord arg0, UWord arg1,
13699efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                  UWord arg2, UWord arg3 )
13709efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
13719efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int socketpair(int d, int type, int protocol, int sv[2]); */
13729efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_WRITE( "socketcall.socketpair(sv)",
13739efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  arg3, 2*sizeof(int) );
13749efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
13759efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1376a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjSysRes
13777eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_socketpair) ( ThreadId tid,
1378a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                                   SysRes res,
1379987a8eb9731107bdb52e7747c2b5c516a5199beasewardj                                   UWord arg0, UWord arg1,
1380987a8eb9731107bdb52e7747c2b5c516a5199beasewardj                                   UWord arg2, UWord arg3 )
13819efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1382a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SysRes r = res;
13839efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Int fd1 = ((Int*)arg3)[0];
13849efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Int fd2 = ((Int*)arg3)[1];
1385cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
13869efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   POST_MEM_WRITE( arg3, 2*sizeof(int) );
13877eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
13887eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj       !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
13899efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      VG_(close)(fd1);
13909efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      VG_(close)(fd2);
1391a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
13929efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   } else {
13939efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      POST_MEM_WRITE( arg3, 2*sizeof(int) );
13949efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      if (VG_(clo_track_fds)) {
1395f845f8ffb1d2fac86714e32f4e279700b07722dfnjn         ML_(record_fd_open_nameless)(tid, fd1);
1396f845f8ffb1d2fac86714e32f4e279700b07722dfnjn         ML_(record_fd_open_nameless)(tid, fd2);
13979efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      }
13989efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   }
13999efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   return r;
14009efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14019efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
14029efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
14039efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1404a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjSysRes
14057eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
14069efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1407a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SysRes r = res;
1408cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1409cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) {
1410cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      VG_(close)(sr_Res(res));
1411a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
14129efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   } else {
14139efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      if (VG_(clo_track_fds))
1414cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         ML_(record_fd_open_nameless)(tid, sr_Res(res));
14159efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   }
14169efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   return r;
14179efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14189efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
14199efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
14209efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1421987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
14227eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_bind) ( ThreadId tid,
14239efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                            UWord arg0, UWord arg1, UWord arg2 )
14249efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
14259efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int bind(int sockfd, struct sockaddr *my_addr,
14269efbbef43ba82de66e77c16a9319915b7346a5d3sewardj               int addrlen); */
14279efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   pre_mem_read_sockaddr(
14289efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      tid, "socketcall.bind(my_addr.%s)",
14299efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      (struct vki_sockaddr *) arg1, arg2
14309efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   );
14319efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14329efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
14339efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
14349efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1435987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
14367eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_accept) ( ThreadId tid,
14379efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                              UWord arg0, UWord arg1, UWord arg2 )
14389efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
14399efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int accept(int s, struct sockaddr *addr, int *addrlen); */
14409efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr addr_p     = arg1;
14419efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr addrlen_p  = arg2;
14429efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   if (addr_p != (Addr)NULL)
1443f37a81bac9893b05fdb7166be94734babc7ad2c4njn      ML_(buf_and_len_pre_check) ( tid, addr_p, addrlen_p,
1444f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                   "socketcall.accept(addr)",
1445f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                   "socketcall.accept(addrlen_in)" );
14469efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14479efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1448a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjSysRes
14497eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_accept) ( ThreadId tid,
1450a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                               SysRes res,
1451987a8eb9731107bdb52e7747c2b5c516a5199beasewardj                               UWord arg0, UWord arg1, UWord arg2 )
14529efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1453a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SysRes r = res;
1454cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1455cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) {
1456cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      VG_(close)(sr_Res(res));
1457a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
14589efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   } else {
14599efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      Addr addr_p     = arg1;
14609efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      Addr addrlen_p  = arg2;
14619efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      if (addr_p != (Addr)NULL)
1462f37a81bac9893b05fdb7166be94734babc7ad2c4njn         ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p,
1463f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                       "socketcall.accept(addrlen_out)" );
14649efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      if (VG_(clo_track_fds))
1465cda2f0fbda4c4b2644babc830244be8aed95de1dnjn          ML_(record_fd_open_nameless)(tid, sr_Res(res));
14669efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   }
14679efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   return r;
14689efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14699efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
14709efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
14719efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1472987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
14737eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_sendto) ( ThreadId tid,
14749efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                              UWord arg0, UWord arg1, UWord arg2,
14759efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                              UWord arg3, UWord arg4, UWord arg5 )
14769efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
14779efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int sendto(int s, const void *msg, int len,
14789efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 unsigned int flags,
14799efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 const struct sockaddr *to, int tolen); */
14809efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_READ( "socketcall.sendto(msg)",
14819efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 arg1, /* msg */
14829efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 arg2  /* len */ );
14839efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   pre_mem_read_sockaddr(
14849efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      tid, "socketcall.sendto(to.%s)",
14859efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      (struct vki_sockaddr *) arg4, arg5
14869efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   );
14879efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
14889efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
14899efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
14909efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1491987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
14927eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_send) ( ThreadId tid,
14939efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                            UWord arg0, UWord arg1, UWord arg2 )
14949efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
14959efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int send(int s, const void *msg, size_t len, int flags); */
14969efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_READ( "socketcall.send(msg)",
14979efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  arg1, /* msg */
14989efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  arg2  /* len */ );
14999efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15009efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15019efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15029efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
15039efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1504987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15057eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
15069efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                UWord arg0, UWord arg1, UWord arg2,
15079efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                UWord arg3, UWord arg4, UWord arg5 )
15089efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15099efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int recvfrom(int s, void *buf, int len, unsigned int flags,
15109efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                   struct sockaddr *from, int *fromlen); */
15119efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr buf_p      = arg1;
15129efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Int  len        = arg2;
15139efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr from_p     = arg4;
15149efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr fromlen_p  = arg5;
15159efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
15169efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   if (from_p != (Addr)NULL)
1517f37a81bac9893b05fdb7166be94734babc7ad2c4njn      ML_(buf_and_len_pre_check) ( tid, from_p, fromlen_p,
1518f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                   "socketcall.recvfrom(from)",
1519f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                   "socketcall.recvfrom(fromlen_in)" );
15209efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15219efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1522987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15237eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_recvfrom) ( ThreadId tid,
1524a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                                 SysRes res,
15259efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                 UWord arg0, UWord arg1, UWord arg2,
15269efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                 UWord arg3, UWord arg4, UWord arg5 )
15279efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15289efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr buf_p      = arg1;
15299efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Int  len        = arg2;
15309efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr from_p     = arg4;
15319efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr fromlen_p  = arg5;
15329efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1533cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
15349efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   if (from_p != (Addr)NULL)
1535f37a81bac9893b05fdb7166be94734babc7ad2c4njn      ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p,
1536f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                    "socketcall.recvfrom(fromlen_out)" );
15379efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   POST_MEM_WRITE( buf_p, len );
15389efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15399efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15409efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
15419efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1542987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15437eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_recv) ( ThreadId tid,
15449efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                            UWord arg0, UWord arg1, UWord arg2 )
15459efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15469efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int recv(int s, void *buf, int len, unsigned int flags); */
15479efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* man 2 recv says:
15489efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      The  recv call is normally used only on a connected socket
15499efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      (see connect(2)) and is identical to recvfrom with a  NULL
15509efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      from parameter.
15519efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   */
15529efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_WRITE( "socketcall.recv(buf)",
15539efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  arg1, /* buf */
15549efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  arg2  /* len */ );
15559efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15569efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1557987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15587eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_recv) ( ThreadId tid,
15599efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                             UWord res,
15609efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                             UWord arg0, UWord arg1, UWord arg2 )
15619efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15629efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   if (res >= 0 && arg1 != 0) {
15639efbbef43ba82de66e77c16a9319915b7346a5d3sewardj      POST_MEM_WRITE( arg1, /* buf */
15649efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                      arg2  /* len */ );
15659efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   }
15669efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15679efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15689efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
15699efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1570987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15717eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_connect) ( ThreadId tid,
15729efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                               UWord arg0, UWord arg1, UWord arg2 )
15739efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15749efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int connect(int sockfd,
15759efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                  struct sockaddr *serv_addr, int addrlen ); */
15769efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   pre_mem_read_sockaddr( tid,
15779efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                          "socketcall.connect(serv_addr.%s)",
15789efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                          (struct vki_sockaddr *) arg1, arg2);
15799efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15809efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15819efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
15829efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1583987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15847eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
15859efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                  UWord arg0, UWord arg1, UWord arg2,
15869efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                  UWord arg3, UWord arg4 )
15879efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
15889efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int setsockopt(int s, int level, int optname,
15899efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                     const void *optval, int optlen); */
15909efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   PRE_MEM_READ( "socketcall.setsockopt(optval)",
15919efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 arg3, /* optval */
15929efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                 arg4  /* optlen */ );
15939efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
15949efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
15959efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
15969efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1597987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
15987eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_getsockname) ( ThreadId tid,
15999efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                   UWord arg0, UWord arg1, UWord arg2 )
16009efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
16019efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int getsockname(int s, struct sockaddr* name, int* namelen) */
16029efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr name_p     = arg1;
16039efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr namelen_p  = arg2;
16049efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* Nb: name_p cannot be NULL */
1605f37a81bac9893b05fdb7166be94734babc7ad2c4njn   ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1606f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                "socketcall.getsockname(name)",
1607f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                "socketcall.getsockname(namelen_in)" );
16089efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16099efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1610987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
16117eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_getsockname) ( ThreadId tid,
1612a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                                    SysRes res,
16139efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                    UWord arg0, UWord arg1, UWord arg2 )
16149efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
16159efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr name_p     = arg1;
16169efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr namelen_p  = arg2;
1617cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1618f37a81bac9893b05fdb7166be94734babc7ad2c4njn   ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1619f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                 "socketcall.getsockname(namelen_out)" );
16209efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16219efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
16229efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
16239efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1624987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
16257eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_getpeername) ( ThreadId tid,
16269efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                   UWord arg0, UWord arg1, UWord arg2 )
16279efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
16289efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* int getpeername(int s, struct sockaddr* name, int* namelen) */
16299efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr name_p     = arg1;
16309efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr namelen_p  = arg2;
16319efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   /* Nb: name_p cannot be NULL */
1632f37a81bac9893b05fdb7166be94734babc7ad2c4njn   ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1633f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                "socketcall.getpeername(name)",
1634f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                "socketcall.getpeername(namelen_in)" );
16359efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16369efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1637987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
16387eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_getpeername) ( ThreadId tid,
1639a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                                    SysRes res,
16409efbbef43ba82de66e77c16a9319915b7346a5d3sewardj                                    UWord arg0, UWord arg1, UWord arg2 )
16419efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
16429efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr name_p     = arg1;
16439efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   Addr namelen_p  = arg2;
1644cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1645f37a81bac9893b05fdb7166be94734babc7ad2c4njn   ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1646f37a81bac9893b05fdb7166be94734babc7ad2c4njn                                 "socketcall.getpeername(namelen_out)" );
16479efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16489efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
16499efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
16509efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1651987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
1652e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianML_(generic_PRE_sys_sendmsg) ( ThreadId tid, const HChar *name,
1653e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                               struct vki_msghdr *msg )
16549efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1655fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom   msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_read_sendmsg, False );
16569efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16579efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
16589efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ------ */
16599efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1660987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
1661e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianML_(generic_PRE_sys_recvmsg) ( ThreadId tid, const HChar *name,
1662e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                               struct vki_msghdr *msg )
16639efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1664fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom   msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_write_recvmsg, True );
16659efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16669efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
1667987a8eb9731107bdb52e7747c2b5c516a5199beasewardjvoid
1668e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianML_(generic_POST_sys_recvmsg) ( ThreadId tid, const HChar *name,
1669e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian                                struct vki_msghdr *msg, UInt length )
16709efbbef43ba82de66e77c16a9319915b7346a5d3sewardj{
1671fc75e5ea3e57d58bbbbd3fd8fff3a71de9a1b172tom   msghdr_foreachfield( tid, name, msg, length, post_mem_write_recvmsg, True );
16729efbbef43ba82de66e77c16a9319915b7346a5d3sewardj   check_cmsg_for_fds( tid, msg );
16739efbbef43ba82de66e77c16a9319915b7346a5d3sewardj}
16749efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
16759efbbef43ba82de66e77c16a9319915b7346a5d3sewardj
16769efbbef43ba82de66e77c16a9319915b7346a5d3sewardj/* ---------------------------------------------------------------------
1677b369c5e35c69997f9bc5798f476108da59876cfcsewardj   Deal with a bunch of IPC related syscalls
1678b369c5e35c69997f9bc5798f476108da59876cfcsewardj   ------------------------------------------------------------------ */
1679b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1680b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1681b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1682b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
16837eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_semop) ( ThreadId tid,
1684b369c5e35c69997f9bc5798f476108da59876cfcsewardj                             UWord arg0, UWord arg1, UWord arg2 )
1685b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1686b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1687b369c5e35c69997f9bc5798f476108da59876cfcsewardj   PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1688b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1689b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1690b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1691b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1692b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
16937eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
1694b369c5e35c69997f9bc5798f476108da59876cfcsewardj                                  UWord arg0, UWord arg1,
1695b369c5e35c69997f9bc5798f476108da59876cfcsewardj                                  UWord arg2, UWord arg3 )
1696b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1697b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1698b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     struct timespec *timeout); */
1699b369c5e35c69997f9bc5798f476108da59876cfcsewardj   PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1700b369c5e35c69997f9bc5798f476108da59876cfcsewardj   if (arg3 != 0)
1701b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1702b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1703b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1704b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1705b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1706b369c5e35c69997f9bc5798f476108da59876cfcsewardjstatic
1707b369c5e35c69997f9bc5798f476108da59876cfcsewardjUInt get_sem_count( Int semid )
1708b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1709a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   struct vki_semid_ds buf;
1710a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   union vki_semun arg;
1711a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SysRes res;
1712b369c5e35c69997f9bc5798f476108da59876cfcsewardj
171327f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj   /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017
171427f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj      (experimental) otherwise complains that the use in the return
171527f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj      statement below is uninitialised. */
171627f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj   buf.sem_nsems = 0;
171727f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj
1718a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   arg.buf = &buf;
1719b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1720a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#  ifdef __NR_semctl
1721a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
1722a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#  else
1723a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1724a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                          VKI_IPC_STAT, (UWord)&arg);
172527f96b3cd47d996b344a02cc5b9adf03e6ea1b43sewardj#  endif
1726cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(res))
1727a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      return 0;
1728b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1729a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   return buf.sem_nsems;
1730b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1731b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1732b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
17337eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_semctl) ( ThreadId tid,
1734b369c5e35c69997f9bc5798f476108da59876cfcsewardj                              UWord arg0, UWord arg1,
1735b369c5e35c69997f9bc5798f476108da59876cfcsewardj                              UWord arg2, UWord arg3 )
1736b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1737b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* int semctl(int semid, int semnum, int cmd, ...); */
1738b369c5e35c69997f9bc5798f476108da59876cfcsewardj   union vki_semun arg = *(union vki_semun *)&arg3;
1739b369c5e35c69997f9bc5798f476108da59876cfcsewardj   UInt nsems;
1740b369c5e35c69997f9bc5798f476108da59876cfcsewardj   switch (arg2 /* cmd */) {
1741f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_INFO)
1742b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO:
1743b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_INFO:
1744b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO|VKI_IPC_64:
1745b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_INFO|VKI_IPC_64:
1746b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1747b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     (Addr)arg.buf, sizeof(struct vki_seminfo) );
1748b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1749f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1750f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1751b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT:
1752f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SEM_STAT)
1753b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_STAT:
1754f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1755b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1756b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1757b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1758f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1760b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT|VKI_IPC_64:
1761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SEM_STAT)
1762b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_STAT|VKI_IPC_64:
1763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1764b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1765b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1766b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1767f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1768f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1769b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_SET:
1770b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1771b369c5e35c69997f9bc5798f476108da59876cfcsewardj                    (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1772b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1773f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1774f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1775b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_SET|VKI_IPC_64:
1776b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1777b369c5e35c69997f9bc5798f476108da59876cfcsewardj                    (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1778b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1779f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1780f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1781b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_GETALL:
1782f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1783b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_GETALL|VKI_IPC_64:
1784f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1785b369c5e35c69997f9bc5798f476108da59876cfcsewardj      nsems = get_sem_count( arg0 );
1786b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1787b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     (Addr)arg.array, sizeof(unsigned short) * nsems );
1788b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1789f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1790b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SETALL:
1791f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1792b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SETALL|VKI_IPC_64:
1793f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1794b369c5e35c69997f9bc5798f476108da59876cfcsewardj      nsems = get_sem_count( arg0 );
1795b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1796b369c5e35c69997f9bc5798f476108da59876cfcsewardj                    (Addr)arg.array, sizeof(unsigned short) * nsems );
1797b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1798b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
1799b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1800b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1801b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
18027eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_semctl) ( ThreadId tid,
1803b369c5e35c69997f9bc5798f476108da59876cfcsewardj                               UWord res,
1804b369c5e35c69997f9bc5798f476108da59876cfcsewardj                               UWord arg0, UWord arg1,
1805b369c5e35c69997f9bc5798f476108da59876cfcsewardj                               UWord arg2, UWord arg3 )
1806b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1807b369c5e35c69997f9bc5798f476108da59876cfcsewardj   union vki_semun arg = *(union vki_semun *)&arg3;
1808b369c5e35c69997f9bc5798f476108da59876cfcsewardj   UInt nsems;
1809b369c5e35c69997f9bc5798f476108da59876cfcsewardj   switch (arg2 /* cmd */) {
1810f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_INFO)
1811b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO:
1812b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_INFO:
1813b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO|VKI_IPC_64:
1814b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_INFO|VKI_IPC_64:
1815b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1816b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1817f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1818f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1819b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT:
1820f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SEM_STAT)
1821b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_STAT:
1822f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1823b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1824b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1825f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1826f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1827b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT|VKI_IPC_64:
1828b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SEM_STAT|VKI_IPC_64:
1829b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1830b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1831f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1832f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1833b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_GETALL:
1834f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1835b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_GETALL|VKI_IPC_64:
1836f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1837b369c5e35c69997f9bc5798f476108da59876cfcsewardj      nsems = get_sem_count( arg0 );
1838b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1839b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1840b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
1841b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1842b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1843b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1844b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1845b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1846b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1847b369c5e35c69997f9bc5798f476108da59876cfcsewardjstatic
18482d75ea221634d6f74ab9e22be9e77370c33ce457philippeSizeT get_shm_size ( Int shmid )
1849b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1850cda2f0fbda4c4b2644babc830244be8aed95de1dnjn#ifdef __NR_shmctl
1851cda2f0fbda4c4b2644babc830244be8aed95de1dnjn#  ifdef VKI_IPC_64
1852b369c5e35c69997f9bc5798f476108da59876cfcsewardj   struct vki_shmid64_ds buf;
1853c8d064a1ea7d7855c5735a388f3ad47c44d4dcb7philippe#    if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
185490741b2f5fba62332effcd9fb4c549905d909edbsewardj     /* See bug 222545 comment 7 */
185590741b2f5fba62332effcd9fb4c549905d909edbsewardj     SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
185690741b2f5fba62332effcd9fb4c549905d909edbsewardj                                     VKI_IPC_STAT, (UWord)&buf);
185790741b2f5fba62332effcd9fb4c549905d909edbsewardj#    else
185890741b2f5fba62332effcd9fb4c549905d909edbsewardj     SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
185990741b2f5fba62332effcd9fb4c549905d909edbsewardj                                     VKI_IPC_STAT|VKI_IPC_64, (UWord)&buf);
186090741b2f5fba62332effcd9fb4c549905d909edbsewardj#    endif
186190741b2f5fba62332effcd9fb4c549905d909edbsewardj#  else /* !def VKI_IPC_64 */
1862b369c5e35c69997f9bc5798f476108da59876cfcsewardj   struct vki_shmid_ds buf;
1863cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
186490741b2f5fba62332effcd9fb4c549905d909edbsewardj#  endif /* def VKI_IPC_64 */
1865cda2f0fbda4c4b2644babc830244be8aed95de1dnjn#else
1866cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   struct vki_shmid_ds buf;
1867a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
1868b369c5e35c69997f9bc5798f476108da59876cfcsewardj                                 VKI_IPC_STAT, 0, (UWord)&buf);
1869cda2f0fbda4c4b2644babc830244be8aed95de1dnjn#endif
1870cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(__res))
1871b369c5e35c69997f9bc5798f476108da59876cfcsewardj      return 0;
1872b369c5e35c69997f9bc5798f476108da59876cfcsewardj
18732d75ea221634d6f74ab9e22be9e77370c33ce457philippe   return (SizeT) buf.shm_segsz;
1874b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1875b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1876b369c5e35c69997f9bc5798f476108da59876cfcsewardjUWord
18777eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_shmat) ( ThreadId tid,
1878b369c5e35c69997f9bc5798f476108da59876cfcsewardj                             UWord arg0, UWord arg1, UWord arg2 )
1879b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1880b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
18812d75ea221634d6f74ab9e22be9e77370c33ce457philippe   SizeT  segmentSize = get_shm_size ( arg0 );
188245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   UWord tmp;
188345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool  ok;
188445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (arg1 == 0) {
188560457093d30b23ac2531682205ab0bd9a5aae2edsewardj      /* arm-linux only: work around the fact that
188660457093d30b23ac2531682205ab0bd9a5aae2edsewardj         VG_(am_get_advisory_client_simple) produces something that is
188760457093d30b23ac2531682205ab0bd9a5aae2edsewardj         VKI_PAGE_SIZE aligned, whereas what we want is something
188860457093d30b23ac2531682205ab0bd9a5aae2edsewardj         VKI_SHMLBA aligned, and VKI_SHMLBA >= VKI_PAGE_SIZE.  Hence
188960457093d30b23ac2531682205ab0bd9a5aae2edsewardj         increase the request size by VKI_SHMLBA - VKI_PAGE_SIZE and
189060457093d30b23ac2531682205ab0bd9a5aae2edsewardj         then round the result up to the next VKI_SHMLBA boundary.
189160457093d30b23ac2531682205ab0bd9a5aae2edsewardj         See bug 222545 comment 15.  So far, arm-linux is the only
189260457093d30b23ac2531682205ab0bd9a5aae2edsewardj         platform where this is known to be necessary. */
189360457093d30b23ac2531682205ab0bd9a5aae2edsewardj      vg_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
189460457093d30b23ac2531682205ab0bd9a5aae2edsewardj      if (VKI_SHMLBA > VKI_PAGE_SIZE) {
189560457093d30b23ac2531682205ab0bd9a5aae2edsewardj         segmentSize += VKI_SHMLBA - VKI_PAGE_SIZE;
189660457093d30b23ac2531682205ab0bd9a5aae2edsewardj      }
189745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
189860457093d30b23ac2531682205ab0bd9a5aae2edsewardj      if (ok) {
189960457093d30b23ac2531682205ab0bd9a5aae2edsewardj         if (VKI_SHMLBA > VKI_PAGE_SIZE) {
190060457093d30b23ac2531682205ab0bd9a5aae2edsewardj            arg1 = VG_ROUNDUP(tmp, VKI_SHMLBA);
190160457093d30b23ac2531682205ab0bd9a5aae2edsewardj         } else {
190260457093d30b23ac2531682205ab0bd9a5aae2edsewardj            arg1 = tmp;
190360457093d30b23ac2531682205ab0bd9a5aae2edsewardj         }
190460457093d30b23ac2531682205ab0bd9a5aae2edsewardj      }
190545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
19067eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
1907b369c5e35c69997f9bc5798f476108da59876cfcsewardj      arg1 = 0;
1908b369c5e35c69997f9bc5798f476108da59876cfcsewardj   return arg1;
1909b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1910b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1911b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
19127eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_shmat) ( ThreadId tid,
1913b369c5e35c69997f9bc5798f476108da59876cfcsewardj                              UWord res,
1914b369c5e35c69997f9bc5798f476108da59876cfcsewardj                              UWord arg0, UWord arg1, UWord arg2 )
1915b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
19162d75ea221634d6f74ab9e22be9e77370c33ce457philippe   SizeT segmentSize = VG_PGROUNDUP(get_shm_size(arg0));
1917b369c5e35c69997f9bc5798f476108da59876cfcsewardj   if ( segmentSize > 0 ) {
1918b369c5e35c69997f9bc5798f476108da59876cfcsewardj      UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
191945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Bool d;
1920b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1921f61fea0d88fc6cc2a6c4ff78c49aa0343529ee20tom      if (arg2 & VKI_SHM_RDONLY)
1922b369c5e35c69997f9bc5798f476108da59876cfcsewardj         prot &= ~VKI_PROT_WRITE;
192345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* It isn't exactly correct to pass 0 for the fd and offset
192445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         here.  The kernel seems to think the corresponding section
192545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         does have dev/ino numbers:
192645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
192745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         04e52000-04ec8000 rw-s 00000000 00:06 1966090  /SYSV00000000 (deleted)
192845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
192945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         However there is no obvious way to find them.  In order to
193045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         cope with the discrepancy, aspacem's sync checker omits the
193145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         dev/ino correspondence check in cases where V does not know
193245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         the dev/ino. */
1933c6fe8a25cbdc45c74d68a533c41b4e4ce2d8dec4njn      d = VG_(am_notify_client_shmat)( res, segmentSize, prot );
193445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
193545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* we don't distinguish whether it's read-only or
193645f4e7c91119c7d01a59f5e827c67841632c9314sewardj       * read-write -- it doesn't matter really. */
19379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False,
19389c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                              0/*di_handle*/ );
193945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (d)
1940ddd61ff058f02059064e083a8accaefed23d5548florian         VG_(discard_translations)( (Addr)res,
194145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                    (ULong)VG_PGROUNDUP(segmentSize),
194245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                    "ML_(generic_POST_sys_shmat)" );
1943b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
1944b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1945b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1946b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1947b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1948b369c5e35c69997f9bc5798f476108da59876cfcsewardjBool
19497eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
1950b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1951b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* int shmdt(const void *shmaddr); */
19527eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
1953b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1954b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1955b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
19567eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
1957b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1958ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   NSegment const* s = VG_(am_find_nsegment)(arg0);
195945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
19600e682c673ffc284737fcd2610e2326fc08ac21fesewardj   if (s != NULL) {
19610e682c673ffc284737fcd2610e2326fc08ac21fesewardj      Addr  s_start = s->start;
19620e682c673ffc284737fcd2610e2326fc08ac21fesewardj      SizeT s_len   = s->end+1 - s->start;
19631340c35bebb175c6d158361596ee6171b4cfc2a2tom      Bool  d;
19641340c35bebb175c6d158361596ee6171b4cfc2a2tom
19657bc57fc9c923e2630c42260d7142a5205a4bca66dirk      vg_assert(s->kind == SkShmC);
19667bc57fc9c923e2630c42260d7142a5205a4bca66dirk      vg_assert(s->start == arg0);
19671340c35bebb175c6d158361596ee6171b4cfc2a2tom
19681340c35bebb175c6d158361596ee6171b4cfc2a2tom      d = VG_(am_notify_munmap)(s_start, s_len);
19690e682c673ffc284737fcd2610e2326fc08ac21fesewardj      s = NULL; /* s is now invalid */
19700e682c673ffc284737fcd2610e2326fc08ac21fesewardj      VG_TRACK( die_mem_munmap, s_start, s_len );
197145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (d)
1972ddd61ff058f02059064e083a8accaefed23d5548florian         VG_(discard_translations)( s_start,
19730e682c673ffc284737fcd2610e2326fc08ac21fesewardj                                    (ULong)s_len,
197445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                    "ML_(generic_POST_sys_shmdt)" );
1975b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
1976b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
1977b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ------ */
1978b369c5e35c69997f9bc5798f476108da59876cfcsewardj
1979b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
19807eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_PRE_sys_shmctl) ( ThreadId tid,
1981b369c5e35c69997f9bc5798f476108da59876cfcsewardj                              UWord arg0, UWord arg1, UWord arg2 )
1982b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
1983b369c5e35c69997f9bc5798f476108da59876cfcsewardj   /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
1984b369c5e35c69997f9bc5798f476108da59876cfcsewardj   switch (arg1 /* cmd */) {
1985f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_INFO)
1986b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO:
1987b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1988b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     arg2, sizeof(struct vki_shminfo) );
1989b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1990f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
1991b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO|VKI_IPC_64:
1992b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1993b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     arg2, sizeof(struct vki_shminfo64) );
1994b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
1995f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1996f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
1997f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1998f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SHM_INFO)
1999b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_INFO:
2000f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
2001b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_INFO|VKI_IPC_64:
2002f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2003b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
2004b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     arg2, sizeof(struct vki_shm_info) );
2005b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2006f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2007f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2008b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT:
2009f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SHM_STAT)
2010b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_STAT:
2011f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2012b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
2013b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     arg2, sizeof(struct vki_shmid_ds) );
2014b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2015f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2016f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
2017b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT|VKI_IPC_64:
2018b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_STAT|VKI_IPC_64:
2019b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
2020b369c5e35c69997f9bc5798f476108da59876cfcsewardj                     arg2, sizeof(struct vki_shmid64_ds) );
2021b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2022f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2023f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2024b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_SET:
2025b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
2026b369c5e35c69997f9bc5798f476108da59876cfcsewardj                    arg2, sizeof(struct vki_shmid_ds) );
2027b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2028f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2029f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
2030b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_SET|VKI_IPC_64:
2031b369c5e35c69997f9bc5798f476108da59876cfcsewardj      PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
2032b369c5e35c69997f9bc5798f476108da59876cfcsewardj                    arg2, sizeof(struct vki_shmid64_ds) );
2033b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2034f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2035b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
2036b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
2037b369c5e35c69997f9bc5798f476108da59876cfcsewardj
2038b369c5e35c69997f9bc5798f476108da59876cfcsewardjvoid
20397eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjML_(generic_POST_sys_shmctl) ( ThreadId tid,
2040b369c5e35c69997f9bc5798f476108da59876cfcsewardj                               UWord res,
2041b369c5e35c69997f9bc5798f476108da59876cfcsewardj                               UWord arg0, UWord arg1, UWord arg2 )
2042b369c5e35c69997f9bc5798f476108da59876cfcsewardj{
2043b369c5e35c69997f9bc5798f476108da59876cfcsewardj   switch (arg1 /* cmd */) {
2044f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_INFO)
2045b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO:
2046b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
2047b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2048b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_INFO|VKI_IPC_64:
2049b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
2050b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2051f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2052f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2053f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SHM_INFO)
2054b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_INFO:
2055b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_INFO|VKI_IPC_64:
2056b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
2057b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2058f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2059f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2060b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT:
2061f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_SHM_STAT)
2062b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_STAT:
2063f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2064b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
2065b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2066f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2067f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_IPC_64)
2068b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_IPC_STAT|VKI_IPC_64:
2069b369c5e35c69997f9bc5798f476108da59876cfcsewardj   case VKI_SHM_STAT|VKI_IPC_64:
2070b369c5e35c69997f9bc5798f476108da59876cfcsewardj      POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
2071b369c5e35c69997f9bc5798f476108da59876cfcsewardj      break;
2072f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2073f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2074f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2075b369c5e35c69997f9bc5798f476108da59876cfcsewardj   }
2076b369c5e35c69997f9bc5798f476108da59876cfcsewardj}
2077b369c5e35c69997f9bc5798f476108da59876cfcsewardj
2078b369c5e35c69997f9bc5798f476108da59876cfcsewardj/* ---------------------------------------------------------------------
20799548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   Generic handler for mmap
20809548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   ------------------------------------------------------------------ */
20819548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
20826d85b04b5c645991811b574af6633bf45106d43ctom/*
20836d85b04b5c645991811b574af6633bf45106d43ctom * Although mmap is specified by POSIX and the argument are generally
20846d85b04b5c645991811b574af6633bf45106d43ctom * consistent across platforms the precise details of the low level
20856d85b04b5c645991811b574af6633bf45106d43ctom * argument passing conventions differ. For example:
20866d85b04b5c645991811b574af6633bf45106d43ctom *
20876d85b04b5c645991811b574af6633bf45106d43ctom * - On x86-linux there is mmap (aka old_mmap) which takes the
20886d85b04b5c645991811b574af6633bf45106d43ctom *   arguments in a memory block and the offset in bytes; and
20896d85b04b5c645991811b574af6633bf45106d43ctom *   mmap2 (aka sys_mmap2) which takes the arguments in the normal
20906d85b04b5c645991811b574af6633bf45106d43ctom *   way and the offset in pages.
20916d85b04b5c645991811b574af6633bf45106d43ctom *
20926d85b04b5c645991811b574af6633bf45106d43ctom * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
20936d85b04b5c645991811b574af6633bf45106d43ctom *   arguments in the normal way and the offset in bytes; and
20946d85b04b5c645991811b574af6633bf45106d43ctom *   mmap2 (aka sys_mmap2) which takes the arguments in the normal
20956d85b04b5c645991811b574af6633bf45106d43ctom *   way and the offset in pages.
20966d85b04b5c645991811b574af6633bf45106d43ctom *
20976d85b04b5c645991811b574af6633bf45106d43ctom * - On amd64-linux everything is simple and there is just the one
20986d85b04b5c645991811b574af6633bf45106d43ctom *   call, mmap (aka sys_mmap)  which takes the arguments in the
20996d85b04b5c645991811b574af6633bf45106d43ctom *   normal way and the offset in bytes.
21006d85b04b5c645991811b574af6633bf45106d43ctom *
2101b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj * - On s390x-linux there is mmap (aka old_mmap) which takes the
2102b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj *   arguments in a memory block and the offset in bytes. mmap2
2103b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj *   is also available (but not exported via unistd.h) with
2104b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj *   arguments in a memory block and the offset in pages.
2105b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj *
21066d85b04b5c645991811b574af6633bf45106d43ctom * To cope with all this we provide a generic handler function here
21076d85b04b5c645991811b574af6633bf45106d43ctom * and then each platform implements one or more system call handlers
21086d85b04b5c645991811b574af6633bf45106d43ctom * which call this generic routine after extracting and normalising
21096d85b04b5c645991811b574af6633bf45106d43ctom * the arguments.
21106d85b04b5c645991811b574af6633bf45106d43ctom */
21116d85b04b5c645991811b574af6633bf45106d43ctom
21129548a16a2cf8a0de3f4d9d72e5777e9b70481f14tomSysRes
21139548a16a2cf8a0de3f4d9d72e5777e9b70481f14tomML_(generic_PRE_sys_mmap) ( ThreadId tid,
21149548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom                            UWord arg1, UWord arg2, UWord arg3,
2115274461dcb67f680196c97e8afb7028a79b97dcb7sewardj                            UWord arg4, UWord arg5, Off64T arg6 )
21169548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom{
21179548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   Addr       advised;
21189548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   SysRes     sres;
21199548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   MapRequest mreq;
21209548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   Bool       mreq_ok;
21219548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
212280fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj#  if defined(VGO_darwin)
2123f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Nb: we can't use this on Darwin, it has races:
2124f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // * needs to RETRY if advisory succeeds but map fails
2125f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   //   (could have been some other thread in a nonblocking call)
2126f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // * needs to not use fixed-position mmap() on Darwin
2127f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   //   (mmap will cheerfully smash whatever's already there, which might
2128f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   //   be a new mapping from some other thread in a nonblocking call)
2129f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   VG_(core_panic)("can't use ML_(generic_PRE_sys_mmap) on Darwin");
213080fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj#  endif
2131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
21329548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   if (arg2 == 0) {
21339548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
21349548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom         shall be established. */
21359548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      return VG_(mk_SysRes_Error)( VKI_EINVAL );
21369548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   }
21379548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
21389548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   if (!VG_IS_PAGE_ALIGNED(arg1)) {
21399548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      /* zap any misaligned addresses. */
21409548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
21419548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom         to fail.   Here, we catch them all. */
21429548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      return VG_(mk_SysRes_Error)( VKI_EINVAL );
21439548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   }
21449548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
21457e21df8076ae62b4921d2356d8aca0237c6910fdsewardj   if (!VG_IS_PAGE_ALIGNED(arg6)) {
21467e21df8076ae62b4921d2356d8aca0237c6910fdsewardj      /* zap any misaligned offsets. */
21477e21df8076ae62b4921d2356d8aca0237c6910fdsewardj      /* SuSV3 says: The off argument is constrained to be aligned and
21487e21df8076ae62b4921d2356d8aca0237c6910fdsewardj         sized according to the value returned by sysconf() when
21497e21df8076ae62b4921d2356d8aca0237c6910fdsewardj         passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
21507e21df8076ae62b4921d2356d8aca0237c6910fdsewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
21517e21df8076ae62b4921d2356d8aca0237c6910fdsewardj   }
21527e21df8076ae62b4921d2356d8aca0237c6910fdsewardj
215380fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj#  if defined(VKI_MAP_32BIT)
215480fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj   /* We can't support MAP_32BIT (at least, not without significant
215580fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj      complication), and it's royally unportable, so if the client
215680fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj      asks for it, just fail it. */
215780fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj   if (arg4 & VKI_MAP_32BIT) {
215880fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj      return VG_(mk_SysRes_Error)( VKI_ENOMEM );
215980fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj   }
216080fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj#  endif
216180fe549a7e8ed88f20ba0ab11832c441b6151fc0sewardj
21629548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   /* Figure out what kind of allocation constraints there are
21639548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      (fixed/hint/any), and ask aspacem what we should do. */
21649548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   mreq.start = arg1;
21659548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   mreq.len   = arg2;
21669548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   if (arg4 & VKI_MAP_FIXED) {
21679548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      mreq.rkind = MFixed;
21689548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   } else
21699548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   if (arg1 != 0) {
21709548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      mreq.rkind = MHint;
21719548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   } else {
21729548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      mreq.rkind = MAny;
21739548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   }
21749548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
21759548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   /* Enquire ... */
21769548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
21779548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   if (!mreq_ok) {
21789548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      /* Our request was bounced, so we'd better fail. */
21799548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      return VG_(mk_SysRes_Error)( VKI_EINVAL );
21809548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   }
21819548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
21829548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   /* Otherwise we're OK (so far).  Install aspacem's choice of
21839548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      address, and let the mmap go through.  */
21849548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
21859548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom                                    arg4 | VKI_MAP_FIXED,
21869548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom                                    arg5, arg6);
21879548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
2188427d016169ed81e11686474acf76ba02c42eb977sewardj   /* A refinement: it may be that the kernel refused aspacem's choice
2189427d016169ed81e11686474acf76ba02c42eb977sewardj      of address.  If we were originally asked for a hinted mapping,
2190427d016169ed81e11686474acf76ba02c42eb977sewardj      there is still a last chance: try again at any address.
2191427d016169ed81e11686474acf76ba02c42eb977sewardj      Hence: */
2192cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (mreq.rkind == MHint && sr_isError(sres)) {
2193427d016169ed81e11686474acf76ba02c42eb977sewardj      mreq.start = 0;
2194427d016169ed81e11686474acf76ba02c42eb977sewardj      mreq.len   = arg2;
2195427d016169ed81e11686474acf76ba02c42eb977sewardj      mreq.rkind = MAny;
2196427d016169ed81e11686474acf76ba02c42eb977sewardj      advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2197427d016169ed81e11686474acf76ba02c42eb977sewardj      if (!mreq_ok) {
2198427d016169ed81e11686474acf76ba02c42eb977sewardj         /* Our request was bounced, so we'd better fail. */
2199427d016169ed81e11686474acf76ba02c42eb977sewardj         return VG_(mk_SysRes_Error)( VKI_EINVAL );
2200427d016169ed81e11686474acf76ba02c42eb977sewardj      }
2201427d016169ed81e11686474acf76ba02c42eb977sewardj      /* and try again with the kernel */
2202427d016169ed81e11686474acf76ba02c42eb977sewardj      sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2203427d016169ed81e11686474acf76ba02c42eb977sewardj                                       arg4 | VKI_MAP_FIXED,
2204427d016169ed81e11686474acf76ba02c42eb977sewardj                                       arg5, arg6);
2205427d016169ed81e11686474acf76ba02c42eb977sewardj   }
2206427d016169ed81e11686474acf76ba02c42eb977sewardj
220798d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe   /* Yet another refinement : sometimes valgrind chooses an address
220898d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      which is not acceptable by the kernel. This at least happens
220998d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      when mmap-ing huge pages, using the flag MAP_HUGETLB.
221098d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      valgrind aspacem does not know about huge pages, and modifying
221198d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      it to handle huge pages is not straightforward (e.g. need
221298d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      to understand special file system mount options).
221398d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      So, let's just redo an mmap, without giving any constraint to
221498d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      the kernel. If that succeeds, check with aspacem that the returned
221598d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      address is acceptable (i.e. is free).
221698d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      This will give a similar effect as if the user would have
221798d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      specified a MAP_FIXED at that address.
221898d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      The aspacem state will be correctly updated afterwards.
221998d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      We however cannot do this last refinement when the user asked
222098d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      for a fixed mapping, as the user asked a specific address. */
222198d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe   if (sr_isError(sres) && !(arg4 & VKI_MAP_FIXED)) {
222298d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      advised = 0;
222398d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      /* try mmap with NULL address and without VKI_MAP_FIXED
222498d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe         to let the kernel decide. */
222598d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
222698d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe                                       arg4,
222798d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe                                       arg5, arg6);
222898d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      if (!sr_isError(sres)) {
222998d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe         vg_assert(VG_(am_covered_by_single_free_segment)((Addr)sr_Res(sres),
223098d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe                                                           arg2));
223198d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe      }
223298d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe   }
223398d6b25e8ce18fe287b1fc9d0c46e963d622cf3dphilippe
2234cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!sr_isError(sres)) {
22359c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      ULong di_handle;
2236510521e3ad8afb569be39ba46794dbe6e7b65a72bart      /* Notify aspacem. */
2237dd3725800151572d32df10ad4df4c8aad0d3d088njn      notify_core_of_mmap(
2238cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         (Addr)sr_Res(sres), /* addr kernel actually assigned */
2239510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg2, /* length */
2240510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg3, /* prot */
22419548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom         arg4, /* the original flags value */
2242510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg5, /* fd */
2243510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg6  /* offset */
22449548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      );
22459548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom      /* Load symbols? */
2246cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres),
22475f2dcad945d0bf3aaa9c9449ae90a5f2ca69adf1sewardj                                       False/*allow_SkFileV*/, (Int)arg5 );
2248510521e3ad8afb569be39ba46794dbe6e7b65a72bart      /* Notify the tool. */
2249510521e3ad8afb569be39ba46794dbe6e7b65a72bart      notify_tool_of_mmap(
2250cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         (Addr)sr_Res(sres), /* addr kernel actually assigned */
2251510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg2, /* length */
2252510521e3ad8afb569be39ba46794dbe6e7b65a72bart         arg3, /* prot */
22539c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj         di_handle /* so the tool can refer to the read debuginfo later,
22549c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                      if it wants. */
2255510521e3ad8afb569be39ba46794dbe6e7b65a72bart      );
22569548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   }
22579548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
22589548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   /* Stay sane */
2259cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED))
2260cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      vg_assert(sr_Res(sres) == arg1);
22619548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
22629548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom   return sres;
22639548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom}
22649548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
22659548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom
22669548a16a2cf8a0de3f4d9d72e5777e9b70481f14tom/* ---------------------------------------------------------------------
22674fa681f368f50057260d6a75ab2a04de4b8436b9nethercote   The Main Entertainment ... syscall wrappers
2268855d93d2e9940890b28874520fa4c1677bf825e2jsgf   ------------------------------------------------------------------ */
2269de4a1d01951937632098a6cda45859afa587a06fsewardj
22704fa681f368f50057260d6a75ab2a04de4b8436b9nethercote/* Note: the PRE() and POST() wrappers are for the actual functions
22718ff888f31d22e31ce0370fe9205972b3b1f36e95nethercote   implementing the system calls in the OS kernel.  These mostly have
22724fa681f368f50057260d6a75ab2a04de4b8436b9nethercote   names like sys_write();  a few have names like old_mmap().  See the
2273af839f52d74df156d655201a889954133ab01be7njn   comment for ML_(syscall_table)[] for important info about the __NR_foo
22748ff888f31d22e31ce0370fe9205972b3b1f36e95nethercote   constants and their relationship to the sys_foo() functions.
22754fa681f368f50057260d6a75ab2a04de4b8436b9nethercote
227692b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote   Some notes about names used for syscalls and args:
227792b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote   - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
227892b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     ambiguity.
227992b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote
228092b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote   - For error messages, we generally use a somewhat generic name
228192b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     for the syscall (eg. "write" rather than "sys_write").  This should be
228292b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     good enough for the average user to understand what is happening,
228392b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     without confusing them with names like "sys_write".
228492b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote
228592b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote   - Also, for error messages the arg names are mostly taken from the man
228692b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     pages (even though many of those man pages are really for glibc
22878ff888f31d22e31ce0370fe9205972b3b1f36e95nethercote     functions of the same name), rather than from the OS kernel source,
228892b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     for the same reason -- a user presented with a "bogus foo(bar)" arg
228992b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     will most likely look at the "foo" man page to see which is the "bar"
229092b2fd542e89939b46edfa5c424af81f4a3bfe0cnethercote     arg.
22918b76fe55a596a4296ba5028e2510015fef38b02fnethercote
22929c311eb3d0c532a972449e5e600d10f0470120b6nethercote   Note that we use our own vki_* types.  The one exception is in
22939c311eb3d0c532a972449e5e600d10f0470120b6nethercote   PRE_REG_READn calls, where pointer types haven't been changed, because
22949c311eb3d0c532a972449e5e600d10f0470120b6nethercote   they don't need to be -- eg. for "foo*" to be used, the type foo need not
22959c311eb3d0c532a972449e5e600d10f0470120b6nethercote   be visible.
22969c311eb3d0c532a972449e5e600d10f0470120b6nethercote
22974fa681f368f50057260d6a75ab2a04de4b8436b9nethercote   XXX: some of these are arch-specific, and should be factored out.
22984fa681f368f50057260d6a75ab2a04de4b8436b9nethercote*/
22994fa681f368f50057260d6a75ab2a04de4b8436b9nethercote
2300a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#define PRE(name)      DEFN_PRE_TEMPLATE(generic, name)
2301a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj#define POST(name)     DEFN_POST_TEMPLATE(generic, name)
2302ef0c7663cb71101c7b718108253444cb75402cbbnethercote
2303ca78724a71ba13f05b92455a8156206e6df27e56tom// Macros to support 64-bit syscall args split into two 32 bit values
2304ca78724a71ba13f05b92455a8156206e6df27e56tom#if defined(VG_LITTLEENDIAN)
2305ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64(lo,hi)   ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2306ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64_FIRST(name) name##_low
2307ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64_SECOND(name) name##_high
2308ca78724a71ba13f05b92455a8156206e6df27e56tom#elif defined(VG_BIGENDIAN)
2309ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64(hi,lo)   ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2310ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64_FIRST(name) name##_high
2311ca78724a71ba13f05b92455a8156206e6df27e56tom#define MERGE64_SECOND(name) name##_low
2312ca78724a71ba13f05b92455a8156206e6df27e56tom#else
2313ca78724a71ba13f05b92455a8156206e6df27e56tom#error Unknown endianness
231489d43f79c020c46b895e2ae916f61e2555636ec8njn#endif
2315e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj
2316a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_exit)
2317855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
2318a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   ThreadState* tst;
2319a922b61f6014e389560475cb7886be77c3aa19f8sewardj   /* simple; just make this thread exit */
2320a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("exit( %ld )", ARG1);
2321aab814edf1195cbfbe0c75f2d66c0cbc8cc65a65njn   PRE_REG_READ1(void, "exit", int, status);
2322a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   tst = VG_(get_ThreadState)(tid);
2323a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /* Set the thread's status to be exiting, then claim that the
2324a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      syscall succeeded. */
2325ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   tst->exitreason = VgSrc_ExitThread;
2326a922b61f6014e389560475cb7886be77c3aa19f8sewardj   tst->os_state.exitcode = ARG1;
2327a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_Success(0);
2328855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2329be23ae7491ed887d2df349b3560b316dc871e59dsewardj
2330a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_ni_syscall)
2331eb1c7b730b5f601c2a5d55ee3dd02f930df4792fnethercote{
23321a1e95c1f385a9b3b4f13f231eebaafff6e56450njn   PRINT("unimplemented (by the kernel) syscall: %s! (ni_syscall)\n",
23331a1e95c1f385a9b3b4f13f231eebaafff6e56450njn      VG_SYSNUM_STRING(SYSNO));
2334eb1c7b730b5f601c2a5d55ee3dd02f930df4792fnethercote   PRE_REG_READ0(long, "ni_syscall");
2335a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_Failure( VKI_ENOSYS );
2336a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj}
2337a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
2338696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_iopl)
2339696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2340a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_iopl ( %ld )", ARG1);
2341696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "iopl", unsigned long, level);
2342696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2343696c55180aae375b48f7acc3f2aa87e13040c807sewardj
234478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_fsync)
234578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
234678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   *flags |= SfMayBlock;
2347a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fsync ( %ld )", ARG1);
234878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ1(long, "fsync", unsigned int, fd);
234978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
235078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
2351696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_fdatasync)
2352696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2353696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2354a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fdatasync ( %ld )", ARG1);
2355696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
2356696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2357696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2358696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_msync)
2359696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2360696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2361a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_msync ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
2362696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ3(long, "msync",
2363696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 unsigned long, start, vki_size_t, length, int, flags);
2364696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
2365696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2366696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2367e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
2368e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj// versions of LiS (Linux Streams).  They are not part of the kernel.
2369e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj// Therefore, we have to provide this type ourself, rather than getting it
2370e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj// from the kernel sources.
2371e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjstruct vki_pmsg_strbuf {
2372e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   int     maxlen;         /* no. of bytes in buffer */
2373e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   int     len;            /* no. of bytes returned */
2374e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   vki_caddr_t buf;        /* pointer to data */
2375e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj};
2376e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_getpmsg)
2377e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
2378e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
2379e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *ctrl;
2380e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *data;
2381e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   *flags |= SfMayBlock;
2382a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
2383e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ5(int, "getpmsg",
2384e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2385e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 int *, bandp, int *, flagsp);
2386e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2387e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   data = (struct vki_pmsg_strbuf *)ARG3;
2388e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (ctrl && ctrl->maxlen > 0)
2389e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2390e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (data && data->maxlen > 0)
2391e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2392e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (ARG4)
2393e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2394e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (ARG5)
2395e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2396e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
2397e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPOST(sys_getpmsg)
2398e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
2399e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *ctrl;
2400e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *data;
2401e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   vg_assert(SUCCESS);
2402e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2403e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   data = (struct vki_pmsg_strbuf *)ARG3;
2404e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (RES == 0 && ctrl && ctrl->len > 0) {
2405e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2406e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   }
2407e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (RES == 0 && data && data->len > 0) {
2408e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      POST_MEM_WRITE( (Addr)data->buf, data->len);
2409e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   }
2410e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
2411e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj
2412e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_putpmsg)
2413e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
2414e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2415e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *ctrl;
2416e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   struct vki_pmsg_strbuf *data;
2417e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   *flags |= SfMayBlock;
2418a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5);
2419e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ5(int, "putpmsg",
2420e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2421e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 int, band, int, flags);
2422e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2423e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   data = (struct vki_pmsg_strbuf *)ARG3;
2424e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (ctrl && ctrl->len > 0)
2425e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2426e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (data && data->len > 0)
2427e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2428e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
2429696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2430696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_getitimer)
2431696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
243272bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2433a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2);
2434696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
243572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn
243672bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
243772bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   PRE_timeval_WRITE( "getitimer(&value->it_value)",    &(value->it_value));
2438696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2439f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2440696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_getitimer)
2441696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2442696c55180aae375b48f7acc3f2aa87e13040c807sewardj   if (ARG2 != (Addr)NULL) {
244372bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
244472bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      POST_timeval_WRITE( &(value->it_interval) );
244572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      POST_timeval_WRITE( &(value->it_value) );
2446696c55180aae375b48f7acc3f2aa87e13040c807sewardj   }
2447696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2448696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2449696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_setitimer)
2450696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2451a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setitimer ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
2452696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ3(long, "setitimer",
2453696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 int, which,
2454696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 struct itimerval *, value, struct itimerval *, ovalue);
245572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   if (ARG2 != (Addr)NULL) {
245672bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
245772bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_READ( "setitimer(&value->it_interval)",
245872bbd8d24c6bd39734f465ce8d54904b6865de9bnjn                         &(value->it_interval));
245972bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_READ( "setitimer(&value->it_value)",
246072bbd8d24c6bd39734f465ce8d54904b6865de9bnjn                         &(value->it_value));
246172bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   }
246272bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   if (ARG3 != (Addr)NULL) {
246372bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
246472bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
246572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn                         &(ovalue->it_interval));
246672bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
246772bbd8d24c6bd39734f465ce8d54904b6865de9bnjn                         &(ovalue->it_value));
246872bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   }
2469696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2470696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2471696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_setitimer)
2472696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2473696c55180aae375b48f7acc3f2aa87e13040c807sewardj   if (ARG3 != (Addr)NULL) {
247472bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
247572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      POST_timeval_WRITE( &(ovalue->it_interval) );
247672bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      POST_timeval_WRITE( &(ovalue->it_value) );
2477696c55180aae375b48f7acc3f2aa87e13040c807sewardj   }
2478696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2479696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2480696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_chroot)
2481696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2482a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_chroot ( %#lx )", ARG1);
2483696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "chroot", const char *, path);
2484696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2485696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2486a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
2487a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_madvise)
2488a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
2489a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
2490a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_madvise ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
2491a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_REG_READ3(long, "madvise",
2492a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                 unsigned long, start, vki_size_t, length, int, advice);
24932e1c37dfb4583a40fa1e93bc4c7285c24d152b7fnethercote}
24942e1c37dfb4583a40fa1e93bc4c7285c24d152b7fnethercote
2495f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if HAVE_MREMAP
2496a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_mremap)
24972e1c37dfb4583a40fa1e93bc4c7285c24d152b7fnethercote{
2498a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   // Nb: this is different to the glibc version described in the man pages,
2499a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   // which lacks the fifth 'new_address' argument.
2500c00fcc79fefd027c24f3a977013a97f7b13aa6catom   if (ARG4 & VKI_MREMAP_FIXED) {
2501a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx, %#lx )",
2502c00fcc79fefd027c24f3a977013a97f7b13aa6catom            ARG1, (ULong)ARG2, ARG3, ARG4, ARG5);
2503c00fcc79fefd027c24f3a977013a97f7b13aa6catom      PRE_REG_READ5(unsigned long, "mremap",
2504c00fcc79fefd027c24f3a977013a97f7b13aa6catom                    unsigned long, old_addr, unsigned long, old_size,
2505c00fcc79fefd027c24f3a977013a97f7b13aa6catom                    unsigned long, new_size, unsigned long, flags,
2506c00fcc79fefd027c24f3a977013a97f7b13aa6catom                    unsigned long, new_addr);
2507c00fcc79fefd027c24f3a977013a97f7b13aa6catom   } else {
2508a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx )",
2509c00fcc79fefd027c24f3a977013a97f7b13aa6catom            ARG1, (ULong)ARG2, ARG3, ARG4);
2510c00fcc79fefd027c24f3a977013a97f7b13aa6catom      PRE_REG_READ4(unsigned long, "mremap",
2511c00fcc79fefd027c24f3a977013a97f7b13aa6catom                    unsigned long, old_addr, unsigned long, old_size,
2512c00fcc79fefd027c24f3a977013a97f7b13aa6catom                    unsigned long, new_size, unsigned long, flags);
2513c00fcc79fefd027c24f3a977013a97f7b13aa6catom   }
2514a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_from_SysRes(
251545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
2516a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   );
2517855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2518f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif /* HAVE_MREMAP */
2519de4a1d01951937632098a6cda45859afa587a06fsewardj
25208c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardjPRE(sys_nice)
25218c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj{
2522a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_nice ( %ld )", ARG1);
25238c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj   PRE_REG_READ1(long, "nice", int, inc);
25248c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj}
252578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
2526696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_mlock)
2527696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2528696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2529a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
2530696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2531696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2532696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2533696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_munlock)
2534696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2535696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2536a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_munlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
2537696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2538696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2539696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2540696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_mlockall)
2541696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2542696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2543a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mlockall ( %lx )", ARG1);
2544696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "mlockall", int, flags);
2545696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2546696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2547696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_setpriority)
2548696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2549a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setpriority ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
2550696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2551696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2552696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2553696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_getpriority)
2554696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2555a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getpriority ( %ld, %ld )", ARG1, ARG2);
2556696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "getpriority", int, which, int, who);
2557696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2558696c55180aae375b48f7acc3f2aa87e13040c807sewardj
25597b1edbdf64325be8000b0662a2f9695c0fa53465njnPRE(sys_pwrite64)
2560edc9547bf4ab4268fd2273ff91dde7f22ab692f8sewardj{
2561e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   *flags |= SfMayBlock;
25627b1edbdf64325be8000b0662a2f9695c0fa53465njn#if VG_WORDSIZE == 4
2563a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
2564ca78724a71ba13f05b92455a8156206e6df27e56tom         ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
2565e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ5(ssize_t, "pwrite64",
2566e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned int, fd, const char *, buf, vki_size_t, count,
25670ca89e0201db387d572047e9afb5d74786370208sewardj                 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
25687b1edbdf64325be8000b0662a2f9695c0fa53465njn#elif VG_WORDSIZE == 8
25697b1edbdf64325be8000b0662a2f9695c0fa53465njn   PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
25707b1edbdf64325be8000b0662a2f9695c0fa53465njn         ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
25717b1edbdf64325be8000b0662a2f9695c0fa53465njn   PRE_REG_READ4(ssize_t, "pwrite64",
25727b1edbdf64325be8000b0662a2f9695c0fa53465njn                 unsigned int, fd, const char *, buf, vki_size_t, count,
25737b1edbdf64325be8000b0662a2f9695c0fa53465njn                 Word, offset);
25747b1edbdf64325be8000b0662a2f9695c0fa53465njn#else
25757b1edbdf64325be8000b0662a2f9695c0fa53465njn#  error Unexpected word size
25767b1edbdf64325be8000b0662a2f9695c0fa53465njn#endif
2577e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2578e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
25798c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj
25808c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardjPRE(sys_sync)
25818c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj{
25828c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj   *flags |= SfMayBlock;
25838c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj   PRINT("sys_sync ( )");
25848c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj   PRE_REG_READ0(long, "sync");
25858c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj}
25868c9ea4ed4abe0fbee8f917a633d02368d6f59ce7sewardj
2587696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_fstatfs)
2588696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2589cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
2590a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fstatfs ( %ld, %#lx )",ARG1,ARG2);
2591696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "fstatfs",
2592696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 unsigned int, fd, struct statfs *, buf);
2593696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2594696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2595696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2596696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_fstatfs)
2597696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2598696c55180aae375b48f7acc3f2aa87e13040c807sewardj   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2599696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2600696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2601e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_fstatfs64)
2602e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
2603cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
2604a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fstatfs64 ( %ld, %llu, %#lx )",ARG1,(ULong)ARG2,ARG3);
2605e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "fstatfs64",
2606e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2607e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2608e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
2609e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPOST(sys_fstatfs64)
2610e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
2611e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   POST_MEM_WRITE( ARG3, ARG2 );
2612e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
2613696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2614696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_getsid)
2615696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2616a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getsid ( %ld )", ARG1);
2617696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2618696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2619696c55180aae375b48f7acc3f2aa87e13040c807sewardj
26207b1edbdf64325be8000b0662a2f9695c0fa53465njnPRE(sys_pread64)
2621e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj{
2622e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   *flags |= SfMayBlock;
26237b1edbdf64325be8000b0662a2f9695c0fa53465njn#if VG_WORDSIZE == 4
2624a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
2625ca78724a71ba13f05b92455a8156206e6df27e56tom         ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
2626e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   PRE_REG_READ5(ssize_t, "pread64",
2627e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj                 unsigned int, fd, char *, buf, vki_size_t, count,
2628ca78724a71ba13f05b92455a8156206e6df27e56tom                 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
26297b1edbdf64325be8000b0662a2f9695c0fa53465njn#elif VG_WORDSIZE == 8
26307b1edbdf64325be8000b0662a2f9695c0fa53465njn   PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
26317b1edbdf64325be8000b0662a2f9695c0fa53465njn         ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
26327b1edbdf64325be8000b0662a2f9695c0fa53465njn   PRE_REG_READ4(ssize_t, "pread64",
26337b1edbdf64325be8000b0662a2f9695c0fa53465njn                 unsigned int, fd, char *, buf, vki_size_t, count,
26347b1edbdf64325be8000b0662a2f9695c0fa53465njn                 Word, offset);
26357b1edbdf64325be8000b0662a2f9695c0fa53465njn#else
26367b1edbdf64325be8000b0662a2f9695c0fa53465njn#  error Unexpected word size
26377b1edbdf64325be8000b0662a2f9695c0fa53465njn#endif
2638e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2639e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj}
26407b1edbdf64325be8000b0662a2f9695c0fa53465njnPOST(sys_pread64)
2641e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj{
2642e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   vg_assert(SUCCESS);
2643e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   if (RES > 0) {
2644e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj      POST_MEM_WRITE( ARG2, RES );
2645e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj   }
2646e7aa4ae857ab875e6b673ad5a081ff6b1b697aecsewardj}
2647a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
2648a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_mknod)
2649855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
2650cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
2651a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mknod ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char*)ARG1, ARG2, ARG3 );
2652a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_REG_READ3(long, "mknod",
2653a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                 const char *, pathname, int, mode, unsigned, dev);
2654a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
2655855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2656de4a1d01951937632098a6cda45859afa587a06fsewardj
2657696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_flock)
2658696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
2659696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
2660a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_flock ( %ld, %ld )", ARG1, ARG2 );
2661696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2662696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
2663696c55180aae375b48f7acc3f2aa87e13040c807sewardj
2664a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj// Pre_read a char** argument.
2665e543f3024ace2925a0fb81985e9fcfc95b8c555aflorianstatic void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
26662e1c37dfb4583a40fa1e93bc4c7285c24d152b7fnethercote{
2667a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   while (True) {
2668a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      Addr a_deref;
2669a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      Addr* a_p = (Addr*)a;
2670a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2671a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      a_deref = *a_p;
2672a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      if (0 == a_deref)
2673a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         break;
2674a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      PRE_MEM_RASCIIZ( s2, a_deref );
2675a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      a += sizeof(char*);
2676a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   }
26772e1c37dfb4583a40fa1e93bc4c7285c24d152b7fnethercote}
2678de4a1d01951937632098a6cda45859afa587a06fsewardj
26797b85dd57f12f86a03f51f7cedea46147ef937f82njnstatic Bool i_am_the_only_thread ( void )
26807b85dd57f12f86a03f51f7cedea46147ef937f82njn{
26817b85dd57f12f86a03f51f7cedea46147ef937f82njn   Int c = VG_(count_living_threads)();
26827b85dd57f12f86a03f51f7cedea46147ef937f82njn   vg_assert(c >= 1); /* stay sane */
26837b85dd57f12f86a03f51f7cedea46147ef937f82njn   return c == 1;
26847b85dd57f12f86a03f51f7cedea46147ef937f82njn}
26857b85dd57f12f86a03f51f7cedea46147ef937f82njn
26867b85dd57f12f86a03f51f7cedea46147ef937f82njn/* Wait until all other threads disappear. */
26877b85dd57f12f86a03f51f7cedea46147ef937f82njnvoid VG_(reap_threads)(ThreadId self)
26887b85dd57f12f86a03f51f7cedea46147ef937f82njn{
26897b85dd57f12f86a03f51f7cedea46147ef937f82njn   while (!i_am_the_only_thread()) {
26907b85dd57f12f86a03f51f7cedea46147ef937f82njn      /* Let other thread(s) run */
26917b85dd57f12f86a03f51f7cedea46147ef937f82njn      VG_(vg_yield)();
26927b85dd57f12f86a03f51f7cedea46147ef937f82njn      VG_(poll_signals)(self);
26937b85dd57f12f86a03f51f7cedea46147ef937f82njn   }
26947b85dd57f12f86a03f51f7cedea46147ef937f82njn   vg_assert(i_am_the_only_thread());
26957b85dd57f12f86a03f51f7cedea46147ef937f82njn}
26967b85dd57f12f86a03f51f7cedea46147ef937f82njn
2697a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2698a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj// but it seems to work nonetheless...
2699a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_execve)
2700855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
270119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar*       path = NULL;       /* path to executable */
270219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar**      envp = NULL;
270319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar**      argv = NULL;
270419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar**      arg2copy;
270519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   HChar*       launcher_basename = NULL;
2706a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   ThreadState* tst;
270745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int          i, j, tot_args;
27087375061f0ecd9534a27ade9bb4fbe47ddce41298njn   SysRes       res;
2709064212709dc8988a48d2cbde5b90528952d8cd74sewardj   Bool         setuid_allowed, trace_this_child;
2710de4a1d01951937632098a6cda45859afa587a06fsewardj
2711a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (char*)ARG1, ARG2, ARG3);
2712a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_REG_READ3(vki_off_t, "execve",
2713a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                 char *, filename, char **, argv, char **, envp);
2714a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
2715a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG2 != 0)
2716a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
2717a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG3 != 0)
2718a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
2719de4a1d01951937632098a6cda45859afa587a06fsewardj
2720a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(VG_(is_valid_tid)(tid));
2721a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   tst = VG_(get_ThreadState)(tid);
2722de4a1d01951937632098a6cda45859afa587a06fsewardj
2723a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /* Erk.  If the exec fails, then the following will have made a
2724a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      mess of things which makes it hard for us to continue.  The
2725a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      right thing to do is piece everything together again in
272645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      POST(execve), but that's close to impossible.  Instead, we make
272745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      an effort to check that the execve will work before actually
272845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      doing it. */
2729de4a1d01951937632098a6cda45859afa587a06fsewardj
27307375061f0ecd9534a27ade9bb4fbe47ddce41298njn   /* Check that the name at least begins in client-accessible storage. */
2731064212709dc8988a48d2cbde5b90528952d8cd74sewardj   if (ARG1 == 0 /* obviously bogus */
2732064212709dc8988a48d2cbde5b90528952d8cd74sewardj       || !VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
273345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      SET_STATUS_Failure( VKI_EFAULT );
273445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
273545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
273645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
27379ab64a4d3043c251561419d0e0f51492172b1072sewardj   // debug-only printing
27389ab64a4d3043c251561419d0e0f51492172b1072sewardj   if (0) {
27399ab64a4d3043c251561419d0e0f51492172b1072sewardj      VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1);
27409ab64a4d3043c251561419d0e0f51492172b1072sewardj      if (ARG2) {
27419ab64a4d3043c251561419d0e0f51492172b1072sewardj         VG_(printf)("ARG2 = ");
27429ab64a4d3043c251561419d0e0f51492172b1072sewardj         Int q;
27439ab64a4d3043c251561419d0e0f51492172b1072sewardj         HChar** vec = (HChar**)ARG2;
27449ab64a4d3043c251561419d0e0f51492172b1072sewardj         for (q = 0; vec[q]; q++)
27459ab64a4d3043c251561419d0e0f51492172b1072sewardj            VG_(printf)("%p(%s) ", vec[q], vec[q]);
27469ab64a4d3043c251561419d0e0f51492172b1072sewardj         VG_(printf)("\n");
27479ab64a4d3043c251561419d0e0f51492172b1072sewardj      } else {
27489ab64a4d3043c251561419d0e0f51492172b1072sewardj         VG_(printf)("ARG2 = null\n");
27499ab64a4d3043c251561419d0e0f51492172b1072sewardj      }
27509ab64a4d3043c251561419d0e0f51492172b1072sewardj   }
27519ab64a4d3043c251561419d0e0f51492172b1072sewardj
2752064212709dc8988a48d2cbde5b90528952d8cd74sewardj   // Decide whether or not we want to follow along
27539ab64a4d3043c251561419d0e0f51492172b1072sewardj   { // Make 'child_argv' be a pointer to the child's arg vector
27549ab64a4d3043c251561419d0e0f51492172b1072sewardj     // (skipping the exe name)
2755518850bf0da07ed3e2244e307268ae0fd80e93a8florian     const HChar** child_argv = (const HChar**)ARG2;
27569ab64a4d3043c251561419d0e0f51492172b1072sewardj     if (child_argv && child_argv[0] == NULL)
27579ab64a4d3043c251561419d0e0f51492172b1072sewardj        child_argv = NULL;
27589ab64a4d3043c251561419d0e0f51492172b1072sewardj     trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv );
27599ab64a4d3043c251561419d0e0f51492172b1072sewardj   }
2760064212709dc8988a48d2cbde5b90528952d8cd74sewardj
27617375061f0ecd9534a27ade9bb4fbe47ddce41298njn   // Do the important checks:  it is a file, is executable, permissions are
2762c74b3ba6f1d1b269aa2abcad3bd1c58d0d630c9fsewardj   // ok, etc.  We allow setuid executables to run only in the case when
2763c74b3ba6f1d1b269aa2abcad3bd1c58d0d630c9fsewardj   // we are not simulating them, that is, they to be run natively.
2764064212709dc8988a48d2cbde5b90528952d8cd74sewardj   setuid_allowed = trace_this_child  ? False  : True;
2765e543f3024ace2925a0fb81985e9fcfc95b8c555aflorian   res = VG_(pre_exec_check)((const HChar *)ARG1, NULL, setuid_allowed);
2766cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(res)) {
2767cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SET_STATUS_Failure( sr_Err(res) );
27687375061f0ecd9534a27ade9bb4fbe47ddce41298njn      return;
27697375061f0ecd9534a27ade9bb4fbe47ddce41298njn   }
27707375061f0ecd9534a27ade9bb4fbe47ddce41298njn
277198e68a4db8df087243c5f095cddb7b34adb2d19bsewardj   /* If we're tracing the child, and the launcher name looks bogus
277298e68a4db8df087243c5f095cddb7b34adb2d19bsewardj      (possibly because launcher.c couldn't figure it out, see
277398e68a4db8df087243c5f095cddb7b34adb2d19bsewardj      comments therein) then we have no option but to fail. */
2774064212709dc8988a48d2cbde5b90528952d8cd74sewardj   if (trace_this_child
277598e68a4db8df087243c5f095cddb7b34adb2d19bsewardj       && (VG_(name_of_launcher) == NULL
277698e68a4db8df087243c5f095cddb7b34adb2d19bsewardj           || VG_(name_of_launcher)[0] != '/')) {
277798e68a4db8df087243c5f095cddb7b34adb2d19bsewardj      SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
277898e68a4db8df087243c5f095cddb7b34adb2d19bsewardj      return;
277998e68a4db8df087243c5f095cddb7b34adb2d19bsewardj   }
278098e68a4db8df087243c5f095cddb7b34adb2d19bsewardj
278145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* After this point, we can't recover if the execve fails. */
278219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian   VG_(debugLog)(1, "syswrap", "Exec of %s\n", (HChar*)ARG1);
278345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2784997546cadb1c8240e90c6e7d316ec7850626d751sewardj
2785997546cadb1c8240e90c6e7d316ec7850626d751sewardj   // Terminate gdbserver if it is active.
2786997546cadb1c8240e90c6e7d316ec7850626d751sewardj   if (VG_(clo_vgdb)  != Vg_VgdbNo) {
2787997546cadb1c8240e90c6e7d316ec7850626d751sewardj      // If the child will not be traced, we need to terminate gdbserver
2788997546cadb1c8240e90c6e7d316ec7850626d751sewardj      // to cleanup the gdbserver resources (e.g. the FIFO files).
2789997546cadb1c8240e90c6e7d316ec7850626d751sewardj      // If child will be traced, we also terminate gdbserver: the new
2790997546cadb1c8240e90c6e7d316ec7850626d751sewardj      // Valgrind will start a fresh gdbserver after exec.
2791997546cadb1c8240e90c6e7d316ec7850626d751sewardj      VG_(gdbserver) (0);
2792997546cadb1c8240e90c6e7d316ec7850626d751sewardj   }
2793997546cadb1c8240e90c6e7d316ec7850626d751sewardj
2794a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /* Resistance is futile.  Nuke all other threads.  POSIX mandates
2795a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      this. (Really, nuke them all, since the new process will make
2796a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      its own new thread.) */
2797ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread );
27987b85dd57f12f86a03f51f7cedea46147ef937f82njn   VG_(reap_threads)(tid);
2799de4a1d01951937632098a6cda45859afa587a06fsewardj
280045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // Set up the child's exe path.
280145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
2802064212709dc8988a48d2cbde5b90528952d8cd74sewardj   if (trace_this_child) {
280345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
280445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // We want to exec the launcher.  Get its pre-remembered path.
280545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      path = VG_(name_of_launcher);
280645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // VG_(name_of_launcher) should have been acquired by m_main at
280745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // startup.
280845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      vg_assert(path);
280945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
281045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      launcher_basename = VG_(strrchr)(path, '/');
281145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (launcher_basename == NULL || launcher_basename[1] == 0) {
281245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         launcher_basename = path;  // hmm, tres dubious
281345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      } else {
281445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         launcher_basename++;
281545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
281645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
281745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
281819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      path = (HChar*)ARG1;
281945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
282045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
282145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // Set up the child's environment.
282245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
28234e1369582e21b6b614cf31ca811d8f19e88833datom   // Remove the valgrind-specific stuff from the environment so the
28247b4e5ba742056c84e76434e9d220e1dc538ed1ecnjn   // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
28254e1369582e21b6b614cf31ca811d8f19e88833datom   // This is done unconditionally, since if we are tracing the child,
282645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // the child valgrind will set up the appropriate client environment.
282711106992f0479d087d9f1069c9d9374b1095a0b4njn   // Nb: we make a copy of the environment before trying to mangle it
282811106992f0479d087d9f1069c9d9374b1095a0b4njn   // as it might be in read-only memory (this was bug #101881).
282945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
283045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // Then, if tracing the child, set VALGRIND_LIB for it.
283145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
283245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (ARG3 == 0) {
283345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      envp = NULL;
283445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
283519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      envp = VG_(env_clone)( (HChar**)ARG3 );
283645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (envp == NULL) goto hosed;
28374e1369582e21b6b614cf31ca811d8f19e88833datom      VG_(env_remove_valgrind_env_stuff)( envp );
2838a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   }
2839de4a1d01951937632098a6cda45859afa587a06fsewardj
2840064212709dc8988a48d2cbde5b90528952d8cd74sewardj   if (trace_this_child) {
284145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // Set VALGRIND_LIB in ARG3 (the environment)
284245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
2843855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
2844de4a1d01951937632098a6cda45859afa587a06fsewardj
284545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // Set up the child's args.  If not tracing it, they are
284645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // simply ARG2.  Otherwise, they are
284745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
284845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
284945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
285045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // except that the first VG_(args_for_valgrind_noexecpass) args
285145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   // are omitted.
285245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   //
2853064212709dc8988a48d2cbde5b90528952d8cd74sewardj   if (!trace_this_child) {
285419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      argv = (HChar**)ARG2;
285545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
285614c7cc5a5fbe9526329f058116f921988efe679esewardj      vg_assert( VG_(args_for_valgrind) );
285745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
285845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      vg_assert( VG_(args_for_valgrind_noexecpass)
285914c7cc5a5fbe9526329f058116f921988efe679esewardj                   <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
286045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* how many args in total will there be? */
286145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // launcher basename
286245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      tot_args = 1;
286345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // V's args
286414c7cc5a5fbe9526329f058116f921988efe679esewardj      tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
286545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      tot_args -= VG_(args_for_valgrind_noexecpass);
286645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // name of client exe
286745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      tot_args++;
286845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // args for client exe, skipping [0]
286919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      arg2copy = (HChar**)ARG2;
287045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (arg2copy && arg2copy[0]) {
287145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         for (i = 1; arg2copy[i]; i++)
287245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            tot_args++;
287345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
287445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // allocate
28759c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj      argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
28769c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj                          (tot_args+1) * sizeof(HChar*) );
287745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // copy
287845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      j = 0;
287945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      argv[j++] = launcher_basename;
288014c7cc5a5fbe9526329f058116f921988efe679esewardj      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
288145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (i < VG_(args_for_valgrind_noexecpass))
288245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            continue;
288314c7cc5a5fbe9526329f058116f921988efe679esewardj         argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
288445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
288519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      argv[j++] = (HChar*)ARG1;
288645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (arg2copy && arg2copy[0])
288745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         for (i = 1; arg2copy[i]; i++)
288845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            argv[j++] = arg2copy[i];
288945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      argv[j++] = NULL;
289045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      // check
289145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      vg_assert(j == tot_args+1);
2892855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
2893de4a1d01951937632098a6cda45859afa587a06fsewardj
2894a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /* restore the DATA rlimit for the child */
2895a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
28965b653bc2c60f6913e5bb6c2ebabfcf705a90c012nethercote
2897a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /*
2898a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      Set the signal state up for exec.
28995b653bc2c60f6913e5bb6c2ebabfcf705a90c012nethercote
2900a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      We need to set the real signal state to make sure the exec'd
2901a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      process gets SIG_IGN properly.
2902de4a1d01951937632098a6cda45859afa587a06fsewardj
2903a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      Also set our real sigmask to match the client's sigmask so that
2904a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      the exec'd child will get the right mask.  First we need to
2905a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      clear out any pending signals so they they don't get delivered,
2906a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      which would confuse things.
2907f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge
2908f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge      XXX This is a bug - the signals should remain pending, and be
2909f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge      delivered to the new process after exec.  There's also a
2910f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge      race-condition, since if someone delivers us a signal between
2911f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge      the sigprocmask and the execve, we'll still get the signal. Oh
2912f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge      well.
2913f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge   */
2914f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge   {
291573b526fb4af0f60634f0078583d92b931d5c0eebnethercote      vki_sigset_t allsigs;
291673b526fb4af0f60634f0078583d92b931d5c0eebnethercote      vki_siginfo_t info;
2917b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
2918cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      /* What this loop does: it queries SCSS (the signal state that
2919cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         the client _thinks_ the kernel is in) by calling
2920cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(do_sys_sigaction), and modifies the real kernel signal
2921cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         state accordingly. */
292245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      for (i = 1; i < VG_(max_signal); i++) {
2923cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         vki_sigaction_fromK_t sa_f;
2924cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         vki_sigaction_toK_t   sa_t;
2925cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(do_sys_sigaction)(i, NULL, &sa_f);
2926cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
2927cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         if (sa_t.ksa_handler == VKI_SIG_IGN)
2928cda2f0fbda4c4b2644babc830244be8aed95de1dnjn            VG_(sigaction)(i, &sa_t, NULL);
2929b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj         else {
2930cda2f0fbda4c4b2644babc830244be8aed95de1dnjn            sa_t.ksa_handler = VKI_SIG_DFL;
2931cda2f0fbda4c4b2644babc830244be8aed95de1dnjn            VG_(sigaction)(i, &sa_t, NULL);
2932b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj         }
2933b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj      }
2934b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
293573b526fb4af0f60634f0078583d92b931d5c0eebnethercote      VG_(sigfillset)(&allsigs);
2936ef1cf8b3583107c7d918c60895937f09969d5b3esewardj      while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
2937b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj         ;
2938f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge
293973b526fb4af0f60634f0078583d92b931d5c0eebnethercote      VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
2940f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge   }
2941f0dd7e17450a6f89629bf519c8d78f5e4cc5c823fitzhardinge
294245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0) {
294319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar **cpp;
294445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(printf)("exec: %s\n", path);
294545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      for (cpp = argv; cpp && *cpp; cpp++)
294645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(printf)("argv: %s\n", *cpp);
294745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (0)
294845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         for (cpp = envp; cpp && *cpp; cpp++)
294945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            VG_(printf)("env: %s\n", *cpp);
295045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
295145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2952a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_from_SysRes(
295345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
2954a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   );
2955e1c06d80fa446cbe2a80de412315be1b630051a4fitzhardinge
295645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* If we got here, then the execve failed.  We've already made way
295745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      too much of a mess to continue, so we have to abort. */
295845f4e7c91119c7d01a59f5e827c67841632c9314sewardj  hosed:
2959dc294c3956c6d1c35862ba05833be33217b5844ftom   vg_assert(FAILURE);
2960738856f99eea33d86ce91dcb1d6cd5b151e307casewardj   VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n",
2961a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                ARG1, (char*)ARG1, ARG2, ARG3, ERR);
2962b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj   VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
2963738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                            "execve() failing, so I'm dying.\n");
2964a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
2965738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                            "or work out how to recover.\n");
2966b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj   VG_(exit)(101);
2967855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2968855d93d2e9940890b28874520fa4c1677bf825e2jsgf
2969a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_access)
2970855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
2971a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_access ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
29729a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
297322cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
2974855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2975855d93d2e9940890b28874520fa4c1677bf825e2jsgf
2976a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_alarm)
2977855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
2978a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_alarm ( %ld )", ARG1);
29799a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
2980855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
2981855d93d2e9940890b28874520fa4c1677bf825e2jsgf
2982a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_brk)
2983855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
298498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge   Addr brk_limit = VG_(brk_limit);
2985a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   Addr brk_new;
298698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2987855d93d2e9940890b28874520fa4c1677bf825e2jsgf   /* libc   says: int   brk(void *end_data_segment);
2988855d93d2e9940890b28874520fa4c1677bf825e2jsgf      kernel says: void* brk(void* end_data_segment);  (more or less)
2989855d93d2e9940890b28874520fa4c1677bf825e2jsgf
2990855d93d2e9940890b28874520fa4c1677bf825e2jsgf      libc returns 0 on success, and -1 (and sets errno) on failure.
2991855d93d2e9940890b28874520fa4c1677bf825e2jsgf      Nb: if you ask to shrink the dataseg end below what it
2992855d93d2e9940890b28874520fa4c1677bf825e2jsgf      currently is, that always succeeds, even if the dataseg end
2993855d93d2e9940890b28874520fa4c1677bf825e2jsgf      doesn't actually change (eg. brk(0)).  Unless it seg faults.
2994855d93d2e9940890b28874520fa4c1677bf825e2jsgf
2995855d93d2e9940890b28874520fa4c1677bf825e2jsgf      Kernel returns the new dataseg end.  If the brk() failed, this
2996855d93d2e9940890b28874520fa4c1677bf825e2jsgf      will be unchanged from the old one.  That's why calling (kernel)
2997855d93d2e9940890b28874520fa4c1677bf825e2jsgf      brk(0) gives the current dataseg end (libc brk() just returns
2998855d93d2e9940890b28874520fa4c1677bf825e2jsgf      zero in that case).
2999855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3000855d93d2e9940890b28874520fa4c1677bf825e2jsgf      Both will seg fault if you shrink it back into a text segment.
3001855d93d2e9940890b28874520fa4c1677bf825e2jsgf   */
3002a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_brk ( %#lx )", ARG1);
30039c311eb3d0c532a972449e5e600d10f0470120b6nethercote   PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
3004855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3005981abb5e4a0f43049ed7efac90cfa52ac61b5140florian   brk_new = do_brk(ARG1, tid);
3006a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_Success( brk_new );
300798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
3008a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (brk_new == ARG1) {
3009855d93d2e9940890b28874520fa4c1677bf825e2jsgf      /* brk() succeeded */
3010a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      if (brk_new < brk_limit) {
3011855d93d2e9940890b28874520fa4c1677bf825e2jsgf         /* successfully shrunk the data segment. */
301222cfccb218c6975fa852a1135ddce342474b99d2njn         VG_TRACK( die_mem_brk, (Addr)ARG1,
301322cfccb218c6975fa852a1135ddce342474b99d2njn		   brk_limit-ARG1 );
3014855d93d2e9940890b28874520fa4c1677bf825e2jsgf      } else
3015a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      if (brk_new > brk_limit) {
3016855d93d2e9940890b28874520fa4c1677bf825e2jsgf         /* successfully grew the data segment */
301798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge         VG_TRACK( new_mem_brk, brk_limit,
30187cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardj                   ARG1-brk_limit, tid );
3019855d93d2e9940890b28874520fa4c1677bf825e2jsgf      }
3020855d93d2e9940890b28874520fa4c1677bf825e2jsgf   } else {
3021855d93d2e9940890b28874520fa4c1677bf825e2jsgf      /* brk() failed */
3022a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      vg_assert(brk_limit == brk_new);
3023855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3024855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3025855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3026a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_chdir)
3027855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3028cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3029a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1);
3030c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ1(long, "chdir", const char *, path);
303122cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
3032855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3033855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3034a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_chmod)
3035855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3036cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3037a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_chmod ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3038c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
303922cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
3040855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3041855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3042e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_chown)
3043e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3044cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3045a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
3046e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "chown",
3047e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 const char *, path, vki_uid_t, owner, vki_gid_t, group);
3048e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
3049e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
3050e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj
3051e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_lchown)
3052e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3053cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3054a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
3055e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "lchown",
3056e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 const char *, path, vki_uid_t, owner, vki_gid_t, group);
3057e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
3058e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
3059a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
3060a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_close)
3061855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3062cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3063a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_close ( %ld )", ARG1);
3064c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ1(long, "close", unsigned int, fd);
3065c6851dde1b46166417a2bdb096c05818f5f07f09nethercote
3066f854867c39a3697ca53e417447048d0cc3ff8a87nethercote   /* Detect and negate attempts by the client to close Valgrind's log fd */
30679da79d1520e4ac844ef33e46a7e9aa7f2d4ee2casewardj   if ( (!ML_(fd_allowed)(ARG1, "close", tid, False))
30689da79d1520e4ac844ef33e46a7e9aa7f2d4ee2casewardj        /* If doing -d style logging (which is to fd=2), don't
30699da79d1520e4ac844ef33e46a7e9aa7f2d4ee2casewardj           allow that to be closed either. */
30709da79d1520e4ac844ef33e46a7e9aa7f2d4ee2casewardj        || (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) )
3071a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
3072855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3073855d93d2e9940890b28874520fa4c1677bf825e2jsgf
307485a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_close)
3075f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh{
30761dcee097db02f9ef3ba355162c4373d90d0e895cnjn   if (VG_(clo_track_fds)) record_fd_close(ARG1);
3077f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh}
3078855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3079a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_dup)
3080855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3081a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_dup ( %ld )", ARG1);
30829a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ1(long, "dup", unsigned int, oldfd);
3083855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3084855d93d2e9940890b28874520fa4c1677bf825e2jsgf
308585a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_dup)
3086855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3087a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
30887eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
308922cfccb218c6975fa852a1135ddce342474b99d2njn      VG_(close)(RES);
3090a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EMFILE );
3091f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
30929a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote      if (VG_(clo_track_fds))
3093096ccdd670d4e4eabdafb18598b1cd06d790fda8njn         ML_(record_fd_open_named)(tid, RES);
3094855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3095855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3096855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3097a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_dup2)
3098855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3099a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_dup2 ( %ld, %ld )", ARG1,ARG2);
310071f05f360cf9b60b129b11d0c56e38bbd4997671nethercote   PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
31017eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
3102a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
3103855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3104855d93d2e9940890b28874520fa4c1677bf825e2jsgf
310585a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_dup2)
3106855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3107a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
310871f05f360cf9b60b129b11d0c56e38bbd4997671nethercote   if (VG_(clo_track_fds))
3109096ccdd670d4e4eabdafb18598b1cd06d790fda8njn      ML_(record_fd_open_named)(tid, RES);
3110855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3111855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3112696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_fchdir)
3113696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3114cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3115a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fchdir ( %ld )", ARG1);
3116696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "fchdir", unsigned int, fd);
3117696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3118696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3119e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_fchown)
3120e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3121cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3122a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fchown ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3123e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "fchown",
3124e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
3125e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
3126696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3127696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_fchmod)
3128696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3129cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3130a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_fchmod ( %ld, %ld )", ARG1,ARG2);
3131696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
3132696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3133696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3134696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_newfstat)
3135696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3136cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3137a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_newfstat ( %ld, %#lx )", ARG1,ARG2);
3138696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
3139696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
3140696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3141696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3142696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_newfstat)
3143696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3144696c55180aae375b48f7acc3f2aa87e13040c807sewardj   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3145696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3146855d93d2e9940890b28874520fa4c1677bf825e2jsgf
314773b526fb4af0f60634f0078583d92b931d5c0eebnethercotestatic vki_sigset_t fork_saved_mask;
3148855d93d2e9940890b28874520fa4c1677bf825e2jsgf
314975a8c98921a3f59ac0351c270b84fa1c7cc29e01nethercote// In Linux, the sys_fork() function varies across architectures, but we
315075a8c98921a3f59ac0351c270b84fa1c7cc29e01nethercote// ignore the various args it gets, and so it looks arch-neutral.  Hmm.
3151a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_fork)
3152855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
315358bbd94336262ff3a01fddf9dac4a041eec9d168njn   Bool is_child;
315458bbd94336262ff3a01fddf9dac4a041eec9d168njn   Int child_pid;
315573b526fb4af0f60634f0078583d92b931d5c0eebnethercote   vki_sigset_t mask;
3156855d93d2e9940890b28874520fa4c1677bf825e2jsgf
315775a8c98921a3f59ac0351c270b84fa1c7cc29e01nethercote   PRINT("sys_fork ( )");
315875a8c98921a3f59ac0351c270b84fa1c7cc29e01nethercote   PRE_REG_READ0(long, "fork");
315975a8c98921a3f59ac0351c270b84fa1c7cc29e01nethercote
3160855d93d2e9940890b28874520fa4c1677bf825e2jsgf   /* Block all signals during fork, so that we can fix things up in
3161855d93d2e9940890b28874520fa4c1677bf825e2jsgf      the child without being interrupted. */
316273b526fb4af0f60634f0078583d92b931d5c0eebnethercote   VG_(sigfillset)(&mask);
316373b526fb4af0f60634f0078583d92b931d5c0eebnethercote   VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
3164855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3165a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
3166855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3167cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!SUCCESS) return;
3168cda2f0fbda4c4b2644babc830244be8aed95de1dnjn
31696e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if defined(VGO_linux)
317058bbd94336262ff3a01fddf9dac4a041eec9d168njn   // RES is 0 for child, non-0 (the child's PID) for parent.
317158bbd94336262ff3a01fddf9dac4a041eec9d168njn   is_child = ( RES == 0 ? True : False );
317258bbd94336262ff3a01fddf9dac4a041eec9d168njn   child_pid = ( is_child ? -1 : RES );
3173f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
3174f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // RES is the child's pid.  RESHI is 1 for child, 0 for parent.
3175f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   is_child = RESHI;
3176f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   child_pid = RES;
3177f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#else
3178f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  error Unknown OS
3179f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
3180cda2f0fbda4c4b2644babc830244be8aed95de1dnjn
3181e9ba34af88cd1b397957018e3e122869c76c1652njn   VG_(do_atfork_pre)(tid);
3182e9ba34af88cd1b397957018e3e122869c76c1652njn
318358bbd94336262ff3a01fddf9dac4a041eec9d168njn   if (is_child) {
3184b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj      VG_(do_atfork_child)(tid);
3185855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3186855d93d2e9940890b28874520fa4c1677bf825e2jsgf      /* restore signal mask */
318773b526fb4af0f60634f0078583d92b931d5c0eebnethercote      VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
31886e31f80899f1c79a54f164955069f3f74fe8b7e2sewardj
31896e31f80899f1c79a54f164955069f3f74fe8b7e2sewardj      /* If --child-silent-after-fork=yes was specified, set the
3190738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         output file descriptors to 'impossible' values.  This is
31916e31f80899f1c79a54f164955069f3f74fe8b7e2sewardj         noticed by send_bytes_to_logging_sink in m_libcprint.c, which
3192738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         duly stops writing any further output. */
3193738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      if (VG_(clo_child_silent_after_fork)) {
3194738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         if (!VG_(log_output_sink).is_socket)
3195738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            VG_(log_output_sink).fd = -1;
3196738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         if (!VG_(xml_output_sink).is_socket)
3197738856f99eea33d86ce91dcb1d6cd5b151e307casewardj            VG_(xml_output_sink).fd = -1;
3198738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      }
319958bbd94336262ff3a01fddf9dac4a041eec9d168njn
3200f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   } else {
3201e9ba34af88cd1b397957018e3e122869c76c1652njn      VG_(do_atfork_parent)(tid);
3202e9ba34af88cd1b397957018e3e122869c76c1652njn
320358bbd94336262ff3a01fddf9dac4a041eec9d168njn      PRINT("   fork: process %d created child %d\n", VG_(getpid)(), child_pid);
3204855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3205855d93d2e9940890b28874520fa4c1677bf825e2jsgf      /* restore signal mask */
320673b526fb4af0f60634f0078583d92b931d5c0eebnethercote      VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
3207855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3208855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3209855d93d2e9940890b28874520fa4c1677bf825e2jsgf
32108c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardjPRE(sys_ftruncate)
32118c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardj{
32128c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardj   *flags |= SfMayBlock;
3213a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_ftruncate ( %ld, %ld )", ARG1,ARG2);
32148c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardj   PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
32158c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardj}
32168c257323279d9036a3d0e283c8c5cd3ee9bb5ee0sewardj
3217696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_truncate)
3218696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3219696c55180aae375b48f7acc3f2aa87e13040c807sewardj   *flags |= SfMayBlock;
3220a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_truncate ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3221696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "truncate",
3222696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 const char *, path, unsigned long, length);
3223696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
3224696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3225696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3226e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_ftruncate64)
3227e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3228e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   *flags |= SfMayBlock;
322989d43f79c020c46b895e2ae916f61e2555636ec8njn#if VG_WORDSIZE == 4
3230ca78724a71ba13f05b92455a8156206e6df27e56tom   PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, MERGE64(ARG2,ARG3));
3231e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "ftruncate64",
3232e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned int, fd,
3233ca78724a71ba13f05b92455a8156206e6df27e56tom                 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
323489d43f79c020c46b895e2ae916f61e2555636ec8njn#else
323589d43f79c020c46b895e2ae916f61e2555636ec8njn   PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, (Long)ARG2);
323689d43f79c020c46b895e2ae916f61e2555636ec8njn   PRE_REG_READ2(long, "ftruncate64",
323789d43f79c020c46b895e2ae916f61e2555636ec8njn                 unsigned int,fd, UWord,length);
3238e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj#endif
323989d43f79c020c46b895e2ae916f61e2555636ec8njn}
3240e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj
3241e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_truncate64)
3242e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3243e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   *flags |= SfMayBlock;
324489d43f79c020c46b895e2ae916f61e2555636ec8njn#if VG_WORDSIZE == 4
3245ca78724a71ba13f05b92455a8156206e6df27e56tom   PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)MERGE64(ARG2, ARG3));
3246e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "truncate64",
3247e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 const char *, path,
3248ca78724a71ba13f05b92455a8156206e6df27e56tom                 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
324989d43f79c020c46b895e2ae916f61e2555636ec8njn#else
325089d43f79c020c46b895e2ae916f61e2555636ec8njn   PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)ARG2);
325189d43f79c020c46b895e2ae916f61e2555636ec8njn   PRE_REG_READ2(long, "truncate64",
325289d43f79c020c46b895e2ae916f61e2555636ec8njn                 const char *,path, UWord,length);
325389d43f79c020c46b895e2ae916f61e2555636ec8njn#endif
3254e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
3255e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
325678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
325778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_getdents)
325878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
325978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   *flags |= SfMayBlock;
3260a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getdents ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
326178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ3(long, "getdents",
326299e644a7331b25402760211be907c679431ceb8eflorian                 unsigned int, fd, struct vki_dirent *, dirp,
326378b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj                 unsigned int, count);
326478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
326578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
326678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
326778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPOST(sys_getdents)
326878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
326978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   vg_assert(SUCCESS);
327078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   if (RES > 0)
327178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj      POST_MEM_WRITE( ARG2, RES );
327278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
3273a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
3274a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getdents64)
3275a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
327678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   *flags |= SfMayBlock;
3277a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getdents64 ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
327806c7bd748d9b40861e8a764e4947b30a787fef2bnethercote   PRE_REG_READ3(long, "getdents64",
327999e644a7331b25402760211be907c679431ceb8eflorian                 unsigned int, fd, struct vki_dirent64 *, dirp,
328006c7bd748d9b40861e8a764e4947b30a787fef2bnethercote                 unsigned int, count);
328122cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
3282855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3283855d93d2e9940890b28874520fa4c1677bf825e2jsgf
328485a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_getdents64)
3285855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3286a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
328722cfccb218c6975fa852a1135ddce342474b99d2njn   if (RES > 0)
328822cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, RES );
3289855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3290855d93d2e9940890b28874520fa4c1677bf825e2jsgf
329178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_getgroups)
329278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
3293a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getgroups ( %ld, %#lx )", ARG1, ARG2);
329478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
329578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   if (ARG1 > 0)
329678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj      PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
329778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
329878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
329978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPOST(sys_getgroups)
330078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
330178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   vg_assert(SUCCESS);
330278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   if (ARG1 > 0 && RES > 0)
330378b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj      POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
330478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
3305a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
3306a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getcwd)
3307855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
33084b70e8c73ee9d28ece852b781457f0b19359e513njn   // Comment from linux/fs/dcache.c:
33094b70e8c73ee9d28ece852b781457f0b19359e513njn   //   NOTE! The user-level library version returns a character pointer.
33104b70e8c73ee9d28ece852b781457f0b19359e513njn   //   The kernel system call just returns the length of the buffer filled
33114b70e8c73ee9d28ece852b781457f0b19359e513njn   //   (which includes the ending '\0' character), or a negative error
33124b70e8c73ee9d28ece852b781457f0b19359e513njn   //   value.
33134b70e8c73ee9d28ece852b781457f0b19359e513njn   // Is this Linux-specific?  If so it should be moved to syswrap-linux.c.
3314a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getcwd ( %#lx, %llu )", ARG1,(ULong)ARG2);
3315ac866b9f2f428e733f7e01e9e84d761785720092nethercote   PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
331622cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
3317855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3318855d93d2e9940890b28874520fa4c1677bf825e2jsgf
331985a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_getcwd)
3320855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3321a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
332222cfccb218c6975fa852a1135ddce342474b99d2njn   if (RES != (Addr)NULL)
332322cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG1, RES );
3324855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3325855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3326a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_geteuid)
3327855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
33280df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRINT("sys_geteuid ( )");
33290df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRE_REG_READ0(long, "geteuid");
3330855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3331855d93d2e9940890b28874520fa4c1677bf825e2jsgf
333278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_getegid)
333378b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
333478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRINT("sys_getegid ( )");
333578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ0(long, "getegid");
333678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
333778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
333878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_getgid)
333978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
334078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRINT("sys_getgid ( )");
334178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ0(long, "getgid");
334278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
3343a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
3344a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getpid)
3345855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
33464e632c27da75082fb80efae45bbf5f7fbf8a2e3enethercote   PRINT("sys_getpid ()");
33474e632c27da75082fb80efae45bbf5f7fbf8a2e3enethercote   PRE_REG_READ0(long, "getpid");
3348855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3349855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3350696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_getpgid)
3351696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3352a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getpgid ( %ld )", ARG1);
3353696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
3354696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
335578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
335678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_getpgrp)
335778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
335878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRINT("sys_getpgrp ()");
335978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ0(long, "getpgrp");
336078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
3361855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3362a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getppid)
3363855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
33644e632c27da75082fb80efae45bbf5f7fbf8a2e3enethercote   PRINT("sys_getppid ()");
33654e632c27da75082fb80efae45bbf5f7fbf8a2e3enethercote   PRE_REG_READ0(long, "getppid");
3366855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3367855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3368cf45fd43a838e8cec32e9f3279fdc9fc893569bcnjnstatic void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
3369855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3370620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
3371620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote
3372f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#ifdef _RLIMIT_POSIX_FLAG
3373f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Darwin will sometimes set _RLIMIT_POSIX_FLAG on getrlimit calls.
3374f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Unset it here to make the switch case below work correctly.
3375f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   a1 &= ~_RLIMIT_POSIX_FLAG;
3376f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
3377f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3378620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   switch (a1) {
3379620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   case VKI_RLIMIT_NOFILE:
3380620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
3381620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
3382620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      break;
3383620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote
3384620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   case VKI_RLIMIT_DATA:
3385620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
3386620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      break;
3387620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote
3388620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   case VKI_RLIMIT_STACK:
3389620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3390620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote      break;
339189d43f79c020c46b895e2ae916f61e2555636ec8njn   }
3392855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3393855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3394696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_old_getrlimit)
3395696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3396a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_old_getrlimit ( %ld, %#lx )", ARG1,ARG2);
3397696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "old_getrlimit",
3398696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 unsigned int, resource, struct rlimit *, rlim);
3399696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3400696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3401696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3402696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_old_getrlimit)
3403696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3404696c55180aae375b48f7acc3f2aa87e13040c807sewardj   common_post_getrlimit(tid, ARG1, ARG2);
3405696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3406c37184fb0f44d188b801f7950a028a9d414b2322thughes
3407a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getrlimit)
3408620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote{
3409a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getrlimit ( %ld, %#lx )", ARG1,ARG2);
3410620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote   PRE_REG_READ2(long, "getrlimit",
3411620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote                 unsigned int, resource, struct rlimit *, rlim);
341222cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3413855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3414855d93d2e9940890b28874520fa4c1677bf825e2jsgf
341585a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_getrlimit)
3416620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote{
341722cfccb218c6975fa852a1135ddce342474b99d2njn   common_post_getrlimit(tid, ARG1, ARG2);
3418620154f29bdbf44659addf9ef6ed2eed6eee934cnethercote}
3419855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3420696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_getrusage)
3421696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3422a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_getrusage ( %ld, %#lx )", ARG1,ARG2);
3423696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3424696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3425696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3426696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3427696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_getrusage)
3428696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3429696c55180aae375b48f7acc3f2aa87e13040c807sewardj   vg_assert(SUCCESS);
3430696c55180aae375b48f7acc3f2aa87e13040c807sewardj   if (RES == 0)
3431696c55180aae375b48f7acc3f2aa87e13040c807sewardj      POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3432696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3433855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3434a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_gettimeofday)
3435855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3436a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
3437686b5db44f043ebb74f3db0fa3b803de3f313b60nethercote   PRE_REG_READ2(long, "gettimeofday",
3438686b5db44f043ebb74f3db0fa3b803de3f313b60nethercote                 struct timeval *, tv, struct timezone *, tz);
3439f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme does darwin write to *tz anymore?
344072bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   if (ARG1 != 0)
344172bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
344222cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != 0)
344322cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3444855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3445855d93d2e9940890b28874520fa4c1677bf825e2jsgf
344685a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_gettimeofday)
3447855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3448a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
344922cfccb218c6975fa852a1135ddce342474b99d2njn   if (RES == 0) {
345072bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      if (ARG1 != 0)
345172bbd8d24c6bd39734f465ce8d54904b6865de9bnjn         POST_timeval_WRITE( ARG1 );
345222cfccb218c6975fa852a1135ddce342474b99d2njn      if (ARG2 != 0)
345322cfccb218c6975fa852a1135ddce342474b99d2njn	 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
3454855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3455855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3456855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3457696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_settimeofday)
3458696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3459a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
3460696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "settimeofday",
3461696c55180aae375b48f7acc3f2aa87e13040c807sewardj                 struct timeval *, tv, struct timezone *, tz);
346272bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   if (ARG1 != 0)
3463da8549df7939ee3024938cdd8a4cc64e6c2279b8njn      PRE_timeval_READ( "settimeofday(tv)", ARG1 );
3464696c55180aae375b48f7acc3f2aa87e13040c807sewardj   if (ARG2 != 0) {
3465696c55180aae375b48f7acc3f2aa87e13040c807sewardj      PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3466696c55180aae375b48f7acc3f2aa87e13040c807sewardj      /* maybe should warn if tz->tz_dsttime is non-zero? */
3467696c55180aae375b48f7acc3f2aa87e13040c807sewardj   }
3468696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3469686b5db44f043ebb74f3db0fa3b803de3f313b60nethercote
3470a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_getuid)
3471855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
34720df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRINT("sys_getuid ( )");
34730df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRE_REG_READ0(long, "getuid");
3474855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3475855d93d2e9940890b28874520fa4c1677bf825e2jsgf
34761be9cf6df71305bb799823cefb48349df8229b7fnjnvoid ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg)
34771be9cf6df71305bb799823cefb48349df8229b7fnjn{
34781be9cf6df71305bb799823cefb48349df8229b7fnjn   /* We don't have any specific information on it, so
34791be9cf6df71305bb799823cefb48349df8229b7fnjn      try to do something reasonable based on direction and
34801be9cf6df71305bb799823cefb48349df8229b7fnjn      size bits.  The encoding scheme is described in
34811be9cf6df71305bb799823cefb48349df8229b7fnjn      /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
34821be9cf6df71305bb799823cefb48349df8229b7fnjn
34831be9cf6df71305bb799823cefb48349df8229b7fnjn      According to Simon Hausmann, _IOC_READ means the kernel
34841be9cf6df71305bb799823cefb48349df8229b7fnjn      writes a value to the ioctl value passed from the user
34851be9cf6df71305bb799823cefb48349df8229b7fnjn      space and the other way around with _IOC_WRITE. */
34861be9cf6df71305bb799823cefb48349df8229b7fnjn
34871be9cf6df71305bb799823cefb48349df8229b7fnjn   UInt dir  = _VKI_IOC_DIR(request);
34881be9cf6df71305bb799823cefb48349df8229b7fnjn   UInt size = _VKI_IOC_SIZE(request);
3489ec905f7ed1659f2251045114c785659fbb11ea88philippe   if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) {
34901be9cf6df71305bb799823cefb48349df8229b7fnjn      /*
34911be9cf6df71305bb799823cefb48349df8229b7fnjn       * Be very lax about ioctl handling; the only
34921be9cf6df71305bb799823cefb48349df8229b7fnjn       * assumption is that the size is correct. Doesn't
34931be9cf6df71305bb799823cefb48349df8229b7fnjn       * require the full buffer to be initialized when
34941be9cf6df71305bb799823cefb48349df8229b7fnjn       * writing.  Without this, using some device
34951be9cf6df71305bb799823cefb48349df8229b7fnjn       * drivers with a large number of strange ioctl
34961be9cf6df71305bb799823cefb48349df8229b7fnjn       * commands becomes very tiresome.
34971be9cf6df71305bb799823cefb48349df8229b7fnjn       */
34981be9cf6df71305bb799823cefb48349df8229b7fnjn   } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
3499d77a4ca487d41f26235601cbcd2af73d5f61cedbbart      static UWord unknown_ioctl[10];
3500d77a4ca487d41f26235601cbcd2af73d5f61cedbbart      static Int moans = sizeof(unknown_ioctl) / sizeof(unknown_ioctl[0]);
3501d77a4ca487d41f26235601cbcd2af73d5f61cedbbart
35021be9cf6df71305bb799823cefb48349df8229b7fnjn      if (moans > 0 && !VG_(clo_xml)) {
3503d77a4ca487d41f26235601cbcd2af73d5f61cedbbart         /* Check if have not already moaned for this request. */
3504d77a4ca487d41f26235601cbcd2af73d5f61cedbbart         UInt i;
3505d77a4ca487d41f26235601cbcd2af73d5f61cedbbart         for (i = 0; i < sizeof(unknown_ioctl)/sizeof(unknown_ioctl[0]); i++) {
3506d77a4ca487d41f26235601cbcd2af73d5f61cedbbart            if (unknown_ioctl[i] == request)
3507d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               break;
3508d77a4ca487d41f26235601cbcd2af73d5f61cedbbart            if (unknown_ioctl[i] == 0) {
3509d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               unknown_ioctl[i] = request;
3510d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               moans--;
3511d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
3512d77a4ca487d41f26235601cbcd2af73d5f61cedbbart                         " with no size/direction hints.\n", request);
3513d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               VG_(umsg)("   This could cause spurious value errors to appear.\n");
3514d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               VG_(umsg)("   See README_MISSING_SYSCALL_OR_IOCTL for "
3515d77a4ca487d41f26235601cbcd2af73d5f61cedbbart                         "guidance on writing a proper wrapper.\n" );
3516d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3517d77a4ca487d41f26235601cbcd2af73d5f61cedbbart               return;
3518d77a4ca487d41f26235601cbcd2af73d5f61cedbbart            }
3519d77a4ca487d41f26235601cbcd2af73d5f61cedbbart         }
35201be9cf6df71305bb799823cefb48349df8229b7fnjn      }
35211be9cf6df71305bb799823cefb48349df8229b7fnjn   } else {
35221be9cf6df71305bb799823cefb48349df8229b7fnjn      //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
35231be9cf6df71305bb799823cefb48349df8229b7fnjn      //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
35241be9cf6df71305bb799823cefb48349df8229b7fnjn      if ((dir & _VKI_IOC_WRITE) && size > 0)
35251be9cf6df71305bb799823cefb48349df8229b7fnjn         PRE_MEM_READ( "ioctl(generic)", arg, size);
35261be9cf6df71305bb799823cefb48349df8229b7fnjn      if ((dir & _VKI_IOC_READ) && size > 0)
35271be9cf6df71305bb799823cefb48349df8229b7fnjn         PRE_MEM_WRITE( "ioctl(generic)", arg, size);
35281be9cf6df71305bb799823cefb48349df8229b7fnjn   }
35291be9cf6df71305bb799823cefb48349df8229b7fnjn}
35301be9cf6df71305bb799823cefb48349df8229b7fnjn
35311be9cf6df71305bb799823cefb48349df8229b7fnjnvoid ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg)
35321be9cf6df71305bb799823cefb48349df8229b7fnjn{
35331be9cf6df71305bb799823cefb48349df8229b7fnjn   /* We don't have any specific information on it, so
35341be9cf6df71305bb799823cefb48349df8229b7fnjn      try to do something reasonable based on direction and
35351be9cf6df71305bb799823cefb48349df8229b7fnjn      size bits.  The encoding scheme is described in
35361be9cf6df71305bb799823cefb48349df8229b7fnjn      /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
35371be9cf6df71305bb799823cefb48349df8229b7fnjn
35381be9cf6df71305bb799823cefb48349df8229b7fnjn      According to Simon Hausmann, _IOC_READ means the kernel
35391be9cf6df71305bb799823cefb48349df8229b7fnjn      writes a value to the ioctl value passed from the user
35401be9cf6df71305bb799823cefb48349df8229b7fnjn      space and the other way around with _IOC_WRITE. */
35411be9cf6df71305bb799823cefb48349df8229b7fnjn
35421be9cf6df71305bb799823cefb48349df8229b7fnjn   UInt dir  = _VKI_IOC_DIR(request);
35431be9cf6df71305bb799823cefb48349df8229b7fnjn   UInt size = _VKI_IOC_SIZE(request);
35441be9cf6df71305bb799823cefb48349df8229b7fnjn   if (size > 0 && (dir & _VKI_IOC_READ)
35451be9cf6df71305bb799823cefb48349df8229b7fnjn       && res == 0
35461be9cf6df71305bb799823cefb48349df8229b7fnjn       && arg != (Addr)NULL)
35471be9cf6df71305bb799823cefb48349df8229b7fnjn   {
35481be9cf6df71305bb799823cefb48349df8229b7fnjn      POST_MEM_WRITE(arg, size);
35491be9cf6df71305bb799823cefb48349df8229b7fnjn   }
35501be9cf6df71305bb799823cefb48349df8229b7fnjn}
3551855d93d2e9940890b28874520fa4c1677bf825e2jsgf
355203f1e58116abbf9aef5090b34e5bcf39f455ec04njn/*
355303f1e58116abbf9aef5090b34e5bcf39f455ec04njn   If we're sending a SIGKILL to one of our own threads, then simulate
355403f1e58116abbf9aef5090b34e5bcf39f455ec04njn   it rather than really sending the signal, so that the target thread
355503f1e58116abbf9aef5090b34e5bcf39f455ec04njn   gets a chance to clean up.  Returns True if we did the killing (or
355603f1e58116abbf9aef5090b34e5bcf39f455ec04njn   no killing is necessary), and False if the caller should use the
355703f1e58116abbf9aef5090b34e5bcf39f455ec04njn   normal kill syscall.
355803f1e58116abbf9aef5090b34e5bcf39f455ec04njn
355903f1e58116abbf9aef5090b34e5bcf39f455ec04njn   "pid" is any pid argument which can be passed to kill; group kills
356003f1e58116abbf9aef5090b34e5bcf39f455ec04njn   (< -1, 0), and owner kills (-1) are ignored, on the grounds that
356103f1e58116abbf9aef5090b34e5bcf39f455ec04njn   they'll most likely hit all the threads and we won't need to worry
356203f1e58116abbf9aef5090b34e5bcf39f455ec04njn   about cleanup.  In truth, we can't fully emulate these multicast
356303f1e58116abbf9aef5090b34e5bcf39f455ec04njn   kills.
356403f1e58116abbf9aef5090b34e5bcf39f455ec04njn
356503f1e58116abbf9aef5090b34e5bcf39f455ec04njn   "tgid" is a thread group id.  If it is not -1, then the target
356603f1e58116abbf9aef5090b34e5bcf39f455ec04njn   thread must be in that thread group.
356703f1e58116abbf9aef5090b34e5bcf39f455ec04njn */
35687eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardjBool ML_(do_sigkill)(Int pid, Int tgid)
356903f1e58116abbf9aef5090b34e5bcf39f455ec04njn{
357003f1e58116abbf9aef5090b34e5bcf39f455ec04njn   ThreadState *tst;
357103f1e58116abbf9aef5090b34e5bcf39f455ec04njn   ThreadId tid;
357203f1e58116abbf9aef5090b34e5bcf39f455ec04njn
357303f1e58116abbf9aef5090b34e5bcf39f455ec04njn   if (pid <= 0)
357403f1e58116abbf9aef5090b34e5bcf39f455ec04njn      return False;
357503f1e58116abbf9aef5090b34e5bcf39f455ec04njn
35764278172aee9a9db96cc2f9aff9158e3164fa113csewardj   tid = VG_(lwpid_to_vgtid)(pid);
357703f1e58116abbf9aef5090b34e5bcf39f455ec04njn   if (tid == VG_INVALID_THREADID)
357803f1e58116abbf9aef5090b34e5bcf39f455ec04njn      return False;		/* none of our threads */
357903f1e58116abbf9aef5090b34e5bcf39f455ec04njn
358003f1e58116abbf9aef5090b34e5bcf39f455ec04njn   tst = VG_(get_ThreadState)(tid);
358103f1e58116abbf9aef5090b34e5bcf39f455ec04njn   if (tst == NULL || tst->status == VgTs_Empty)
358203f1e58116abbf9aef5090b34e5bcf39f455ec04njn      return False;		/* hm, shouldn't happen */
358303f1e58116abbf9aef5090b34e5bcf39f455ec04njn
358403f1e58116abbf9aef5090b34e5bcf39f455ec04njn   if (tgid != -1 && tst->os_state.threadgroup != tgid)
358503f1e58116abbf9aef5090b34e5bcf39f455ec04njn      return False;		/* not the right thread group */
358603f1e58116abbf9aef5090b34e5bcf39f455ec04njn
358703f1e58116abbf9aef5090b34e5bcf39f455ec04njn   /* Check to see that the target isn't already exiting. */
358803f1e58116abbf9aef5090b34e5bcf39f455ec04njn   if (!VG_(is_exiting)(tid)) {
358903f1e58116abbf9aef5090b34e5bcf39f455ec04njn      if (VG_(clo_trace_signals))
3590738856f99eea33d86ce91dcb1d6cd5b151e307casewardj	 VG_(message)(Vg_DebugMsg,
3591738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      "Thread %d being killed with SIGKILL\n",
3592738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                      tst->tid);
359303f1e58116abbf9aef5090b34e5bcf39f455ec04njn
359403f1e58116abbf9aef5090b34e5bcf39f455ec04njn      tst->exitreason = VgSrc_FatalSig;
359503f1e58116abbf9aef5090b34e5bcf39f455ec04njn      tst->os_state.fatalsig = VKI_SIGKILL;
359603f1e58116abbf9aef5090b34e5bcf39f455ec04njn
359703f1e58116abbf9aef5090b34e5bcf39f455ec04njn      if (!VG_(is_running_thread)(tid))
3598ef1cf8b3583107c7d918c60895937f09969d5b3esewardj	 VG_(get_thread_out_of_syscall)(tid);
359903f1e58116abbf9aef5090b34e5bcf39f455ec04njn   }
360003f1e58116abbf9aef5090b34e5bcf39f455ec04njn
360103f1e58116abbf9aef5090b34e5bcf39f455ec04njn   return True;
360203f1e58116abbf9aef5090b34e5bcf39f455ec04njn}
360303f1e58116abbf9aef5090b34e5bcf39f455ec04njn
3604a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_kill)
3605855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3606a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_kill ( %ld, %ld )", ARG1,ARG2);
36079a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ2(long, "kill", int, pid, int, sig);
36087eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(client_signal_OK)(ARG2)) {
3609a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EINVAL );
361003f1e58116abbf9aef5090b34e5bcf39f455ec04njn      return;
361103f1e58116abbf9aef5090b34e5bcf39f455ec04njn   }
361203f1e58116abbf9aef5090b34e5bcf39f455ec04njn
361303f1e58116abbf9aef5090b34e5bcf39f455ec04njn   /* If we're sending SIGKILL, check to see if the target is one of
361403f1e58116abbf9aef5090b34e5bcf39f455ec04njn      our threads and handle it specially. */
36157eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
3616a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Success(0);
361703f1e58116abbf9aef5090b34e5bcf39f455ec04njn   else
3618cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean)
3619cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         affecting how posix-compliant the call is.  I guess it is
3620cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         harmless to pass the 3rd arg on other platforms; hence pass
3621cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         it on all. */
3622cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) );
3623855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3624b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj   if (VG_(clo_trace_signals))
3625738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld\n",
3626a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj		   ARG2, ARG1);
3627855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3628a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   /* This kill might have given us a pending signal.  Ask for a check once
3629a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      the syscall is done. */
3630a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfPollAfter;
3631855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3632855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3633a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_link)
3634855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3635a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
3636a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_link ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
3637a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
3638a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
3639a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
3640855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3641855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3642696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_newlstat)
3643696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3644a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
3645696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
3646696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
3647696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
3648696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3649696c55180aae375b48f7acc3f2aa87e13040c807sewardj
3650696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_newlstat)
3651696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
3652696c55180aae375b48f7acc3f2aa87e13040c807sewardj   vg_assert(SUCCESS);
36539331c7b3e370971945f47e6c5f647a728ae0815anjn   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3654696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
3655a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
3656a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_mkdir)
3657a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
3658a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
3659a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mkdir ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
36609a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
366122cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
3662855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3663855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3664a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_mprotect)
3665855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3666a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mprotect ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
366706c7bd748d9b40861e8a764e4947b30a787fef2bnethercote   PRE_REG_READ3(long, "mprotect",
366806c7bd748d9b40861e8a764e4947b30a787fef2bnethercote                 unsigned long, addr, vki_size_t, len, unsigned long, prot);
366998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
367065505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom   if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
3671a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_ENOMEM );
3672337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj   }
3673f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VKI_PROT_GROWSDOWN)
3674337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj   else
3675337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj   if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
3676337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj      /* Deal with mprotects on growable stack areas.
3677337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj
3678337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         The critical files to understand all this are mm/mprotect.c
3679337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
3680337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         glibc.
3681337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj
3682337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
3683337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         round the start/end address of mprotect to the start/end of
3684337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         the underlying vma and glibc uses that as an easy way to
3685337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         change the protection of the stack by calling mprotect on the
3686337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         last page of the stack with PROT_GROWSDOWN set.
3687337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj
3688337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         The sanity check provided by the kernel is that the vma must
3689337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate.  */
369065505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
3691ef1cf8b3583107c7d918c60895937f09969d5b3esewardj      NSegment const *aseg = VG_(am_find_nsegment)(ARG1);
3692ef1cf8b3583107c7d918c60895937f09969d5b3esewardj      NSegment const *rseg;
369365505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom
369465505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      vg_assert(aseg);
369565505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom
369665505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      if (grows == VKI_PROT_GROWSDOWN) {
36973e7986312a0ffc7646b0552d4c4ea3744a870e73florian         rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ );
369865505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         if (rseg &&
369965505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             rseg->kind == SkResvn &&
370065505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             rseg->smode == SmUpper &&
370165505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             rseg->end+1 == aseg->start) {
370265505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            Addr end = ARG1 + ARG2;
370365505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            ARG1 = aseg->start;
370465505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            ARG2 = end - aseg->start;
370565505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            ARG3 &= ~VKI_PROT_GROWSDOWN;
370665505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         } else {
370765505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            SET_STATUS_Failure( VKI_EINVAL );
370865505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         }
370965505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      } else if (grows == VKI_PROT_GROWSUP) {
37103e7986312a0ffc7646b0552d4c4ea3744a870e73florian         rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
371165505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         if (rseg &&
371265505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             rseg->kind == SkResvn &&
371365505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             rseg->smode == SmLower &&
371465505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom             aseg->end+1 == rseg->start) {
371565505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            ARG2 = aseg->end - ARG1 + 1;
371665505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            ARG3 &= ~VKI_PROT_GROWSUP;
371765505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         } else {
371865505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom            SET_STATUS_Failure( VKI_EINVAL );
371965505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         }
372065505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      } else {
3721337556eb91e1b42f37cd9c9c4760c4814f991a9csewardj         /* both GROWSUP and GROWSDOWN */
372265505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom         SET_STATUS_Failure( VKI_EINVAL );
372365505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom      }
372465505193b8d9c8f36f3df6c5d6a8e1d475bb37cbtom   }
3725f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif   // defined(VKI_PROT_GROWSDOWN)
3726855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3727855d93d2e9940890b28874520fa4c1677bf825e2jsgf
372885a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_mprotect)
3729855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
373022cfccb218c6975fa852a1135ddce342474b99d2njn   Addr a    = ARG1;
373122cfccb218c6975fa852a1135ddce342474b99d2njn   SizeT len = ARG2;
373222cfccb218c6975fa852a1135ddce342474b99d2njn   Int  prot = ARG3;
373327ea8bc6721add61e6284cbbf684b7d06a4bd2eenethercote
3734dd3725800151572d32df10ad4df4c8aad0d3d088njn   ML_(notify_core_and_tool_of_mprotect)(a, len, prot);
3735855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3736855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3737a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_munmap)
3738855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3739a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   if (0) VG_(printf)("  munmap( %#lx )\n", ARG1);
3740a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_munmap ( %#lx, %llu )", ARG1,(ULong)ARG2);
374106c7bd748d9b40861e8a764e4947b30a787fef2bnethercote   PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
374298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
37437eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
3744a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EINVAL );
3745855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3746855d93d2e9940890b28874520fa4c1677bf825e2jsgf
374785a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_munmap)
3748855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
374922cfccb218c6975fa852a1135ddce342474b99d2njn   Addr  a   = ARG1;
375022cfccb218c6975fa852a1135ddce342474b99d2njn   SizeT len = ARG2;
375127ea8bc6721add61e6284cbbf684b7d06a4bd2eenethercote
3752ddd61ff058f02059064e083a8accaefed23d5548florian   ML_(notify_core_and_tool_of_munmap)( a, len );
3753855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3754855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3755e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_mincore)
3756e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3757a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_mincore ( %#lx, %llu, %#lx )", ARG1,(ULong)ARG2,ARG3);
3758e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "mincore",
3759e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned long, start, vki_size_t, length,
3760e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 unsigned char *, vec);
3761cdaec51384acbac00c7d88f9a54f2ee1f8f3f3e7njn   PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
3762e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
3763e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPOST(sys_mincore)
3764e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
3765cdaec51384acbac00c7d88f9a54f2ee1f8f3f3e7njn   POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
3766e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
37676ceb231d84aaff064f27d38b9662750a584a189dmueller
3768a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_nanosleep)
3769855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3770a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock|SfPostOnFail;
3771a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_nanosleep ( %#lx, %#lx )", ARG1,ARG2);
37725b653bc2c60f6913e5bb6c2ebabfcf705a90c012nethercote   PRE_REG_READ2(long, "nanosleep",
37735b653bc2c60f6913e5bb6c2ebabfcf705a90c012nethercote                 struct timespec *, req, struct timespec *, rem);
377422cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
377522cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != 0)
377622cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
3777855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3778855d93d2e9940890b28874520fa4c1677bf825e2jsgf
377985a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_nanosleep)
3780855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3781a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS || FAILURE);
3782ef1cf8b3583107c7d918c60895937f09969d5b3esewardj   if (ARG2 != 0 && FAILURE && ERR == VKI_EINTR)
378322cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
3784855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3785855d93d2e9940890b28874520fa4c1677bf825e2jsgf
3786a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_open)
3787855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
378822cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 & VKI_O_CREAT) {
3789e824cc428f6ef4a68707e99119e4ff5f1764681enethercote      // 3-arg version
3790a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      PRINT("sys_open ( %#lx(%s), %ld, %ld )",ARG1,(char*)ARG1,ARG2,ARG3);
3791e824cc428f6ef4a68707e99119e4ff5f1764681enethercote      PRE_REG_READ3(long, "open",
37920df495a33f39817e5cabbe94f3a5159f178d1a3anethercote                    const char *, filename, int, flags, int, mode);
3793e70bd7d565d58f043d07f140fd1c1b88c47899b4nethercote   } else {
3794e824cc428f6ef4a68707e99119e4ff5f1764681enethercote      // 2-arg version
3795a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart      PRINT("sys_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
3796e824cc428f6ef4a68707e99119e4ff5f1764681enethercote      PRE_REG_READ2(long, "open",
37970df495a33f39817e5cabbe94f3a5159f178d1a3anethercote                    const char *, filename, int, flags);
3798e70bd7d565d58f043d07f140fd1c1b88c47899b4nethercote   }
379922cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
380045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
38019b533f803bec4634f1106e4d4a7063d49c9694e7bart#if defined(VGO_linux)
38029b533f803bec4634f1106e4d4a7063d49c9694e7bart   /* Handle the case where the open is of /proc/self/cmdline or
38039b533f803bec4634f1106e4d4a7063d49c9694e7bart      /proc/<pid>/cmdline, and just give it a copy of the fd for the
38049b533f803bec4634f1106e4d4a7063d49c9694e7bart      fake file we cooked up at startup (in m_main).  Also, seek the
38059b533f803bec4634f1106e4d4a7063d49c9694e7bart      cloned fd back to the start. */
380670fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn   {
3807f44ff62031a5344468774ada6f1b7375dfd85e7bflorian      HChar  name[30];   // large enough
380819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* arg1s = (HChar*) ARG1;
380970fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn      SysRes sres;
381070fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn
381170fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn      VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
381270fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn      if (ML_(safe_to_deref)( arg1s, 1 ) &&
381370fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn          (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/cmdline"))
381470fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         )
381570fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn      {
381670fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         sres = VG_(dup)( VG_(cl_cmdline_fd) );
381770fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         SET_STATUS_from_SysRes( sres );
381870fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         if (!sr_isError(sres)) {
381970fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn            OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
382070fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn            if (off < 0)
382170fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn               SET_STATUS_Failure( VKI_EMFILE );
382270fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         }
382370fa47d6e19313d5f3a7b7aaae14059d98b6f1aenjn         return;
382445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
382545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
382641ad7e73914ee13bd1467ce48a1532570218e327tom
382741ad7e73914ee13bd1467ce48a1532570218e327tom   /* Handle the case where the open is of /proc/self/auxv or
382841ad7e73914ee13bd1467ce48a1532570218e327tom      /proc/<pid>/auxv, and just give it a copy of the fd for the
382941ad7e73914ee13bd1467ce48a1532570218e327tom      fake file we cooked up at startup (in m_main).  Also, seek the
383041ad7e73914ee13bd1467ce48a1532570218e327tom      cloned fd back to the start. */
383141ad7e73914ee13bd1467ce48a1532570218e327tom   {
3832f44ff62031a5344468774ada6f1b7375dfd85e7bflorian      HChar  name[30];   // large enough
383319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* arg1s = (HChar*) ARG1;
383441ad7e73914ee13bd1467ce48a1532570218e327tom      SysRes sres;
383541ad7e73914ee13bd1467ce48a1532570218e327tom
383641ad7e73914ee13bd1467ce48a1532570218e327tom      VG_(sprintf)(name, "/proc/%d/auxv", VG_(getpid)());
383741ad7e73914ee13bd1467ce48a1532570218e327tom      if (ML_(safe_to_deref)( arg1s, 1 ) &&
383841ad7e73914ee13bd1467ce48a1532570218e327tom          (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/auxv"))
383941ad7e73914ee13bd1467ce48a1532570218e327tom         )
384041ad7e73914ee13bd1467ce48a1532570218e327tom      {
384141ad7e73914ee13bd1467ce48a1532570218e327tom         sres = VG_(dup)( VG_(cl_auxv_fd) );
384241ad7e73914ee13bd1467ce48a1532570218e327tom         SET_STATUS_from_SysRes( sres );
384341ad7e73914ee13bd1467ce48a1532570218e327tom         if (!sr_isError(sres)) {
384441ad7e73914ee13bd1467ce48a1532570218e327tom            OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
384541ad7e73914ee13bd1467ce48a1532570218e327tom            if (off < 0)
384641ad7e73914ee13bd1467ce48a1532570218e327tom               SET_STATUS_Failure( VKI_EMFILE );
384741ad7e73914ee13bd1467ce48a1532570218e327tom         }
384841ad7e73914ee13bd1467ce48a1532570218e327tom         return;
384941ad7e73914ee13bd1467ce48a1532570218e327tom      }
385041ad7e73914ee13bd1467ce48a1532570218e327tom   }
38519b533f803bec4634f1106e4d4a7063d49c9694e7bart#endif // defined(VGO_linux)
385245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
385345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Otherwise handle normally */
385445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *flags |= SfMayBlock;
3855855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
38562f0de32c44c3e04c080fd9f6ccb1b486a954d8a7sewardj
385785a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_open)
3858855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3859a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
38607eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(RES, "open", tid, True)) {
386122cfccb218c6975fa852a1135ddce342474b99d2njn      VG_(close)(RES);
3862a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EMFILE );
3863f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
3864493dd18a6344fcb2a017a7b888d33b7fbe8b1519nethercote      if (VG_(clo_track_fds))
386519f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3866855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3867855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
38682f0de32c44c3e04c080fd9f6ccb1b486a954d8a7sewardj
3869a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_read)
3870855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3871a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
3872a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
38738b76fe55a596a4296ba5028e2510015fef38b02fnethercote   PRE_REG_READ3(ssize_t, "read",
3874ca0518df66f8c3375a860f1a55a51f18e2a16c44njn                 unsigned int, fd, char *, buf, vki_size_t, count);
3875de4a1d01951937632098a6cda45859afa587a06fsewardj
38767eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(ARG1, "read", tid, False))
3877a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
387826ab77bacd7e40d93ba47632deac0403c39921b4thughes   else
387922cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
3880855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3881de4a1d01951937632098a6cda45859afa587a06fsewardj
388285a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_read)
3883855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3884a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
388522cfccb218c6975fa852a1135ddce342474b99d2njn   POST_MEM_WRITE( ARG2, RES );
3886855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3887de4a1d01951937632098a6cda45859afa587a06fsewardj
3888a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_write)
3889855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
389045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool ok;
3891a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
3892a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_write ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
38938b76fe55a596a4296ba5028e2510015fef38b02fnethercote   PRE_REG_READ3(ssize_t, "write",
3894ca0518df66f8c3375a860f1a55a51f18e2a16c44njn                 unsigned int, fd, const char *, buf, vki_size_t, count);
389545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* check to see if it is allowed.  If not, try for an exemption from
3896628add6061c08b1e93562bd5559e40f6d158bbb6njn      --sim-hints=enable-outer (used for self hosting). */
389745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ok = ML_(fd_allowed)(ARG1, "write", tid, False);
389845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok && ARG1 == 2/*stderr*/
3899ec905f7ed1659f2251045114c785659fbb11ea88philippe           && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
390045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      ok = True;
390145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok)
3902a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
3903855d93d2e9940890b28874520fa4c1677bf825e2jsgf   else
390422cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
3905855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3906de4a1d01951937632098a6cda45859afa587a06fsewardj
3907a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_creat)
3908855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3909a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
3910a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_creat ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3911c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
391222cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
3913855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3914de4a1d01951937632098a6cda45859afa587a06fsewardj
391585a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_creat)
3916855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3917a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
39187eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
391922cfccb218c6975fa852a1135ddce342474b99d2njn      VG_(close)(RES);
3920a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EMFILE );
3921f5f536f398c082b8c92b2789a90d83b34ab98660rjwalsh   } else {
3922493dd18a6344fcb2a017a7b888d33b7fbe8b1519nethercote      if (VG_(clo_track_fds))
392319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian         ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3924855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3925855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3926de4a1d01951937632098a6cda45859afa587a06fsewardj
3927a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_poll)
3928855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3929855d93d2e9940890b28874520fa4c1677bf825e2jsgf   /* struct pollfd {
3930ef0c7663cb71101c7b718108253444cb75402cbbnethercote        int fd;           -- file descriptor
3931ef0c7663cb71101c7b718108253444cb75402cbbnethercote        short events;     -- requested events
3932ef0c7663cb71101c7b718108253444cb75402cbbnethercote        short revents;    -- returned events
3933855d93d2e9940890b28874520fa4c1677bf825e2jsgf      };
3934eb0592dc023c1cbe99a2e25d3251d11aa60bec64nethercote      int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
3935855d93d2e9940890b28874520fa4c1677bf825e2jsgf   */
3936eb0592dc023c1cbe99a2e25d3251d11aa60bec64nethercote   UInt i;
393722cfccb218c6975fa852a1135ddce342474b99d2njn   struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
393860a4b0b77180f0c54ddca5c8d9ca20a877637f01tom   *flags |= SfMayBlock;
3939a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3);
3940f90953e0461db3fb14e293a66a909a5d661dd0adnethercote   PRE_REG_READ3(long, "poll",
3941363ec7610ee649b946edf5c1a5546b94bbf0844dtom                 struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout);
3942363ec7610ee649b946edf5c1a5546b94bbf0844dtom
394322cfccb218c6975fa852a1135ddce342474b99d2njn   for (i = 0; i < ARG2; i++) {
3944363ec7610ee649b946edf5c1a5546b94bbf0844dtom      PRE_MEM_READ( "poll(ufds.fd)",
3945363ec7610ee649b946edf5c1a5546b94bbf0844dtom                    (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
3946363ec7610ee649b946edf5c1a5546b94bbf0844dtom      PRE_MEM_READ( "poll(ufds.events)",
3947363ec7610ee649b946edf5c1a5546b94bbf0844dtom                    (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
394868f338fbf7dd659d5377e7e0f6c6532a7f73f302tom      PRE_MEM_WRITE( "poll(ufds.revents)",
3949363ec7610ee649b946edf5c1a5546b94bbf0844dtom                     (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
3950363ec7610ee649b946edf5c1a5546b94bbf0844dtom   }
3951855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3952de4a1d01951937632098a6cda45859afa587a06fsewardj
395385a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_poll)
3954855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3955416b206ee93d5e2848f66a4d86ffb654956ee2b8sewardj   if (RES >= 0) {
3956855d93d2e9940890b28874520fa4c1677bf825e2jsgf      UInt i;
395722cfccb218c6975fa852a1135ddce342474b99d2njn      struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
395822cfccb218c6975fa852a1135ddce342474b99d2njn      for (i = 0; i < ARG2; i++)
3959363ec7610ee649b946edf5c1a5546b94bbf0844dtom	 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
3960855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
3961855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
3962de4a1d01951937632098a6cda45859afa587a06fsewardj
3963a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_readlink)
3964855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
3965cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
3966cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn   Word saved = SYSNO;
3967144c56d11824d3a3f7df68737b73c1b562155723sewardj
3968a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
39695a945afbb6f858ed3a51219bb8aaf24caa07c2c5nethercote   PRE_REG_READ3(long, "readlink",
39705a945afbb6f858ed3a51219bb8aaf24caa07c2c5nethercote                 const char *, path, char *, buf, int, bufsiz);
397122cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
397222cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
3973de4a1d01951937632098a6cda45859afa587a06fsewardj
3974cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn   {
39759b533f803bec4634f1106e4d4a7063d49c9694e7bart#if defined(VGO_linux)
3976cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      /*
3977cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn       * Handle the case where readlink is looking at /proc/self/exe or
3978cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn       * /proc/<pid>/exe.
3979cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn       */
3980f44ff62031a5344468774ada6f1b7375dfd85e7bflorian      HChar  name[30];   // large enough
398119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      HChar* arg1s = (HChar*) ARG1;
3982cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
39839b533f803bec4634f1106e4d4a7063d49c9694e7bart      if (ML_(safe_to_deref)(arg1s, 1) &&
3984cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn          (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe"))
3985cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn         )
3986cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      {
3987cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn         VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
3988cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn         SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
3989cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn                                                         ARG2, ARG3));
3990cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      } else
39919b533f803bec4634f1106e4d4a7063d49c9694e7bart#endif // defined(VGO_linux)
3992cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      {
3993cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn         /* Normal case */
3994cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn         SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
3995cc1284f15c0a3fcfeec7fde68761c03d7f217f8anjn      }
399617d853046a1bfc276c7dd75b7c6b2e348cdf5d24rjwalsh   }
399717d853046a1bfc276c7dd75b7c6b2e348cdf5d24rjwalsh
3998a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (SUCCESS && RES > 0)
399922cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, RES );
4000855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4001de4a1d01951937632098a6cda45859afa587a06fsewardj
4002a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_readv)
4003855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4004855d93d2e9940890b28874520fa4c1677bf825e2jsgf   Int i;
400573b526fb4af0f60634f0078583d92b931d5c0eebnethercote   struct vki_iovec * vec;
4006a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4007a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_readv ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
4008d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote   PRE_REG_READ3(ssize_t, "readv",
4009d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                 unsigned long, fd, const struct iovec *, vector,
4010d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                 unsigned long, count);
40117eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
4012a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
4013855d93d2e9940890b28874520fa4c1677bf825e2jsgf   } else {
40147cbe0688bc1ac313110dee71966a5d958f8c7066florian      if ((Int)ARG3 >= 0)
40157cbe0688bc1ac313110dee71966a5d958f8c7066florian         PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
4016d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote
401722cfccb218c6975fa852a1135ddce342474b99d2njn      if (ARG2 != 0) {
4018d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote         /* ToDo: don't do any of the following if the vector is invalid */
401922cfccb218c6975fa852a1135ddce342474b99d2njn         vec = (struct vki_iovec *)ARG2;
402022cfccb218c6975fa852a1135ddce342474b99d2njn         for (i = 0; i < (Int)ARG3; i++)
4021d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote            PRE_MEM_WRITE( "readv(vector[...])",
4022d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                           (Addr)vec[i].iov_base, vec[i].iov_len );
4023d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote      }
4024855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4025855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4026de4a1d01951937632098a6cda45859afa587a06fsewardj
402785a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_readv)
4028855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4029a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
403022cfccb218c6975fa852a1135ddce342474b99d2njn   if (RES > 0) {
4031855d93d2e9940890b28874520fa4c1677bf825e2jsgf      Int i;
403222cfccb218c6975fa852a1135ddce342474b99d2njn      struct vki_iovec * vec = (struct vki_iovec *)ARG2;
403322cfccb218c6975fa852a1135ddce342474b99d2njn      Int remains = RES;
4034855d93d2e9940890b28874520fa4c1677bf825e2jsgf
403522cfccb218c6975fa852a1135ddce342474b99d2njn      /* RES holds the number of bytes read. */
403622cfccb218c6975fa852a1135ddce342474b99d2njn      for (i = 0; i < (Int)ARG3; i++) {
4037855d93d2e9940890b28874520fa4c1677bf825e2jsgf	 Int nReadThisBuf = vec[i].iov_len;
4038855d93d2e9940890b28874520fa4c1677bf825e2jsgf	 if (nReadThisBuf > remains) nReadThisBuf = remains;
4039ef0c7663cb71101c7b718108253444cb75402cbbnethercote	 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
4040855d93d2e9940890b28874520fa4c1677bf825e2jsgf	 remains -= nReadThisBuf;
4041855d93d2e9940890b28874520fa4c1677bf825e2jsgf	 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4042855d93d2e9940890b28874520fa4c1677bf825e2jsgf      }
4043855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4044855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4045de4a1d01951937632098a6cda45859afa587a06fsewardj
4046a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_rename)
4047855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4048cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
4049a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
40509a3beb9fc89e9859ca9c3b93fa9c08ee2a2df11bnethercote   PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
405122cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
405222cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
4053855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4054de4a1d01951937632098a6cda45859afa587a06fsewardj
405578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_rmdir)
405678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
405778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   *flags |= SfMayBlock;
4058a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_rmdir ( %#lx(%s) )", ARG1,(char*)ARG1);
405978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ1(long, "rmdir", const char *, pathname);
406078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
406178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
406278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
4063a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_select)
4064a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
4065a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4066a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
4067f1049bfd7145c4d8ee333bb2a714700e1ab3a049nethercote   PRE_REG_READ5(long, "select",
4068f1049bfd7145c4d8ee333bb2a714700e1ab3a049nethercote                 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
4069363ec7610ee649b946edf5c1a5546b94bbf0844dtom                 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
4070a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   // XXX: this possibly understates how much memory is read.
4071a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG2 != 0)
4072a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      PRE_MEM_READ( "select(readfds)",
4073a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj		     ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
4074a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG3 != 0)
4075a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      PRE_MEM_READ( "select(writefds)",
4076a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj		     ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
4077a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG4 != 0)
4078a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      PRE_MEM_READ( "select(exceptfds)",
4079a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj		     ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
4080a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   if (ARG5 != 0)
408172bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_READ( "select(timeout)", ARG5 );
4082855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4083de4a1d01951937632098a6cda45859afa587a06fsewardj
4084e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_setgid)
4085e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4086a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setgid ( %ld )", ARG1);
4087e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
4088e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4089696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4090696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_setsid)
4091696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4092696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRINT("sys_setsid ( )");
4093696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ0(long, "setsid");
4094696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4095696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4096e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_setgroups)
4097e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4098a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("setgroups ( %llu, %#lx )", (ULong)ARG1, ARG2);
4099e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
4100e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   if (ARG1 > 0)
4101e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj      PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
4102e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4103696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4104696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_setpgid)
4105696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4106a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("setpgid ( %ld, %ld )", ARG1, ARG2);
4107696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
4108696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4109696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4110696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_setregid)
4111696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4112a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setregid ( %ld, %ld )", ARG1, ARG2);
4113696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
4114696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4115696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4116e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_setreuid)
4117e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4118a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setreuid ( 0x%lx, 0x%lx )", ARG1, ARG2);
4119e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
4120e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4121a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
4122a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_setrlimit)
4123855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4124f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   UWord arg1 = ARG1;
4125a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setrlimit ( %ld, %#lx )", ARG1,ARG2);
4126a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_REG_READ2(long, "setrlimit",
4127a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                 unsigned int, resource, struct rlimit *, rlim);
4128a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
4129de4a1d01951937632098a6cda45859afa587a06fsewardj
4130f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#ifdef _RLIMIT_POSIX_FLAG
4131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Darwin will sometimes set _RLIMIT_POSIX_FLAG on setrlimit calls.
4132f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Unset it here to make the if statements below work correctly.
4133f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   arg1 &= ~_RLIMIT_POSIX_FLAG;
4134f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
4135f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
4136db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe   if (!VG_(am_is_valid_for_client)(ARG2, sizeof(struct vki_rlimit),
4137db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe                                    VKI_PROT_READ)) {
4138db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe      SET_STATUS_Failure( VKI_EFAULT );
4139db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe   }
4140db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe   else if (((struct vki_rlimit *)ARG2)->rlim_cur
4141db16f835c79e8f5167b4aff9ee1ddf72637ef605philippe            > ((struct vki_rlimit *)ARG2)->rlim_max) {
4142aba260b91b0331551006d15f25b8576b7544d0e8tom      SET_STATUS_Failure( VKI_EINVAL );
4143aba260b91b0331551006d15f25b8576b7544d0e8tom   }
4144aba260b91b0331551006d15f25b8576b7544d0e8tom   else if (arg1 == VKI_RLIMIT_NOFILE) {
4145a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
4146a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj          ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
4147a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Failure( VKI_EPERM );
4148a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4149a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      else {
4150a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
4151a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Success( 0 );
4152a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4153a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   }
4154f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   else if (arg1 == VKI_RLIMIT_DATA) {
4155ae0739db46c69a8eb61bcad010e14395b7e55507tom      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_data).rlim_max ||
4156ae0739db46c69a8eb61bcad010e14395b7e55507tom          ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_data).rlim_max) {
4157a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Failure( VKI_EPERM );
4158a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4159a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      else {
4160a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
4161a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Success( 0 );
4162a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4163a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   }
4164f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
4165ae0739db46c69a8eb61bcad010e14395b7e55507tom      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_stack).rlim_max ||
4166ae0739db46c69a8eb61bcad010e14395b7e55507tom          ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_stack).rlim_max) {
4167a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Failure( VKI_EPERM );
4168a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4169a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      else {
4170a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
4171a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
4172a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj         SET_STATUS_Success( 0 );
4173a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      }
4174a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   }
4175855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4176de4a1d01951937632098a6cda45859afa587a06fsewardj
4177e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_setuid)
4178e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4179a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_setuid ( %ld )", ARG1);
4180e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
4181e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4182a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
4183696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_newstat)
4184696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4185d7aa40dc6b8f90fcd31272b83beb9c6efb25ef96philippe   FUSE_COMPATIBLE_MAY_BLOCK();
4186a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
4187696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
4188696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
4189696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
4190696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4191696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4192696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_newstat)
4193696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4194696c55180aae375b48f7acc3f2aa87e13040c807sewardj   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
4195696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4196696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4197696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_statfs)
4198696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4199d7aa40dc6b8f90fcd31272b83beb9c6efb25ef96philippe   FUSE_COMPATIBLE_MAY_BLOCK();
4200a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
4201696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
4202696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
4203696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
4204696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4205696c55180aae375b48f7acc3f2aa87e13040c807sewardjPOST(sys_statfs)
4206696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4207696c55180aae375b48f7acc3f2aa87e13040c807sewardj   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
4208696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4209696c55180aae375b48f7acc3f2aa87e13040c807sewardj
4210e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_statfs64)
4211e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4212a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3);
4213e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ3(long, "statfs64",
4214e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj                 const char *, path, vki_size_t, size, struct statfs64 *, buf);
4215e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4216e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
4217e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4218e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPOST(sys_statfs64)
4219e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4220e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   POST_MEM_WRITE( ARG3, ARG2 );
4221e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
422278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
422378b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_symlink)
422478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
422578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   *flags |= SfMayBlock;
4226a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_symlink ( %#lx(%s), %#lx(%s) )",ARG1,(char*)ARG1,ARG2,(char*)ARG2);
422778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
422878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
422978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
423078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
4231a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
4232a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_time)
4233855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4234855d93d2e9940890b28874520fa4c1677bf825e2jsgf   /* time_t time(time_t *t); */
4235a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_time ( %#lx )",ARG1);
4236c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ1(long, "time", int *, t);
423722cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG1 != 0) {
423822cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
4239855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4240855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4241de4a1d01951937632098a6cda45859afa587a06fsewardj
424285a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_time)
4243855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
424422cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG1 != 0) {
424522cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
4246855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4247855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4248de4a1d01951937632098a6cda45859afa587a06fsewardj
424978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_times)
425078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
4251a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_times ( %#lx )", ARG1);
425278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ1(long, "times", struct tms *, buf);
425318f19278908d44d9d3ed0d8c318a1c6f28f7d06ftom   if (ARG1 != 0) {
425418f19278908d44d9d3ed0d8c318a1c6f28f7d06ftom      PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
425518f19278908d44d9d3ed0d8c318a1c6f28f7d06ftom   }
425678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
425778b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
425878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPOST(sys_times)
425978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
426078b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   if (ARG1 != 0) {
426178b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj      POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
426278b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   }
426378b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
426478b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj
426578b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardjPRE(sys_umask)
426678b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj{
4267a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_umask ( %ld )", ARG1);
426878b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj   PRE_REG_READ1(long, "umask", int, mask);
426978b50e44c3d2a0c8c5e5d32516a03bb6903a8d1asewardj}
4270a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
4271a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_unlink)
4272a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
4273a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4274a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
4275c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ1(long, "unlink", const char *, pathname);
427622cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
4277855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4278de4a1d01951937632098a6cda45859afa587a06fsewardj
4279a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_newuname)
4280855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4281a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_newuname ( %#lx )", ARG1);
42821a1b9b7f6ccdaf88f3fb3a69ea9a2752d7a2c726nethercote   PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
428322cfccb218c6975fa852a1135ddce342474b99d2njn   PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
4284855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4285de4a1d01951937632098a6cda45859afa587a06fsewardj
428685a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_newuname)
4287855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
428822cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG1 != 0) {
428922cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
4290855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4291855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4292de4a1d01951937632098a6cda45859afa587a06fsewardj
4293a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_waitpid)
4294855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4295a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4296a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_waitpid ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
4297c6851dde1b46166417a2bdb096c05818f5f07f09nethercote   PRE_REG_READ3(long, "waitpid",
4298c6851dde1b46166417a2bdb096c05818f5f07f09nethercote                 vki_pid_t, pid, unsigned int *, status, int, options);
4299de4a1d01951937632098a6cda45859afa587a06fsewardj
430022cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != (Addr)NULL)
430122cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
4302855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4303de4a1d01951937632098a6cda45859afa587a06fsewardj
430485a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_waitpid)
4305855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
430622cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != (Addr)NULL)
430722cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, sizeof(int) );
4308855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4309de4a1d01951937632098a6cda45859afa587a06fsewardj
4310a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_wait4)
4311855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4312a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4313a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_wait4 ( %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4);
4314855d93d2e9940890b28874520fa4c1677bf825e2jsgf
43157f7e4d1ac0c4ea8bf771e5490b69d0e4d619dfe9nethercote   PRE_REG_READ4(long, "wait4",
43167f7e4d1ac0c4ea8bf771e5490b69d0e4d619dfe9nethercote                 vki_pid_t, pid, unsigned int *, status, int, options,
43177f7e4d1ac0c4ea8bf771e5490b69d0e4d619dfe9nethercote                 struct rusage *, rusage);
431822cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != (Addr)NULL)
431922cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
432022cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG4 != (Addr)NULL)
432122cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
4322855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4323de4a1d01951937632098a6cda45859afa587a06fsewardj
432485a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_wait4)
4325855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
432622cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != (Addr)NULL)
432722cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, sizeof(int) );
432822cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG4 != (Addr)NULL)
432922cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
4330855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4331de4a1d01951937632098a6cda45859afa587a06fsewardj
4332a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_writev)
4333855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4334855d93d2e9940890b28874520fa4c1677bf825e2jsgf   Int i;
433573b526fb4af0f60634f0078583d92b931d5c0eebnethercote   struct vki_iovec * vec;
4336a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
4337a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_writev ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
4338d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote   PRE_REG_READ3(ssize_t, "writev",
4339d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                 unsigned long, fd, const struct iovec *, vector,
4340d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                 unsigned long, count);
43417eb7c58d166ac00515ec757dcf9c7b0d177d28c9sewardj   if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
4342a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      SET_STATUS_Failure( VKI_EBADF );
4343855d93d2e9940890b28874520fa4c1677bf825e2jsgf   } else {
43447cbe0688bc1ac313110dee71966a5d958f8c7066florian      if ((Int)ARG3 >= 0)
43457cbe0688bc1ac313110dee71966a5d958f8c7066florian         PRE_MEM_READ( "writev(vector)",
43467cbe0688bc1ac313110dee71966a5d958f8c7066florian                       ARG2, ARG3 * sizeof(struct vki_iovec) );
434722cfccb218c6975fa852a1135ddce342474b99d2njn      if (ARG2 != 0) {
4348d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote         /* ToDo: don't do any of the following if the vector is invalid */
434922cfccb218c6975fa852a1135ddce342474b99d2njn         vec = (struct vki_iovec *)ARG2;
435022cfccb218c6975fa852a1135ddce342474b99d2njn         for (i = 0; i < (Int)ARG3; i++)
4351d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote            PRE_MEM_READ( "writev(vector[...])",
4352d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote                           (Addr)vec[i].iov_base, vec[i].iov_len );
4353d6b5a2103d0d57546d4ef9e00fb5f3a07fe0e803nethercote      }
4354855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
4355855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4356de4a1d01951937632098a6cda45859afa587a06fsewardj
4357e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardjPRE(sys_utimes)
4358e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj{
4359cc3de2dfcb3b724ecd305d9a30e9095fae6664c5sewardj   FUSE_COMPATIBLE_MAY_BLOCK();
4360a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
4361e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
4362e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj   PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
436372bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   if (ARG2 != 0) {
436472bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_READ( "utimes(tvp[0])", ARG2 );
436572bbd8d24c6bd39734f465ce8d54904b6865de9bnjn      PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
436672bbd8d24c6bd39734f465ce8d54904b6865de9bnjn   }
4367e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj}
4368e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj
4369696c55180aae375b48f7acc3f2aa87e13040c807sewardjPRE(sys_acct)
4370696c55180aae375b48f7acc3f2aa87e13040c807sewardj{
4371a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sys_acct ( %#lx(%s) )", ARG1,(char*)ARG1);
4372696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_REG_READ1(long, "acct", const char *, filename);
4373696c55180aae375b48f7acc3f2aa87e13040c807sewardj   PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
4374696c55180aae375b48f7acc3f2aa87e13040c807sewardj}
4375a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
4376a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_pause)
4377a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj{
4378a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   *flags |= SfMayBlock;
43790df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRINT("sys_pause ( )");
43800df495a33f39817e5cabbe94f3a5159f178d1a3anethercote   PRE_REG_READ0(long, "pause");
4381855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4382de4a1d01951937632098a6cda45859afa587a06fsewardj
4383a8d8e239876796bc194636b8bb4b3b3c86db8528sewardjPRE(sys_sigaltstack)
4384855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4385a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart   PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2);
4386b77dee6ad91370ba97e4aa8ba169d0b6cc18cce2nethercote   PRE_REG_READ2(int, "sigaltstack",
4387b77dee6ad91370ba97e4aa8ba169d0b6cc18cce2nethercote                 const vki_stack_t *, ss, vki_stack_t *, oss);
438822cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG1 != 0) {
438992098dbd2b54267f92c62f70ce4050071664b590tom      const vki_stack_t *ss = (vki_stack_t *)ARG1;
439092098dbd2b54267f92c62f70ce4050071664b590tom      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
439192098dbd2b54267f92c62f70ce4050071664b590tom      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
439292098dbd2b54267f92c62f70ce4050071664b590tom      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
4393855d93d2e9940890b28874520fa4c1677bf825e2jsgf   }
439422cfccb218c6975fa852a1135ddce342474b99d2njn   if (ARG2 != 0) {
439522cfccb218c6975fa852a1135ddce342474b99d2njn      PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
4396de4a1d01951937632098a6cda45859afa587a06fsewardj   }
4397de4a1d01951937632098a6cda45859afa587a06fsewardj
4398a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   SET_STATUS_from_SysRes(
4399a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj      VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
4400a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj                              (vki_stack_t*)ARG2)
4401a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   );
4402855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
440385a456f3640bbb4d4606f9464cd0832029e93c72nethercotePOST(sys_sigaltstack)
4404855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
4405a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj   vg_assert(SUCCESS);
440622cfccb218c6975fa852a1135ddce342474b99d2njn   if (RES == 0 && ARG2 != 0)
440722cfccb218c6975fa852a1135ddce342474b99d2njn      POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
4408855d93d2e9940890b28874520fa4c1677bf825e2jsgf}
4409de4a1d01951937632098a6cda45859afa587a06fsewardj
4410f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtomPRE(sys_sethostname)
4411f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom{
4412f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom   PRINT("sys_sethostname ( %#lx, %ld )", ARG1,ARG2);
4413f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom   PRE_REG_READ2(long, "sethostname", char *, name, int, len);
4414f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom   PRE_MEM_READ( "sethostname(name)", ARG1, ARG2 );
4415f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom}
4416f93bbd90a4e8b5c73270f230a5d7a5fadba540bdtom
4417e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj#undef PRE
4418e6d5e72a82ba7a2c5ae243bfc226a43e43884a81sewardj#undef POST
44192e93c50dc50235189661b70e3f27a4098d5cccccsewardj
44208b68b64759254d514d98328c496cbd88cde4c9a5njn#endif // defined(VGO_linux) || defined(VGO_darwin)
44218b68b64759254d514d98328c496cbd88cde4c9a5njn
4422de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
4423c1b0181cbd6f296401daa6ff0e6e14d3a8ab91a0njn/*--- end                                                          ---*/
4424de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
4425