blob: f1207f47f39cc3580e692ca7289f28abfab5d78a [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
sewardj6e9de462011-06-28 07:25:29 +00003/*--- Wrappers for generic Unix system calls ---*/
njn8b68b642009-06-24 00:37:09 +00004/*--- syswrap-generic.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005/*--------------------------------------------------------------------*/
6
7/*
njnb9c427c2004-12-01 14:14:42 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjde4a1d02002-03-22 01:27:54 +000010
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2000-2013 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
njn8b68b642009-06-24 00:37:09 +000032#if defined(VGO_linux) || defined(VGO_darwin)
33
njnc7561b92005-06-19 01:24:32 +000034#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000035#include "pub_core_vki.h"
36#include "pub_core_vkiscnums.h"
sewardj6c591e12011-04-11 16:17:51 +000037#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
njnc7561b92005-06-19 01:24:32 +000038#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000039#include "pub_core_debuginfo.h" // VG_(di_notify_*)
sewardj55f9d1a2005-04-25 11:11:44 +000040#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000041#include "pub_core_transtab.h" // VG_(discard_translations)
sewardj14c7cc52007-02-25 15:08:24 +000042#include "pub_core_xarray.h"
sewardj45f4e7c2005-09-27 19:20:21 +000043#include "pub_core_clientstate.h" // VG_(brk_base), VG_(brk_limit)
njn899ce732005-06-21 00:28:11 +000044#include "pub_core_debuglog.h"
njn0087c502005-07-01 04:15:36 +000045#include "pub_core_errormgr.h"
florianc91f5842013-09-15 10:42:26 +000046#include "pub_core_gdbserver.h" // VG_(gdbserver)
njn97405b22005-06-02 03:39:33 +000047#include "pub_core_libcbase.h"
sewardja8d8e232005-06-07 20:04:56 +000048#include "pub_core_libcassert.h"
njnde62cbf2005-06-10 22:08:14 +000049#include "pub_core_libcfile.h"
50#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000051#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000052#include "pub_core_libcsignal.h"
njnf76d27a2009-05-28 01:53:07 +000053#include "pub_core_machine.h" // VG_(get_SP)
njnaf1d7df2005-06-11 01:31:52 +000054#include "pub_core_mallocfree.h"
sewardja8d8e232005-06-07 20:04:56 +000055#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000056#include "pub_core_scheduler.h"
sewardja8d8e232005-06-07 20:04:56 +000057#include "pub_core_signals.h"
njn419bbcb2005-06-21 03:52:49 +000058#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
njn9abd6082005-06-17 21:31:45 +000059#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000060#include "pub_core_syswrap.h"
njn419bbcb2005-06-21 03:52:49 +000061#include "pub_core_tooliface.h"
njn73750612005-10-14 03:11:30 +000062#include "pub_core_ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000063
sewardja8d8e232005-06-07 20:04:56 +000064#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000065#include "priv_syswrap-generic.h"
sewardjde4a1d02002-03-22 01:27:54 +000066
bart870f7452009-12-29 16:56:18 +000067#include "config.h"
68
jsgf855d93d2003-10-13 22:26:55 +000069
sewardj45f4e7c2005-09-27 19:20:21 +000070/* Returns True iff address range is something the client can
71 plausibly mess with: all of it is either already belongs to the
72 client or is free or a reservation. */
73
sewardj7eb7c582005-06-23 01:02:53 +000074Bool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
floriane543f302012-10-21 19:43:43 +000075 const HChar *syscallname)
fitzhardinge1a303042003-12-22 08:48:50 +000076{
fitzhardinge1a303042003-12-22 08:48:50 +000077 Bool ret;
78
79 if (size == 0)
80 return True;
81
sewardj45f4e7c2005-09-27 19:20:21 +000082 ret = VG_(am_is_valid_for_client_or_free_or_resvn)
83 (start,size,VKI_PROT_NONE);
fitzhardinge1a303042003-12-22 08:48:50 +000084
85 if (0)
barta0b6b2c2008-07-07 06:49:24 +000086 VG_(printf)("%s: test=%#lx-%#lx ret=%d\n",
sewardj45f4e7c2005-09-27 19:20:21 +000087 syscallname, start, start+size-1, (Int)ret);
fitzhardinge1a303042003-12-22 08:48:50 +000088
nethercote1543adf2004-10-25 15:43:21 +000089 if (!ret && syscallname != NULL) {
sewardja8d8e232005-06-07 20:04:56 +000090 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
sewardj738856f2009-07-15 14:48:32 +000091 "to modify addresses %#lx-%#lx\n",
barta0b6b2c2008-07-07 06:49:24 +000092 syscallname, start, start+size-1);
fitzhardinge1a303042003-12-22 08:48:50 +000093 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +000094 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
fitzhardinge1a303042003-12-22 08:48:50 +000095 }
96 }
97
98 return ret;
99}
100
sewardj45f4e7c2005-09-27 19:20:21 +0000101
sewardj7eb7c582005-06-23 01:02:53 +0000102Bool ML_(client_signal_OK)(Int sigNo)
njn419bbcb2005-06-21 03:52:49 +0000103{
104 /* signal 0 is OK for kill */
njn351d0062005-06-21 22:23:59 +0000105 Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
njn419bbcb2005-06-21 03:52:49 +0000106
107 //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
108
109 return ret;
110}
111
sewardj45f4e7c2005-09-27 19:20:21 +0000112
113/* Handy small function to help stop wrappers from segfaulting when
114 presented with bogus client addresses. Is not used for generating
115 user-visible errors. */
116
117Bool ML_(safe_to_deref) ( void* start, SizeT size )
118{
njn143377e2009-06-10 06:13:34 +0000119 return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_READ );
sewardj45f4e7c2005-09-27 19:20:21 +0000120}
121
122
njn25e49d8e72002-09-23 09:36:25 +0000123/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000124 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000125 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000126
njn25e49d8e72002-09-23 09:36:25 +0000127/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
128 munmap, mprotect (and mremap??) work at the page level. So addresses
129 and lengths must be adjusted for this. */
130
131/* Mash around start and length so that the area exactly covers
132 an integral number of pages. If we don't do that, memcheck's
133 idea of addressible memory diverges from that of the
134 kernel's, which causes the leak detector to crash. */
135static
sewardj45f4e7c2005-09-27 19:20:21 +0000136void page_align_addr_and_len( Addr* a, SizeT* len)
sewardjde4a1d02002-03-22 01:27:54 +0000137{
fitzhardinge98abfc72003-12-16 02:05:15 +0000138 Addr ra;
139
njn13bfd852005-06-02 03:52:53 +0000140 ra = VG_PGROUNDDN(*a);
141 *len = VG_PGROUNDUP(*a + *len) - ra;
fitzhardinge98abfc72003-12-16 02:05:15 +0000142 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000143}
144
njndd372582009-05-10 22:42:19 +0000145static void notify_core_of_mmap(Addr a, SizeT len, UInt prot,
146 UInt flags, Int fd, Off64T offset)
bart510521e2008-05-29 08:52:44 +0000147{
148 Bool d;
njn25e49d8e72002-09-23 09:36:25 +0000149
sewardj45f4e7c2005-09-27 19:20:21 +0000150 /* 'a' is the return value from a real kernel mmap, hence: */
151 vg_assert(VG_IS_PAGE_ALIGNED(a));
152 /* whereas len is whatever the syscall supplied. So: */
153 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000154
sewardj45f4e7c2005-09-27 19:20:21 +0000155 d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
fitzhardinge98abfc72003-12-16 02:05:15 +0000156
bart510521e2008-05-29 08:52:44 +0000157 if (d)
158 VG_(discard_translations)( (Addr64)a, (ULong)len,
njndd372582009-05-10 22:42:19 +0000159 "notify_core_of_mmap" );
bart510521e2008-05-29 08:52:44 +0000160}
161
njndd372582009-05-10 22:42:19 +0000162static void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, ULong di_handle)
bart510521e2008-05-29 08:52:44 +0000163{
164 Bool rr, ww, xx;
165
166 /* 'a' is the return value from a real kernel mmap, hence: */
167 vg_assert(VG_IS_PAGE_ALIGNED(a));
168 /* whereas len is whatever the syscall supplied. So: */
169 len = VG_PGROUNDUP(len);
170
sewardj45f4e7c2005-09-27 19:20:21 +0000171 rr = toBool(prot & VKI_PROT_READ);
172 ww = toBool(prot & VKI_PROT_WRITE);
173 xx = toBool(prot & VKI_PROT_EXEC);
njn25e49d8e72002-09-23 09:36:25 +0000174
sewardj9c606bd2008-09-18 18:12:50 +0000175 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle );
sewardjde4a1d02002-03-22 01:27:54 +0000176}
177
njndd372582009-05-10 22:42:19 +0000178
179/* When a client mmap has been successfully done, this function must
180 be called. It notifies both aspacem and the tool of the new
181 mapping.
182
183 JRS 2008-Aug-14: But notice this is *very* obscure. The only place
184 it is called from is POST(sys_io_setup). In particular,
185 ML_(generic_PRE_sys_mmap), in m_syswrap, is the "normal case" handler for
186 client mmap. But it doesn't call this function; instead it does the
187 relevant notifications itself. Here, we just pass di_handle=0 to
188 notify_tool_of_mmap as we have no better information. But really this
189 function should be done away with; problem is I don't understand what
190 POST(sys_io_setup) does or how it works.
191
192 [However, this function is used lots for Darwin, because
193 ML_(generic_PRE_sys_mmap) cannot be used for Darwin.]
194 */
195void
196ML_(notify_core_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
197 UInt flags, Int fd, Off64T offset )
198{
199 // XXX: unlike the other notify_core_and_tool* functions, this one doesn't
200 // do anything with debug info (ie. it doesn't call VG_(di_notify_mmap)).
201 // Should it? --njn
202 notify_core_of_mmap(a, len, prot, flags, fd, offset);
203 notify_tool_of_mmap(a, len, prot, 0/*di_handle*/);
204}
205
206void
207ML_(notify_core_and_tool_of_munmap) ( Addr a, SizeT len )
208{
209 Bool d;
210
211 page_align_addr_and_len(&a, &len);
212 d = VG_(am_notify_munmap)(a, len);
213 VG_TRACK( die_mem_munmap, a, len );
214 VG_(di_notify_munmap)( a, len );
215 if (d)
216 VG_(discard_translations)( (Addr64)a, (ULong)len,
217 "ML_(notify_core_and_tool_of_munmap)" );
218}
219
220void
221ML_(notify_core_and_tool_of_mprotect) ( Addr a, SizeT len, Int prot )
222{
223 Bool rr = toBool(prot & VKI_PROT_READ);
224 Bool ww = toBool(prot & VKI_PROT_WRITE);
225 Bool xx = toBool(prot & VKI_PROT_EXEC);
226 Bool d;
227
228 page_align_addr_and_len(&a, &len);
229 d = VG_(am_notify_mprotect)(a, len, prot);
230 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
231 VG_(di_notify_mprotect)( a, len, prot );
232 if (d)
233 VG_(discard_translations)( (Addr64)a, (ULong)len,
234 "ML_(notify_core_and_tool_of_mprotect)" );
235}
236
237
238
njnf76d27a2009-05-28 01:53:07 +0000239#if HAVE_MREMAP
sewardj45f4e7c2005-09-27 19:20:21 +0000240/* Expand (or shrink) an existing mapping, potentially moving it at
241 the same time (controlled by the MREMAP_MAYMOVE flag). Nightmare.
242*/
243static
244SysRes do_mremap( Addr old_addr, SizeT old_len,
245 Addr new_addr, SizeT new_len,
246 UWord flags, ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +0000247{
sewardj45f4e7c2005-09-27 19:20:21 +0000248# define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
njn25e49d8e72002-09-23 09:36:25 +0000249
sewardj45f4e7c2005-09-27 19:20:21 +0000250 Bool ok, d;
sewardjef1cf8b2006-10-17 01:47:30 +0000251 NSegment const* old_seg;
sewardj45f4e7c2005-09-27 19:20:21 +0000252 Addr advised;
253 Bool f_fixed = toBool(flags & VKI_MREMAP_FIXED);
254 Bool f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
fitzhardinge1a303042003-12-22 08:48:50 +0000255
256 if (0)
barta0b6b2c2008-07-07 06:49:24 +0000257 VG_(printf)("do_remap (old %#lx %ld) (new %#lx %ld) %s %s\n",
sewardj45f4e7c2005-09-27 19:20:21 +0000258 old_addr,old_len,new_addr,new_len,
259 flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
260 flags & VKI_MREMAP_FIXED ? "FIXED" : "");
sewardj63a622f2006-08-16 14:22:29 +0000261 if (0)
262 VG_(am_show_nsegments)(0, "do_remap: before");
fitzhardinge1a303042003-12-22 08:48:50 +0000263
sewardj45f4e7c2005-09-27 19:20:21 +0000264 if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
265 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000266
sewardj45f4e7c2005-09-27 19:20:21 +0000267 if (!VG_IS_PAGE_ALIGNED(old_addr))
268 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000269
sewardj45f4e7c2005-09-27 19:20:21 +0000270 old_len = VG_PGROUNDUP(old_len);
271 new_len = VG_PGROUNDUP(new_len);
fitzhardinge1a303042003-12-22 08:48:50 +0000272
sewardj45f4e7c2005-09-27 19:20:21 +0000273 if (new_len == 0)
274 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000275
sewardj45f4e7c2005-09-27 19:20:21 +0000276 /* kernel doesn't reject this, but we do. */
277 if (old_len == 0)
278 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000279
sewardj45f4e7c2005-09-27 19:20:21 +0000280 /* reject wraparounds */
toma5e13dd2011-08-11 14:51:47 +0000281 if (old_addr + old_len < old_addr)
282 goto eINVAL;
283 if (f_fixed == True && new_addr + new_len < new_len)
sewardj45f4e7c2005-09-27 19:20:21 +0000284 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000285
sewardj45f4e7c2005-09-27 19:20:21 +0000286 /* kernel rejects all fixed, no-move requests (which are
287 meaningless). */
288 if (f_fixed == True && f_maymove == False)
289 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000290
sewardj45f4e7c2005-09-27 19:20:21 +0000291 /* Stay away from non-client areas. */
292 if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
293 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000294
sewardj45f4e7c2005-09-27 19:20:21 +0000295 /* In all remaining cases, if the old range does not fall within a
296 single segment, fail. */
297 old_seg = VG_(am_find_nsegment)( old_addr );
298 if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
299 goto eINVAL;
sewardjfdf619e2005-11-23 03:41:41 +0000300 if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC)
sewardj45f4e7c2005-09-27 19:20:21 +0000301 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000302
sewardj45f4e7c2005-09-27 19:20:21 +0000303 vg_assert(old_len > 0);
304 vg_assert(new_len > 0);
305 vg_assert(VG_IS_PAGE_ALIGNED(old_len));
306 vg_assert(VG_IS_PAGE_ALIGNED(new_len));
307 vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
fitzhardinge1a303042003-12-22 08:48:50 +0000308
sewardj45f4e7c2005-09-27 19:20:21 +0000309 /* There are 3 remaining cases:
fitzhardinge1a303042003-12-22 08:48:50 +0000310
sewardj45f4e7c2005-09-27 19:20:21 +0000311 * maymove == False
312
313 new space has to be at old address, so:
314 - shrink -> unmap end
315 - same size -> do nothing
316 - grow -> if can grow in-place, do so, else fail
317
318 * maymove == True, fixed == False
319
320 new space can be anywhere, so:
321 - shrink -> unmap end
322 - same size -> do nothing
323 - grow -> if can grow in-place, do so, else
324 move to anywhere large enough, else fail
325
326 * maymove == True, fixed == True
327
328 new space must be at new address, so:
329
330 - if new address is not page aligned, fail
331 - if new address range overlaps old one, fail
332 - if new address range cannot be allocated, fail
333 - else move to new address range with new size
334 - else fail
335 */
336
337 if (f_maymove == False) {
338 /* new space has to be at old address */
339 if (new_len < old_len)
340 goto shrink_in_place;
341 if (new_len > old_len)
342 goto grow_in_place_or_fail;
343 goto same_in_place;
344 }
345
346 if (f_maymove == True && f_fixed == False) {
347 /* new space can be anywhere */
348 if (new_len < old_len)
349 goto shrink_in_place;
350 if (new_len > old_len)
351 goto grow_in_place_or_move_anywhere_or_fail;
352 goto same_in_place;
353 }
354
355 if (f_maymove == True && f_fixed == True) {
356 /* new space can only be at the new address */
357 if (!VG_IS_PAGE_ALIGNED(new_addr))
358 goto eINVAL;
359 if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
360 /* no overlap */
fitzhardinge1a303042003-12-22 08:48:50 +0000361 } else {
sewardj45f4e7c2005-09-27 19:20:21 +0000362 goto eINVAL;
363 }
364 if (new_addr == 0)
365 goto eINVAL;
366 /* VG_(am_get_advisory_client_simple) interprets zero to mean
367 non-fixed, which is not what we want */
368 advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
369 if (!ok || advised != new_addr)
370 goto eNOMEM;
371 ok = VG_(am_relocate_nooverlap_client)
372 ( &d, old_addr, old_len, new_addr, new_len );
373 if (ok) {
374 VG_TRACK( copy_mem_remap, old_addr, new_addr,
375 MIN_SIZET(old_len,new_len) );
376 if (new_len > old_len)
377 VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
sewardj9c606bd2008-09-18 18:12:50 +0000378 old_seg->hasR, old_seg->hasW, old_seg->hasX,
379 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000380 VG_TRACK(die_mem_munmap, old_addr, old_len);
381 if (d) {
382 VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
383 VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
384 }
385 return VG_(mk_SysRes_Success)( new_addr );
386 }
387 goto eNOMEM;
388 }
fitzhardinge1a303042003-12-22 08:48:50 +0000389
sewardj45f4e7c2005-09-27 19:20:21 +0000390 /* end of the 3 cases */
391 /*NOTREACHED*/ vg_assert(0);
fitzhardinge1a303042003-12-22 08:48:50 +0000392
sewardj45f4e7c2005-09-27 19:20:21 +0000393 grow_in_place_or_move_anywhere_or_fail:
394 {
395 /* try growing it in-place */
396 Addr needA = old_addr + old_len;
397 SSizeT needL = new_len - old_len;
fitzhardinge1a303042003-12-22 08:48:50 +0000398
sewardj45f4e7c2005-09-27 19:20:21 +0000399 vg_assert(needL > 0);
400 if (needA == 0)
401 goto eINVAL;
402 /* VG_(am_get_advisory_client_simple) interprets zero to mean
403 non-fixed, which is not what we want */
404 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
sewardj63a622f2006-08-16 14:22:29 +0000405 if (ok) {
philippe15e301e2011-12-22 13:25:58 +0000406 /* Fixes bug #129866. */
407 ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
sewardj63a622f2006-08-16 14:22:29 +0000408 }
sewardj45f4e7c2005-09-27 19:20:21 +0000409 if (ok && advised == needA) {
florian3e798632012-11-24 19:41:54 +0000410 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
sewardj45f4e7c2005-09-27 19:20:21 +0000411 if (ok) {
412 VG_TRACK( new_mem_mmap, needA, needL,
413 old_seg->hasR,
sewardj9c606bd2008-09-18 18:12:50 +0000414 old_seg->hasW, old_seg->hasX,
415 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000416 if (d)
417 VG_(discard_translations)( needA, needL, "do_remap(3)" );
418 return VG_(mk_SysRes_Success)( old_addr );
fitzhardinge1a303042003-12-22 08:48:50 +0000419 }
420 }
421
sewardj45f4e7c2005-09-27 19:20:21 +0000422 /* that failed. Look elsewhere. */
423 advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
424 if (ok) {
tom5484f382010-09-27 15:08:34 +0000425 Bool oldR = old_seg->hasR;
426 Bool oldW = old_seg->hasW;
427 Bool oldX = old_seg->hasX;
sewardj45f4e7c2005-09-27 19:20:21 +0000428 /* assert new area does not overlap old */
429 vg_assert(advised+new_len-1 < old_addr
430 || advised > old_addr+old_len-1);
431 ok = VG_(am_relocate_nooverlap_client)
432 ( &d, old_addr, old_len, advised, new_len );
433 if (ok) {
434 VG_TRACK( copy_mem_remap, old_addr, advised,
435 MIN_SIZET(old_len,new_len) );
436 if (new_len > old_len)
437 VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
tom5484f382010-09-27 15:08:34 +0000438 oldR, oldW, oldX, 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000439 VG_TRACK(die_mem_munmap, old_addr, old_len);
440 if (d) {
441 VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
442 VG_(discard_translations)( advised, new_len, "do_remap(5)" );
443 }
444 return VG_(mk_SysRes_Success)( advised );
445 }
446 }
447 goto eNOMEM;
448 }
449 /*NOTREACHED*/ vg_assert(0);
450
451 grow_in_place_or_fail:
452 {
453 Addr needA = old_addr + old_len;
454 SizeT needL = new_len - old_len;
455 if (needA == 0)
456 goto eINVAL;
457 /* VG_(am_get_advisory_client_simple) interprets zero to mean
458 non-fixed, which is not what we want */
459 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
sewardj63a622f2006-08-16 14:22:29 +0000460 if (ok) {
philippe15e301e2011-12-22 13:25:58 +0000461 /* Fixes bug #129866. */
462 ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
sewardj63a622f2006-08-16 14:22:29 +0000463 }
sewardj45f4e7c2005-09-27 19:20:21 +0000464 if (!ok || advised != needA)
465 goto eNOMEM;
florian3e798632012-11-24 19:41:54 +0000466 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
sewardj45f4e7c2005-09-27 19:20:21 +0000467 if (!ok)
468 goto eNOMEM;
469 VG_TRACK( new_mem_mmap, needA, needL,
sewardj9c606bd2008-09-18 18:12:50 +0000470 old_seg->hasR, old_seg->hasW, old_seg->hasX,
471 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000472 if (d)
473 VG_(discard_translations)( needA, needL, "do_remap(6)" );
474 return VG_(mk_SysRes_Success)( old_addr );
475 }
476 /*NOTREACHED*/ vg_assert(0);
477
478 shrink_in_place:
479 {
480 SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
njncda2f0f2009-05-18 02:12:08 +0000481 if (sr_isError(sres))
sewardj45f4e7c2005-09-27 19:20:21 +0000482 return sres;
483 VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
484 if (d)
485 VG_(discard_translations)( old_addr+new_len, old_len-new_len,
486 "do_remap(7)" );
487 return VG_(mk_SysRes_Success)( old_addr );
488 }
489 /*NOTREACHED*/ vg_assert(0);
490
491 same_in_place:
492 return VG_(mk_SysRes_Success)( old_addr );
493 /*NOTREACHED*/ vg_assert(0);
494
495 eINVAL:
496 return VG_(mk_SysRes_Error)( VKI_EINVAL );
497 eNOMEM:
498 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
499
500# undef MIN_SIZET
sewardjde4a1d02002-03-22 01:27:54 +0000501}
njnf76d27a2009-05-28 01:53:07 +0000502#endif /* HAVE_MREMAP */
sewardjde4a1d02002-03-22 01:27:54 +0000503
504
sewardja8d8e232005-06-07 20:04:56 +0000505/* ---------------------------------------------------------------------
506 File-descriptor tracking
507 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000508
rjwalshf5f536f2003-11-17 17:45:00 +0000509/* One of these is allocated for each open file descriptor. */
rjwalshf5f536f2003-11-17 17:45:00 +0000510typedef struct OpenFd
511{
512 Int fd; /* The file descriptor */
florian19f91bb2012-11-10 22:29:54 +0000513 HChar *pathname; /* NULL if not a regular file or unknown */
rjwalshf5f536f2003-11-17 17:45:00 +0000514 ExeContext *where; /* NULL if inherited from parent */
515 struct OpenFd *next, *prev;
516} OpenFd;
517
518/* List of allocated file descriptors. */
sewardj1aa40212006-12-11 01:11:02 +0000519static OpenFd *allocated_fds = NULL;
rjwalshf5f536f2003-11-17 17:45:00 +0000520
521/* Count of open file descriptors. */
sewardj0a400c72005-07-23 09:22:46 +0000522static Int fd_count = 0;
rjwalshf5f536f2003-11-17 17:45:00 +0000523
rjwalshf5f536f2003-11-17 17:45:00 +0000524
rjwalshf5f536f2003-11-17 17:45:00 +0000525/* Note the fact that a file descriptor was just closed. */
rjwalshf5f536f2003-11-17 17:45:00 +0000526static
njn1dcee092009-02-24 03:07:37 +0000527void record_fd_close(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000528{
529 OpenFd *i = allocated_fds;
530
thughesad1c9562004-06-26 11:27:52 +0000531 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000532 return; /* Valgrind internal */
533
rjwalshf5f536f2003-11-17 17:45:00 +0000534 while(i) {
535 if(i->fd == fd) {
536 if(i->prev)
537 i->prev->next = i->next;
538 else
539 allocated_fds = i->next;
540 if(i->next)
541 i->next->prev = i->prev;
542 if(i->pathname)
fitzhardingea7728472003-12-16 01:48:38 +0000543 VG_(arena_free) (VG_AR_CORE, i->pathname);
544 VG_(arena_free) (VG_AR_CORE, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000545 fd_count--;
546 break;
547 }
548 i = i->next;
549 }
550}
551
552/* Note the fact that a file descriptor was just opened. If the
553 tid is -1, this indicates an inherited fd. If the pathname is NULL,
554 this either indicates a non-standard file (i.e. a pipe or socket or
555 some such thing) or that we don't know the filename. If the fd is
556 already open, then we're probably doing a dup2() to an existing fd,
557 so just overwrite the existing one. */
njn4279a882005-08-26 03:43:28 +0000558void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname)
rjwalshf5f536f2003-11-17 17:45:00 +0000559{
560 OpenFd *i;
561
thughesad1c9562004-06-26 11:27:52 +0000562 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000563 return; /* Valgrind internal */
564
rjwalshf5f536f2003-11-17 17:45:00 +0000565 /* Check to see if this fd is already open. */
566 i = allocated_fds;
567 while (i) {
568 if (i->fd == fd) {
fitzhardingea7728472003-12-16 01:48:38 +0000569 if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000570 break;
571 }
572 i = i->next;
573 }
574
575 /* Not already one: allocate an OpenFd */
576 if (i == NULL) {
sewardj9c606bd2008-09-18 18:12:50 +0000577 i = VG_(arena_malloc)(VG_AR_CORE, "syswrap.rfdowgn.1", sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000578
579 i->prev = NULL;
580 i->next = allocated_fds;
581 if(allocated_fds) allocated_fds->prev = i;
582 allocated_fds = i;
583 fd_count++;
584 }
585
586 i->fd = fd;
sewardj9c606bd2008-09-18 18:12:50 +0000587 i->pathname = VG_(arena_strdup)(VG_AR_CORE, "syswrap.rfdowgn.2", pathname);
sewardjd01b5982007-11-09 23:24:09 +0000588 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
rjwalshf5f536f2003-11-17 17:45:00 +0000589}
590
njnf845f8f2005-06-23 02:26:47 +0000591// Record opening of an fd, and find its name.
njn096ccdd2009-02-22 23:00:30 +0000592void ML_(record_fd_open_named)(ThreadId tid, Int fd)
njnf845f8f2005-06-23 02:26:47 +0000593{
594 static HChar buf[VKI_PATH_MAX];
floriane543f302012-10-21 19:43:43 +0000595 HChar* name;
njnf845f8f2005-06-23 02:26:47 +0000596 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
597 name = buf;
598 else
599 name = NULL;
600
njn4279a882005-08-26 03:43:28 +0000601 ML_(record_fd_open_with_given_name)(tid, fd, name);
njnf845f8f2005-06-23 02:26:47 +0000602}
603
604// Record opening of a nameless fd.
605void ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
606{
njn4279a882005-08-26 03:43:28 +0000607 ML_(record_fd_open_with_given_name)(tid, fd, NULL);
njnf845f8f2005-06-23 02:26:47 +0000608}
609
rjwalshf5f536f2003-11-17 17:45:00 +0000610static
tom39955262014-02-24 15:06:06 +0000611HChar *unix_to_name(struct vki_sockaddr_un *sa, UInt len, HChar *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000612{
nethercote73b526f2004-10-31 18:48:21 +0000613 if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
rjwalshf5f536f2003-11-17 17:45:00 +0000614 VG_(sprintf)(name, "<unknown>");
615 } else {
616 VG_(sprintf)(name, "%s", sa->sun_path);
617 }
618
619 return name;
620}
621
622static
tom39955262014-02-24 15:06:06 +0000623HChar *inet_to_name(struct vki_sockaddr_in *sa, UInt len, HChar *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000624{
nethercote73b526f2004-10-31 18:48:21 +0000625 if (sa == NULL || len == 0) {
rjwalshf5f536f2003-11-17 17:45:00 +0000626 VG_(sprintf)(name, "<unknown>");
tom39955262014-02-24 15:06:06 +0000627 } else if (sa->sin_port == 0) {
628 VG_(sprintf)(name, "<unbound>");
rjwalshf5f536f2003-11-17 17:45:00 +0000629 } else {
tom329af4b2005-11-17 12:02:58 +0000630 UInt addr = VG_(ntohl)(sa->sin_addr.s_addr);
tom39955262014-02-24 15:06:06 +0000631 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
632 (addr>>24) & 0xFF, (addr>>16) & 0xFF,
633 (addr>>8) & 0xFF, addr & 0xFF,
634 VG_(ntohs)(sa->sin_port));
635 }
636
637 return name;
638}
639
640static
641void inet6_format(HChar *s, const UChar ip[16])
642{
643 static const unsigned char V4mappedprefix[12] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
644
645 if (!VG_(memcmp)(ip, V4mappedprefix, 12)) {
646 struct vki_in_addr *sin_addr = (struct vki_in_addr *)(ip + 12);
647 UInt addr = VG_(ntohl)(sin_addr->s_addr);
648
649 VG_(sprintf)(s, "::ffff:%u.%u.%u.%u",
650 (addr>>24) & 0xFF, (addr>>16) & 0xFF,
651 (addr>>8) & 0xFF, addr & 0xFF);
652 } else {
653 Bool compressing = False;
654 Bool compressed = False;
655 Int len = 0;
656 Int i;
657
658 for (i = 0; i < 16; i += 2) {
659 UInt word = ((UInt)ip[i] << 8) | (UInt)ip[i+1];
660 if (word == 0 && !compressed) {
661 compressing = True;
662 } else {
663 if (compressing) {
664 compressing = False;
665 compressed = True;
666 s[len++] = ':';
667 }
668 if (i > 0) {
669 s[len++] = ':';
670 }
671 len += VG_(sprintf)(s + len, "%x", word);
672 }
rjwalshf5f536f2003-11-17 17:45:00 +0000673 }
tom39955262014-02-24 15:06:06 +0000674
675 if (compressing) {
676 s[len++] = ':';
677 s[len++] = ':';
678 }
679
680 s[len++] = 0;
681 }
682
683 return;
684}
685
686static
687HChar *inet6_to_name(struct vki_sockaddr_in6 *sa, UInt len, HChar *name)
688{
689 if (sa == NULL || len == 0) {
690 VG_(sprintf)(name, "<unknown>");
691 } else if (sa->sin6_port == 0) {
692 VG_(sprintf)(name, "<unbound>");
693 } else {
694 char addr[128];
695 inet6_format(addr, (void *)&(sa->sin6_addr));
696 VG_(sprintf)(name, "[%s]:%u", addr, VG_(ntohs)(sa->sin6_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000697 }
698
699 return name;
700}
701
rjwalshf5f536f2003-11-17 17:45:00 +0000702/*
703 * Try get some details about a socket.
704 */
rjwalshf5f536f2003-11-17 17:45:00 +0000705static void
sewardj0a400c72005-07-23 09:22:46 +0000706getsockdetails(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000707{
708 union u {
nethercote73b526f2004-10-31 18:48:21 +0000709 struct vki_sockaddr a;
710 struct vki_sockaddr_in in;
tom39955262014-02-24 15:06:06 +0000711 struct vki_sockaddr_in6 in6;
nethercote73b526f2004-10-31 18:48:21 +0000712 struct vki_sockaddr_un un;
rjwalshf5f536f2003-11-17 17:45:00 +0000713 } laddr;
florian1636d332012-11-15 04:27:04 +0000714 Int llen;
rjwalshf5f536f2003-11-17 17:45:00 +0000715
716 llen = sizeof(laddr);
717 VG_(memset)(&laddr, 0, llen);
718
719 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
720 switch(laddr.a.sa_family) {
nethercote73b526f2004-10-31 18:48:21 +0000721 case VKI_AF_INET: {
rjwalshf5f536f2003-11-17 17:45:00 +0000722 static char lname[32];
723 static char pname[32];
nethercote73b526f2004-10-31 18:48:21 +0000724 struct vki_sockaddr_in paddr;
florian1636d332012-11-15 04:27:04 +0000725 Int plen = sizeof(struct vki_sockaddr_in);
rjwalshf5f536f2003-11-17 17:45:00 +0000726
sewardj738856f2009-07-15 14:48:32 +0000727 if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
728 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s\n", fd,
tom39955262014-02-24 15:06:06 +0000729 inet_to_name(&(laddr.in), llen, lname),
730 inet_to_name(&paddr, plen, pname));
rjwalshf5f536f2003-11-17 17:45:00 +0000731 } else {
sewardj738856f2009-07-15 14:48:32 +0000732 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound\n",
tom39955262014-02-24 15:06:06 +0000733 fd, inet_to_name(&(laddr.in), llen, lname));
734 }
735 return;
736 }
737 case VKI_AF_INET6: {
738 static char lname[128];
739 static char pname[128];
740 struct vki_sockaddr_in6 paddr;
741 Int plen = sizeof(struct vki_sockaddr_in6);
742
743 if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
744 VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> %s\n", fd,
745 inet6_to_name(&(laddr.in6), llen, lname),
746 inet6_to_name(&paddr, plen, pname));
747 } else {
748 VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> unbound\n",
749 fd, inet6_to_name(&(laddr.in6), llen, lname));
rjwalshf5f536f2003-11-17 17:45:00 +0000750 }
751 return;
752 }
nethercote73b526f2004-10-31 18:48:21 +0000753 case VKI_AF_UNIX: {
rjwalshf5f536f2003-11-17 17:45:00 +0000754 static char lname[256];
sewardj738856f2009-07-15 14:48:32 +0000755 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s\n", fd,
tom39955262014-02-24 15:06:06 +0000756 unix_to_name(&(laddr.un), llen, lname));
rjwalshf5f536f2003-11-17 17:45:00 +0000757 return;
758 }
759 default:
sewardj738856f2009-07-15 14:48:32 +0000760 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:\n",
rjwalshf5f536f2003-11-17 17:45:00 +0000761 laddr.a.sa_family, fd);
762 return;
763 }
764 }
765
sewardj738856f2009-07-15 14:48:32 +0000766 VG_(message)(Vg_UserMsg, "Open socket %d:\n", fd);
rjwalshf5f536f2003-11-17 17:45:00 +0000767}
768
769
nethercote3a42fb82004-08-03 18:08:50 +0000770/* Dump out a summary, and a more detailed list, of open file descriptors. */
floriane543f302012-10-21 19:43:43 +0000771void VG_(show_open_fds) (const HChar* when)
rjwalshf5f536f2003-11-17 17:45:00 +0000772{
773 OpenFd *i = allocated_fds;
774
philippec3360382012-10-21 14:37:14 +0000775 VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open %s.\n", fd_count, when);
rjwalshf5f536f2003-11-17 17:45:00 +0000776
sewardj738856f2009-07-15 14:48:32 +0000777 while (i) {
778 if (i->pathname) {
779 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd,
rjwalshf5f536f2003-11-17 17:45:00 +0000780 i->pathname);
781 } else {
sewardj0a400c72005-07-23 09:22:46 +0000782 Int val;
florian1636d332012-11-15 04:27:04 +0000783 Int len = sizeof(val);
rjwalshf5f536f2003-11-17 17:45:00 +0000784
sewardj738856f2009-07-15 14:48:32 +0000785 if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len)
786 == -1) {
787 VG_(message)(Vg_UserMsg, "Open file descriptor %d:\n", i->fd);
rjwalshf5f536f2003-11-17 17:45:00 +0000788 } else {
789 getsockdetails(i->fd);
790 }
791 }
792
793 if(i->where) {
794 VG_(pp_ExeContext)(i->where);
sewardj738856f2009-07-15 14:48:32 +0000795 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000796 } else {
sewardj738856f2009-07-15 14:48:32 +0000797 VG_(message)(Vg_UserMsg, " <inherited from parent>\n");
798 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000799 }
800
801 i = i->next;
802 }
803
sewardj738856f2009-07-15 14:48:32 +0000804 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000805}
806
njn81b975c2009-04-28 05:35:53 +0000807/* If /proc/self/fd doesn't exist (e.g. you've got a Linux kernel that doesn't
808 have /proc support compiled in, or a non-Linux kernel), then we need to
809 find out what file descriptors we inherited from our parent process the
810 hard way - by checking each fd in turn. */
rjwalshf5f536f2003-11-17 17:45:00 +0000811static
njn81b975c2009-04-28 05:35:53 +0000812void init_preopened_fds_without_proc_self_fd(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000813{
814 struct vki_rlimit lim;
sewardj0a400c72005-07-23 09:22:46 +0000815 UInt count;
816 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000817
nethercote620154f2004-11-12 21:21:07 +0000818 if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000819 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
820 an arbitrarily high number. 1024 happens to be the limit in
njn81b975c2009-04-28 05:35:53 +0000821 the 2.4 Linux kernels. */
rjwalshf5f536f2003-11-17 17:45:00 +0000822 count = 1024;
823 } else {
824 count = lim.rlim_cur;
825 }
826
827 for (i = 0; i < count; i++)
njn81b975c2009-04-28 05:35:53 +0000828 if (VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
829 ML_(record_fd_open_named)(-1, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000830}
831
832/* Initialize the list of open file descriptors with the file descriptors
833 we inherited from out parent process. */
834
sewardj1aa40212006-12-11 01:11:02 +0000835void VG_(init_preopened_fds)(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000836{
njnf76d27a2009-05-28 01:53:07 +0000837// DDD: should probably use HAVE_PROC here or similar, instead.
njn81b975c2009-04-28 05:35:53 +0000838#if defined(VGO_linux)
sewardj0a400c72005-07-23 09:22:46 +0000839 Int ret;
rjwalshf5f536f2003-11-17 17:45:00 +0000840 struct vki_dirent d;
sewardj92645592005-07-23 09:18:34 +0000841 SysRes f;
rjwalshf5f536f2003-11-17 17:45:00 +0000842
843 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
njncda2f0f2009-05-18 02:12:08 +0000844 if (sr_isError(f)) {
njn81b975c2009-04-28 05:35:53 +0000845 init_preopened_fds_without_proc_self_fd();
rjwalshf5f536f2003-11-17 17:45:00 +0000846 return;
847 }
848
njncda2f0f2009-05-18 02:12:08 +0000849 while ((ret = VG_(getdents)(sr_Res(f), &d, sizeof(d))) != 0) {
njnf845f8f2005-06-23 02:26:47 +0000850 if (ret == -1)
rjwalshf5f536f2003-11-17 17:45:00 +0000851 goto out;
852
njnf845f8f2005-06-23 02:26:47 +0000853 if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
florian19f91bb2012-11-10 22:29:54 +0000854 HChar* s;
njn83df0b62009-02-25 01:01:05 +0000855 Int fno = VG_(strtoll10)(d.d_name, &s);
856 if (*s == '\0') {
njncda2f0f2009-05-18 02:12:08 +0000857 if (fno != sr_Res(f))
njn83df0b62009-02-25 01:01:05 +0000858 if (VG_(clo_track_fds))
859 ML_(record_fd_open_named)(-1, fno);
860 } else {
861 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +0000862 "Warning: invalid file name in /proc/self/fd: %s\n",
863 d.d_name);
njn83df0b62009-02-25 01:01:05 +0000864 }
rjwalshf5f536f2003-11-17 17:45:00 +0000865 }
866
njncda2f0f2009-05-18 02:12:08 +0000867 VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET);
rjwalshf5f536f2003-11-17 17:45:00 +0000868 }
869
sewardj92645592005-07-23 09:18:34 +0000870 out:
njncda2f0f2009-05-18 02:12:08 +0000871 VG_(close)(sr_Res(f));
njn81b975c2009-04-28 05:35:53 +0000872
njnf76d27a2009-05-28 01:53:07 +0000873#elif defined(VGO_darwin)
874 init_preopened_fds_without_proc_self_fd();
875
njn81b975c2009-04-28 05:35:53 +0000876#else
877# error Unknown OS
878#endif
rjwalshf5f536f2003-11-17 17:45:00 +0000879}
880
sewardjde4a1d02002-03-22 01:27:54 +0000881static
floriane543f302012-10-21 19:43:43 +0000882HChar *strdupcat ( const HChar* cc, const HChar *s1, const HChar *s2,
883 ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000884{
885 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
floriane543f302012-10-21 19:43:43 +0000886 HChar *result = VG_(arena_malloc) ( aid, cc, len );
sewardjde4a1d02002-03-22 01:27:54 +0000887 VG_(strcpy) ( result, s1 );
888 VG_(strcat) ( result, s2 );
889 return result;
890}
891
892static
tom56e1c842005-07-18 22:41:33 +0000893void pre_mem_read_sendmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000894 const HChar *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000895{
floriane543f302012-10-21 19:43:43 +0000896 HChar *outmsg = strdupcat ( "di.syswrap.pmrs.1",
897 "sendmsg", msg, VG_AR_CORE );
nethercoteef0c7662004-11-06 15:38:43 +0000898 PRE_MEM_READ( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000899 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000900}
901
902static
tom56e1c842005-07-18 22:41:33 +0000903void pre_mem_write_recvmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000904 const HChar *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000905{
floriane543f302012-10-21 19:43:43 +0000906 HChar *outmsg = strdupcat ( "di.syswrap.pmwr.1",
907 "recvmsg", msg, VG_AR_CORE );
tom56e1c842005-07-18 22:41:33 +0000908 if ( read )
909 PRE_MEM_READ( outmsg, base, size );
910 else
911 PRE_MEM_WRITE( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000912 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000913}
914
915static
tom56e1c842005-07-18 22:41:33 +0000916void post_mem_write_recvmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000917 const HChar *fieldName, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000918{
tom56e1c842005-07-18 22:41:33 +0000919 if ( !read )
920 POST_MEM_WRITE( base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000921}
922
923static
sewardj8c824512002-04-14 04:16:48 +0000924void msghdr_foreachfield (
toma4991232012-02-10 11:30:09 +0000925 ThreadId tid,
floriane543f302012-10-21 19:43:43 +0000926 const HChar *name,
tom8b3a6092012-02-10 16:45:01 +0000927 struct vki_msghdr *msg,
928 UInt length,
tomfc75e5e2013-02-28 12:50:55 +0000929 void (*foreach_func)( ThreadId, Bool, const HChar *, Addr, SizeT ),
930 Bool recv
sewardj8c824512002-04-14 04:16:48 +0000931 )
sewardjde4a1d02002-03-22 01:27:54 +0000932{
floriane543f302012-10-21 19:43:43 +0000933 HChar *fieldName;
toma4991232012-02-10 11:30:09 +0000934
sewardjde4a1d02002-03-22 01:27:54 +0000935 if ( !msg )
936 return;
937
toma4991232012-02-10 11:30:09 +0000938 fieldName = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.mfef", VG_(strlen)(name) + 32 );
sewardjde4a1d02002-03-22 01:27:54 +0000939
toma4991232012-02-10 11:30:09 +0000940 VG_(sprintf) ( fieldName, "(%s)", name );
941
942 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
943 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
944 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
945 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
946 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
947 foreach_func ( tid, True, fieldName, (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
tomfc75e5e2013-02-28 12:50:55 +0000948
949 /* msg_flags is completely ignored for send_mesg, recv_mesg doesn't read
950 the field, but does write to it. */
951 if ( recv )
952 foreach_func ( tid, False, fieldName, (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
toma4991232012-02-10 11:30:09 +0000953
mjwaa02f662014-05-14 11:35:54 +0000954 if ( ML_(safe_to_deref)(&msg->msg_name, sizeof (void *))
955 && msg->msg_name ) {
toma4991232012-02-10 11:30:09 +0000956 VG_(sprintf) ( fieldName, "(%s.msg_name)", name );
957 foreach_func ( tid, False, fieldName,
sewardjde4a1d02002-03-22 01:27:54 +0000958 (Addr)msg->msg_name, msg->msg_namelen );
toma4991232012-02-10 11:30:09 +0000959 }
sewardjde4a1d02002-03-22 01:27:54 +0000960
mjwaa02f662014-05-14 11:35:54 +0000961 if ( ML_(safe_to_deref)(&msg->msg_iov, sizeof (void *))
962 && msg->msg_iov ) {
nethercote73b526f2004-10-31 18:48:21 +0000963 struct vki_iovec *iov = msg->msg_iov;
sewardjde4a1d02002-03-22 01:27:54 +0000964 UInt i;
965
toma4991232012-02-10 11:30:09 +0000966 VG_(sprintf) ( fieldName, "(%s.msg_iov)", name );
967
968 foreach_func ( tid, True, fieldName,
nethercote73b526f2004-10-31 18:48:21 +0000969 (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
sewardjde4a1d02002-03-22 01:27:54 +0000970
toma4991232012-02-10 11:30:09 +0000971 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov ) {
tom8b3a6092012-02-10 16:45:01 +0000972 UInt iov_len = iov->iov_len <= length ? iov->iov_len : length;
toma4991232012-02-10 11:30:09 +0000973 VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i );
974 foreach_func ( tid, False, fieldName,
tom8b3a6092012-02-10 16:45:01 +0000975 (Addr)iov->iov_base, iov_len );
976 length = length - iov_len;
toma4991232012-02-10 11:30:09 +0000977 }
sewardjde4a1d02002-03-22 01:27:54 +0000978 }
979
mjwaa02f662014-05-14 11:35:54 +0000980 if ( ML_(safe_to_deref) (&msg->msg_control, sizeof (void *))
981 && msg->msg_control )
toma4991232012-02-10 11:30:09 +0000982 {
983 VG_(sprintf) ( fieldName, "(%s.msg_control)", name );
984 foreach_func ( tid, False, fieldName,
sewardjde4a1d02002-03-22 01:27:54 +0000985 (Addr)msg->msg_control, msg->msg_controllen );
toma4991232012-02-10 11:30:09 +0000986 }
987
988 VG_(arena_free) ( VG_AR_CORE, fieldName );
sewardjde4a1d02002-03-22 01:27:54 +0000989}
990
sewardjb5f6f512005-03-10 23:59:00 +0000991static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
rjwalshf5f536f2003-11-17 17:45:00 +0000992{
nethercote73b526f2004-10-31 18:48:21 +0000993 struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
rjwalshf5f536f2003-11-17 17:45:00 +0000994
995 while (cm) {
nethercote73b526f2004-10-31 18:48:21 +0000996 if (cm->cmsg_level == VKI_SOL_SOCKET &&
997 cm->cmsg_type == VKI_SCM_RIGHTS ) {
sewardj0a400c72005-07-23 09:22:46 +0000998 Int *fds = (Int *) VKI_CMSG_DATA(cm);
999 Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
rjwalshf5f536f2003-11-17 17:45:00 +00001000 / sizeof(int);
sewardj0a400c72005-07-23 09:22:46 +00001001 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +00001002
1003 for (i = 0; i < fdc; i++)
1004 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +00001005 // XXX: must we check the range on these fds with
cerion7b2c38c2005-06-23 07:52:54 +00001006 // ML_(fd_allowed)()?
njn096ccdd2009-02-22 23:00:30 +00001007 ML_(record_fd_open_named)(tid, fds[i]);
rjwalshf5f536f2003-11-17 17:45:00 +00001008 }
1009
nethercote73b526f2004-10-31 18:48:21 +00001010 cm = VKI_CMSG_NXTHDR(msg, cm);
rjwalshf5f536f2003-11-17 17:45:00 +00001011 }
1012}
1013
njnf76d27a2009-05-28 01:53:07 +00001014/* GrP kernel ignores sa_len (at least on Darwin); this checks the rest */
sewardjc483e8f2002-05-03 21:01:35 +00001015static
jsgf855d93d2003-10-13 22:26:55 +00001016void pre_mem_read_sockaddr ( ThreadId tid,
floriane543f302012-10-21 19:43:43 +00001017 const HChar *description,
sewardja8d8e232005-06-07 20:04:56 +00001018 struct vki_sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +00001019{
floriane543f302012-10-21 19:43:43 +00001020 HChar *outmsg;
njnff424472009-05-23 01:18:44 +00001021 struct vki_sockaddr_un* sun = (struct vki_sockaddr_un *)sa;
1022 struct vki_sockaddr_in* sin = (struct vki_sockaddr_in *)sa;
1023 struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
mjw4cb663f2013-05-22 10:37:52 +00001024#ifdef VKI_AF_BLUETOOTH
mjwada5ad72013-05-22 10:21:10 +00001025 struct vki_sockaddr_rc* rc = (struct vki_sockaddr_rc *)sa;
mjw4cb663f2013-05-22 10:37:52 +00001026#endif
sewardjff7c1ab2003-02-24 21:55:34 +00001027
1028 /* NULL/zero-length sockaddrs are legal */
1029 if ( sa == NULL || salen == 0 ) return;
1030
sewardj9c606bd2008-09-18 18:12:50 +00001031 outmsg = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.pmr_sockaddr.1",
nethercote73b526f2004-10-31 18:48:21 +00001032 VG_(strlen)( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +00001033
njnff424472009-05-23 01:18:44 +00001034 VG_(sprintf) ( outmsg, description, "sa_family" );
nethercoteef0c7662004-11-06 15:38:43 +00001035 PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +00001036
sewardjc483e8f2002-05-03 21:01:35 +00001037 switch (sa->sa_family) {
1038
nethercote73b526f2004-10-31 18:48:21 +00001039 case VKI_AF_UNIX:
njnff424472009-05-23 01:18:44 +00001040 VG_(sprintf) ( outmsg, description, "sun_path" );
1041 PRE_MEM_RASCIIZ( outmsg, (Addr) sun->sun_path );
njnf76d27a2009-05-28 01:53:07 +00001042 // GrP fixme max of sun_len-2? what about nul char?
sewardjc483e8f2002-05-03 21:01:35 +00001043 break;
1044
nethercote73b526f2004-10-31 18:48:21 +00001045 case VKI_AF_INET:
njnff424472009-05-23 01:18:44 +00001046 VG_(sprintf) ( outmsg, description, "sin_port" );
1047 PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) );
1048 VG_(sprintf) ( outmsg, description, "sin_addr" );
1049 PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) );
sewardjc483e8f2002-05-03 21:01:35 +00001050 break;
1051
nethercote73b526f2004-10-31 18:48:21 +00001052 case VKI_AF_INET6:
njnff424472009-05-23 01:18:44 +00001053 VG_(sprintf) ( outmsg, description, "sin6_port" );
nethercoteef0c7662004-11-06 15:38:43 +00001054 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001055 (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) );
1056 VG_(sprintf) ( outmsg, description, "sin6_flowinfo" );
nethercoteef0c7662004-11-06 15:38:43 +00001057 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001058 (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) );
1059 VG_(sprintf) ( outmsg, description, "sin6_addr" );
nethercoteef0c7662004-11-06 15:38:43 +00001060 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001061 (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) );
1062 VG_(sprintf) ( outmsg, description, "sin6_scope_id" );
nethercoteef0c7662004-11-06 15:38:43 +00001063 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001064 (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) );
sewardjc483e8f2002-05-03 21:01:35 +00001065 break;
mjw4cb663f2013-05-22 10:37:52 +00001066
1067#ifdef VKI_AF_BLUETOOTH
mjwada5ad72013-05-22 10:21:10 +00001068 case VKI_AF_BLUETOOTH:
1069 VG_(sprintf) ( outmsg, description, "rc_bdaddr" );
1070 PRE_MEM_READ( outmsg, (Addr) &rc->rc_bdaddr, sizeof (rc->rc_bdaddr) );
1071 VG_(sprintf) ( outmsg, description, "rc_channel" );
1072 PRE_MEM_READ( outmsg, (Addr) &rc->rc_channel, sizeof (rc->rc_channel) );
1073 break;
mjw4cb663f2013-05-22 10:37:52 +00001074#endif
mjwada5ad72013-05-22 10:21:10 +00001075
sewardjc483e8f2002-05-03 21:01:35 +00001076 default:
1077 VG_(sprintf) ( outmsg, description, "" );
nethercoteef0c7662004-11-06 15:38:43 +00001078 PRE_MEM_READ( outmsg, (Addr) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +00001079 break;
1080 }
1081
njn9f46df62005-03-13 18:11:44 +00001082 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +00001083}
1084
njn25e49d8e72002-09-23 09:36:25 +00001085/* Dereference a pointer to a UInt. */
floriane543f302012-10-21 19:43:43 +00001086static UInt deref_UInt ( ThreadId tid, Addr a, const HChar* s )
njn25e49d8e72002-09-23 09:36:25 +00001087{
1088 UInt* a_p = (UInt*)a;
nethercoteef0c7662004-11-06 15:38:43 +00001089 PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +00001090 if (a_p == NULL)
1091 return 0;
1092 else
1093 return *a_p;
1094}
1095
njnf37a81b2009-02-17 00:23:30 +00001096void ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p,
floriane543f302012-10-21 19:43:43 +00001097 const HChar* buf_s, const HChar* buflen_s )
njn25e49d8e72002-09-23 09:36:25 +00001098{
njn51d827b2005-05-09 01:02:08 +00001099 if (VG_(tdict).track_pre_mem_write) {
njn72718642003-07-24 08:45:32 +00001100 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +00001101 if (buflen_in > 0) {
njncda2f0f2009-05-18 02:12:08 +00001102 VG_(tdict).track_pre_mem_write(
1103 Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +00001104 }
1105 }
1106}
1107
njnf37a81b2009-02-17 00:23:30 +00001108void ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res,
floriane543f302012-10-21 19:43:43 +00001109 Addr buf_p, Addr buflen_p, const HChar* s )
njn25e49d8e72002-09-23 09:36:25 +00001110{
njncda2f0f2009-05-18 02:12:08 +00001111 if (!sr_isError(res) && VG_(tdict).track_post_mem_write) {
njn72718642003-07-24 08:45:32 +00001112 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +00001113 if (buflen_out > 0 && buf_p != (Addr)NULL) {
njn51d827b2005-05-09 01:02:08 +00001114 VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +00001115 }
1116 }
1117}
1118
1119/* ---------------------------------------------------------------------
1120 Data seg end, for brk()
1121 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001122
sewardj45f4e7c2005-09-27 19:20:21 +00001123/* +--------+------------+
1124 | anon | resvn |
1125 +--------+------------+
nethercotece471262004-08-25 13:43:44 +00001126
sewardj45f4e7c2005-09-27 19:20:21 +00001127 ^ ^ ^
1128 | | boundary is page aligned
1129 | VG_(brk_limit) -- no alignment constraint
1130 VG_(brk_base) -- page aligned -- does not move
1131
1132 Both the anon part and the reservation part are always at least
1133 one page.
1134*/
1135
1136/* Set the new data segment end to NEWBRK. If this succeeds, return
1137 NEWBRK, else return the current data segment end. */
1138
1139static Addr do_brk ( Addr newbrk )
1140{
sewardjef1cf8b2006-10-17 01:47:30 +00001141 NSegment const* aseg;
1142 NSegment const* rseg;
sewardj45f4e7c2005-09-27 19:20:21 +00001143 Addr newbrkP;
1144 SizeT delta;
1145 Bool ok;
1146 Bool debug = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001147
1148 if (debug)
barta0b6b2c2008-07-07 06:49:24 +00001149 VG_(printf)("\ndo_brk: brk_base=%#lx brk_limit=%#lx newbrk=%#lx\n",
fitzhardinge98abfc72003-12-16 02:05:15 +00001150 VG_(brk_base), VG_(brk_limit), newbrk);
1151
sewardj79048ce2005-02-18 08:28:32 +00001152# if 0
sewardje517b802005-02-16 01:58:51 +00001153 if (0) show_segments("in_brk");
sewardj79048ce2005-02-18 08:28:32 +00001154# endif
sewardj548be6d2005-02-16 01:31:37 +00001155
sewardj45f4e7c2005-09-27 19:20:21 +00001156 if (newbrk < VG_(brk_base))
1157 /* Clearly impossible. */
1158 goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +00001159
sewardj45f4e7c2005-09-27 19:20:21 +00001160 if (newbrk >= VG_(brk_base) && newbrk < VG_(brk_limit)) {
1161 /* shrinking the data segment. Be lazy and don't munmap the
1162 excess area. */
sewardjef1cf8b2006-10-17 01:47:30 +00001163 NSegment const * seg = VG_(am_find_nsegment)(newbrk);
sewardj45f4e7c2005-09-27 19:20:21 +00001164 if (seg && seg->hasT)
1165 VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
1166 "do_brk(shrink)" );
sewardjd2d241b2006-02-14 11:37:41 +00001167 /* Since we're being lazy and not unmapping pages, we have to
1168 zero out the area, so that if the area later comes back into
1169 circulation, it will be filled with zeroes, as if it really
1170 had been unmapped and later remapped. Be a bit paranoid and
1171 try hard to ensure we're not going to segfault by doing the
1172 write - check both ends of the range are in the same segment
1173 and that segment is writable. */
1174 if (seg) {
1175 /* pre: newbrk < VG_(brk_limit)
1176 => newbrk <= VG_(brk_limit)-1 */
sewardjef1cf8b2006-10-17 01:47:30 +00001177 NSegment const * seg2;
sewardjd2d241b2006-02-14 11:37:41 +00001178 vg_assert(newbrk < VG_(brk_limit));
1179 seg2 = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
1180 if (seg2 && seg == seg2 && seg->hasW)
1181 VG_(memset)( (void*)newbrk, 0, VG_(brk_limit) - newbrk );
1182 }
1183
sewardj45f4e7c2005-09-27 19:20:21 +00001184 VG_(brk_limit) = newbrk;
1185 return newbrk;
1186 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001187
sewardj45f4e7c2005-09-27 19:20:21 +00001188 /* otherwise we're expanding the brk segment. */
tom8e5963d2005-10-06 14:49:21 +00001189 if (VG_(brk_limit) > VG_(brk_base))
1190 aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
1191 else
1192 aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
florian3e798632012-11-24 19:41:54 +00001193 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
fitzhardinge98abfc72003-12-16 02:05:15 +00001194
sewardj45f4e7c2005-09-27 19:20:21 +00001195 /* These should be assured by setup_client_dataseg in m_main. */
1196 vg_assert(aseg);
1197 vg_assert(rseg);
1198 vg_assert(aseg->kind == SkAnonC);
1199 vg_assert(rseg->kind == SkResvn);
1200 vg_assert(aseg->end+1 == rseg->start);
fitzhardinge98abfc72003-12-16 02:05:15 +00001201
sewardj45f4e7c2005-09-27 19:20:21 +00001202 vg_assert(newbrk >= VG_(brk_base));
1203 if (newbrk <= rseg->start) {
1204 /* still fits within the anon segment. */
1205 VG_(brk_limit) = newbrk;
1206 return newbrk;
1207 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001208
tom02f75332006-06-21 08:01:14 +00001209 if (newbrk > rseg->end+1 - VKI_PAGE_SIZE) {
sewardj45f4e7c2005-09-27 19:20:21 +00001210 /* request is too large -- the resvn would fall below 1 page,
1211 which isn't allowed. */
1212 goto bad;
1213 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001214
sewardj45f4e7c2005-09-27 19:20:21 +00001215 newbrkP = VG_PGROUNDUP(newbrk);
tom02f75332006-06-21 08:01:14 +00001216 vg_assert(newbrkP > rseg->start && newbrkP <= rseg->end+1 - VKI_PAGE_SIZE);
sewardj45f4e7c2005-09-27 19:20:21 +00001217 delta = newbrkP - rseg->start;
1218 vg_assert(delta > 0);
1219 vg_assert(VG_IS_PAGE_ALIGNED(delta));
1220
florian3e798632012-11-24 19:41:54 +00001221 ok = VG_(am_extend_into_adjacent_reservation_client)( aseg, delta );
sewardj45f4e7c2005-09-27 19:20:21 +00001222 if (!ok) goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +00001223
sewardj45f4e7c2005-09-27 19:20:21 +00001224 VG_(brk_limit) = newbrk;
1225 return newbrk;
fitzhardinge98abfc72003-12-16 02:05:15 +00001226
sewardj45f4e7c2005-09-27 19:20:21 +00001227 bad:
1228 return VG_(brk_limit);
fitzhardinge98abfc72003-12-16 02:05:15 +00001229}
1230
1231
njn25e49d8e72002-09-23 09:36:25 +00001232/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00001233 Vet file descriptors for sanity
1234 ------------------------------------------------------------------ */
sewardj04236902005-10-04 22:27:22 +00001235/*
1236> - what does the "Bool soft" parameter mean?
1237
1238(Tom Hughes, 3 Oct 05):
1239
1240Whether or not to consider a file descriptor invalid if it is above
1241the current soft limit.
1242
1243Basically if we are testing whether a newly created file descriptor is
1244valid (in a post handler) then we set soft to true, and if we are
1245testing whether a file descriptor that is about to be used (in a pre
1246handler) is valid [viz, an already-existing fd] then we set it to false.
1247
1248The point is that if the (virtual) soft limit is lowered then any
1249existing descriptors can still be read/written/closed etc (so long as
1250they are below the valgrind reserved descriptors) but no new
1251descriptors can be created above the new soft limit.
1252
1253(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
1254*/
jsgf855d93d2003-10-13 22:26:55 +00001255
1256/* Return true if we're allowed to use or create this fd */
floriane543f302012-10-21 19:43:43 +00001257Bool ML_(fd_allowed)(Int fd, const HChar *syscallname, ThreadId tid,
1258 Bool isNewFd)
jsgf855d93d2003-10-13 22:26:55 +00001259{
sewardj04236902005-10-04 22:27:22 +00001260 Bool allowed = True;
1261
1262 /* hard limits always apply */
1263 if (fd < 0 || fd >= VG_(fd_hard_limit))
1264 allowed = False;
1265
sewardj738856f2009-07-15 14:48:32 +00001266 /* hijacking the output fds is never allowed */
1267 if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd)
sewardj04236902005-10-04 22:27:22 +00001268 allowed = False;
1269
1270 /* if creating a new fd (rather than using an existing one), the
1271 soft limit must also be observed */
1272 if (isNewFd && fd >= VG_(fd_soft_limit))
1273 allowed = False;
1274
1275 /* this looks like it ought to be included, but causes problems: */
1276 /*
1277 if (fd == 2 && VG_(debugLog_getLevel)() > 0)
1278 allowed = False;
1279 */
1280 /* The difficulty is as follows: consider a program P which expects
1281 to be able to mess with (redirect) its own stderr (fd 2).
1282 Usually to deal with P we would issue command line flags to send
1283 logging somewhere other than stderr, so as not to disrupt P.
1284 The problem is that -d unilaterally hijacks stderr with no
1285 consultation with P. And so, if this check is enabled, P will
1286 work OK normally but fail if -d is issued.
1287
1288 Basically -d is a hack and you take your chances when using it.
1289 It's very useful for low level debugging -- particularly at
1290 startup -- and having its presence change the behaviour of the
1291 client is exactly what we don't want. */
1292
1293 /* croak? */
1294 if ((!allowed) && VG_(showing_core_errors)() ) {
jsewardd9320a42003-12-12 06:40:05 +00001295 VG_(message)(Vg_UserMsg,
sewardj738856f2009-07-15 14:48:32 +00001296 "Warning: invalid file descriptor %d in syscall %s()\n",
nethercote1543adf2004-10-25 15:43:21 +00001297 fd, syscallname);
sewardj738856f2009-07-15 14:48:32 +00001298 if (fd == VG_(log_output_sink).fd && VG_(log_output_sink).fd >= 0)
jsewardd9320a42003-12-12 06:40:05 +00001299 VG_(message)(Vg_UserMsg,
sewardj738856f2009-07-15 14:48:32 +00001300 " Use --log-fd=<number> to select an alternative log fd.\n");
1301 if (fd == VG_(xml_output_sink).fd && VG_(xml_output_sink).fd >= 0)
1302 VG_(message)(Vg_UserMsg,
1303 " Use --xml-fd=<number> to select an alternative XML "
1304 "output fd.\n");
njneb04c892009-05-22 07:09:03 +00001305 // DDD: consider always printing this stack trace, it's useful.
1306 // Also consider also making this a proper core error, ie.
1307 // suppressible and all that.
jsgf855d93d2003-10-13 22:26:55 +00001308 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +00001309 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
jsgf855d93d2003-10-13 22:26:55 +00001310 }
jsgf855d93d2003-10-13 22:26:55 +00001311 }
sewardj04236902005-10-04 22:27:22 +00001312
1313 return allowed;
jsgf855d93d2003-10-13 22:26:55 +00001314}
1315
1316
1317/* ---------------------------------------------------------------------
sewardj9efbbef2005-03-01 16:45:23 +00001318 Deal with a bunch of socket-related syscalls
1319 ------------------------------------------------------------------ */
1320
1321/* ------ */
1322
sewardj987a8eb2005-03-01 19:00:30 +00001323void
sewardj7eb7c582005-06-23 01:02:53 +00001324ML_(generic_PRE_sys_socketpair) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001325 UWord arg0, UWord arg1,
1326 UWord arg2, UWord arg3 )
1327{
1328 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1329 PRE_MEM_WRITE( "socketcall.socketpair(sv)",
1330 arg3, 2*sizeof(int) );
1331}
1332
sewardja8d8e232005-06-07 20:04:56 +00001333SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001334ML_(generic_POST_sys_socketpair) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001335 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001336 UWord arg0, UWord arg1,
1337 UWord arg2, UWord arg3 )
sewardj9efbbef2005-03-01 16:45:23 +00001338{
sewardja8d8e232005-06-07 20:04:56 +00001339 SysRes r = res;
sewardj9efbbef2005-03-01 16:45:23 +00001340 Int fd1 = ((Int*)arg3)[0];
1341 Int fd2 = ((Int*)arg3)[1];
njncda2f0f2009-05-18 02:12:08 +00001342 vg_assert(!sr_isError(res)); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001343 POST_MEM_WRITE( arg3, 2*sizeof(int) );
sewardj7eb7c582005-06-23 01:02:53 +00001344 if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
1345 !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
sewardj9efbbef2005-03-01 16:45:23 +00001346 VG_(close)(fd1);
1347 VG_(close)(fd2);
sewardja8d8e232005-06-07 20:04:56 +00001348 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001349 } else {
1350 POST_MEM_WRITE( arg3, 2*sizeof(int) );
1351 if (VG_(clo_track_fds)) {
njnf845f8f2005-06-23 02:26:47 +00001352 ML_(record_fd_open_nameless)(tid, fd1);
1353 ML_(record_fd_open_nameless)(tid, fd2);
sewardj9efbbef2005-03-01 16:45:23 +00001354 }
1355 }
1356 return r;
1357}
1358
1359/* ------ */
1360
sewardja8d8e232005-06-07 20:04:56 +00001361SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001362ML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
sewardj9efbbef2005-03-01 16:45:23 +00001363{
sewardja8d8e232005-06-07 20:04:56 +00001364 SysRes r = res;
njncda2f0f2009-05-18 02:12:08 +00001365 vg_assert(!sr_isError(res)); /* guaranteed by caller */
1366 if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) {
1367 VG_(close)(sr_Res(res));
sewardja8d8e232005-06-07 20:04:56 +00001368 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001369 } else {
1370 if (VG_(clo_track_fds))
njncda2f0f2009-05-18 02:12:08 +00001371 ML_(record_fd_open_nameless)(tid, sr_Res(res));
sewardj9efbbef2005-03-01 16:45:23 +00001372 }
1373 return r;
1374}
1375
1376/* ------ */
1377
sewardj987a8eb2005-03-01 19:00:30 +00001378void
sewardj7eb7c582005-06-23 01:02:53 +00001379ML_(generic_PRE_sys_bind) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001380 UWord arg0, UWord arg1, UWord arg2 )
1381{
1382 /* int bind(int sockfd, struct sockaddr *my_addr,
1383 int addrlen); */
1384 pre_mem_read_sockaddr(
1385 tid, "socketcall.bind(my_addr.%s)",
1386 (struct vki_sockaddr *) arg1, arg2
1387 );
1388}
1389
1390/* ------ */
1391
sewardj987a8eb2005-03-01 19:00:30 +00001392void
sewardj7eb7c582005-06-23 01:02:53 +00001393ML_(generic_PRE_sys_accept) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001394 UWord arg0, UWord arg1, UWord arg2 )
1395{
1396 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1397 Addr addr_p = arg1;
1398 Addr addrlen_p = arg2;
1399 if (addr_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001400 ML_(buf_and_len_pre_check) ( tid, addr_p, addrlen_p,
1401 "socketcall.accept(addr)",
1402 "socketcall.accept(addrlen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001403}
1404
sewardja8d8e232005-06-07 20:04:56 +00001405SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001406ML_(generic_POST_sys_accept) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001407 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001408 UWord arg0, UWord arg1, UWord arg2 )
sewardj9efbbef2005-03-01 16:45:23 +00001409{
sewardja8d8e232005-06-07 20:04:56 +00001410 SysRes r = res;
njncda2f0f2009-05-18 02:12:08 +00001411 vg_assert(!sr_isError(res)); /* guaranteed by caller */
1412 if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) {
1413 VG_(close)(sr_Res(res));
sewardja8d8e232005-06-07 20:04:56 +00001414 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001415 } else {
1416 Addr addr_p = arg1;
1417 Addr addrlen_p = arg2;
1418 if (addr_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001419 ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p,
1420 "socketcall.accept(addrlen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001421 if (VG_(clo_track_fds))
njncda2f0f2009-05-18 02:12:08 +00001422 ML_(record_fd_open_nameless)(tid, sr_Res(res));
sewardj9efbbef2005-03-01 16:45:23 +00001423 }
1424 return r;
1425}
1426
1427/* ------ */
1428
sewardj987a8eb2005-03-01 19:00:30 +00001429void
sewardj7eb7c582005-06-23 01:02:53 +00001430ML_(generic_PRE_sys_sendto) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001431 UWord arg0, UWord arg1, UWord arg2,
1432 UWord arg3, UWord arg4, UWord arg5 )
1433{
1434 /* int sendto(int s, const void *msg, int len,
1435 unsigned int flags,
1436 const struct sockaddr *to, int tolen); */
1437 PRE_MEM_READ( "socketcall.sendto(msg)",
1438 arg1, /* msg */
1439 arg2 /* len */ );
1440 pre_mem_read_sockaddr(
1441 tid, "socketcall.sendto(to.%s)",
1442 (struct vki_sockaddr *) arg4, arg5
1443 );
1444}
1445
1446/* ------ */
1447
sewardj987a8eb2005-03-01 19:00:30 +00001448void
sewardj7eb7c582005-06-23 01:02:53 +00001449ML_(generic_PRE_sys_send) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001450 UWord arg0, UWord arg1, UWord arg2 )
1451{
1452 /* int send(int s, const void *msg, size_t len, int flags); */
1453 PRE_MEM_READ( "socketcall.send(msg)",
1454 arg1, /* msg */
1455 arg2 /* len */ );
1456
1457}
1458
1459/* ------ */
1460
sewardj987a8eb2005-03-01 19:00:30 +00001461void
sewardj7eb7c582005-06-23 01:02:53 +00001462ML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001463 UWord arg0, UWord arg1, UWord arg2,
1464 UWord arg3, UWord arg4, UWord arg5 )
1465{
1466 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1467 struct sockaddr *from, int *fromlen); */
1468 Addr buf_p = arg1;
1469 Int len = arg2;
1470 Addr from_p = arg4;
1471 Addr fromlen_p = arg5;
1472 PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
1473 if (from_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001474 ML_(buf_and_len_pre_check) ( tid, from_p, fromlen_p,
1475 "socketcall.recvfrom(from)",
1476 "socketcall.recvfrom(fromlen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001477}
1478
sewardj987a8eb2005-03-01 19:00:30 +00001479void
sewardj7eb7c582005-06-23 01:02:53 +00001480ML_(generic_POST_sys_recvfrom) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001481 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001482 UWord arg0, UWord arg1, UWord arg2,
1483 UWord arg3, UWord arg4, UWord arg5 )
1484{
1485 Addr buf_p = arg1;
1486 Int len = arg2;
1487 Addr from_p = arg4;
1488 Addr fromlen_p = arg5;
1489
njncda2f0f2009-05-18 02:12:08 +00001490 vg_assert(!sr_isError(res)); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001491 if (from_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001492 ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p,
1493 "socketcall.recvfrom(fromlen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001494 POST_MEM_WRITE( buf_p, len );
1495}
1496
1497/* ------ */
1498
sewardj987a8eb2005-03-01 19:00:30 +00001499void
sewardj7eb7c582005-06-23 01:02:53 +00001500ML_(generic_PRE_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001501 UWord arg0, UWord arg1, UWord arg2 )
1502{
1503 /* int recv(int s, void *buf, int len, unsigned int flags); */
1504 /* man 2 recv says:
1505 The recv call is normally used only on a connected socket
1506 (see connect(2)) and is identical to recvfrom with a NULL
1507 from parameter.
1508 */
1509 PRE_MEM_WRITE( "socketcall.recv(buf)",
1510 arg1, /* buf */
1511 arg2 /* len */ );
1512}
1513
sewardj987a8eb2005-03-01 19:00:30 +00001514void
sewardj7eb7c582005-06-23 01:02:53 +00001515ML_(generic_POST_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001516 UWord res,
1517 UWord arg0, UWord arg1, UWord arg2 )
1518{
1519 if (res >= 0 && arg1 != 0) {
1520 POST_MEM_WRITE( arg1, /* buf */
1521 arg2 /* len */ );
1522 }
1523}
1524
1525/* ------ */
1526
sewardj987a8eb2005-03-01 19:00:30 +00001527void
sewardj7eb7c582005-06-23 01:02:53 +00001528ML_(generic_PRE_sys_connect) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001529 UWord arg0, UWord arg1, UWord arg2 )
1530{
1531 /* int connect(int sockfd,
1532 struct sockaddr *serv_addr, int addrlen ); */
sewardj9efbbef2005-03-01 16:45:23 +00001533 pre_mem_read_sockaddr( tid,
1534 "socketcall.connect(serv_addr.%s)",
1535 (struct vki_sockaddr *) arg1, arg2);
1536}
1537
1538/* ------ */
1539
sewardj987a8eb2005-03-01 19:00:30 +00001540void
sewardj7eb7c582005-06-23 01:02:53 +00001541ML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001542 UWord arg0, UWord arg1, UWord arg2,
1543 UWord arg3, UWord arg4 )
1544{
1545 /* int setsockopt(int s, int level, int optname,
1546 const void *optval, int optlen); */
1547 PRE_MEM_READ( "socketcall.setsockopt(optval)",
1548 arg3, /* optval */
1549 arg4 /* optlen */ );
1550}
1551
1552/* ------ */
1553
sewardj987a8eb2005-03-01 19:00:30 +00001554void
sewardj7eb7c582005-06-23 01:02:53 +00001555ML_(generic_PRE_sys_getsockname) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001556 UWord arg0, UWord arg1, UWord arg2 )
1557{
1558 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1559 Addr name_p = arg1;
1560 Addr namelen_p = arg2;
1561 /* Nb: name_p cannot be NULL */
njnf37a81b2009-02-17 00:23:30 +00001562 ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1563 "socketcall.getsockname(name)",
1564 "socketcall.getsockname(namelen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001565}
1566
sewardj987a8eb2005-03-01 19:00:30 +00001567void
sewardj7eb7c582005-06-23 01:02:53 +00001568ML_(generic_POST_sys_getsockname) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001569 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001570 UWord arg0, UWord arg1, UWord arg2 )
1571{
1572 Addr name_p = arg1;
1573 Addr namelen_p = arg2;
njncda2f0f2009-05-18 02:12:08 +00001574 vg_assert(!sr_isError(res)); /* guaranteed by caller */
njnf37a81b2009-02-17 00:23:30 +00001575 ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1576 "socketcall.getsockname(namelen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001577}
1578
1579/* ------ */
1580
sewardj987a8eb2005-03-01 19:00:30 +00001581void
sewardj7eb7c582005-06-23 01:02:53 +00001582ML_(generic_PRE_sys_getpeername) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001583 UWord arg0, UWord arg1, UWord arg2 )
1584{
1585 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1586 Addr name_p = arg1;
1587 Addr namelen_p = arg2;
1588 /* Nb: name_p cannot be NULL */
njnf37a81b2009-02-17 00:23:30 +00001589 ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1590 "socketcall.getpeername(name)",
1591 "socketcall.getpeername(namelen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001592}
1593
sewardj987a8eb2005-03-01 19:00:30 +00001594void
sewardj7eb7c582005-06-23 01:02:53 +00001595ML_(generic_POST_sys_getpeername) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001596 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001597 UWord arg0, UWord arg1, UWord arg2 )
1598{
1599 Addr name_p = arg1;
1600 Addr namelen_p = arg2;
njncda2f0f2009-05-18 02:12:08 +00001601 vg_assert(!sr_isError(res)); /* guaranteed by caller */
njnf37a81b2009-02-17 00:23:30 +00001602 ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1603 "socketcall.getpeername(namelen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001604}
1605
1606/* ------ */
1607
sewardj987a8eb2005-03-01 19:00:30 +00001608void
floriane543f302012-10-21 19:43:43 +00001609ML_(generic_PRE_sys_sendmsg) ( ThreadId tid, const HChar *name,
1610 struct vki_msghdr *msg )
sewardj9efbbef2005-03-01 16:45:23 +00001611{
tomfc75e5e2013-02-28 12:50:55 +00001612 msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_read_sendmsg, False );
sewardj9efbbef2005-03-01 16:45:23 +00001613}
1614
1615/* ------ */
1616
sewardj987a8eb2005-03-01 19:00:30 +00001617void
floriane543f302012-10-21 19:43:43 +00001618ML_(generic_PRE_sys_recvmsg) ( ThreadId tid, const HChar *name,
1619 struct vki_msghdr *msg )
sewardj9efbbef2005-03-01 16:45:23 +00001620{
tomfc75e5e2013-02-28 12:50:55 +00001621 msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_write_recvmsg, True );
sewardj9efbbef2005-03-01 16:45:23 +00001622}
1623
sewardj987a8eb2005-03-01 19:00:30 +00001624void
floriane543f302012-10-21 19:43:43 +00001625ML_(generic_POST_sys_recvmsg) ( ThreadId tid, const HChar *name,
1626 struct vki_msghdr *msg, UInt length )
sewardj9efbbef2005-03-01 16:45:23 +00001627{
tomfc75e5e2013-02-28 12:50:55 +00001628 msghdr_foreachfield( tid, name, msg, length, post_mem_write_recvmsg, True );
sewardj9efbbef2005-03-01 16:45:23 +00001629 check_cmsg_for_fds( tid, msg );
1630}
1631
1632
1633/* ---------------------------------------------------------------------
sewardjb369c5e2005-03-24 17:52:02 +00001634 Deal with a bunch of IPC related syscalls
1635 ------------------------------------------------------------------ */
1636
1637/* ------ */
1638
1639void
sewardj7eb7c582005-06-23 01:02:53 +00001640ML_(generic_PRE_sys_semop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001641 UWord arg0, UWord arg1, UWord arg2 )
1642{
1643 /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1644 PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1645}
1646
1647/* ------ */
1648
1649void
sewardj7eb7c582005-06-23 01:02:53 +00001650ML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001651 UWord arg0, UWord arg1,
1652 UWord arg2, UWord arg3 )
1653{
1654 /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1655 struct timespec *timeout); */
1656 PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1657 if (arg3 != 0)
1658 PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1659}
1660
1661/* ------ */
1662
1663static
1664UInt get_sem_count( Int semid )
1665{
sewardja8d8e232005-06-07 20:04:56 +00001666 struct vki_semid_ds buf;
1667 union vki_semun arg;
1668 SysRes res;
sewardjb369c5e2005-03-24 17:52:02 +00001669
sewardj27f96b32008-10-23 09:46:59 +00001670 /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017
1671 (experimental) otherwise complains that the use in the return
1672 statement below is uninitialised. */
1673 buf.sem_nsems = 0;
1674
sewardja8d8e232005-06-07 20:04:56 +00001675 arg.buf = &buf;
sewardjb369c5e2005-03-24 17:52:02 +00001676
sewardja8d8e232005-06-07 20:04:56 +00001677# ifdef __NR_semctl
1678 res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
1679# else
1680 res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1681 VKI_IPC_STAT, (UWord)&arg);
sewardj27f96b32008-10-23 09:46:59 +00001682# endif
njncda2f0f2009-05-18 02:12:08 +00001683 if (sr_isError(res))
sewardja8d8e232005-06-07 20:04:56 +00001684 return 0;
sewardjb369c5e2005-03-24 17:52:02 +00001685
sewardja8d8e232005-06-07 20:04:56 +00001686 return buf.sem_nsems;
sewardjb369c5e2005-03-24 17:52:02 +00001687}
1688
1689void
sewardj7eb7c582005-06-23 01:02:53 +00001690ML_(generic_PRE_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001691 UWord arg0, UWord arg1,
1692 UWord arg2, UWord arg3 )
1693{
1694 /* int semctl(int semid, int semnum, int cmd, ...); */
1695 union vki_semun arg = *(union vki_semun *)&arg3;
1696 UInt nsems;
1697 switch (arg2 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00001698#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001699 case VKI_IPC_INFO:
1700 case VKI_SEM_INFO:
1701 case VKI_IPC_INFO|VKI_IPC_64:
1702 case VKI_SEM_INFO|VKI_IPC_64:
1703 PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1704 (Addr)arg.buf, sizeof(struct vki_seminfo) );
1705 break;
njnf76d27a2009-05-28 01:53:07 +00001706#endif
1707
sewardjb369c5e2005-03-24 17:52:02 +00001708 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00001709#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001710 case VKI_SEM_STAT:
njnf76d27a2009-05-28 01:53:07 +00001711#endif
sewardjb369c5e2005-03-24 17:52:02 +00001712 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1713 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1714 break;
njnf76d27a2009-05-28 01:53:07 +00001715
1716#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001717 case VKI_IPC_STAT|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001718#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001719 case VKI_SEM_STAT|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001720#endif
sewardjb369c5e2005-03-24 17:52:02 +00001721 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1722 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1723 break;
njnf76d27a2009-05-28 01:53:07 +00001724#endif
1725
sewardjb369c5e2005-03-24 17:52:02 +00001726 case VKI_IPC_SET:
1727 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1728 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1729 break;
njnf76d27a2009-05-28 01:53:07 +00001730
1731#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001732 case VKI_IPC_SET|VKI_IPC_64:
1733 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1734 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1735 break;
njnf76d27a2009-05-28 01:53:07 +00001736#endif
1737
sewardjb369c5e2005-03-24 17:52:02 +00001738 case VKI_GETALL:
njnf76d27a2009-05-28 01:53:07 +00001739#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001740 case VKI_GETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001741#endif
sewardjb369c5e2005-03-24 17:52:02 +00001742 nsems = get_sem_count( arg0 );
1743 PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1744 (Addr)arg.array, sizeof(unsigned short) * nsems );
1745 break;
njnf76d27a2009-05-28 01:53:07 +00001746
sewardjb369c5e2005-03-24 17:52:02 +00001747 case VKI_SETALL:
njnf76d27a2009-05-28 01:53:07 +00001748#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001749 case VKI_SETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001750#endif
sewardjb369c5e2005-03-24 17:52:02 +00001751 nsems = get_sem_count( arg0 );
1752 PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1753 (Addr)arg.array, sizeof(unsigned short) * nsems );
1754 break;
1755 }
1756}
1757
1758void
sewardj7eb7c582005-06-23 01:02:53 +00001759ML_(generic_POST_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001760 UWord res,
1761 UWord arg0, UWord arg1,
1762 UWord arg2, UWord arg3 )
1763{
1764 union vki_semun arg = *(union vki_semun *)&arg3;
1765 UInt nsems;
1766 switch (arg2 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00001767#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001768 case VKI_IPC_INFO:
1769 case VKI_SEM_INFO:
1770 case VKI_IPC_INFO|VKI_IPC_64:
1771 case VKI_SEM_INFO|VKI_IPC_64:
1772 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1773 break;
njnf76d27a2009-05-28 01:53:07 +00001774#endif
1775
sewardjb369c5e2005-03-24 17:52:02 +00001776 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00001777#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001778 case VKI_SEM_STAT:
njnf76d27a2009-05-28 01:53:07 +00001779#endif
sewardjb369c5e2005-03-24 17:52:02 +00001780 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1781 break;
njnf76d27a2009-05-28 01:53:07 +00001782
1783#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001784 case VKI_IPC_STAT|VKI_IPC_64:
1785 case VKI_SEM_STAT|VKI_IPC_64:
1786 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1787 break;
njnf76d27a2009-05-28 01:53:07 +00001788#endif
1789
sewardjb369c5e2005-03-24 17:52:02 +00001790 case VKI_GETALL:
njnf76d27a2009-05-28 01:53:07 +00001791#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001792 case VKI_GETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001793#endif
sewardjb369c5e2005-03-24 17:52:02 +00001794 nsems = get_sem_count( arg0 );
1795 POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1796 break;
1797 }
1798}
1799
1800/* ------ */
1801
sewardjb369c5e2005-03-24 17:52:02 +00001802/* ------ */
1803
1804static
philippe2d75ea22012-08-16 19:40:52 +00001805SizeT get_shm_size ( Int shmid )
sewardjb369c5e2005-03-24 17:52:02 +00001806{
njncda2f0f2009-05-18 02:12:08 +00001807#ifdef __NR_shmctl
1808# ifdef VKI_IPC_64
sewardjb369c5e2005-03-24 17:52:02 +00001809 struct vki_shmid64_ds buf;
sewardj90741b22010-10-06 12:59:44 +00001810# ifdef VGP_amd64_linux
1811 /* See bug 222545 comment 7 */
1812 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1813 VKI_IPC_STAT, (UWord)&buf);
1814# else
1815 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1816 VKI_IPC_STAT|VKI_IPC_64, (UWord)&buf);
1817# endif
1818# else /* !def VKI_IPC_64 */
sewardjb369c5e2005-03-24 17:52:02 +00001819 struct vki_shmid_ds buf;
njncda2f0f2009-05-18 02:12:08 +00001820 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
sewardj90741b22010-10-06 12:59:44 +00001821# endif /* def VKI_IPC_64 */
njncda2f0f2009-05-18 02:12:08 +00001822#else
1823 struct vki_shmid_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001824 SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
sewardjb369c5e2005-03-24 17:52:02 +00001825 VKI_IPC_STAT, 0, (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +00001826#endif
1827 if (sr_isError(__res))
sewardjb369c5e2005-03-24 17:52:02 +00001828 return 0;
1829
philippe2d75ea22012-08-16 19:40:52 +00001830 return (SizeT) buf.shm_segsz;
sewardjb369c5e2005-03-24 17:52:02 +00001831}
1832
1833UWord
sewardj7eb7c582005-06-23 01:02:53 +00001834ML_(generic_PRE_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001835 UWord arg0, UWord arg1, UWord arg2 )
1836{
1837 /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
philippe2d75ea22012-08-16 19:40:52 +00001838 SizeT segmentSize = get_shm_size ( arg0 );
sewardj45f4e7c2005-09-27 19:20:21 +00001839 UWord tmp;
1840 Bool ok;
1841 if (arg1 == 0) {
sewardj60457092010-10-06 15:24:39 +00001842 /* arm-linux only: work around the fact that
1843 VG_(am_get_advisory_client_simple) produces something that is
1844 VKI_PAGE_SIZE aligned, whereas what we want is something
1845 VKI_SHMLBA aligned, and VKI_SHMLBA >= VKI_PAGE_SIZE. Hence
1846 increase the request size by VKI_SHMLBA - VKI_PAGE_SIZE and
1847 then round the result up to the next VKI_SHMLBA boundary.
1848 See bug 222545 comment 15. So far, arm-linux is the only
1849 platform where this is known to be necessary. */
1850 vg_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
1851 if (VKI_SHMLBA > VKI_PAGE_SIZE) {
1852 segmentSize += VKI_SHMLBA - VKI_PAGE_SIZE;
1853 }
sewardj45f4e7c2005-09-27 19:20:21 +00001854 tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
sewardj60457092010-10-06 15:24:39 +00001855 if (ok) {
1856 if (VKI_SHMLBA > VKI_PAGE_SIZE) {
1857 arg1 = VG_ROUNDUP(tmp, VKI_SHMLBA);
1858 } else {
1859 arg1 = tmp;
1860 }
1861 }
sewardj45f4e7c2005-09-27 19:20:21 +00001862 }
sewardj7eb7c582005-06-23 01:02:53 +00001863 else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
sewardjb369c5e2005-03-24 17:52:02 +00001864 arg1 = 0;
1865 return arg1;
1866}
1867
1868void
sewardj7eb7c582005-06-23 01:02:53 +00001869ML_(generic_POST_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001870 UWord res,
1871 UWord arg0, UWord arg1, UWord arg2 )
1872{
philippe2d75ea22012-08-16 19:40:52 +00001873 SizeT segmentSize = VG_PGROUNDUP(get_shm_size(arg0));
sewardjb369c5e2005-03-24 17:52:02 +00001874 if ( segmentSize > 0 ) {
1875 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001876 Bool d;
sewardjb369c5e2005-03-24 17:52:02 +00001877
tomf61fea02005-10-04 12:04:06 +00001878 if (arg2 & VKI_SHM_RDONLY)
sewardjb369c5e2005-03-24 17:52:02 +00001879 prot &= ~VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001880 /* It isn't exactly correct to pass 0 for the fd and offset
1881 here. The kernel seems to think the corresponding section
1882 does have dev/ino numbers:
1883
1884 04e52000-04ec8000 rw-s 00000000 00:06 1966090 /SYSV00000000 (deleted)
1885
1886 However there is no obvious way to find them. In order to
1887 cope with the discrepancy, aspacem's sync checker omits the
1888 dev/ino correspondence check in cases where V does not know
1889 the dev/ino. */
njnc6fe8a22010-12-08 02:51:43 +00001890 d = VG_(am_notify_client_shmat)( res, segmentSize, prot );
sewardj45f4e7c2005-09-27 19:20:21 +00001891
1892 /* we don't distinguish whether it's read-only or
1893 * read-write -- it doesn't matter really. */
sewardj9c606bd2008-09-18 18:12:50 +00001894 VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False,
1895 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00001896 if (d)
1897 VG_(discard_translations)( (Addr64)res,
1898 (ULong)VG_PGROUNDUP(segmentSize),
1899 "ML_(generic_POST_sys_shmat)" );
sewardjb369c5e2005-03-24 17:52:02 +00001900 }
1901}
1902
1903/* ------ */
1904
1905Bool
sewardj7eb7c582005-06-23 01:02:53 +00001906ML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001907{
1908 /* int shmdt(const void *shmaddr); */
sewardj7eb7c582005-06-23 01:02:53 +00001909 return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
sewardjb369c5e2005-03-24 17:52:02 +00001910}
1911
1912void
sewardj7eb7c582005-06-23 01:02:53 +00001913ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001914{
sewardjef1cf8b2006-10-17 01:47:30 +00001915 NSegment const* s = VG_(am_find_nsegment)(arg0);
sewardjb369c5e2005-03-24 17:52:02 +00001916
sewardj0e682c62005-09-28 20:05:31 +00001917 if (s != NULL) {
1918 Addr s_start = s->start;
1919 SizeT s_len = s->end+1 - s->start;
tom1340c352005-10-04 15:59:54 +00001920 Bool d;
1921
dirk7bc57fc2006-04-27 11:05:13 +00001922 vg_assert(s->kind == SkShmC);
1923 vg_assert(s->start == arg0);
tom1340c352005-10-04 15:59:54 +00001924
1925 d = VG_(am_notify_munmap)(s_start, s_len);
sewardj0e682c62005-09-28 20:05:31 +00001926 s = NULL; /* s is now invalid */
1927 VG_TRACK( die_mem_munmap, s_start, s_len );
sewardj45f4e7c2005-09-27 19:20:21 +00001928 if (d)
sewardj0e682c62005-09-28 20:05:31 +00001929 VG_(discard_translations)( (Addr64)s_start,
1930 (ULong)s_len,
sewardj45f4e7c2005-09-27 19:20:21 +00001931 "ML_(generic_POST_sys_shmdt)" );
sewardjb369c5e2005-03-24 17:52:02 +00001932 }
1933}
1934/* ------ */
1935
1936void
sewardj7eb7c582005-06-23 01:02:53 +00001937ML_(generic_PRE_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001938 UWord arg0, UWord arg1, UWord arg2 )
1939{
1940 /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
1941 switch (arg1 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00001942#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001943 case VKI_IPC_INFO:
1944 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1945 arg2, sizeof(struct vki_shminfo) );
1946 break;
njnf76d27a2009-05-28 01:53:07 +00001947#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001948 case VKI_IPC_INFO|VKI_IPC_64:
1949 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1950 arg2, sizeof(struct vki_shminfo64) );
1951 break;
njnf76d27a2009-05-28 01:53:07 +00001952#endif
1953#endif
1954
1955#if defined(VKI_SHM_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001956 case VKI_SHM_INFO:
njnf76d27a2009-05-28 01:53:07 +00001957#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001958 case VKI_SHM_INFO|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001959#endif
sewardjb369c5e2005-03-24 17:52:02 +00001960 PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
1961 arg2, sizeof(struct vki_shm_info) );
1962 break;
njnf76d27a2009-05-28 01:53:07 +00001963#endif
1964
sewardjb369c5e2005-03-24 17:52:02 +00001965 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00001966#if defined(VKI_SHM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001967 case VKI_SHM_STAT:
njnf76d27a2009-05-28 01:53:07 +00001968#endif
sewardjb369c5e2005-03-24 17:52:02 +00001969 PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
1970 arg2, sizeof(struct vki_shmid_ds) );
1971 break;
njnf76d27a2009-05-28 01:53:07 +00001972
1973#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001974 case VKI_IPC_STAT|VKI_IPC_64:
1975 case VKI_SHM_STAT|VKI_IPC_64:
1976 PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
1977 arg2, sizeof(struct vki_shmid64_ds) );
1978 break;
njnf76d27a2009-05-28 01:53:07 +00001979#endif
1980
sewardjb369c5e2005-03-24 17:52:02 +00001981 case VKI_IPC_SET:
1982 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1983 arg2, sizeof(struct vki_shmid_ds) );
1984 break;
njnf76d27a2009-05-28 01:53:07 +00001985
1986#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001987 case VKI_IPC_SET|VKI_IPC_64:
1988 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1989 arg2, sizeof(struct vki_shmid64_ds) );
1990 break;
njnf76d27a2009-05-28 01:53:07 +00001991#endif
sewardjb369c5e2005-03-24 17:52:02 +00001992 }
1993}
1994
1995void
sewardj7eb7c582005-06-23 01:02:53 +00001996ML_(generic_POST_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001997 UWord res,
1998 UWord arg0, UWord arg1, UWord arg2 )
1999{
2000 switch (arg1 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00002001#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002002 case VKI_IPC_INFO:
2003 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
2004 break;
2005 case VKI_IPC_INFO|VKI_IPC_64:
2006 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
2007 break;
njnf76d27a2009-05-28 01:53:07 +00002008#endif
2009
2010#if defined(VKI_SHM_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002011 case VKI_SHM_INFO:
2012 case VKI_SHM_INFO|VKI_IPC_64:
2013 POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
2014 break;
njnf76d27a2009-05-28 01:53:07 +00002015#endif
2016
sewardjb369c5e2005-03-24 17:52:02 +00002017 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00002018#if defined(VKI_SHM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00002019 case VKI_SHM_STAT:
njnf76d27a2009-05-28 01:53:07 +00002020#endif
sewardjb369c5e2005-03-24 17:52:02 +00002021 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
2022 break;
njnf76d27a2009-05-28 01:53:07 +00002023
2024#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002025 case VKI_IPC_STAT|VKI_IPC_64:
2026 case VKI_SHM_STAT|VKI_IPC_64:
2027 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
2028 break;
njnf76d27a2009-05-28 01:53:07 +00002029#endif
2030
2031
sewardjb369c5e2005-03-24 17:52:02 +00002032 }
2033}
2034
sewardjb369c5e2005-03-24 17:52:02 +00002035/* ---------------------------------------------------------------------
tom9548a162005-09-30 08:07:53 +00002036 Generic handler for mmap
2037 ------------------------------------------------------------------ */
2038
tom6d85b042005-09-30 16:09:12 +00002039/*
2040 * Although mmap is specified by POSIX and the argument are generally
2041 * consistent across platforms the precise details of the low level
2042 * argument passing conventions differ. For example:
2043 *
2044 * - On x86-linux there is mmap (aka old_mmap) which takes the
2045 * arguments in a memory block and the offset in bytes; and
2046 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
2047 * way and the offset in pages.
2048 *
2049 * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
2050 * arguments in the normal way and the offset in bytes; and
2051 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
2052 * way and the offset in pages.
2053 *
2054 * - On amd64-linux everything is simple and there is just the one
2055 * call, mmap (aka sys_mmap) which takes the arguments in the
2056 * normal way and the offset in bytes.
2057 *
sewardjb5b87402011-03-07 16:05:35 +00002058 * - On s390x-linux there is mmap (aka old_mmap) which takes the
2059 * arguments in a memory block and the offset in bytes. mmap2
2060 * is also available (but not exported via unistd.h) with
2061 * arguments in a memory block and the offset in pages.
2062 *
tom6d85b042005-09-30 16:09:12 +00002063 * To cope with all this we provide a generic handler function here
2064 * and then each platform implements one or more system call handlers
2065 * which call this generic routine after extracting and normalising
2066 * the arguments.
2067 */
2068
tom9548a162005-09-30 08:07:53 +00002069SysRes
2070ML_(generic_PRE_sys_mmap) ( ThreadId tid,
2071 UWord arg1, UWord arg2, UWord arg3,
sewardj274461d2005-10-02 17:01:41 +00002072 UWord arg4, UWord arg5, Off64T arg6 )
tom9548a162005-09-30 08:07:53 +00002073{
2074 Addr advised;
2075 SysRes sres;
2076 MapRequest mreq;
2077 Bool mreq_ok;
2078
sewardj80fe5492013-10-14 14:50:57 +00002079# if defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +00002080 // Nb: we can't use this on Darwin, it has races:
2081 // * needs to RETRY if advisory succeeds but map fails
2082 // (could have been some other thread in a nonblocking call)
2083 // * needs to not use fixed-position mmap() on Darwin
2084 // (mmap will cheerfully smash whatever's already there, which might
2085 // be a new mapping from some other thread in a nonblocking call)
2086 VG_(core_panic)("can't use ML_(generic_PRE_sys_mmap) on Darwin");
sewardj80fe5492013-10-14 14:50:57 +00002087# endif
njnf76d27a2009-05-28 01:53:07 +00002088
tom9548a162005-09-30 08:07:53 +00002089 if (arg2 == 0) {
2090 /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
2091 shall be established. */
2092 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2093 }
2094
2095 if (!VG_IS_PAGE_ALIGNED(arg1)) {
2096 /* zap any misaligned addresses. */
2097 /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
2098 to fail. Here, we catch them all. */
2099 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2100 }
2101
sewardj7e21df82005-09-30 10:48:27 +00002102 if (!VG_IS_PAGE_ALIGNED(arg6)) {
2103 /* zap any misaligned offsets. */
2104 /* SuSV3 says: The off argument is constrained to be aligned and
2105 sized according to the value returned by sysconf() when
2106 passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
2107 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2108 }
2109
sewardj80fe5492013-10-14 14:50:57 +00002110# if defined(VKI_MAP_32BIT)
2111 /* We can't support MAP_32BIT (at least, not without significant
2112 complication), and it's royally unportable, so if the client
2113 asks for it, just fail it. */
2114 if (arg4 & VKI_MAP_32BIT) {
2115 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
2116 }
2117# endif
2118
tom9548a162005-09-30 08:07:53 +00002119 /* Figure out what kind of allocation constraints there are
2120 (fixed/hint/any), and ask aspacem what we should do. */
2121 mreq.start = arg1;
2122 mreq.len = arg2;
2123 if (arg4 & VKI_MAP_FIXED) {
2124 mreq.rkind = MFixed;
2125 } else
2126 if (arg1 != 0) {
2127 mreq.rkind = MHint;
2128 } else {
2129 mreq.rkind = MAny;
2130 }
2131
2132 /* Enquire ... */
2133 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2134 if (!mreq_ok) {
2135 /* Our request was bounced, so we'd better fail. */
2136 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2137 }
2138
2139 /* Otherwise we're OK (so far). Install aspacem's choice of
2140 address, and let the mmap go through. */
2141 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2142 arg4 | VKI_MAP_FIXED,
2143 arg5, arg6);
2144
sewardj427d0162007-01-09 16:47:20 +00002145 /* A refinement: it may be that the kernel refused aspacem's choice
2146 of address. If we were originally asked for a hinted mapping,
2147 there is still a last chance: try again at any address.
2148 Hence: */
njncda2f0f2009-05-18 02:12:08 +00002149 if (mreq.rkind == MHint && sr_isError(sres)) {
sewardj427d0162007-01-09 16:47:20 +00002150 mreq.start = 0;
2151 mreq.len = arg2;
2152 mreq.rkind = MAny;
2153 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2154 if (!mreq_ok) {
2155 /* Our request was bounced, so we'd better fail. */
2156 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2157 }
2158 /* and try again with the kernel */
2159 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2160 arg4 | VKI_MAP_FIXED,
2161 arg5, arg6);
2162 }
2163
njncda2f0f2009-05-18 02:12:08 +00002164 if (!sr_isError(sres)) {
sewardj9c606bd2008-09-18 18:12:50 +00002165 ULong di_handle;
bart510521e2008-05-29 08:52:44 +00002166 /* Notify aspacem. */
njndd372582009-05-10 22:42:19 +00002167 notify_core_of_mmap(
njncda2f0f2009-05-18 02:12:08 +00002168 (Addr)sr_Res(sres), /* addr kernel actually assigned */
bart510521e2008-05-29 08:52:44 +00002169 arg2, /* length */
2170 arg3, /* prot */
tom9548a162005-09-30 08:07:53 +00002171 arg4, /* the original flags value */
bart510521e2008-05-29 08:52:44 +00002172 arg5, /* fd */
2173 arg6 /* offset */
tom9548a162005-09-30 08:07:53 +00002174 );
2175 /* Load symbols? */
njncda2f0f2009-05-18 02:12:08 +00002176 di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres),
sewardj5f2dcad2011-10-24 08:53:03 +00002177 False/*allow_SkFileV*/, (Int)arg5 );
bart510521e2008-05-29 08:52:44 +00002178 /* Notify the tool. */
2179 notify_tool_of_mmap(
njncda2f0f2009-05-18 02:12:08 +00002180 (Addr)sr_Res(sres), /* addr kernel actually assigned */
bart510521e2008-05-29 08:52:44 +00002181 arg2, /* length */
2182 arg3, /* prot */
sewardj9c606bd2008-09-18 18:12:50 +00002183 di_handle /* so the tool can refer to the read debuginfo later,
2184 if it wants. */
bart510521e2008-05-29 08:52:44 +00002185 );
tom9548a162005-09-30 08:07:53 +00002186 }
2187
2188 /* Stay sane */
njncda2f0f2009-05-18 02:12:08 +00002189 if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED))
2190 vg_assert(sr_Res(sres) == arg1);
tom9548a162005-09-30 08:07:53 +00002191
2192 return sres;
2193}
2194
2195
2196/* ---------------------------------------------------------------------
nethercote4fa681f2004-11-08 17:51:39 +00002197 The Main Entertainment ... syscall wrappers
njn25e49d8e72002-09-23 09:36:25 +00002198 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00002199
nethercote4fa681f2004-11-08 17:51:39 +00002200/* Note: the PRE() and POST() wrappers are for the actual functions
nethercote8ff888f2004-11-17 17:11:45 +00002201 implementing the system calls in the OS kernel. These mostly have
nethercote4fa681f2004-11-08 17:51:39 +00002202 names like sys_write(); a few have names like old_mmap(). See the
njnaf839f52005-06-23 03:27:57 +00002203 comment for ML_(syscall_table)[] for important info about the __NR_foo
nethercote8ff888f2004-11-17 17:11:45 +00002204 constants and their relationship to the sys_foo() functions.
nethercote4fa681f2004-11-08 17:51:39 +00002205
nethercote92b2fd52004-11-16 16:15:41 +00002206 Some notes about names used for syscalls and args:
2207 - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
2208 ambiguity.
2209
2210 - For error messages, we generally use a somewhat generic name
2211 for the syscall (eg. "write" rather than "sys_write"). This should be
2212 good enough for the average user to understand what is happening,
2213 without confusing them with names like "sys_write".
2214
2215 - Also, for error messages the arg names are mostly taken from the man
2216 pages (even though many of those man pages are really for glibc
nethercote8ff888f2004-11-17 17:11:45 +00002217 functions of the same name), rather than from the OS kernel source,
nethercote92b2fd52004-11-16 16:15:41 +00002218 for the same reason -- a user presented with a "bogus foo(bar)" arg
2219 will most likely look at the "foo" man page to see which is the "bar"
2220 arg.
nethercote8b76fe52004-11-08 19:20:09 +00002221
nethercote9c311eb2004-11-12 18:20:12 +00002222 Note that we use our own vki_* types. The one exception is in
2223 PRE_REG_READn calls, where pointer types haven't been changed, because
2224 they don't need to be -- eg. for "foo*" to be used, the type foo need not
2225 be visible.
2226
nethercote4fa681f2004-11-08 17:51:39 +00002227 XXX: some of these are arch-specific, and should be factored out.
2228*/
2229
sewardja8d8e232005-06-07 20:04:56 +00002230#define PRE(name) DEFN_PRE_TEMPLATE(generic, name)
2231#define POST(name) DEFN_POST_TEMPLATE(generic, name)
jsgf855d93d2003-10-13 22:26:55 +00002232
tomca787242009-11-25 11:24:00 +00002233// Macros to support 64-bit syscall args split into two 32 bit values
2234#if defined(VG_LITTLEENDIAN)
2235#define MERGE64(lo,hi) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2236#define MERGE64_FIRST(name) name##_low
2237#define MERGE64_SECOND(name) name##_high
2238#elif defined(VG_BIGENDIAN)
2239#define MERGE64(hi,lo) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
2240#define MERGE64_FIRST(name) name##_high
2241#define MERGE64_SECOND(name) name##_low
2242#else
2243#error Unknown endianness
njn89d43f72009-05-24 23:02:55 +00002244#endif
sewardje7aa4ae2005-06-09 12:43:42 +00002245
sewardja8d8e232005-06-07 20:04:56 +00002246PRE(sys_exit)
jsgf855d93d2003-10-13 22:26:55 +00002247{
sewardja8d8e232005-06-07 20:04:56 +00002248 ThreadState* tst;
sewardja922b612005-03-11 02:47:32 +00002249 /* simple; just make this thread exit */
barta0b6b2c2008-07-07 06:49:24 +00002250 PRINT("exit( %ld )", ARG1);
njnaab814e2009-03-03 05:39:23 +00002251 PRE_REG_READ1(void, "exit", int, status);
sewardja8d8e232005-06-07 20:04:56 +00002252 tst = VG_(get_ThreadState)(tid);
2253 /* Set the thread's status to be exiting, then claim that the
2254 syscall succeeded. */
sewardjef1cf8b2006-10-17 01:47:30 +00002255 tst->exitreason = VgSrc_ExitThread;
sewardja922b612005-03-11 02:47:32 +00002256 tst->os_state.exitcode = ARG1;
sewardja8d8e232005-06-07 20:04:56 +00002257 SET_STATUS_Success(0);
jsgf855d93d2003-10-13 22:26:55 +00002258}
2259
sewardja8d8e232005-06-07 20:04:56 +00002260PRE(sys_ni_syscall)
nethercoteeb1c7b72004-11-11 19:43:50 +00002261{
njn1a1e95c2009-06-03 06:50:06 +00002262 PRINT("unimplemented (by the kernel) syscall: %s! (ni_syscall)\n",
2263 VG_SYSNUM_STRING(SYSNO));
nethercoteeb1c7b72004-11-11 19:43:50 +00002264 PRE_REG_READ0(long, "ni_syscall");
sewardja8d8e232005-06-07 20:04:56 +00002265 SET_STATUS_Failure( VKI_ENOSYS );
nethercoteeb1c7b72004-11-11 19:43:50 +00002266}
2267
sewardj696c5512005-06-08 23:38:32 +00002268PRE(sys_iopl)
2269{
barta0b6b2c2008-07-07 06:49:24 +00002270 PRINT("sys_iopl ( %ld )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002271 PRE_REG_READ1(long, "iopl", unsigned long, level);
2272}
2273
sewardj78b50e42005-06-08 01:47:28 +00002274PRE(sys_fsync)
2275{
2276 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002277 PRINT("sys_fsync ( %ld )", ARG1);
sewardj78b50e42005-06-08 01:47:28 +00002278 PRE_REG_READ1(long, "fsync", unsigned int, fd);
2279}
2280
sewardj696c5512005-06-08 23:38:32 +00002281PRE(sys_fdatasync)
2282{
2283 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002284 PRINT("sys_fdatasync ( %ld )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002285 PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
2286}
2287
2288PRE(sys_msync)
2289{
2290 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002291 PRINT("sys_msync ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
sewardj696c5512005-06-08 23:38:32 +00002292 PRE_REG_READ3(long, "msync",
2293 unsigned long, start, vki_size_t, length, int, flags);
2294 PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
2295}
2296
sewardje6d5e722005-06-10 10:27:55 +00002297// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
2298// versions of LiS (Linux Streams). They are not part of the kernel.
2299// Therefore, we have to provide this type ourself, rather than getting it
2300// from the kernel sources.
2301struct vki_pmsg_strbuf {
2302 int maxlen; /* no. of bytes in buffer */
2303 int len; /* no. of bytes returned */
2304 vki_caddr_t buf; /* pointer to data */
2305};
2306PRE(sys_getpmsg)
2307{
2308 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
2309 struct vki_pmsg_strbuf *ctrl;
2310 struct vki_pmsg_strbuf *data;
2311 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002312 PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
sewardje6d5e722005-06-10 10:27:55 +00002313 PRE_REG_READ5(int, "getpmsg",
2314 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2315 int *, bandp, int *, flagsp);
2316 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2317 data = (struct vki_pmsg_strbuf *)ARG3;
2318 if (ctrl && ctrl->maxlen > 0)
2319 PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2320 if (data && data->maxlen > 0)
2321 PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2322 if (ARG4)
2323 PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2324 if (ARG5)
2325 PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2326}
2327POST(sys_getpmsg)
2328{
2329 struct vki_pmsg_strbuf *ctrl;
2330 struct vki_pmsg_strbuf *data;
2331 vg_assert(SUCCESS);
2332 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2333 data = (struct vki_pmsg_strbuf *)ARG3;
2334 if (RES == 0 && ctrl && ctrl->len > 0) {
2335 POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2336 }
2337 if (RES == 0 && data && data->len > 0) {
2338 POST_MEM_WRITE( (Addr)data->buf, data->len);
2339 }
2340}
2341
2342PRE(sys_putpmsg)
2343{
2344 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2345 struct vki_pmsg_strbuf *ctrl;
2346 struct vki_pmsg_strbuf *data;
2347 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002348 PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5);
sewardje6d5e722005-06-10 10:27:55 +00002349 PRE_REG_READ5(int, "putpmsg",
2350 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2351 int, band, int, flags);
2352 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2353 data = (struct vki_pmsg_strbuf *)ARG3;
2354 if (ctrl && ctrl->len > 0)
2355 PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2356 if (data && data->len > 0)
2357 PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2358}
sewardj696c5512005-06-08 23:38:32 +00002359
2360PRE(sys_getitimer)
2361{
njn72bbd8d2009-05-22 08:12:46 +00002362 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
barta0b6b2c2008-07-07 06:49:24 +00002363 PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002364 PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
njn72bbd8d2009-05-22 08:12:46 +00002365
2366 PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
2367 PRE_timeval_WRITE( "getitimer(&value->it_value)", &(value->it_value));
sewardj696c5512005-06-08 23:38:32 +00002368}
njnf76d27a2009-05-28 01:53:07 +00002369
sewardj696c5512005-06-08 23:38:32 +00002370POST(sys_getitimer)
2371{
2372 if (ARG2 != (Addr)NULL) {
njn72bbd8d2009-05-22 08:12:46 +00002373 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2374 POST_timeval_WRITE( &(value->it_interval) );
2375 POST_timeval_WRITE( &(value->it_value) );
sewardj696c5512005-06-08 23:38:32 +00002376 }
2377}
2378
2379PRE(sys_setitimer)
2380{
barta0b6b2c2008-07-07 06:49:24 +00002381 PRINT("sys_setitimer ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
sewardj696c5512005-06-08 23:38:32 +00002382 PRE_REG_READ3(long, "setitimer",
2383 int, which,
2384 struct itimerval *, value, struct itimerval *, ovalue);
njn72bbd8d2009-05-22 08:12:46 +00002385 if (ARG2 != (Addr)NULL) {
2386 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2387 PRE_timeval_READ( "setitimer(&value->it_interval)",
2388 &(value->it_interval));
2389 PRE_timeval_READ( "setitimer(&value->it_value)",
2390 &(value->it_value));
2391 }
2392 if (ARG3 != (Addr)NULL) {
2393 struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2394 PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
2395 &(ovalue->it_interval));
2396 PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
2397 &(ovalue->it_value));
2398 }
sewardj696c5512005-06-08 23:38:32 +00002399}
2400
2401POST(sys_setitimer)
2402{
2403 if (ARG3 != (Addr)NULL) {
njn72bbd8d2009-05-22 08:12:46 +00002404 struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2405 POST_timeval_WRITE( &(ovalue->it_interval) );
2406 POST_timeval_WRITE( &(ovalue->it_value) );
sewardj696c5512005-06-08 23:38:32 +00002407 }
2408}
2409
2410PRE(sys_chroot)
2411{
barta0b6b2c2008-07-07 06:49:24 +00002412 PRINT("sys_chroot ( %#lx )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002413 PRE_REG_READ1(long, "chroot", const char *, path);
2414 PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2415}
sewardja8d8e232005-06-07 20:04:56 +00002416
2417PRE(sys_madvise)
jsgf855d93d2003-10-13 22:26:55 +00002418{
sewardja8d8e232005-06-07 20:04:56 +00002419 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002420 PRINT("sys_madvise ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
nethercoteac866b92004-11-15 20:23:15 +00002421 PRE_REG_READ3(long, "madvise",
2422 unsigned long, start, vki_size_t, length, int, advice);
jsgf855d93d2003-10-13 22:26:55 +00002423}
2424
njnf76d27a2009-05-28 01:53:07 +00002425#if HAVE_MREMAP
sewardja8d8e232005-06-07 20:04:56 +00002426PRE(sys_mremap)
jsgf855d93d2003-10-13 22:26:55 +00002427{
nethercote27ea8bc2004-07-10 17:21:14 +00002428 // Nb: this is different to the glibc version described in the man pages,
2429 // which lacks the fifth 'new_address' argument.
tomc00fcc72006-05-08 11:58:06 +00002430 if (ARG4 & VKI_MREMAP_FIXED) {
barta0b6b2c2008-07-07 06:49:24 +00002431 PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx, %#lx )",
tomc00fcc72006-05-08 11:58:06 +00002432 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5);
2433 PRE_REG_READ5(unsigned long, "mremap",
2434 unsigned long, old_addr, unsigned long, old_size,
2435 unsigned long, new_size, unsigned long, flags,
2436 unsigned long, new_addr);
2437 } else {
barta0b6b2c2008-07-07 06:49:24 +00002438 PRINT("sys_mremap ( %#lx, %llu, %ld, 0x%lx )",
tomc00fcc72006-05-08 11:58:06 +00002439 ARG1, (ULong)ARG2, ARG3, ARG4);
2440 PRE_REG_READ4(unsigned long, "mremap",
2441 unsigned long, old_addr, unsigned long, old_size,
2442 unsigned long, new_size, unsigned long, flags);
2443 }
sewardja8d8e232005-06-07 20:04:56 +00002444 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002445 do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
sewardja8d8e232005-06-07 20:04:56 +00002446 );
jsgf855d93d2003-10-13 22:26:55 +00002447}
njnf76d27a2009-05-28 01:53:07 +00002448#endif /* HAVE_MREMAP */
jsgf855d93d2003-10-13 22:26:55 +00002449
sewardj8c9ea4e2005-06-08 10:46:56 +00002450PRE(sys_nice)
2451{
barta0b6b2c2008-07-07 06:49:24 +00002452 PRINT("sys_nice ( %ld )", ARG1);
sewardj8c9ea4e2005-06-08 10:46:56 +00002453 PRE_REG_READ1(long, "nice", int, inc);
2454}
sewardj78b50e42005-06-08 01:47:28 +00002455
sewardj696c5512005-06-08 23:38:32 +00002456PRE(sys_mlock)
2457{
2458 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002459 PRINT("sys_mlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
sewardj696c5512005-06-08 23:38:32 +00002460 PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2461}
2462
2463PRE(sys_munlock)
2464{
2465 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002466 PRINT("sys_munlock ( %#lx, %llu )", ARG1, (ULong)ARG2);
sewardj696c5512005-06-08 23:38:32 +00002467 PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2468}
2469
2470PRE(sys_mlockall)
2471{
2472 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002473 PRINT("sys_mlockall ( %lx )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002474 PRE_REG_READ1(long, "mlockall", int, flags);
2475}
2476
sewardj696c5512005-06-08 23:38:32 +00002477PRE(sys_setpriority)
2478{
barta0b6b2c2008-07-07 06:49:24 +00002479 PRINT("sys_setpriority ( %ld, %ld, %ld )", ARG1, ARG2, ARG3);
sewardj696c5512005-06-08 23:38:32 +00002480 PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2481}
2482
2483PRE(sys_getpriority)
2484{
barta0b6b2c2008-07-07 06:49:24 +00002485 PRINT("sys_getpriority ( %ld, %ld )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002486 PRE_REG_READ2(long, "getpriority", int, which, int, who);
2487}
2488
njn7b1edbd2009-05-19 06:50:37 +00002489PRE(sys_pwrite64)
sewardjedc95472008-08-07 20:29:55 +00002490{
sewardjedc95472008-08-07 20:29:55 +00002491 *flags |= SfMayBlock;
njn7b1edbd2009-05-19 06:50:37 +00002492#if VG_WORDSIZE == 4
barta0b6b2c2008-07-07 06:49:24 +00002493 PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
tomca787242009-11-25 11:24:00 +00002494 ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
sewardje6d5e722005-06-10 10:27:55 +00002495 PRE_REG_READ5(ssize_t, "pwrite64",
2496 unsigned int, fd, const char *, buf, vki_size_t, count,
sewardj0ca89e02009-11-25 13:57:47 +00002497 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
njn7b1edbd2009-05-19 06:50:37 +00002498#elif VG_WORDSIZE == 8
2499 PRINT("sys_pwrite64 ( %ld, %#lx, %llu, %lld )",
2500 ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
2501 PRE_REG_READ4(ssize_t, "pwrite64",
2502 unsigned int, fd, const char *, buf, vki_size_t, count,
2503 Word, offset);
2504#else
2505# error Unexpected word size
2506#endif
sewardje6d5e722005-06-10 10:27:55 +00002507 PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2508}
sewardj8c9ea4e2005-06-08 10:46:56 +00002509
2510PRE(sys_sync)
2511{
2512 *flags |= SfMayBlock;
2513 PRINT("sys_sync ( )");
2514 PRE_REG_READ0(long, "sync");
2515}
2516
sewardj696c5512005-06-08 23:38:32 +00002517PRE(sys_fstatfs)
2518{
sewardjcc3de2d2011-08-18 15:08:20 +00002519 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002520 PRINT("sys_fstatfs ( %ld, %#lx )",ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00002521 PRE_REG_READ2(long, "fstatfs",
2522 unsigned int, fd, struct statfs *, buf);
2523 PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2524}
2525
2526POST(sys_fstatfs)
2527{
2528 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2529}
2530
sewardje6d5e722005-06-10 10:27:55 +00002531PRE(sys_fstatfs64)
2532{
sewardjcc3de2d2011-08-18 15:08:20 +00002533 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002534 PRINT("sys_fstatfs64 ( %ld, %llu, %#lx )",ARG1,(ULong)ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00002535 PRE_REG_READ3(long, "fstatfs64",
2536 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2537 PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2538}
2539POST(sys_fstatfs64)
2540{
2541 POST_MEM_WRITE( ARG3, ARG2 );
2542}
sewardj696c5512005-06-08 23:38:32 +00002543
2544PRE(sys_getsid)
2545{
barta0b6b2c2008-07-07 06:49:24 +00002546 PRINT("sys_getsid ( %ld )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002547 PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2548}
2549
njn7b1edbd2009-05-19 06:50:37 +00002550PRE(sys_pread64)
sewardjedc95472008-08-07 20:29:55 +00002551{
sewardjedc95472008-08-07 20:29:55 +00002552 *flags |= SfMayBlock;
njn7b1edbd2009-05-19 06:50:37 +00002553#if VG_WORDSIZE == 4
barta0b6b2c2008-07-07 06:49:24 +00002554 PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
tomca787242009-11-25 11:24:00 +00002555 ARG1, ARG2, (ULong)ARG3, MERGE64(ARG4,ARG5));
sewardje7aa4ae2005-06-09 12:43:42 +00002556 PRE_REG_READ5(ssize_t, "pread64",
2557 unsigned int, fd, char *, buf, vki_size_t, count,
tomca787242009-11-25 11:24:00 +00002558 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
njn7b1edbd2009-05-19 06:50:37 +00002559#elif VG_WORDSIZE == 8
2560 PRINT("sys_pread64 ( %ld, %#lx, %llu, %lld )",
2561 ARG1, ARG2, (ULong)ARG3, (Long)ARG4);
2562 PRE_REG_READ4(ssize_t, "pread64",
2563 unsigned int, fd, char *, buf, vki_size_t, count,
2564 Word, offset);
2565#else
2566# error Unexpected word size
2567#endif
sewardje7aa4ae2005-06-09 12:43:42 +00002568 PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2569}
njn7b1edbd2009-05-19 06:50:37 +00002570POST(sys_pread64)
sewardje7aa4ae2005-06-09 12:43:42 +00002571{
2572 vg_assert(SUCCESS);
2573 if (RES > 0) {
2574 POST_MEM_WRITE( ARG2, RES );
2575 }
2576}
jsgf855d93d2003-10-13 22:26:55 +00002577
sewardja8d8e232005-06-07 20:04:56 +00002578PRE(sys_mknod)
jsgf855d93d2003-10-13 22:26:55 +00002579{
sewardjcc3de2d2011-08-18 15:08:20 +00002580 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002581 PRINT("sys_mknod ( %#lx(%s), 0x%lx, 0x%lx )", ARG1, (char*)ARG1, ARG2, ARG3 );
nethercotec6851dd2004-11-11 18:00:47 +00002582 PRE_REG_READ3(long, "mknod",
2583 const char *, pathname, int, mode, unsigned, dev);
njn22cfccb2004-11-27 16:10:23 +00002584 PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002585}
2586
sewardj696c5512005-06-08 23:38:32 +00002587PRE(sys_flock)
2588{
2589 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002590 PRINT("sys_flock ( %ld, %ld )", ARG1, ARG2 );
sewardj696c5512005-06-08 23:38:32 +00002591 PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2592}
2593
nethercotea81e9162004-02-12 14:34:14 +00002594// Pre_read a char** argument.
floriane543f302012-10-21 19:43:43 +00002595static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
nethercotea81e9162004-02-12 14:34:14 +00002596{
2597 while (True) {
njnb249fd72004-11-29 14:24:57 +00002598 Addr a_deref;
2599 Addr* a_p = (Addr*)a;
2600 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2601 a_deref = *a_p;
nethercotea81e9162004-02-12 14:34:14 +00002602 if (0 == a_deref)
2603 break;
nethercoteef0c7662004-11-06 15:38:43 +00002604 PRE_MEM_RASCIIZ( s2, a_deref );
nethercotea81e9162004-02-12 14:34:14 +00002605 a += sizeof(char*);
2606 }
2607}
2608
njn7b85dd52005-06-12 17:26:29 +00002609static Bool i_am_the_only_thread ( void )
2610{
2611 Int c = VG_(count_living_threads)();
2612 vg_assert(c >= 1); /* stay sane */
2613 return c == 1;
2614}
2615
2616/* Wait until all other threads disappear. */
2617void VG_(reap_threads)(ThreadId self)
2618{
2619 while (!i_am_the_only_thread()) {
2620 /* Let other thread(s) run */
2621 VG_(vg_yield)();
2622 VG_(poll_signals)(self);
2623 }
2624 vg_assert(i_am_the_only_thread());
2625}
2626
nethercote7310afb2004-11-12 15:41:06 +00002627// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2628// but it seems to work nonetheless...
sewardja8d8e232005-06-07 20:04:56 +00002629PRE(sys_execve)
jsgf855d93d2003-10-13 22:26:55 +00002630{
florian19f91bb2012-11-10 22:29:54 +00002631 HChar* path = NULL; /* path to executable */
2632 HChar** envp = NULL;
2633 HChar** argv = NULL;
2634 HChar** arg2copy;
2635 HChar* launcher_basename = NULL;
sewardja8d8e232005-06-07 20:04:56 +00002636 ThreadState* tst;
sewardj45f4e7c2005-09-27 19:20:21 +00002637 Int i, j, tot_args;
njn73750612005-10-14 03:11:30 +00002638 SysRes res;
sewardj06421272009-11-05 08:55:13 +00002639 Bool setuid_allowed, trace_this_child;
sewardjb5f6f512005-03-10 23:59:00 +00002640
barta0b6b2c2008-07-07 06:49:24 +00002641 PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (char*)ARG1, ARG2, ARG3);
nethercote7310afb2004-11-12 15:41:06 +00002642 PRE_REG_READ3(vki_off_t, "execve",
2643 char *, filename, char **, argv, char **, envp);
njn22cfccb2004-11-27 16:10:23 +00002644 PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
2645 if (ARG2 != 0)
2646 pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
2647 if (ARG3 != 0)
2648 pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
fitzhardingee1c06d82003-10-30 07:21:44 +00002649
sewardja8d8e232005-06-07 20:04:56 +00002650 vg_assert(VG_(is_valid_tid)(tid));
2651 tst = VG_(get_ThreadState)(tid);
2652
fitzhardingee1c06d82003-10-30 07:21:44 +00002653 /* Erk. If the exec fails, then the following will have made a
2654 mess of things which makes it hard for us to continue. The
2655 right thing to do is piece everything together again in
sewardj45f4e7c2005-09-27 19:20:21 +00002656 POST(execve), but that's close to impossible. Instead, we make
2657 an effort to check that the execve will work before actually
2658 doing it. */
fitzhardingee1c06d82003-10-30 07:21:44 +00002659
njn73750612005-10-14 03:11:30 +00002660 /* Check that the name at least begins in client-accessible storage. */
sewardj06421272009-11-05 08:55:13 +00002661 if (ARG1 == 0 /* obviously bogus */
2662 || !VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
sewardj45f4e7c2005-09-27 19:20:21 +00002663 SET_STATUS_Failure( VKI_EFAULT );
2664 return;
2665 }
2666
sewardj9ab64a42010-12-06 11:40:04 +00002667 // debug-only printing
2668 if (0) {
2669 VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1);
2670 if (ARG2) {
2671 VG_(printf)("ARG2 = ");
2672 Int q;
2673 HChar** vec = (HChar**)ARG2;
2674 for (q = 0; vec[q]; q++)
2675 VG_(printf)("%p(%s) ", vec[q], vec[q]);
2676 VG_(printf)("\n");
2677 } else {
2678 VG_(printf)("ARG2 = null\n");
2679 }
2680 }
2681
sewardj06421272009-11-05 08:55:13 +00002682 // Decide whether or not we want to follow along
sewardj9ab64a42010-12-06 11:40:04 +00002683 { // Make 'child_argv' be a pointer to the child's arg vector
2684 // (skipping the exe name)
2685 HChar** child_argv = (HChar**)ARG2;
2686 if (child_argv && child_argv[0] == NULL)
2687 child_argv = NULL;
2688 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv );
2689 }
sewardj06421272009-11-05 08:55:13 +00002690
njn73750612005-10-14 03:11:30 +00002691 // Do the important checks: it is a file, is executable, permissions are
sewardjc74b3ba2007-11-17 21:11:57 +00002692 // ok, etc. We allow setuid executables to run only in the case when
2693 // we are not simulating them, that is, they to be run natively.
sewardj06421272009-11-05 08:55:13 +00002694 setuid_allowed = trace_this_child ? False : True;
floriane543f302012-10-21 19:43:43 +00002695 res = VG_(pre_exec_check)((const HChar *)ARG1, NULL, setuid_allowed);
njncda2f0f2009-05-18 02:12:08 +00002696 if (sr_isError(res)) {
2697 SET_STATUS_Failure( sr_Err(res) );
njn73750612005-10-14 03:11:30 +00002698 return;
2699 }
2700
sewardj98e68a42005-10-04 23:07:33 +00002701 /* If we're tracing the child, and the launcher name looks bogus
2702 (possibly because launcher.c couldn't figure it out, see
2703 comments therein) then we have no option but to fail. */
sewardj06421272009-11-05 08:55:13 +00002704 if (trace_this_child
sewardj98e68a42005-10-04 23:07:33 +00002705 && (VG_(name_of_launcher) == NULL
2706 || VG_(name_of_launcher)[0] != '/')) {
2707 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2708 return;
2709 }
2710
sewardj45f4e7c2005-09-27 19:20:21 +00002711 /* After this point, we can't recover if the execve fails. */
florian19f91bb2012-11-10 22:29:54 +00002712 VG_(debugLog)(1, "syswrap", "Exec of %s\n", (HChar*)ARG1);
sewardj45f4e7c2005-09-27 19:20:21 +00002713
sewardj997546c2011-05-17 18:14:53 +00002714
2715 // Terminate gdbserver if it is active.
2716 if (VG_(clo_vgdb) != Vg_VgdbNo) {
2717 // If the child will not be traced, we need to terminate gdbserver
2718 // to cleanup the gdbserver resources (e.g. the FIFO files).
2719 // If child will be traced, we also terminate gdbserver: the new
2720 // Valgrind will start a fresh gdbserver after exec.
2721 VG_(gdbserver) (0);
2722 }
2723
fitzhardingee1c06d82003-10-30 07:21:44 +00002724 /* Resistance is futile. Nuke all other threads. POSIX mandates
2725 this. (Really, nuke them all, since the new process will make
2726 its own new thread.) */
sewardjef1cf8b2006-10-17 01:47:30 +00002727 VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread );
njn7b85dd52005-06-12 17:26:29 +00002728 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002729
sewardj45f4e7c2005-09-27 19:20:21 +00002730 // Set up the child's exe path.
2731 //
sewardj06421272009-11-05 08:55:13 +00002732 if (trace_this_child) {
sewardj45f4e7c2005-09-27 19:20:21 +00002733
2734 // We want to exec the launcher. Get its pre-remembered path.
2735 path = VG_(name_of_launcher);
2736 // VG_(name_of_launcher) should have been acquired by m_main at
2737 // startup.
2738 vg_assert(path);
2739
2740 launcher_basename = VG_(strrchr)(path, '/');
2741 if (launcher_basename == NULL || launcher_basename[1] == 0) {
2742 launcher_basename = path; // hmm, tres dubious
2743 } else {
2744 launcher_basename++;
2745 }
2746
2747 } else {
florian19f91bb2012-11-10 22:29:54 +00002748 path = (HChar*)ARG1;
sewardj45f4e7c2005-09-27 19:20:21 +00002749 }
2750
2751 // Set up the child's environment.
2752 //
tom4e136952005-07-18 14:02:11 +00002753 // Remove the valgrind-specific stuff from the environment so the
njn7b4e5ba2005-08-25 22:53:57 +00002754 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
tom4e136952005-07-18 14:02:11 +00002755 // This is done unconditionally, since if we are tracing the child,
sewardj45f4e7c2005-09-27 19:20:21 +00002756 // the child valgrind will set up the appropriate client environment.
njn11106992005-07-18 14:10:12 +00002757 // Nb: we make a copy of the environment before trying to mangle it
2758 // as it might be in read-only memory (this was bug #101881).
sewardj45f4e7c2005-09-27 19:20:21 +00002759 //
2760 // Then, if tracing the child, set VALGRIND_LIB for it.
2761 //
2762 if (ARG3 == 0) {
2763 envp = NULL;
2764 } else {
florian19f91bb2012-11-10 22:29:54 +00002765 envp = VG_(env_clone)( (HChar**)ARG3 );
sewardj45f4e7c2005-09-27 19:20:21 +00002766 if (envp == NULL) goto hosed;
tom4e136952005-07-18 14:02:11 +00002767 VG_(env_remove_valgrind_env_stuff)( envp );
fitzhardinge5408c062004-01-04 23:52:59 +00002768 }
2769
sewardj06421272009-11-05 08:55:13 +00002770 if (trace_this_child) {
sewardj45f4e7c2005-09-27 19:20:21 +00002771 // Set VALGRIND_LIB in ARG3 (the environment)
2772 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
fitzhardinge98abfc72003-12-16 02:05:15 +00002773 }
2774
sewardj45f4e7c2005-09-27 19:20:21 +00002775 // Set up the child's args. If not tracing it, they are
2776 // simply ARG2. Otherwise, they are
2777 //
2778 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
2779 //
2780 // except that the first VG_(args_for_valgrind_noexecpass) args
2781 // are omitted.
2782 //
sewardj06421272009-11-05 08:55:13 +00002783 if (!trace_this_child) {
florian19f91bb2012-11-10 22:29:54 +00002784 argv = (HChar**)ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00002785 } else {
sewardj14c7cc52007-02-25 15:08:24 +00002786 vg_assert( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +00002787 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2788 vg_assert( VG_(args_for_valgrind_noexecpass)
sewardj14c7cc52007-02-25 15:08:24 +00002789 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
sewardj45f4e7c2005-09-27 19:20:21 +00002790 /* how many args in total will there be? */
2791 // launcher basename
2792 tot_args = 1;
2793 // V's args
sewardj14c7cc52007-02-25 15:08:24 +00002794 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +00002795 tot_args -= VG_(args_for_valgrind_noexecpass);
2796 // name of client exe
2797 tot_args++;
2798 // args for client exe, skipping [0]
florian19f91bb2012-11-10 22:29:54 +00002799 arg2copy = (HChar**)ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00002800 if (arg2copy && arg2copy[0]) {
2801 for (i = 1; arg2copy[i]; i++)
2802 tot_args++;
2803 }
2804 // allocate
sewardj9c606bd2008-09-18 18:12:50 +00002805 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
2806 (tot_args+1) * sizeof(HChar*) );
sewardj45f4e7c2005-09-27 19:20:21 +00002807 if (argv == 0) goto hosed;
2808 // copy
2809 j = 0;
2810 argv[j++] = launcher_basename;
sewardj14c7cc52007-02-25 15:08:24 +00002811 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
sewardj45f4e7c2005-09-27 19:20:21 +00002812 if (i < VG_(args_for_valgrind_noexecpass))
2813 continue;
sewardj14c7cc52007-02-25 15:08:24 +00002814 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
sewardj45f4e7c2005-09-27 19:20:21 +00002815 }
florian19f91bb2012-11-10 22:29:54 +00002816 argv[j++] = (HChar*)ARG1;
sewardj45f4e7c2005-09-27 19:20:21 +00002817 if (arg2copy && arg2copy[0])
2818 for (i = 1; arg2copy[i]; i++)
2819 argv[j++] = arg2copy[i];
2820 argv[j++] = NULL;
2821 // check
2822 vg_assert(j == tot_args+1);
jsgf855d93d2003-10-13 22:26:55 +00002823 }
jsgf855d93d2003-10-13 22:26:55 +00002824
sewardjb5f6f512005-03-10 23:59:00 +00002825 /* restore the DATA rlimit for the child */
2826 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2827
2828 /*
2829 Set the signal state up for exec.
2830
2831 We need to set the real signal state to make sure the exec'd
2832 process gets SIG_IGN properly.
2833
2834 Also set our real sigmask to match the client's sigmask so that
2835 the exec'd child will get the right mask. First we need to
2836 clear out any pending signals so they they don't get delivered,
2837 which would confuse things.
fitzhardingef0dd7e12004-01-16 02:17:30 +00002838
2839 XXX This is a bug - the signals should remain pending, and be
2840 delivered to the new process after exec. There's also a
2841 race-condition, since if someone delivers us a signal between
2842 the sigprocmask and the execve, we'll still get the signal. Oh
2843 well.
2844 */
2845 {
nethercote73b526f2004-10-31 18:48:21 +00002846 vki_sigset_t allsigs;
2847 vki_siginfo_t info;
sewardjb5f6f512005-03-10 23:59:00 +00002848
njncda2f0f2009-05-18 02:12:08 +00002849 /* What this loop does: it queries SCSS (the signal state that
2850 the client _thinks_ the kernel is in) by calling
2851 VG_(do_sys_sigaction), and modifies the real kernel signal
2852 state accordingly. */
sewardj45f4e7c2005-09-27 19:20:21 +00002853 for (i = 1; i < VG_(max_signal); i++) {
njncda2f0f2009-05-18 02:12:08 +00002854 vki_sigaction_fromK_t sa_f;
2855 vki_sigaction_toK_t sa_t;
2856 VG_(do_sys_sigaction)(i, NULL, &sa_f);
2857 VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
2858 if (sa_t.ksa_handler == VKI_SIG_IGN)
2859 VG_(sigaction)(i, &sa_t, NULL);
sewardjb5f6f512005-03-10 23:59:00 +00002860 else {
njncda2f0f2009-05-18 02:12:08 +00002861 sa_t.ksa_handler = VKI_SIG_DFL;
2862 VG_(sigaction)(i, &sa_t, NULL);
sewardjb5f6f512005-03-10 23:59:00 +00002863 }
2864 }
2865
nethercote73b526f2004-10-31 18:48:21 +00002866 VG_(sigfillset)(&allsigs);
sewardjef1cf8b2006-10-17 01:47:30 +00002867 while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
sewardjb5f6f512005-03-10 23:59:00 +00002868 ;
fitzhardingef0dd7e12004-01-16 02:17:30 +00002869
nethercote73b526f2004-10-31 18:48:21 +00002870 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
fitzhardingef0dd7e12004-01-16 02:17:30 +00002871 }
2872
sewardj45f4e7c2005-09-27 19:20:21 +00002873 if (0) {
florian19f91bb2012-11-10 22:29:54 +00002874 HChar **cpp;
sewardj45f4e7c2005-09-27 19:20:21 +00002875 VG_(printf)("exec: %s\n", path);
2876 for (cpp = argv; cpp && *cpp; cpp++)
2877 VG_(printf)("argv: %s\n", *cpp);
2878 if (0)
2879 for (cpp = envp; cpp && *cpp; cpp++)
2880 VG_(printf)("env: %s\n", *cpp);
2881 }
2882
sewardja8d8e232005-06-07 20:04:56 +00002883 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002884 VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
sewardja8d8e232005-06-07 20:04:56 +00002885 );
fitzhardingeb50068f2004-02-24 23:42:55 +00002886
sewardj45f4e7c2005-09-27 19:20:21 +00002887 /* If we got here, then the execve failed. We've already made way
2888 too much of a mess to continue, so we have to abort. */
2889 hosed:
tomdc294c32005-08-16 10:19:58 +00002890 vg_assert(FAILURE);
sewardj738856f2009-07-15 14:48:32 +00002891 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n",
barta0b6b2c2008-07-07 06:49:24 +00002892 ARG1, (char*)ARG1, ARG2, ARG3, ERR);
sewardjb5f6f512005-03-10 23:59:00 +00002893 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
sewardj738856f2009-07-15 14:48:32 +00002894 "execve() failing, so I'm dying.\n");
sewardja8d8e232005-06-07 20:04:56 +00002895 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
sewardj738856f2009-07-15 14:48:32 +00002896 "or work out how to recover.\n");
sewardjb5f6f512005-03-10 23:59:00 +00002897 VG_(exit)(101);
jsgf855d93d2003-10-13 22:26:55 +00002898}
2899
sewardja8d8e232005-06-07 20:04:56 +00002900PRE(sys_access)
jsgf855d93d2003-10-13 22:26:55 +00002901{
barta0b6b2c2008-07-07 06:49:24 +00002902 PRINT("sys_access ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00002903 PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00002904 PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002905}
2906
sewardja8d8e232005-06-07 20:04:56 +00002907PRE(sys_alarm)
jsgf855d93d2003-10-13 22:26:55 +00002908{
barta0b6b2c2008-07-07 06:49:24 +00002909 PRINT("sys_alarm ( %ld )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00002910 PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
jsgf855d93d2003-10-13 22:26:55 +00002911}
2912
sewardja8d8e232005-06-07 20:04:56 +00002913PRE(sys_brk)
jsgf855d93d2003-10-13 22:26:55 +00002914{
fitzhardinge98abfc72003-12-16 02:05:15 +00002915 Addr brk_limit = VG_(brk_limit);
sewardja8d8e232005-06-07 20:04:56 +00002916 Addr brk_new;
fitzhardinge98abfc72003-12-16 02:05:15 +00002917
jsgf855d93d2003-10-13 22:26:55 +00002918 /* libc says: int brk(void *end_data_segment);
2919 kernel says: void* brk(void* end_data_segment); (more or less)
2920
2921 libc returns 0 on success, and -1 (and sets errno) on failure.
2922 Nb: if you ask to shrink the dataseg end below what it
2923 currently is, that always succeeds, even if the dataseg end
2924 doesn't actually change (eg. brk(0)). Unless it seg faults.
2925
2926 Kernel returns the new dataseg end. If the brk() failed, this
2927 will be unchanged from the old one. That's why calling (kernel)
2928 brk(0) gives the current dataseg end (libc brk() just returns
2929 zero in that case).
2930
2931 Both will seg fault if you shrink it back into a text segment.
2932 */
barta0b6b2c2008-07-07 06:49:24 +00002933 PRINT("sys_brk ( %#lx )", ARG1);
nethercote9c311eb2004-11-12 18:20:12 +00002934 PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
jsgf855d93d2003-10-13 22:26:55 +00002935
sewardja8d8e232005-06-07 20:04:56 +00002936 brk_new = do_brk(ARG1);
2937 SET_STATUS_Success( brk_new );
fitzhardinge98abfc72003-12-16 02:05:15 +00002938
sewardja8d8e232005-06-07 20:04:56 +00002939 if (brk_new == ARG1) {
jsgf855d93d2003-10-13 22:26:55 +00002940 /* brk() succeeded */
sewardja8d8e232005-06-07 20:04:56 +00002941 if (brk_new < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002942 /* successfully shrunk the data segment. */
njn22cfccb2004-11-27 16:10:23 +00002943 VG_TRACK( die_mem_brk, (Addr)ARG1,
2944 brk_limit-ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002945 } else
sewardja8d8e232005-06-07 20:04:56 +00002946 if (brk_new > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002947 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00002948 VG_TRACK( new_mem_brk, brk_limit,
sewardj7cf4e6b2008-05-01 20:24:26 +00002949 ARG1-brk_limit, tid );
jsgf855d93d2003-10-13 22:26:55 +00002950 }
jsgf855d93d2003-10-13 22:26:55 +00002951 } else {
2952 /* brk() failed */
sewardja8d8e232005-06-07 20:04:56 +00002953 vg_assert(brk_limit == brk_new);
jsgf855d93d2003-10-13 22:26:55 +00002954 }
2955}
2956
sewardja8d8e232005-06-07 20:04:56 +00002957PRE(sys_chdir)
jsgf855d93d2003-10-13 22:26:55 +00002958{
sewardjcc3de2d2011-08-18 15:08:20 +00002959 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002960 PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002961 PRE_REG_READ1(long, "chdir", const char *, path);
njn22cfccb2004-11-27 16:10:23 +00002962 PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002963}
2964
sewardja8d8e232005-06-07 20:04:56 +00002965PRE(sys_chmod)
jsgf855d93d2003-10-13 22:26:55 +00002966{
sewardjcc3de2d2011-08-18 15:08:20 +00002967 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002968 PRINT("sys_chmod ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00002969 PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
njn22cfccb2004-11-27 16:10:23 +00002970 PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002971}
2972
sewardje6d5e722005-06-10 10:27:55 +00002973PRE(sys_chown)
2974{
sewardjcc3de2d2011-08-18 15:08:20 +00002975 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002976 PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00002977 PRE_REG_READ3(long, "chown",
2978 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2979 PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
2980}
2981
2982PRE(sys_lchown)
2983{
sewardjcc3de2d2011-08-18 15:08:20 +00002984 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002985 PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00002986 PRE_REG_READ3(long, "lchown",
2987 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2988 PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
2989}
nethercote2e1c37d2004-11-13 13:57:12 +00002990
sewardja8d8e232005-06-07 20:04:56 +00002991PRE(sys_close)
jsgf855d93d2003-10-13 22:26:55 +00002992{
sewardjcc3de2d2011-08-18 15:08:20 +00002993 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00002994 PRINT("sys_close ( %ld )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002995 PRE_REG_READ1(long, "close", unsigned int, fd);
2996
nethercotef8548672004-06-21 12:42:35 +00002997 /* Detect and negate attempts by the client to close Valgrind's log fd */
sewardj9da79d12007-01-13 22:27:51 +00002998 if ( (!ML_(fd_allowed)(ARG1, "close", tid, False))
2999 /* If doing -d style logging (which is to fd=2), don't
3000 allow that to be closed either. */
3001 || (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) )
sewardja8d8e232005-06-07 20:04:56 +00003002 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003003}
3004
nethercote85a456f2004-11-16 17:31:56 +00003005POST(sys_close)
rjwalshf5f536f2003-11-17 17:45:00 +00003006{
njn1dcee092009-02-24 03:07:37 +00003007 if (VG_(clo_track_fds)) record_fd_close(ARG1);
rjwalshf5f536f2003-11-17 17:45:00 +00003008}
jsgf855d93d2003-10-13 22:26:55 +00003009
sewardja8d8e232005-06-07 20:04:56 +00003010PRE(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00003011{
barta0b6b2c2008-07-07 06:49:24 +00003012 PRINT("sys_dup ( %ld )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00003013 PRE_REG_READ1(long, "dup", unsigned int, oldfd);
jsgf855d93d2003-10-13 22:26:55 +00003014}
3015
nethercote85a456f2004-11-16 17:31:56 +00003016POST(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00003017{
sewardja8d8e232005-06-07 20:04:56 +00003018 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00003019 if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00003020 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00003021 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00003022 } else {
nethercote9a3beb92004-11-12 17:07:26 +00003023 if (VG_(clo_track_fds))
njn096ccdd2009-02-22 23:00:30 +00003024 ML_(record_fd_open_named)(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00003025 }
3026}
3027
sewardja8d8e232005-06-07 20:04:56 +00003028PRE(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00003029{
barta0b6b2c2008-07-07 06:49:24 +00003030 PRINT("sys_dup2 ( %ld, %ld )", ARG1,ARG2);
nethercote71f05f32004-11-12 18:49:27 +00003031 PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
sewardj7eb7c582005-06-23 01:02:53 +00003032 if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
sewardja8d8e232005-06-07 20:04:56 +00003033 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003034}
3035
nethercote85a456f2004-11-16 17:31:56 +00003036POST(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00003037{
sewardja8d8e232005-06-07 20:04:56 +00003038 vg_assert(SUCCESS);
nethercote71f05f32004-11-12 18:49:27 +00003039 if (VG_(clo_track_fds))
njn096ccdd2009-02-22 23:00:30 +00003040 ML_(record_fd_open_named)(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00003041}
3042
sewardj696c5512005-06-08 23:38:32 +00003043PRE(sys_fchdir)
3044{
sewardjcc3de2d2011-08-18 15:08:20 +00003045 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003046 PRINT("sys_fchdir ( %ld )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00003047 PRE_REG_READ1(long, "fchdir", unsigned int, fd);
3048}
3049
sewardje6d5e722005-06-10 10:27:55 +00003050PRE(sys_fchown)
3051{
sewardjcc3de2d2011-08-18 15:08:20 +00003052 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003053 PRINT("sys_fchown ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003054 PRE_REG_READ3(long, "fchown",
3055 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
3056}
sewardj696c5512005-06-08 23:38:32 +00003057
3058PRE(sys_fchmod)
3059{
sewardjcc3de2d2011-08-18 15:08:20 +00003060 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003061 PRINT("sys_fchmod ( %ld, %ld )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003062 PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
3063}
3064
sewardj696c5512005-06-08 23:38:32 +00003065PRE(sys_newfstat)
3066{
sewardjcc3de2d2011-08-18 15:08:20 +00003067 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003068 PRINT("sys_newfstat ( %ld, %#lx )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003069 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
3070 PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
3071}
3072
3073POST(sys_newfstat)
3074{
3075 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3076}
jsgf855d93d2003-10-13 22:26:55 +00003077
nethercote73b526f2004-10-31 18:48:21 +00003078static vki_sigset_t fork_saved_mask;
jsgf855d93d2003-10-13 22:26:55 +00003079
nethercote75a8c982004-11-11 19:03:34 +00003080// In Linux, the sys_fork() function varies across architectures, but we
3081// ignore the various args it gets, and so it looks arch-neutral. Hmm.
sewardja8d8e232005-06-07 20:04:56 +00003082PRE(sys_fork)
jsgf855d93d2003-10-13 22:26:55 +00003083{
njn58bbd942009-05-21 23:59:34 +00003084 Bool is_child;
3085 Int child_pid;
nethercote73b526f2004-10-31 18:48:21 +00003086 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +00003087
nethercote75a8c982004-11-11 19:03:34 +00003088 PRINT("sys_fork ( )");
3089 PRE_REG_READ0(long, "fork");
3090
jsgf855d93d2003-10-13 22:26:55 +00003091 /* Block all signals during fork, so that we can fix things up in
3092 the child without being interrupted. */
nethercote73b526f2004-10-31 18:48:21 +00003093 VG_(sigfillset)(&mask);
3094 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
jsgf855d93d2003-10-13 22:26:55 +00003095
sewardja8d8e232005-06-07 20:04:56 +00003096 SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
sewardjb5f6f512005-03-10 23:59:00 +00003097
njncda2f0f2009-05-18 02:12:08 +00003098 if (!SUCCESS) return;
3099
sewardj6e9de462011-06-28 07:25:29 +00003100#if defined(VGO_linux)
njn58bbd942009-05-21 23:59:34 +00003101 // RES is 0 for child, non-0 (the child's PID) for parent.
3102 is_child = ( RES == 0 ? True : False );
3103 child_pid = ( is_child ? -1 : RES );
njnf76d27a2009-05-28 01:53:07 +00003104#elif defined(VGO_darwin)
3105 // RES is the child's pid. RESHI is 1 for child, 0 for parent.
3106 is_child = RESHI;
3107 child_pid = RES;
3108#else
3109# error Unknown OS
3110#endif
njncda2f0f2009-05-18 02:12:08 +00003111
njne9ba34a2008-10-13 04:19:15 +00003112 VG_(do_atfork_pre)(tid);
3113
njn58bbd942009-05-21 23:59:34 +00003114 if (is_child) {
sewardjb5f6f512005-03-10 23:59:00 +00003115 VG_(do_atfork_child)(tid);
jsgf855d93d2003-10-13 22:26:55 +00003116
3117 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00003118 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
sewardj6e31f802007-11-17 22:29:25 +00003119
3120 /* If --child-silent-after-fork=yes was specified, set the
sewardj738856f2009-07-15 14:48:32 +00003121 output file descriptors to 'impossible' values. This is
sewardj6e31f802007-11-17 22:29:25 +00003122 noticed by send_bytes_to_logging_sink in m_libcprint.c, which
sewardj738856f2009-07-15 14:48:32 +00003123 duly stops writing any further output. */
3124 if (VG_(clo_child_silent_after_fork)) {
3125 if (!VG_(log_output_sink).is_socket)
3126 VG_(log_output_sink).fd = -1;
3127 if (!VG_(xml_output_sink).is_socket)
3128 VG_(xml_output_sink).fd = -1;
3129 }
njn58bbd942009-05-21 23:59:34 +00003130
njnf76d27a2009-05-28 01:53:07 +00003131 } else {
njne9ba34a2008-10-13 04:19:15 +00003132 VG_(do_atfork_parent)(tid);
3133
njn58bbd942009-05-21 23:59:34 +00003134 PRINT(" fork: process %d created child %d\n", VG_(getpid)(), child_pid);
jsgf855d93d2003-10-13 22:26:55 +00003135
jsgf855d93d2003-10-13 22:26:55 +00003136 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00003137 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +00003138 }
3139}
3140
sewardj8c257322005-06-08 01:01:48 +00003141PRE(sys_ftruncate)
3142{
3143 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003144 PRINT("sys_ftruncate ( %ld, %ld )", ARG1,ARG2);
sewardj8c257322005-06-08 01:01:48 +00003145 PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
3146}
3147
sewardj696c5512005-06-08 23:38:32 +00003148PRE(sys_truncate)
3149{
3150 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003151 PRINT("sys_truncate ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003152 PRE_REG_READ2(long, "truncate",
3153 const char *, path, unsigned long, length);
3154 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
3155}
3156
sewardje6d5e722005-06-10 10:27:55 +00003157PRE(sys_ftruncate64)
3158{
3159 *flags |= SfMayBlock;
njn89d43f72009-05-24 23:02:55 +00003160#if VG_WORDSIZE == 4
tomca787242009-11-25 11:24:00 +00003161 PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, MERGE64(ARG2,ARG3));
sewardje6d5e722005-06-10 10:27:55 +00003162 PRE_REG_READ3(long, "ftruncate64",
3163 unsigned int, fd,
tomca787242009-11-25 11:24:00 +00003164 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
njn89d43f72009-05-24 23:02:55 +00003165#else
3166 PRINT("sys_ftruncate64 ( %ld, %lld )", ARG1, (Long)ARG2);
3167 PRE_REG_READ2(long, "ftruncate64",
3168 unsigned int,fd, UWord,length);
sewardje6d5e722005-06-10 10:27:55 +00003169#endif
njn89d43f72009-05-24 23:02:55 +00003170}
sewardje6d5e722005-06-10 10:27:55 +00003171
sewardje6d5e722005-06-10 10:27:55 +00003172PRE(sys_truncate64)
3173{
3174 *flags |= SfMayBlock;
njn89d43f72009-05-24 23:02:55 +00003175#if VG_WORDSIZE == 4
tomca787242009-11-25 11:24:00 +00003176 PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)MERGE64(ARG2, ARG3));
sewardje6d5e722005-06-10 10:27:55 +00003177 PRE_REG_READ3(long, "truncate64",
3178 const char *, path,
tomca787242009-11-25 11:24:00 +00003179 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
njn89d43f72009-05-24 23:02:55 +00003180#else
3181 PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)ARG2);
3182 PRE_REG_READ2(long, "truncate64",
3183 const char *,path, UWord,length);
3184#endif
sewardje6d5e722005-06-10 10:27:55 +00003185 PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
3186}
sewardj78b50e42005-06-08 01:47:28 +00003187
3188PRE(sys_getdents)
3189{
3190 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003191 PRINT("sys_getdents ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
sewardj78b50e42005-06-08 01:47:28 +00003192 PRE_REG_READ3(long, "getdents",
3193 unsigned int, fd, struct linux_dirent *, dirp,
3194 unsigned int, count);
3195 PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
3196}
3197
3198POST(sys_getdents)
3199{
3200 vg_assert(SUCCESS);
3201 if (RES > 0)
3202 POST_MEM_WRITE( ARG2, RES );
3203}
jsgf855d93d2003-10-13 22:26:55 +00003204
sewardja8d8e232005-06-07 20:04:56 +00003205PRE(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00003206{
sewardj78b50e42005-06-08 01:47:28 +00003207 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003208 PRINT("sys_getdents64 ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00003209 PRE_REG_READ3(long, "getdents64",
3210 unsigned int, fd, struct linux_dirent64 *, dirp,
3211 unsigned int, count);
njn22cfccb2004-11-27 16:10:23 +00003212 PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00003213}
3214
nethercote85a456f2004-11-16 17:31:56 +00003215POST(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00003216{
sewardja8d8e232005-06-07 20:04:56 +00003217 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003218 if (RES > 0)
3219 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00003220}
3221
sewardj78b50e42005-06-08 01:47:28 +00003222PRE(sys_getgroups)
3223{
barta0b6b2c2008-07-07 06:49:24 +00003224 PRINT("sys_getgroups ( %ld, %#lx )", ARG1, ARG2);
sewardj78b50e42005-06-08 01:47:28 +00003225 PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
3226 if (ARG1 > 0)
3227 PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
3228}
3229
3230POST(sys_getgroups)
3231{
3232 vg_assert(SUCCESS);
3233 if (ARG1 > 0 && RES > 0)
3234 POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
3235}
nethercote686b5db2004-11-14 13:42:51 +00003236
sewardja8d8e232005-06-07 20:04:56 +00003237PRE(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00003238{
njn4b70e8c2005-08-14 17:36:07 +00003239 // Comment from linux/fs/dcache.c:
3240 // NOTE! The user-level library version returns a character pointer.
3241 // The kernel system call just returns the length of the buffer filled
3242 // (which includes the ending '\0' character), or a negative error
3243 // value.
3244 // Is this Linux-specific? If so it should be moved to syswrap-linux.c.
barta0b6b2c2008-07-07 06:49:24 +00003245 PRINT("sys_getcwd ( %#lx, %llu )", ARG1,(ULong)ARG2);
nethercoteac866b92004-11-15 20:23:15 +00003246 PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
njn22cfccb2004-11-27 16:10:23 +00003247 PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00003248}
3249
nethercote85a456f2004-11-16 17:31:56 +00003250POST(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00003251{
sewardja8d8e232005-06-07 20:04:56 +00003252 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003253 if (RES != (Addr)NULL)
3254 POST_MEM_WRITE( ARG1, RES );
jsgf855d93d2003-10-13 22:26:55 +00003255}
3256
sewardja8d8e232005-06-07 20:04:56 +00003257PRE(sys_geteuid)
jsgf855d93d2003-10-13 22:26:55 +00003258{
nethercote0df495a2004-11-11 16:38:21 +00003259 PRINT("sys_geteuid ( )");
3260 PRE_REG_READ0(long, "geteuid");
jsgf855d93d2003-10-13 22:26:55 +00003261}
3262
sewardj78b50e42005-06-08 01:47:28 +00003263PRE(sys_getegid)
3264{
3265 PRINT("sys_getegid ( )");
3266 PRE_REG_READ0(long, "getegid");
3267}
3268
sewardj78b50e42005-06-08 01:47:28 +00003269PRE(sys_getgid)
3270{
3271 PRINT("sys_getgid ( )");
3272 PRE_REG_READ0(long, "getgid");
3273}
jsgf855d93d2003-10-13 22:26:55 +00003274
sewardja8d8e232005-06-07 20:04:56 +00003275PRE(sys_getpid)
jsgf855d93d2003-10-13 22:26:55 +00003276{
nethercote4e632c22004-11-09 16:45:33 +00003277 PRINT("sys_getpid ()");
3278 PRE_REG_READ0(long, "getpid");
jsgf855d93d2003-10-13 22:26:55 +00003279}
3280
sewardj696c5512005-06-08 23:38:32 +00003281PRE(sys_getpgid)
3282{
barta0b6b2c2008-07-07 06:49:24 +00003283 PRINT("sys_getpgid ( %ld )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00003284 PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
3285}
sewardj78b50e42005-06-08 01:47:28 +00003286
3287PRE(sys_getpgrp)
3288{
3289 PRINT("sys_getpgrp ()");
3290 PRE_REG_READ0(long, "getpgrp");
3291}
jsgf855d93d2003-10-13 22:26:55 +00003292
sewardja8d8e232005-06-07 20:04:56 +00003293PRE(sys_getppid)
jsgf855d93d2003-10-13 22:26:55 +00003294{
nethercote4e632c22004-11-09 16:45:33 +00003295 PRINT("sys_getppid ()");
3296 PRE_REG_READ0(long, "getppid");
jsgf855d93d2003-10-13 22:26:55 +00003297}
3298
njncf45fd42004-11-24 16:30:22 +00003299static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
jsgf855d93d2003-10-13 22:26:55 +00003300{
nethercote620154f2004-11-12 21:21:07 +00003301 POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00003302
njnf76d27a2009-05-28 01:53:07 +00003303#ifdef _RLIMIT_POSIX_FLAG
3304 // Darwin will sometimes set _RLIMIT_POSIX_FLAG on getrlimit calls.
3305 // Unset it here to make the switch case below work correctly.
3306 a1 &= ~_RLIMIT_POSIX_FLAG;
3307#endif
3308
nethercote620154f2004-11-12 21:21:07 +00003309 switch (a1) {
3310 case VKI_RLIMIT_NOFILE:
3311 ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
3312 ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
3313 break;
nethercote535f03b2004-02-15 15:32:51 +00003314
nethercote620154f2004-11-12 21:21:07 +00003315 case VKI_RLIMIT_DATA:
3316 *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
3317 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00003318
nethercote620154f2004-11-12 21:21:07 +00003319 case VKI_RLIMIT_STACK:
3320 *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3321 break;
njn89d43f72009-05-24 23:02:55 +00003322 }
jsgf855d93d2003-10-13 22:26:55 +00003323}
3324
sewardj696c5512005-06-08 23:38:32 +00003325PRE(sys_old_getrlimit)
3326{
barta0b6b2c2008-07-07 06:49:24 +00003327 PRINT("sys_old_getrlimit ( %ld, %#lx )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003328 PRE_REG_READ2(long, "old_getrlimit",
3329 unsigned int, resource, struct rlimit *, rlim);
3330 PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3331}
3332
3333POST(sys_old_getrlimit)
3334{
3335 common_post_getrlimit(tid, ARG1, ARG2);
3336}
nethercote620154f2004-11-12 21:21:07 +00003337
sewardja8d8e232005-06-07 20:04:56 +00003338PRE(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003339{
barta0b6b2c2008-07-07 06:49:24 +00003340 PRINT("sys_getrlimit ( %ld, %#lx )", ARG1,ARG2);
nethercote620154f2004-11-12 21:21:07 +00003341 PRE_REG_READ2(long, "getrlimit",
3342 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00003343 PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
nethercote620154f2004-11-12 21:21:07 +00003344}
3345
nethercote85a456f2004-11-16 17:31:56 +00003346POST(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003347{
njn22cfccb2004-11-27 16:10:23 +00003348 common_post_getrlimit(tid, ARG1, ARG2);
nethercote620154f2004-11-12 21:21:07 +00003349}
jsgf855d93d2003-10-13 22:26:55 +00003350
sewardj696c5512005-06-08 23:38:32 +00003351PRE(sys_getrusage)
3352{
barta0b6b2c2008-07-07 06:49:24 +00003353 PRINT("sys_getrusage ( %ld, %#lx )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003354 PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3355 PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3356}
3357
3358POST(sys_getrusage)
3359{
3360 vg_assert(SUCCESS);
3361 if (RES == 0)
3362 POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3363}
jsgf855d93d2003-10-13 22:26:55 +00003364
sewardja8d8e232005-06-07 20:04:56 +00003365PRE(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003366{
barta0b6b2c2008-07-07 06:49:24 +00003367 PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
nethercote686b5db2004-11-14 13:42:51 +00003368 PRE_REG_READ2(long, "gettimeofday",
3369 struct timeval *, tv, struct timezone *, tz);
njnf76d27a2009-05-28 01:53:07 +00003370 // GrP fixme does darwin write to *tz anymore?
njn72bbd8d2009-05-22 08:12:46 +00003371 if (ARG1 != 0)
3372 PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
njn22cfccb2004-11-27 16:10:23 +00003373 if (ARG2 != 0)
3374 PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003375}
3376
nethercote85a456f2004-11-16 17:31:56 +00003377POST(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003378{
sewardja8d8e232005-06-07 20:04:56 +00003379 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003380 if (RES == 0) {
njn72bbd8d2009-05-22 08:12:46 +00003381 if (ARG1 != 0)
3382 POST_timeval_WRITE( ARG1 );
njn22cfccb2004-11-27 16:10:23 +00003383 if (ARG2 != 0)
3384 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003385 }
3386}
3387
sewardj696c5512005-06-08 23:38:32 +00003388PRE(sys_settimeofday)
3389{
barta0b6b2c2008-07-07 06:49:24 +00003390 PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003391 PRE_REG_READ2(long, "settimeofday",
3392 struct timeval *, tv, struct timezone *, tz);
njn72bbd8d2009-05-22 08:12:46 +00003393 if (ARG1 != 0)
njnda8549d2009-05-25 01:48:59 +00003394 PRE_timeval_READ( "settimeofday(tv)", ARG1 );
sewardj696c5512005-06-08 23:38:32 +00003395 if (ARG2 != 0) {
3396 PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3397 /* maybe should warn if tz->tz_dsttime is non-zero? */
3398 }
3399}
nethercote686b5db2004-11-14 13:42:51 +00003400
sewardja8d8e232005-06-07 20:04:56 +00003401PRE(sys_getuid)
jsgf855d93d2003-10-13 22:26:55 +00003402{
nethercote0df495a2004-11-11 16:38:21 +00003403 PRINT("sys_getuid ( )");
3404 PRE_REG_READ0(long, "getuid");
jsgf855d93d2003-10-13 22:26:55 +00003405}
3406
njn1be9cf62009-05-22 00:15:06 +00003407void ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg)
3408{
3409 /* We don't have any specific information on it, so
3410 try to do something reasonable based on direction and
3411 size bits. The encoding scheme is described in
3412 /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3413
3414 According to Simon Hausmann, _IOC_READ means the kernel
3415 writes a value to the ioctl value passed from the user
3416 space and the other way around with _IOC_WRITE. */
3417
3418 UInt dir = _VKI_IOC_DIR(request);
3419 UInt size = _VKI_IOC_SIZE(request);
3420 if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) {
3421 /*
3422 * Be very lax about ioctl handling; the only
3423 * assumption is that the size is correct. Doesn't
3424 * require the full buffer to be initialized when
3425 * writing. Without this, using some device
3426 * drivers with a large number of strange ioctl
3427 * commands becomes very tiresome.
3428 */
3429 } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
3430 //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
3431 //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3432 static Int moans = 3;
3433 if (moans > 0 && !VG_(clo_xml)) {
3434 moans--;
sewardj738856f2009-07-15 14:48:32 +00003435 VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
3436 " with no size/direction hints\n", request);
3437 VG_(umsg)(" This could cause spurious value errors to appear.\n");
3438 VG_(umsg)(" See README_MISSING_SYSCALL_OR_IOCTL for "
3439 "guidance on writing a proper wrapper.\n" );
njn1be9cf62009-05-22 00:15:06 +00003440 }
3441 } else {
3442 //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
3443 //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3444 if ((dir & _VKI_IOC_WRITE) && size > 0)
3445 PRE_MEM_READ( "ioctl(generic)", arg, size);
3446 if ((dir & _VKI_IOC_READ) && size > 0)
3447 PRE_MEM_WRITE( "ioctl(generic)", arg, size);
3448 }
3449}
3450
3451void ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg)
3452{
3453 /* We don't have any specific information on it, so
3454 try to do something reasonable based on direction and
3455 size bits. The encoding scheme is described in
3456 /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3457
3458 According to Simon Hausmann, _IOC_READ means the kernel
3459 writes a value to the ioctl value passed from the user
3460 space and the other way around with _IOC_WRITE. */
3461
3462 UInt dir = _VKI_IOC_DIR(request);
3463 UInt size = _VKI_IOC_SIZE(request);
3464 if (size > 0 && (dir & _VKI_IOC_READ)
3465 && res == 0
3466 && arg != (Addr)NULL)
3467 {
3468 POST_MEM_WRITE(arg, size);
3469 }
3470}
jsgf855d93d2003-10-13 22:26:55 +00003471
njn03f1e582005-03-26 20:08:06 +00003472/*
3473 If we're sending a SIGKILL to one of our own threads, then simulate
3474 it rather than really sending the signal, so that the target thread
3475 gets a chance to clean up. Returns True if we did the killing (or
3476 no killing is necessary), and False if the caller should use the
3477 normal kill syscall.
3478
3479 "pid" is any pid argument which can be passed to kill; group kills
3480 (< -1, 0), and owner kills (-1) are ignored, on the grounds that
3481 they'll most likely hit all the threads and we won't need to worry
3482 about cleanup. In truth, we can't fully emulate these multicast
3483 kills.
3484
3485 "tgid" is a thread group id. If it is not -1, then the target
3486 thread must be in that thread group.
3487 */
sewardj7eb7c582005-06-23 01:02:53 +00003488Bool ML_(do_sigkill)(Int pid, Int tgid)
njn03f1e582005-03-26 20:08:06 +00003489{
3490 ThreadState *tst;
3491 ThreadId tid;
3492
3493 if (pid <= 0)
3494 return False;
3495
sewardj42781722006-12-17 19:36:06 +00003496 tid = VG_(lwpid_to_vgtid)(pid);
njn03f1e582005-03-26 20:08:06 +00003497 if (tid == VG_INVALID_THREADID)
3498 return False; /* none of our threads */
3499
3500 tst = VG_(get_ThreadState)(tid);
3501 if (tst == NULL || tst->status == VgTs_Empty)
3502 return False; /* hm, shouldn't happen */
3503
3504 if (tgid != -1 && tst->os_state.threadgroup != tgid)
3505 return False; /* not the right thread group */
3506
3507 /* Check to see that the target isn't already exiting. */
3508 if (!VG_(is_exiting)(tid)) {
3509 if (VG_(clo_trace_signals))
sewardj738856f2009-07-15 14:48:32 +00003510 VG_(message)(Vg_DebugMsg,
3511 "Thread %d being killed with SIGKILL\n",
3512 tst->tid);
njn03f1e582005-03-26 20:08:06 +00003513
3514 tst->exitreason = VgSrc_FatalSig;
3515 tst->os_state.fatalsig = VKI_SIGKILL;
3516
3517 if (!VG_(is_running_thread)(tid))
sewardjef1cf8b2006-10-17 01:47:30 +00003518 VG_(get_thread_out_of_syscall)(tid);
njn03f1e582005-03-26 20:08:06 +00003519 }
3520
3521 return True;
3522}
3523
sewardja8d8e232005-06-07 20:04:56 +00003524PRE(sys_kill)
jsgf855d93d2003-10-13 22:26:55 +00003525{
barta0b6b2c2008-07-07 06:49:24 +00003526 PRINT("sys_kill ( %ld, %ld )", ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00003527 PRE_REG_READ2(long, "kill", int, pid, int, sig);
sewardj7eb7c582005-06-23 01:02:53 +00003528 if (!ML_(client_signal_OK)(ARG2)) {
sewardja8d8e232005-06-07 20:04:56 +00003529 SET_STATUS_Failure( VKI_EINVAL );
njn03f1e582005-03-26 20:08:06 +00003530 return;
3531 }
jsgf855d93d2003-10-13 22:26:55 +00003532
njn03f1e582005-03-26 20:08:06 +00003533 /* If we're sending SIGKILL, check to see if the target is one of
3534 our threads and handle it specially. */
sewardj7eb7c582005-06-23 01:02:53 +00003535 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
sewardja8d8e232005-06-07 20:04:56 +00003536 SET_STATUS_Success(0);
njn03f1e582005-03-26 20:08:06 +00003537 else
njncda2f0f2009-05-18 02:12:08 +00003538 /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean)
3539 affecting how posix-compliant the call is. I guess it is
3540 harmless to pass the 3rd arg on other platforms; hence pass
3541 it on all. */
3542 SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) );
njn03f1e582005-03-26 20:08:06 +00003543
sewardjb5f6f512005-03-10 23:59:00 +00003544 if (VG_(clo_trace_signals))
sewardj738856f2009-07-15 14:48:32 +00003545 VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld\n",
njn03f1e582005-03-26 20:08:06 +00003546 ARG2, ARG1);
sewardja8d8e232005-06-07 20:04:56 +00003547
3548 /* This kill might have given us a pending signal. Ask for a check once
3549 the syscall is done. */
3550 *flags |= SfPollAfter;
jsgf855d93d2003-10-13 22:26:55 +00003551}
3552
sewardja8d8e232005-06-07 20:04:56 +00003553PRE(sys_link)
jsgf855d93d2003-10-13 22:26:55 +00003554{
sewardja8d8e232005-06-07 20:04:56 +00003555 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003556 PRINT("sys_link ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00003557 PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00003558 PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
3559 PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
jsgf855d93d2003-10-13 22:26:55 +00003560}
3561
sewardj696c5512005-06-08 23:38:32 +00003562PRE(sys_newlstat)
3563{
barta0b6b2c2008-07-07 06:49:24 +00003564 PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003565 PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
3566 PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
3567 PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
3568}
3569
3570POST(sys_newlstat)
3571{
3572 vg_assert(SUCCESS);
njn9331c7b2009-06-15 07:43:50 +00003573 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
sewardj696c5512005-06-08 23:38:32 +00003574}
jsgf855d93d2003-10-13 22:26:55 +00003575
sewardja8d8e232005-06-07 20:04:56 +00003576PRE(sys_mkdir)
jsgf855d93d2003-10-13 22:26:55 +00003577{
sewardja8d8e232005-06-07 20:04:56 +00003578 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003579 PRINT("sys_mkdir ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00003580 PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00003581 PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003582}
3583
sewardja8d8e232005-06-07 20:04:56 +00003584PRE(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00003585{
barta0b6b2c2008-07-07 06:49:24 +00003586 PRINT("sys_mprotect ( %#lx, %llu, %ld )", ARG1,(ULong)ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00003587 PRE_REG_READ3(long, "mprotect",
3588 unsigned long, addr, vki_size_t, len, unsigned long, prot);
fitzhardinge98abfc72003-12-16 02:05:15 +00003589
tom65505192005-11-08 16:51:55 +00003590 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
sewardja8d8e232005-06-07 20:04:56 +00003591 SET_STATUS_Failure( VKI_ENOMEM );
sewardj337556e2005-11-09 14:51:59 +00003592 }
njnf76d27a2009-05-28 01:53:07 +00003593#if defined(VKI_PROT_GROWSDOWN)
sewardj337556e2005-11-09 14:51:59 +00003594 else
3595 if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
3596 /* Deal with mprotects on growable stack areas.
3597
3598 The critical files to understand all this are mm/mprotect.c
3599 in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
3600 glibc.
3601
3602 The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
3603 round the start/end address of mprotect to the start/end of
3604 the underlying vma and glibc uses that as an easy way to
3605 change the protection of the stack by calling mprotect on the
3606 last page of the stack with PROT_GROWSDOWN set.
3607
3608 The sanity check provided by the kernel is that the vma must
3609 have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */
tom65505192005-11-08 16:51:55 +00003610 UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
sewardjef1cf8b2006-10-17 01:47:30 +00003611 NSegment const *aseg = VG_(am_find_nsegment)(ARG1);
3612 NSegment const *rseg;
tom65505192005-11-08 16:51:55 +00003613
3614 vg_assert(aseg);
3615
3616 if (grows == VKI_PROT_GROWSDOWN) {
florian3e798632012-11-24 19:41:54 +00003617 rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ );
tom65505192005-11-08 16:51:55 +00003618 if (rseg &&
3619 rseg->kind == SkResvn &&
3620 rseg->smode == SmUpper &&
3621 rseg->end+1 == aseg->start) {
3622 Addr end = ARG1 + ARG2;
3623 ARG1 = aseg->start;
3624 ARG2 = end - aseg->start;
3625 ARG3 &= ~VKI_PROT_GROWSDOWN;
3626 } else {
3627 SET_STATUS_Failure( VKI_EINVAL );
3628 }
3629 } else if (grows == VKI_PROT_GROWSUP) {
florian3e798632012-11-24 19:41:54 +00003630 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
tom65505192005-11-08 16:51:55 +00003631 if (rseg &&
3632 rseg->kind == SkResvn &&
3633 rseg->smode == SmLower &&
3634 aseg->end+1 == rseg->start) {
3635 ARG2 = aseg->end - ARG1 + 1;
3636 ARG3 &= ~VKI_PROT_GROWSUP;
3637 } else {
3638 SET_STATUS_Failure( VKI_EINVAL );
3639 }
3640 } else {
sewardj337556e2005-11-09 14:51:59 +00003641 /* both GROWSUP and GROWSDOWN */
tom65505192005-11-08 16:51:55 +00003642 SET_STATUS_Failure( VKI_EINVAL );
3643 }
3644 }
njnf76d27a2009-05-28 01:53:07 +00003645#endif // defined(VKI_PROT_GROWSDOWN)
jsgf855d93d2003-10-13 22:26:55 +00003646}
3647
nethercote85a456f2004-11-16 17:31:56 +00003648POST(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00003649{
njn22cfccb2004-11-27 16:10:23 +00003650 Addr a = ARG1;
3651 SizeT len = ARG2;
3652 Int prot = ARG3;
nethercote27ea8bc2004-07-10 17:21:14 +00003653
njndd372582009-05-10 22:42:19 +00003654 ML_(notify_core_and_tool_of_mprotect)(a, len, prot);
jsgf855d93d2003-10-13 22:26:55 +00003655}
3656
sewardja8d8e232005-06-07 20:04:56 +00003657PRE(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00003658{
barta0b6b2c2008-07-07 06:49:24 +00003659 if (0) VG_(printf)(" munmap( %#lx )\n", ARG1);
3660 PRINT("sys_munmap ( %#lx, %llu )", ARG1,(ULong)ARG2);
nethercote06c7bd72004-11-14 19:11:56 +00003661 PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
fitzhardinge98abfc72003-12-16 02:05:15 +00003662
sewardj7eb7c582005-06-23 01:02:53 +00003663 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
sewardja8d8e232005-06-07 20:04:56 +00003664 SET_STATUS_Failure( VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00003665}
3666
nethercote85a456f2004-11-16 17:31:56 +00003667POST(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00003668{
njn22cfccb2004-11-27 16:10:23 +00003669 Addr a = ARG1;
3670 SizeT len = ARG2;
nethercote27ea8bc2004-07-10 17:21:14 +00003671
njndd372582009-05-10 22:42:19 +00003672 ML_(notify_core_and_tool_of_munmap)( (Addr64)a, (ULong)len );
jsgf855d93d2003-10-13 22:26:55 +00003673}
3674
sewardje6d5e722005-06-10 10:27:55 +00003675PRE(sys_mincore)
3676{
barta0b6b2c2008-07-07 06:49:24 +00003677 PRINT("sys_mincore ( %#lx, %llu, %#lx )", ARG1,(ULong)ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003678 PRE_REG_READ3(long, "mincore",
3679 unsigned long, start, vki_size_t, length,
3680 unsigned char *, vec);
njncdaec512005-06-30 00:16:02 +00003681 PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00003682}
3683POST(sys_mincore)
3684{
njncdaec512005-06-30 00:16:02 +00003685 POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00003686}
mueller6ceb2312004-01-02 22:52:34 +00003687
sewardja8d8e232005-06-07 20:04:56 +00003688PRE(sys_nanosleep)
mueller6ceb2312004-01-02 22:52:34 +00003689{
sewardja8d8e232005-06-07 20:04:56 +00003690 *flags |= SfMayBlock|SfPostOnFail;
barta0b6b2c2008-07-07 06:49:24 +00003691 PRINT("sys_nanosleep ( %#lx, %#lx )", ARG1,ARG2);
nethercote5b653bc2004-11-15 14:32:12 +00003692 PRE_REG_READ2(long, "nanosleep",
3693 struct timespec *, req, struct timespec *, rem);
njn22cfccb2004-11-27 16:10:23 +00003694 PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
3695 if (ARG2 != 0)
3696 PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00003697}
3698
nethercote85a456f2004-11-16 17:31:56 +00003699POST(sys_nanosleep)
jsgf855d93d2003-10-13 22:26:55 +00003700{
sewardja8d8e232005-06-07 20:04:56 +00003701 vg_assert(SUCCESS || FAILURE);
sewardjef1cf8b2006-10-17 01:47:30 +00003702 if (ARG2 != 0 && FAILURE && ERR == VKI_EINTR)
njn22cfccb2004-11-27 16:10:23 +00003703 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00003704}
3705
sewardja8d8e232005-06-07 20:04:56 +00003706PRE(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00003707{
njn22cfccb2004-11-27 16:10:23 +00003708 if (ARG2 & VKI_O_CREAT) {
nethercotee824cc42004-11-09 16:20:46 +00003709 // 3-arg version
barta0b6b2c2008-07-07 06:49:24 +00003710 PRINT("sys_open ( %#lx(%s), %ld, %ld )",ARG1,(char*)ARG1,ARG2,ARG3);
nethercotee824cc42004-11-09 16:20:46 +00003711 PRE_REG_READ3(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00003712 const char *, filename, int, flags, int, mode);
nethercotee70bd7d2004-08-18 14:37:17 +00003713 } else {
nethercotee824cc42004-11-09 16:20:46 +00003714 // 2-arg version
barta0b6b2c2008-07-07 06:49:24 +00003715 PRINT("sys_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
nethercotee824cc42004-11-09 16:20:46 +00003716 PRE_REG_READ2(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00003717 const char *, filename, int, flags);
nethercotee70bd7d2004-08-18 14:37:17 +00003718 }
njn22cfccb2004-11-27 16:10:23 +00003719 PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
sewardj45f4e7c2005-09-27 19:20:21 +00003720
bart9b533f82009-08-25 20:15:41 +00003721#if defined(VGO_linux)
3722 /* Handle the case where the open is of /proc/self/cmdline or
3723 /proc/<pid>/cmdline, and just give it a copy of the fd for the
3724 fake file we cooked up at startup (in m_main). Also, seek the
3725 cloned fd back to the start. */
njn70fa47d2009-05-24 22:32:33 +00003726 {
3727 HChar name[30];
florian19f91bb2012-11-10 22:29:54 +00003728 HChar* arg1s = (HChar*) ARG1;
njn70fa47d2009-05-24 22:32:33 +00003729 SysRes sres;
sewardj45f4e7c2005-09-27 19:20:21 +00003730
njn70fa47d2009-05-24 22:32:33 +00003731 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
3732 if (ML_(safe_to_deref)( arg1s, 1 ) &&
3733 (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/cmdline"))
3734 )
3735 {
3736 sres = VG_(dup)( VG_(cl_cmdline_fd) );
3737 SET_STATUS_from_SysRes( sres );
3738 if (!sr_isError(sres)) {
3739 OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
3740 if (off < 0)
3741 SET_STATUS_Failure( VKI_EMFILE );
3742 }
3743 return;
sewardj45f4e7c2005-09-27 19:20:21 +00003744 }
sewardj45f4e7c2005-09-27 19:20:21 +00003745 }
tom41ad7e72012-10-04 20:27:38 +00003746
3747 /* Handle the case where the open is of /proc/self/auxv or
3748 /proc/<pid>/auxv, and just give it a copy of the fd for the
3749 fake file we cooked up at startup (in m_main). Also, seek the
3750 cloned fd back to the start. */
3751 {
3752 HChar name[30];
florian19f91bb2012-11-10 22:29:54 +00003753 HChar* arg1s = (HChar*) ARG1;
tom41ad7e72012-10-04 20:27:38 +00003754 SysRes sres;
3755
3756 VG_(sprintf)(name, "/proc/%d/auxv", VG_(getpid)());
3757 if (ML_(safe_to_deref)( arg1s, 1 ) &&
3758 (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/auxv"))
3759 )
3760 {
3761 sres = VG_(dup)( VG_(cl_auxv_fd) );
3762 SET_STATUS_from_SysRes( sres );
3763 if (!sr_isError(sres)) {
3764 OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
3765 if (off < 0)
3766 SET_STATUS_Failure( VKI_EMFILE );
3767 }
3768 return;
3769 }
3770 }
bart9b533f82009-08-25 20:15:41 +00003771#endif // defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +00003772
3773 /* Otherwise handle normally */
3774 *flags |= SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00003775}
3776
nethercote85a456f2004-11-16 17:31:56 +00003777POST(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00003778{
sewardja8d8e232005-06-07 20:04:56 +00003779 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00003780 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00003781 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00003782 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00003783 } else {
nethercote493dd182004-02-24 23:57:47 +00003784 if (VG_(clo_track_fds))
florian19f91bb2012-11-10 22:29:54 +00003785 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00003786 }
jsgf855d93d2003-10-13 22:26:55 +00003787}
3788
sewardja8d8e232005-06-07 20:04:56 +00003789PRE(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00003790{
sewardja8d8e232005-06-07 20:04:56 +00003791 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003792 PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00003793 PRE_REG_READ3(ssize_t, "read",
njnca0518d2004-11-26 19:34:36 +00003794 unsigned int, fd, char *, buf, vki_size_t, count);
jsgf855d93d2003-10-13 22:26:55 +00003795
sewardj7eb7c582005-06-23 01:02:53 +00003796 if (!ML_(fd_allowed)(ARG1, "read", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00003797 SET_STATUS_Failure( VKI_EBADF );
thughes26ab77b2004-08-14 12:10:49 +00003798 else
njn22cfccb2004-11-27 16:10:23 +00003799 PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00003800}
3801
nethercote85a456f2004-11-16 17:31:56 +00003802POST(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00003803{
sewardja8d8e232005-06-07 20:04:56 +00003804 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003805 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00003806}
3807
sewardja8d8e232005-06-07 20:04:56 +00003808PRE(sys_write)
jsgf855d93d2003-10-13 22:26:55 +00003809{
sewardj45f4e7c2005-09-27 19:20:21 +00003810 Bool ok;
sewardja8d8e232005-06-07 20:04:56 +00003811 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003812 PRINT("sys_write ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00003813 PRE_REG_READ3(ssize_t, "write",
njnca0518d2004-11-26 19:34:36 +00003814 unsigned int, fd, const char *, buf, vki_size_t, count);
sewardj45f4e7c2005-09-27 19:20:21 +00003815 /* check to see if it is allowed. If not, try for an exemption from
njn628add62005-11-12 18:21:40 +00003816 --sim-hints=enable-outer (used for self hosting). */
sewardj45f4e7c2005-09-27 19:20:21 +00003817 ok = ML_(fd_allowed)(ARG1, "write", tid, False);
3818 if (!ok && ARG1 == 2/*stderr*/
njn628add62005-11-12 18:21:40 +00003819 && VG_(strstr)(VG_(clo_sim_hints),"enable-outer"))
sewardj45f4e7c2005-09-27 19:20:21 +00003820 ok = True;
3821 if (!ok)
sewardja8d8e232005-06-07 20:04:56 +00003822 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003823 else
njn22cfccb2004-11-27 16:10:23 +00003824 PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00003825}
3826
sewardja8d8e232005-06-07 20:04:56 +00003827PRE(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00003828{
sewardja8d8e232005-06-07 20:04:56 +00003829 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003830 PRINT("sys_creat ( %#lx(%s), %ld )", ARG1,(char*)ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00003831 PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00003832 PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003833}
3834
nethercote85a456f2004-11-16 17:31:56 +00003835POST(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00003836{
sewardja8d8e232005-06-07 20:04:56 +00003837 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00003838 if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00003839 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00003840 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00003841 } else {
nethercote493dd182004-02-24 23:57:47 +00003842 if (VG_(clo_track_fds))
florian19f91bb2012-11-10 22:29:54 +00003843 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00003844 }
jsgf855d93d2003-10-13 22:26:55 +00003845}
3846
sewardja8d8e232005-06-07 20:04:56 +00003847PRE(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00003848{
3849 /* struct pollfd {
nethercoteef0c7662004-11-06 15:38:43 +00003850 int fd; -- file descriptor
3851 short events; -- requested events
3852 short revents; -- returned events
jsgf855d93d2003-10-13 22:26:55 +00003853 };
nethercoteeb0592d2004-11-05 12:02:27 +00003854 int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
jsgf855d93d2003-10-13 22:26:55 +00003855 */
nethercoteeb0592d2004-11-05 12:02:27 +00003856 UInt i;
njn22cfccb2004-11-27 16:10:23 +00003857 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
tom60a4b0b2005-10-12 10:45:27 +00003858 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003859 PRINT("sys_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3);
nethercotef90953e2004-11-15 14:50:02 +00003860 PRE_REG_READ3(long, "poll",
tom363ec762006-03-21 10:58:35 +00003861 struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout);
3862
njn22cfccb2004-11-27 16:10:23 +00003863 for (i = 0; i < ARG2; i++) {
tom363ec762006-03-21 10:58:35 +00003864 PRE_MEM_READ( "poll(ufds.fd)",
3865 (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
3866 PRE_MEM_READ( "poll(ufds.events)",
3867 (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
tom68f338f2014-02-09 11:10:08 +00003868 PRE_MEM_WRITE( "poll(ufds.revents)",
tom363ec762006-03-21 10:58:35 +00003869 (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
3870 }
jsgf855d93d2003-10-13 22:26:55 +00003871}
3872
nethercote85a456f2004-11-16 17:31:56 +00003873POST(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00003874{
sewardj416b2062008-05-12 15:46:34 +00003875 if (RES >= 0) {
jsgf855d93d2003-10-13 22:26:55 +00003876 UInt i;
njn22cfccb2004-11-27 16:10:23 +00003877 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
njn22cfccb2004-11-27 16:10:23 +00003878 for (i = 0; i < ARG2; i++)
tom363ec762006-03-21 10:58:35 +00003879 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
jsgf855d93d2003-10-13 22:26:55 +00003880 }
3881}
3882
sewardja8d8e232005-06-07 20:04:56 +00003883PRE(sys_readlink)
jsgf855d93d2003-10-13 22:26:55 +00003884{
sewardjcc3de2d2011-08-18 15:08:20 +00003885 FUSE_COMPATIBLE_MAY_BLOCK();
njncc1284f2009-05-23 01:51:54 +00003886 Word saved = SYSNO;
sewardj144c56d2005-09-30 01:09:50 +00003887
barta0b6b2c2008-07-07 06:49:24 +00003888 PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
nethercote5a945af2004-11-14 18:37:07 +00003889 PRE_REG_READ3(long, "readlink",
3890 const char *, path, char *, buf, int, bufsiz);
njn22cfccb2004-11-27 16:10:23 +00003891 PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
3892 PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00003893
njncc1284f2009-05-23 01:51:54 +00003894 {
bart9b533f82009-08-25 20:15:41 +00003895#if defined(VGO_linux)
njncc1284f2009-05-23 01:51:54 +00003896 /*
3897 * Handle the case where readlink is looking at /proc/self/exe or
3898 * /proc/<pid>/exe.
3899 */
3900 HChar name[25];
florian19f91bb2012-11-10 22:29:54 +00003901 HChar* arg1s = (HChar*) ARG1;
njncc1284f2009-05-23 01:51:54 +00003902 VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
bart9b533f82009-08-25 20:15:41 +00003903 if (ML_(safe_to_deref)(arg1s, 1) &&
njncc1284f2009-05-23 01:51:54 +00003904 (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe"))
3905 )
3906 {
3907 VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
3908 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
3909 ARG2, ARG3));
3910 } else
bart9b533f82009-08-25 20:15:41 +00003911#endif // defined(VGO_linux)
njncc1284f2009-05-23 01:51:54 +00003912 {
3913 /* Normal case */
3914 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
3915 }
rjwalsh17d85302004-11-18 22:56:09 +00003916 }
3917
sewardja8d8e232005-06-07 20:04:56 +00003918 if (SUCCESS && RES > 0)
njn22cfccb2004-11-27 16:10:23 +00003919 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00003920}
3921
sewardja8d8e232005-06-07 20:04:56 +00003922PRE(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00003923{
jsgf855d93d2003-10-13 22:26:55 +00003924 Int i;
nethercote73b526f2004-10-31 18:48:21 +00003925 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00003926 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003927 PRINT("sys_readv ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00003928 PRE_REG_READ3(ssize_t, "readv",
3929 unsigned long, fd, const struct iovec *, vector,
3930 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00003931 if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00003932 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003933 } else {
njn22cfccb2004-11-27 16:10:23 +00003934 PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
nethercoted6b5a212004-11-15 17:04:14 +00003935
njn22cfccb2004-11-27 16:10:23 +00003936 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00003937 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00003938 vec = (struct vki_iovec *)ARG2;
3939 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00003940 PRE_MEM_WRITE( "readv(vector[...])",
3941 (Addr)vec[i].iov_base, vec[i].iov_len );
3942 }
jsgf855d93d2003-10-13 22:26:55 +00003943 }
3944}
3945
nethercote85a456f2004-11-16 17:31:56 +00003946POST(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00003947{
sewardja8d8e232005-06-07 20:04:56 +00003948 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003949 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00003950 Int i;
njn22cfccb2004-11-27 16:10:23 +00003951 struct vki_iovec * vec = (struct vki_iovec *)ARG2;
3952 Int remains = RES;
jsgf855d93d2003-10-13 22:26:55 +00003953
njn22cfccb2004-11-27 16:10:23 +00003954 /* RES holds the number of bytes read. */
3955 for (i = 0; i < (Int)ARG3; i++) {
jsgf855d93d2003-10-13 22:26:55 +00003956 Int nReadThisBuf = vec[i].iov_len;
3957 if (nReadThisBuf > remains) nReadThisBuf = remains;
nethercoteef0c7662004-11-06 15:38:43 +00003958 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
jsgf855d93d2003-10-13 22:26:55 +00003959 remains -= nReadThisBuf;
3960 if (remains < 0) VG_(core_panic)("readv: remains < 0");
3961 }
3962 }
3963}
3964
sewardja8d8e232005-06-07 20:04:56 +00003965PRE(sys_rename)
jsgf855d93d2003-10-13 22:26:55 +00003966{
sewardjcc3de2d2011-08-18 15:08:20 +00003967 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003968 PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00003969 PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00003970 PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
3971 PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00003972}
3973
sewardj78b50e42005-06-08 01:47:28 +00003974PRE(sys_rmdir)
3975{
3976 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003977 PRINT("sys_rmdir ( %#lx(%s) )", ARG1,(char*)ARG1);
sewardj78b50e42005-06-08 01:47:28 +00003978 PRE_REG_READ1(long, "rmdir", const char *, pathname);
3979 PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
3980}
3981
sewardja8d8e232005-06-07 20:04:56 +00003982PRE(sys_select)
jsgf855d93d2003-10-13 22:26:55 +00003983{
sewardja8d8e232005-06-07 20:04:56 +00003984 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003985 PRINT("sys_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotef1049bf2004-11-14 17:03:47 +00003986 PRE_REG_READ5(long, "select",
3987 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
tom363ec762006-03-21 10:58:35 +00003988 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
nethercotef1049bf2004-11-14 17:03:47 +00003989 // XXX: this possibly understates how much memory is read.
njn22cfccb2004-11-27 16:10:23 +00003990 if (ARG2 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00003991 PRE_MEM_READ( "select(readfds)",
njn22cfccb2004-11-27 16:10:23 +00003992 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
3993 if (ARG3 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00003994 PRE_MEM_READ( "select(writefds)",
njn22cfccb2004-11-27 16:10:23 +00003995 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
3996 if (ARG4 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00003997 PRE_MEM_READ( "select(exceptfds)",
njn22cfccb2004-11-27 16:10:23 +00003998 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
3999 if (ARG5 != 0)
njn72bbd8d2009-05-22 08:12:46 +00004000 PRE_timeval_READ( "select(timeout)", ARG5 );
nethercotef1049bf2004-11-14 17:03:47 +00004001}
4002
sewardje6d5e722005-06-10 10:27:55 +00004003PRE(sys_setgid)
4004{
barta0b6b2c2008-07-07 06:49:24 +00004005 PRINT("sys_setgid ( %ld )", ARG1);
sewardje6d5e722005-06-10 10:27:55 +00004006 PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
4007}
sewardj696c5512005-06-08 23:38:32 +00004008
4009PRE(sys_setsid)
4010{
4011 PRINT("sys_setsid ( )");
4012 PRE_REG_READ0(long, "setsid");
4013}
4014
sewardje6d5e722005-06-10 10:27:55 +00004015PRE(sys_setgroups)
4016{
barta0b6b2c2008-07-07 06:49:24 +00004017 PRINT("setgroups ( %llu, %#lx )", (ULong)ARG1, ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004018 PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
4019 if (ARG1 > 0)
4020 PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
4021}
sewardj696c5512005-06-08 23:38:32 +00004022
4023PRE(sys_setpgid)
4024{
barta0b6b2c2008-07-07 06:49:24 +00004025 PRINT("setpgid ( %ld, %ld )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00004026 PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
4027}
4028
4029PRE(sys_setregid)
4030{
barta0b6b2c2008-07-07 06:49:24 +00004031 PRINT("sys_setregid ( %ld, %ld )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00004032 PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
4033}
4034
sewardje6d5e722005-06-10 10:27:55 +00004035PRE(sys_setreuid)
4036{
barta0b6b2c2008-07-07 06:49:24 +00004037 PRINT("sys_setreuid ( 0x%lx, 0x%lx )", ARG1, ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004038 PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
4039}
nethercote9c311eb2004-11-12 18:20:12 +00004040
sewardja8d8e232005-06-07 20:04:56 +00004041PRE(sys_setrlimit)
jsgf855d93d2003-10-13 22:26:55 +00004042{
njnf76d27a2009-05-28 01:53:07 +00004043 UWord arg1 = ARG1;
barta0b6b2c2008-07-07 06:49:24 +00004044 PRINT("sys_setrlimit ( %ld, %#lx )", ARG1,ARG2);
nethercote17258dc2004-11-12 19:55:08 +00004045 PRE_REG_READ2(long, "setrlimit",
4046 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00004047 PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
fitzhardingeb50068f2004-02-24 23:42:55 +00004048
njnf76d27a2009-05-28 01:53:07 +00004049#ifdef _RLIMIT_POSIX_FLAG
4050 // Darwin will sometimes set _RLIMIT_POSIX_FLAG on setrlimit calls.
4051 // Unset it here to make the if statements below work correctly.
4052 arg1 &= ~_RLIMIT_POSIX_FLAG;
4053#endif
4054
tomaba260b2012-03-01 13:42:18 +00004055 if (ARG2 &&
4056 ((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max) {
4057 SET_STATUS_Failure( VKI_EINVAL );
4058 }
4059 else if (arg1 == VKI_RLIMIT_NOFILE) {
njn22cfccb2004-11-27 16:10:23 +00004060 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
4061 ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
sewardja8d8e232005-06-07 20:04:56 +00004062 SET_STATUS_Failure( VKI_EPERM );
thughesad1c9562004-06-26 11:27:52 +00004063 }
4064 else {
njn22cfccb2004-11-27 16:10:23 +00004065 VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
sewardja8d8e232005-06-07 20:04:56 +00004066 SET_STATUS_Success( 0 );
thughesad1c9562004-06-26 11:27:52 +00004067 }
4068 }
njnf76d27a2009-05-28 01:53:07 +00004069 else if (arg1 == VKI_RLIMIT_DATA) {
tomae0739d2006-03-20 15:36:28 +00004070 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_data).rlim_max ||
4071 ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_data).rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00004072 SET_STATUS_Failure( VKI_EPERM );
thughesaa4fb112004-09-11 14:19:25 +00004073 }
4074 else {
njn22cfccb2004-11-27 16:10:23 +00004075 VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00004076 SET_STATUS_Success( 0 );
thughesaa4fb112004-09-11 14:19:25 +00004077 }
fitzhardingeb50068f2004-02-24 23:42:55 +00004078 }
njnf76d27a2009-05-28 01:53:07 +00004079 else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
tomae0739d2006-03-20 15:36:28 +00004080 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_stack).rlim_max ||
4081 ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_stack).rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00004082 SET_STATUS_Failure( VKI_EPERM );
thughesc37184f2004-09-11 14:16:57 +00004083 }
4084 else {
sewardja8d8e232005-06-07 20:04:56 +00004085 VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
njn22cfccb2004-11-27 16:10:23 +00004086 VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00004087 SET_STATUS_Success( 0 );
thughesc37184f2004-09-11 14:16:57 +00004088 }
4089 }
jsgf855d93d2003-10-13 22:26:55 +00004090}
4091
sewardje6d5e722005-06-10 10:27:55 +00004092PRE(sys_setuid)
4093{
barta0b6b2c2008-07-07 06:49:24 +00004094 PRINT("sys_setuid ( %ld )", ARG1);
sewardje6d5e722005-06-10 10:27:55 +00004095 PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
4096}
jsgf855d93d2003-10-13 22:26:55 +00004097
sewardj696c5512005-06-08 23:38:32 +00004098PRE(sys_newstat)
4099{
barta0b6b2c2008-07-07 06:49:24 +00004100 PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00004101 PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
4102 PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
4103 PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
4104}
4105
4106POST(sys_newstat)
4107{
4108 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
4109}
4110
4111PRE(sys_statfs)
4112{
barta0b6b2c2008-07-07 06:49:24 +00004113 PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00004114 PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
4115 PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
4116 PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
4117}
sewardj696c5512005-06-08 23:38:32 +00004118POST(sys_statfs)
4119{
4120 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
4121}
4122
sewardje6d5e722005-06-10 10:27:55 +00004123PRE(sys_statfs64)
4124{
barta0b6b2c2008-07-07 06:49:24 +00004125 PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00004126 PRE_REG_READ3(long, "statfs64",
4127 const char *, path, vki_size_t, size, struct statfs64 *, buf);
4128 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4129 PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
4130}
4131POST(sys_statfs64)
4132{
4133 POST_MEM_WRITE( ARG3, ARG2 );
4134}
sewardj78b50e42005-06-08 01:47:28 +00004135
4136PRE(sys_symlink)
4137{
4138 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004139 PRINT("sys_symlink ( %#lx(%s), %#lx(%s) )",ARG1,(char*)ARG1,ARG2,(char*)ARG2);
sewardj78b50e42005-06-08 01:47:28 +00004140 PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
4141 PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
4142 PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
4143}
sewardj9efbbef2005-03-01 16:45:23 +00004144
sewardja8d8e232005-06-07 20:04:56 +00004145PRE(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00004146{
4147 /* time_t time(time_t *t); */
barta0b6b2c2008-07-07 06:49:24 +00004148 PRINT("sys_time ( %#lx )",ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00004149 PRE_REG_READ1(long, "time", int *, t);
njn22cfccb2004-11-27 16:10:23 +00004150 if (ARG1 != 0) {
4151 PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00004152 }
4153}
4154
nethercote85a456f2004-11-16 17:31:56 +00004155POST(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00004156{
njn22cfccb2004-11-27 16:10:23 +00004157 if (ARG1 != 0) {
4158 POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00004159 }
4160}
4161
sewardj78b50e42005-06-08 01:47:28 +00004162PRE(sys_times)
4163{
barta0b6b2c2008-07-07 06:49:24 +00004164 PRINT("sys_times ( %#lx )", ARG1);
sewardj78b50e42005-06-08 01:47:28 +00004165 PRE_REG_READ1(long, "times", struct tms *, buf);
tom18f19272005-07-18 11:03:35 +00004166 if (ARG1 != 0) {
4167 PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
4168 }
sewardj78b50e42005-06-08 01:47:28 +00004169}
4170
4171POST(sys_times)
4172{
4173 if (ARG1 != 0) {
4174 POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
4175 }
4176}
4177
4178PRE(sys_umask)
4179{
barta0b6b2c2008-07-07 06:49:24 +00004180 PRINT("sys_umask ( %ld )", ARG1);
sewardj78b50e42005-06-08 01:47:28 +00004181 PRE_REG_READ1(long, "umask", int, mask);
4182}
jsgf855d93d2003-10-13 22:26:55 +00004183
sewardja8d8e232005-06-07 20:04:56 +00004184PRE(sys_unlink)
jsgf855d93d2003-10-13 22:26:55 +00004185{
sewardja8d8e232005-06-07 20:04:56 +00004186 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004187 PRINT("sys_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00004188 PRE_REG_READ1(long, "unlink", const char *, pathname);
njn22cfccb2004-11-27 16:10:23 +00004189 PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004190}
4191
sewardja8d8e232005-06-07 20:04:56 +00004192PRE(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00004193{
barta0b6b2c2008-07-07 06:49:24 +00004194 PRINT("sys_newuname ( %#lx )", ARG1);
nethercote1a1b9b72004-11-12 11:19:36 +00004195 PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
njn22cfccb2004-11-27 16:10:23 +00004196 PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00004197}
4198
nethercote85a456f2004-11-16 17:31:56 +00004199POST(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00004200{
njn22cfccb2004-11-27 16:10:23 +00004201 if (ARG1 != 0) {
4202 POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00004203 }
4204}
4205
sewardja8d8e232005-06-07 20:04:56 +00004206PRE(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00004207{
sewardja8d8e232005-06-07 20:04:56 +00004208 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004209 PRINT("sys_waitpid ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
nethercotec6851dd2004-11-11 18:00:47 +00004210 PRE_REG_READ3(long, "waitpid",
4211 vki_pid_t, pid, unsigned int *, status, int, options);
jsgf855d93d2003-10-13 22:26:55 +00004212
njn22cfccb2004-11-27 16:10:23 +00004213 if (ARG2 != (Addr)NULL)
4214 PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00004215}
4216
nethercote85a456f2004-11-16 17:31:56 +00004217POST(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00004218{
njn22cfccb2004-11-27 16:10:23 +00004219 if (ARG2 != (Addr)NULL)
4220 POST_MEM_WRITE( ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00004221}
4222
sewardja8d8e232005-06-07 20:04:56 +00004223PRE(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00004224{
sewardja8d8e232005-06-07 20:04:56 +00004225 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004226 PRINT("sys_wait4 ( %ld, %#lx, %ld, %#lx )", ARG1,ARG2,ARG3,ARG4);
jsgf855d93d2003-10-13 22:26:55 +00004227
nethercote7f7e4d12004-11-15 12:28:58 +00004228 PRE_REG_READ4(long, "wait4",
4229 vki_pid_t, pid, unsigned int *, status, int, options,
4230 struct rusage *, rusage);
njn22cfccb2004-11-27 16:10:23 +00004231 if (ARG2 != (Addr)NULL)
4232 PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
4233 if (ARG4 != (Addr)NULL)
4234 PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00004235}
4236
nethercote85a456f2004-11-16 17:31:56 +00004237POST(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00004238{
njn22cfccb2004-11-27 16:10:23 +00004239 if (ARG2 != (Addr)NULL)
4240 POST_MEM_WRITE( ARG2, sizeof(int) );
4241 if (ARG4 != (Addr)NULL)
4242 POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00004243}
4244
sewardja8d8e232005-06-07 20:04:56 +00004245PRE(sys_writev)
jsgf855d93d2003-10-13 22:26:55 +00004246{
jsgf855d93d2003-10-13 22:26:55 +00004247 Int i;
nethercote73b526f2004-10-31 18:48:21 +00004248 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00004249 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004250 PRINT("sys_writev ( %ld, %#lx, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00004251 PRE_REG_READ3(ssize_t, "writev",
4252 unsigned long, fd, const struct iovec *, vector,
4253 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00004254 if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00004255 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004256 } else {
nethercoteef0c7662004-11-06 15:38:43 +00004257 PRE_MEM_READ( "writev(vector)",
njn22cfccb2004-11-27 16:10:23 +00004258 ARG2, ARG3 * sizeof(struct vki_iovec) );
4259 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00004260 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00004261 vec = (struct vki_iovec *)ARG2;
4262 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00004263 PRE_MEM_READ( "writev(vector[...])",
4264 (Addr)vec[i].iov_base, vec[i].iov_len );
4265 }
jsgf855d93d2003-10-13 22:26:55 +00004266 }
4267}
4268
sewardje6d5e722005-06-10 10:27:55 +00004269PRE(sys_utimes)
4270{
sewardjcc3de2d2011-08-18 15:08:20 +00004271 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00004272 PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004273 PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
4274 PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
njn72bbd8d2009-05-22 08:12:46 +00004275 if (ARG2 != 0) {
4276 PRE_timeval_READ( "utimes(tvp[0])", ARG2 );
4277 PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
4278 }
sewardje6d5e722005-06-10 10:27:55 +00004279}
4280
sewardj696c5512005-06-08 23:38:32 +00004281PRE(sys_acct)
4282{
barta0b6b2c2008-07-07 06:49:24 +00004283 PRINT("sys_acct ( %#lx(%s) )", ARG1,(char*)ARG1);
sewardj696c5512005-06-08 23:38:32 +00004284 PRE_REG_READ1(long, "acct", const char *, filename);
4285 PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
4286}
muellerd3502b62003-11-19 00:43:57 +00004287
sewardja8d8e232005-06-07 20:04:56 +00004288PRE(sys_pause)
thughes2f8d5f82004-09-11 14:29:19 +00004289{
sewardja8d8e232005-06-07 20:04:56 +00004290 *flags |= SfMayBlock;
nethercote0df495a2004-11-11 16:38:21 +00004291 PRINT("sys_pause ( )");
4292 PRE_REG_READ0(long, "pause");
jsgf855d93d2003-10-13 22:26:55 +00004293}
4294
sewardja8d8e232005-06-07 20:04:56 +00004295PRE(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00004296{
barta0b6b2c2008-07-07 06:49:24 +00004297 PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2);
nethercoteb77dee62004-11-16 17:13:24 +00004298 PRE_REG_READ2(int, "sigaltstack",
4299 const vki_stack_t *, ss, vki_stack_t *, oss);
njn22cfccb2004-11-27 16:10:23 +00004300 if (ARG1 != 0) {
tom92098db2005-07-18 23:18:10 +00004301 const vki_stack_t *ss = (vki_stack_t *)ARG1;
4302 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
4303 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
4304 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
jsgf855d93d2003-10-13 22:26:55 +00004305 }
njn22cfccb2004-11-27 16:10:23 +00004306 if (ARG2 != 0) {
4307 PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
jsgf855d93d2003-10-13 22:26:55 +00004308 }
4309
sewardja8d8e232005-06-07 20:04:56 +00004310 SET_STATUS_from_SysRes(
4311 VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
4312 (vki_stack_t*)ARG2)
4313 );
jsgf855d93d2003-10-13 22:26:55 +00004314}
nethercote85a456f2004-11-16 17:31:56 +00004315POST(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00004316{
sewardja8d8e232005-06-07 20:04:56 +00004317 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004318 if (RES == 0 && ARG2 != 0)
4319 POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
jsgf855d93d2003-10-13 22:26:55 +00004320}
4321
tomf93bbd92013-07-17 12:43:30 +00004322PRE(sys_sethostname)
4323{
4324 PRINT("sys_sethostname ( %#lx, %ld )", ARG1,ARG2);
4325 PRE_REG_READ2(long, "sethostname", char *, name, int, len);
4326 PRE_MEM_READ( "sethostname(name)", ARG1, ARG2 );
4327}
4328
sewardje6d5e722005-06-10 10:27:55 +00004329#undef PRE
4330#undef POST
sewardj2e93c502002-04-12 11:12:52 +00004331
njn8b68b642009-06-24 00:37:09 +00004332#endif // defined(VGO_linux) || defined(VGO_darwin)
4333
sewardjde4a1d02002-03-22 01:27:54 +00004334/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00004335/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004336/*--------------------------------------------------------------------*/