blob: b0fbfd9393ca3d27069c56de1c41bac211aa4989 [file] [log] [blame]
florian95f10372015-02-26 21:48:19 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardjde4a1d02002-03-22 01:27:54 +00002
3/*--------------------------------------------------------------------*/
sewardj6e9de462011-06-28 07:25:29 +00004/*--- Wrappers for generic Unix system calls ---*/
njn8b68b642009-06-24 00:37:09 +00005/*--- syswrap-generic.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006/*--------------------------------------------------------------------*/
7
8/*
njnb9c427c2004-12-01 14:14:42 +00009 This file is part of Valgrind, a dynamic binary instrumentation
10 framework.
sewardjde4a1d02002-03-22 01:27:54 +000011
Elliott Hughesed398002017-06-21 14:41:24 -070012 Copyright (C) 2000-2017 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
sewardj8eb8bab2015-07-21 14:44:28 +000033#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
njn8b68b642009-06-24 00:37:09 +000034
njnc7561b92005-06-19 01:24:32 +000035#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000036#include "pub_core_vki.h"
37#include "pub_core_vkiscnums.h"
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"
philippe38a74d22014-08-29 22:53:19 +000063#include "pub_core_stacks.h"
sewardj55f9d1a2005-04-25 11:11:44 +000064
sewardja8d8e232005-06-07 20:04:56 +000065#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000066#include "priv_syswrap-generic.h"
sewardjde4a1d02002-03-22 01:27:54 +000067
bart870f7452009-12-29 16:56:18 +000068#include "config.h"
69
jsgf855d93d2003-10-13 22:26:55 +000070
philippe38a74d22014-08-29 22:53:19 +000071void ML_(guess_and_register_stack) (Addr sp, ThreadState* tst)
72{
73 Bool debug = False;
74 NSegment const* seg;
75
76 /* We don't really know where the client stack is, because its
77 allocated by the client. The best we can do is look at the
78 memory mappings and try to derive some useful information. We
79 assume that sp starts near its highest possible value, and can
80 only go down to the start of the mmaped segment. */
81 seg = VG_(am_find_nsegment)(sp);
Elliott Hughesed398002017-06-21 14:41:24 -070082 if (seg
83 && VG_(am_is_valid_for_client)(sp, 1, VKI_PROT_READ | VKI_PROT_WRITE)) {
philippe38a74d22014-08-29 22:53:19 +000084 tst->client_stack_highest_byte = (Addr)VG_PGROUNDUP(sp)-1;
85 tst->client_stack_szB = tst->client_stack_highest_byte - seg->start + 1;
86
Elliott Hughesed398002017-06-21 14:41:24 -070087 tst->os_state.stk_id
88 = VG_(register_stack)(seg->start, tst->client_stack_highest_byte);
philippe38a74d22014-08-29 22:53:19 +000089
90 if (debug)
Elliott Hughesed398002017-06-21 14:41:24 -070091 VG_(printf)("tid %u: guessed client stack range [%#lx-%#lx]"
92 " as stk_id %lu\n",
93 tst->tid, seg->start, tst->client_stack_highest_byte,
94 tst->os_state.stk_id);
philippe38a74d22014-08-29 22:53:19 +000095 } else {
96 VG_(message)(Vg_UserMsg,
florianb26101c2015-08-08 21:45:33 +000097 "!? New thread %u starts with SP(%#lx) unmapped\n",
philippe38a74d22014-08-29 22:53:19 +000098 tst->tid, sp);
99 tst->client_stack_highest_byte = 0;
100 tst->client_stack_szB = 0;
101 }
102}
103
sewardj45f4e7c2005-09-27 19:20:21 +0000104/* Returns True iff address range is something the client can
105 plausibly mess with: all of it is either already belongs to the
106 client or is free or a reservation. */
107
sewardj7eb7c582005-06-23 01:02:53 +0000108Bool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
floriane543f302012-10-21 19:43:43 +0000109 const HChar *syscallname)
fitzhardinge1a303042003-12-22 08:48:50 +0000110{
fitzhardinge1a303042003-12-22 08:48:50 +0000111 Bool ret;
112
113 if (size == 0)
114 return True;
115
sewardj45f4e7c2005-09-27 19:20:21 +0000116 ret = VG_(am_is_valid_for_client_or_free_or_resvn)
117 (start,size,VKI_PROT_NONE);
fitzhardinge1a303042003-12-22 08:48:50 +0000118
119 if (0)
barta0b6b2c2008-07-07 06:49:24 +0000120 VG_(printf)("%s: test=%#lx-%#lx ret=%d\n",
sewardj45f4e7c2005-09-27 19:20:21 +0000121 syscallname, start, start+size-1, (Int)ret);
fitzhardinge1a303042003-12-22 08:48:50 +0000122
nethercote1543adf2004-10-25 15:43:21 +0000123 if (!ret && syscallname != NULL) {
sewardja8d8e232005-06-07 20:04:56 +0000124 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
sewardj738856f2009-07-15 14:48:32 +0000125 "to modify addresses %#lx-%#lx\n",
barta0b6b2c2008-07-07 06:49:24 +0000126 syscallname, start, start+size-1);
fitzhardinge1a303042003-12-22 08:48:50 +0000127 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +0000128 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
fitzhardinge1a303042003-12-22 08:48:50 +0000129 }
130 }
131
132 return ret;
133}
134
sewardj45f4e7c2005-09-27 19:20:21 +0000135
sewardj7eb7c582005-06-23 01:02:53 +0000136Bool ML_(client_signal_OK)(Int sigNo)
njn419bbcb2005-06-21 03:52:49 +0000137{
138 /* signal 0 is OK for kill */
njn351d0062005-06-21 22:23:59 +0000139 Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
njn419bbcb2005-06-21 03:52:49 +0000140
141 //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
142
143 return ret;
144}
145
sewardj45f4e7c2005-09-27 19:20:21 +0000146
147/* Handy small function to help stop wrappers from segfaulting when
148 presented with bogus client addresses. Is not used for generating
149 user-visible errors. */
150
sewardj8eb8bab2015-07-21 14:44:28 +0000151Bool ML_(safe_to_deref) ( const void *start, SizeT size )
sewardj45f4e7c2005-09-27 19:20:21 +0000152{
njn143377e2009-06-10 06:13:34 +0000153 return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_READ );
sewardj45f4e7c2005-09-27 19:20:21 +0000154}
155
156
njn25e49d8e72002-09-23 09:36:25 +0000157/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000158 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000159 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000160
njn25e49d8e72002-09-23 09:36:25 +0000161/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
162 munmap, mprotect (and mremap??) work at the page level. So addresses
163 and lengths must be adjusted for this. */
164
165/* Mash around start and length so that the area exactly covers
166 an integral number of pages. If we don't do that, memcheck's
167 idea of addressible memory diverges from that of the
168 kernel's, which causes the leak detector to crash. */
169static
sewardj45f4e7c2005-09-27 19:20:21 +0000170void page_align_addr_and_len( Addr* a, SizeT* len)
sewardjde4a1d02002-03-22 01:27:54 +0000171{
fitzhardinge98abfc72003-12-16 02:05:15 +0000172 Addr ra;
173
njn13bfd852005-06-02 03:52:53 +0000174 ra = VG_PGROUNDDN(*a);
175 *len = VG_PGROUNDUP(*a + *len) - ra;
fitzhardinge98abfc72003-12-16 02:05:15 +0000176 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000177}
178
njndd372582009-05-10 22:42:19 +0000179static void notify_core_of_mmap(Addr a, SizeT len, UInt prot,
180 UInt flags, Int fd, Off64T offset)
bart510521e2008-05-29 08:52:44 +0000181{
182 Bool d;
njn25e49d8e72002-09-23 09:36:25 +0000183
sewardj45f4e7c2005-09-27 19:20:21 +0000184 /* 'a' is the return value from a real kernel mmap, hence: */
185 vg_assert(VG_IS_PAGE_ALIGNED(a));
186 /* whereas len is whatever the syscall supplied. So: */
187 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000188
sewardj45f4e7c2005-09-27 19:20:21 +0000189 d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
fitzhardinge98abfc72003-12-16 02:05:15 +0000190
bart510521e2008-05-29 08:52:44 +0000191 if (d)
florianddd61ff2015-01-04 17:20:45 +0000192 VG_(discard_translations)( a, (ULong)len,
njndd372582009-05-10 22:42:19 +0000193 "notify_core_of_mmap" );
bart510521e2008-05-29 08:52:44 +0000194}
195
njndd372582009-05-10 22:42:19 +0000196static void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, ULong di_handle)
bart510521e2008-05-29 08:52:44 +0000197{
198 Bool rr, ww, xx;
199
200 /* 'a' is the return value from a real kernel mmap, hence: */
201 vg_assert(VG_IS_PAGE_ALIGNED(a));
202 /* whereas len is whatever the syscall supplied. So: */
203 len = VG_PGROUNDUP(len);
204
sewardj45f4e7c2005-09-27 19:20:21 +0000205 rr = toBool(prot & VKI_PROT_READ);
206 ww = toBool(prot & VKI_PROT_WRITE);
207 xx = toBool(prot & VKI_PROT_EXEC);
njn25e49d8e72002-09-23 09:36:25 +0000208
sewardj9c606bd2008-09-18 18:12:50 +0000209 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle );
sewardjde4a1d02002-03-22 01:27:54 +0000210}
211
njndd372582009-05-10 22:42:19 +0000212
213/* When a client mmap has been successfully done, this function must
214 be called. It notifies both aspacem and the tool of the new
215 mapping.
216
217 JRS 2008-Aug-14: But notice this is *very* obscure. The only place
218 it is called from is POST(sys_io_setup). In particular,
219 ML_(generic_PRE_sys_mmap), in m_syswrap, is the "normal case" handler for
220 client mmap. But it doesn't call this function; instead it does the
221 relevant notifications itself. Here, we just pass di_handle=0 to
222 notify_tool_of_mmap as we have no better information. But really this
223 function should be done away with; problem is I don't understand what
224 POST(sys_io_setup) does or how it works.
225
226 [However, this function is used lots for Darwin, because
227 ML_(generic_PRE_sys_mmap) cannot be used for Darwin.]
228 */
229void
230ML_(notify_core_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
231 UInt flags, Int fd, Off64T offset )
232{
233 // XXX: unlike the other notify_core_and_tool* functions, this one doesn't
234 // do anything with debug info (ie. it doesn't call VG_(di_notify_mmap)).
235 // Should it? --njn
236 notify_core_of_mmap(a, len, prot, flags, fd, offset);
237 notify_tool_of_mmap(a, len, prot, 0/*di_handle*/);
238}
239
240void
241ML_(notify_core_and_tool_of_munmap) ( Addr a, SizeT len )
242{
243 Bool d;
244
245 page_align_addr_and_len(&a, &len);
246 d = VG_(am_notify_munmap)(a, len);
247 VG_TRACK( die_mem_munmap, a, len );
248 VG_(di_notify_munmap)( a, len );
249 if (d)
florianddd61ff2015-01-04 17:20:45 +0000250 VG_(discard_translations)( a, (ULong)len,
njndd372582009-05-10 22:42:19 +0000251 "ML_(notify_core_and_tool_of_munmap)" );
252}
253
254void
255ML_(notify_core_and_tool_of_mprotect) ( Addr a, SizeT len, Int prot )
256{
257 Bool rr = toBool(prot & VKI_PROT_READ);
258 Bool ww = toBool(prot & VKI_PROT_WRITE);
259 Bool xx = toBool(prot & VKI_PROT_EXEC);
260 Bool d;
261
262 page_align_addr_and_len(&a, &len);
263 d = VG_(am_notify_mprotect)(a, len, prot);
264 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
265 VG_(di_notify_mprotect)( a, len, prot );
266 if (d)
florianddd61ff2015-01-04 17:20:45 +0000267 VG_(discard_translations)( a, (ULong)len,
njndd372582009-05-10 22:42:19 +0000268 "ML_(notify_core_and_tool_of_mprotect)" );
269}
270
271
272
njnf76d27a2009-05-28 01:53:07 +0000273#if HAVE_MREMAP
sewardj45f4e7c2005-09-27 19:20:21 +0000274/* Expand (or shrink) an existing mapping, potentially moving it at
275 the same time (controlled by the MREMAP_MAYMOVE flag). Nightmare.
276*/
277static
278SysRes do_mremap( Addr old_addr, SizeT old_len,
279 Addr new_addr, SizeT new_len,
280 UWord flags, ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +0000281{
sewardj45f4e7c2005-09-27 19:20:21 +0000282# define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
njn25e49d8e72002-09-23 09:36:25 +0000283
sewardj45f4e7c2005-09-27 19:20:21 +0000284 Bool ok, d;
sewardjef1cf8b2006-10-17 01:47:30 +0000285 NSegment const* old_seg;
sewardj45f4e7c2005-09-27 19:20:21 +0000286 Addr advised;
287 Bool f_fixed = toBool(flags & VKI_MREMAP_FIXED);
288 Bool f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
fitzhardinge1a303042003-12-22 08:48:50 +0000289
290 if (0)
florianb26101c2015-08-08 21:45:33 +0000291 VG_(printf)("do_remap (old %#lx %lu) (new %#lx %lu) %s %s\n",
sewardj45f4e7c2005-09-27 19:20:21 +0000292 old_addr,old_len,new_addr,new_len,
293 flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
294 flags & VKI_MREMAP_FIXED ? "FIXED" : "");
sewardj63a622f2006-08-16 14:22:29 +0000295 if (0)
296 VG_(am_show_nsegments)(0, "do_remap: before");
fitzhardinge1a303042003-12-22 08:48:50 +0000297
sewardj45f4e7c2005-09-27 19:20:21 +0000298 if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
299 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000300
sewardj45f4e7c2005-09-27 19:20:21 +0000301 if (!VG_IS_PAGE_ALIGNED(old_addr))
302 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000303
sewardj45f4e7c2005-09-27 19:20:21 +0000304 old_len = VG_PGROUNDUP(old_len);
305 new_len = VG_PGROUNDUP(new_len);
fitzhardinge1a303042003-12-22 08:48:50 +0000306
sewardj45f4e7c2005-09-27 19:20:21 +0000307 if (new_len == 0)
308 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000309
sewardj45f4e7c2005-09-27 19:20:21 +0000310 /* kernel doesn't reject this, but we do. */
311 if (old_len == 0)
312 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000313
sewardj45f4e7c2005-09-27 19:20:21 +0000314 /* reject wraparounds */
toma5e13dd2011-08-11 14:51:47 +0000315 if (old_addr + old_len < old_addr)
316 goto eINVAL;
317 if (f_fixed == True && new_addr + new_len < new_len)
sewardj45f4e7c2005-09-27 19:20:21 +0000318 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000319
sewardj45f4e7c2005-09-27 19:20:21 +0000320 /* kernel rejects all fixed, no-move requests (which are
321 meaningless). */
322 if (f_fixed == True && f_maymove == False)
323 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000324
sewardj45f4e7c2005-09-27 19:20:21 +0000325 /* Stay away from non-client areas. */
326 if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
327 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000328
sewardj45f4e7c2005-09-27 19:20:21 +0000329 /* In all remaining cases, if the old range does not fall within a
330 single segment, fail. */
331 old_seg = VG_(am_find_nsegment)( old_addr );
332 if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
333 goto eINVAL;
Elliott Hughesed398002017-06-21 14:41:24 -0700334 if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC
335 && old_seg->kind != SkShmC)
sewardj45f4e7c2005-09-27 19:20:21 +0000336 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000337
sewardj45f4e7c2005-09-27 19:20:21 +0000338 vg_assert(old_len > 0);
339 vg_assert(new_len > 0);
340 vg_assert(VG_IS_PAGE_ALIGNED(old_len));
341 vg_assert(VG_IS_PAGE_ALIGNED(new_len));
342 vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
fitzhardinge1a303042003-12-22 08:48:50 +0000343
sewardj45f4e7c2005-09-27 19:20:21 +0000344 /* There are 3 remaining cases:
fitzhardinge1a303042003-12-22 08:48:50 +0000345
sewardj45f4e7c2005-09-27 19:20:21 +0000346 * maymove == False
347
348 new space has to be at old address, so:
349 - shrink -> unmap end
350 - same size -> do nothing
351 - grow -> if can grow in-place, do so, else fail
352
353 * maymove == True, fixed == False
354
355 new space can be anywhere, so:
356 - shrink -> unmap end
357 - same size -> do nothing
358 - grow -> if can grow in-place, do so, else
359 move to anywhere large enough, else fail
360
361 * maymove == True, fixed == True
362
363 new space must be at new address, so:
364
365 - if new address is not page aligned, fail
366 - if new address range overlaps old one, fail
367 - if new address range cannot be allocated, fail
368 - else move to new address range with new size
369 - else fail
370 */
371
372 if (f_maymove == False) {
373 /* new space has to be at old address */
374 if (new_len < old_len)
375 goto shrink_in_place;
376 if (new_len > old_len)
377 goto grow_in_place_or_fail;
378 goto same_in_place;
379 }
380
381 if (f_maymove == True && f_fixed == False) {
382 /* new space can be anywhere */
383 if (new_len < old_len)
384 goto shrink_in_place;
385 if (new_len > old_len)
386 goto grow_in_place_or_move_anywhere_or_fail;
387 goto same_in_place;
388 }
389
390 if (f_maymove == True && f_fixed == True) {
391 /* new space can only be at the new address */
392 if (!VG_IS_PAGE_ALIGNED(new_addr))
393 goto eINVAL;
394 if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
395 /* no overlap */
fitzhardinge1a303042003-12-22 08:48:50 +0000396 } else {
sewardj45f4e7c2005-09-27 19:20:21 +0000397 goto eINVAL;
398 }
399 if (new_addr == 0)
400 goto eINVAL;
401 /* VG_(am_get_advisory_client_simple) interprets zero to mean
402 non-fixed, which is not what we want */
403 advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
404 if (!ok || advised != new_addr)
405 goto eNOMEM;
406 ok = VG_(am_relocate_nooverlap_client)
407 ( &d, old_addr, old_len, new_addr, new_len );
408 if (ok) {
409 VG_TRACK( copy_mem_remap, old_addr, new_addr,
410 MIN_SIZET(old_len,new_len) );
411 if (new_len > old_len)
412 VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
sewardj9c606bd2008-09-18 18:12:50 +0000413 old_seg->hasR, old_seg->hasW, old_seg->hasX,
414 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000415 VG_TRACK(die_mem_munmap, old_addr, old_len);
416 if (d) {
417 VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
418 VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
419 }
420 return VG_(mk_SysRes_Success)( new_addr );
421 }
422 goto eNOMEM;
423 }
fitzhardinge1a303042003-12-22 08:48:50 +0000424
sewardj45f4e7c2005-09-27 19:20:21 +0000425 /* end of the 3 cases */
426 /*NOTREACHED*/ vg_assert(0);
fitzhardinge1a303042003-12-22 08:48:50 +0000427
sewardj45f4e7c2005-09-27 19:20:21 +0000428 grow_in_place_or_move_anywhere_or_fail:
429 {
430 /* try growing it in-place */
431 Addr needA = old_addr + old_len;
432 SSizeT needL = new_len - old_len;
fitzhardinge1a303042003-12-22 08:48:50 +0000433
sewardj45f4e7c2005-09-27 19:20:21 +0000434 vg_assert(needL > 0);
florian0b41f322014-11-24 17:30:01 +0000435 vg_assert(needA > 0);
436
sewardj45f4e7c2005-09-27 19:20:21 +0000437 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
sewardj63a622f2006-08-16 14:22:29 +0000438 if (ok) {
philippe15e301e2011-12-22 13:25:58 +0000439 /* Fixes bug #129866. */
440 ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
sewardj63a622f2006-08-16 14:22:29 +0000441 }
sewardj45f4e7c2005-09-27 19:20:21 +0000442 if (ok && advised == needA) {
floriandd7318b2015-02-25 10:06:06 +0000443 const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
444 if (new_seg) {
sewardj45f4e7c2005-09-27 19:20:21 +0000445 VG_TRACK( new_mem_mmap, needA, needL,
floriandd7318b2015-02-25 10:06:06 +0000446 new_seg->hasR,
447 new_seg->hasW, new_seg->hasX,
sewardj9c606bd2008-09-18 18:12:50 +0000448 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000449 return VG_(mk_SysRes_Success)( old_addr );
fitzhardinge1a303042003-12-22 08:48:50 +0000450 }
451 }
452
sewardj45f4e7c2005-09-27 19:20:21 +0000453 /* that failed. Look elsewhere. */
454 advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
455 if (ok) {
tom5484f382010-09-27 15:08:34 +0000456 Bool oldR = old_seg->hasR;
457 Bool oldW = old_seg->hasW;
458 Bool oldX = old_seg->hasX;
sewardj45f4e7c2005-09-27 19:20:21 +0000459 /* assert new area does not overlap old */
460 vg_assert(advised+new_len-1 < old_addr
461 || advised > old_addr+old_len-1);
462 ok = VG_(am_relocate_nooverlap_client)
463 ( &d, old_addr, old_len, advised, new_len );
464 if (ok) {
465 VG_TRACK( copy_mem_remap, old_addr, advised,
466 MIN_SIZET(old_len,new_len) );
467 if (new_len > old_len)
468 VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
tom5484f382010-09-27 15:08:34 +0000469 oldR, oldW, oldX, 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +0000470 VG_TRACK(die_mem_munmap, old_addr, old_len);
471 if (d) {
472 VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
473 VG_(discard_translations)( advised, new_len, "do_remap(5)" );
474 }
475 return VG_(mk_SysRes_Success)( advised );
476 }
477 }
478 goto eNOMEM;
479 }
480 /*NOTREACHED*/ vg_assert(0);
481
482 grow_in_place_or_fail:
483 {
484 Addr needA = old_addr + old_len;
485 SizeT needL = new_len - old_len;
florian0b41f322014-11-24 17:30:01 +0000486
487 vg_assert(needA > 0);
488
sewardj45f4e7c2005-09-27 19:20:21 +0000489 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
sewardj63a622f2006-08-16 14:22:29 +0000490 if (ok) {
philippe15e301e2011-12-22 13:25:58 +0000491 /* Fixes bug #129866. */
492 ok = VG_(am_covered_by_single_free_segment) ( needA, needL );
sewardj63a622f2006-08-16 14:22:29 +0000493 }
sewardj45f4e7c2005-09-27 19:20:21 +0000494 if (!ok || advised != needA)
495 goto eNOMEM;
floriandd7318b2015-02-25 10:06:06 +0000496 const NSegment *new_seg = VG_(am_extend_map_client)( old_addr, needL );
497 if (!new_seg)
sewardj45f4e7c2005-09-27 19:20:21 +0000498 goto eNOMEM;
499 VG_TRACK( new_mem_mmap, needA, needL,
floriandd7318b2015-02-25 10:06:06 +0000500 new_seg->hasR, new_seg->hasW, new_seg->hasX,
sewardj9c606bd2008-09-18 18:12:50 +0000501 0/*di_handle*/ );
floriandd7318b2015-02-25 10:06:06 +0000502
sewardj45f4e7c2005-09-27 19:20:21 +0000503 return VG_(mk_SysRes_Success)( old_addr );
504 }
505 /*NOTREACHED*/ vg_assert(0);
506
507 shrink_in_place:
508 {
509 SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
njncda2f0f2009-05-18 02:12:08 +0000510 if (sr_isError(sres))
sewardj45f4e7c2005-09-27 19:20:21 +0000511 return sres;
512 VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
513 if (d)
514 VG_(discard_translations)( old_addr+new_len, old_len-new_len,
515 "do_remap(7)" );
516 return VG_(mk_SysRes_Success)( old_addr );
517 }
518 /*NOTREACHED*/ vg_assert(0);
519
520 same_in_place:
521 return VG_(mk_SysRes_Success)( old_addr );
522 /*NOTREACHED*/ vg_assert(0);
523
524 eINVAL:
525 return VG_(mk_SysRes_Error)( VKI_EINVAL );
526 eNOMEM:
527 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
528
529# undef MIN_SIZET
sewardjde4a1d02002-03-22 01:27:54 +0000530}
njnf76d27a2009-05-28 01:53:07 +0000531#endif /* HAVE_MREMAP */
sewardjde4a1d02002-03-22 01:27:54 +0000532
533
sewardja8d8e232005-06-07 20:04:56 +0000534/* ---------------------------------------------------------------------
535 File-descriptor tracking
536 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000537
rjwalshf5f536f2003-11-17 17:45:00 +0000538/* One of these is allocated for each open file descriptor. */
rjwalshf5f536f2003-11-17 17:45:00 +0000539typedef struct OpenFd
540{
541 Int fd; /* The file descriptor */
florian19f91bb2012-11-10 22:29:54 +0000542 HChar *pathname; /* NULL if not a regular file or unknown */
rjwalshf5f536f2003-11-17 17:45:00 +0000543 ExeContext *where; /* NULL if inherited from parent */
544 struct OpenFd *next, *prev;
545} OpenFd;
546
547/* List of allocated file descriptors. */
sewardj1aa40212006-12-11 01:11:02 +0000548static OpenFd *allocated_fds = NULL;
rjwalshf5f536f2003-11-17 17:45:00 +0000549
550/* Count of open file descriptors. */
sewardj0a400c72005-07-23 09:22:46 +0000551static Int fd_count = 0;
rjwalshf5f536f2003-11-17 17:45:00 +0000552
rjwalshf5f536f2003-11-17 17:45:00 +0000553
rjwalshf5f536f2003-11-17 17:45:00 +0000554/* Note the fact that a file descriptor was just closed. */
sewardj8eb8bab2015-07-21 14:44:28 +0000555void ML_(record_fd_close)(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000556{
557 OpenFd *i = allocated_fds;
558
thughesad1c9562004-06-26 11:27:52 +0000559 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000560 return; /* Valgrind internal */
561
rjwalshf5f536f2003-11-17 17:45:00 +0000562 while(i) {
563 if(i->fd == fd) {
564 if(i->prev)
565 i->prev->next = i->next;
566 else
567 allocated_fds = i->next;
568 if(i->next)
569 i->next->prev = i->prev;
570 if(i->pathname)
florian77eb20b2014-09-11 21:19:17 +0000571 VG_(free) (i->pathname);
572 VG_(free) (i);
rjwalshf5f536f2003-11-17 17:45:00 +0000573 fd_count--;
574 break;
575 }
576 i = i->next;
577 }
578}
579
580/* Note the fact that a file descriptor was just opened. If the
581 tid is -1, this indicates an inherited fd. If the pathname is NULL,
582 this either indicates a non-standard file (i.e. a pipe or socket or
583 some such thing) or that we don't know the filename. If the fd is
584 already open, then we're probably doing a dup2() to an existing fd,
585 so just overwrite the existing one. */
florian3130eab2014-11-14 19:25:08 +0000586void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd,
587 const HChar *pathname)
rjwalshf5f536f2003-11-17 17:45:00 +0000588{
589 OpenFd *i;
590
thughesad1c9562004-06-26 11:27:52 +0000591 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000592 return; /* Valgrind internal */
593
rjwalshf5f536f2003-11-17 17:45:00 +0000594 /* Check to see if this fd is already open. */
595 i = allocated_fds;
596 while (i) {
597 if (i->fd == fd) {
florian77eb20b2014-09-11 21:19:17 +0000598 if (i->pathname) VG_(free)(i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000599 break;
600 }
601 i = i->next;
602 }
603
604 /* Not already one: allocate an OpenFd */
605 if (i == NULL) {
florian77eb20b2014-09-11 21:19:17 +0000606 i = VG_(malloc)("syswrap.rfdowgn.1", sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000607
608 i->prev = NULL;
609 i->next = allocated_fds;
610 if(allocated_fds) allocated_fds->prev = i;
611 allocated_fds = i;
612 fd_count++;
613 }
614
615 i->fd = fd;
florian77eb20b2014-09-11 21:19:17 +0000616 i->pathname = VG_(strdup)("syswrap.rfdowgn.2", pathname);
sewardjd01b5982007-11-09 23:24:09 +0000617 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
rjwalshf5f536f2003-11-17 17:45:00 +0000618}
619
njnf845f8f2005-06-23 02:26:47 +0000620// Record opening of an fd, and find its name.
njn096ccdd2009-02-22 23:00:30 +0000621void ML_(record_fd_open_named)(ThreadId tid, Int fd)
njnf845f8f2005-06-23 02:26:47 +0000622{
florian3130eab2014-11-14 19:25:08 +0000623 const HChar* buf;
624 const HChar* name;
floriana175ffb2014-10-14 21:01:33 +0000625 if (VG_(resolve_filename)(fd, &buf))
njnf845f8f2005-06-23 02:26:47 +0000626 name = buf;
627 else
628 name = NULL;
629
njn4279a882005-08-26 03:43:28 +0000630 ML_(record_fd_open_with_given_name)(tid, fd, name);
njnf845f8f2005-06-23 02:26:47 +0000631}
632
633// Record opening of a nameless fd.
634void ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
635{
njn4279a882005-08-26 03:43:28 +0000636 ML_(record_fd_open_with_given_name)(tid, fd, NULL);
njnf845f8f2005-06-23 02:26:47 +0000637}
638
sewardj8eb8bab2015-07-21 14:44:28 +0000639// Return if a given file descriptor is already recorded.
640Bool ML_(fd_recorded)(Int fd)
641{
642 OpenFd *i = allocated_fds;
643 while (i) {
644 if (i->fd == fd)
645 return True;
646 i = i->next;
647 }
648 return False;
649}
650
651/* Returned string must not be modified nor free'd. */
652const HChar *ML_(find_fd_recorded_by_fd)(Int fd)
653{
654 OpenFd *i = allocated_fds;
655
656 while (i) {
657 if (i->fd == fd)
658 return i->pathname;
659 i = i->next;
660 }
661
662 return NULL;
663}
664
rjwalshf5f536f2003-11-17 17:45:00 +0000665static
tom39955262014-02-24 15:06:06 +0000666HChar *unix_to_name(struct vki_sockaddr_un *sa, UInt len, HChar *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000667{
nethercote73b526f2004-10-31 18:48:21 +0000668 if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
rjwalshf5f536f2003-11-17 17:45:00 +0000669 VG_(sprintf)(name, "<unknown>");
670 } else {
671 VG_(sprintf)(name, "%s", sa->sun_path);
672 }
673
674 return name;
675}
676
677static
tom39955262014-02-24 15:06:06 +0000678HChar *inet_to_name(struct vki_sockaddr_in *sa, UInt len, HChar *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000679{
nethercote73b526f2004-10-31 18:48:21 +0000680 if (sa == NULL || len == 0) {
rjwalshf5f536f2003-11-17 17:45:00 +0000681 VG_(sprintf)(name, "<unknown>");
tom39955262014-02-24 15:06:06 +0000682 } else if (sa->sin_port == 0) {
683 VG_(sprintf)(name, "<unbound>");
rjwalshf5f536f2003-11-17 17:45:00 +0000684 } else {
tom329af4b2005-11-17 12:02:58 +0000685 UInt addr = VG_(ntohl)(sa->sin_addr.s_addr);
tom39955262014-02-24 15:06:06 +0000686 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
687 (addr>>24) & 0xFF, (addr>>16) & 0xFF,
688 (addr>>8) & 0xFF, addr & 0xFF,
689 VG_(ntohs)(sa->sin_port));
690 }
691
692 return name;
693}
694
695static
696void inet6_format(HChar *s, const UChar ip[16])
697{
698 static const unsigned char V4mappedprefix[12] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
699
700 if (!VG_(memcmp)(ip, V4mappedprefix, 12)) {
florian8eebf232014-09-18 18:35:47 +0000701 const struct vki_in_addr *sin_addr =
702 (const struct vki_in_addr *)(ip + 12);
tom39955262014-02-24 15:06:06 +0000703 UInt addr = VG_(ntohl)(sin_addr->s_addr);
704
705 VG_(sprintf)(s, "::ffff:%u.%u.%u.%u",
706 (addr>>24) & 0xFF, (addr>>16) & 0xFF,
707 (addr>>8) & 0xFF, addr & 0xFF);
708 } else {
709 Bool compressing = False;
710 Bool compressed = False;
711 Int len = 0;
712 Int i;
713
714 for (i = 0; i < 16; i += 2) {
715 UInt word = ((UInt)ip[i] << 8) | (UInt)ip[i+1];
716 if (word == 0 && !compressed) {
717 compressing = True;
718 } else {
719 if (compressing) {
720 compressing = False;
721 compressed = True;
722 s[len++] = ':';
723 }
724 if (i > 0) {
725 s[len++] = ':';
726 }
727 len += VG_(sprintf)(s + len, "%x", word);
728 }
rjwalshf5f536f2003-11-17 17:45:00 +0000729 }
tom39955262014-02-24 15:06:06 +0000730
731 if (compressing) {
732 s[len++] = ':';
733 s[len++] = ':';
734 }
735
736 s[len++] = 0;
737 }
738
739 return;
740}
741
742static
743HChar *inet6_to_name(struct vki_sockaddr_in6 *sa, UInt len, HChar *name)
744{
745 if (sa == NULL || len == 0) {
746 VG_(sprintf)(name, "<unknown>");
747 } else if (sa->sin6_port == 0) {
748 VG_(sprintf)(name, "<unbound>");
749 } else {
florianf44ff622014-12-20 16:52:08 +0000750 HChar addr[100]; // large enough
tom39955262014-02-24 15:06:06 +0000751 inet6_format(addr, (void *)&(sa->sin6_addr));
752 VG_(sprintf)(name, "[%s]:%u", addr, VG_(ntohs)(sa->sin6_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000753 }
754
755 return name;
756}
757
rjwalshf5f536f2003-11-17 17:45:00 +0000758/*
759 * Try get some details about a socket.
760 */
rjwalshf5f536f2003-11-17 17:45:00 +0000761static void
sewardj0a400c72005-07-23 09:22:46 +0000762getsockdetails(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000763{
764 union u {
nethercote73b526f2004-10-31 18:48:21 +0000765 struct vki_sockaddr a;
766 struct vki_sockaddr_in in;
tom39955262014-02-24 15:06:06 +0000767 struct vki_sockaddr_in6 in6;
nethercote73b526f2004-10-31 18:48:21 +0000768 struct vki_sockaddr_un un;
rjwalshf5f536f2003-11-17 17:45:00 +0000769 } laddr;
florian1636d332012-11-15 04:27:04 +0000770 Int llen;
rjwalshf5f536f2003-11-17 17:45:00 +0000771
772 llen = sizeof(laddr);
773 VG_(memset)(&laddr, 0, llen);
774
775 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
776 switch(laddr.a.sa_family) {
nethercote73b526f2004-10-31 18:48:21 +0000777 case VKI_AF_INET: {
florianf44ff622014-12-20 16:52:08 +0000778 HChar lname[32]; // large enough
779 HChar pname[32]; // large enough
nethercote73b526f2004-10-31 18:48:21 +0000780 struct vki_sockaddr_in paddr;
florian1636d332012-11-15 04:27:04 +0000781 Int plen = sizeof(struct vki_sockaddr_in);
rjwalshf5f536f2003-11-17 17:45:00 +0000782
sewardj738856f2009-07-15 14:48:32 +0000783 if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
784 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s\n", fd,
tom39955262014-02-24 15:06:06 +0000785 inet_to_name(&(laddr.in), llen, lname),
786 inet_to_name(&paddr, plen, pname));
rjwalshf5f536f2003-11-17 17:45:00 +0000787 } else {
sewardj738856f2009-07-15 14:48:32 +0000788 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound\n",
tom39955262014-02-24 15:06:06 +0000789 fd, inet_to_name(&(laddr.in), llen, lname));
790 }
791 return;
792 }
793 case VKI_AF_INET6: {
florianf44ff622014-12-20 16:52:08 +0000794 HChar lname[128]; // large enough
795 HChar pname[128]; // large enough
tom39955262014-02-24 15:06:06 +0000796 struct vki_sockaddr_in6 paddr;
797 Int plen = sizeof(struct vki_sockaddr_in6);
798
799 if (VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
800 VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> %s\n", fd,
801 inet6_to_name(&(laddr.in6), llen, lname),
802 inet6_to_name(&paddr, plen, pname));
803 } else {
804 VG_(message)(Vg_UserMsg, "Open AF_INET6 socket %d: %s <-> unbound\n",
805 fd, inet6_to_name(&(laddr.in6), llen, lname));
rjwalshf5f536f2003-11-17 17:45:00 +0000806 }
807 return;
808 }
nethercote73b526f2004-10-31 18:48:21 +0000809 case VKI_AF_UNIX: {
rjwalshf5f536f2003-11-17 17:45:00 +0000810 static char lname[256];
sewardj738856f2009-07-15 14:48:32 +0000811 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s\n", fd,
tom39955262014-02-24 15:06:06 +0000812 unix_to_name(&(laddr.un), llen, lname));
rjwalshf5f536f2003-11-17 17:45:00 +0000813 return;
814 }
815 default:
sewardj738856f2009-07-15 14:48:32 +0000816 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:\n",
rjwalshf5f536f2003-11-17 17:45:00 +0000817 laddr.a.sa_family, fd);
818 return;
819 }
820 }
821
sewardj738856f2009-07-15 14:48:32 +0000822 VG_(message)(Vg_UserMsg, "Open socket %d:\n", fd);
rjwalshf5f536f2003-11-17 17:45:00 +0000823}
824
825
nethercote3a42fb82004-08-03 18:08:50 +0000826/* Dump out a summary, and a more detailed list, of open file descriptors. */
floriane543f302012-10-21 19:43:43 +0000827void VG_(show_open_fds) (const HChar* when)
rjwalshf5f536f2003-11-17 17:45:00 +0000828{
829 OpenFd *i = allocated_fds;
830
philippec3360382012-10-21 14:37:14 +0000831 VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open %s.\n", fd_count, when);
rjwalshf5f536f2003-11-17 17:45:00 +0000832
sewardj738856f2009-07-15 14:48:32 +0000833 while (i) {
834 if (i->pathname) {
835 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s\n", i->fd,
rjwalshf5f536f2003-11-17 17:45:00 +0000836 i->pathname);
837 } else {
sewardj0a400c72005-07-23 09:22:46 +0000838 Int val;
florian1636d332012-11-15 04:27:04 +0000839 Int len = sizeof(val);
rjwalshf5f536f2003-11-17 17:45:00 +0000840
sewardj738856f2009-07-15 14:48:32 +0000841 if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len)
842 == -1) {
843 VG_(message)(Vg_UserMsg, "Open file descriptor %d:\n", i->fd);
rjwalshf5f536f2003-11-17 17:45:00 +0000844 } else {
845 getsockdetails(i->fd);
846 }
847 }
848
849 if(i->where) {
850 VG_(pp_ExeContext)(i->where);
sewardj738856f2009-07-15 14:48:32 +0000851 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000852 } else {
sewardj738856f2009-07-15 14:48:32 +0000853 VG_(message)(Vg_UserMsg, " <inherited from parent>\n");
854 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000855 }
856
857 i = i->next;
858 }
859
sewardj738856f2009-07-15 14:48:32 +0000860 VG_(message)(Vg_UserMsg, "\n");
rjwalshf5f536f2003-11-17 17:45:00 +0000861}
862
njn81b975c2009-04-28 05:35:53 +0000863/* If /proc/self/fd doesn't exist (e.g. you've got a Linux kernel that doesn't
864 have /proc support compiled in, or a non-Linux kernel), then we need to
865 find out what file descriptors we inherited from our parent process the
866 hard way - by checking each fd in turn. */
rjwalshf5f536f2003-11-17 17:45:00 +0000867static
njn81b975c2009-04-28 05:35:53 +0000868void init_preopened_fds_without_proc_self_fd(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000869{
870 struct vki_rlimit lim;
sewardj0a400c72005-07-23 09:22:46 +0000871 UInt count;
872 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000873
nethercote620154f2004-11-12 21:21:07 +0000874 if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000875 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
876 an arbitrarily high number. 1024 happens to be the limit in
njn81b975c2009-04-28 05:35:53 +0000877 the 2.4 Linux kernels. */
rjwalshf5f536f2003-11-17 17:45:00 +0000878 count = 1024;
879 } else {
880 count = lim.rlim_cur;
881 }
882
883 for (i = 0; i < count; i++)
njn81b975c2009-04-28 05:35:53 +0000884 if (VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
885 ML_(record_fd_open_named)(-1, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000886}
887
888/* Initialize the list of open file descriptors with the file descriptors
889 we inherited from out parent process. */
890
sewardj1aa40212006-12-11 01:11:02 +0000891void VG_(init_preopened_fds)(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000892{
njnf76d27a2009-05-28 01:53:07 +0000893// DDD: should probably use HAVE_PROC here or similar, instead.
njn81b975c2009-04-28 05:35:53 +0000894#if defined(VGO_linux)
sewardj0a400c72005-07-23 09:22:46 +0000895 Int ret;
mjw495c6562014-08-29 14:28:30 +0000896 struct vki_dirent64 d;
sewardj92645592005-07-23 09:18:34 +0000897 SysRes f;
rjwalshf5f536f2003-11-17 17:45:00 +0000898
899 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
njncda2f0f2009-05-18 02:12:08 +0000900 if (sr_isError(f)) {
njn81b975c2009-04-28 05:35:53 +0000901 init_preopened_fds_without_proc_self_fd();
rjwalshf5f536f2003-11-17 17:45:00 +0000902 return;
903 }
904
mjw495c6562014-08-29 14:28:30 +0000905 while ((ret = VG_(getdents64)(sr_Res(f), &d, sizeof(d))) != 0) {
njnf845f8f2005-06-23 02:26:47 +0000906 if (ret == -1)
rjwalshf5f536f2003-11-17 17:45:00 +0000907 goto out;
908
njnf845f8f2005-06-23 02:26:47 +0000909 if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
florian19f91bb2012-11-10 22:29:54 +0000910 HChar* s;
njn83df0b62009-02-25 01:01:05 +0000911 Int fno = VG_(strtoll10)(d.d_name, &s);
912 if (*s == '\0') {
njncda2f0f2009-05-18 02:12:08 +0000913 if (fno != sr_Res(f))
njn83df0b62009-02-25 01:01:05 +0000914 if (VG_(clo_track_fds))
915 ML_(record_fd_open_named)(-1, fno);
916 } else {
917 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +0000918 "Warning: invalid file name in /proc/self/fd: %s\n",
919 d.d_name);
njn83df0b62009-02-25 01:01:05 +0000920 }
rjwalshf5f536f2003-11-17 17:45:00 +0000921 }
922
njncda2f0f2009-05-18 02:12:08 +0000923 VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET);
rjwalshf5f536f2003-11-17 17:45:00 +0000924 }
925
sewardj92645592005-07-23 09:18:34 +0000926 out:
njncda2f0f2009-05-18 02:12:08 +0000927 VG_(close)(sr_Res(f));
njn81b975c2009-04-28 05:35:53 +0000928
njnf76d27a2009-05-28 01:53:07 +0000929#elif defined(VGO_darwin)
930 init_preopened_fds_without_proc_self_fd();
931
sewardj8eb8bab2015-07-21 14:44:28 +0000932#elif defined(VGO_solaris)
933 Int ret;
934 Char buf[VKI_MAXGETDENTS_SIZE];
935 SysRes f;
936
937 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
938 if (sr_isError(f)) {
939 init_preopened_fds_without_proc_self_fd();
940 return;
941 }
942
943 while ((ret = VG_(getdents64)(sr_Res(f), (struct vki_dirent64 *) buf,
944 sizeof(buf))) > 0) {
945 Int i = 0;
946 while (i < ret) {
947 /* Proceed one entry. */
948 struct vki_dirent64 *d = (struct vki_dirent64 *) (buf + i);
949 if (VG_(strcmp)(d->d_name, ".") && VG_(strcmp)(d->d_name, "..")) {
950 HChar *s;
951 Int fno = VG_(strtoll10)(d->d_name, &s);
952 if (*s == '\0') {
953 if (fno != sr_Res(f))
954 if (VG_(clo_track_fds))
955 ML_(record_fd_open_named)(-1, fno);
956 } else {
957 VG_(message)(Vg_DebugMsg,
958 "Warning: invalid file name in /proc/self/fd: %s\n",
959 d->d_name);
960 }
961 }
962
963 /* Move on the next entry. */
964 i += d->d_reclen;
965 }
966 }
967
968 VG_(close)(sr_Res(f));
969
njn81b975c2009-04-28 05:35:53 +0000970#else
971# error Unknown OS
972#endif
rjwalshf5f536f2003-11-17 17:45:00 +0000973}
974
sewardjde4a1d02002-03-22 01:27:54 +0000975static
tom56e1c842005-07-18 22:41:33 +0000976void pre_mem_read_sendmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000977 const HChar *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000978{
Elliott Hughesed398002017-06-21 14:41:24 -0700979 HChar outmsg[VG_(strlen)(msg) + 10]; // large enough
980 VG_(sprintf)(outmsg, "sendmsg%s", msg);
nethercoteef0c7662004-11-06 15:38:43 +0000981 PRE_MEM_READ( outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000982}
983
984static
tom56e1c842005-07-18 22:41:33 +0000985void pre_mem_write_recvmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000986 const HChar *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000987{
Elliott Hughesed398002017-06-21 14:41:24 -0700988 HChar outmsg[VG_(strlen)(msg) + 10]; // large enough
989 VG_(sprintf)(outmsg, "recvmsg%s", msg);
tom56e1c842005-07-18 22:41:33 +0000990 if ( read )
991 PRE_MEM_READ( outmsg, base, size );
992 else
993 PRE_MEM_WRITE( outmsg, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000994}
995
996static
tom56e1c842005-07-18 22:41:33 +0000997void post_mem_write_recvmsg ( ThreadId tid, Bool read,
floriane543f302012-10-21 19:43:43 +0000998 const HChar *fieldName, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000999{
tom56e1c842005-07-18 22:41:33 +00001000 if ( !read )
1001 POST_MEM_WRITE( base, size );
sewardjde4a1d02002-03-22 01:27:54 +00001002}
1003
1004static
sewardj8c824512002-04-14 04:16:48 +00001005void msghdr_foreachfield (
toma4991232012-02-10 11:30:09 +00001006 ThreadId tid,
floriane543f302012-10-21 19:43:43 +00001007 const HChar *name,
tom8b3a6092012-02-10 16:45:01 +00001008 struct vki_msghdr *msg,
1009 UInt length,
tomfc75e5e2013-02-28 12:50:55 +00001010 void (*foreach_func)( ThreadId, Bool, const HChar *, Addr, SizeT ),
sewardj6822be82014-06-20 14:07:38 +00001011 Bool rekv /* "recv" apparently shadows some header decl on OSX108 */
sewardj8c824512002-04-14 04:16:48 +00001012 )
sewardjde4a1d02002-03-22 01:27:54 +00001013{
Elliott Hughesed398002017-06-21 14:41:24 -07001014 HChar fieldName[VG_(strlen)(name) + 32]; // large enough.
1015 Addr a;
1016 SizeT s;
toma4991232012-02-10 11:30:09 +00001017
sewardjde4a1d02002-03-22 01:27:54 +00001018 if ( !msg )
1019 return;
1020
toma4991232012-02-10 11:30:09 +00001021 VG_(sprintf) ( fieldName, "(%s)", name );
1022
Elliott Hughesed398002017-06-21 14:41:24 -07001023 /* FIELDPAIR helps the compiler do one call to foreach_func
1024 for consecutive (no holes) fields. */
1025#define FIELDPAIR(f1,f2) \
1026 if (offsetof(struct vki_msghdr, f1) + sizeof(msg->f1) \
1027 == offsetof(struct vki_msghdr, f2)) \
1028 s += sizeof(msg->f2); \
1029 else { \
1030 foreach_func (tid, True, fieldName, a, s); \
1031 a = (Addr)&msg->f2; \
1032 s = sizeof(msg->f2); \
1033 }
1034
1035 a = (Addr)&msg->msg_name;
1036 s = sizeof(msg->msg_name);
1037 FIELDPAIR(msg_name, msg_namelen);
1038 FIELDPAIR(msg_namelen, msg_iov);
1039 FIELDPAIR(msg_iov, msg_iovlen);
1040 FIELDPAIR(msg_iovlen, msg_control);
1041 FIELDPAIR(msg_control, msg_controllen);
1042 foreach_func ( tid, True, fieldName, a, s);
1043#undef FIELDPAIR
tomfc75e5e2013-02-28 12:50:55 +00001044
1045 /* msg_flags is completely ignored for send_mesg, recv_mesg doesn't read
1046 the field, but does write to it. */
sewardj6822be82014-06-20 14:07:38 +00001047 if ( rekv )
tomfc75e5e2013-02-28 12:50:55 +00001048 foreach_func ( tid, False, fieldName, (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
toma4991232012-02-10 11:30:09 +00001049
mjwaa02f662014-05-14 11:35:54 +00001050 if ( ML_(safe_to_deref)(&msg->msg_name, sizeof (void *))
1051 && msg->msg_name ) {
toma4991232012-02-10 11:30:09 +00001052 VG_(sprintf) ( fieldName, "(%s.msg_name)", name );
1053 foreach_func ( tid, False, fieldName,
sewardjde4a1d02002-03-22 01:27:54 +00001054 (Addr)msg->msg_name, msg->msg_namelen );
toma4991232012-02-10 11:30:09 +00001055 }
sewardjde4a1d02002-03-22 01:27:54 +00001056
mjwaa02f662014-05-14 11:35:54 +00001057 if ( ML_(safe_to_deref)(&msg->msg_iov, sizeof (void *))
1058 && msg->msg_iov ) {
nethercote73b526f2004-10-31 18:48:21 +00001059 struct vki_iovec *iov = msg->msg_iov;
sewardjde4a1d02002-03-22 01:27:54 +00001060 UInt i;
1061
Elliott Hughesa0664b92017-04-18 17:46:52 -07001062 if (ML_(safe_to_deref)(&msg->msg_iovlen, sizeof (UInt))) {
Elliott Hughesed398002017-06-21 14:41:24 -07001063 VG_(sprintf) ( fieldName, "(%s.msg_iov)", name );
Elliott Hughesa0664b92017-04-18 17:46:52 -07001064 foreach_func ( tid, True, fieldName, (Addr)iov,
1065 msg->msg_iovlen * sizeof( struct vki_iovec ) );
sewardjde4a1d02002-03-22 01:27:54 +00001066
Elliott Hughesa0664b92017-04-18 17:46:52 -07001067 for ( i = 0; i < msg->msg_iovlen && length > 0; ++i, ++iov ) {
1068 if (ML_(safe_to_deref)(&iov->iov_len, sizeof (UInt))) {
1069 UInt iov_len = iov->iov_len <= length ? iov->iov_len : length;
1070 VG_(sprintf) ( fieldName, "(%s.msg_iov[%u])", name, i );
1071 foreach_func ( tid, False, fieldName,
1072 (Addr)iov->iov_base, iov_len );
1073 length = length - iov_len;
1074 }
1075 }
toma4991232012-02-10 11:30:09 +00001076 }
sewardjde4a1d02002-03-22 01:27:54 +00001077 }
1078
mjwaa02f662014-05-14 11:35:54 +00001079 if ( ML_(safe_to_deref) (&msg->msg_control, sizeof (void *))
Elliott Hughesed398002017-06-21 14:41:24 -07001080 && msg->msg_control ) {
toma4991232012-02-10 11:30:09 +00001081 VG_(sprintf) ( fieldName, "(%s.msg_control)", name );
1082 foreach_func ( tid, False, fieldName,
sewardjde4a1d02002-03-22 01:27:54 +00001083 (Addr)msg->msg_control, msg->msg_controllen );
toma4991232012-02-10 11:30:09 +00001084 }
1085
sewardjde4a1d02002-03-22 01:27:54 +00001086}
1087
sewardjb5f6f512005-03-10 23:59:00 +00001088static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
rjwalshf5f536f2003-11-17 17:45:00 +00001089{
nethercote73b526f2004-10-31 18:48:21 +00001090 struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
rjwalshf5f536f2003-11-17 17:45:00 +00001091
1092 while (cm) {
Elliott Hughesed398002017-06-21 14:41:24 -07001093 if (cm->cmsg_level == VKI_SOL_SOCKET
1094 && cm->cmsg_type == VKI_SCM_RIGHTS ) {
sewardj0a400c72005-07-23 09:22:46 +00001095 Int *fds = (Int *) VKI_CMSG_DATA(cm);
1096 Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
rjwalshf5f536f2003-11-17 17:45:00 +00001097 / sizeof(int);
sewardj0a400c72005-07-23 09:22:46 +00001098 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +00001099
1100 for (i = 0; i < fdc; i++)
1101 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +00001102 // XXX: must we check the range on these fds with
cerion7b2c38c2005-06-23 07:52:54 +00001103 // ML_(fd_allowed)()?
njn096ccdd2009-02-22 23:00:30 +00001104 ML_(record_fd_open_named)(tid, fds[i]);
rjwalshf5f536f2003-11-17 17:45:00 +00001105 }
1106
nethercote73b526f2004-10-31 18:48:21 +00001107 cm = VKI_CMSG_NXTHDR(msg, cm);
rjwalshf5f536f2003-11-17 17:45:00 +00001108 }
1109}
1110
njnf76d27a2009-05-28 01:53:07 +00001111/* GrP kernel ignores sa_len (at least on Darwin); this checks the rest */
sewardjc483e8f2002-05-03 21:01:35 +00001112static
jsgf855d93d2003-10-13 22:26:55 +00001113void pre_mem_read_sockaddr ( ThreadId tid,
floriane543f302012-10-21 19:43:43 +00001114 const HChar *description,
sewardja8d8e232005-06-07 20:04:56 +00001115 struct vki_sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +00001116{
Elliott Hughesed398002017-06-21 14:41:24 -07001117 HChar outmsg[VG_(strlen)( description ) + 30]; // large enough
sewardj8eb8bab2015-07-21 14:44:28 +00001118 struct vki_sockaddr_un* saun = (struct vki_sockaddr_un *)sa;
njnff424472009-05-23 01:18:44 +00001119 struct vki_sockaddr_in* sin = (struct vki_sockaddr_in *)sa;
1120 struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
sewardj19ce5d52014-08-06 19:52:12 +00001121# ifdef VKI_AF_BLUETOOTH
mjwada5ad72013-05-22 10:21:10 +00001122 struct vki_sockaddr_rc* rc = (struct vki_sockaddr_rc *)sa;
sewardj19ce5d52014-08-06 19:52:12 +00001123# endif
1124# ifdef VKI_AF_NETLINK
1125 struct vki_sockaddr_nl* nl = (struct vki_sockaddr_nl *)sa;
1126# endif
sewardjff7c1ab2003-02-24 21:55:34 +00001127
1128 /* NULL/zero-length sockaddrs are legal */
1129 if ( sa == NULL || salen == 0 ) return;
1130
njnff424472009-05-23 01:18:44 +00001131 VG_(sprintf) ( outmsg, description, "sa_family" );
nethercoteef0c7662004-11-06 15:38:43 +00001132 PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +00001133
Elliott Hughesa0664b92017-04-18 17:46:52 -07001134 /* Don't do any extra checking if we cannot determine the sa_family. */
Elliott Hughesed398002017-06-21 14:41:24 -07001135 if (! ML_(safe_to_deref) (&sa->sa_family, sizeof(vki_sa_family_t)))
Elliott Hughesa0664b92017-04-18 17:46:52 -07001136 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07001137
sewardjc483e8f2002-05-03 21:01:35 +00001138 switch (sa->sa_family) {
1139
nethercote73b526f2004-10-31 18:48:21 +00001140 case VKI_AF_UNIX:
Elliott Hughesa0664b92017-04-18 17:46:52 -07001141 if (ML_(safe_to_deref) (&saun->sun_path, sizeof (Addr))) {
1142 VG_(sprintf) ( outmsg, description, "sun_path" );
1143 PRE_MEM_RASCIIZ( outmsg, (Addr) saun->sun_path );
1144 // GrP fixme max of sun_len-2? what about nul char?
1145 }
sewardjc483e8f2002-05-03 21:01:35 +00001146 break;
1147
nethercote73b526f2004-10-31 18:48:21 +00001148 case VKI_AF_INET:
njnff424472009-05-23 01:18:44 +00001149 VG_(sprintf) ( outmsg, description, "sin_port" );
1150 PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) );
1151 VG_(sprintf) ( outmsg, description, "sin_addr" );
1152 PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) );
sewardjc483e8f2002-05-03 21:01:35 +00001153 break;
1154
nethercote73b526f2004-10-31 18:48:21 +00001155 case VKI_AF_INET6:
njnff424472009-05-23 01:18:44 +00001156 VG_(sprintf) ( outmsg, description, "sin6_port" );
nethercoteef0c7662004-11-06 15:38:43 +00001157 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001158 (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) );
1159 VG_(sprintf) ( outmsg, description, "sin6_flowinfo" );
nethercoteef0c7662004-11-06 15:38:43 +00001160 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001161 (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) );
1162 VG_(sprintf) ( outmsg, description, "sin6_addr" );
nethercoteef0c7662004-11-06 15:38:43 +00001163 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001164 (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) );
1165 VG_(sprintf) ( outmsg, description, "sin6_scope_id" );
nethercoteef0c7662004-11-06 15:38:43 +00001166 PRE_MEM_READ( outmsg,
njnff424472009-05-23 01:18:44 +00001167 (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) );
sewardjc483e8f2002-05-03 21:01:35 +00001168 break;
mjw4cb663f2013-05-22 10:37:52 +00001169
sewardj19ce5d52014-08-06 19:52:12 +00001170# ifdef VKI_AF_BLUETOOTH
mjwada5ad72013-05-22 10:21:10 +00001171 case VKI_AF_BLUETOOTH:
1172 VG_(sprintf) ( outmsg, description, "rc_bdaddr" );
1173 PRE_MEM_READ( outmsg, (Addr) &rc->rc_bdaddr, sizeof (rc->rc_bdaddr) );
1174 VG_(sprintf) ( outmsg, description, "rc_channel" );
1175 PRE_MEM_READ( outmsg, (Addr) &rc->rc_channel, sizeof (rc->rc_channel) );
1176 break;
sewardj19ce5d52014-08-06 19:52:12 +00001177# endif
1178
1179# ifdef VKI_AF_NETLINK
1180 case VKI_AF_NETLINK:
1181 VG_(sprintf)(outmsg, description, "nl_pid");
1182 PRE_MEM_READ(outmsg, (Addr)&nl->nl_pid, sizeof(nl->nl_pid));
1183 VG_(sprintf)(outmsg, description, "nl_groups");
1184 PRE_MEM_READ(outmsg, (Addr)&nl->nl_groups, sizeof(nl->nl_groups));
1185 break;
1186# endif
mjwada5ad72013-05-22 10:21:10 +00001187
sewardjaa62d842014-08-20 17:45:00 +00001188# ifdef VKI_AF_UNSPEC
1189 case VKI_AF_UNSPEC:
1190 break;
1191# endif
1192
sewardjc483e8f2002-05-03 21:01:35 +00001193 default:
philippec06f6842014-07-30 22:20:29 +00001194 /* No specific information about this address family.
1195 Let's just check the full data following the family.
1196 Note that this can give false positive if this (unknown)
1197 struct sockaddr_???? has padding bytes between its elements. */
1198 VG_(sprintf) ( outmsg, description, "sa_data" );
1199 PRE_MEM_READ( outmsg, (Addr)&sa->sa_family + sizeof(sa->sa_family),
philippe90a70732014-12-29 18:24:37 +00001200 salen - sizeof(sa->sa_family));
sewardjc483e8f2002-05-03 21:01:35 +00001201 break;
1202 }
sewardjc483e8f2002-05-03 21:01:35 +00001203}
1204
njn25e49d8e72002-09-23 09:36:25 +00001205/* Dereference a pointer to a UInt. */
floriane543f302012-10-21 19:43:43 +00001206static UInt deref_UInt ( ThreadId tid, Addr a, const HChar* s )
njn25e49d8e72002-09-23 09:36:25 +00001207{
1208 UInt* a_p = (UInt*)a;
nethercoteef0c7662004-11-06 15:38:43 +00001209 PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
Elliott Hughesa0664b92017-04-18 17:46:52 -07001210 if (a_p == NULL || ! ML_(safe_to_deref) (a_p, sizeof(UInt)))
njn25e49d8e72002-09-23 09:36:25 +00001211 return 0;
1212 else
1213 return *a_p;
1214}
1215
njnf37a81b2009-02-17 00:23:30 +00001216void ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p,
floriane543f302012-10-21 19:43:43 +00001217 const HChar* buf_s, const HChar* buflen_s )
njn25e49d8e72002-09-23 09:36:25 +00001218{
njn51d827b2005-05-09 01:02:08 +00001219 if (VG_(tdict).track_pre_mem_write) {
njn72718642003-07-24 08:45:32 +00001220 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +00001221 if (buflen_in > 0) {
njncda2f0f2009-05-18 02:12:08 +00001222 VG_(tdict).track_pre_mem_write(
1223 Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +00001224 }
1225 }
1226}
1227
njnf37a81b2009-02-17 00:23:30 +00001228void ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res,
floriane543f302012-10-21 19:43:43 +00001229 Addr buf_p, Addr buflen_p, const HChar* s )
njn25e49d8e72002-09-23 09:36:25 +00001230{
njncda2f0f2009-05-18 02:12:08 +00001231 if (!sr_isError(res) && VG_(tdict).track_post_mem_write) {
njn72718642003-07-24 08:45:32 +00001232 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +00001233 if (buflen_out > 0 && buf_p != (Addr)NULL) {
njn51d827b2005-05-09 01:02:08 +00001234 VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +00001235 }
1236 }
1237}
1238
1239/* ---------------------------------------------------------------------
1240 Data seg end, for brk()
1241 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001242
sewardj45f4e7c2005-09-27 19:20:21 +00001243/* +--------+------------+
1244 | anon | resvn |
1245 +--------+------------+
nethercotece471262004-08-25 13:43:44 +00001246
sewardj45f4e7c2005-09-27 19:20:21 +00001247 ^ ^ ^
1248 | | boundary is page aligned
1249 | VG_(brk_limit) -- no alignment constraint
1250 VG_(brk_base) -- page aligned -- does not move
1251
1252 Both the anon part and the reservation part are always at least
1253 one page.
1254*/
1255
1256/* Set the new data segment end to NEWBRK. If this succeeds, return
1257 NEWBRK, else return the current data segment end. */
1258
florian981abb52015-04-29 12:59:16 +00001259static Addr do_brk ( Addr newbrk, ThreadId tid )
sewardj45f4e7c2005-09-27 19:20:21 +00001260{
sewardjef1cf8b2006-10-17 01:47:30 +00001261 NSegment const* aseg;
sewardj45f4e7c2005-09-27 19:20:21 +00001262 Addr newbrkP;
1263 SizeT delta;
sewardj45f4e7c2005-09-27 19:20:21 +00001264 Bool debug = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001265
1266 if (debug)
barta0b6b2c2008-07-07 06:49:24 +00001267 VG_(printf)("\ndo_brk: brk_base=%#lx brk_limit=%#lx newbrk=%#lx\n",
fitzhardinge98abfc72003-12-16 02:05:15 +00001268 VG_(brk_base), VG_(brk_limit), newbrk);
1269
florian95f10372015-02-26 21:48:19 +00001270 if (0) VG_(am_show_nsegments)(0, "in_brk");
sewardj548be6d2005-02-16 01:31:37 +00001271
sewardj45f4e7c2005-09-27 19:20:21 +00001272 if (newbrk < VG_(brk_base))
1273 /* Clearly impossible. */
1274 goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +00001275
florian95f10372015-02-26 21:48:19 +00001276 if (newbrk < VG_(brk_limit)) {
sewardj45f4e7c2005-09-27 19:20:21 +00001277 /* shrinking the data segment. Be lazy and don't munmap the
1278 excess area. */
sewardjef1cf8b2006-10-17 01:47:30 +00001279 NSegment const * seg = VG_(am_find_nsegment)(newbrk);
florian95f10372015-02-26 21:48:19 +00001280 vg_assert(seg);
1281
1282 if (seg->hasT)
sewardj45f4e7c2005-09-27 19:20:21 +00001283 VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
1284 "do_brk(shrink)" );
sewardjd2d241b2006-02-14 11:37:41 +00001285 /* Since we're being lazy and not unmapping pages, we have to
1286 zero out the area, so that if the area later comes back into
1287 circulation, it will be filled with zeroes, as if it really
1288 had been unmapped and later remapped. Be a bit paranoid and
1289 try hard to ensure we're not going to segfault by doing the
1290 write - check both ends of the range are in the same segment
1291 and that segment is writable. */
florian95f10372015-02-26 21:48:19 +00001292 NSegment const * seg2;
1293
floriane787fca2015-05-05 06:14:10 +00001294 seg2 = VG_(am_find_nsegment)( VG_(brk_limit) - 1 );
florian95f10372015-02-26 21:48:19 +00001295 vg_assert(seg2);
1296
1297 if (seg == seg2 && seg->hasW)
1298 VG_(memset)( (void*)newbrk, 0, VG_(brk_limit) - newbrk );
sewardjd2d241b2006-02-14 11:37:41 +00001299
sewardj45f4e7c2005-09-27 19:20:21 +00001300 VG_(brk_limit) = newbrk;
1301 return newbrk;
1302 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001303
sewardj45f4e7c2005-09-27 19:20:21 +00001304 /* otherwise we're expanding the brk segment. */
tom8e5963d2005-10-06 14:49:21 +00001305 if (VG_(brk_limit) > VG_(brk_base))
1306 aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
1307 else
1308 aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001309
sewardj45f4e7c2005-09-27 19:20:21 +00001310 /* These should be assured by setup_client_dataseg in m_main. */
1311 vg_assert(aseg);
sewardj45f4e7c2005-09-27 19:20:21 +00001312 vg_assert(aseg->kind == SkAnonC);
fitzhardinge98abfc72003-12-16 02:05:15 +00001313
florian95f10372015-02-26 21:48:19 +00001314 if (newbrk <= aseg->end + 1) {
sewardj45f4e7c2005-09-27 19:20:21 +00001315 /* still fits within the anon segment. */
1316 VG_(brk_limit) = newbrk;
1317 return newbrk;
1318 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001319
sewardj45f4e7c2005-09-27 19:20:21 +00001320 newbrkP = VG_PGROUNDUP(newbrk);
florian95f10372015-02-26 21:48:19 +00001321 delta = newbrkP - (aseg->end + 1);
sewardj45f4e7c2005-09-27 19:20:21 +00001322 vg_assert(delta > 0);
1323 vg_assert(VG_IS_PAGE_ALIGNED(delta));
1324
Elliott Hughesed398002017-06-21 14:41:24 -07001325 Bool overflow = False;
florian15fa8a22015-03-03 14:56:17 +00001326 if (! VG_(am_extend_into_adjacent_reservation_client)( aseg->start, delta,
florian981abb52015-04-29 12:59:16 +00001327 &overflow)) {
Elliott Hughesed398002017-06-21 14:41:24 -07001328 if (overflow) {
1329 static Bool alreadyComplained = False;
1330 if (!alreadyComplained) {
1331 alreadyComplained = True;
1332 if (VG_(clo_verbosity) > 0) {
1333 VG_(umsg)("brk segment overflow in thread #%u: "
1334 "can't grow to %#lx\n",
1335 tid, newbrkP);
1336 VG_(umsg)("(see section Limitations in user manual)\n");
1337 VG_(umsg)("NOTE: further instances of this message "
1338 "will not be shown\n");
1339 }
1340 }
1341 } else {
1342 if (VG_(clo_verbosity) > 0) {
1343 VG_(umsg)("Cannot map memory to grow brk segment in thread #%u "
1344 "to %#lx\n", tid, newbrkP);
1345 VG_(umsg)("(see section Limitations in user manual)\n");
1346 }
1347 }
florian888b8152015-02-26 16:07:12 +00001348 goto bad;
florian981abb52015-04-29 12:59:16 +00001349 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001350
sewardj45f4e7c2005-09-27 19:20:21 +00001351 VG_(brk_limit) = newbrk;
1352 return newbrk;
fitzhardinge98abfc72003-12-16 02:05:15 +00001353
sewardj45f4e7c2005-09-27 19:20:21 +00001354 bad:
1355 return VG_(brk_limit);
fitzhardinge98abfc72003-12-16 02:05:15 +00001356}
1357
1358
njn25e49d8e72002-09-23 09:36:25 +00001359/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00001360 Vet file descriptors for sanity
1361 ------------------------------------------------------------------ */
sewardj04236902005-10-04 22:27:22 +00001362/*
1363> - what does the "Bool soft" parameter mean?
1364
1365(Tom Hughes, 3 Oct 05):
1366
1367Whether or not to consider a file descriptor invalid if it is above
1368the current soft limit.
1369
1370Basically if we are testing whether a newly created file descriptor is
1371valid (in a post handler) then we set soft to true, and if we are
1372testing whether a file descriptor that is about to be used (in a pre
1373handler) is valid [viz, an already-existing fd] then we set it to false.
1374
1375The point is that if the (virtual) soft limit is lowered then any
1376existing descriptors can still be read/written/closed etc (so long as
1377they are below the valgrind reserved descriptors) but no new
1378descriptors can be created above the new soft limit.
1379
1380(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
1381*/
jsgf855d93d2003-10-13 22:26:55 +00001382
1383/* Return true if we're allowed to use or create this fd */
floriane543f302012-10-21 19:43:43 +00001384Bool ML_(fd_allowed)(Int fd, const HChar *syscallname, ThreadId tid,
1385 Bool isNewFd)
jsgf855d93d2003-10-13 22:26:55 +00001386{
sewardj04236902005-10-04 22:27:22 +00001387 Bool allowed = True;
1388
1389 /* hard limits always apply */
1390 if (fd < 0 || fd >= VG_(fd_hard_limit))
1391 allowed = False;
1392
sewardj738856f2009-07-15 14:48:32 +00001393 /* hijacking the output fds is never allowed */
1394 if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd)
sewardj04236902005-10-04 22:27:22 +00001395 allowed = False;
1396
1397 /* if creating a new fd (rather than using an existing one), the
1398 soft limit must also be observed */
1399 if (isNewFd && fd >= VG_(fd_soft_limit))
1400 allowed = False;
1401
1402 /* this looks like it ought to be included, but causes problems: */
1403 /*
1404 if (fd == 2 && VG_(debugLog_getLevel)() > 0)
1405 allowed = False;
1406 */
1407 /* The difficulty is as follows: consider a program P which expects
1408 to be able to mess with (redirect) its own stderr (fd 2).
1409 Usually to deal with P we would issue command line flags to send
1410 logging somewhere other than stderr, so as not to disrupt P.
1411 The problem is that -d unilaterally hijacks stderr with no
1412 consultation with P. And so, if this check is enabled, P will
1413 work OK normally but fail if -d is issued.
1414
1415 Basically -d is a hack and you take your chances when using it.
1416 It's very useful for low level debugging -- particularly at
1417 startup -- and having its presence change the behaviour of the
1418 client is exactly what we don't want. */
1419
1420 /* croak? */
1421 if ((!allowed) && VG_(showing_core_errors)() ) {
jsewardd9320a42003-12-12 06:40:05 +00001422 VG_(message)(Vg_UserMsg,
sewardj738856f2009-07-15 14:48:32 +00001423 "Warning: invalid file descriptor %d in syscall %s()\n",
nethercote1543adf2004-10-25 15:43:21 +00001424 fd, syscallname);
sewardj738856f2009-07-15 14:48:32 +00001425 if (fd == VG_(log_output_sink).fd && VG_(log_output_sink).fd >= 0)
jsewardd9320a42003-12-12 06:40:05 +00001426 VG_(message)(Vg_UserMsg,
sewardj738856f2009-07-15 14:48:32 +00001427 " Use --log-fd=<number> to select an alternative log fd.\n");
1428 if (fd == VG_(xml_output_sink).fd && VG_(xml_output_sink).fd >= 0)
1429 VG_(message)(Vg_UserMsg,
1430 " Use --xml-fd=<number> to select an alternative XML "
1431 "output fd.\n");
njneb04c892009-05-22 07:09:03 +00001432 // DDD: consider always printing this stack trace, it's useful.
1433 // Also consider also making this a proper core error, ie.
1434 // suppressible and all that.
jsgf855d93d2003-10-13 22:26:55 +00001435 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +00001436 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
jsgf855d93d2003-10-13 22:26:55 +00001437 }
jsgf855d93d2003-10-13 22:26:55 +00001438 }
sewardj04236902005-10-04 22:27:22 +00001439
1440 return allowed;
jsgf855d93d2003-10-13 22:26:55 +00001441}
1442
1443
1444/* ---------------------------------------------------------------------
sewardj9efbbef2005-03-01 16:45:23 +00001445 Deal with a bunch of socket-related syscalls
1446 ------------------------------------------------------------------ */
1447
1448/* ------ */
1449
sewardj987a8eb2005-03-01 19:00:30 +00001450void
sewardj7eb7c582005-06-23 01:02:53 +00001451ML_(generic_PRE_sys_socketpair) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001452 UWord arg0, UWord arg1,
1453 UWord arg2, UWord arg3 )
1454{
1455 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1456 PRE_MEM_WRITE( "socketcall.socketpair(sv)",
1457 arg3, 2*sizeof(int) );
1458}
1459
sewardja8d8e232005-06-07 20:04:56 +00001460SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001461ML_(generic_POST_sys_socketpair) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001462 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001463 UWord arg0, UWord arg1,
1464 UWord arg2, UWord arg3 )
sewardj9efbbef2005-03-01 16:45:23 +00001465{
sewardja8d8e232005-06-07 20:04:56 +00001466 SysRes r = res;
sewardj9efbbef2005-03-01 16:45:23 +00001467 Int fd1 = ((Int*)arg3)[0];
1468 Int fd2 = ((Int*)arg3)[1];
njncda2f0f2009-05-18 02:12:08 +00001469 vg_assert(!sr_isError(res)); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001470 POST_MEM_WRITE( arg3, 2*sizeof(int) );
sewardj7eb7c582005-06-23 01:02:53 +00001471 if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
1472 !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
sewardj9efbbef2005-03-01 16:45:23 +00001473 VG_(close)(fd1);
1474 VG_(close)(fd2);
sewardja8d8e232005-06-07 20:04:56 +00001475 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001476 } else {
1477 POST_MEM_WRITE( arg3, 2*sizeof(int) );
1478 if (VG_(clo_track_fds)) {
njnf845f8f2005-06-23 02:26:47 +00001479 ML_(record_fd_open_nameless)(tid, fd1);
1480 ML_(record_fd_open_nameless)(tid, fd2);
sewardj9efbbef2005-03-01 16:45:23 +00001481 }
1482 }
1483 return r;
1484}
1485
1486/* ------ */
1487
sewardja8d8e232005-06-07 20:04:56 +00001488SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001489ML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
sewardj9efbbef2005-03-01 16:45:23 +00001490{
sewardja8d8e232005-06-07 20:04:56 +00001491 SysRes r = res;
njncda2f0f2009-05-18 02:12:08 +00001492 vg_assert(!sr_isError(res)); /* guaranteed by caller */
1493 if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) {
1494 VG_(close)(sr_Res(res));
sewardja8d8e232005-06-07 20:04:56 +00001495 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001496 } else {
1497 if (VG_(clo_track_fds))
njncda2f0f2009-05-18 02:12:08 +00001498 ML_(record_fd_open_nameless)(tid, sr_Res(res));
sewardj9efbbef2005-03-01 16:45:23 +00001499 }
1500 return r;
1501}
1502
1503/* ------ */
1504
sewardj987a8eb2005-03-01 19:00:30 +00001505void
sewardj7eb7c582005-06-23 01:02:53 +00001506ML_(generic_PRE_sys_bind) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001507 UWord arg0, UWord arg1, UWord arg2 )
1508{
1509 /* int bind(int sockfd, struct sockaddr *my_addr,
1510 int addrlen); */
1511 pre_mem_read_sockaddr(
1512 tid, "socketcall.bind(my_addr.%s)",
1513 (struct vki_sockaddr *) arg1, arg2
1514 );
1515}
1516
1517/* ------ */
1518
sewardj987a8eb2005-03-01 19:00:30 +00001519void
sewardj7eb7c582005-06-23 01:02:53 +00001520ML_(generic_PRE_sys_accept) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001521 UWord arg0, UWord arg1, UWord arg2 )
1522{
1523 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1524 Addr addr_p = arg1;
1525 Addr addrlen_p = arg2;
1526 if (addr_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001527 ML_(buf_and_len_pre_check) ( tid, addr_p, addrlen_p,
1528 "socketcall.accept(addr)",
1529 "socketcall.accept(addrlen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001530}
1531
sewardja8d8e232005-06-07 20:04:56 +00001532SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001533ML_(generic_POST_sys_accept) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001534 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001535 UWord arg0, UWord arg1, UWord arg2 )
sewardj9efbbef2005-03-01 16:45:23 +00001536{
sewardja8d8e232005-06-07 20:04:56 +00001537 SysRes r = res;
njncda2f0f2009-05-18 02:12:08 +00001538 vg_assert(!sr_isError(res)); /* guaranteed by caller */
1539 if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) {
1540 VG_(close)(sr_Res(res));
sewardja8d8e232005-06-07 20:04:56 +00001541 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001542 } else {
1543 Addr addr_p = arg1;
1544 Addr addrlen_p = arg2;
1545 if (addr_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001546 ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p,
1547 "socketcall.accept(addrlen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001548 if (VG_(clo_track_fds))
njncda2f0f2009-05-18 02:12:08 +00001549 ML_(record_fd_open_nameless)(tid, sr_Res(res));
sewardj9efbbef2005-03-01 16:45:23 +00001550 }
1551 return r;
1552}
1553
1554/* ------ */
1555
sewardj987a8eb2005-03-01 19:00:30 +00001556void
sewardj7eb7c582005-06-23 01:02:53 +00001557ML_(generic_PRE_sys_sendto) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001558 UWord arg0, UWord arg1, UWord arg2,
1559 UWord arg3, UWord arg4, UWord arg5 )
1560{
1561 /* int sendto(int s, const void *msg, int len,
1562 unsigned int flags,
1563 const struct sockaddr *to, int tolen); */
1564 PRE_MEM_READ( "socketcall.sendto(msg)",
1565 arg1, /* msg */
1566 arg2 /* len */ );
1567 pre_mem_read_sockaddr(
1568 tid, "socketcall.sendto(to.%s)",
1569 (struct vki_sockaddr *) arg4, arg5
1570 );
1571}
1572
1573/* ------ */
1574
sewardj987a8eb2005-03-01 19:00:30 +00001575void
sewardj7eb7c582005-06-23 01:02:53 +00001576ML_(generic_PRE_sys_send) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001577 UWord arg0, UWord arg1, UWord arg2 )
1578{
1579 /* int send(int s, const void *msg, size_t len, int flags); */
1580 PRE_MEM_READ( "socketcall.send(msg)",
1581 arg1, /* msg */
1582 arg2 /* len */ );
1583
1584}
1585
1586/* ------ */
1587
sewardj987a8eb2005-03-01 19:00:30 +00001588void
sewardj7eb7c582005-06-23 01:02:53 +00001589ML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001590 UWord arg0, UWord arg1, UWord arg2,
1591 UWord arg3, UWord arg4, UWord arg5 )
1592{
1593 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1594 struct sockaddr *from, int *fromlen); */
1595 Addr buf_p = arg1;
1596 Int len = arg2;
1597 Addr from_p = arg4;
1598 Addr fromlen_p = arg5;
1599 PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
1600 if (from_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001601 ML_(buf_and_len_pre_check) ( tid, from_p, fromlen_p,
1602 "socketcall.recvfrom(from)",
1603 "socketcall.recvfrom(fromlen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001604}
1605
sewardj987a8eb2005-03-01 19:00:30 +00001606void
sewardj7eb7c582005-06-23 01:02:53 +00001607ML_(generic_POST_sys_recvfrom) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001608 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001609 UWord arg0, UWord arg1, UWord arg2,
1610 UWord arg3, UWord arg4, UWord arg5 )
1611{
1612 Addr buf_p = arg1;
1613 Int len = arg2;
1614 Addr from_p = arg4;
1615 Addr fromlen_p = arg5;
1616
njncda2f0f2009-05-18 02:12:08 +00001617 vg_assert(!sr_isError(res)); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001618 if (from_p != (Addr)NULL)
njnf37a81b2009-02-17 00:23:30 +00001619 ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p,
1620 "socketcall.recvfrom(fromlen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001621 POST_MEM_WRITE( buf_p, len );
1622}
1623
1624/* ------ */
1625
sewardj987a8eb2005-03-01 19:00:30 +00001626void
sewardj7eb7c582005-06-23 01:02:53 +00001627ML_(generic_PRE_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001628 UWord arg0, UWord arg1, UWord arg2 )
1629{
1630 /* int recv(int s, void *buf, int len, unsigned int flags); */
1631 /* man 2 recv says:
1632 The recv call is normally used only on a connected socket
1633 (see connect(2)) and is identical to recvfrom with a NULL
1634 from parameter.
1635 */
1636 PRE_MEM_WRITE( "socketcall.recv(buf)",
1637 arg1, /* buf */
1638 arg2 /* len */ );
1639}
1640
sewardj987a8eb2005-03-01 19:00:30 +00001641void
sewardj7eb7c582005-06-23 01:02:53 +00001642ML_(generic_POST_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001643 UWord res,
1644 UWord arg0, UWord arg1, UWord arg2 )
1645{
1646 if (res >= 0 && arg1 != 0) {
1647 POST_MEM_WRITE( arg1, /* buf */
1648 arg2 /* len */ );
1649 }
1650}
1651
1652/* ------ */
1653
sewardj987a8eb2005-03-01 19:00:30 +00001654void
sewardj7eb7c582005-06-23 01:02:53 +00001655ML_(generic_PRE_sys_connect) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001656 UWord arg0, UWord arg1, UWord arg2 )
1657{
1658 /* int connect(int sockfd,
1659 struct sockaddr *serv_addr, int addrlen ); */
sewardj9efbbef2005-03-01 16:45:23 +00001660 pre_mem_read_sockaddr( tid,
1661 "socketcall.connect(serv_addr.%s)",
1662 (struct vki_sockaddr *) arg1, arg2);
1663}
1664
1665/* ------ */
1666
sewardj987a8eb2005-03-01 19:00:30 +00001667void
sewardj7eb7c582005-06-23 01:02:53 +00001668ML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001669 UWord arg0, UWord arg1, UWord arg2,
1670 UWord arg3, UWord arg4 )
1671{
1672 /* int setsockopt(int s, int level, int optname,
1673 const void *optval, int optlen); */
1674 PRE_MEM_READ( "socketcall.setsockopt(optval)",
1675 arg3, /* optval */
1676 arg4 /* optlen */ );
1677}
1678
1679/* ------ */
1680
sewardj987a8eb2005-03-01 19:00:30 +00001681void
sewardj7eb7c582005-06-23 01:02:53 +00001682ML_(generic_PRE_sys_getsockname) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001683 UWord arg0, UWord arg1, UWord arg2 )
1684{
1685 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1686 Addr name_p = arg1;
1687 Addr namelen_p = arg2;
1688 /* Nb: name_p cannot be NULL */
njnf37a81b2009-02-17 00:23:30 +00001689 ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1690 "socketcall.getsockname(name)",
1691 "socketcall.getsockname(namelen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001692}
1693
sewardj987a8eb2005-03-01 19:00:30 +00001694void
sewardj7eb7c582005-06-23 01:02:53 +00001695ML_(generic_POST_sys_getsockname) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001696 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001697 UWord arg0, UWord arg1, UWord arg2 )
1698{
1699 Addr name_p = arg1;
1700 Addr namelen_p = arg2;
njncda2f0f2009-05-18 02:12:08 +00001701 vg_assert(!sr_isError(res)); /* guaranteed by caller */
njnf37a81b2009-02-17 00:23:30 +00001702 ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1703 "socketcall.getsockname(namelen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001704}
1705
1706/* ------ */
1707
sewardj987a8eb2005-03-01 19:00:30 +00001708void
sewardj7eb7c582005-06-23 01:02:53 +00001709ML_(generic_PRE_sys_getpeername) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001710 UWord arg0, UWord arg1, UWord arg2 )
1711{
1712 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1713 Addr name_p = arg1;
1714 Addr namelen_p = arg2;
1715 /* Nb: name_p cannot be NULL */
njnf37a81b2009-02-17 00:23:30 +00001716 ML_(buf_and_len_pre_check) ( tid, name_p, namelen_p,
1717 "socketcall.getpeername(name)",
1718 "socketcall.getpeername(namelen_in)" );
sewardj9efbbef2005-03-01 16:45:23 +00001719}
1720
sewardj987a8eb2005-03-01 19:00:30 +00001721void
sewardj7eb7c582005-06-23 01:02:53 +00001722ML_(generic_POST_sys_getpeername) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001723 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001724 UWord arg0, UWord arg1, UWord arg2 )
1725{
1726 Addr name_p = arg1;
1727 Addr namelen_p = arg2;
njncda2f0f2009-05-18 02:12:08 +00001728 vg_assert(!sr_isError(res)); /* guaranteed by caller */
njnf37a81b2009-02-17 00:23:30 +00001729 ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p,
1730 "socketcall.getpeername(namelen_out)" );
sewardj9efbbef2005-03-01 16:45:23 +00001731}
1732
1733/* ------ */
1734
sewardj987a8eb2005-03-01 19:00:30 +00001735void
floriane543f302012-10-21 19:43:43 +00001736ML_(generic_PRE_sys_sendmsg) ( ThreadId tid, const HChar *name,
1737 struct vki_msghdr *msg )
sewardj9efbbef2005-03-01 16:45:23 +00001738{
tomfc75e5e2013-02-28 12:50:55 +00001739 msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_read_sendmsg, False );
sewardj9efbbef2005-03-01 16:45:23 +00001740}
1741
1742/* ------ */
1743
sewardj987a8eb2005-03-01 19:00:30 +00001744void
floriane543f302012-10-21 19:43:43 +00001745ML_(generic_PRE_sys_recvmsg) ( ThreadId tid, const HChar *name,
1746 struct vki_msghdr *msg )
sewardj9efbbef2005-03-01 16:45:23 +00001747{
tomfc75e5e2013-02-28 12:50:55 +00001748 msghdr_foreachfield ( tid, name, msg, ~0, pre_mem_write_recvmsg, True );
sewardj9efbbef2005-03-01 16:45:23 +00001749}
1750
sewardj987a8eb2005-03-01 19:00:30 +00001751void
floriane543f302012-10-21 19:43:43 +00001752ML_(generic_POST_sys_recvmsg) ( ThreadId tid, const HChar *name,
1753 struct vki_msghdr *msg, UInt length )
sewardj9efbbef2005-03-01 16:45:23 +00001754{
tomfc75e5e2013-02-28 12:50:55 +00001755 msghdr_foreachfield( tid, name, msg, length, post_mem_write_recvmsg, True );
sewardj9efbbef2005-03-01 16:45:23 +00001756 check_cmsg_for_fds( tid, msg );
1757}
1758
1759
1760/* ---------------------------------------------------------------------
sewardjb369c5e2005-03-24 17:52:02 +00001761 Deal with a bunch of IPC related syscalls
1762 ------------------------------------------------------------------ */
1763
1764/* ------ */
1765
1766void
sewardj7eb7c582005-06-23 01:02:53 +00001767ML_(generic_PRE_sys_semop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001768 UWord arg0, UWord arg1, UWord arg2 )
1769{
1770 /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1771 PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1772}
1773
1774/* ------ */
1775
1776void
sewardj7eb7c582005-06-23 01:02:53 +00001777ML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001778 UWord arg0, UWord arg1,
1779 UWord arg2, UWord arg3 )
1780{
1781 /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1782 struct timespec *timeout); */
1783 PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1784 if (arg3 != 0)
1785 PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1786}
1787
1788/* ------ */
1789
1790static
1791UInt get_sem_count( Int semid )
1792{
sewardja8d8e232005-06-07 20:04:56 +00001793 struct vki_semid_ds buf;
1794 union vki_semun arg;
1795 SysRes res;
sewardjb369c5e2005-03-24 17:52:02 +00001796
sewardj27f96b32008-10-23 09:46:59 +00001797 /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017
1798 (experimental) otherwise complains that the use in the return
1799 statement below is uninitialised. */
1800 buf.sem_nsems = 0;
1801
sewardja8d8e232005-06-07 20:04:56 +00001802 arg.buf = &buf;
sewardjb369c5e2005-03-24 17:52:02 +00001803
sewardj8eb8bab2015-07-21 14:44:28 +00001804# if defined(__NR_semctl)
sewardja8d8e232005-06-07 20:04:56 +00001805 res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
sewardj8eb8bab2015-07-21 14:44:28 +00001806# elif defined(__NR_semsys) /* Solaris */
1807 res = VG_(do_syscall5)(__NR_semsys, VKI_SEMCTL, semid, 0, VKI_IPC_STAT,
1808 *(UWord *)&arg);
sewardja8d8e232005-06-07 20:04:56 +00001809# else
1810 res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1811 VKI_IPC_STAT, (UWord)&arg);
sewardj27f96b32008-10-23 09:46:59 +00001812# endif
njncda2f0f2009-05-18 02:12:08 +00001813 if (sr_isError(res))
sewardja8d8e232005-06-07 20:04:56 +00001814 return 0;
sewardjb369c5e2005-03-24 17:52:02 +00001815
sewardja8d8e232005-06-07 20:04:56 +00001816 return buf.sem_nsems;
sewardjb369c5e2005-03-24 17:52:02 +00001817}
1818
1819void
sewardj7eb7c582005-06-23 01:02:53 +00001820ML_(generic_PRE_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001821 UWord arg0, UWord arg1,
1822 UWord arg2, UWord arg3 )
1823{
1824 /* int semctl(int semid, int semnum, int cmd, ...); */
1825 union vki_semun arg = *(union vki_semun *)&arg3;
1826 UInt nsems;
1827 switch (arg2 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00001828#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001829 case VKI_IPC_INFO:
1830 case VKI_SEM_INFO:
1831 case VKI_IPC_INFO|VKI_IPC_64:
1832 case VKI_SEM_INFO|VKI_IPC_64:
1833 PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1834 (Addr)arg.buf, sizeof(struct vki_seminfo) );
1835 break;
njnf76d27a2009-05-28 01:53:07 +00001836#endif
1837
sewardjb369c5e2005-03-24 17:52:02 +00001838 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00001839#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001840 case VKI_SEM_STAT:
njnf76d27a2009-05-28 01:53:07 +00001841#endif
sewardjb369c5e2005-03-24 17:52:02 +00001842 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1843 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1844 break;
njnf76d27a2009-05-28 01:53:07 +00001845
1846#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001847 case VKI_IPC_STAT|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001848#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001849 case VKI_SEM_STAT|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001850#endif
sewardj8eb8bab2015-07-21 14:44:28 +00001851#endif
1852#if defined(VKI_IPC_STAT64)
1853 case VKI_IPC_STAT64:
1854#endif
1855#if defined(VKI_IPC_64) || defined(VKI_IPC_STAT64)
sewardjb369c5e2005-03-24 17:52:02 +00001856 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1857 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1858 break;
njnf76d27a2009-05-28 01:53:07 +00001859#endif
1860
sewardjb369c5e2005-03-24 17:52:02 +00001861 case VKI_IPC_SET:
1862 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1863 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1864 break;
njnf76d27a2009-05-28 01:53:07 +00001865
1866#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001867 case VKI_IPC_SET|VKI_IPC_64:
sewardj8eb8bab2015-07-21 14:44:28 +00001868#endif
1869#if defined(VKI_IPC_SET64)
1870 case VKI_IPC_SET64:
1871#endif
1872#if defined(VKI_IPC64) || defined(VKI_IPC_SET64)
sewardjb369c5e2005-03-24 17:52:02 +00001873 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1874 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1875 break;
njnf76d27a2009-05-28 01:53:07 +00001876#endif
1877
sewardjb369c5e2005-03-24 17:52:02 +00001878 case VKI_GETALL:
njnf76d27a2009-05-28 01:53:07 +00001879#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001880 case VKI_GETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001881#endif
sewardjb369c5e2005-03-24 17:52:02 +00001882 nsems = get_sem_count( arg0 );
1883 PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1884 (Addr)arg.array, sizeof(unsigned short) * nsems );
1885 break;
njnf76d27a2009-05-28 01:53:07 +00001886
sewardjb369c5e2005-03-24 17:52:02 +00001887 case VKI_SETALL:
njnf76d27a2009-05-28 01:53:07 +00001888#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001889 case VKI_SETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001890#endif
sewardjb369c5e2005-03-24 17:52:02 +00001891 nsems = get_sem_count( arg0 );
1892 PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1893 (Addr)arg.array, sizeof(unsigned short) * nsems );
1894 break;
1895 }
1896}
1897
1898void
sewardj7eb7c582005-06-23 01:02:53 +00001899ML_(generic_POST_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001900 UWord res,
1901 UWord arg0, UWord arg1,
1902 UWord arg2, UWord arg3 )
1903{
1904 union vki_semun arg = *(union vki_semun *)&arg3;
1905 UInt nsems;
1906 switch (arg2 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00001907#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00001908 case VKI_IPC_INFO:
1909 case VKI_SEM_INFO:
1910 case VKI_IPC_INFO|VKI_IPC_64:
1911 case VKI_SEM_INFO|VKI_IPC_64:
1912 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1913 break;
njnf76d27a2009-05-28 01:53:07 +00001914#endif
1915
sewardjb369c5e2005-03-24 17:52:02 +00001916 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00001917#if defined(VKI_SEM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00001918 case VKI_SEM_STAT:
njnf76d27a2009-05-28 01:53:07 +00001919#endif
sewardjb369c5e2005-03-24 17:52:02 +00001920 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1921 break;
njnf76d27a2009-05-28 01:53:07 +00001922
1923#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001924 case VKI_IPC_STAT|VKI_IPC_64:
1925 case VKI_SEM_STAT|VKI_IPC_64:
sewardj8eb8bab2015-07-21 14:44:28 +00001926#endif
1927#if defined(VKI_IPC_STAT64)
1928 case VKI_IPC_STAT64:
1929#endif
1930#if defined(VKI_IPC_64) || defined(VKI_IPC_STAT64)
sewardjb369c5e2005-03-24 17:52:02 +00001931 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1932 break;
njnf76d27a2009-05-28 01:53:07 +00001933#endif
1934
sewardjb369c5e2005-03-24 17:52:02 +00001935 case VKI_GETALL:
njnf76d27a2009-05-28 01:53:07 +00001936#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00001937 case VKI_GETALL|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00001938#endif
sewardjb369c5e2005-03-24 17:52:02 +00001939 nsems = get_sem_count( arg0 );
1940 POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1941 break;
1942 }
1943}
1944
1945/* ------ */
1946
sewardjb369c5e2005-03-24 17:52:02 +00001947/* ------ */
1948
1949static
philippe2d75ea22012-08-16 19:40:52 +00001950SizeT get_shm_size ( Int shmid )
sewardjb369c5e2005-03-24 17:52:02 +00001951{
sewardj8eb8bab2015-07-21 14:44:28 +00001952#if defined(__NR_shmctl)
njncda2f0f2009-05-18 02:12:08 +00001953# ifdef VKI_IPC_64
sewardjb369c5e2005-03-24 17:52:02 +00001954 struct vki_shmid64_ds buf;
philippec8d064a2014-12-17 20:39:55 +00001955# if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
sewardj90741b22010-10-06 12:59:44 +00001956 /* See bug 222545 comment 7 */
1957 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1958 VKI_IPC_STAT, (UWord)&buf);
1959# else
1960 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid,
1961 VKI_IPC_STAT|VKI_IPC_64, (UWord)&buf);
1962# endif
1963# else /* !def VKI_IPC_64 */
sewardjb369c5e2005-03-24 17:52:02 +00001964 struct vki_shmid_ds buf;
njncda2f0f2009-05-18 02:12:08 +00001965 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
sewardj90741b22010-10-06 12:59:44 +00001966# endif /* def VKI_IPC_64 */
sewardj8eb8bab2015-07-21 14:44:28 +00001967#elif defined(__NR_shmsys) /* Solaris */
1968 struct vki_shmid_ds buf;
1969 SysRes __res = VG_(do_syscall4)(__NR_shmsys, VKI_SHMCTL, shmid, VKI_IPC_STAT,
1970 (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +00001971#else
1972 struct vki_shmid_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001973 SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
sewardjb369c5e2005-03-24 17:52:02 +00001974 VKI_IPC_STAT, 0, (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +00001975#endif
1976 if (sr_isError(__res))
sewardjb369c5e2005-03-24 17:52:02 +00001977 return 0;
1978
philippe2d75ea22012-08-16 19:40:52 +00001979 return (SizeT) buf.shm_segsz;
sewardjb369c5e2005-03-24 17:52:02 +00001980}
1981
1982UWord
sewardj7eb7c582005-06-23 01:02:53 +00001983ML_(generic_PRE_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001984 UWord arg0, UWord arg1, UWord arg2 )
1985{
1986 /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
philippe2d75ea22012-08-16 19:40:52 +00001987 SizeT segmentSize = get_shm_size ( arg0 );
sewardj45f4e7c2005-09-27 19:20:21 +00001988 UWord tmp;
1989 Bool ok;
1990 if (arg1 == 0) {
sewardj60457092010-10-06 15:24:39 +00001991 /* arm-linux only: work around the fact that
1992 VG_(am_get_advisory_client_simple) produces something that is
1993 VKI_PAGE_SIZE aligned, whereas what we want is something
1994 VKI_SHMLBA aligned, and VKI_SHMLBA >= VKI_PAGE_SIZE. Hence
1995 increase the request size by VKI_SHMLBA - VKI_PAGE_SIZE and
1996 then round the result up to the next VKI_SHMLBA boundary.
1997 See bug 222545 comment 15. So far, arm-linux is the only
1998 platform where this is known to be necessary. */
1999 vg_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
2000 if (VKI_SHMLBA > VKI_PAGE_SIZE) {
2001 segmentSize += VKI_SHMLBA - VKI_PAGE_SIZE;
2002 }
sewardj45f4e7c2005-09-27 19:20:21 +00002003 tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
sewardj60457092010-10-06 15:24:39 +00002004 if (ok) {
2005 if (VKI_SHMLBA > VKI_PAGE_SIZE) {
2006 arg1 = VG_ROUNDUP(tmp, VKI_SHMLBA);
2007 } else {
2008 arg1 = tmp;
2009 }
2010 }
sewardj45f4e7c2005-09-27 19:20:21 +00002011 }
sewardj7eb7c582005-06-23 01:02:53 +00002012 else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
sewardjb369c5e2005-03-24 17:52:02 +00002013 arg1 = 0;
2014 return arg1;
2015}
2016
2017void
sewardj7eb7c582005-06-23 01:02:53 +00002018ML_(generic_POST_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00002019 UWord res,
2020 UWord arg0, UWord arg1, UWord arg2 )
2021{
philippe2d75ea22012-08-16 19:40:52 +00002022 SizeT segmentSize = VG_PGROUNDUP(get_shm_size(arg0));
sewardjb369c5e2005-03-24 17:52:02 +00002023 if ( segmentSize > 0 ) {
2024 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00002025 Bool d;
sewardjb369c5e2005-03-24 17:52:02 +00002026
tomf61fea02005-10-04 12:04:06 +00002027 if (arg2 & VKI_SHM_RDONLY)
sewardjb369c5e2005-03-24 17:52:02 +00002028 prot &= ~VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00002029 /* It isn't exactly correct to pass 0 for the fd and offset
2030 here. The kernel seems to think the corresponding section
2031 does have dev/ino numbers:
2032
2033 04e52000-04ec8000 rw-s 00000000 00:06 1966090 /SYSV00000000 (deleted)
2034
2035 However there is no obvious way to find them. In order to
2036 cope with the discrepancy, aspacem's sync checker omits the
2037 dev/ino correspondence check in cases where V does not know
2038 the dev/ino. */
njnc6fe8a22010-12-08 02:51:43 +00002039 d = VG_(am_notify_client_shmat)( res, segmentSize, prot );
sewardj45f4e7c2005-09-27 19:20:21 +00002040
2041 /* we don't distinguish whether it's read-only or
2042 * read-write -- it doesn't matter really. */
sewardj9c606bd2008-09-18 18:12:50 +00002043 VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False,
2044 0/*di_handle*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002045 if (d)
florianddd61ff2015-01-04 17:20:45 +00002046 VG_(discard_translations)( (Addr)res,
sewardj45f4e7c2005-09-27 19:20:21 +00002047 (ULong)VG_PGROUNDUP(segmentSize),
2048 "ML_(generic_POST_sys_shmat)" );
sewardjb369c5e2005-03-24 17:52:02 +00002049 }
2050}
2051
2052/* ------ */
2053
2054Bool
sewardj7eb7c582005-06-23 01:02:53 +00002055ML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00002056{
2057 /* int shmdt(const void *shmaddr); */
sewardj7eb7c582005-06-23 01:02:53 +00002058 return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
sewardjb369c5e2005-03-24 17:52:02 +00002059}
2060
2061void
sewardj7eb7c582005-06-23 01:02:53 +00002062ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00002063{
sewardjef1cf8b2006-10-17 01:47:30 +00002064 NSegment const* s = VG_(am_find_nsegment)(arg0);
sewardjb369c5e2005-03-24 17:52:02 +00002065
sewardj0e682c62005-09-28 20:05:31 +00002066 if (s != NULL) {
2067 Addr s_start = s->start;
2068 SizeT s_len = s->end+1 - s->start;
tom1340c352005-10-04 15:59:54 +00002069 Bool d;
2070
dirk7bc57fc2006-04-27 11:05:13 +00002071 vg_assert(s->kind == SkShmC);
2072 vg_assert(s->start == arg0);
tom1340c352005-10-04 15:59:54 +00002073
2074 d = VG_(am_notify_munmap)(s_start, s_len);
sewardj0e682c62005-09-28 20:05:31 +00002075 s = NULL; /* s is now invalid */
2076 VG_TRACK( die_mem_munmap, s_start, s_len );
sewardj45f4e7c2005-09-27 19:20:21 +00002077 if (d)
florianddd61ff2015-01-04 17:20:45 +00002078 VG_(discard_translations)( s_start,
sewardj0e682c62005-09-28 20:05:31 +00002079 (ULong)s_len,
sewardj45f4e7c2005-09-27 19:20:21 +00002080 "ML_(generic_POST_sys_shmdt)" );
sewardjb369c5e2005-03-24 17:52:02 +00002081 }
2082}
2083/* ------ */
2084
2085void
sewardj7eb7c582005-06-23 01:02:53 +00002086ML_(generic_PRE_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00002087 UWord arg0, UWord arg1, UWord arg2 )
2088{
2089 /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
2090 switch (arg1 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00002091#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002092 case VKI_IPC_INFO:
2093 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
2094 arg2, sizeof(struct vki_shminfo) );
2095 break;
njnf76d27a2009-05-28 01:53:07 +00002096#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002097 case VKI_IPC_INFO|VKI_IPC_64:
2098 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
2099 arg2, sizeof(struct vki_shminfo64) );
2100 break;
njnf76d27a2009-05-28 01:53:07 +00002101#endif
2102#endif
2103
2104#if defined(VKI_SHM_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002105 case VKI_SHM_INFO:
njnf76d27a2009-05-28 01:53:07 +00002106#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002107 case VKI_SHM_INFO|VKI_IPC_64:
njnf76d27a2009-05-28 01:53:07 +00002108#endif
sewardjb369c5e2005-03-24 17:52:02 +00002109 PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
2110 arg2, sizeof(struct vki_shm_info) );
2111 break;
njnf76d27a2009-05-28 01:53:07 +00002112#endif
2113
sewardjb369c5e2005-03-24 17:52:02 +00002114 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00002115#if defined(VKI_SHM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00002116 case VKI_SHM_STAT:
njnf76d27a2009-05-28 01:53:07 +00002117#endif
sewardjb369c5e2005-03-24 17:52:02 +00002118 PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
2119 arg2, sizeof(struct vki_shmid_ds) );
2120 break;
njnf76d27a2009-05-28 01:53:07 +00002121
2122#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002123 case VKI_IPC_STAT|VKI_IPC_64:
2124 case VKI_SHM_STAT|VKI_IPC_64:
2125 PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
2126 arg2, sizeof(struct vki_shmid64_ds) );
2127 break;
njnf76d27a2009-05-28 01:53:07 +00002128#endif
2129
sewardjb369c5e2005-03-24 17:52:02 +00002130 case VKI_IPC_SET:
2131 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
2132 arg2, sizeof(struct vki_shmid_ds) );
2133 break;
njnf76d27a2009-05-28 01:53:07 +00002134
2135#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002136 case VKI_IPC_SET|VKI_IPC_64:
2137 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
2138 arg2, sizeof(struct vki_shmid64_ds) );
2139 break;
njnf76d27a2009-05-28 01:53:07 +00002140#endif
sewardjb369c5e2005-03-24 17:52:02 +00002141 }
2142}
2143
2144void
sewardj7eb7c582005-06-23 01:02:53 +00002145ML_(generic_POST_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00002146 UWord res,
2147 UWord arg0, UWord arg1, UWord arg2 )
2148{
2149 switch (arg1 /* cmd */) {
njnf76d27a2009-05-28 01:53:07 +00002150#if defined(VKI_IPC_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002151 case VKI_IPC_INFO:
2152 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
2153 break;
2154 case VKI_IPC_INFO|VKI_IPC_64:
2155 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
2156 break;
njnf76d27a2009-05-28 01:53:07 +00002157#endif
2158
2159#if defined(VKI_SHM_INFO)
sewardjb369c5e2005-03-24 17:52:02 +00002160 case VKI_SHM_INFO:
2161 case VKI_SHM_INFO|VKI_IPC_64:
2162 POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
2163 break;
njnf76d27a2009-05-28 01:53:07 +00002164#endif
2165
sewardjb369c5e2005-03-24 17:52:02 +00002166 case VKI_IPC_STAT:
njnf76d27a2009-05-28 01:53:07 +00002167#if defined(VKI_SHM_STAT)
sewardjb369c5e2005-03-24 17:52:02 +00002168 case VKI_SHM_STAT:
njnf76d27a2009-05-28 01:53:07 +00002169#endif
sewardjb369c5e2005-03-24 17:52:02 +00002170 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
2171 break;
njnf76d27a2009-05-28 01:53:07 +00002172
2173#if defined(VKI_IPC_64)
sewardjb369c5e2005-03-24 17:52:02 +00002174 case VKI_IPC_STAT|VKI_IPC_64:
2175 case VKI_SHM_STAT|VKI_IPC_64:
2176 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
2177 break;
njnf76d27a2009-05-28 01:53:07 +00002178#endif
2179
2180
sewardjb369c5e2005-03-24 17:52:02 +00002181 }
2182}
2183
sewardjb369c5e2005-03-24 17:52:02 +00002184/* ---------------------------------------------------------------------
tom9548a162005-09-30 08:07:53 +00002185 Generic handler for mmap
2186 ------------------------------------------------------------------ */
2187
tom6d85b042005-09-30 16:09:12 +00002188/*
2189 * Although mmap is specified by POSIX and the argument are generally
2190 * consistent across platforms the precise details of the low level
2191 * argument passing conventions differ. For example:
2192 *
2193 * - On x86-linux there is mmap (aka old_mmap) which takes the
2194 * arguments in a memory block and the offset in bytes; and
2195 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
2196 * way and the offset in pages.
2197 *
2198 * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
2199 * arguments in the normal way and the offset in bytes; and
2200 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
2201 * way and the offset in pages.
2202 *
2203 * - On amd64-linux everything is simple and there is just the one
2204 * call, mmap (aka sys_mmap) which takes the arguments in the
2205 * normal way and the offset in bytes.
2206 *
sewardjb5b87402011-03-07 16:05:35 +00002207 * - On s390x-linux there is mmap (aka old_mmap) which takes the
2208 * arguments in a memory block and the offset in bytes. mmap2
2209 * is also available (but not exported via unistd.h) with
2210 * arguments in a memory block and the offset in pages.
2211 *
tom6d85b042005-09-30 16:09:12 +00002212 * To cope with all this we provide a generic handler function here
2213 * and then each platform implements one or more system call handlers
2214 * which call this generic routine after extracting and normalising
2215 * the arguments.
2216 */
2217
tom9548a162005-09-30 08:07:53 +00002218SysRes
2219ML_(generic_PRE_sys_mmap) ( ThreadId tid,
2220 UWord arg1, UWord arg2, UWord arg3,
sewardj274461d2005-10-02 17:01:41 +00002221 UWord arg4, UWord arg5, Off64T arg6 )
tom9548a162005-09-30 08:07:53 +00002222{
2223 Addr advised;
2224 SysRes sres;
2225 MapRequest mreq;
2226 Bool mreq_ok;
2227
sewardj80fe5492013-10-14 14:50:57 +00002228# if defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +00002229 // Nb: we can't use this on Darwin, it has races:
2230 // * needs to RETRY if advisory succeeds but map fails
2231 // (could have been some other thread in a nonblocking call)
2232 // * needs to not use fixed-position mmap() on Darwin
2233 // (mmap will cheerfully smash whatever's already there, which might
2234 // be a new mapping from some other thread in a nonblocking call)
2235 VG_(core_panic)("can't use ML_(generic_PRE_sys_mmap) on Darwin");
sewardj80fe5492013-10-14 14:50:57 +00002236# endif
njnf76d27a2009-05-28 01:53:07 +00002237
tom9548a162005-09-30 08:07:53 +00002238 if (arg2 == 0) {
2239 /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
2240 shall be established. */
2241 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2242 }
2243
2244 if (!VG_IS_PAGE_ALIGNED(arg1)) {
2245 /* zap any misaligned addresses. */
2246 /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
2247 to fail. Here, we catch them all. */
2248 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2249 }
2250
sewardj7e21df82005-09-30 10:48:27 +00002251 if (!VG_IS_PAGE_ALIGNED(arg6)) {
2252 /* zap any misaligned offsets. */
2253 /* SuSV3 says: The off argument is constrained to be aligned and
2254 sized according to the value returned by sysconf() when
2255 passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
2256 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2257 }
2258
tom9548a162005-09-30 08:07:53 +00002259 /* Figure out what kind of allocation constraints there are
2260 (fixed/hint/any), and ask aspacem what we should do. */
2261 mreq.start = arg1;
2262 mreq.len = arg2;
2263 if (arg4 & VKI_MAP_FIXED) {
2264 mreq.rkind = MFixed;
2265 } else
sewardj8eb8bab2015-07-21 14:44:28 +00002266#if defined(VKI_MAP_ALIGN) /* Solaris specific */
2267 if (arg4 & VKI_MAP_ALIGN) {
2268 mreq.rkind = MAlign;
2269 if (mreq.start == 0) {
2270 mreq.start = VKI_PAGE_SIZE;
2271 }
2272 /* VKI_MAP_FIXED and VKI_MAP_ALIGN don't like each other. */
2273 arg4 &= ~VKI_MAP_ALIGN;
2274 } else
2275#endif
tom9548a162005-09-30 08:07:53 +00002276 if (arg1 != 0) {
2277 mreq.rkind = MHint;
2278 } else {
2279 mreq.rkind = MAny;
2280 }
2281
2282 /* Enquire ... */
2283 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2284 if (!mreq_ok) {
2285 /* Our request was bounced, so we'd better fail. */
2286 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2287 }
2288
philippeda0a8cb2015-06-17 19:57:09 +00002289# if defined(VKI_MAP_32BIT)
2290 /* MAP_32BIT is royally unportable, so if the client asks for it, try our
2291 best to make it work (but without complexifying aspacemgr).
2292 If the user requested MAP_32BIT, the mmap-ed space must be in the
2293 first 2GB of the address space. So, return ENOMEM if aspacemgr
2294 advisory is above the first 2GB. If MAP_FIXED is also requested,
2295 MAP_32BIT has to be ignored.
2296 Assumption about aspacemgr behaviour: aspacemgr scans the address space
2297 from low addresses to find a free segment. No special effort is done
2298 to keep the first 2GB 'free' for this MAP_32BIT. So, this will often
2299 fail once the program has already allocated significant memory. */
2300 if ((arg4 & VKI_MAP_32BIT) && !(arg4 & VKI_MAP_FIXED)) {
2301 if (advised + arg2 >= 0x80000000)
2302 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
2303 }
2304# endif
2305
tom9548a162005-09-30 08:07:53 +00002306 /* Otherwise we're OK (so far). Install aspacem's choice of
2307 address, and let the mmap go through. */
2308 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2309 arg4 | VKI_MAP_FIXED,
2310 arg5, arg6);
2311
philippeda0a8cb2015-06-17 19:57:09 +00002312# if defined(VKI_MAP_32BIT)
2313 /* No recovery trial if the advisory was not accepted. */
2314 if ((arg4 & VKI_MAP_32BIT) && !(arg4 & VKI_MAP_FIXED)
2315 && sr_isError(sres)) {
2316 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
2317 }
2318# endif
2319
sewardj427d0162007-01-09 16:47:20 +00002320 /* A refinement: it may be that the kernel refused aspacem's choice
2321 of address. If we were originally asked for a hinted mapping,
2322 there is still a last chance: try again at any address.
2323 Hence: */
njncda2f0f2009-05-18 02:12:08 +00002324 if (mreq.rkind == MHint && sr_isError(sres)) {
sewardj427d0162007-01-09 16:47:20 +00002325 mreq.start = 0;
2326 mreq.len = arg2;
2327 mreq.rkind = MAny;
2328 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2329 if (!mreq_ok) {
2330 /* Our request was bounced, so we'd better fail. */
2331 return VG_(mk_SysRes_Error)( VKI_EINVAL );
2332 }
2333 /* and try again with the kernel */
2334 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2335 arg4 | VKI_MAP_FIXED,
2336 arg5, arg6);
2337 }
2338
philippe98d6b252014-11-01 21:02:13 +00002339 /* Yet another refinement : sometimes valgrind chooses an address
2340 which is not acceptable by the kernel. This at least happens
2341 when mmap-ing huge pages, using the flag MAP_HUGETLB.
2342 valgrind aspacem does not know about huge pages, and modifying
2343 it to handle huge pages is not straightforward (e.g. need
2344 to understand special file system mount options).
2345 So, let's just redo an mmap, without giving any constraint to
2346 the kernel. If that succeeds, check with aspacem that the returned
florian8f8811e2015-08-13 20:35:03 +00002347 address is acceptable.
philippe98d6b252014-11-01 21:02:13 +00002348 This will give a similar effect as if the user would have
florian8f8811e2015-08-13 20:35:03 +00002349 hinted that address.
philippe98d6b252014-11-01 21:02:13 +00002350 The aspacem state will be correctly updated afterwards.
2351 We however cannot do this last refinement when the user asked
2352 for a fixed mapping, as the user asked a specific address. */
2353 if (sr_isError(sres) && !(arg4 & VKI_MAP_FIXED)) {
2354 advised = 0;
2355 /* try mmap with NULL address and without VKI_MAP_FIXED
2356 to let the kernel decide. */
2357 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
2358 arg4,
2359 arg5, arg6);
2360 if (!sr_isError(sres)) {
florian8f8811e2015-08-13 20:35:03 +00002361 /* The kernel is supposed to know what it is doing, but let's
2362 do a last sanity check anyway, as if the chosen address had
2363 been initially hinted by the client. The whole point of this
2364 last try was to allow mmap of huge pages to succeed without
2365 making aspacem understand them, on the other hand the kernel
2366 does not know about valgrind reservations, so this mapping
2367 can end up in free space and reservations. */
2368 mreq.start = (Addr)sr_Res(sres);
2369 mreq.len = arg2;
2370 mreq.rkind = MHint;
2371 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
2372 vg_assert(mreq_ok && advised == mreq.start);
philippe98d6b252014-11-01 21:02:13 +00002373 }
2374 }
2375
njncda2f0f2009-05-18 02:12:08 +00002376 if (!sr_isError(sres)) {
sewardj9c606bd2008-09-18 18:12:50 +00002377 ULong di_handle;
bart510521e2008-05-29 08:52:44 +00002378 /* Notify aspacem. */
njndd372582009-05-10 22:42:19 +00002379 notify_core_of_mmap(
njncda2f0f2009-05-18 02:12:08 +00002380 (Addr)sr_Res(sres), /* addr kernel actually assigned */
bart510521e2008-05-29 08:52:44 +00002381 arg2, /* length */
2382 arg3, /* prot */
tom9548a162005-09-30 08:07:53 +00002383 arg4, /* the original flags value */
bart510521e2008-05-29 08:52:44 +00002384 arg5, /* fd */
2385 arg6 /* offset */
tom9548a162005-09-30 08:07:53 +00002386 );
2387 /* Load symbols? */
njncda2f0f2009-05-18 02:12:08 +00002388 di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres),
sewardj5f2dcad2011-10-24 08:53:03 +00002389 False/*allow_SkFileV*/, (Int)arg5 );
bart510521e2008-05-29 08:52:44 +00002390 /* Notify the tool. */
2391 notify_tool_of_mmap(
njncda2f0f2009-05-18 02:12:08 +00002392 (Addr)sr_Res(sres), /* addr kernel actually assigned */
bart510521e2008-05-29 08:52:44 +00002393 arg2, /* length */
2394 arg3, /* prot */
sewardj9c606bd2008-09-18 18:12:50 +00002395 di_handle /* so the tool can refer to the read debuginfo later,
2396 if it wants. */
bart510521e2008-05-29 08:52:44 +00002397 );
tom9548a162005-09-30 08:07:53 +00002398 }
2399
2400 /* Stay sane */
njncda2f0f2009-05-18 02:12:08 +00002401 if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED))
2402 vg_assert(sr_Res(sres) == arg1);
tom9548a162005-09-30 08:07:53 +00002403
2404 return sres;
2405}
2406
2407
2408/* ---------------------------------------------------------------------
nethercote4fa681f2004-11-08 17:51:39 +00002409 The Main Entertainment ... syscall wrappers
njn25e49d8e72002-09-23 09:36:25 +00002410 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00002411
nethercote4fa681f2004-11-08 17:51:39 +00002412/* Note: the PRE() and POST() wrappers are for the actual functions
nethercote8ff888f2004-11-17 17:11:45 +00002413 implementing the system calls in the OS kernel. These mostly have
nethercote4fa681f2004-11-08 17:51:39 +00002414 names like sys_write(); a few have names like old_mmap(). See the
njnaf839f52005-06-23 03:27:57 +00002415 comment for ML_(syscall_table)[] for important info about the __NR_foo
nethercote8ff888f2004-11-17 17:11:45 +00002416 constants and their relationship to the sys_foo() functions.
nethercote4fa681f2004-11-08 17:51:39 +00002417
nethercote92b2fd52004-11-16 16:15:41 +00002418 Some notes about names used for syscalls and args:
2419 - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
2420 ambiguity.
2421
2422 - For error messages, we generally use a somewhat generic name
2423 for the syscall (eg. "write" rather than "sys_write"). This should be
2424 good enough for the average user to understand what is happening,
2425 without confusing them with names like "sys_write".
2426
2427 - Also, for error messages the arg names are mostly taken from the man
2428 pages (even though many of those man pages are really for glibc
nethercote8ff888f2004-11-17 17:11:45 +00002429 functions of the same name), rather than from the OS kernel source,
nethercote92b2fd52004-11-16 16:15:41 +00002430 for the same reason -- a user presented with a "bogus foo(bar)" arg
2431 will most likely look at the "foo" man page to see which is the "bar"
2432 arg.
nethercote8b76fe52004-11-08 19:20:09 +00002433
nethercote9c311eb2004-11-12 18:20:12 +00002434 Note that we use our own vki_* types. The one exception is in
2435 PRE_REG_READn calls, where pointer types haven't been changed, because
2436 they don't need to be -- eg. for "foo*" to be used, the type foo need not
2437 be visible.
2438
nethercote4fa681f2004-11-08 17:51:39 +00002439 XXX: some of these are arch-specific, and should be factored out.
2440*/
2441
sewardja8d8e232005-06-07 20:04:56 +00002442#define PRE(name) DEFN_PRE_TEMPLATE(generic, name)
2443#define POST(name) DEFN_POST_TEMPLATE(generic, name)
jsgf855d93d2003-10-13 22:26:55 +00002444
sewardja8d8e232005-06-07 20:04:56 +00002445PRE(sys_exit)
jsgf855d93d2003-10-13 22:26:55 +00002446{
sewardja8d8e232005-06-07 20:04:56 +00002447 ThreadState* tst;
sewardja922b612005-03-11 02:47:32 +00002448 /* simple; just make this thread exit */
florianb26101c2015-08-08 21:45:33 +00002449 PRINT("exit( %ld )", SARG1);
njnaab814e2009-03-03 05:39:23 +00002450 PRE_REG_READ1(void, "exit", int, status);
sewardja8d8e232005-06-07 20:04:56 +00002451 tst = VG_(get_ThreadState)(tid);
2452 /* Set the thread's status to be exiting, then claim that the
2453 syscall succeeded. */
sewardjef1cf8b2006-10-17 01:47:30 +00002454 tst->exitreason = VgSrc_ExitThread;
sewardja922b612005-03-11 02:47:32 +00002455 tst->os_state.exitcode = ARG1;
sewardja8d8e232005-06-07 20:04:56 +00002456 SET_STATUS_Success(0);
jsgf855d93d2003-10-13 22:26:55 +00002457}
2458
sewardja8d8e232005-06-07 20:04:56 +00002459PRE(sys_ni_syscall)
nethercoteeb1c7b72004-11-11 19:43:50 +00002460{
njn1a1e95c2009-06-03 06:50:06 +00002461 PRINT("unimplemented (by the kernel) syscall: %s! (ni_syscall)\n",
2462 VG_SYSNUM_STRING(SYSNO));
nethercoteeb1c7b72004-11-11 19:43:50 +00002463 PRE_REG_READ0(long, "ni_syscall");
sewardja8d8e232005-06-07 20:04:56 +00002464 SET_STATUS_Failure( VKI_ENOSYS );
nethercoteeb1c7b72004-11-11 19:43:50 +00002465}
2466
sewardj696c5512005-06-08 23:38:32 +00002467PRE(sys_iopl)
2468{
florianb26101c2015-08-08 21:45:33 +00002469 PRINT("sys_iopl ( %lu )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002470 PRE_REG_READ1(long, "iopl", unsigned long, level);
2471}
2472
sewardj78b50e42005-06-08 01:47:28 +00002473PRE(sys_fsync)
2474{
2475 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002476 PRINT("sys_fsync ( %lu )", ARG1);
sewardj78b50e42005-06-08 01:47:28 +00002477 PRE_REG_READ1(long, "fsync", unsigned int, fd);
2478}
2479
sewardj696c5512005-06-08 23:38:32 +00002480PRE(sys_fdatasync)
2481{
2482 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002483 PRINT("sys_fdatasync ( %lu )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002484 PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
2485}
2486
2487PRE(sys_msync)
2488{
2489 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002490 PRINT("sys_msync ( %#lx, %lu, %#lx )", ARG1, ARG2, ARG3);
sewardj696c5512005-06-08 23:38:32 +00002491 PRE_REG_READ3(long, "msync",
2492 unsigned long, start, vki_size_t, length, int, flags);
2493 PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
2494}
2495
sewardje6d5e722005-06-10 10:27:55 +00002496// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
2497// versions of LiS (Linux Streams). They are not part of the kernel.
2498// Therefore, we have to provide this type ourself, rather than getting it
2499// from the kernel sources.
2500struct vki_pmsg_strbuf {
2501 int maxlen; /* no. of bytes in buffer */
2502 int len; /* no. of bytes returned */
2503 vki_caddr_t buf; /* pointer to data */
2504};
2505PRE(sys_getpmsg)
2506{
2507 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
2508 struct vki_pmsg_strbuf *ctrl;
2509 struct vki_pmsg_strbuf *data;
2510 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002511 PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
2512 ARG4, ARG5);
sewardje6d5e722005-06-10 10:27:55 +00002513 PRE_REG_READ5(int, "getpmsg",
2514 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2515 int *, bandp, int *, flagsp);
2516 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2517 data = (struct vki_pmsg_strbuf *)ARG3;
2518 if (ctrl && ctrl->maxlen > 0)
2519 PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2520 if (data && data->maxlen > 0)
2521 PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2522 if (ARG4)
2523 PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2524 if (ARG5)
2525 PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2526}
2527POST(sys_getpmsg)
2528{
2529 struct vki_pmsg_strbuf *ctrl;
2530 struct vki_pmsg_strbuf *data;
2531 vg_assert(SUCCESS);
2532 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2533 data = (struct vki_pmsg_strbuf *)ARG3;
2534 if (RES == 0 && ctrl && ctrl->len > 0) {
2535 POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2536 }
2537 if (RES == 0 && data && data->len > 0) {
2538 POST_MEM_WRITE( (Addr)data->buf, data->len);
2539 }
2540}
2541
2542PRE(sys_putpmsg)
2543{
2544 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2545 struct vki_pmsg_strbuf *ctrl;
2546 struct vki_pmsg_strbuf *data;
2547 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002548 PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", SARG1, ARG2, ARG3,
2549 SARG4, SARG5);
sewardje6d5e722005-06-10 10:27:55 +00002550 PRE_REG_READ5(int, "putpmsg",
2551 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2552 int, band, int, flags);
2553 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2554 data = (struct vki_pmsg_strbuf *)ARG3;
2555 if (ctrl && ctrl->len > 0)
2556 PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2557 if (data && data->len > 0)
2558 PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2559}
sewardj696c5512005-06-08 23:38:32 +00002560
2561PRE(sys_getitimer)
2562{
njn72bbd8d2009-05-22 08:12:46 +00002563 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
florianb26101c2015-08-08 21:45:33 +00002564 PRINT("sys_getitimer ( %ld, %#lx )", SARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002565 PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
njn72bbd8d2009-05-22 08:12:46 +00002566
2567 PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
2568 PRE_timeval_WRITE( "getitimer(&value->it_value)", &(value->it_value));
sewardj696c5512005-06-08 23:38:32 +00002569}
njnf76d27a2009-05-28 01:53:07 +00002570
sewardj696c5512005-06-08 23:38:32 +00002571POST(sys_getitimer)
2572{
2573 if (ARG2 != (Addr)NULL) {
njn72bbd8d2009-05-22 08:12:46 +00002574 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2575 POST_timeval_WRITE( &(value->it_interval) );
2576 POST_timeval_WRITE( &(value->it_value) );
sewardj696c5512005-06-08 23:38:32 +00002577 }
2578}
2579
2580PRE(sys_setitimer)
2581{
florianb26101c2015-08-08 21:45:33 +00002582 PRINT("sys_setitimer ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
sewardj696c5512005-06-08 23:38:32 +00002583 PRE_REG_READ3(long, "setitimer",
2584 int, which,
2585 struct itimerval *, value, struct itimerval *, ovalue);
njn72bbd8d2009-05-22 08:12:46 +00002586 if (ARG2 != (Addr)NULL) {
2587 struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
2588 PRE_timeval_READ( "setitimer(&value->it_interval)",
2589 &(value->it_interval));
2590 PRE_timeval_READ( "setitimer(&value->it_value)",
2591 &(value->it_value));
2592 }
2593 if (ARG3 != (Addr)NULL) {
2594 struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2595 PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
2596 &(ovalue->it_interval));
2597 PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
2598 &(ovalue->it_value));
2599 }
sewardj696c5512005-06-08 23:38:32 +00002600}
2601
2602POST(sys_setitimer)
2603{
2604 if (ARG3 != (Addr)NULL) {
njn72bbd8d2009-05-22 08:12:46 +00002605 struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
2606 POST_timeval_WRITE( &(ovalue->it_interval) );
2607 POST_timeval_WRITE( &(ovalue->it_value) );
sewardj696c5512005-06-08 23:38:32 +00002608 }
2609}
2610
2611PRE(sys_chroot)
2612{
barta0b6b2c2008-07-07 06:49:24 +00002613 PRINT("sys_chroot ( %#lx )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002614 PRE_REG_READ1(long, "chroot", const char *, path);
2615 PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2616}
sewardja8d8e232005-06-07 20:04:56 +00002617
2618PRE(sys_madvise)
jsgf855d93d2003-10-13 22:26:55 +00002619{
sewardja8d8e232005-06-07 20:04:56 +00002620 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002621 PRINT("sys_madvise ( %#lx, %lu, %ld )", ARG1, ARG2, SARG3);
nethercoteac866b92004-11-15 20:23:15 +00002622 PRE_REG_READ3(long, "madvise",
2623 unsigned long, start, vki_size_t, length, int, advice);
jsgf855d93d2003-10-13 22:26:55 +00002624}
2625
njnf76d27a2009-05-28 01:53:07 +00002626#if HAVE_MREMAP
sewardja8d8e232005-06-07 20:04:56 +00002627PRE(sys_mremap)
jsgf855d93d2003-10-13 22:26:55 +00002628{
nethercote27ea8bc2004-07-10 17:21:14 +00002629 // Nb: this is different to the glibc version described in the man pages,
2630 // which lacks the fifth 'new_address' argument.
tomc00fcc72006-05-08 11:58:06 +00002631 if (ARG4 & VKI_MREMAP_FIXED) {
florianb26101c2015-08-08 21:45:33 +00002632 PRINT("sys_mremap ( %#lx, %lu, %lu, %#lx, %#lx )",
2633 ARG1, ARG2, ARG3, ARG4, ARG5);
tomc00fcc72006-05-08 11:58:06 +00002634 PRE_REG_READ5(unsigned long, "mremap",
2635 unsigned long, old_addr, unsigned long, old_size,
2636 unsigned long, new_size, unsigned long, flags,
2637 unsigned long, new_addr);
2638 } else {
florianb26101c2015-08-08 21:45:33 +00002639 PRINT("sys_mremap ( %#lx, %lu, %lu, 0x%lx )",
2640 ARG1, ARG2, ARG3, ARG4);
tomc00fcc72006-05-08 11:58:06 +00002641 PRE_REG_READ4(unsigned long, "mremap",
2642 unsigned long, old_addr, unsigned long, old_size,
2643 unsigned long, new_size, unsigned long, flags);
2644 }
sewardja8d8e232005-06-07 20:04:56 +00002645 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002646 do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
sewardja8d8e232005-06-07 20:04:56 +00002647 );
jsgf855d93d2003-10-13 22:26:55 +00002648}
njnf76d27a2009-05-28 01:53:07 +00002649#endif /* HAVE_MREMAP */
jsgf855d93d2003-10-13 22:26:55 +00002650
sewardj8c9ea4e2005-06-08 10:46:56 +00002651PRE(sys_nice)
2652{
florianb26101c2015-08-08 21:45:33 +00002653 PRINT("sys_nice ( %ld )", SARG1);
sewardj8c9ea4e2005-06-08 10:46:56 +00002654 PRE_REG_READ1(long, "nice", int, inc);
2655}
sewardj78b50e42005-06-08 01:47:28 +00002656
sewardj696c5512005-06-08 23:38:32 +00002657PRE(sys_mlock)
2658{
2659 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002660 PRINT("sys_mlock ( %#lx, %lu )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002661 PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2662}
2663
2664PRE(sys_munlock)
2665{
2666 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002667 PRINT("sys_munlock ( %#lx, %lu )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002668 PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2669}
2670
2671PRE(sys_mlockall)
2672{
2673 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00002674 PRINT("sys_mlockall ( %lx )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00002675 PRE_REG_READ1(long, "mlockall", int, flags);
2676}
2677
sewardj696c5512005-06-08 23:38:32 +00002678PRE(sys_setpriority)
2679{
florianb26101c2015-08-08 21:45:33 +00002680 PRINT("sys_setpriority ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
sewardj696c5512005-06-08 23:38:32 +00002681 PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2682}
2683
2684PRE(sys_getpriority)
2685{
florianb26101c2015-08-08 21:45:33 +00002686 PRINT("sys_getpriority ( %ld, %ld )", SARG1, SARG2);
sewardj696c5512005-06-08 23:38:32 +00002687 PRE_REG_READ2(long, "getpriority", int, which, int, who);
2688}
2689
njn7b1edbd2009-05-19 06:50:37 +00002690PRE(sys_pwrite64)
sewardjedc95472008-08-07 20:29:55 +00002691{
sewardjedc95472008-08-07 20:29:55 +00002692 *flags |= SfMayBlock;
njn7b1edbd2009-05-19 06:50:37 +00002693#if VG_WORDSIZE == 4
florianb26101c2015-08-08 21:45:33 +00002694 PRINT("sys_pwrite64 ( %lu, %#lx, %lu, %lld )",
2695 ARG1, ARG2, ARG3, (Long)MERGE64(ARG4,ARG5));
sewardje6d5e722005-06-10 10:27:55 +00002696 PRE_REG_READ5(ssize_t, "pwrite64",
2697 unsigned int, fd, const char *, buf, vki_size_t, count,
sewardj0ca89e02009-11-25 13:57:47 +00002698 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
njn7b1edbd2009-05-19 06:50:37 +00002699#elif VG_WORDSIZE == 8
florianb26101c2015-08-08 21:45:33 +00002700 PRINT("sys_pwrite64 ( %lu, %#lx, %lu, %ld )",
2701 ARG1, ARG2, ARG3, SARG4);
njn7b1edbd2009-05-19 06:50:37 +00002702 PRE_REG_READ4(ssize_t, "pwrite64",
2703 unsigned int, fd, const char *, buf, vki_size_t, count,
2704 Word, offset);
2705#else
2706# error Unexpected word size
2707#endif
sewardje6d5e722005-06-10 10:27:55 +00002708 PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2709}
sewardj8c9ea4e2005-06-08 10:46:56 +00002710
2711PRE(sys_sync)
2712{
2713 *flags |= SfMayBlock;
2714 PRINT("sys_sync ( )");
2715 PRE_REG_READ0(long, "sync");
2716}
2717
sewardj696c5512005-06-08 23:38:32 +00002718PRE(sys_fstatfs)
2719{
sewardjcc3de2d2011-08-18 15:08:20 +00002720 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00002721 PRINT("sys_fstatfs ( %lu, %#lx )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00002722 PRE_REG_READ2(long, "fstatfs",
2723 unsigned int, fd, struct statfs *, buf);
2724 PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2725}
2726
2727POST(sys_fstatfs)
2728{
2729 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2730}
2731
sewardje6d5e722005-06-10 10:27:55 +00002732PRE(sys_fstatfs64)
2733{
sewardjcc3de2d2011-08-18 15:08:20 +00002734 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00002735 PRINT("sys_fstatfs64 ( %lu, %lu, %#lx )", ARG1, ARG2, ARG3);
sewardje6d5e722005-06-10 10:27:55 +00002736 PRE_REG_READ3(long, "fstatfs64",
2737 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2738 PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2739}
2740POST(sys_fstatfs64)
2741{
2742 POST_MEM_WRITE( ARG3, ARG2 );
2743}
sewardj696c5512005-06-08 23:38:32 +00002744
2745PRE(sys_getsid)
2746{
florianb26101c2015-08-08 21:45:33 +00002747 PRINT("sys_getsid ( %ld )", SARG1);
sewardj696c5512005-06-08 23:38:32 +00002748 PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2749}
2750
njn7b1edbd2009-05-19 06:50:37 +00002751PRE(sys_pread64)
sewardjedc95472008-08-07 20:29:55 +00002752{
sewardjedc95472008-08-07 20:29:55 +00002753 *flags |= SfMayBlock;
njn7b1edbd2009-05-19 06:50:37 +00002754#if VG_WORDSIZE == 4
florianb26101c2015-08-08 21:45:33 +00002755 PRINT("sys_pread64 ( %lu, %#lx, %lu, %lld )",
2756 ARG1, ARG2, ARG3, (Long)MERGE64(ARG4,ARG5));
sewardje7aa4ae2005-06-09 12:43:42 +00002757 PRE_REG_READ5(ssize_t, "pread64",
2758 unsigned int, fd, char *, buf, vki_size_t, count,
tomca787242009-11-25 11:24:00 +00002759 vki_u32, MERGE64_FIRST(offset), vki_u32, MERGE64_SECOND(offset));
njn7b1edbd2009-05-19 06:50:37 +00002760#elif VG_WORDSIZE == 8
florianb26101c2015-08-08 21:45:33 +00002761 PRINT("sys_pread64 ( %lu, %#lx, %lu, %ld )",
2762 ARG1, ARG2, ARG3, SARG4);
njn7b1edbd2009-05-19 06:50:37 +00002763 PRE_REG_READ4(ssize_t, "pread64",
2764 unsigned int, fd, char *, buf, vki_size_t, count,
2765 Word, offset);
2766#else
2767# error Unexpected word size
2768#endif
sewardje7aa4ae2005-06-09 12:43:42 +00002769 PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2770}
njn7b1edbd2009-05-19 06:50:37 +00002771POST(sys_pread64)
sewardje7aa4ae2005-06-09 12:43:42 +00002772{
2773 vg_assert(SUCCESS);
2774 if (RES > 0) {
2775 POST_MEM_WRITE( ARG2, RES );
2776 }
2777}
jsgf855d93d2003-10-13 22:26:55 +00002778
sewardja8d8e232005-06-07 20:04:56 +00002779PRE(sys_mknod)
jsgf855d93d2003-10-13 22:26:55 +00002780{
sewardjcc3de2d2011-08-18 15:08:20 +00002781 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00002782 PRINT("sys_mknod ( %#lx(%s), %#lx, %#lx )", ARG1, (HChar*)ARG1, ARG2, ARG3 );
nethercotec6851dd2004-11-11 18:00:47 +00002783 PRE_REG_READ3(long, "mknod",
2784 const char *, pathname, int, mode, unsigned, dev);
njn22cfccb2004-11-27 16:10:23 +00002785 PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002786}
2787
sewardj696c5512005-06-08 23:38:32 +00002788PRE(sys_flock)
2789{
2790 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00002791 PRINT("sys_flock ( %lu, %lu )", ARG1, ARG2 );
sewardj696c5512005-06-08 23:38:32 +00002792 PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2793}
2794
nethercotea81e9162004-02-12 14:34:14 +00002795// Pre_read a char** argument.
sewardj8eb8bab2015-07-21 14:44:28 +00002796void ML_(pre_argv_envp)(Addr a, ThreadId tid, const HChar *s1, const HChar *s2)
nethercotea81e9162004-02-12 14:34:14 +00002797{
2798 while (True) {
njnb249fd72004-11-29 14:24:57 +00002799 Addr a_deref;
2800 Addr* a_p = (Addr*)a;
2801 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2802 a_deref = *a_p;
nethercotea81e9162004-02-12 14:34:14 +00002803 if (0 == a_deref)
2804 break;
nethercoteef0c7662004-11-06 15:38:43 +00002805 PRE_MEM_RASCIIZ( s2, a_deref );
nethercotea81e9162004-02-12 14:34:14 +00002806 a += sizeof(char*);
2807 }
2808}
2809
njn7b85dd52005-06-12 17:26:29 +00002810static Bool i_am_the_only_thread ( void )
2811{
2812 Int c = VG_(count_living_threads)();
2813 vg_assert(c >= 1); /* stay sane */
2814 return c == 1;
2815}
2816
2817/* Wait until all other threads disappear. */
2818void VG_(reap_threads)(ThreadId self)
2819{
2820 while (!i_am_the_only_thread()) {
2821 /* Let other thread(s) run */
2822 VG_(vg_yield)();
2823 VG_(poll_signals)(self);
2824 }
2825 vg_assert(i_am_the_only_thread());
2826}
2827
nethercote7310afb2004-11-12 15:41:06 +00002828// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2829// but it seems to work nonetheless...
sewardja8d8e232005-06-07 20:04:56 +00002830PRE(sys_execve)
jsgf855d93d2003-10-13 22:26:55 +00002831{
florian19f91bb2012-11-10 22:29:54 +00002832 HChar* path = NULL; /* path to executable */
2833 HChar** envp = NULL;
2834 HChar** argv = NULL;
2835 HChar** arg2copy;
2836 HChar* launcher_basename = NULL;
sewardja8d8e232005-06-07 20:04:56 +00002837 ThreadState* tst;
sewardj45f4e7c2005-09-27 19:20:21 +00002838 Int i, j, tot_args;
njn73750612005-10-14 03:11:30 +00002839 SysRes res;
sewardj06421272009-11-05 08:55:13 +00002840 Bool setuid_allowed, trace_this_child;
sewardjb5f6f512005-03-10 23:59:00 +00002841
Elliott Hughesed398002017-06-21 14:41:24 -07002842 PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (HChar*)ARG1, ARG2, ARG3);
nethercote7310afb2004-11-12 15:41:06 +00002843 PRE_REG_READ3(vki_off_t, "execve",
2844 char *, filename, char **, argv, char **, envp);
njn22cfccb2004-11-27 16:10:23 +00002845 PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
Elliott Hughesed398002017-06-21 14:41:24 -07002846 if (ARG2 != 0) {
2847 /* At least the terminating NULL must be addressable. */
2848 if (!ML_(safe_to_deref)((HChar **) ARG2, sizeof(HChar *))) {
2849 SET_STATUS_Failure(VKI_EFAULT);
2850 return;
2851 }
sewardj8eb8bab2015-07-21 14:44:28 +00002852 ML_(pre_argv_envp)( ARG2, tid, "execve(argv)", "execve(argv[i])" );
Elliott Hughesed398002017-06-21 14:41:24 -07002853 }
2854 if (ARG3 != 0) {
2855 /* At least the terminating NULL must be addressable. */
2856 if (!ML_(safe_to_deref)((HChar **) ARG3, sizeof(HChar *))) {
2857 SET_STATUS_Failure(VKI_EFAULT);
2858 return;
2859 }
sewardj8eb8bab2015-07-21 14:44:28 +00002860 ML_(pre_argv_envp)( ARG3, tid, "execve(envp)", "execve(envp[i])" );
Elliott Hughesed398002017-06-21 14:41:24 -07002861 }
fitzhardingee1c06d82003-10-30 07:21:44 +00002862
sewardja8d8e232005-06-07 20:04:56 +00002863 vg_assert(VG_(is_valid_tid)(tid));
2864 tst = VG_(get_ThreadState)(tid);
2865
fitzhardingee1c06d82003-10-30 07:21:44 +00002866 /* Erk. If the exec fails, then the following will have made a
2867 mess of things which makes it hard for us to continue. The
2868 right thing to do is piece everything together again in
sewardj45f4e7c2005-09-27 19:20:21 +00002869 POST(execve), but that's close to impossible. Instead, we make
2870 an effort to check that the execve will work before actually
2871 doing it. */
fitzhardingee1c06d82003-10-30 07:21:44 +00002872
njn73750612005-10-14 03:11:30 +00002873 /* Check that the name at least begins in client-accessible storage. */
sewardj06421272009-11-05 08:55:13 +00002874 if (ARG1 == 0 /* obviously bogus */
2875 || !VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
sewardj45f4e7c2005-09-27 19:20:21 +00002876 SET_STATUS_Failure( VKI_EFAULT );
2877 return;
2878 }
2879
sewardj9ab64a42010-12-06 11:40:04 +00002880 // debug-only printing
2881 if (0) {
2882 VG_(printf)("ARG1 = %p(%s)\n", (void*)ARG1, (HChar*)ARG1);
2883 if (ARG2) {
2884 VG_(printf)("ARG2 = ");
2885 Int q;
2886 HChar** vec = (HChar**)ARG2;
2887 for (q = 0; vec[q]; q++)
2888 VG_(printf)("%p(%s) ", vec[q], vec[q]);
2889 VG_(printf)("\n");
2890 } else {
2891 VG_(printf)("ARG2 = null\n");
2892 }
2893 }
2894
sewardj06421272009-11-05 08:55:13 +00002895 // Decide whether or not we want to follow along
sewardj9ab64a42010-12-06 11:40:04 +00002896 { // Make 'child_argv' be a pointer to the child's arg vector
2897 // (skipping the exe name)
florian518850b2014-10-22 22:25:30 +00002898 const HChar** child_argv = (const HChar**)ARG2;
sewardj9ab64a42010-12-06 11:40:04 +00002899 if (child_argv && child_argv[0] == NULL)
2900 child_argv = NULL;
2901 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG1, child_argv );
2902 }
sewardj06421272009-11-05 08:55:13 +00002903
njn73750612005-10-14 03:11:30 +00002904 // Do the important checks: it is a file, is executable, permissions are
sewardjc74b3ba2007-11-17 21:11:57 +00002905 // ok, etc. We allow setuid executables to run only in the case when
2906 // we are not simulating them, that is, they to be run natively.
sewardj06421272009-11-05 08:55:13 +00002907 setuid_allowed = trace_this_child ? False : True;
floriane543f302012-10-21 19:43:43 +00002908 res = VG_(pre_exec_check)((const HChar *)ARG1, NULL, setuid_allowed);
njncda2f0f2009-05-18 02:12:08 +00002909 if (sr_isError(res)) {
2910 SET_STATUS_Failure( sr_Err(res) );
njn73750612005-10-14 03:11:30 +00002911 return;
2912 }
2913
sewardj98e68a42005-10-04 23:07:33 +00002914 /* If we're tracing the child, and the launcher name looks bogus
2915 (possibly because launcher.c couldn't figure it out, see
2916 comments therein) then we have no option but to fail. */
sewardj06421272009-11-05 08:55:13 +00002917 if (trace_this_child
sewardj98e68a42005-10-04 23:07:33 +00002918 && (VG_(name_of_launcher) == NULL
2919 || VG_(name_of_launcher)[0] != '/')) {
2920 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2921 return;
2922 }
2923
sewardj45f4e7c2005-09-27 19:20:21 +00002924 /* After this point, we can't recover if the execve fails. */
florian19f91bb2012-11-10 22:29:54 +00002925 VG_(debugLog)(1, "syswrap", "Exec of %s\n", (HChar*)ARG1);
sewardj45f4e7c2005-09-27 19:20:21 +00002926
sewardj997546c2011-05-17 18:14:53 +00002927
2928 // Terminate gdbserver if it is active.
2929 if (VG_(clo_vgdb) != Vg_VgdbNo) {
2930 // If the child will not be traced, we need to terminate gdbserver
2931 // to cleanup the gdbserver resources (e.g. the FIFO files).
2932 // If child will be traced, we also terminate gdbserver: the new
2933 // Valgrind will start a fresh gdbserver after exec.
2934 VG_(gdbserver) (0);
2935 }
2936
fitzhardingee1c06d82003-10-30 07:21:44 +00002937 /* Resistance is futile. Nuke all other threads. POSIX mandates
2938 this. (Really, nuke them all, since the new process will make
2939 its own new thread.) */
sewardjef1cf8b2006-10-17 01:47:30 +00002940 VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread );
njn7b85dd52005-06-12 17:26:29 +00002941 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002942
sewardj45f4e7c2005-09-27 19:20:21 +00002943 // Set up the child's exe path.
2944 //
sewardj06421272009-11-05 08:55:13 +00002945 if (trace_this_child) {
sewardj45f4e7c2005-09-27 19:20:21 +00002946
2947 // We want to exec the launcher. Get its pre-remembered path.
2948 path = VG_(name_of_launcher);
2949 // VG_(name_of_launcher) should have been acquired by m_main at
2950 // startup.
2951 vg_assert(path);
2952
2953 launcher_basename = VG_(strrchr)(path, '/');
2954 if (launcher_basename == NULL || launcher_basename[1] == 0) {
2955 launcher_basename = path; // hmm, tres dubious
2956 } else {
2957 launcher_basename++;
2958 }
2959
2960 } else {
florian19f91bb2012-11-10 22:29:54 +00002961 path = (HChar*)ARG1;
sewardj45f4e7c2005-09-27 19:20:21 +00002962 }
2963
2964 // Set up the child's environment.
2965 //
tom4e136952005-07-18 14:02:11 +00002966 // Remove the valgrind-specific stuff from the environment so the
njn7b4e5ba2005-08-25 22:53:57 +00002967 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
tom4e136952005-07-18 14:02:11 +00002968 // This is done unconditionally, since if we are tracing the child,
sewardj45f4e7c2005-09-27 19:20:21 +00002969 // the child valgrind will set up the appropriate client environment.
njn11106992005-07-18 14:10:12 +00002970 // Nb: we make a copy of the environment before trying to mangle it
2971 // as it might be in read-only memory (this was bug #101881).
sewardj45f4e7c2005-09-27 19:20:21 +00002972 //
2973 // Then, if tracing the child, set VALGRIND_LIB for it.
2974 //
2975 if (ARG3 == 0) {
2976 envp = NULL;
2977 } else {
florian19f91bb2012-11-10 22:29:54 +00002978 envp = VG_(env_clone)( (HChar**)ARG3 );
sewardj45f4e7c2005-09-27 19:20:21 +00002979 if (envp == NULL) goto hosed;
sewardj8eb8bab2015-07-21 14:44:28 +00002980 VG_(env_remove_valgrind_env_stuff)( envp, True /*ro_strings*/, NULL );
fitzhardinge5408c062004-01-04 23:52:59 +00002981 }
2982
sewardj06421272009-11-05 08:55:13 +00002983 if (trace_this_child) {
sewardj45f4e7c2005-09-27 19:20:21 +00002984 // Set VALGRIND_LIB in ARG3 (the environment)
2985 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
fitzhardinge98abfc72003-12-16 02:05:15 +00002986 }
2987
sewardj45f4e7c2005-09-27 19:20:21 +00002988 // Set up the child's args. If not tracing it, they are
2989 // simply ARG2. Otherwise, they are
2990 //
2991 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
2992 //
2993 // except that the first VG_(args_for_valgrind_noexecpass) args
2994 // are omitted.
2995 //
sewardj06421272009-11-05 08:55:13 +00002996 if (!trace_this_child) {
florian19f91bb2012-11-10 22:29:54 +00002997 argv = (HChar**)ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00002998 } else {
sewardj14c7cc52007-02-25 15:08:24 +00002999 vg_assert( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +00003000 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3001 vg_assert( VG_(args_for_valgrind_noexecpass)
sewardj14c7cc52007-02-25 15:08:24 +00003002 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
sewardj45f4e7c2005-09-27 19:20:21 +00003003 /* how many args in total will there be? */
3004 // launcher basename
3005 tot_args = 1;
3006 // V's args
sewardj14c7cc52007-02-25 15:08:24 +00003007 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
sewardj45f4e7c2005-09-27 19:20:21 +00003008 tot_args -= VG_(args_for_valgrind_noexecpass);
3009 // name of client exe
3010 tot_args++;
3011 // args for client exe, skipping [0]
florian19f91bb2012-11-10 22:29:54 +00003012 arg2copy = (HChar**)ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00003013 if (arg2copy && arg2copy[0]) {
3014 for (i = 1; arg2copy[i]; i++)
3015 tot_args++;
3016 }
3017 // allocate
sewardj9c606bd2008-09-18 18:12:50 +00003018 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3019 (tot_args+1) * sizeof(HChar*) );
sewardj45f4e7c2005-09-27 19:20:21 +00003020 // copy
3021 j = 0;
3022 argv[j++] = launcher_basename;
sewardj14c7cc52007-02-25 15:08:24 +00003023 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
sewardj45f4e7c2005-09-27 19:20:21 +00003024 if (i < VG_(args_for_valgrind_noexecpass))
3025 continue;
sewardj14c7cc52007-02-25 15:08:24 +00003026 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
sewardj45f4e7c2005-09-27 19:20:21 +00003027 }
florian19f91bb2012-11-10 22:29:54 +00003028 argv[j++] = (HChar*)ARG1;
sewardj45f4e7c2005-09-27 19:20:21 +00003029 if (arg2copy && arg2copy[0])
3030 for (i = 1; arg2copy[i]; i++)
3031 argv[j++] = arg2copy[i];
3032 argv[j++] = NULL;
3033 // check
3034 vg_assert(j == tot_args+1);
jsgf855d93d2003-10-13 22:26:55 +00003035 }
jsgf855d93d2003-10-13 22:26:55 +00003036
sewardjb5f6f512005-03-10 23:59:00 +00003037 /*
3038 Set the signal state up for exec.
3039
3040 We need to set the real signal state to make sure the exec'd
3041 process gets SIG_IGN properly.
3042
3043 Also set our real sigmask to match the client's sigmask so that
3044 the exec'd child will get the right mask. First we need to
3045 clear out any pending signals so they they don't get delivered,
3046 which would confuse things.
fitzhardingef0dd7e12004-01-16 02:17:30 +00003047
3048 XXX This is a bug - the signals should remain pending, and be
3049 delivered to the new process after exec. There's also a
3050 race-condition, since if someone delivers us a signal between
3051 the sigprocmask and the execve, we'll still get the signal. Oh
3052 well.
3053 */
3054 {
nethercote73b526f2004-10-31 18:48:21 +00003055 vki_sigset_t allsigs;
3056 vki_siginfo_t info;
sewardjb5f6f512005-03-10 23:59:00 +00003057
njncda2f0f2009-05-18 02:12:08 +00003058 /* What this loop does: it queries SCSS (the signal state that
3059 the client _thinks_ the kernel is in) by calling
3060 VG_(do_sys_sigaction), and modifies the real kernel signal
3061 state accordingly. */
sewardj45f4e7c2005-09-27 19:20:21 +00003062 for (i = 1; i < VG_(max_signal); i++) {
njncda2f0f2009-05-18 02:12:08 +00003063 vki_sigaction_fromK_t sa_f;
3064 vki_sigaction_toK_t sa_t;
3065 VG_(do_sys_sigaction)(i, NULL, &sa_f);
3066 VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
3067 if (sa_t.ksa_handler == VKI_SIG_IGN)
3068 VG_(sigaction)(i, &sa_t, NULL);
sewardjb5f6f512005-03-10 23:59:00 +00003069 else {
njncda2f0f2009-05-18 02:12:08 +00003070 sa_t.ksa_handler = VKI_SIG_DFL;
3071 VG_(sigaction)(i, &sa_t, NULL);
sewardjb5f6f512005-03-10 23:59:00 +00003072 }
3073 }
3074
nethercote73b526f2004-10-31 18:48:21 +00003075 VG_(sigfillset)(&allsigs);
sewardjef1cf8b2006-10-17 01:47:30 +00003076 while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
sewardjb5f6f512005-03-10 23:59:00 +00003077 ;
fitzhardingef0dd7e12004-01-16 02:17:30 +00003078
nethercote73b526f2004-10-31 18:48:21 +00003079 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
fitzhardingef0dd7e12004-01-16 02:17:30 +00003080 }
3081
sewardj45f4e7c2005-09-27 19:20:21 +00003082 if (0) {
florian19f91bb2012-11-10 22:29:54 +00003083 HChar **cpp;
sewardj45f4e7c2005-09-27 19:20:21 +00003084 VG_(printf)("exec: %s\n", path);
3085 for (cpp = argv; cpp && *cpp; cpp++)
3086 VG_(printf)("argv: %s\n", *cpp);
3087 if (0)
3088 for (cpp = envp; cpp && *cpp; cpp++)
3089 VG_(printf)("env: %s\n", *cpp);
3090 }
3091
sewardja8d8e232005-06-07 20:04:56 +00003092 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00003093 VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
sewardja8d8e232005-06-07 20:04:56 +00003094 );
fitzhardingeb50068f2004-02-24 23:42:55 +00003095
sewardj45f4e7c2005-09-27 19:20:21 +00003096 /* If we got here, then the execve failed. We've already made way
3097 too much of a mess to continue, so we have to abort. */
3098 hosed:
tomdc294c32005-08-16 10:19:58 +00003099 vg_assert(FAILURE);
florianb26101c2015-08-08 21:45:33 +00003100 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %lu\n",
3101 ARG1, (HChar*)ARG1, ARG2, ARG3, ERR);
sewardjb5f6f512005-03-10 23:59:00 +00003102 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
sewardj738856f2009-07-15 14:48:32 +00003103 "execve() failing, so I'm dying.\n");
sewardja8d8e232005-06-07 20:04:56 +00003104 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
sewardj738856f2009-07-15 14:48:32 +00003105 "or work out how to recover.\n");
sewardjb5f6f512005-03-10 23:59:00 +00003106 VG_(exit)(101);
jsgf855d93d2003-10-13 22:26:55 +00003107}
3108
sewardja8d8e232005-06-07 20:04:56 +00003109PRE(sys_access)
jsgf855d93d2003-10-13 22:26:55 +00003110{
florianb26101c2015-08-08 21:45:33 +00003111 PRINT("sys_access ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
nethercote9a3beb92004-11-12 17:07:26 +00003112 PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00003113 PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003114}
3115
sewardja8d8e232005-06-07 20:04:56 +00003116PRE(sys_alarm)
jsgf855d93d2003-10-13 22:26:55 +00003117{
florianb26101c2015-08-08 21:45:33 +00003118 PRINT("sys_alarm ( %lu )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00003119 PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
jsgf855d93d2003-10-13 22:26:55 +00003120}
3121
sewardja8d8e232005-06-07 20:04:56 +00003122PRE(sys_brk)
jsgf855d93d2003-10-13 22:26:55 +00003123{
fitzhardinge98abfc72003-12-16 02:05:15 +00003124 Addr brk_limit = VG_(brk_limit);
sewardja8d8e232005-06-07 20:04:56 +00003125 Addr brk_new;
fitzhardinge98abfc72003-12-16 02:05:15 +00003126
jsgf855d93d2003-10-13 22:26:55 +00003127 /* libc says: int brk(void *end_data_segment);
3128 kernel says: void* brk(void* end_data_segment); (more or less)
3129
3130 libc returns 0 on success, and -1 (and sets errno) on failure.
3131 Nb: if you ask to shrink the dataseg end below what it
3132 currently is, that always succeeds, even if the dataseg end
3133 doesn't actually change (eg. brk(0)). Unless it seg faults.
3134
3135 Kernel returns the new dataseg end. If the brk() failed, this
3136 will be unchanged from the old one. That's why calling (kernel)
3137 brk(0) gives the current dataseg end (libc brk() just returns
3138 zero in that case).
3139
3140 Both will seg fault if you shrink it back into a text segment.
3141 */
barta0b6b2c2008-07-07 06:49:24 +00003142 PRINT("sys_brk ( %#lx )", ARG1);
nethercote9c311eb2004-11-12 18:20:12 +00003143 PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
jsgf855d93d2003-10-13 22:26:55 +00003144
florian981abb52015-04-29 12:59:16 +00003145 brk_new = do_brk(ARG1, tid);
sewardja8d8e232005-06-07 20:04:56 +00003146 SET_STATUS_Success( brk_new );
fitzhardinge98abfc72003-12-16 02:05:15 +00003147
sewardja8d8e232005-06-07 20:04:56 +00003148 if (brk_new == ARG1) {
jsgf855d93d2003-10-13 22:26:55 +00003149 /* brk() succeeded */
sewardja8d8e232005-06-07 20:04:56 +00003150 if (brk_new < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00003151 /* successfully shrunk the data segment. */
njn22cfccb2004-11-27 16:10:23 +00003152 VG_TRACK( die_mem_brk, (Addr)ARG1,
3153 brk_limit-ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003154 } else
sewardja8d8e232005-06-07 20:04:56 +00003155 if (brk_new > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00003156 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00003157 VG_TRACK( new_mem_brk, brk_limit,
sewardj7cf4e6b2008-05-01 20:24:26 +00003158 ARG1-brk_limit, tid );
jsgf855d93d2003-10-13 22:26:55 +00003159 }
jsgf855d93d2003-10-13 22:26:55 +00003160 } else {
3161 /* brk() failed */
sewardja8d8e232005-06-07 20:04:56 +00003162 vg_assert(brk_limit == brk_new);
jsgf855d93d2003-10-13 22:26:55 +00003163 }
3164}
3165
sewardja8d8e232005-06-07 20:04:56 +00003166PRE(sys_chdir)
jsgf855d93d2003-10-13 22:26:55 +00003167{
sewardjcc3de2d2011-08-18 15:08:20 +00003168 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003169 PRINT("sys_chdir ( %#lx(%s) )", ARG1,(char*)ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00003170 PRE_REG_READ1(long, "chdir", const char *, path);
njn22cfccb2004-11-27 16:10:23 +00003171 PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003172}
3173
sewardja8d8e232005-06-07 20:04:56 +00003174PRE(sys_chmod)
jsgf855d93d2003-10-13 22:26:55 +00003175{
sewardjcc3de2d2011-08-18 15:08:20 +00003176 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003177 PRINT("sys_chmod ( %#lx(%s), %lu )", ARG1, (HChar*)ARG1, ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00003178 PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
njn22cfccb2004-11-27 16:10:23 +00003179 PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003180}
3181
sewardje6d5e722005-06-10 10:27:55 +00003182PRE(sys_chown)
3183{
sewardjcc3de2d2011-08-18 15:08:20 +00003184 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003185 PRINT("sys_chown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003186 PRE_REG_READ3(long, "chown",
3187 const char *, path, vki_uid_t, owner, vki_gid_t, group);
3188 PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
3189}
3190
3191PRE(sys_lchown)
3192{
sewardjcc3de2d2011-08-18 15:08:20 +00003193 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00003194 PRINT("sys_lchown ( %#lx(%s), 0x%lx, 0x%lx )", ARG1,(char*)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003195 PRE_REG_READ3(long, "lchown",
3196 const char *, path, vki_uid_t, owner, vki_gid_t, group);
3197 PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
3198}
nethercote2e1c37d2004-11-13 13:57:12 +00003199
sewardja8d8e232005-06-07 20:04:56 +00003200PRE(sys_close)
jsgf855d93d2003-10-13 22:26:55 +00003201{
sewardjcc3de2d2011-08-18 15:08:20 +00003202 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003203 PRINT("sys_close ( %lu )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00003204 PRE_REG_READ1(long, "close", unsigned int, fd);
3205
nethercotef8548672004-06-21 12:42:35 +00003206 /* Detect and negate attempts by the client to close Valgrind's log fd */
sewardj9da79d12007-01-13 22:27:51 +00003207 if ( (!ML_(fd_allowed)(ARG1, "close", tid, False))
3208 /* If doing -d style logging (which is to fd=2), don't
3209 allow that to be closed either. */
3210 || (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) )
sewardja8d8e232005-06-07 20:04:56 +00003211 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003212}
3213
nethercote85a456f2004-11-16 17:31:56 +00003214POST(sys_close)
rjwalshf5f536f2003-11-17 17:45:00 +00003215{
sewardj8eb8bab2015-07-21 14:44:28 +00003216 if (VG_(clo_track_fds)) ML_(record_fd_close)(ARG1);
rjwalshf5f536f2003-11-17 17:45:00 +00003217}
jsgf855d93d2003-10-13 22:26:55 +00003218
sewardja8d8e232005-06-07 20:04:56 +00003219PRE(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00003220{
florianb26101c2015-08-08 21:45:33 +00003221 PRINT("sys_dup ( %lu )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00003222 PRE_REG_READ1(long, "dup", unsigned int, oldfd);
jsgf855d93d2003-10-13 22:26:55 +00003223}
3224
nethercote85a456f2004-11-16 17:31:56 +00003225POST(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00003226{
sewardja8d8e232005-06-07 20:04:56 +00003227 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00003228 if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00003229 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00003230 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00003231 } else {
nethercote9a3beb92004-11-12 17:07:26 +00003232 if (VG_(clo_track_fds))
njn096ccdd2009-02-22 23:00:30 +00003233 ML_(record_fd_open_named)(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00003234 }
3235}
3236
sewardja8d8e232005-06-07 20:04:56 +00003237PRE(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00003238{
florianb26101c2015-08-08 21:45:33 +00003239 PRINT("sys_dup2 ( %lu, %lu )", ARG1, ARG2);
nethercote71f05f32004-11-12 18:49:27 +00003240 PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
sewardj7eb7c582005-06-23 01:02:53 +00003241 if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
sewardja8d8e232005-06-07 20:04:56 +00003242 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00003243}
3244
nethercote85a456f2004-11-16 17:31:56 +00003245POST(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00003246{
sewardja8d8e232005-06-07 20:04:56 +00003247 vg_assert(SUCCESS);
nethercote71f05f32004-11-12 18:49:27 +00003248 if (VG_(clo_track_fds))
njn096ccdd2009-02-22 23:00:30 +00003249 ML_(record_fd_open_named)(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00003250}
3251
sewardj696c5512005-06-08 23:38:32 +00003252PRE(sys_fchdir)
3253{
sewardjcc3de2d2011-08-18 15:08:20 +00003254 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003255 PRINT("sys_fchdir ( %lu )", ARG1);
sewardj696c5512005-06-08 23:38:32 +00003256 PRE_REG_READ1(long, "fchdir", unsigned int, fd);
3257}
3258
sewardje6d5e722005-06-10 10:27:55 +00003259PRE(sys_fchown)
3260{
sewardjcc3de2d2011-08-18 15:08:20 +00003261 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003262 PRINT("sys_fchown ( %lu, %lu, %lu )", ARG1, ARG2, ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003263 PRE_REG_READ3(long, "fchown",
3264 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
3265}
sewardj696c5512005-06-08 23:38:32 +00003266
3267PRE(sys_fchmod)
3268{
sewardjcc3de2d2011-08-18 15:08:20 +00003269 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003270 PRINT("sys_fchmod ( %lu, %lu )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00003271 PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
3272}
3273
sewardj696c5512005-06-08 23:38:32 +00003274PRE(sys_newfstat)
3275{
sewardjcc3de2d2011-08-18 15:08:20 +00003276 FUSE_COMPATIBLE_MAY_BLOCK();
florianb26101c2015-08-08 21:45:33 +00003277 PRINT("sys_newfstat ( %lu, %#lx )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00003278 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
3279 PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
3280}
3281
3282POST(sys_newfstat)
3283{
3284 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
3285}
jsgf855d93d2003-10-13 22:26:55 +00003286
Elliott Hughesa0664b92017-04-18 17:46:52 -07003287#if !defined(VGO_solaris) && !defined(VGP_arm64_linux)
nethercote73b526f2004-10-31 18:48:21 +00003288static vki_sigset_t fork_saved_mask;
jsgf855d93d2003-10-13 22:26:55 +00003289
nethercote75a8c982004-11-11 19:03:34 +00003290// In Linux, the sys_fork() function varies across architectures, but we
3291// ignore the various args it gets, and so it looks arch-neutral. Hmm.
sewardja8d8e232005-06-07 20:04:56 +00003292PRE(sys_fork)
jsgf855d93d2003-10-13 22:26:55 +00003293{
njn58bbd942009-05-21 23:59:34 +00003294 Bool is_child;
3295 Int child_pid;
nethercote73b526f2004-10-31 18:48:21 +00003296 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +00003297
nethercote75a8c982004-11-11 19:03:34 +00003298 PRINT("sys_fork ( )");
3299 PRE_REG_READ0(long, "fork");
3300
jsgf855d93d2003-10-13 22:26:55 +00003301 /* Block all signals during fork, so that we can fix things up in
3302 the child without being interrupted. */
nethercote73b526f2004-10-31 18:48:21 +00003303 VG_(sigfillset)(&mask);
3304 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
jsgf855d93d2003-10-13 22:26:55 +00003305
sewardj8eb8bab2015-07-21 14:44:28 +00003306 VG_(do_atfork_pre)(tid);
3307
sewardja8d8e232005-06-07 20:04:56 +00003308 SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
sewardjb5f6f512005-03-10 23:59:00 +00003309
njncda2f0f2009-05-18 02:12:08 +00003310 if (!SUCCESS) return;
3311
sewardj6e9de462011-06-28 07:25:29 +00003312#if defined(VGO_linux)
njn58bbd942009-05-21 23:59:34 +00003313 // RES is 0 for child, non-0 (the child's PID) for parent.
3314 is_child = ( RES == 0 ? True : False );
3315 child_pid = ( is_child ? -1 : RES );
njnf76d27a2009-05-28 01:53:07 +00003316#elif defined(VGO_darwin)
3317 // RES is the child's pid. RESHI is 1 for child, 0 for parent.
3318 is_child = RESHI;
3319 child_pid = RES;
3320#else
3321# error Unknown OS
3322#endif
njncda2f0f2009-05-18 02:12:08 +00003323
njn58bbd942009-05-21 23:59:34 +00003324 if (is_child) {
sewardjb5f6f512005-03-10 23:59:00 +00003325 VG_(do_atfork_child)(tid);
jsgf855d93d2003-10-13 22:26:55 +00003326
3327 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00003328 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
njnf76d27a2009-05-28 01:53:07 +00003329 } else {
njne9ba34a2008-10-13 04:19:15 +00003330 VG_(do_atfork_parent)(tid);
3331
njn58bbd942009-05-21 23:59:34 +00003332 PRINT(" fork: process %d created child %d\n", VG_(getpid)(), child_pid);
jsgf855d93d2003-10-13 22:26:55 +00003333
jsgf855d93d2003-10-13 22:26:55 +00003334 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00003335 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +00003336 }
3337}
Elliott Hughesa0664b92017-04-18 17:46:52 -07003338#endif // !defined(VGO_solaris) && !defined(VGP_arm64_linux)
jsgf855d93d2003-10-13 22:26:55 +00003339
sewardj8c257322005-06-08 01:01:48 +00003340PRE(sys_ftruncate)
3341{
3342 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00003343 PRINT("sys_ftruncate ( %lu, %lu )", ARG1, ARG2);
sewardj8c257322005-06-08 01:01:48 +00003344 PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
3345}
3346
sewardj696c5512005-06-08 23:38:32 +00003347PRE(sys_truncate)
3348{
3349 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00003350 PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1, (HChar*)ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00003351 PRE_REG_READ2(long, "truncate",
3352 const char *, path, unsigned long, length);
3353 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
3354}
3355
sewardje6d5e722005-06-10 10:27:55 +00003356PRE(sys_ftruncate64)
3357{
3358 *flags |= SfMayBlock;
njn89d43f72009-05-24 23:02:55 +00003359#if VG_WORDSIZE == 4
florianb26101c2015-08-08 21:45:33 +00003360 PRINT("sys_ftruncate64 ( %lu, %llu )", ARG1, MERGE64(ARG2,ARG3));
sewardje6d5e722005-06-10 10:27:55 +00003361 PRE_REG_READ3(long, "ftruncate64",
3362 unsigned int, fd,
tomca787242009-11-25 11:24:00 +00003363 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
njn89d43f72009-05-24 23:02:55 +00003364#else
florianb26101c2015-08-08 21:45:33 +00003365 PRINT("sys_ftruncate64 ( %lu, %lu )", ARG1, ARG2);
njn89d43f72009-05-24 23:02:55 +00003366 PRE_REG_READ2(long, "ftruncate64",
3367 unsigned int,fd, UWord,length);
sewardje6d5e722005-06-10 10:27:55 +00003368#endif
njn89d43f72009-05-24 23:02:55 +00003369}
sewardje6d5e722005-06-10 10:27:55 +00003370
sewardje6d5e722005-06-10 10:27:55 +00003371PRE(sys_truncate64)
3372{
3373 *flags |= SfMayBlock;
njn89d43f72009-05-24 23:02:55 +00003374#if VG_WORDSIZE == 4
tomca787242009-11-25 11:24:00 +00003375 PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)MERGE64(ARG2, ARG3));
sewardje6d5e722005-06-10 10:27:55 +00003376 PRE_REG_READ3(long, "truncate64",
3377 const char *, path,
tomca787242009-11-25 11:24:00 +00003378 UWord, MERGE64_FIRST(length), UWord, MERGE64_SECOND(length));
njn89d43f72009-05-24 23:02:55 +00003379#else
3380 PRINT("sys_truncate64 ( %#lx, %lld )", ARG1, (Long)ARG2);
3381 PRE_REG_READ2(long, "truncate64",
3382 const char *,path, UWord,length);
3383#endif
sewardje6d5e722005-06-10 10:27:55 +00003384 PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
3385}
sewardj78b50e42005-06-08 01:47:28 +00003386
3387PRE(sys_getdents)
3388{
3389 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00003390 PRINT("sys_getdents ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
sewardj78b50e42005-06-08 01:47:28 +00003391 PRE_REG_READ3(long, "getdents",
florian99e644a2014-10-04 21:32:06 +00003392 unsigned int, fd, struct vki_dirent *, dirp,
sewardj78b50e42005-06-08 01:47:28 +00003393 unsigned int, count);
3394 PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
3395}
3396
3397POST(sys_getdents)
3398{
3399 vg_assert(SUCCESS);
3400 if (RES > 0)
3401 POST_MEM_WRITE( ARG2, RES );
3402}
jsgf855d93d2003-10-13 22:26:55 +00003403
sewardja8d8e232005-06-07 20:04:56 +00003404PRE(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00003405{
sewardj78b50e42005-06-08 01:47:28 +00003406 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00003407 PRINT("sys_getdents64 ( %lu, %#lx, %lu )",ARG1, ARG2, ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00003408 PRE_REG_READ3(long, "getdents64",
florian99e644a2014-10-04 21:32:06 +00003409 unsigned int, fd, struct vki_dirent64 *, dirp,
nethercote06c7bd72004-11-14 19:11:56 +00003410 unsigned int, count);
njn22cfccb2004-11-27 16:10:23 +00003411 PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00003412}
3413
nethercote85a456f2004-11-16 17:31:56 +00003414POST(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00003415{
sewardja8d8e232005-06-07 20:04:56 +00003416 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003417 if (RES > 0)
3418 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00003419}
3420
sewardj78b50e42005-06-08 01:47:28 +00003421PRE(sys_getgroups)
3422{
florianb26101c2015-08-08 21:45:33 +00003423 PRINT("sys_getgroups ( %ld, %#lx )", SARG1, ARG2);
sewardj78b50e42005-06-08 01:47:28 +00003424 PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
3425 if (ARG1 > 0)
3426 PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
3427}
3428
3429POST(sys_getgroups)
3430{
3431 vg_assert(SUCCESS);
3432 if (ARG1 > 0 && RES > 0)
3433 POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
3434}
nethercote686b5db2004-11-14 13:42:51 +00003435
sewardja8d8e232005-06-07 20:04:56 +00003436PRE(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00003437{
njn4b70e8c2005-08-14 17:36:07 +00003438 // Comment from linux/fs/dcache.c:
3439 // NOTE! The user-level library version returns a character pointer.
3440 // The kernel system call just returns the length of the buffer filled
3441 // (which includes the ending '\0' character), or a negative error
3442 // value.
3443 // Is this Linux-specific? If so it should be moved to syswrap-linux.c.
barta0b6b2c2008-07-07 06:49:24 +00003444 PRINT("sys_getcwd ( %#lx, %llu )", ARG1,(ULong)ARG2);
nethercoteac866b92004-11-15 20:23:15 +00003445 PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
njn22cfccb2004-11-27 16:10:23 +00003446 PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00003447}
3448
nethercote85a456f2004-11-16 17:31:56 +00003449POST(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00003450{
sewardja8d8e232005-06-07 20:04:56 +00003451 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003452 if (RES != (Addr)NULL)
3453 POST_MEM_WRITE( ARG1, RES );
jsgf855d93d2003-10-13 22:26:55 +00003454}
3455
sewardja8d8e232005-06-07 20:04:56 +00003456PRE(sys_geteuid)
jsgf855d93d2003-10-13 22:26:55 +00003457{
nethercote0df495a2004-11-11 16:38:21 +00003458 PRINT("sys_geteuid ( )");
3459 PRE_REG_READ0(long, "geteuid");
jsgf855d93d2003-10-13 22:26:55 +00003460}
3461
sewardj78b50e42005-06-08 01:47:28 +00003462PRE(sys_getegid)
3463{
3464 PRINT("sys_getegid ( )");
3465 PRE_REG_READ0(long, "getegid");
3466}
3467
sewardj78b50e42005-06-08 01:47:28 +00003468PRE(sys_getgid)
3469{
3470 PRINT("sys_getgid ( )");
3471 PRE_REG_READ0(long, "getgid");
3472}
jsgf855d93d2003-10-13 22:26:55 +00003473
sewardja8d8e232005-06-07 20:04:56 +00003474PRE(sys_getpid)
jsgf855d93d2003-10-13 22:26:55 +00003475{
nethercote4e632c22004-11-09 16:45:33 +00003476 PRINT("sys_getpid ()");
3477 PRE_REG_READ0(long, "getpid");
jsgf855d93d2003-10-13 22:26:55 +00003478}
3479
sewardj696c5512005-06-08 23:38:32 +00003480PRE(sys_getpgid)
3481{
florianb26101c2015-08-08 21:45:33 +00003482 PRINT("sys_getpgid ( %ld )", SARG1);
sewardj696c5512005-06-08 23:38:32 +00003483 PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
3484}
sewardj78b50e42005-06-08 01:47:28 +00003485
3486PRE(sys_getpgrp)
3487{
3488 PRINT("sys_getpgrp ()");
3489 PRE_REG_READ0(long, "getpgrp");
3490}
jsgf855d93d2003-10-13 22:26:55 +00003491
sewardja8d8e232005-06-07 20:04:56 +00003492PRE(sys_getppid)
jsgf855d93d2003-10-13 22:26:55 +00003493{
nethercote4e632c22004-11-09 16:45:33 +00003494 PRINT("sys_getppid ()");
3495 PRE_REG_READ0(long, "getppid");
jsgf855d93d2003-10-13 22:26:55 +00003496}
3497
njncf45fd42004-11-24 16:30:22 +00003498static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
jsgf855d93d2003-10-13 22:26:55 +00003499{
nethercote620154f2004-11-12 21:21:07 +00003500 POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00003501
njnf76d27a2009-05-28 01:53:07 +00003502#ifdef _RLIMIT_POSIX_FLAG
3503 // Darwin will sometimes set _RLIMIT_POSIX_FLAG on getrlimit calls.
3504 // Unset it here to make the switch case below work correctly.
3505 a1 &= ~_RLIMIT_POSIX_FLAG;
3506#endif
3507
nethercote620154f2004-11-12 21:21:07 +00003508 switch (a1) {
3509 case VKI_RLIMIT_NOFILE:
3510 ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
3511 ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
3512 break;
nethercote535f03b2004-02-15 15:32:51 +00003513
nethercote620154f2004-11-12 21:21:07 +00003514 case VKI_RLIMIT_DATA:
3515 *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
3516 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00003517
nethercote620154f2004-11-12 21:21:07 +00003518 case VKI_RLIMIT_STACK:
3519 *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3520 break;
njn89d43f72009-05-24 23:02:55 +00003521 }
jsgf855d93d2003-10-13 22:26:55 +00003522}
3523
sewardj696c5512005-06-08 23:38:32 +00003524PRE(sys_old_getrlimit)
3525{
florianb26101c2015-08-08 21:45:33 +00003526 PRINT("sys_old_getrlimit ( %lu, %#lx )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00003527 PRE_REG_READ2(long, "old_getrlimit",
3528 unsigned int, resource, struct rlimit *, rlim);
3529 PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3530}
3531
3532POST(sys_old_getrlimit)
3533{
3534 common_post_getrlimit(tid, ARG1, ARG2);
3535}
nethercote620154f2004-11-12 21:21:07 +00003536
sewardja8d8e232005-06-07 20:04:56 +00003537PRE(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003538{
florianb26101c2015-08-08 21:45:33 +00003539 PRINT("sys_getrlimit ( %lu, %#lx )", ARG1, ARG2);
nethercote620154f2004-11-12 21:21:07 +00003540 PRE_REG_READ2(long, "getrlimit",
3541 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00003542 PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
nethercote620154f2004-11-12 21:21:07 +00003543}
3544
nethercote85a456f2004-11-16 17:31:56 +00003545POST(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003546{
njn22cfccb2004-11-27 16:10:23 +00003547 common_post_getrlimit(tid, ARG1, ARG2);
nethercote620154f2004-11-12 21:21:07 +00003548}
jsgf855d93d2003-10-13 22:26:55 +00003549
sewardj696c5512005-06-08 23:38:32 +00003550PRE(sys_getrusage)
3551{
florianb26101c2015-08-08 21:45:33 +00003552 PRINT("sys_getrusage ( %ld, %#lx )", SARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00003553 PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3554 PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3555}
3556
3557POST(sys_getrusage)
3558{
3559 vg_assert(SUCCESS);
3560 if (RES == 0)
3561 POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3562}
jsgf855d93d2003-10-13 22:26:55 +00003563
sewardja8d8e232005-06-07 20:04:56 +00003564PRE(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003565{
barta0b6b2c2008-07-07 06:49:24 +00003566 PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
nethercote686b5db2004-11-14 13:42:51 +00003567 PRE_REG_READ2(long, "gettimeofday",
3568 struct timeval *, tv, struct timezone *, tz);
njnf76d27a2009-05-28 01:53:07 +00003569 // GrP fixme does darwin write to *tz anymore?
njn72bbd8d2009-05-22 08:12:46 +00003570 if (ARG1 != 0)
3571 PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
njn22cfccb2004-11-27 16:10:23 +00003572 if (ARG2 != 0)
3573 PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003574}
3575
nethercote85a456f2004-11-16 17:31:56 +00003576POST(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003577{
sewardja8d8e232005-06-07 20:04:56 +00003578 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003579 if (RES == 0) {
njn72bbd8d2009-05-22 08:12:46 +00003580 if (ARG1 != 0)
3581 POST_timeval_WRITE( ARG1 );
njn22cfccb2004-11-27 16:10:23 +00003582 if (ARG2 != 0)
3583 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003584 }
3585}
3586
sewardj696c5512005-06-08 23:38:32 +00003587PRE(sys_settimeofday)
3588{
barta0b6b2c2008-07-07 06:49:24 +00003589 PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003590 PRE_REG_READ2(long, "settimeofday",
3591 struct timeval *, tv, struct timezone *, tz);
njn72bbd8d2009-05-22 08:12:46 +00003592 if (ARG1 != 0)
njnda8549d2009-05-25 01:48:59 +00003593 PRE_timeval_READ( "settimeofday(tv)", ARG1 );
sewardj696c5512005-06-08 23:38:32 +00003594 if (ARG2 != 0) {
3595 PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3596 /* maybe should warn if tz->tz_dsttime is non-zero? */
3597 }
3598}
nethercote686b5db2004-11-14 13:42:51 +00003599
sewardja8d8e232005-06-07 20:04:56 +00003600PRE(sys_getuid)
jsgf855d93d2003-10-13 22:26:55 +00003601{
nethercote0df495a2004-11-11 16:38:21 +00003602 PRINT("sys_getuid ( )");
3603 PRE_REG_READ0(long, "getuid");
jsgf855d93d2003-10-13 22:26:55 +00003604}
3605
njn1be9cf62009-05-22 00:15:06 +00003606void ML_(PRE_unknown_ioctl)(ThreadId tid, UWord request, UWord arg)
3607{
3608 /* We don't have any specific information on it, so
3609 try to do something reasonable based on direction and
3610 size bits. The encoding scheme is described in
3611 /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3612
3613 According to Simon Hausmann, _IOC_READ means the kernel
3614 writes a value to the ioctl value passed from the user
3615 space and the other way around with _IOC_WRITE. */
sewardj8eb8bab2015-07-21 14:44:28 +00003616
3617#if defined(VGO_solaris)
3618 /* Majority of Solaris ioctl requests does not honour direction hints. */
3619 UInt dir = _VKI_IOC_NONE;
3620#else
njn1be9cf62009-05-22 00:15:06 +00003621 UInt dir = _VKI_IOC_DIR(request);
sewardj8eb8bab2015-07-21 14:44:28 +00003622#endif
njn1be9cf62009-05-22 00:15:06 +00003623 UInt size = _VKI_IOC_SIZE(request);
sewardj8eb8bab2015-07-21 14:44:28 +00003624
philippeec905f72014-08-17 20:03:51 +00003625 if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) {
njn1be9cf62009-05-22 00:15:06 +00003626 /*
3627 * Be very lax about ioctl handling; the only
3628 * assumption is that the size is correct. Doesn't
3629 * require the full buffer to be initialized when
3630 * writing. Without this, using some device
3631 * drivers with a large number of strange ioctl
3632 * commands becomes very tiresome.
3633 */
3634 } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
bartd77a4ca2014-06-28 07:18:33 +00003635 static UWord unknown_ioctl[10];
3636 static Int moans = sizeof(unknown_ioctl) / sizeof(unknown_ioctl[0]);
3637
njn1be9cf62009-05-22 00:15:06 +00003638 if (moans > 0 && !VG_(clo_xml)) {
bartd77a4ca2014-06-28 07:18:33 +00003639 /* Check if have not already moaned for this request. */
3640 UInt i;
3641 for (i = 0; i < sizeof(unknown_ioctl)/sizeof(unknown_ioctl[0]); i++) {
3642 if (unknown_ioctl[i] == request)
3643 break;
3644 if (unknown_ioctl[i] == 0) {
3645 unknown_ioctl[i] = request;
3646 moans--;
3647 VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
3648 " with no size/direction hints.\n", request);
3649 VG_(umsg)(" This could cause spurious value errors to appear.\n");
3650 VG_(umsg)(" See README_MISSING_SYSCALL_OR_IOCTL for "
3651 "guidance on writing a proper wrapper.\n" );
3652 //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3653 return;
3654 }
3655 }
njn1be9cf62009-05-22 00:15:06 +00003656 }
3657 } else {
3658 //VG_(message)(Vg_UserMsg, "UNKNOWN ioctl %#lx\n", request);
3659 //VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
3660 if ((dir & _VKI_IOC_WRITE) && size > 0)
3661 PRE_MEM_READ( "ioctl(generic)", arg, size);
3662 if ((dir & _VKI_IOC_READ) && size > 0)
3663 PRE_MEM_WRITE( "ioctl(generic)", arg, size);
3664 }
3665}
3666
3667void ML_(POST_unknown_ioctl)(ThreadId tid, UInt res, UWord request, UWord arg)
3668{
3669 /* We don't have any specific information on it, so
3670 try to do something reasonable based on direction and
3671 size bits. The encoding scheme is described in
3672 /usr/include/asm/ioctl.h or /usr/include/sys/ioccom.h .
3673
3674 According to Simon Hausmann, _IOC_READ means the kernel
3675 writes a value to the ioctl value passed from the user
3676 space and the other way around with _IOC_WRITE. */
3677
3678 UInt dir = _VKI_IOC_DIR(request);
3679 UInt size = _VKI_IOC_SIZE(request);
3680 if (size > 0 && (dir & _VKI_IOC_READ)
3681 && res == 0
Elliott Hughesed398002017-06-21 14:41:24 -07003682 && arg != (Addr)NULL) {
njn1be9cf62009-05-22 00:15:06 +00003683 POST_MEM_WRITE(arg, size);
3684 }
3685}
jsgf855d93d2003-10-13 22:26:55 +00003686
njn03f1e582005-03-26 20:08:06 +00003687/*
3688 If we're sending a SIGKILL to one of our own threads, then simulate
3689 it rather than really sending the signal, so that the target thread
3690 gets a chance to clean up. Returns True if we did the killing (or
3691 no killing is necessary), and False if the caller should use the
3692 normal kill syscall.
3693
3694 "pid" is any pid argument which can be passed to kill; group kills
3695 (< -1, 0), and owner kills (-1) are ignored, on the grounds that
3696 they'll most likely hit all the threads and we won't need to worry
3697 about cleanup. In truth, we can't fully emulate these multicast
3698 kills.
3699
3700 "tgid" is a thread group id. If it is not -1, then the target
3701 thread must be in that thread group.
3702 */
sewardj7eb7c582005-06-23 01:02:53 +00003703Bool ML_(do_sigkill)(Int pid, Int tgid)
njn03f1e582005-03-26 20:08:06 +00003704{
3705 ThreadState *tst;
3706 ThreadId tid;
3707
3708 if (pid <= 0)
3709 return False;
3710
sewardj42781722006-12-17 19:36:06 +00003711 tid = VG_(lwpid_to_vgtid)(pid);
njn03f1e582005-03-26 20:08:06 +00003712 if (tid == VG_INVALID_THREADID)
3713 return False; /* none of our threads */
3714
3715 tst = VG_(get_ThreadState)(tid);
3716 if (tst == NULL || tst->status == VgTs_Empty)
3717 return False; /* hm, shouldn't happen */
3718
3719 if (tgid != -1 && tst->os_state.threadgroup != tgid)
3720 return False; /* not the right thread group */
3721
3722 /* Check to see that the target isn't already exiting. */
3723 if (!VG_(is_exiting)(tid)) {
3724 if (VG_(clo_trace_signals))
sewardj738856f2009-07-15 14:48:32 +00003725 VG_(message)(Vg_DebugMsg,
florianb26101c2015-08-08 21:45:33 +00003726 "Thread %u being killed with SIGKILL\n",
sewardj738856f2009-07-15 14:48:32 +00003727 tst->tid);
njn03f1e582005-03-26 20:08:06 +00003728
3729 tst->exitreason = VgSrc_FatalSig;
3730 tst->os_state.fatalsig = VKI_SIGKILL;
3731
3732 if (!VG_(is_running_thread)(tid))
sewardjef1cf8b2006-10-17 01:47:30 +00003733 VG_(get_thread_out_of_syscall)(tid);
njn03f1e582005-03-26 20:08:06 +00003734 }
3735
3736 return True;
3737}
3738
sewardja8d8e232005-06-07 20:04:56 +00003739PRE(sys_kill)
jsgf855d93d2003-10-13 22:26:55 +00003740{
florianb26101c2015-08-08 21:45:33 +00003741 PRINT("sys_kill ( %ld, %ld )", SARG1, SARG2);
sewardj8eb8bab2015-07-21 14:44:28 +00003742 PRE_REG_READ2(long, "kill", int, pid, int, signal);
sewardj7eb7c582005-06-23 01:02:53 +00003743 if (!ML_(client_signal_OK)(ARG2)) {
sewardja8d8e232005-06-07 20:04:56 +00003744 SET_STATUS_Failure( VKI_EINVAL );
njn03f1e582005-03-26 20:08:06 +00003745 return;
3746 }
jsgf855d93d2003-10-13 22:26:55 +00003747
njn03f1e582005-03-26 20:08:06 +00003748 /* If we're sending SIGKILL, check to see if the target is one of
3749 our threads and handle it specially. */
sewardj7eb7c582005-06-23 01:02:53 +00003750 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
sewardja8d8e232005-06-07 20:04:56 +00003751 SET_STATUS_Success(0);
njn03f1e582005-03-26 20:08:06 +00003752 else
njncda2f0f2009-05-18 02:12:08 +00003753 /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean)
3754 affecting how posix-compliant the call is. I guess it is
3755 harmless to pass the 3rd arg on other platforms; hence pass
3756 it on all. */
3757 SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) );
njn03f1e582005-03-26 20:08:06 +00003758
sewardjb5f6f512005-03-10 23:59:00 +00003759 if (VG_(clo_trace_signals))
sewardj738856f2009-07-15 14:48:32 +00003760 VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld\n",
florianb26101c2015-08-08 21:45:33 +00003761 SARG2, SARG1);
sewardja8d8e232005-06-07 20:04:56 +00003762
3763 /* This kill might have given us a pending signal. Ask for a check once
3764 the syscall is done. */
3765 *flags |= SfPollAfter;
jsgf855d93d2003-10-13 22:26:55 +00003766}
3767
sewardja8d8e232005-06-07 20:04:56 +00003768PRE(sys_link)
jsgf855d93d2003-10-13 22:26:55 +00003769{
sewardja8d8e232005-06-07 20:04:56 +00003770 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00003771 PRINT("sys_link ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00003772 PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00003773 PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
3774 PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
jsgf855d93d2003-10-13 22:26:55 +00003775}
3776
sewardj696c5512005-06-08 23:38:32 +00003777PRE(sys_newlstat)
3778{
barta0b6b2c2008-07-07 06:49:24 +00003779 PRINT("sys_newlstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00003780 PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
3781 PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
3782 PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
3783}
3784
3785POST(sys_newlstat)
3786{
3787 vg_assert(SUCCESS);
njn9331c7b2009-06-15 07:43:50 +00003788 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
sewardj696c5512005-06-08 23:38:32 +00003789}
jsgf855d93d2003-10-13 22:26:55 +00003790
sewardja8d8e232005-06-07 20:04:56 +00003791PRE(sys_mkdir)
jsgf855d93d2003-10-13 22:26:55 +00003792{
sewardja8d8e232005-06-07 20:04:56 +00003793 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00003794 PRINT("sys_mkdir ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
nethercote9a3beb92004-11-12 17:07:26 +00003795 PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00003796 PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00003797}
3798
sewardja8d8e232005-06-07 20:04:56 +00003799PRE(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00003800{
florianb26101c2015-08-08 21:45:33 +00003801 PRINT("sys_mprotect ( %#lx, %lu, %lu )", ARG1, ARG2, ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00003802 PRE_REG_READ3(long, "mprotect",
3803 unsigned long, addr, vki_size_t, len, unsigned long, prot);
fitzhardinge98abfc72003-12-16 02:05:15 +00003804
tom65505192005-11-08 16:51:55 +00003805 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
sewardja8d8e232005-06-07 20:04:56 +00003806 SET_STATUS_Failure( VKI_ENOMEM );
sewardj337556e2005-11-09 14:51:59 +00003807 }
njnf76d27a2009-05-28 01:53:07 +00003808#if defined(VKI_PROT_GROWSDOWN)
sewardj337556e2005-11-09 14:51:59 +00003809 else
3810 if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
3811 /* Deal with mprotects on growable stack areas.
3812
3813 The critical files to understand all this are mm/mprotect.c
3814 in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
3815 glibc.
3816
3817 The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
3818 round the start/end address of mprotect to the start/end of
3819 the underlying vma and glibc uses that as an easy way to
3820 change the protection of the stack by calling mprotect on the
3821 last page of the stack with PROT_GROWSDOWN set.
3822
3823 The sanity check provided by the kernel is that the vma must
3824 have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */
tom65505192005-11-08 16:51:55 +00003825 UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
sewardjef1cf8b2006-10-17 01:47:30 +00003826 NSegment const *aseg = VG_(am_find_nsegment)(ARG1);
3827 NSegment const *rseg;
tom65505192005-11-08 16:51:55 +00003828
3829 vg_assert(aseg);
3830
3831 if (grows == VKI_PROT_GROWSDOWN) {
florian3e798632012-11-24 19:41:54 +00003832 rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ );
Elliott Hughesed398002017-06-21 14:41:24 -07003833 if (rseg
3834 && rseg->kind == SkResvn
3835 && rseg->smode == SmUpper
3836 && rseg->end+1 == aseg->start) {
tom65505192005-11-08 16:51:55 +00003837 Addr end = ARG1 + ARG2;
3838 ARG1 = aseg->start;
3839 ARG2 = end - aseg->start;
3840 ARG3 &= ~VKI_PROT_GROWSDOWN;
3841 } else {
3842 SET_STATUS_Failure( VKI_EINVAL );
3843 }
3844 } else if (grows == VKI_PROT_GROWSUP) {
florian3e798632012-11-24 19:41:54 +00003845 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
Elliott Hughesed398002017-06-21 14:41:24 -07003846 if (rseg
3847 && rseg->kind == SkResvn
3848 && rseg->smode == SmLower
3849 && aseg->end+1 == rseg->start) {
tom65505192005-11-08 16:51:55 +00003850 ARG2 = aseg->end - ARG1 + 1;
3851 ARG3 &= ~VKI_PROT_GROWSUP;
3852 } else {
3853 SET_STATUS_Failure( VKI_EINVAL );
3854 }
3855 } else {
sewardj337556e2005-11-09 14:51:59 +00003856 /* both GROWSUP and GROWSDOWN */
tom65505192005-11-08 16:51:55 +00003857 SET_STATUS_Failure( VKI_EINVAL );
3858 }
3859 }
njnf76d27a2009-05-28 01:53:07 +00003860#endif // defined(VKI_PROT_GROWSDOWN)
jsgf855d93d2003-10-13 22:26:55 +00003861}
3862
nethercote85a456f2004-11-16 17:31:56 +00003863POST(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00003864{
njn22cfccb2004-11-27 16:10:23 +00003865 Addr a = ARG1;
3866 SizeT len = ARG2;
3867 Int prot = ARG3;
nethercote27ea8bc2004-07-10 17:21:14 +00003868
njndd372582009-05-10 22:42:19 +00003869 ML_(notify_core_and_tool_of_mprotect)(a, len, prot);
jsgf855d93d2003-10-13 22:26:55 +00003870}
3871
sewardja8d8e232005-06-07 20:04:56 +00003872PRE(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00003873{
barta0b6b2c2008-07-07 06:49:24 +00003874 if (0) VG_(printf)(" munmap( %#lx )\n", ARG1);
3875 PRINT("sys_munmap ( %#lx, %llu )", ARG1,(ULong)ARG2);
nethercote06c7bd72004-11-14 19:11:56 +00003876 PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
fitzhardinge98abfc72003-12-16 02:05:15 +00003877
sewardj7eb7c582005-06-23 01:02:53 +00003878 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
sewardja8d8e232005-06-07 20:04:56 +00003879 SET_STATUS_Failure( VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00003880}
3881
nethercote85a456f2004-11-16 17:31:56 +00003882POST(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00003883{
njn22cfccb2004-11-27 16:10:23 +00003884 Addr a = ARG1;
3885 SizeT len = ARG2;
nethercote27ea8bc2004-07-10 17:21:14 +00003886
florianddd61ff2015-01-04 17:20:45 +00003887 ML_(notify_core_and_tool_of_munmap)( a, len );
jsgf855d93d2003-10-13 22:26:55 +00003888}
3889
sewardje6d5e722005-06-10 10:27:55 +00003890PRE(sys_mincore)
3891{
barta0b6b2c2008-07-07 06:49:24 +00003892 PRINT("sys_mincore ( %#lx, %llu, %#lx )", ARG1,(ULong)ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00003893 PRE_REG_READ3(long, "mincore",
3894 unsigned long, start, vki_size_t, length,
3895 unsigned char *, vec);
njncdaec512005-06-30 00:16:02 +00003896 PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00003897}
3898POST(sys_mincore)
3899{
njncdaec512005-06-30 00:16:02 +00003900 POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00003901}
mueller6ceb2312004-01-02 22:52:34 +00003902
sewardja8d8e232005-06-07 20:04:56 +00003903PRE(sys_nanosleep)
mueller6ceb2312004-01-02 22:52:34 +00003904{
sewardja8d8e232005-06-07 20:04:56 +00003905 *flags |= SfMayBlock|SfPostOnFail;
barta0b6b2c2008-07-07 06:49:24 +00003906 PRINT("sys_nanosleep ( %#lx, %#lx )", ARG1,ARG2);
nethercote5b653bc2004-11-15 14:32:12 +00003907 PRE_REG_READ2(long, "nanosleep",
3908 struct timespec *, req, struct timespec *, rem);
njn22cfccb2004-11-27 16:10:23 +00003909 PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
3910 if (ARG2 != 0)
3911 PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00003912}
3913
nethercote85a456f2004-11-16 17:31:56 +00003914POST(sys_nanosleep)
jsgf855d93d2003-10-13 22:26:55 +00003915{
sewardja8d8e232005-06-07 20:04:56 +00003916 vg_assert(SUCCESS || FAILURE);
sewardjef1cf8b2006-10-17 01:47:30 +00003917 if (ARG2 != 0 && FAILURE && ERR == VKI_EINTR)
njn22cfccb2004-11-27 16:10:23 +00003918 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00003919}
3920
sewardj8eb8bab2015-07-21 14:44:28 +00003921#if defined(VGO_linux) || defined(VGO_solaris)
3922/* Handles the case where the open is of /proc/self/auxv or
3923 /proc/<pid>/auxv, and just gives out a copy of the fd for the
3924 fake file we cooked up at startup (in m_main). Also, seeks the
3925 cloned fd back to the start.
3926 Returns True if auxv open was handled (status is set). */
3927Bool ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
3928 int flags)
3929{
3930 HChar name[30]; // large enough
3931
3932 if (!ML_(safe_to_deref)((const void *) filename, 1))
3933 return False;
3934
3935 /* Opening /proc/<pid>/auxv or /proc/self/auxv? */
3936 VG_(sprintf)(name, "/proc/%d/auxv", VG_(getpid)());
3937 if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/auxv"))
3938 return False;
3939
3940 /* Allow to open the file only for reading. */
3941 if (flags & (VKI_O_WRONLY | VKI_O_RDWR)) {
3942 SET_STATUS_Failure(VKI_EACCES);
3943 return True;
3944 }
3945
3946# if defined(VGO_solaris)
3947 VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_auxv_fd));
3948 SysRes sres = VG_(open)(name, flags, 0);
3949 SET_STATUS_from_SysRes(sres);
3950# else
3951 SysRes sres = VG_(dup)(VG_(cl_auxv_fd));
3952 SET_STATUS_from_SysRes(sres);
3953 if (!sr_isError(sres)) {
3954 OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
3955 if (off < 0)
3956 SET_STATUS_Failure(VKI_EMFILE);
3957 }
3958# endif
3959
3960 return True;
3961}
3962#endif // defined(VGO_linux) || defined(VGO_solaris)
3963
sewardja8d8e232005-06-07 20:04:56 +00003964PRE(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00003965{
njn22cfccb2004-11-27 16:10:23 +00003966 if (ARG2 & VKI_O_CREAT) {
nethercotee824cc42004-11-09 16:20:46 +00003967 // 3-arg version
florianb26101c2015-08-08 21:45:33 +00003968 PRINT("sys_open ( %#lx(%s), %ld, %ld )",ARG1, (HChar*)ARG1, SARG2, SARG3);
nethercotee824cc42004-11-09 16:20:46 +00003969 PRE_REG_READ3(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00003970 const char *, filename, int, flags, int, mode);
nethercotee70bd7d2004-08-18 14:37:17 +00003971 } else {
nethercotee824cc42004-11-09 16:20:46 +00003972 // 2-arg version
florianb26101c2015-08-08 21:45:33 +00003973 PRINT("sys_open ( %#lx(%s), %ld )",ARG1, (HChar*)ARG1, SARG2);
nethercotee824cc42004-11-09 16:20:46 +00003974 PRE_REG_READ2(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00003975 const char *, filename, int, flags);
nethercotee70bd7d2004-08-18 14:37:17 +00003976 }
njn22cfccb2004-11-27 16:10:23 +00003977 PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
sewardj45f4e7c2005-09-27 19:20:21 +00003978
bart9b533f82009-08-25 20:15:41 +00003979#if defined(VGO_linux)
3980 /* Handle the case where the open is of /proc/self/cmdline or
3981 /proc/<pid>/cmdline, and just give it a copy of the fd for the
3982 fake file we cooked up at startup (in m_main). Also, seek the
3983 cloned fd back to the start. */
njn70fa47d2009-05-24 22:32:33 +00003984 {
florianf44ff622014-12-20 16:52:08 +00003985 HChar name[30]; // large enough
florian19f91bb2012-11-10 22:29:54 +00003986 HChar* arg1s = (HChar*) ARG1;
njn70fa47d2009-05-24 22:32:33 +00003987 SysRes sres;
sewardj45f4e7c2005-09-27 19:20:21 +00003988
njn70fa47d2009-05-24 22:32:33 +00003989 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
Elliott Hughesed398002017-06-21 14:41:24 -07003990 if (ML_(safe_to_deref)( arg1s, 1 )
3991 && (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/cmdline"))) {
njn70fa47d2009-05-24 22:32:33 +00003992 sres = VG_(dup)( VG_(cl_cmdline_fd) );
3993 SET_STATUS_from_SysRes( sres );
3994 if (!sr_isError(sres)) {
3995 OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
3996 if (off < 0)
3997 SET_STATUS_Failure( VKI_EMFILE );
3998 }
3999 return;
sewardj45f4e7c2005-09-27 19:20:21 +00004000 }
sewardj45f4e7c2005-09-27 19:20:21 +00004001 }
tom41ad7e72012-10-04 20:27:38 +00004002
sewardj8eb8bab2015-07-21 14:44:28 +00004003 /* Handle also the case of /proc/self/auxv or /proc/<pid>/auxv. */
4004 if (ML_(handle_auxv_open)(status, (const HChar *)ARG1, ARG2))
4005 return;
bart9b533f82009-08-25 20:15:41 +00004006#endif // defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +00004007
4008 /* Otherwise handle normally */
4009 *flags |= SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00004010}
4011
nethercote85a456f2004-11-16 17:31:56 +00004012POST(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00004013{
sewardja8d8e232005-06-07 20:04:56 +00004014 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004015 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004016 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004017 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004018 } else {
nethercote493dd182004-02-24 23:57:47 +00004019 if (VG_(clo_track_fds))
florian19f91bb2012-11-10 22:29:54 +00004020 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004021 }
jsgf855d93d2003-10-13 22:26:55 +00004022}
4023
sewardja8d8e232005-06-07 20:04:56 +00004024PRE(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004025{
sewardja8d8e232005-06-07 20:04:56 +00004026 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004027 PRINT("sys_read ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004028 PRE_REG_READ3(ssize_t, "read",
njnca0518d2004-11-26 19:34:36 +00004029 unsigned int, fd, char *, buf, vki_size_t, count);
jsgf855d93d2003-10-13 22:26:55 +00004030
sewardj7eb7c582005-06-23 01:02:53 +00004031 if (!ML_(fd_allowed)(ARG1, "read", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00004032 SET_STATUS_Failure( VKI_EBADF );
thughes26ab77b2004-08-14 12:10:49 +00004033 else
njn22cfccb2004-11-27 16:10:23 +00004034 PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004035}
4036
nethercote85a456f2004-11-16 17:31:56 +00004037POST(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004038{
sewardja8d8e232005-06-07 20:04:56 +00004039 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004040 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004041}
4042
sewardja8d8e232005-06-07 20:04:56 +00004043PRE(sys_write)
jsgf855d93d2003-10-13 22:26:55 +00004044{
sewardj45f4e7c2005-09-27 19:20:21 +00004045 Bool ok;
sewardja8d8e232005-06-07 20:04:56 +00004046 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004047 PRINT("sys_write ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004048 PRE_REG_READ3(ssize_t, "write",
njnca0518d2004-11-26 19:34:36 +00004049 unsigned int, fd, const char *, buf, vki_size_t, count);
sewardj45f4e7c2005-09-27 19:20:21 +00004050 /* check to see if it is allowed. If not, try for an exemption from
njn628add62005-11-12 18:21:40 +00004051 --sim-hints=enable-outer (used for self hosting). */
sewardj45f4e7c2005-09-27 19:20:21 +00004052 ok = ML_(fd_allowed)(ARG1, "write", tid, False);
4053 if (!ok && ARG1 == 2/*stderr*/
philippeec905f72014-08-17 20:03:51 +00004054 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
sewardj45f4e7c2005-09-27 19:20:21 +00004055 ok = True;
sewardj8eb8bab2015-07-21 14:44:28 +00004056#if defined(VGO_solaris)
Elliott Hughesed398002017-06-21 14:41:24 -07004057 if (!ok && VG_(vfork_fildes_addr) != NULL
4058 && *VG_(vfork_fildes_addr) >= 0 && *VG_(vfork_fildes_addr) == ARG1)
sewardj8eb8bab2015-07-21 14:44:28 +00004059 ok = True;
4060#endif
sewardj45f4e7c2005-09-27 19:20:21 +00004061 if (!ok)
sewardja8d8e232005-06-07 20:04:56 +00004062 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004063 else
njn22cfccb2004-11-27 16:10:23 +00004064 PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004065}
4066
sewardja8d8e232005-06-07 20:04:56 +00004067PRE(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004068{
sewardja8d8e232005-06-07 20:04:56 +00004069 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004070 PRINT("sys_creat ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
nethercotec6851dd2004-11-11 18:00:47 +00004071 PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00004072 PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004073}
4074
nethercote85a456f2004-11-16 17:31:56 +00004075POST(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004076{
sewardja8d8e232005-06-07 20:04:56 +00004077 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004078 if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004079 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004080 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004081 } else {
nethercote493dd182004-02-24 23:57:47 +00004082 if (VG_(clo_track_fds))
florian19f91bb2012-11-10 22:29:54 +00004083 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004084 }
jsgf855d93d2003-10-13 22:26:55 +00004085}
4086
sewardja8d8e232005-06-07 20:04:56 +00004087PRE(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004088{
4089 /* struct pollfd {
nethercoteef0c7662004-11-06 15:38:43 +00004090 int fd; -- file descriptor
4091 short events; -- requested events
4092 short revents; -- returned events
jsgf855d93d2003-10-13 22:26:55 +00004093 };
nethercoteeb0592d2004-11-05 12:02:27 +00004094 int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
jsgf855d93d2003-10-13 22:26:55 +00004095 */
nethercoteeb0592d2004-11-05 12:02:27 +00004096 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004097 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
tom60a4b0b2005-10-12 10:45:27 +00004098 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004099 PRINT("sys_poll ( %#lx, %lu, %ld )\n", ARG1, ARG2, SARG3);
nethercotef90953e2004-11-15 14:50:02 +00004100 PRE_REG_READ3(long, "poll",
tom363ec762006-03-21 10:58:35 +00004101 struct vki_pollfd *, ufds, unsigned int, nfds, long, timeout);
4102
njn22cfccb2004-11-27 16:10:23 +00004103 for (i = 0; i < ARG2; i++) {
tom363ec762006-03-21 10:58:35 +00004104 PRE_MEM_READ( "poll(ufds.fd)",
4105 (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
4106 PRE_MEM_READ( "poll(ufds.events)",
4107 (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
tom68f338f2014-02-09 11:10:08 +00004108 PRE_MEM_WRITE( "poll(ufds.revents)",
tom363ec762006-03-21 10:58:35 +00004109 (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
4110 }
jsgf855d93d2003-10-13 22:26:55 +00004111}
4112
nethercote85a456f2004-11-16 17:31:56 +00004113POST(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004114{
sewardj416b2062008-05-12 15:46:34 +00004115 if (RES >= 0) {
jsgf855d93d2003-10-13 22:26:55 +00004116 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004117 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
njn22cfccb2004-11-27 16:10:23 +00004118 for (i = 0; i < ARG2; i++)
tom363ec762006-03-21 10:58:35 +00004119 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
jsgf855d93d2003-10-13 22:26:55 +00004120 }
4121}
4122
sewardja8d8e232005-06-07 20:04:56 +00004123PRE(sys_readlink)
jsgf855d93d2003-10-13 22:26:55 +00004124{
sewardjcc3de2d2011-08-18 15:08:20 +00004125 FUSE_COMPATIBLE_MAY_BLOCK();
njncc1284f2009-05-23 01:51:54 +00004126 Word saved = SYSNO;
sewardj144c56d2005-09-30 01:09:50 +00004127
barta0b6b2c2008-07-07 06:49:24 +00004128 PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
nethercote5a945af2004-11-14 18:37:07 +00004129 PRE_REG_READ3(long, "readlink",
4130 const char *, path, char *, buf, int, bufsiz);
njn22cfccb2004-11-27 16:10:23 +00004131 PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
4132 PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004133
Elliott Hughesed398002017-06-21 14:41:24 -07004134
njncc1284f2009-05-23 01:51:54 +00004135 {
Elliott Hughesed398002017-06-21 14:41:24 -07004136#if defined(VGO_linux) || defined(VGO_solaris)
bart9b533f82009-08-25 20:15:41 +00004137#if defined(VGO_linux)
Elliott Hughesed398002017-06-21 14:41:24 -07004138#define PID_EXEPATH "/proc/%d/exe"
4139#define SELF_EXEPATH "/proc/self/exe"
4140#define SELF_EXEFD "/proc/self/fd/%d"
4141#elif defined(VGO_solaris)
4142#define PID_EXEPATH "/proc/%d/path/a.out"
4143#define SELF_EXEPATH "/proc/self/path/a.out"
4144#define SELF_EXEFD "/proc/self/path/%d"
4145#endif
njncc1284f2009-05-23 01:51:54 +00004146 /*
4147 * Handle the case where readlink is looking at /proc/self/exe or
Elliott Hughesed398002017-06-21 14:41:24 -07004148 * /proc/<pid>/exe, or equivalent on Solaris.
njncc1284f2009-05-23 01:51:54 +00004149 */
florianf44ff622014-12-20 16:52:08 +00004150 HChar name[30]; // large enough
florian19f91bb2012-11-10 22:29:54 +00004151 HChar* arg1s = (HChar*) ARG1;
Elliott Hughesed398002017-06-21 14:41:24 -07004152 VG_(sprintf)(name, PID_EXEPATH, VG_(getpid)());
4153 if (ML_(safe_to_deref)(arg1s, 1)
4154 && (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, SELF_EXEPATH))) {
4155 VG_(sprintf)(name, SELF_EXEFD, VG_(cl_exec_fd));
njncc1284f2009-05-23 01:51:54 +00004156 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
4157 ARG2, ARG3));
4158 } else
sewardj8eb8bab2015-07-21 14:44:28 +00004159#endif
njncc1284f2009-05-23 01:51:54 +00004160 {
4161 /* Normal case */
4162 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
4163 }
rjwalsh17d85302004-11-18 22:56:09 +00004164 }
4165
sewardja8d8e232005-06-07 20:04:56 +00004166 if (SUCCESS && RES > 0)
njn22cfccb2004-11-27 16:10:23 +00004167 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004168}
4169
sewardja8d8e232005-06-07 20:04:56 +00004170PRE(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004171{
jsgf855d93d2003-10-13 22:26:55 +00004172 Int i;
nethercote73b526f2004-10-31 18:48:21 +00004173 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00004174 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004175 PRINT("sys_readv ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00004176 PRE_REG_READ3(ssize_t, "readv",
4177 unsigned long, fd, const struct iovec *, vector,
4178 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00004179 if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00004180 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004181 } else {
florian7cbe0682015-04-25 18:14:17 +00004182 if ((Int)ARG3 >= 0)
4183 PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
nethercoted6b5a212004-11-15 17:04:14 +00004184
njn22cfccb2004-11-27 16:10:23 +00004185 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00004186 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00004187 vec = (struct vki_iovec *)ARG2;
4188 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00004189 PRE_MEM_WRITE( "readv(vector[...])",
4190 (Addr)vec[i].iov_base, vec[i].iov_len );
4191 }
jsgf855d93d2003-10-13 22:26:55 +00004192 }
4193}
4194
nethercote85a456f2004-11-16 17:31:56 +00004195POST(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004196{
sewardja8d8e232005-06-07 20:04:56 +00004197 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004198 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00004199 Int i;
njn22cfccb2004-11-27 16:10:23 +00004200 struct vki_iovec * vec = (struct vki_iovec *)ARG2;
4201 Int remains = RES;
jsgf855d93d2003-10-13 22:26:55 +00004202
njn22cfccb2004-11-27 16:10:23 +00004203 /* RES holds the number of bytes read. */
4204 for (i = 0; i < (Int)ARG3; i++) {
jsgf855d93d2003-10-13 22:26:55 +00004205 Int nReadThisBuf = vec[i].iov_len;
4206 if (nReadThisBuf > remains) nReadThisBuf = remains;
nethercoteef0c7662004-11-06 15:38:43 +00004207 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
jsgf855d93d2003-10-13 22:26:55 +00004208 remains -= nReadThisBuf;
4209 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4210 }
4211 }
4212}
4213
sewardja8d8e232005-06-07 20:04:56 +00004214PRE(sys_rename)
jsgf855d93d2003-10-13 22:26:55 +00004215{
sewardjcc3de2d2011-08-18 15:08:20 +00004216 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00004217 PRINT("sys_rename ( %#lx(%s), %#lx(%s) )", ARG1,(char*)ARG1,ARG2,(char*)ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00004218 PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00004219 PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
4220 PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00004221}
4222
sewardj78b50e42005-06-08 01:47:28 +00004223PRE(sys_rmdir)
4224{
4225 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004226 PRINT("sys_rmdir ( %#lx(%s) )", ARG1,(char*)ARG1);
sewardj78b50e42005-06-08 01:47:28 +00004227 PRE_REG_READ1(long, "rmdir", const char *, pathname);
4228 PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
4229}
4230
sewardja8d8e232005-06-07 20:04:56 +00004231PRE(sys_select)
jsgf855d93d2003-10-13 22:26:55 +00004232{
sewardja8d8e232005-06-07 20:04:56 +00004233 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004234 PRINT("sys_select ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
4235 ARG4, ARG5);
nethercotef1049bf2004-11-14 17:03:47 +00004236 PRE_REG_READ5(long, "select",
4237 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
tom363ec762006-03-21 10:58:35 +00004238 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
nethercotef1049bf2004-11-14 17:03:47 +00004239 // XXX: this possibly understates how much memory is read.
njn22cfccb2004-11-27 16:10:23 +00004240 if (ARG2 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004241 PRE_MEM_READ( "select(readfds)",
njn22cfccb2004-11-27 16:10:23 +00004242 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
4243 if (ARG3 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004244 PRE_MEM_READ( "select(writefds)",
njn22cfccb2004-11-27 16:10:23 +00004245 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
4246 if (ARG4 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004247 PRE_MEM_READ( "select(exceptfds)",
njn22cfccb2004-11-27 16:10:23 +00004248 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
4249 if (ARG5 != 0)
njn72bbd8d2009-05-22 08:12:46 +00004250 PRE_timeval_READ( "select(timeout)", ARG5 );
nethercotef1049bf2004-11-14 17:03:47 +00004251}
4252
sewardje6d5e722005-06-10 10:27:55 +00004253PRE(sys_setgid)
4254{
florianb26101c2015-08-08 21:45:33 +00004255 PRINT("sys_setgid ( %lu )", ARG1);
sewardje6d5e722005-06-10 10:27:55 +00004256 PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
4257}
sewardj696c5512005-06-08 23:38:32 +00004258
4259PRE(sys_setsid)
4260{
4261 PRINT("sys_setsid ( )");
4262 PRE_REG_READ0(long, "setsid");
4263}
4264
sewardje6d5e722005-06-10 10:27:55 +00004265PRE(sys_setgroups)
4266{
barta0b6b2c2008-07-07 06:49:24 +00004267 PRINT("setgroups ( %llu, %#lx )", (ULong)ARG1, ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004268 PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
4269 if (ARG1 > 0)
4270 PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
4271}
sewardj696c5512005-06-08 23:38:32 +00004272
4273PRE(sys_setpgid)
4274{
florianb26101c2015-08-08 21:45:33 +00004275 PRINT("setpgid ( %ld, %ld )", SARG1, SARG2);
sewardj696c5512005-06-08 23:38:32 +00004276 PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
4277}
4278
4279PRE(sys_setregid)
4280{
florianb26101c2015-08-08 21:45:33 +00004281 PRINT("sys_setregid ( %lu, %lu )", ARG1, ARG2);
sewardj696c5512005-06-08 23:38:32 +00004282 PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
4283}
4284
sewardje6d5e722005-06-10 10:27:55 +00004285PRE(sys_setreuid)
4286{
barta0b6b2c2008-07-07 06:49:24 +00004287 PRINT("sys_setreuid ( 0x%lx, 0x%lx )", ARG1, ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004288 PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
4289}
nethercote9c311eb2004-11-12 18:20:12 +00004290
sewardja8d8e232005-06-07 20:04:56 +00004291PRE(sys_setrlimit)
jsgf855d93d2003-10-13 22:26:55 +00004292{
njnf76d27a2009-05-28 01:53:07 +00004293 UWord arg1 = ARG1;
florianb26101c2015-08-08 21:45:33 +00004294 PRINT("sys_setrlimit ( %lu, %#lx )", ARG1, ARG2);
nethercote17258dc2004-11-12 19:55:08 +00004295 PRE_REG_READ2(long, "setrlimit",
4296 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00004297 PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
fitzhardingeb50068f2004-02-24 23:42:55 +00004298
njnf76d27a2009-05-28 01:53:07 +00004299#ifdef _RLIMIT_POSIX_FLAG
4300 // Darwin will sometimes set _RLIMIT_POSIX_FLAG on setrlimit calls.
4301 // Unset it here to make the if statements below work correctly.
4302 arg1 &= ~_RLIMIT_POSIX_FLAG;
4303#endif
4304
philippedb16f832014-09-19 19:35:24 +00004305 if (!VG_(am_is_valid_for_client)(ARG2, sizeof(struct vki_rlimit),
4306 VKI_PROT_READ)) {
4307 SET_STATUS_Failure( VKI_EFAULT );
4308 }
4309 else if (((struct vki_rlimit *)ARG2)->rlim_cur
4310 > ((struct vki_rlimit *)ARG2)->rlim_max) {
tomaba260b2012-03-01 13:42:18 +00004311 SET_STATUS_Failure( VKI_EINVAL );
4312 }
4313 else if (arg1 == VKI_RLIMIT_NOFILE) {
njn22cfccb2004-11-27 16:10:23 +00004314 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
4315 ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
sewardja8d8e232005-06-07 20:04:56 +00004316 SET_STATUS_Failure( VKI_EPERM );
thughesad1c9562004-06-26 11:27:52 +00004317 }
4318 else {
njn22cfccb2004-11-27 16:10:23 +00004319 VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
sewardja8d8e232005-06-07 20:04:56 +00004320 SET_STATUS_Success( 0 );
thughesad1c9562004-06-26 11:27:52 +00004321 }
4322 }
njnf76d27a2009-05-28 01:53:07 +00004323 else if (arg1 == VKI_RLIMIT_DATA) {
tomae0739d2006-03-20 15:36:28 +00004324 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_data).rlim_max ||
4325 ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_data).rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00004326 SET_STATUS_Failure( VKI_EPERM );
thughesaa4fb112004-09-11 14:19:25 +00004327 }
4328 else {
njn22cfccb2004-11-27 16:10:23 +00004329 VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00004330 SET_STATUS_Success( 0 );
thughesaa4fb112004-09-11 14:19:25 +00004331 }
fitzhardingeb50068f2004-02-24 23:42:55 +00004332 }
njnf76d27a2009-05-28 01:53:07 +00004333 else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
tomae0739d2006-03-20 15:36:28 +00004334 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(client_rlimit_stack).rlim_max ||
4335 ((struct vki_rlimit *)ARG2)->rlim_max > VG_(client_rlimit_stack).rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00004336 SET_STATUS_Failure( VKI_EPERM );
thughesc37184f2004-09-11 14:16:57 +00004337 }
4338 else {
sewardj8eb8bab2015-07-21 14:44:28 +00004339 /* Change the value of client_stack_szB to the rlim_cur value but
4340 only if it is smaller than the size of the allocated stack for the
4341 client.
4342 TODO: All platforms should set VG_(clstk_max_size) as part of their
4343 setup_client_stack(). */
4344 if ((VG_(clstk_max_size) == 0)
4345 || (((struct vki_rlimit *) ARG2)->rlim_cur <= VG_(clstk_max_size)))
4346 VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
4347
njn22cfccb2004-11-27 16:10:23 +00004348 VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00004349 SET_STATUS_Success( 0 );
thughesc37184f2004-09-11 14:16:57 +00004350 }
4351 }
jsgf855d93d2003-10-13 22:26:55 +00004352}
4353
sewardje6d5e722005-06-10 10:27:55 +00004354PRE(sys_setuid)
4355{
florianb26101c2015-08-08 21:45:33 +00004356 PRINT("sys_setuid ( %lu )", ARG1);
sewardje6d5e722005-06-10 10:27:55 +00004357 PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
4358}
jsgf855d93d2003-10-13 22:26:55 +00004359
sewardj696c5512005-06-08 23:38:32 +00004360PRE(sys_newstat)
4361{
philipped7aa40d2015-04-19 12:39:33 +00004362 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00004363 PRINT("sys_newstat ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00004364 PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
4365 PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
4366 PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
4367}
4368
4369POST(sys_newstat)
4370{
4371 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
4372}
4373
4374PRE(sys_statfs)
4375{
philipped7aa40d2015-04-19 12:39:33 +00004376 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00004377 PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
sewardj696c5512005-06-08 23:38:32 +00004378 PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
4379 PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
4380 PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
4381}
sewardj696c5512005-06-08 23:38:32 +00004382POST(sys_statfs)
4383{
4384 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
4385}
4386
sewardje6d5e722005-06-10 10:27:55 +00004387PRE(sys_statfs64)
4388{
barta0b6b2c2008-07-07 06:49:24 +00004389 PRINT("sys_statfs64 ( %#lx(%s), %llu, %#lx )",ARG1,(char*)ARG1,(ULong)ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00004390 PRE_REG_READ3(long, "statfs64",
4391 const char *, path, vki_size_t, size, struct statfs64 *, buf);
4392 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4393 PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
4394}
4395POST(sys_statfs64)
4396{
4397 POST_MEM_WRITE( ARG3, ARG2 );
4398}
sewardj78b50e42005-06-08 01:47:28 +00004399
4400PRE(sys_symlink)
4401{
4402 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004403 PRINT("sys_symlink ( %#lx(%s), %#lx(%s) )",ARG1,(char*)ARG1,ARG2,(char*)ARG2);
sewardj78b50e42005-06-08 01:47:28 +00004404 PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
4405 PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
4406 PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
4407}
sewardj9efbbef2005-03-01 16:45:23 +00004408
sewardja8d8e232005-06-07 20:04:56 +00004409PRE(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00004410{
4411 /* time_t time(time_t *t); */
barta0b6b2c2008-07-07 06:49:24 +00004412 PRINT("sys_time ( %#lx )",ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00004413 PRE_REG_READ1(long, "time", int *, t);
njn22cfccb2004-11-27 16:10:23 +00004414 if (ARG1 != 0) {
4415 PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00004416 }
4417}
4418
nethercote85a456f2004-11-16 17:31:56 +00004419POST(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00004420{
njn22cfccb2004-11-27 16:10:23 +00004421 if (ARG1 != 0) {
4422 POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00004423 }
4424}
4425
sewardj78b50e42005-06-08 01:47:28 +00004426PRE(sys_times)
4427{
barta0b6b2c2008-07-07 06:49:24 +00004428 PRINT("sys_times ( %#lx )", ARG1);
sewardj78b50e42005-06-08 01:47:28 +00004429 PRE_REG_READ1(long, "times", struct tms *, buf);
tom18f19272005-07-18 11:03:35 +00004430 if (ARG1 != 0) {
4431 PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
4432 }
sewardj78b50e42005-06-08 01:47:28 +00004433}
4434
4435POST(sys_times)
4436{
4437 if (ARG1 != 0) {
4438 POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
4439 }
4440}
4441
4442PRE(sys_umask)
4443{
florianb26101c2015-08-08 21:45:33 +00004444 PRINT("sys_umask ( %ld )", SARG1);
sewardj78b50e42005-06-08 01:47:28 +00004445 PRE_REG_READ1(long, "umask", int, mask);
4446}
jsgf855d93d2003-10-13 22:26:55 +00004447
sewardja8d8e232005-06-07 20:04:56 +00004448PRE(sys_unlink)
jsgf855d93d2003-10-13 22:26:55 +00004449{
sewardja8d8e232005-06-07 20:04:56 +00004450 *flags |= SfMayBlock;
barta0b6b2c2008-07-07 06:49:24 +00004451 PRINT("sys_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00004452 PRE_REG_READ1(long, "unlink", const char *, pathname);
njn22cfccb2004-11-27 16:10:23 +00004453 PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004454}
4455
sewardja8d8e232005-06-07 20:04:56 +00004456PRE(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00004457{
barta0b6b2c2008-07-07 06:49:24 +00004458 PRINT("sys_newuname ( %#lx )", ARG1);
nethercote1a1b9b72004-11-12 11:19:36 +00004459 PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
njn22cfccb2004-11-27 16:10:23 +00004460 PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00004461}
4462
nethercote85a456f2004-11-16 17:31:56 +00004463POST(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00004464{
njn22cfccb2004-11-27 16:10:23 +00004465 if (ARG1 != 0) {
4466 POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00004467 }
4468}
4469
sewardja8d8e232005-06-07 20:04:56 +00004470PRE(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00004471{
sewardja8d8e232005-06-07 20:04:56 +00004472 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004473 PRINT("sys_waitpid ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
nethercotec6851dd2004-11-11 18:00:47 +00004474 PRE_REG_READ3(long, "waitpid",
4475 vki_pid_t, pid, unsigned int *, status, int, options);
jsgf855d93d2003-10-13 22:26:55 +00004476
njn22cfccb2004-11-27 16:10:23 +00004477 if (ARG2 != (Addr)NULL)
4478 PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00004479}
4480
nethercote85a456f2004-11-16 17:31:56 +00004481POST(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00004482{
njn22cfccb2004-11-27 16:10:23 +00004483 if (ARG2 != (Addr)NULL)
4484 POST_MEM_WRITE( ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00004485}
4486
sewardja8d8e232005-06-07 20:04:56 +00004487PRE(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00004488{
sewardja8d8e232005-06-07 20:04:56 +00004489 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004490 PRINT("sys_wait4 ( %ld, %#lx, %ld, %#lx )", SARG1, ARG2, SARG3, ARG4);
jsgf855d93d2003-10-13 22:26:55 +00004491
nethercote7f7e4d12004-11-15 12:28:58 +00004492 PRE_REG_READ4(long, "wait4",
4493 vki_pid_t, pid, unsigned int *, status, int, options,
4494 struct rusage *, rusage);
njn22cfccb2004-11-27 16:10:23 +00004495 if (ARG2 != (Addr)NULL)
4496 PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
4497 if (ARG4 != (Addr)NULL)
4498 PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00004499}
4500
nethercote85a456f2004-11-16 17:31:56 +00004501POST(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00004502{
njn22cfccb2004-11-27 16:10:23 +00004503 if (ARG2 != (Addr)NULL)
4504 POST_MEM_WRITE( ARG2, sizeof(int) );
4505 if (ARG4 != (Addr)NULL)
4506 POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00004507}
4508
sewardja8d8e232005-06-07 20:04:56 +00004509PRE(sys_writev)
jsgf855d93d2003-10-13 22:26:55 +00004510{
jsgf855d93d2003-10-13 22:26:55 +00004511 Int i;
nethercote73b526f2004-10-31 18:48:21 +00004512 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00004513 *flags |= SfMayBlock;
florianb26101c2015-08-08 21:45:33 +00004514 PRINT("sys_writev ( %lu, %#lx, %lu )", ARG1, ARG2, ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00004515 PRE_REG_READ3(ssize_t, "writev",
4516 unsigned long, fd, const struct iovec *, vector,
4517 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00004518 if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00004519 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004520 } else {
florian7cbe0682015-04-25 18:14:17 +00004521 if ((Int)ARG3 >= 0)
4522 PRE_MEM_READ( "writev(vector)",
4523 ARG2, ARG3 * sizeof(struct vki_iovec) );
njn22cfccb2004-11-27 16:10:23 +00004524 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00004525 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00004526 vec = (struct vki_iovec *)ARG2;
4527 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00004528 PRE_MEM_READ( "writev(vector[...])",
4529 (Addr)vec[i].iov_base, vec[i].iov_len );
4530 }
jsgf855d93d2003-10-13 22:26:55 +00004531 }
4532}
4533
sewardje6d5e722005-06-10 10:27:55 +00004534PRE(sys_utimes)
4535{
sewardjcc3de2d2011-08-18 15:08:20 +00004536 FUSE_COMPATIBLE_MAY_BLOCK();
barta0b6b2c2008-07-07 06:49:24 +00004537 PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
sewardje6d5e722005-06-10 10:27:55 +00004538 PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
4539 PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
njn72bbd8d2009-05-22 08:12:46 +00004540 if (ARG2 != 0) {
4541 PRE_timeval_READ( "utimes(tvp[0])", ARG2 );
4542 PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
4543 }
sewardje6d5e722005-06-10 10:27:55 +00004544}
4545
sewardj696c5512005-06-08 23:38:32 +00004546PRE(sys_acct)
4547{
barta0b6b2c2008-07-07 06:49:24 +00004548 PRINT("sys_acct ( %#lx(%s) )", ARG1,(char*)ARG1);
sewardj696c5512005-06-08 23:38:32 +00004549 PRE_REG_READ1(long, "acct", const char *, filename);
4550 PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
4551}
muellerd3502b62003-11-19 00:43:57 +00004552
sewardja8d8e232005-06-07 20:04:56 +00004553PRE(sys_pause)
thughes2f8d5f82004-09-11 14:29:19 +00004554{
sewardja8d8e232005-06-07 20:04:56 +00004555 *flags |= SfMayBlock;
nethercote0df495a2004-11-11 16:38:21 +00004556 PRINT("sys_pause ( )");
4557 PRE_REG_READ0(long, "pause");
jsgf855d93d2003-10-13 22:26:55 +00004558}
4559
sewardja8d8e232005-06-07 20:04:56 +00004560PRE(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00004561{
barta0b6b2c2008-07-07 06:49:24 +00004562 PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2);
nethercoteb77dee62004-11-16 17:13:24 +00004563 PRE_REG_READ2(int, "sigaltstack",
4564 const vki_stack_t *, ss, vki_stack_t *, oss);
njn22cfccb2004-11-27 16:10:23 +00004565 if (ARG1 != 0) {
tom92098db2005-07-18 23:18:10 +00004566 const vki_stack_t *ss = (vki_stack_t *)ARG1;
4567 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
4568 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
4569 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
jsgf855d93d2003-10-13 22:26:55 +00004570 }
njn22cfccb2004-11-27 16:10:23 +00004571 if (ARG2 != 0) {
4572 PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
jsgf855d93d2003-10-13 22:26:55 +00004573 }
4574
sewardj8eb8bab2015-07-21 14:44:28 +00004575 /* Be safe. */
4576 if (ARG1 && !ML_(safe_to_deref((void*)ARG1, sizeof(vki_stack_t)))) {
4577 SET_STATUS_Failure(VKI_EFAULT);
4578 return;
4579 }
4580 if (ARG2 && !ML_(safe_to_deref((void*)ARG2, sizeof(vki_stack_t)))) {
4581 SET_STATUS_Failure(VKI_EFAULT);
4582 return;
4583 }
4584
sewardja8d8e232005-06-07 20:04:56 +00004585 SET_STATUS_from_SysRes(
4586 VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
4587 (vki_stack_t*)ARG2)
4588 );
jsgf855d93d2003-10-13 22:26:55 +00004589}
nethercote85a456f2004-11-16 17:31:56 +00004590POST(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00004591{
sewardja8d8e232005-06-07 20:04:56 +00004592 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004593 if (RES == 0 && ARG2 != 0)
4594 POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
jsgf855d93d2003-10-13 22:26:55 +00004595}
4596
tomf93bbd92013-07-17 12:43:30 +00004597PRE(sys_sethostname)
4598{
florianb26101c2015-08-08 21:45:33 +00004599 PRINT("sys_sethostname ( %#lx, %ld )", ARG1, SARG2);
tomf93bbd92013-07-17 12:43:30 +00004600 PRE_REG_READ2(long, "sethostname", char *, name, int, len);
4601 PRE_MEM_READ( "sethostname(name)", ARG1, ARG2 );
4602}
4603
sewardje6d5e722005-06-10 10:27:55 +00004604#undef PRE
4605#undef POST
sewardj2e93c502002-04-12 11:12:52 +00004606
sewardj8eb8bab2015-07-21 14:44:28 +00004607#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
njn8b68b642009-06-24 00:37:09 +00004608
sewardjde4a1d02002-03-22 01:27:54 +00004609/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00004610/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004611/*--------------------------------------------------------------------*/