1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Wrappers for generic Unix system calls                       ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                            syswrap-generic.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2000-2011 Julian Seward
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) || defined(VGO_darwin)
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h"     // VG_(di_notify_*)
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h"      // VG_(discard_translations)
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h"   // VG_(brk_base), VG_(brk_limit)
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h"
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_gdbserver.h"     // VG_(gdbserver)
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h"
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h"       // VG_(get_SP)
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h"
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h"
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h"
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h"    // For VG_(get_and_pp_StackTrace)()
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h"
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h"
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_ume.h"
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_types_n_macros.h"
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-generic.h"
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h"
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns True iff address range is something the client can
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   plausibly mess with: all of it is either already belongs to the
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   client or is free or a reservation. */
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   const Char *syscallname)
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ret;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size == 0)
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ret = VG_(am_is_valid_for_client_or_free_or_resvn)
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (start,size,VKI_PROT_NONE);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%s: test=%#lx-%#lx ret=%d\n",
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  syscallname, start, start+size-1, (Int)ret);
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ret && syscallname != NULL) {
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "to modify addresses %#lx-%#lx\n",
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               syscallname, start, start+size-1);
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_verbosity) > 1) {
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(client_signal_OK)(Int sigNo)
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* signal 0 is OK for kill */
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handy small function to help stop wrappers from segfaulting when
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   presented with bogus client addresses.  Is not used for generating
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   user-visible errors. */
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(safe_to_deref) ( void* start, SizeT size )
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_READ );
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Doing mmap, mremap
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   munmap, mprotect (and mremap??) work at the page level.  So addresses
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and lengths must be adjusted for this. */
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mash around start and length so that the area exactly covers
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an integral number of pages.  If we don't do that, memcheck's
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idea of addressible memory diverges from that of the
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   kernel's, which causes the leak detector to crash. */
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid page_align_addr_and_len( Addr* a, SizeT* len)
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr ra;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ra = VG_PGROUNDDN(*a);
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *len = VG_PGROUNDUP(*a + *len) - ra;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *a = ra;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void notify_core_of_mmap(Addr a, SizeT len, UInt prot,
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UInt flags, Int fd, Off64T offset)
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool d;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 'a' is the return value from a real kernel mmap, hence: */
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(a));
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* whereas len is whatever the syscall supplied.  So: */
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len = VG_PGROUNDUP(len);
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d)
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)( (Addr64)a, (ULong)len,
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "notify_core_of_mmap" );
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, ULong di_handle)
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
164f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   SizeT fourgig = (1ULL << 32);
165f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   SizeT guardpage = 10 * fourgig;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool rr, ww, xx;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 'a' is the return value from a real kernel mmap, hence: */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(a));
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* whereas len is whatever the syscall supplied.  So: */
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len = VG_PGROUNDUP(len);
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rr = toBool(prot & VKI_PROT_READ);
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ww = toBool(prot & VKI_PROT_WRITE);
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xx = toBool(prot & VKI_PROT_EXEC);
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
177f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#ifdef VGA_amd64
178f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   if (len >= fourgig + 2 * guardpage) {
179f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov     VG_(printf)("Valgrind: ignoring NaCl's mmap(84G)\n");
180f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov     return;
181f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   }
182f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#endif  // VGA_amd64
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle );
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* When a client mmap has been successfully done, this function must
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be called.  It notifies both aspacem and the tool of the new
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mapping.
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   JRS 2008-Aug-14: But notice this is *very* obscure.  The only place
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it is called from is POST(sys_io_setup).  In particular,
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(generic_PRE_sys_mmap), in m_syswrap, is the "normal case" handler for
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   client mmap.  But it doesn't call this function; instead it does the
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relevant notifications itself.  Here, we just pass di_handle=0 to
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notify_tool_of_mmap as we have no better information.  But really this
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   function should be done away with; problem is I don't understand what
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST(sys_io_setup) does or how it works.
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   [However, this function is used lots for Darwin, because
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ML_(generic_PRE_sys_mmap) cannot be used for Darwin.]
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    UInt flags, Int fd, Off64T offset )
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // XXX: unlike the other notify_core_and_tool* functions, this one doesn't
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // do anything with debug info (ie. it doesn't call VG_(di_notify_mmap)).
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Should it?  --njn
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notify_core_of_mmap(a, len, prot, flags, fd, offset);
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notify_tool_of_mmap(a, len, prot, 0/*di_handle*/);
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_munmap) ( Addr a, SizeT len )
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool d;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   page_align_addr_and_len(&a, &len);
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   d = VG_(am_notify_munmap)(a, len);
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( die_mem_munmap, a, len );
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(di_notify_munmap)( a, len );
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d)
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)( (Addr64)a, (ULong)len,
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "ML_(notify_core_and_tool_of_munmap)" );
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(notify_core_and_tool_of_mprotect) ( Addr a, SizeT len, Int prot )
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool rr = toBool(prot & VKI_PROT_READ);
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ww = toBool(prot & VKI_PROT_WRITE);
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool xx = toBool(prot & VKI_PROT_EXEC);
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool d;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   page_align_addr_and_len(&a, &len);
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   d = VG_(am_notify_mprotect)(a, len, prot);
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(di_notify_mprotect)( a, len, prot );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d)
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)( (Addr64)a, (ULong)len,
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "ML_(notify_core_and_tool_of_mprotect)" );
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_MREMAP
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expand (or shrink) an existing mapping, potentially moving it at
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same time (controlled by the MREMAP_MAYMOVE flag).  Nightmare.
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes do_mremap( Addr old_addr, SizeT old_len,
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Addr new_addr, SizeT new_len,
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  UWord flags, ThreadId tid )
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      ok, d;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* old_seg;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr      advised;
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      f_fixed   = toBool(flags & VKI_MREMAP_FIXED);
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("do_remap (old %#lx %ld) (new %#lx %ld) %s %s\n",
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  old_addr,old_len,new_addr,new_len,
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  flags & VKI_MREMAP_FIXED ? "FIXED" : "");
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(am_show_nsegments)(0, "do_remap: before");
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_IS_PAGE_ALIGNED(old_addr))
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_len = VG_PGROUNDUP(old_len);
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new_len = VG_PGROUNDUP(new_len);
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (new_len == 0)
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* kernel doesn't reject this, but we do. */
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (old_len == 0)
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* reject wraparounds */
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (old_addr + old_len < old_addr)
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      goto eINVAL;
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (f_fixed == True && new_addr + new_len < new_len)
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* kernel rejects all fixed, no-move requests (which are
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      meaningless). */
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (f_fixed == True && f_maymove == False)
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Stay away from non-client areas. */
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In all remaining cases, if the old range does not fall within a
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      single segment, fail. */
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_seg = VG_(am_find_nsegment)( old_addr );
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC)
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(old_len > 0);
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(new_len > 0);
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(old_len));
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(new_len));
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There are 3 remaining cases:
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * maymove == False
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        new space has to be at old address, so:
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - shrink    -> unmap end
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - same size -> do nothing
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - grow      -> if can grow in-place, do so, else fail
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * maymove == True, fixed == False
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        new space can be anywhere, so:
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - shrink    -> unmap end
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - same size -> do nothing
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - grow      -> if can grow in-place, do so, else
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           move to anywhere large enough, else fail
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * maymove == True, fixed == True
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        new space must be at new address, so:
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - if new address is not page aligned, fail
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - if new address range overlaps old one, fail
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - if new address range cannot be allocated, fail
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - else move to new address range with new size
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            - else fail
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (f_maymove == False) {
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new space has to be at old address */
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_len < old_len)
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto shrink_in_place;
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_len > old_len)
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto grow_in_place_or_fail;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto same_in_place;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (f_maymove == True && f_fixed == False) {
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new space can be anywhere */
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_len < old_len)
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto shrink_in_place;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_len > old_len)
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto grow_in_place_or_move_anywhere_or_fail;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto same_in_place;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (f_maymove == True && f_fixed == True) {
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new space can only be at the new address */
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_IS_PAGE_ALIGNED(new_addr))
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto eINVAL;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* no overlap */
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto eINVAL;
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (new_addr == 0)
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto eINVAL;
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VG_(am_get_advisory_client_simple) interprets zero to mean
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            non-fixed, which is not what we want */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ok || advised != new_addr)
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto eNOMEM;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ok = VG_(am_relocate_nooverlap_client)
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ( &d, old_addr, old_len, new_addr, new_len );
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok) {
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK( copy_mem_remap, old_addr, new_addr,
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   MIN_SIZET(old_len,new_len) );
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (new_len > old_len)
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      old_seg->hasR, old_seg->hasW, old_seg->hasX,
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      0/*di_handle*/ );
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK(die_mem_munmap, old_addr, old_len);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d) {
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return VG_(mk_SysRes_Success)( new_addr );
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eNOMEM;
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* end of the 3 cases */
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/ vg_assert(0);
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  grow_in_place_or_move_anywhere_or_fail:
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* try growing it in-place */
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr   needA = old_addr + old_len;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SSizeT needL = new_len - old_len;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(needL > 0);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (needA == 0)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VG_(am_get_advisory_client_simple) interprets zero to mean
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         non-fixed, which is not what we want */
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ok) {
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VG_(am_get_advisory_client_simple) (first arg == 0, meaning
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this-or-nothing) is too lenient, and may allow us to trash
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the next segment along.  So make very sure that the proposed
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new area really is free.  This is perhaps overly
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         conservative, but it fixes #129866. */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const* segLo = VG_(am_find_nsegment)( needA );
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const* segHi = VG_(am_find_nsegment)( needA + needL - 1 );
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (segLo == NULL || segHi == NULL
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || segLo != segHi || segLo->kind != SkFree)
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ok = False;
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ok && advised == needA) {
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL );
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok) {
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK( new_mem_mmap, needA, needL,
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 old_seg->hasR,
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 old_seg->hasW, old_seg->hasX,
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 0/*di_handle*/ );
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d)
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(discard_translations)( needA, needL, "do_remap(3)" );
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return VG_(mk_SysRes_Success)( old_addr );
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* that failed.  Look elsewhere. */
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ok) {
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool oldR = old_seg->hasR;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool oldW = old_seg->hasW;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool oldX = old_seg->hasX;
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* assert new area does not overlap old */
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(advised+new_len-1 < old_addr
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || advised > old_addr+old_len-1);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ok = VG_(am_relocate_nooverlap_client)
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ( &d, old_addr, old_len, advised, new_len );
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok) {
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK( copy_mem_remap, old_addr, advised,
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   MIN_SIZET(old_len,new_len) );
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (new_len > old_len)
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      oldR, oldW, oldX, 0/*di_handle*/ );
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK(die_mem_munmap, old_addr, old_len);
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d) {
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(discard_translations)( advised, new_len, "do_remap(5)" );
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return VG_(mk_SysRes_Success)( advised );
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   goto eNOMEM;
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/ vg_assert(0);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  grow_in_place_or_fail:
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr  needA = old_addr + old_len;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT needL = new_len - old_len;
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (needA == 0)
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eINVAL;
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VG_(am_get_advisory_client_simple) interprets zero to mean
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         non-fixed, which is not what we want */
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ok) {
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VG_(am_get_advisory_client_simple) (first arg == 0, meaning
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this-or-nothing) is too lenient, and may allow us to trash
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the next segment along.  So make very sure that the proposed
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new area really is free. */
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const* segLo = VG_(am_find_nsegment)( needA );
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const* segHi = VG_(am_find_nsegment)( needA + needL - 1 );
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (segLo == NULL || segHi == NULL
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || segLo != segHi || segLo->kind != SkFree)
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ok = False;
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ok || advised != needA)
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eNOMEM;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ok = VG_(am_extend_map_client)( &d, (NSegment*)old_seg, needL );
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ok)
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto eNOMEM;
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( new_mem_mmap, needA, needL,
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           old_seg->hasR, old_seg->hasW, old_seg->hasX,
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           0/*di_handle*/ );
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d)
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)( needA, needL, "do_remap(6)" );
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Success)( old_addr );
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/ vg_assert(0);
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  shrink_in_place:
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(sres))
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sres;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d)
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)( old_addr+new_len, old_len-new_len,
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "do_remap(7)" );
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Success)( old_addr );
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/ vg_assert(0);
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  same_in_place:
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Success)( old_addr );
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/ vg_assert(0);
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  eINVAL:
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Error)( VKI_EINVAL );
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  eNOMEM:
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Error)( VKI_ENOMEM );
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef MIN_SIZET
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* HAVE_MREMAP */
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   File-descriptor tracking
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* One of these is allocated for each open file descriptor.  */
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct OpenFd
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int fd;                        /* The file descriptor */
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char *pathname;                /* NULL if not a regular file or unknown */
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ExeContext *where;             /* NULL if inherited from parent */
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct OpenFd *next, *prev;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} OpenFd;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* List of allocated file descriptors. */
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OpenFd *allocated_fds = NULL;
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Count of open file descriptors. */
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int fd_count = 0;
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note the fact that a file descriptor was just closed. */
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid record_fd_close(Int fd)
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OpenFd *i = allocated_fds;
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (fd >= VG_(fd_hard_limit))
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;			/* Valgrind internal */
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while(i) {
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(i->fd == fd) {
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if(i->prev)
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i->prev->next = i->next;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            allocated_fds = i->next;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if(i->next)
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i->next->prev = i->prev;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if(i->pathname)
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(arena_free) (VG_AR_CORE, i->pathname);
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(arena_free) (VG_AR_CORE, i);
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fd_count--;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i = i->next;
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note the fact that a file descriptor was just opened.  If the
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tid is -1, this indicates an inherited fd.  If the pathname is NULL,
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this either indicates a non-standard file (i.e. a pipe or socket or
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   some such thing) or that we don't know the filename.  If the fd is
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   already open, then we're probably doing a dup2() to an existing fd,
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so just overwrite the existing one. */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname)
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OpenFd *i;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (fd >= VG_(fd_hard_limit))
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;			/* Valgrind internal */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check to see if this fd is already open. */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = allocated_fds;
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i) {
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->fd == fd) {
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i = i->next;
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Not already one: allocate an OpenFd */
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (i == NULL) {
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i = VG_(arena_malloc)(VG_AR_CORE, "syswrap.rfdowgn.1", sizeof(OpenFd));
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i->prev = NULL;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i->next = allocated_fds;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(allocated_fds) allocated_fds->prev = i;
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allocated_fds = i;
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd_count++;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->fd = fd;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->pathname = VG_(arena_strdup)(VG_AR_CORE, "syswrap.rfdowgn.2", pathname);
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Record opening of an fd, and find its name.
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_named)(ThreadId tid, Int fd)
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static HChar buf[VKI_PATH_MAX];
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* name;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name = buf;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name = NULL;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(record_fd_open_with_given_name)(tid, fd, name);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Record opening of a nameless fd.
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(record_fd_open_with_given_name)(tid, fd, NULL);
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *unix2name(struct vki_sockaddr_un *sa, UInt len, Char *name)
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(name, "<unknown>");
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(name, "%s", sa->sun_path);
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return name;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *inet2name(struct vki_sockaddr_in *sa, UInt len, Char *name)
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sa == NULL || len == 0) {
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(name, "<unknown>");
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt addr = VG_(ntohl)(sa->sin_addr.s_addr);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addr == 0) {
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(name, "<unbound>");
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(name, "%u.%u.%u.%u:%u",
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (addr>>24) & 0xFF, (addr>>16) & 0xFF,
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (addr>>8) & 0xFF, addr & 0xFF,
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      VG_(ntohs)(sa->sin_port));
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return name;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Try get some details about a socket.
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browngetsockdetails(Int fd)
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   union u {
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_sockaddr a;
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_sockaddr_in in;
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_sockaddr_un un;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } laddr;
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt llen;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   llen = sizeof(laddr);
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&laddr, 0, llen);
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(laddr.a.sa_family) {
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_AF_INET: {
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         static char lname[32];
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         static char pname[32];
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct vki_sockaddr_in paddr;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt plen = sizeof(struct vki_sockaddr_in);
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s\n", fd,
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         inet2name(&(laddr.in), llen, lname),
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         inet2name(&paddr, plen, pname));
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound\n",
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         fd, inet2name(&(laddr.in), llen, lname));
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_AF_UNIX: {
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         static char lname[256];
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s\n", fd,
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unix2name(&(laddr.un), llen, lname));
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:\n",
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      laddr.a.sa_family, fd);
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "Open socket %d:\n", fd);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dump out a summary, and a more detailed list, of open file descriptors. */
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(show_open_fds) (void)
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OpenFd *i = allocated_fds;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open at exit.\n", fd_count);
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i) {
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i->pathname) {
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd,
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      i->pathname);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int val;
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt len = sizeof(val);
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len)
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == -1) {
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_UserMsg, "Open file descriptor %d:\n", i->fd);
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            getsockdetails(i->fd);
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(i->where) {
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)(i->where);
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "\n");
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "   <inherited from parent>\n");
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "\n");
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i = i->next;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "\n");
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If /proc/self/fd doesn't exist (e.g. you've got a Linux kernel that doesn't
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   have /proc support compiled in, or a non-Linux kernel), then we need to
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   find out what file descriptors we inherited from our parent process the
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   hard way - by checking each fd in turn. */
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid init_preopened_fds_without_proc_self_fd(void)
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_rlimit lim;
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt count;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Hmm.  getrlimit() failed.  Now we're screwed, so just choose
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         an arbitrarily high number.  1024 happens to be the limit in
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the 2.4 Linux kernels. */
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      count = 1024;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      count = lim.rlim_cur;
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < count; i++)
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_named)(-1, i);
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialize the list of open file descriptors with the file descriptors
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we inherited from out parent process. */
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(init_preopened_fds)(void)
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DDD: should probably use HAVE_PROC here or similar, instead.
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ret;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_dirent d;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes f;
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(f)) {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      init_preopened_fds_without_proc_self_fd();
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while ((ret = VG_(getdents)(sr_Res(f), &d, sizeof(d))) != 0) {
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret == -1)
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto out;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char* s;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int fno = VG_(strtoll10)(d.d_name, &s);
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*s == '\0') {
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fno != sr_Res(f))
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (VG_(clo_track_fds))
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ML_(record_fd_open_named)(-1, fno);
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_DebugMsg,
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Warning: invalid file name in /proc/self/fd: %s\n",
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               d.d_name);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET);
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(close)(sr_Res(f));
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_preopened_fds_without_proc_self_fd();
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unknown OS
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *strdupcat ( HChar* cc, const Char *s1, const Char *s2, ArenaId aid )
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char *result = VG_(arena_malloc) ( aid, cc, len );
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strcpy) ( result, s1 );
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strcat) ( result, s2 );
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return result;
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_read_sendmsg ( ThreadId tid, Bool read,
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            Char *msg, Addr base, SizeT size )
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char *outmsg = strdupcat ( "di.syswrap.pmrs.1",
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "socketcall.sendmsg", msg, VG_AR_CORE );
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( outmsg, base, size );
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(arena_free) ( VG_AR_CORE, outmsg );
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_write_recvmsg ( ThreadId tid, Bool read,
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Char *msg, Addr base, SizeT size )
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char *outmsg = strdupcat ( "di.syswrap.pmwr.1",
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "socketcall.recvmsg", msg, VG_AR_CORE );
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( read )
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( outmsg, base, size );
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( outmsg, base, size );
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(arena_free) ( VG_AR_CORE, outmsg );
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid post_mem_write_recvmsg ( ThreadId tid, Bool read,
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Char *fieldName, Addr base, SizeT size )
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( !read )
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( base, size );
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid msghdr_foreachfield (
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ThreadId tid,
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct vki_msghdr *msg,
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        void (*foreach_func)( ThreadId, Bool, Char *, Addr, SizeT )
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     )
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( !msg )
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   foreach_func ( tid, False, "(msg)", (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( msg->msg_name )
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      foreach_func ( tid, False,
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "(msg.msg_name)",
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)msg->msg_name, msg->msg_namelen );
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( msg->msg_iov ) {
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_iovec *iov = msg->msg_iov;
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt i;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      foreach_func ( tid, True,
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "(msg.msg_iov)",
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         foreach_func ( tid, False,
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "(msg.msg_iov[i])",
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Addr)iov->iov_base, iov->iov_len );
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( msg->msg_control )
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      foreach_func ( tid, False,
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "(msg.msg_control)",
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)msg->msg_control, msg->msg_controllen );
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (cm) {
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cm->cmsg_level == VKI_SOL_SOCKET &&
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          cm->cmsg_type == VKI_SCM_RIGHTS ) {
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int *fds = (Int *) VKI_CMSG_DATA(cm);
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         / sizeof(int);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int i;
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < fdc; i++)
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if(VG_(clo_track_fds))
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // XXX: must we check the range on these fds with
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               //      ML_(fd_allowed)()?
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ML_(record_fd_open_named)(tid, fds[i]);
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cm = VKI_CMSG_NXTHDR(msg, cm);
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GrP kernel ignores sa_len (at least on Darwin); this checks the rest */
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pre_mem_read_sockaddr ( ThreadId tid,
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Char *description,
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             struct vki_sockaddr *sa, UInt salen )
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char *outmsg;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_sockaddr_un*  sun  = (struct vki_sockaddr_un *)sa;
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_sockaddr_in*  sin  = (struct vki_sockaddr_in *)sa;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NULL/zero-length sockaddrs are legal */
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( sa == NULL || salen == 0 ) return;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   outmsg = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.pmr_sockaddr.1",
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                VG_(strlen)( description ) + 30 );
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf) ( outmsg, description, "sa_family" );
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sa->sa_family) {
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_AF_UNIX:
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sun_path" );
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_RASCIIZ( outmsg, (Addr) sun->sun_path );
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // GrP fixme max of sun_len-2? what about nul char?
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_AF_INET:
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin_port" );
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) );
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin_addr" );
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) );
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_AF_INET6:
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin6_port" );
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg,
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) );
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin6_flowinfo" );
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg,
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) );
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin6_addr" );
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg,
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) );
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "sin6_scope_id" );
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg,
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) );
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf) ( outmsg, description, "" );
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( outmsg, (Addr) sa, salen );
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(arena_free) ( VG_AR_CORE, outmsg );
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dereference a pointer to a UInt. */
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* a_p = (UInt*)a;
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a_p == NULL)
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return *a_p;
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p,
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Char* buf_s, Char* buflen_s )
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(tdict).track_pre_mem_write) {
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (buflen_in > 0) {
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tdict).track_pre_mem_write(
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res,
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   Addr buf_p, Addr buflen_p, Char* s )
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!sr_isError(res) && VG_(tdict).track_post_mem_write) {
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt buflen_out = deref_UInt( tid, buflen_p, s);
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (buflen_out > 0 && buf_p != (Addr)NULL) {
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Data seg end, for brk()
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*   +--------+------------+
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     | anon   |    resvn   |
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     +--------+------------+
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ^     ^  ^
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     |     |  boundary is page aligned
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     |     VG_(brk_limit) -- no alignment constraint
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(brk_base) -- page aligned -- does not move
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Both the anon part and the reservation part are always at least
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     one page.
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the new data segment end to NEWBRK.  If this succeeds, return
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NEWBRK, else return the current data segment end. */
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr do_brk ( Addr newbrk )
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* aseg;
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* rseg;
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr newbrkP;
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT delta;
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ok;
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool debug = False;
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (debug)
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\ndo_brk: brk_base=%#lx brk_limit=%#lx newbrk=%#lx\n",
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  VG_(brk_base), VG_(brk_limit), newbrk);
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) show_segments("in_brk");
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newbrk < VG_(brk_base))
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Clearly impossible. */
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto bad;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newbrk >= VG_(brk_base) && newbrk < VG_(brk_limit)) {
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* shrinking the data segment.  Be lazy and don't munmap the
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         excess area. */
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const * seg = VG_(am_find_nsegment)(newbrk);
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (seg && seg->hasT)
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    "do_brk(shrink)" );
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Since we're being lazy and not unmapping pages, we have to
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zero out the area, so that if the area later comes back into
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         circulation, it will be filled with zeroes, as if it really
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         had been unmapped and later remapped.  Be a bit paranoid and
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         try hard to ensure we're not going to segfault by doing the
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         write - check both ends of the range are in the same segment
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and that segment is writable. */
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (seg) {
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* pre: newbrk < VG_(brk_limit)
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              => newbrk <= VG_(brk_limit)-1 */
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         NSegment const * seg2;
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(newbrk < VG_(brk_limit));
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         seg2 = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (seg2 && seg == seg2 && seg->hasW)
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)( (void*)newbrk, 0, VG_(brk_limit) - newbrk );
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(brk_limit) = newbrk;
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return newbrk;
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* otherwise we're expanding the brk segment. */
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(brk_limit) > VG_(brk_base))
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rseg = VG_(am_next_nsegment)( (NSegment*)aseg, True/*forwards*/ );
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These should be assured by setup_client_dataseg in m_main. */
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(aseg);
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(rseg);
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(aseg->kind == SkAnonC);
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(rseg->kind == SkResvn);
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(aseg->end+1 == rseg->start);
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(newbrk >= VG_(brk_base));
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newbrk <= rseg->start) {
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* still fits within the anon segment. */
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(brk_limit) = newbrk;
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return newbrk;
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newbrk > rseg->end+1 - VKI_PAGE_SIZE) {
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* request is too large -- the resvn would fall below 1 page,
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         which isn't allowed. */
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto bad;
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newbrkP = VG_PGROUNDUP(newbrk);
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(newbrkP > rseg->start && newbrkP <= rseg->end+1 - VKI_PAGE_SIZE);
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta = newbrkP - rseg->start;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(delta > 0);
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_IS_PAGE_ALIGNED(delta));
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ok = VG_(am_extend_into_adjacent_reservation_client)( (NSegment*)aseg, delta );
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ok) goto bad;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(brk_limit) = newbrk;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return newbrk;
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bad:
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(brk_limit);
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Vet file descriptors for sanity
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown> - what does the "Bool soft" parameter mean?
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(Tom Hughes, 3 Oct 05):
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWhether or not to consider a file descriptor invalid if it is above
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthe current soft limit.
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBasically if we are testing whether a newly created file descriptor is
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvalid (in a post handler) then we set soft to true, and if we are
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntesting whether a file descriptor that is about to be used (in a pre
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownhandler) is valid [viz, an already-existing fd] then we set it to false.
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThe point is that if the (virtual) soft limit is lowered then any
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownexisting descriptors can still be read/written/closed etc (so long as
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthey are below the valgrind reserved descriptors) but no new
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndescriptors can be created above the new soft limit.
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return true if we're allowed to use or create this fd */
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool isNewFd)
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool allowed = True;
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* hard limits always apply */
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (fd < 0 || fd >= VG_(fd_hard_limit))
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allowed = False;
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* hijacking the output fds is never allowed */
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd)
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allowed = False;
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if creating a new fd (rather than using an existing one), the
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      soft limit must also be observed */
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isNewFd && fd >= VG_(fd_soft_limit))
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allowed = False;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* this looks like it ought to be included, but causes problems: */
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (fd == 2 && VG_(debugLog_getLevel)() > 0)
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allowed = False;
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The difficulty is as follows: consider a program P which expects
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to be able to mess with (redirect) its own stderr (fd 2).
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Usually to deal with P we would issue command line flags to send
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      logging somewhere other than stderr, so as not to disrupt P.
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The problem is that -d unilaterally hijacks stderr with no
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      consultation with P.  And so, if this check is enabled, P will
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      work OK normally but fail if -d is issued.
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Basically -d is a hack and you take your chances when using it.
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      It's very useful for low level debugging -- particularly at
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      startup -- and having its presence change the behaviour of the
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      client is exactly what we don't want.  */
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* croak? */
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((!allowed) && VG_(showing_core_errors)() ) {
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "Warning: invalid file descriptor %d in syscall %s()\n",
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fd, syscallname);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fd == VG_(log_output_sink).fd && VG_(log_output_sink).fd >= 0)
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(message)(Vg_UserMsg,
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "   Use --log-fd=<number> to select an alternative log fd.\n");
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fd == VG_(xml_output_sink).fd && VG_(xml_output_sink).fd >= 0)
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(message)(Vg_UserMsg,
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "   Use --xml-fd=<number> to select an alternative XML "
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "output fd.\n");
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // DDD: consider always printing this stack trace, it's useful.
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Also consider also making this a proper core error, ie.
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // suppressible and all that.
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_verbosity) > 1) {
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return allowed;
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Deal with a bunch of socket-related syscalls
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_socketpair) ( ThreadId tid,
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg0, UWord arg1,
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg2, UWord arg3 )
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int socketpair(int d, int type, int protocol, int sv[2]); */
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "socketcall.socketpair(sv)",
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg3, 2*sizeof(int) );
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_socketpair) ( ThreadId tid,
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   SysRes res,
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   UWord arg0, UWord arg1,
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   UWord arg2, UWord arg3 )
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r = res;
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int fd1 = ((Int*)arg3)[0];
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int fd2 = ((Int*)arg3)[1];
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( arg3, 2*sizeof(int) );
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(fd1);
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(fd2);
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg3, 2*sizeof(int) );
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds)) {
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_nameless)(tid, fd1);
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_nameless)(tid, fd2);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r = res;
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) {
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(sr_Res(res));
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds))
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_nameless)(tid, sr_Res(res));
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_bind) ( ThreadId tid,
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord arg0, UWord arg1, UWord arg2 )
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int bind(int sockfd, struct sockaddr *my_addr,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               int addrlen); */
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pre_mem_read_sockaddr(
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tid, "socketcall.bind(my_addr.%s)",
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (struct vki_sockaddr *) arg1, arg2
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_accept) ( ThreadId tid,
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg0, UWord arg1, UWord arg2 )
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr addr_p     = arg1;
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr addrlen_p  = arg2;
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (addr_p != (Addr)NULL)
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(buf_and_len_pre_check) ( tid, addr_p, addrlen_p,
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "socketcall.accept(addr)",
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "socketcall.accept(addrlen_in)" );
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_accept) ( ThreadId tid,
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               SysRes res,
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1, UWord arg2 )
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r = res;
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) {
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(sr_Res(res));
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = VG_(mk_SysRes_Error)( VKI_EMFILE );
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr addr_p     = arg1;
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr addrlen_p  = arg2;
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (addr_p != (Addr)NULL)
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p,
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       "socketcall.accept(addrlen_out)" );
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds))
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ML_(record_fd_open_nameless)(tid, sr_Res(res));
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_sendto) ( ThreadId tid,
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg0, UWord arg1, UWord arg2,
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg3, UWord arg4, UWord arg5 )
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int sendto(int s, const void *msg, int len,
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int flags,
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const struct sockaddr *to, int tolen); */
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "socketcall.sendto(msg)",
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 arg1, /* msg */
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 arg2  /* len */ );
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pre_mem_read_sockaddr(
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tid, "socketcall.sendto(to.%s)",
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (struct vki_sockaddr *) arg4, arg5
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_send) ( ThreadId tid,
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord arg0, UWord arg1, UWord arg2 )
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int send(int s, const void *msg, size_t len, int flags); */
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "socketcall.send(msg)",
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg1, /* msg */
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg2  /* len */ );
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UWord arg0, UWord arg1, UWord arg2,
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UWord arg3, UWord arg4, UWord arg5 )
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   struct sockaddr *from, int *fromlen); */
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr buf_p      = arg1;
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  len        = arg2;
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr from_p     = arg4;
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr fromlen_p  = arg5;
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (from_p != (Addr)NULL)
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(buf_and_len_pre_check) ( tid, from_p, fromlen_p,
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "socketcall.recvfrom(from)",
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   "socketcall.recvfrom(fromlen_in)" );
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recvfrom) ( ThreadId tid,
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 SysRes res,
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 UWord arg0, UWord arg1, UWord arg2,
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 UWord arg3, UWord arg4, UWord arg5 )
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr buf_p      = arg1;
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  len        = arg2;
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr from_p     = arg4;
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr fromlen_p  = arg5;
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (from_p != (Addr)NULL)
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p,
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    "socketcall.recvfrom(fromlen_out)" );
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( buf_p, len );
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recv) ( ThreadId tid,
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord arg0, UWord arg1, UWord arg2 )
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int recv(int s, void *buf, int len, unsigned int flags); */
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* man 2 recv says:
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The  recv call is normally used only on a connected socket
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (see connect(2)) and is identical to recvfrom with a  NULL
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      from parameter.
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "socketcall.recv(buf)",
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg1, /* buf */
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg2  /* len */ );
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recv) ( ThreadId tid,
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UWord res,
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UWord arg0, UWord arg1, UWord arg2 )
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (res >= 0 && arg1 != 0) {
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg1, /* buf */
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      arg2  /* len */ );
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_connect) ( ThreadId tid,
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1, UWord arg2 )
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int connect(int sockfd,
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  struct sockaddr *serv_addr, int addrlen ); */
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pre_mem_read_sockaddr( tid,
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "socketcall.connect(serv_addr.%s)",
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (struct vki_sockaddr *) arg1, arg2);
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg0, UWord arg1, UWord arg2,
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg3, UWord arg4 )
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int setsockopt(int s, int level, int optname,
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     const void *optval, int optlen); */
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "socketcall.setsockopt(optval)",
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 arg3, /* optval */
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 arg4  /* optlen */ );
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_getsockname) ( ThreadId tid,
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   UWord arg0, UWord arg1, UWord arg2 )
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr name_p     = arg1;
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr namelen_p  = arg2;
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Nb: name_p cannot be NULL */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "socketcall.getsockname(name)",
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "socketcall.getsockname(namelen_in)" );
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_getsockname) ( ThreadId tid,
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    SysRes res,
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    UWord arg0, UWord arg1, UWord arg2 )
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr name_p     = arg1;
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr namelen_p  = arg2;
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "socketcall.getsockname(namelen_out)" );
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_getpeername) ( ThreadId tid,
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   UWord arg0, UWord arg1, UWord arg2 )
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr name_p     = arg1;
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr namelen_p  = arg2;
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Nb: name_p cannot be NULL */
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "socketcall.getpeername(name)",
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "socketcall.getpeername(namelen_in)" );
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_getpeername) ( ThreadId tid,
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    SysRes res,
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    UWord arg0, UWord arg1, UWord arg2 )
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr name_p     = arg1;
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr namelen_p  = arg2;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(!sr_isError(res)); /* guaranteed by caller */
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "socketcall.getpeername(namelen_out)" );
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_sendmsg) ( ThreadId tid,
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1 )
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_recvmsg) ( ThreadId tid,
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1 )
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int recvmsg(int s, struct msghdr *msg, int flags); */
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_recvmsg) ( ThreadId tid,
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                UWord arg0, UWord arg1 )
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   check_cmsg_for_fds( tid, msg );
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Deal with a bunch of IPC related syscalls
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semop) ( ThreadId tid,
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UWord arg0, UWord arg1, UWord arg2 )
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg0, UWord arg1,
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  UWord arg2, UWord arg3 )
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     struct timespec *timeout); */
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg3 != 0)
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_sem_count( Int semid )
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_semid_ds buf;
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   union vki_semun arg;
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (experimental) otherwise complains that the use in the return
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      statement below is uninitialised. */
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   buf.sem_nsems = 0;
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arg.buf = &buf;
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  ifdef __NR_semctl
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VKI_IPC_STAT, (UWord)&arg);
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(res))
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return buf.sem_nsems;
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_semctl) ( ThreadId tid,
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg0, UWord arg1,
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg2, UWord arg3 )
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int semctl(int semid, int semnum, int cmd, ...); */
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   union vki_semun arg = *(union vki_semun *)&arg3;
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nsems;
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (arg2 /* cmd */) {
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO)
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO:
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_INFO:
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO|VKI_IPC_64:
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_INFO|VKI_IPC_64:
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)arg.buf, sizeof(struct vki_seminfo) );
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT:
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT)
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_STAT:
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT|VKI_IPC_64:
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT)
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_STAT|VKI_IPC_64:
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_SET:
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_SET|VKI_IPC_64:
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_GETALL:
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_GETALL|VKI_IPC_64:
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nsems = get_sem_count( arg0 );
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)arg.array, sizeof(unsigned short) * nsems );
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SETALL:
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SETALL|VKI_IPC_64:
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nsems = get_sem_count( arg0 );
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Addr)arg.array, sizeof(unsigned short) * nsems );
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_semctl) ( ThreadId tid,
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord res,
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1,
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg2, UWord arg3 )
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   union vki_semun arg = *(union vki_semun *)&arg3;
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nsems;
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (arg2 /* cmd */) {
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO)
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO:
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_INFO:
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO|VKI_IPC_64:
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_INFO|VKI_IPC_64:
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT:
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SEM_STAT)
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_STAT:
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT|VKI_IPC_64:
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEM_STAT|VKI_IPC_64:
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_GETALL:
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_GETALL|VKI_IPC_64:
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nsems = get_sem_count( arg0 );
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_shm_size ( Int shmid )
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __NR_shmctl
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  ifdef VKI_IPC_64
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_shmid64_ds buf;
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    ifdef VGP_amd64_linux
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* See bug 222545 comment 7 */
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     VKI_IPC_STAT, (UWord)&buf);
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    else
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     VKI_IPC_STAT|VKI_IPC_64, (UWord)&buf);
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    endif
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else /* !def VKI_IPC_64 */
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_shmid_ds buf;
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif /* def VKI_IPC_64 */
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_shmid_ds buf;
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 VKI_IPC_STAT, 0, (UWord)&buf);
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(__res))
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return buf.shm_segsz;
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmat) ( ThreadId tid,
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UWord arg0, UWord arg1, UWord arg2 )
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  segmentSize = get_shm_size ( arg0 );
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord tmp;
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool  ok;
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg1 == 0) {
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* arm-linux only: work around the fact that
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(am_get_advisory_client_simple) produces something that is
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VKI_PAGE_SIZE aligned, whereas what we want is something
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VKI_SHMLBA aligned, and VKI_SHMLBA >= VKI_PAGE_SIZE.  Hence
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         increase the request size by VKI_SHMLBA - VKI_PAGE_SIZE and
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then round the result up to the next VKI_SHMLBA boundary.
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         See bug 222545 comment 15.  So far, arm-linux is the only
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         platform where this is known to be necessary. */
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VKI_SHMLBA > VKI_PAGE_SIZE) {
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         segmentSize += VKI_SHMLBA - VKI_PAGE_SIZE;
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok) {
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VKI_SHMLBA > VKI_PAGE_SIZE) {
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg1 = VG_ROUNDUP(tmp, VKI_SHMLBA);
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg1 = tmp;
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg1 = 0;
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return arg1;
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmat) ( ThreadId tid,
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord res,
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg0, UWord arg1, UWord arg2 )
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   UInt segmentSize = VG_PGROUNDUP(get_shm_size(arg0));
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( segmentSize > 0 ) {
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool d;
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (arg2 & VKI_SHM_RDONLY)
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         prot &= ~VKI_PROT_WRITE;
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* It isn't exactly correct to pass 0 for the fd and offset
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here.  The kernel seems to think the corresponding section
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         does have dev/ino numbers:
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         04e52000-04ec8000 rw-s 00000000 00:06 1966090  /SYSV00000000 (deleted)
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         However there is no obvious way to find them.  In order to
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cope with the discrepancy, aspacem's sync checker omits the
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dev/ino correspondence check in cases where V does not know
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the dev/ino. */
1802f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      d = VG_(am_notify_client_shmat)( res, segmentSize, prot );
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we don't distinguish whether it's read-only or
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * read-write -- it doesn't matter really. */
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False,
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              0/*di_handle*/ );
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d)
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(discard_translations)( (Addr64)res,
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    (ULong)VG_PGROUNDUP(segmentSize),
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    "ML_(generic_POST_sys_shmat)" );
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int shmdt(const void *shmaddr); */
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* s = VG_(am_find_nsegment)(arg0);
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s != NULL) {
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr  s_start = s->start;
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT s_len   = s->end+1 - s->start;
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool  d;
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(s->kind == SkShmC);
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(s->start == arg0);
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d = VG_(am_notify_munmap)(s_start, s_len);
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      s = NULL; /* s is now invalid */
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( die_mem_munmap, s_start, s_len );
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d)
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(discard_translations)( (Addr64)s_start,
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    (ULong)s_len,
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    "ML_(generic_POST_sys_shmdt)" );
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ */
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_shmctl) ( ThreadId tid,
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UWord arg0, UWord arg1, UWord arg2 )
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (arg1 /* cmd */) {
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO)
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO:
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arg2, sizeof(struct vki_shminfo) );
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO|VKI_IPC_64:
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arg2, sizeof(struct vki_shminfo64) );
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_INFO)
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_INFO:
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_INFO|VKI_IPC_64:
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arg2, sizeof(struct vki_shm_info) );
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT:
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_STAT)
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_STAT:
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arg2, sizeof(struct vki_shmid_ds) );
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT|VKI_IPC_64:
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_STAT|VKI_IPC_64:
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     arg2, sizeof(struct vki_shmid64_ds) );
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_SET:
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    arg2, sizeof(struct vki_shmid_ds) );
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_SET|VKI_IPC_64:
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    arg2, sizeof(struct vki_shmid64_ds) );
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_POST_sys_shmctl) ( ThreadId tid,
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord res,
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               UWord arg0, UWord arg1, UWord arg2 )
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (arg1 /* cmd */) {
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_INFO)
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO:
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_INFO|VKI_IPC_64:
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_INFO)
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_INFO:
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_INFO|VKI_IPC_64:
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT:
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_SHM_STAT)
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_STAT:
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_IPC_64)
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_IPC_STAT|VKI_IPC_64:
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHM_STAT|VKI_IPC_64:
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generic handler for mmap
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Although mmap is specified by POSIX and the argument are generally
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * consistent across platforms the precise details of the low level
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * argument passing conventions differ. For example:
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On x86-linux there is mmap (aka old_mmap) which takes the
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   arguments in a memory block and the offset in bytes; and
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   mmap2 (aka sys_mmap2) which takes the arguments in the normal
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   way and the offset in pages.
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   arguments in the normal way and the offset in bytes; and
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   mmap2 (aka sys_mmap2) which takes the arguments in the normal
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   way and the offset in pages.
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - On amd64-linux everything is simple and there is just the one
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   call, mmap (aka sys_mmap)  which takes the arguments in the
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   normal way and the offset in bytes.
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * - On s390x-linux there is mmap (aka old_mmap) which takes the
1972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   arguments in a memory block and the offset in bytes. mmap2
1973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   is also available (but not exported via unistd.h) with
1974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   arguments in a memory block and the offset in pages.
1975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * To cope with all this we provide a generic handler function here
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and then each platform implements one or more system call handlers
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * which call this generic routine after extracting and normalising
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the arguments.
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownML_(generic_PRE_sys_mmap) ( ThreadId tid,
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord arg1, UWord arg2, UWord arg3,
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord arg4, UWord arg5, Off64T arg6 )
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr       advised;
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes     sres;
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MapRequest mreq;
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       mreq_ok;
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin)
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: we can't use this on Darwin, it has races:
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * needs to RETRY if advisory succeeds but map fails
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   (could have been some other thread in a nonblocking call)
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * needs to not use fixed-position mmap() on Darwin
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   (mmap will cheerfully smash whatever's already there, which might
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   be a new mapping from some other thread in a nonblocking call)
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(core_panic)("can't use ML_(generic_PRE_sys_mmap) on Darwin");
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg2 == 0) {
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shall be established. */
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_IS_PAGE_ALIGNED(arg1)) {
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* zap any misaligned addresses. */
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to fail.   Here, we catch them all. */
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_IS_PAGE_ALIGNED(arg6)) {
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* zap any misaligned offsets. */
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SuSV3 says: The off argument is constrained to be aligned and
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sized according to the value returned by sysconf() when
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Figure out what kind of allocation constraints there are
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (fixed/hint/any), and ask aspacem what we should do. */
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mreq.start = arg1;
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mreq.len   = arg2;
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg4 & VKI_MAP_FIXED) {
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.rkind = MFixed;
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg1 != 0) {
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.rkind = MHint;
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.rkind = MAny;
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Enquire ... */
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!mreq_ok) {
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Our request was bounced, so we'd better fail. */
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Otherwise we're OK (so far).  Install aspacem's choice of
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      address, and let the mmap go through.  */
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    arg4 | VKI_MAP_FIXED,
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    arg5, arg6);
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A refinement: it may be that the kernel refused aspacem's choice
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of address.  If we were originally asked for a hinted mapping,
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      there is still a last chance: try again at any address.
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Hence: */
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mreq.rkind == MHint && sr_isError(sres)) {
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.start = 0;
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.len   = arg2;
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mreq.rkind = MAny;
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mreq_ok) {
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Our request was bounced, so we'd better fail. */
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return VG_(mk_SysRes_Error)( VKI_EINVAL );
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and try again with the kernel */
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       arg4 | VKI_MAP_FIXED,
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       arg5, arg6);
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!sr_isError(sres)) {
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong di_handle;
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Notify aspacem. */
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      notify_core_of_mmap(
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Addr)sr_Res(sres), /* addr kernel actually assigned */
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg2, /* length */
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg3, /* prot */
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg4, /* the original flags value */
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg5, /* fd */
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg6  /* offset */
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Load symbols? */
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres),
2081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       False/*allow_SkFileV*/, (Int)arg5 );
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Notify the tool. */
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      notify_tool_of_mmap(
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Addr)sr_Res(sres), /* addr kernel actually assigned */
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg2, /* length */
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg3, /* prot */
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di_handle /* so the tool can refer to the read debuginfo later,
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      if it wants. */
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Stay sane */
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED))
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(sr_Res(sres) == arg1);
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sres;
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The Main Entertainment ... syscall wrappers
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note: the PRE() and POST() wrappers are for the actual functions
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   implementing the system calls in the OS kernel.  These mostly have
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   names like sys_write();  a few have names like old_mmap().  See the
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   comment for ML_(syscall_table)[] for important info about the __NR_foo
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   constants and their relationship to the sys_foo() functions.
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Some notes about names used for syscalls and args:
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ambiguity.
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - For error messages, we generally use a somewhat generic name
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for the syscall (eg. "write" rather than "sys_write").  This should be
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     good enough for the average user to understand what is happening,
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     without confusing them with names like "sys_write".
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Also, for error messages the arg names are mostly taken from the man
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pages (even though many of those man pages are really for glibc
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     functions of the same name), rather than from the OS kernel source,
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for the same reason -- a user presented with a "bogus foo(bar)" arg
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     will most likely look at the "foo" man page to see which is the "bar"
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     arg.
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that we use our own vki_* types.  The one exception is in
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READn calls, where pointer types haven't been changed, because
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   they don't need to be -- eg. for "foo*" to be used, the type foo need not
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be visible.
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XXX: some of these are arch-specific, and should be factored out.
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PRE(name)      DEFN_PRE_TEMPLATE(generic, name)
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define POST(name)     DEFN_POST_TEMPLATE(generic, name)
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Macros to support 64-bit syscall args split into two 32 bit values
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VG_LITTLEENDIAN)
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64(lo,hi)   ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_FIRST(name) name##_low
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_SECOND(name) name##_high
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VG_BIGENDIAN)
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64(hi,lo)   ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_FIRST(name) name##_high
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MERGE64_SECOND(name) name##_low
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error Unknown endianness
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_exit)
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* tst;
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* simple; just make this thread exit */
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("exit( %ld )", ARG1);
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(void, "exit", int, status);
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set the thread's status to be exiting, then claim that the
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      syscall succeeded. */
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->exitreason = VgSrc_ExitThread;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->os_state.exitcode = ARG1;
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_Success(0);
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ni_syscall)
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("unimplemented (by the kernel) syscall: %s! (ni_syscall)\n",
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_SYSNUM_STRING(SYSNO));
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "ni_syscall");
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_Failure( VKI_ENOSYS );
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_iopl)
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_iopl ( %ld )", ARG1);
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "iopl", unsigned long, level);
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fsync)
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fsync ( %ld )", ARG1);
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "fsync", unsigned int, fd);
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fdatasync)
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fdatasync ( %ld )", ARG1);
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_msync)
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_msync ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "msync",
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, start, vki_size_t, length, int, flags);
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// versions of LiS (Linux Streams).  They are not part of the kernel.
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Therefore, we have to provide this type ourself, rather than getting it
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// from the kernel sources.
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct vki_pmsg_strbuf {
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int     maxlen;         /* no. of bytes in buffer */
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int     len;            /* no. of bytes returned */
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_caddr_t buf;        /* pointer to data */
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpmsg)
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *ctrl;
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *data;
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ5(int, "getpmsg",
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int *, bandp, int *, flagsp);
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data = (struct vki_pmsg_strbuf *)ARG3;
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctrl && ctrl->maxlen > 0)
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (data && data->maxlen > 0)
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG4)
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG5)
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getpmsg)
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *ctrl;
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *data;
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data = (struct vki_pmsg_strbuf *)ARG3;
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0 && ctrl && ctrl->len > 0) {
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0 && data && data->len > 0) {
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( (Addr)data->buf, data->len);
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_putpmsg)
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *ctrl;
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pmsg_strbuf *data;
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5);
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ5(int, "putpmsg",
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, band, int, flags);
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctrl = (struct vki_pmsg_strbuf *)ARG2;
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   data = (struct vki_pmsg_strbuf *)ARG3;
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ctrl && ctrl->len > 0)
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (data && data->len > 0)
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getitimer)
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2);
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_timeval_WRITE( "getitimer(&value->it_value)",    &(value->it_value));
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getitimer)
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL) {
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_timeval_WRITE( &(value->it_interval) );
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_timeval_WRITE( &(value->it_value) );
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setitimer)
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setitimer ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "setitimer",
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, which,
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct itimerval *, value, struct itimerval *, ovalue);
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL) {
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "setitimer(&value->it_interval)",
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         &(value->it_interval));
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "setitimer(&value->it_value)",
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         &(value->it_value));
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 != (Addr)NULL) {
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         &(ovalue->it_interval));
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         &(ovalue->it_value));
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_setitimer)
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 != (Addr)NULL) {
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_timeval_WRITE( &(ovalue->it_interval) );
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_timeval_WRITE( &(ovalue->it_value) );
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chroot)
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_chroot ( %#lx )", ARG1);
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "chroot", const char *, path);
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_madvise)
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_madvise ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "madvise",
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, start, vki_size_t, length, int, advice);
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_MREMAP
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mremap)
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: this is different to the glibc version described in the man pages,
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // which lacks the fifth 'new_address' argument.
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG4 & VKI_MREMAP_FIXED) {
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx, %#lx )",
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG1, (ULong)ARG2, ARG3, ARG4, ARG5);
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_REG_READ5(unsigned long, "mremap",
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned long, old_addr, unsigned long, old_size,
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned long, new_size, unsigned long, flags,
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned long, new_addr);
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx )",
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG1, (ULong)ARG2, ARG3, ARG4);
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_REG_READ4(unsigned long, "mremap",
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned long, old_addr, unsigned long, old_size,
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned long, new_size, unsigned long, flags);
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes(
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* HAVE_MREMAP */
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_nice)
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_nice ( %ld )", ARG1);
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "nice", int, inc);
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mlock)
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_munlock)
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_munlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mlockall)
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mlockall ( %lx )", ARG1);
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "mlockall", int, flags);
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setpriority)
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setpriority ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpriority)
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getpriority ( %ld, %ld )", ARG1, ARG2);
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getpriority", int, which, int, who);
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pwrite64)
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ5(ssize_t, "pwrite64",
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, const char *, buf, vki_size_t, count,
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif VG_WORDSIZE == 8
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ4(ssize_t, "pwrite64",
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, const char *, buf, vki_size_t, count,
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Word, offset);
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unexpected word size
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_sync)
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_sync ( )");
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "sync");
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstatfs)
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fstatfs ( %ld, %#lx )",ARG1,ARG2);
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "fstatfs",
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, struct statfs *, buf);
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstatfs)
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstatfs64)
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fstatfs64 ( %ld, %llu, %#lx )",ARG1,(ULong)ARG2,ARG3);
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "fstatfs64",
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstatfs64)
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG3, ARG2 );
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getsid)
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getsid ( %ld )", ARG1);
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pread64)
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ5(ssize_t, "pread64",
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, char *, buf, vki_size_t, count,
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif VG_WORDSIZE == 8
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ4(ssize_t, "pread64",
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, char *, buf, vki_size_t, count,
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Word, offset);
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unexpected word size
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_pread64)
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES > 0) {
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES );
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mknod)
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mknod ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char*)ARG1, ARG2, ARG3 );
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "mknod",
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, pathname, int, mode, unsigned, dev);
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_flock)
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_flock ( %ld, %ld )", ARG1, ARG2 );
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Pre_read a char** argument.
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr a_deref;
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr* a_p = (Addr*)a;
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a_deref = *a_p;
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == a_deref)
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_RASCIIZ( s2, a_deref );
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a += sizeof(char*);
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool i_am_the_only_thread ( void )
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int c = VG_(count_living_threads)();
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(c >= 1); /* stay sane */
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return c == 1;
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Wait until all other threads disappear. */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(reap_threads)(ThreadId self)
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (!i_am_the_only_thread()) {
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Let other thread(s) run */
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(vg_yield)();
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(poll_signals)(self);
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(i_am_the_only_thread());
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// but it seems to work nonetheless...
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_execve)
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char*        path = NULL;       /* path to executable */
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char**       envp = NULL;
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char**       argv = NULL;
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char**       arg2copy;
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char*        launcher_basename = NULL;
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* tst;
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int          i, j, tot_args;
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes       res;
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool         setuid_allowed, trace_this_child;
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (char*)ARG1, ARG2, ARG3);
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(vki_off_t, "execve",
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 char *, filename, char **, argv, char **, envp);
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0)
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 != 0)
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(tid));
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Erk.  If the exec fails, then the following will have made a
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mess of things which makes it hard for us to continue.  The
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      right thing to do is piece everything together again in
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST(execve), but that's close to impossible.  Instead, we make
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an effort to check that the execve will work before actually
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doing it. */
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check that the name at least begins in client-accessible storage. */
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == 0 /* obviously bogus */
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       || !VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EFAULT );
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // debug-only printing
2571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0) {
2572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1);
2573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (ARG2) {
2574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf)("ARG2 = ");
2575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Int q;
2576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HChar** vec = (HChar**)ARG2;
2577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         for (q = 0; vec[q]; q++)
2578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VG_(printf)("%p(%s) ", vec[q], vec[q]);
2579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf)("\n");
2580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
2581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf)("ARG2 = null\n");
2582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Decide whether or not we want to follow along
2586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   { // Make 'child_argv' be a pointer to the child's arg vector
2587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     // (skipping the exe name)
2588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     HChar** child_argv = (HChar**)ARG2;
2589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if (child_argv && child_argv[0] == NULL)
2590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        child_argv = NULL;
2591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv );
2592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Do the important checks:  it is a file, is executable, permissions are
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // ok, etc.  We allow setuid executables to run only in the case when
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // we are not simulating them, that is, they to be run natively.
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setuid_allowed = trace_this_child  ? False  : True;
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(pre_exec_check)((const Char*)ARG1, NULL, setuid_allowed);
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(res)) {
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( sr_Err(res) );
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If we're tracing the child, and the launcher name looks bogus
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (possibly because launcher.c couldn't figure it out, see
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      comments therein) then we have no option but to fail. */
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_this_child
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (VG_(name_of_launcher) == NULL
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || VG_(name_of_launcher)[0] != '/')) {
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* After this point, we can't recover if the execve fails. */
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Terminate gdbserver if it is active.
2619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(clo_vgdb)  != Vg_VgdbNo) {
2620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // If the child will not be traced, we need to terminate gdbserver
2621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // to cleanup the gdbserver resources (e.g. the FIFO files).
2622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // If child will be traced, we also terminate gdbserver: the new
2623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // Valgrind will start a fresh gdbserver after exec.
2624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(gdbserver) (0);
2625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Resistance is futile.  Nuke all other threads.  POSIX mandates
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this. (Really, nuke them all, since the new process will make
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      its own new thread.) */
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread );
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(reap_threads)(tid);
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up the child's exe path.
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_this_child) {
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // We want to exec the launcher.  Get its pre-remembered path.
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      path = VG_(name_of_launcher);
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // VG_(name_of_launcher) should have been acquired by m_main at
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // startup.
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(path);
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      launcher_basename = VG_(strrchr)(path, '/');
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (launcher_basename == NULL || launcher_basename[1] == 0) {
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         launcher_basename = path;  // hmm, tres dubious
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         launcher_basename++;
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      path = (Char*)ARG1;
2652f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      if (VG_(clo_xml)) {
2653f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov        VG_(printf_xml)("\n<execv/>\n\n</valgrindoutput>\n\n");
2654f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      } else {
2655f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov        VG_(umsg)("execv called - the tool will now quit\n");
2656f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      }
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up the child's environment.
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Remove the valgrind-specific stuff from the environment so the
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This is done unconditionally, since if we are tracing the child,
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the child valgrind will set up the appropriate client environment.
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: we make a copy of the environment before trying to mangle it
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // as it might be in read-only memory (this was bug #101881).
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Then, if tracing the child, set VALGRIND_LIB for it.
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 == 0) {
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      envp = NULL;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      envp = VG_(env_clone)( (Char**)ARG3 );
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (envp == NULL) goto hosed;
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(env_remove_valgrind_env_stuff)( envp );
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (trace_this_child) {
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Set VALGRIND_LIB in ARG3 (the environment)
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up the child's args.  If not tracing it, they are
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // simply ARG2.  Otherwise, they are
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // except that the first VG_(args_for_valgrind_noexecpass) args
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // are omitted.
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!trace_this_child) {
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = (Char**)ARG2;
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( VG_(args_for_valgrind) );
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( VG_(args_for_valgrind_noexecpass)
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* how many args in total will there be? */
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // launcher basename
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tot_args = 1;
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // V's args
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tot_args -= VG_(args_for_valgrind_noexecpass);
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // name of client exe
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tot_args++;
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // args for client exe, skipping [0]
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg2copy = (Char**)ARG2;
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (arg2copy && arg2copy[0]) {
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 1; arg2copy[i]; i++)
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tot_args++;
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // allocate
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (tot_args+1) * sizeof(HChar*) );
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (argv == 0) goto hosed;
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // copy
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      j = 0;
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv[j++] = launcher_basename;
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (i < VG_(args_for_valgrind_noexecpass))
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv[j++] = (Char*)ARG1;
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (arg2copy && arg2copy[0])
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 1; arg2copy[i]; i++)
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv[j++] = arg2copy[i];
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv[j++] = NULL;
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // check
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(j == tot_args+1);
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* restore the DATA rlimit for the child */
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Set the signal state up for exec.
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      We need to set the real signal state to make sure the exec'd
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      process gets SIG_IGN properly.
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Also set our real sigmask to match the client's sigmask so that
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the exec'd child will get the right mask.  First we need to
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      clear out any pending signals so they they don't get delivered,
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which would confuse things.
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XXX This is a bug - the signals should remain pending, and be
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delivered to the new process after exec.  There's also a
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      race-condition, since if someone delivers us a signal between
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the sigprocmask and the execve, we'll still get the signal. Oh
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      well.
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vki_sigset_t allsigs;
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vki_siginfo_t info;
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* What this loop does: it queries SCSS (the signal state that
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the client _thinks_ the kernel is in) by calling
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(do_sys_sigaction), and modifies the real kernel signal
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         state accordingly. */
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < VG_(max_signal); i++) {
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vki_sigaction_fromK_t sa_f;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vki_sigaction_toK_t   sa_t;
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(do_sys_sigaction)(i, NULL, &sa_f);
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sa_t.ksa_handler == VKI_SIG_IGN)
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(sigaction)(i, &sa_t, NULL);
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sa_t.ksa_handler = VKI_SIG_DFL;
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(sigaction)(i, &sa_t, NULL);
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sigfillset)(&allsigs);
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ;
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char **cpp;
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("exec: %s\n", path);
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (cpp = argv; cpp && *cpp; cpp++)
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("argv: %s\n", *cpp);
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0)
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (cpp = envp; cpp && *cpp; cpp++)
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("env: %s\n", *cpp);
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes(
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If we got here, then the execve failed.  We've already made way
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      too much of a mess to continue, so we have to abort. */
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  hosed:
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(FAILURE);
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n",
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ARG1, (char*)ARG1, ARG2, ARG3, ERR);
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "execve() failing, so I'm dying.\n");
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "or work out how to recover.\n");
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(exit)(101);
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_access)
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_access ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_alarm)
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_alarm ( %ld )", ARG1);
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_brk)
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr brk_limit = VG_(brk_limit);
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr brk_new;
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* libc   says: int   brk(void *end_data_segment);
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      kernel says: void* brk(void* end_data_segment);  (more or less)
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      libc returns 0 on success, and -1 (and sets errno) on failure.
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Nb: if you ask to shrink the dataseg end below what it
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      currently is, that always succeeds, even if the dataseg end
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doesn't actually change (eg. brk(0)).  Unless it seg faults.
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Kernel returns the new dataseg end.  If the brk() failed, this
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      will be unchanged from the old one.  That's why calling (kernel)
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      brk(0) gives the current dataseg end (libc brk() just returns
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero in that case).
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Both will seg fault if you shrink it back into a text segment.
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_brk ( %#lx )", ARG1);
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   brk_new = do_brk(ARG1);
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_Success( brk_new );
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (brk_new == ARG1) {
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* brk() succeeded */
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (brk_new < brk_limit) {
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* successfully shrunk the data segment. */
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK( die_mem_brk, (Addr)ARG1,
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   brk_limit-ARG1 );
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (brk_new > brk_limit) {
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* successfully grew the data segment */
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_TRACK( new_mem_brk, brk_limit,
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ARG1-brk_limit, tid );
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* brk() failed */
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(brk_limit == brk_new);
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chdir)
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1);
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "chdir", const char *, path);
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chmod)
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_chmod ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_chown)
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "chown",
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_lchown)
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "lchown",
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_close)
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_close ( %ld )", ARG1);
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "close", unsigned int, fd);
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Detect and negate attempts by the client to close Valgrind's log fd */
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( (!ML_(fd_allowed)(ARG1, "close", tid, False))
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* If doing -d style logging (which is to fd=2), don't
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           allow that to be closed either. */
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) )
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_close)
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_track_fds)) record_fd_close(ARG1);
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_dup)
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_dup ( %ld )", ARG1);
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "dup", unsigned int, oldfd);
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_dup)
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(RES);
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EMFILE );
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds))
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_named)(tid, RES);
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_dup2)
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_dup2 ( %ld, %ld )", ARG1,ARG2);
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_dup2)
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_track_fds))
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(record_fd_open_named)(tid, RES);
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchdir)
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fchdir ( %ld )", ARG1);
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "fchdir", unsigned int, fd);
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchown)
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fchown ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "fchown",
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fchmod)
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fchmod ( %ld, %ld )", ARG1,ARG2);
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newfstat)
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_newfstat ( %ld, %#lx )", ARG1,ARG2);
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newfstat)
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vki_sigset_t fork_saved_mask;
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In Linux, the sys_fork() function varies across architectures, but we
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ignore the various args it gets, and so it looks arch-neutral.  Hmm.
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fork)
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool is_child;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int child_pid;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_sigset_t mask;
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fork ( )");
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "fork");
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Block all signals during fork, so that we can fix things up in
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the child without being interrupted. */
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigfillset)(&mask);
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!SUCCESS) return;
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // RES is 0 for child, non-0 (the child's PID) for parent.
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is_child = ( RES == 0 ? True : False );
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child_pid = ( is_child ? -1 : RES );
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // RES is the child's pid.  RESHI is 1 for child, 0 for parent.
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is_child = RESHI;
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child_pid = RES;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unknown OS
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(do_atfork_pre)(tid);
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (is_child) {
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(do_atfork_child)(tid);
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* restore signal mask */
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If --child-silent-after-fork=yes was specified, set the
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         output file descriptors to 'impossible' values.  This is
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         noticed by send_bytes_to_logging_sink in m_libcprint.c, which
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         duly stops writing any further output. */
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_child_silent_after_fork)) {
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!VG_(log_output_sink).is_socket)
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(log_output_sink).fd = -1;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!VG_(xml_output_sink).is_socket)
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(xml_output_sink).fd = -1;
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(do_atfork_parent)(tid);
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("   fork: process %d created child %d\n", VG_(getpid)(), child_pid);
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* restore signal mask */
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ftruncate)
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_ftruncate ( %ld, %ld )", ARG1,ARG2);
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_truncate)
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_truncate ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "truncate",
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path, unsigned long, length);
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ftruncate64)
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, MERGE64(ARG2,ARG3));
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "ftruncate64",
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd,
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, (Long)ARG2);
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "ftruncate64",
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int,fd, UWord,length);
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_truncate64)
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if VG_WORDSIZE == 4
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)MERGE64(ARG2, ARG3));
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "truncate64",
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path,
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)ARG2);
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "truncate64",
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *,path, UWord,length);
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getdents)
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getdents ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "getdents",
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, struct linux_dirent *, dirp,
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, count);
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getdents)
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES > 0)
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES );
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getdents64)
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getdents64 ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "getdents64",
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, struct linux_dirent64 *, dirp,
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, count);
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getdents64)
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES > 0)
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES );
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getgroups)
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getgroups ( %ld, %#lx )", ARG1, ARG2);
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 > 0)
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getgroups)
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 > 0 && RES > 0)
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getcwd)
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Comment from linux/fs/dcache.c:
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   NOTE! The user-level library version returns a character pointer.
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   The kernel system call just returns the length of the buffer filled
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   (which includes the ending '\0' character), or a negative error
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   value.
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Is this Linux-specific?  If so it should be moved to syswrap-linux.c.
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getcwd ( %#lx, %llu )", ARG1,(ULong)ARG2);
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getcwd)
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES != (Addr)NULL)
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG1, RES );
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_geteuid)
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_geteuid ( )");
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "geteuid");
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getegid)
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getegid ( )");
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getegid");
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getgid)
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getgid ( )");
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getgid");
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpid)
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getpid ()");
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getpid");
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpgid)
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getpgid ( %ld )", ARG1);
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getpgrp)
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getpgrp ()");
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getpgrp");
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getppid)
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getppid ()");
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getppid");
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef _RLIMIT_POSIX_FLAG
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Darwin will sometimes set _RLIMIT_POSIX_FLAG on getrlimit calls.
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Unset it here to make the switch case below work correctly.
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a1 &= ~_RLIMIT_POSIX_FLAG;
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (a1) {
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_RLIMIT_NOFILE:
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_RLIMIT_DATA:
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_RLIMIT_STACK:
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_old_getrlimit)
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_old_getrlimit ( %ld, %#lx )", ARG1,ARG2);
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "old_getrlimit",
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, resource, struct rlimit *, rlim);
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_old_getrlimit)
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   common_post_getrlimit(tid, ARG1, ARG2);
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getrlimit)
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getrlimit ( %ld, %#lx )", ARG1,ARG2);
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getrlimit",
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, resource, struct rlimit *, rlim);
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getrlimit)
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   common_post_getrlimit(tid, ARG1, ARG2);
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getrusage)
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getrusage ( %ld, %#lx )", ARG1,ARG2);
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_getrusage)
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0)
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_gettimeofday)
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "gettimeofday",
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timeval *, tv, struct timezone *, tz);
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // GrP fixme does darwin write to *tz anymore?
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0)
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0)
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_gettimeofday)
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0) {
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG1 != 0)
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         POST_timeval_WRITE( ARG1 );
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG2 != 0)
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_settimeofday)
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "settimeofday",
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timeval *, tv, struct timezone *, tz);
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0)
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "settimeofday(tv)", ARG1 );
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0) {
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* maybe should warn if tz->tz_dsttime is non-zero? */
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_getuid)
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_getuid ( )");
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "getuid");
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg)
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We don't have any specific information on it, so
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      try to do something reasonable based on direction and
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size bits.  The encoding scheme is described in
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      According to Simon Hausmann, _IOC_READ means the kernel
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      writes a value to the ioctl value passed from the user
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      space and the other way around with _IOC_WRITE. */
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dir  = _VKI_IOC_DIR(request);
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = _VKI_IOC_SIZE(request);
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) {
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * Be very lax about ioctl handling; the only
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * assumption is that the size is correct. Doesn't
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * require the full buffer to be initialized when
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * writing.  Without this, using some device
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * drivers with a large number of strange ioctl
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * commands becomes very tiresome.
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      static Int moans = 3;
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (moans > 0 && !VG_(clo_xml)) {
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         moans--;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   " with no size/direction hints\n", request);
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(umsg)("   This could cause spurious value errors to appear.\n");
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(umsg)("   See README_MISSING_SYSCALL_OR_IOCTL for "
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "guidance on writing a proper wrapper.\n" );
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((dir & _VKI_IOC_WRITE) && size > 0)
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( "ioctl(generic)", arg, size);
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((dir & _VKI_IOC_READ) && size > 0)
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_WRITE( "ioctl(generic)", arg, size);
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg)
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We don't have any specific information on it, so
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      try to do something reasonable based on direction and
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size bits.  The encoding scheme is described in
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      According to Simon Hausmann, _IOC_READ means the kernel
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      writes a value to the ioctl value passed from the user
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      space and the other way around with _IOC_WRITE. */
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dir  = _VKI_IOC_DIR(request);
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = _VKI_IOC_SIZE(request);
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size > 0 && (dir & _VKI_IOC_READ)
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && res == 0
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && arg != (Addr)NULL)
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE(arg, size);
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If we're sending a SIGKILL to one of our own threads, then simulate
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it rather than really sending the signal, so that the target thread
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gets a chance to clean up.  Returns True if we did the killing (or
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   no killing is necessary), and False if the caller should use the
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   normal kill syscall.
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "pid" is any pid argument which can be passed to kill; group kills
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (< -1, 0), and owner kills (-1) are ignored, on the grounds that
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   they'll most likely hit all the threads and we won't need to worry
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   about cleanup.  In truth, we can't fully emulate these multicast
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   kills.
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "tgid" is a thread group id.  If it is not -1, then the target
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread must be in that thread group.
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool ML_(do_sigkill)(Int pid, Int tgid)
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState *tst;
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId tid;
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (pid <= 0)
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tid = VG_(lwpid_to_vgtid)(pid);
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tid == VG_INVALID_THREADID)
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;		/* none of our threads */
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tst == NULL || tst->status == VgTs_Empty)
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;		/* hm, shouldn't happen */
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tgid != -1 && tst->os_state.threadgroup != tgid)
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;		/* not the right thread group */
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check to see that the target isn't already exiting. */
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_(is_exiting)(tid)) {
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_trace_signals))
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(message)(Vg_DebugMsg,
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Thread %d being killed with SIGKILL\n",
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      tst->tid);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->exitreason = VgSrc_FatalSig;
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tst->os_state.fatalsig = VKI_SIGKILL;
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(is_running_thread)(tid))
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(get_thread_out_of_syscall)(tid);
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_kill)
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_kill ( %ld, %ld )", ARG1,ARG2);
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "kill", int, pid, int, sig);
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(client_signal_OK)(ARG2)) {
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EINVAL );
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If we're sending SIGKILL, check to see if the target is one of
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      our threads and handle it specially. */
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Success(0);
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean)
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         affecting how posix-compliant the call is.  I guess it is
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         harmless to pass the 3rd arg on other platforms; hence pass
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it on all. */
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) );
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_trace_signals))
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld\n",
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   ARG2, ARG1);
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This kill might have given us a pending signal.  Ask for a check once
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the syscall is done. */
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfPollAfter;
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_link)
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_link ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newlstat)
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newlstat)
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mkdir)
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mkdir ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mprotect)
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mprotect ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "mprotect",
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, addr, vki_size_t, len, unsigned long, prot);
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_ENOMEM );
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VKI_PROT_GROWSDOWN)
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with mprotects on growable stack areas.
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The critical files to understand all this are mm/mprotect.c
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         glibc.
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         round the start/end address of mprotect to the start/end of
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the underlying vma and glibc uses that as an easy way to
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         change the protection of the stack by calling mprotect on the
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         last page of the stack with PROT_GROWSDOWN set.
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The sanity check provided by the kernel is that the vma must
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate.  */
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const *aseg = VG_(am_find_nsegment)(ARG1);
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      NSegment const *rseg;
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(aseg);
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (grows == VKI_PROT_GROWSDOWN) {
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rseg = VG_(am_next_nsegment)( (NSegment*)aseg, False/*backwards*/ );
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rseg &&
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rseg->kind == SkResvn &&
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rseg->smode == SmUpper &&
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rseg->end+1 == aseg->start) {
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr end = ARG1 + ARG2;
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG1 = aseg->start;
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG2 = end - aseg->start;
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG3 &= ~VKI_PROT_GROWSDOWN;
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            SET_STATUS_Failure( VKI_EINVAL );
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if (grows == VKI_PROT_GROWSUP) {
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rseg = VG_(am_next_nsegment)( (NSegment*)aseg, True/*forwards*/ );
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rseg &&
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rseg->kind == SkResvn &&
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rseg->smode == SmLower &&
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             aseg->end+1 == rseg->start) {
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG2 = aseg->end - ARG1 + 1;
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARG3 &= ~VKI_PROT_GROWSUP;
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            SET_STATUS_Failure( VKI_EINVAL );
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* both GROWSUP and GROWSDOWN */
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Failure( VKI_EINVAL );
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif   // defined(VKI_PROT_GROWSDOWN)
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_mprotect)
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr a    = ARG1;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT len = ARG2;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  prot = ARG3;
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(notify_core_and_tool_of_mprotect)(a, len, prot);
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_munmap)
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) VG_(printf)("  munmap( %#lx )\n", ARG1);
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_munmap ( %#lx, %llu )", ARG1,(ULong)ARG2);
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EINVAL );
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_munmap)
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr  a   = ARG1;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT len = ARG2;
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(notify_core_and_tool_of_munmap)( (Addr64)a, (ULong)len );
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mincore)
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mincore ( %#lx, %llu, %#lx )", ARG1,(ULong)ARG2,ARG3);
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "mincore",
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, start, vki_size_t, length,
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned char *, vec);
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_mincore)
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_nanosleep)
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock|SfPostOnFail;
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_nanosleep ( %#lx, %#lx )", ARG1,ARG2);
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "nanosleep",
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timespec *, req, struct timespec *, rem);
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0)
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_nanosleep)
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS || FAILURE);
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0 && FAILURE && ERR == VKI_EINTR)
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_open)
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 & VKI_O_CREAT) {
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // 3-arg version
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("sys_open ( %#lx(%s), %ld, %ld )",ARG1,(char*)ARG1,ARG2,ARG3);
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_REG_READ3(long, "open",
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const char *, filename, int, flags, int, mode);
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // 2-arg version
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("sys_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_REG_READ2(long, "open",
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const char *, filename, int, flags);
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Handle the case where the open is of /proc/self/cmdline or
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /proc/<pid>/cmdline, and just give it a copy of the fd for the
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fake file we cooked up at startup (in m_main).  Also, seek the
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cloned fd back to the start. */
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar  name[30];
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char*  arg1s = (Char*) ARG1;
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SysRes sres;
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ML_(safe_to_deref)( arg1s, 1 ) &&
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/cmdline"))
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sres = VG_(dup)( VG_(cl_cmdline_fd) );
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_from_SysRes( sres );
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!sr_isError(sres)) {
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (off < 0)
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               SET_STATUS_Failure( VKI_EMFILE );
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux)
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Otherwise handle normally */
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_open)
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(RES, "open", tid, True)) {
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(RES);
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EMFILE );
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds))
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_read)
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(ssize_t, "read",
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, char *, buf, vki_size_t, count);
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(ARG1, "read", tid, False))
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_read)
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, RES );
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_write)
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool ok;
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_write ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(ssize_t, "write",
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, fd, const char *, buf, vki_size_t, count);
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* check to see if it is allowed.  If not, try for an exemption from
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --sim-hints=enable-outer (used for self hosting). */
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ok = ML_(fd_allowed)(ARG1, "write", tid, False);
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ok && ARG1 == 2/*stderr*/
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           && VG_(strstr)(VG_(clo_sim_hints),"enable-outer"))
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ok = True;
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ok)
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_creat)
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_creat ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_creat)
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(close)(RES);
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EMFILE );
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_track_fds))
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_poll)
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* struct pollfd {
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int fd;           -- file descriptor
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        short events;     -- requested events
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        short revents;    -- returned events
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      };
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i;
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3);
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "poll",
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout);
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < ARG2; i++) {
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "poll(ufds.fd)",
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "poll(ufds.events)",
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "poll(ufds.reventss)",
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_poll)
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES >= 0) {
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt i;
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < ARG2; i++)
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_readlink)
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word saved = SYSNO;
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "readlink",
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path, char *, buf, int, bufsiz);
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * Handle the case where readlink is looking at /proc/self/exe or
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * /proc/<pid>/exe.
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar name[25];
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* arg1s = (Char*) ARG1;
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ML_(safe_to_deref)(arg1s, 1) &&
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe"))
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         ARG2, ARG3));
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux)
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Normal case */
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SUCCESS && RES > 0)
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES );
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_readv)
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_iovec * vec;
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_readv ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(ssize_t, "readv",
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, fd, const struct iovec *, vector,
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, count);
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG2 != 0) {
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ToDo: don't do any of the following if the vector is invalid */
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vec = (struct vki_iovec *)ARG2;
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < (Int)ARG3; i++)
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PRE_MEM_WRITE( "readv(vector[...])",
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Addr)vec[i].iov_base, vec[i].iov_len );
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_readv)
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES > 0) {
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int i;
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct vki_iovec * vec = (struct vki_iovec *)ARG2;
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int remains = RES;
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* RES holds the number of bytes read. */
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < (Int)ARG3; i++) {
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 Int nReadThisBuf = vec[i].iov_len;
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (nReadThisBuf > remains) nReadThisBuf = remains;
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 remains -= nReadThisBuf;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (remains < 0) VG_(core_panic)("readv: remains < 0");
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_rename)
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_rmdir)
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_rmdir ( %#lx(%s) )", ARG1,(char*)ARG1);
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "rmdir", const char *, pathname);
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_select)
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ5(long, "select",
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // XXX: this possibly understates how much memory is read.
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0)
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "select(readfds)",
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG3 != 0)
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "select(writefds)",
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG4 != 0)
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "select(exceptfds)",
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG5 != 0)
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "select(timeout)", ARG5 );
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setgid)
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setgid ( %ld )", ARG1);
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setsid)
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setsid ( )");
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "setsid");
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setgroups)
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("setgroups ( %llu, %#lx )", (ULong)ARG1, ARG2);
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 > 0)
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setpgid)
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("setpgid ( %ld, %ld )", ARG1, ARG2);
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setregid)
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setregid ( %ld, %ld )", ARG1, ARG2);
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setreuid)
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setreuid ( 0x%lx, 0x%lx )", ARG1, ARG2);
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setrlimit)
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord arg1 = ARG1;
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setrlimit ( %ld, %#lx )", ARG1,ARG2);
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "setrlimit",
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned int, resource, struct rlimit *, rlim);
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef _RLIMIT_POSIX_FLAG
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Darwin will sometimes set _RLIMIT_POSIX_FLAG on setrlimit calls.
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Unset it here to make the if statements below work correctly.
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arg1 &= ~_RLIMIT_POSIX_FLAG;
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg1 == VKI_RLIMIT_NOFILE) {
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Failure( VKI_EPERM );
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Success( 0 );
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (arg1 == VKI_RLIMIT_DATA) {
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_data).rlim_max ||
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_data).rlim_max) {
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Failure( VKI_EPERM );
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Success( 0 );
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_stack).rlim_max ||
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_stack).rlim_max) {
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Failure( VKI_EPERM );
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Success( 0 );
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_setuid)
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_setuid ( %ld )", ARG1);
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newstat)
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newstat)
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_statfs)
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_statfs)
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_statfs64)
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3);
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "statfs64",
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char *, path, vki_size_t, size, struct statfs64 *, buf);
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_statfs64)
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG3, ARG2 );
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_symlink)
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_symlink ( %#lx(%s), %#lx(%s) )",ARG1,(char*)ARG1,ARG2,(char*)ARG2);
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_time)
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* time_t time(time_t *t); */
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_time ( %#lx )",ARG1);
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "time", int *, t);
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_time)
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_times)
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_times ( %#lx )", ARG1);
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "times", struct tms *, buf);
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_times)
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_umask)
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_umask ( %ld )", ARG1);
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "umask", int, mask);
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_unlink)
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "unlink", const char *, pathname);
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_newuname)
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_newuname ( %#lx )", ARG1);
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_newuname)
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_waitpid)
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_waitpid ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "waitpid",
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_pid_t, pid, unsigned int *, status, int, options);
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL)
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_waitpid)
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL)
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(int) );
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_wait4)
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_wait4 ( %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4);
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ4(long, "wait4",
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_pid_t, pid, unsigned int *, status, int, options,
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct rusage *, rusage);
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL)
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG4 != (Addr)NULL)
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_wait4)
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != (Addr)NULL)
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(int) );
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG4 != (Addr)NULL)
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_writev)
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_iovec * vec;
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_writev ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(ssize_t, "writev",
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, fd, const struct iovec *, vector,
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, count);
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EBADF );
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "writev(vector)",
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ARG2, ARG3 * sizeof(struct vki_iovec) );
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG2 != 0) {
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ToDo: don't do any of the following if the vector is invalid */
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vec = (struct vki_iovec *)ARG2;
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < (Int)ARG3; i++)
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PRE_MEM_READ( "writev(vector[...])",
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (Addr)vec[i].iov_base, vec[i].iov_len );
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_utimes)
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   FUSE_COMPATIBLE_MAY_BLOCK();
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0) {
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "utimes(tvp[0])", ARG2 );
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_acct)
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_acct ( %#lx(%s) )", ARG1,(char*)ARG1);
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "acct", const char *, filename);
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_pause)
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_pause ( )");
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ0(long, "pause");
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_sigaltstack)
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2);
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(int, "sigaltstack",
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const vki_stack_t *, ss, vki_stack_t *, oss);
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 != 0) {
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const vki_stack_t *ss = (vki_stack_t *)ARG1;
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG2 != 0) {
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes(
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              (vki_stack_t*)ARG2)
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_sigaltstack)
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0 && ARG2 != 0)
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef PRE
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef POST
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_linux) || defined(VGO_darwin)
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4209