blob: af08fb29fdf8fc39de46b8c34aff4ae3fd9ce4ab [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00003/*--- Wrappers for generic Unix system calls syswrap-generic.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_debuginfo.h" // VG_(di_notify_*)
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_transtab.h" // VG_(discard_translations)
36#include "pub_core_clientstate.h" // VG_(brk_base), VG_(brk_limit)
njn899ce732005-06-21 00:28:11 +000037#include "pub_core_debuglog.h"
njn0087c502005-07-01 04:15:36 +000038#include "pub_core_errormgr.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
sewardja8d8e232005-06-07 20:04:56 +000040#include "pub_core_libcassert.h"
njnde62cbf2005-06-10 22:08:14 +000041#include "pub_core_libcfile.h"
42#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000043#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000044#include "pub_core_libcsignal.h"
njnaf1d7df2005-06-11 01:31:52 +000045#include "pub_core_mallocfree.h"
sewardja8d8e232005-06-07 20:04:56 +000046#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000047#include "pub_core_scheduler.h"
sewardja8d8e232005-06-07 20:04:56 +000048#include "pub_core_signals.h"
njn419bbcb2005-06-21 03:52:49 +000049#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
njn9abd6082005-06-17 21:31:45 +000050#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000051#include "pub_core_syswrap.h"
njn419bbcb2005-06-21 03:52:49 +000052#include "pub_core_tooliface.h"
njn73750612005-10-14 03:11:30 +000053#include "pub_core_ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000054
sewardja8d8e232005-06-07 20:04:56 +000055#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000056#include "priv_syswrap-generic.h"
sewardjde4a1d02002-03-22 01:27:54 +000057
sewardja8d8e232005-06-07 20:04:56 +000058#include "vki_unistd.h" /* for the __NR_* constants */
sewardjde4a1d02002-03-22 01:27:54 +000059
jsgf855d93d2003-10-13 22:26:55 +000060
sewardj45f4e7c2005-09-27 19:20:21 +000061/* Returns True iff address range is something the client can
62 plausibly mess with: all of it is either already belongs to the
63 client or is free or a reservation. */
64
sewardj7eb7c582005-06-23 01:02:53 +000065Bool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
nethercote8ff888f2004-11-17 17:11:45 +000066 const Char *syscallname)
fitzhardinge1a303042003-12-22 08:48:50 +000067{
fitzhardinge1a303042003-12-22 08:48:50 +000068 Bool ret;
69
70 if (size == 0)
71 return True;
72
sewardj45f4e7c2005-09-27 19:20:21 +000073 ret = VG_(am_is_valid_for_client_or_free_or_resvn)
74 (start,size,VKI_PROT_NONE);
fitzhardinge1a303042003-12-22 08:48:50 +000075
76 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +000077 VG_(printf)("%s: test=%p-%p ret=%d\n",
78 syscallname, start, start+size-1, (Int)ret);
fitzhardinge1a303042003-12-22 08:48:50 +000079
nethercote1543adf2004-10-25 15:43:21 +000080 if (!ret && syscallname != NULL) {
sewardja8d8e232005-06-07 20:04:56 +000081 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
82 "to modify addresses %p-%p",
sewardj45f4e7c2005-09-27 19:20:21 +000083 syscallname, start, start+size-1);
fitzhardinge1a303042003-12-22 08:48:50 +000084 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +000085 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
fitzhardinge1a303042003-12-22 08:48:50 +000086 }
87 }
88
89 return ret;
90}
91
sewardj45f4e7c2005-09-27 19:20:21 +000092
sewardj7eb7c582005-06-23 01:02:53 +000093Bool ML_(client_signal_OK)(Int sigNo)
njn419bbcb2005-06-21 03:52:49 +000094{
95 /* signal 0 is OK for kill */
njn351d0062005-06-21 22:23:59 +000096 Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
njn419bbcb2005-06-21 03:52:49 +000097
98 //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
99
100 return ret;
101}
102
sewardj45f4e7c2005-09-27 19:20:21 +0000103
104/* Handy small function to help stop wrappers from segfaulting when
105 presented with bogus client addresses. Is not used for generating
106 user-visible errors. */
107
108Bool ML_(safe_to_deref) ( void* start, SizeT size )
109{
110 return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_NONE );
111}
112
113
njn25e49d8e72002-09-23 09:36:25 +0000114/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000115 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000116 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000117
njn25e49d8e72002-09-23 09:36:25 +0000118// Nb: this isn't done as precisely as possible, but it seems that programs
119// are usually sufficiently well-behaved that the more obscure corner cases
120// aren't important. Various comments in the few functions below give more
121// details... njn 2002-Sep-17
122
123/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
124 munmap, mprotect (and mremap??) work at the page level. So addresses
125 and lengths must be adjusted for this. */
126
127/* Mash around start and length so that the area exactly covers
128 an integral number of pages. If we don't do that, memcheck's
129 idea of addressible memory diverges from that of the
130 kernel's, which causes the leak detector to crash. */
131static
sewardj45f4e7c2005-09-27 19:20:21 +0000132void page_align_addr_and_len( Addr* a, SizeT* len)
sewardjde4a1d02002-03-22 01:27:54 +0000133{
fitzhardinge98abfc72003-12-16 02:05:15 +0000134 Addr ra;
135
njn13bfd852005-06-02 03:52:53 +0000136 ra = VG_PGROUNDDN(*a);
137 *len = VG_PGROUNDUP(*a + *len) - ra;
fitzhardinge98abfc72003-12-16 02:05:15 +0000138 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000139}
140
sewardj45f4e7c2005-09-27 19:20:21 +0000141/* When a client mmap has been successfully done, this function must
142 be called. It notifies both aspacem and the tool of the new
143 mapping.
144*/
145void
146ML_(notify_aspacem_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
sewardj274461d2005-10-02 17:01:41 +0000147 UInt flags, Int fd, Off64T offset )
sewardjde4a1d02002-03-22 01:27:54 +0000148{
sewardj45f4e7c2005-09-27 19:20:21 +0000149 Bool rr, ww, xx, d;
njn25e49d8e72002-09-23 09:36:25 +0000150
sewardj45f4e7c2005-09-27 19:20:21 +0000151 /* 'a' is the return value from a real kernel mmap, hence: */
152 vg_assert(VG_IS_PAGE_ALIGNED(a));
153 /* whereas len is whatever the syscall supplied. So: */
154 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000155
sewardj45f4e7c2005-09-27 19:20:21 +0000156 d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
fitzhardinge98abfc72003-12-16 02:05:15 +0000157
sewardj45f4e7c2005-09-27 19:20:21 +0000158 rr = toBool(prot & VKI_PROT_READ);
159 ww = toBool(prot & VKI_PROT_WRITE);
160 xx = toBool(prot & VKI_PROT_EXEC);
njn25e49d8e72002-09-23 09:36:25 +0000161
sewardj40f8ebe2002-10-23 21:46:13 +0000162 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
sewardj45f4e7c2005-09-27 19:20:21 +0000163
164 if (d)
165 VG_(discard_translations)( (Addr64)a, (ULong)len,
166 "ML_(notify_aspacem_and_tool_of_mmap)" );
sewardjde4a1d02002-03-22 01:27:54 +0000167}
168
sewardj45f4e7c2005-09-27 19:20:21 +0000169/* Expand (or shrink) an existing mapping, potentially moving it at
170 the same time (controlled by the MREMAP_MAYMOVE flag). Nightmare.
171*/
172static
173SysRes do_mremap( Addr old_addr, SizeT old_len,
174 Addr new_addr, SizeT new_len,
175 UWord flags, ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +0000176{
sewardj45f4e7c2005-09-27 19:20:21 +0000177# define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
njn25e49d8e72002-09-23 09:36:25 +0000178
sewardj45f4e7c2005-09-27 19:20:21 +0000179 Bool ok, d;
180 NSegment* old_seg;
181 Addr advised;
182 Bool f_fixed = toBool(flags & VKI_MREMAP_FIXED);
183 Bool f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
fitzhardinge1a303042003-12-22 08:48:50 +0000184
185 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000186 VG_(printf)("do_remap (old %p %d) (new %p %d) %s %s\n",
187 old_addr,old_len,new_addr,new_len,
188 flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
189 flags & VKI_MREMAP_FIXED ? "FIXED" : "");
fitzhardinge1a303042003-12-22 08:48:50 +0000190
sewardj45f4e7c2005-09-27 19:20:21 +0000191 if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
192 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000193
sewardj45f4e7c2005-09-27 19:20:21 +0000194 if (!VG_IS_PAGE_ALIGNED(old_addr))
195 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000196
sewardj45f4e7c2005-09-27 19:20:21 +0000197 old_len = VG_PGROUNDUP(old_len);
198 new_len = VG_PGROUNDUP(new_len);
fitzhardinge1a303042003-12-22 08:48:50 +0000199
sewardj45f4e7c2005-09-27 19:20:21 +0000200 if (new_len == 0)
201 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000202
sewardj45f4e7c2005-09-27 19:20:21 +0000203 /* kernel doesn't reject this, but we do. */
204 if (old_len == 0)
205 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000206
sewardj45f4e7c2005-09-27 19:20:21 +0000207 /* reject wraparounds */
208 if (old_addr + old_len < old_addr
209 || new_addr + new_len < new_len)
210 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000211
sewardj45f4e7c2005-09-27 19:20:21 +0000212 /* kernel rejects all fixed, no-move requests (which are
213 meaningless). */
214 if (f_fixed == True && f_maymove == False)
215 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000216
sewardj45f4e7c2005-09-27 19:20:21 +0000217 /* Stay away from non-client areas. */
218 if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
219 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000220
sewardj45f4e7c2005-09-27 19:20:21 +0000221 /* In all remaining cases, if the old range does not fall within a
222 single segment, fail. */
223 old_seg = VG_(am_find_nsegment)( old_addr );
224 if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
225 goto eINVAL;
226 if (old_seg->kind != SkAnonC && old_seg->kind != SkAnonV)
227 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000228
sewardj45f4e7c2005-09-27 19:20:21 +0000229 vg_assert(old_len > 0);
230 vg_assert(new_len > 0);
231 vg_assert(VG_IS_PAGE_ALIGNED(old_len));
232 vg_assert(VG_IS_PAGE_ALIGNED(new_len));
233 vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
fitzhardinge1a303042003-12-22 08:48:50 +0000234
sewardj45f4e7c2005-09-27 19:20:21 +0000235 /* There are 3 remaining cases:
fitzhardinge1a303042003-12-22 08:48:50 +0000236
sewardj45f4e7c2005-09-27 19:20:21 +0000237 * maymove == False
238
239 new space has to be at old address, so:
240 - shrink -> unmap end
241 - same size -> do nothing
242 - grow -> if can grow in-place, do so, else fail
243
244 * maymove == True, fixed == False
245
246 new space can be anywhere, so:
247 - shrink -> unmap end
248 - same size -> do nothing
249 - grow -> if can grow in-place, do so, else
250 move to anywhere large enough, else fail
251
252 * maymove == True, fixed == True
253
254 new space must be at new address, so:
255
256 - if new address is not page aligned, fail
257 - if new address range overlaps old one, fail
258 - if new address range cannot be allocated, fail
259 - else move to new address range with new size
260 - else fail
261 */
262
263 if (f_maymove == False) {
264 /* new space has to be at old address */
265 if (new_len < old_len)
266 goto shrink_in_place;
267 if (new_len > old_len)
268 goto grow_in_place_or_fail;
269 goto same_in_place;
270 }
271
272 if (f_maymove == True && f_fixed == False) {
273 /* new space can be anywhere */
274 if (new_len < old_len)
275 goto shrink_in_place;
276 if (new_len > old_len)
277 goto grow_in_place_or_move_anywhere_or_fail;
278 goto same_in_place;
279 }
280
281 if (f_maymove == True && f_fixed == True) {
282 /* new space can only be at the new address */
283 if (!VG_IS_PAGE_ALIGNED(new_addr))
284 goto eINVAL;
285 if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
286 /* no overlap */
fitzhardinge1a303042003-12-22 08:48:50 +0000287 } else {
sewardj45f4e7c2005-09-27 19:20:21 +0000288 goto eINVAL;
289 }
290 if (new_addr == 0)
291 goto eINVAL;
292 /* VG_(am_get_advisory_client_simple) interprets zero to mean
293 non-fixed, which is not what we want */
294 advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
295 if (!ok || advised != new_addr)
296 goto eNOMEM;
297 ok = VG_(am_relocate_nooverlap_client)
298 ( &d, old_addr, old_len, new_addr, new_len );
299 if (ok) {
300 VG_TRACK( copy_mem_remap, old_addr, new_addr,
301 MIN_SIZET(old_len,new_len) );
302 if (new_len > old_len)
303 VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
304 old_seg->hasR, old_seg->hasW, old_seg->hasX );
305 VG_TRACK(die_mem_munmap, old_addr, old_len);
306 if (d) {
307 VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
308 VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
309 }
310 return VG_(mk_SysRes_Success)( new_addr );
311 }
312 goto eNOMEM;
313 }
fitzhardinge1a303042003-12-22 08:48:50 +0000314
sewardj45f4e7c2005-09-27 19:20:21 +0000315 /* end of the 3 cases */
316 /*NOTREACHED*/ vg_assert(0);
fitzhardinge1a303042003-12-22 08:48:50 +0000317
sewardj45f4e7c2005-09-27 19:20:21 +0000318 grow_in_place_or_move_anywhere_or_fail:
319 {
320 /* try growing it in-place */
321 Addr needA = old_addr + old_len;
322 SSizeT needL = new_len - old_len;
fitzhardinge1a303042003-12-22 08:48:50 +0000323
sewardj45f4e7c2005-09-27 19:20:21 +0000324 vg_assert(needL > 0);
325 if (needA == 0)
326 goto eINVAL;
327 /* VG_(am_get_advisory_client_simple) interprets zero to mean
328 non-fixed, which is not what we want */
329 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
330 if (ok && advised == needA) {
331 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
332 if (ok) {
333 VG_TRACK( new_mem_mmap, needA, needL,
334 old_seg->hasR,
335 old_seg->hasW, old_seg->hasX );
336 if (d)
337 VG_(discard_translations)( needA, needL, "do_remap(3)" );
338 return VG_(mk_SysRes_Success)( old_addr );
fitzhardinge1a303042003-12-22 08:48:50 +0000339 }
340 }
341
sewardj45f4e7c2005-09-27 19:20:21 +0000342 /* that failed. Look elsewhere. */
343 advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
344 if (ok) {
345 /* assert new area does not overlap old */
346 vg_assert(advised+new_len-1 < old_addr
347 || advised > old_addr+old_len-1);
348 ok = VG_(am_relocate_nooverlap_client)
349 ( &d, old_addr, old_len, advised, new_len );
350 if (ok) {
351 VG_TRACK( copy_mem_remap, old_addr, advised,
352 MIN_SIZET(old_len,new_len) );
353 if (new_len > old_len)
354 VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
355 old_seg->hasR, old_seg->hasW, old_seg->hasX );
356 VG_TRACK(die_mem_munmap, old_addr, old_len);
357 if (d) {
358 VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
359 VG_(discard_translations)( advised, new_len, "do_remap(5)" );
360 }
361 return VG_(mk_SysRes_Success)( advised );
362 }
363 }
364 goto eNOMEM;
365 }
366 /*NOTREACHED*/ vg_assert(0);
367
368 grow_in_place_or_fail:
369 {
370 Addr needA = old_addr + old_len;
371 SizeT needL = new_len - old_len;
372 if (needA == 0)
373 goto eINVAL;
374 /* VG_(am_get_advisory_client_simple) interprets zero to mean
375 non-fixed, which is not what we want */
376 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
377 if (!ok || advised != needA)
378 goto eNOMEM;
379 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
380 if (!ok)
381 goto eNOMEM;
382 VG_TRACK( new_mem_mmap, needA, needL,
383 old_seg->hasR, old_seg->hasW, old_seg->hasX );
384 if (d)
385 VG_(discard_translations)( needA, needL, "do_remap(6)" );
386 return VG_(mk_SysRes_Success)( old_addr );
387 }
388 /*NOTREACHED*/ vg_assert(0);
389
390 shrink_in_place:
391 {
392 SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
393 if (sres.isError)
394 return sres;
395 VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
396 if (d)
397 VG_(discard_translations)( old_addr+new_len, old_len-new_len,
398 "do_remap(7)" );
399 return VG_(mk_SysRes_Success)( old_addr );
400 }
401 /*NOTREACHED*/ vg_assert(0);
402
403 same_in_place:
404 return VG_(mk_SysRes_Success)( old_addr );
405 /*NOTREACHED*/ vg_assert(0);
406
407 eINVAL:
408 return VG_(mk_SysRes_Error)( VKI_EINVAL );
409 eNOMEM:
410 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
411
412# undef MIN_SIZET
sewardjde4a1d02002-03-22 01:27:54 +0000413}
414
415
sewardja8d8e232005-06-07 20:04:56 +0000416/* ---------------------------------------------------------------------
417 File-descriptor tracking
418 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000419
rjwalshf5f536f2003-11-17 17:45:00 +0000420/* One of these is allocated for each open file descriptor. */
rjwalshf5f536f2003-11-17 17:45:00 +0000421typedef struct OpenFd
422{
423 Int fd; /* The file descriptor */
424 Char *pathname; /* NULL if not a regular file or unknown */
425 ExeContext *where; /* NULL if inherited from parent */
426 struct OpenFd *next, *prev;
427} OpenFd;
428
429/* List of allocated file descriptors. */
rjwalshf5f536f2003-11-17 17:45:00 +0000430static OpenFd *allocated_fds;
431
432/* Count of open file descriptors. */
sewardj0a400c72005-07-23 09:22:46 +0000433static Int fd_count = 0;
rjwalshf5f536f2003-11-17 17:45:00 +0000434
rjwalshf5f536f2003-11-17 17:45:00 +0000435
rjwalshf5f536f2003-11-17 17:45:00 +0000436/* Note the fact that a file descriptor was just closed. */
rjwalshf5f536f2003-11-17 17:45:00 +0000437static
njnc6168192004-11-29 13:54:10 +0000438void record_fd_close(ThreadId tid, Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000439{
440 OpenFd *i = allocated_fds;
441
thughesad1c9562004-06-26 11:27:52 +0000442 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000443 return; /* Valgrind internal */
444
rjwalshf5f536f2003-11-17 17:45:00 +0000445 while(i) {
446 if(i->fd == fd) {
447 if(i->prev)
448 i->prev->next = i->next;
449 else
450 allocated_fds = i->next;
451 if(i->next)
452 i->next->prev = i->prev;
453 if(i->pathname)
fitzhardingea7728472003-12-16 01:48:38 +0000454 VG_(arena_free) (VG_AR_CORE, i->pathname);
455 VG_(arena_free) (VG_AR_CORE, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000456 fd_count--;
457 break;
458 }
459 i = i->next;
460 }
461}
462
463/* Note the fact that a file descriptor was just opened. If the
464 tid is -1, this indicates an inherited fd. If the pathname is NULL,
465 this either indicates a non-standard file (i.e. a pipe or socket or
466 some such thing) or that we don't know the filename. If the fd is
467 already open, then we're probably doing a dup2() to an existing fd,
468 so just overwrite the existing one. */
njn4279a882005-08-26 03:43:28 +0000469void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname)
rjwalshf5f536f2003-11-17 17:45:00 +0000470{
471 OpenFd *i;
472
thughesad1c9562004-06-26 11:27:52 +0000473 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000474 return; /* Valgrind internal */
475
rjwalshf5f536f2003-11-17 17:45:00 +0000476 /* Check to see if this fd is already open. */
477 i = allocated_fds;
478 while (i) {
479 if (i->fd == fd) {
fitzhardingea7728472003-12-16 01:48:38 +0000480 if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000481 break;
482 }
483 i = i->next;
484 }
485
486 /* Not already one: allocate an OpenFd */
487 if (i == NULL) {
fitzhardingea7728472003-12-16 01:48:38 +0000488 i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000489
490 i->prev = NULL;
491 i->next = allocated_fds;
492 if(allocated_fds) allocated_fds->prev = i;
493 allocated_fds = i;
494 fd_count++;
495 }
496
497 i->fd = fd;
njnf845f8f2005-06-23 02:26:47 +0000498 i->pathname = VG_(arena_strdup)(VG_AR_CORE, pathname);
njnd01fef72005-03-25 23:35:48 +0000499 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid);
rjwalshf5f536f2003-11-17 17:45:00 +0000500}
501
njnf845f8f2005-06-23 02:26:47 +0000502// Record opening of an fd, and find its name.
503static void record_fd_open_named(ThreadId tid, Int fd)
504{
505 static HChar buf[VKI_PATH_MAX];
506 Char* name;
507 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
508 name = buf;
509 else
510 name = NULL;
511
njn4279a882005-08-26 03:43:28 +0000512 ML_(record_fd_open_with_given_name)(tid, fd, name);
njnf845f8f2005-06-23 02:26:47 +0000513}
514
515// Record opening of a nameless fd.
516void ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
517{
njn4279a882005-08-26 03:43:28 +0000518 ML_(record_fd_open_with_given_name)(tid, fd, NULL);
njnf845f8f2005-06-23 02:26:47 +0000519}
520
rjwalshf5f536f2003-11-17 17:45:00 +0000521static
nethercote73b526f2004-10-31 18:48:21 +0000522Char *unix2name(struct vki_sockaddr_un *sa, UInt len, Char *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000523{
nethercote73b526f2004-10-31 18:48:21 +0000524 if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
rjwalshf5f536f2003-11-17 17:45:00 +0000525 VG_(sprintf)(name, "<unknown>");
526 } else {
527 VG_(sprintf)(name, "%s", sa->sun_path);
528 }
529
530 return name;
531}
532
533static
nethercote73b526f2004-10-31 18:48:21 +0000534Char *inet2name(struct vki_sockaddr_in *sa, UInt len, Char *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000535{
nethercote73b526f2004-10-31 18:48:21 +0000536 if (sa == NULL || len == 0) {
rjwalshf5f536f2003-11-17 17:45:00 +0000537 VG_(sprintf)(name, "<unknown>");
538 } else {
539 UInt addr = sa->sin_addr.s_addr;
540
541 if (addr == 0) {
542 VG_(sprintf)(name, "<unbound>");
543 } else {
544 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
545 addr & 0xFF, (addr>>8) & 0xFF,
546 (addr>>16) & 0xFF, (addr>>24) & 0xFF,
nethercote73b526f2004-10-31 18:48:21 +0000547 vki_ntohs(sa->sin_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000548 }
549 }
550
551 return name;
552}
553
rjwalshf5f536f2003-11-17 17:45:00 +0000554/*
555 * Try get some details about a socket.
556 */
rjwalshf5f536f2003-11-17 17:45:00 +0000557static void
sewardj0a400c72005-07-23 09:22:46 +0000558getsockdetails(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000559{
560 union u {
nethercote73b526f2004-10-31 18:48:21 +0000561 struct vki_sockaddr a;
562 struct vki_sockaddr_in in;
563 struct vki_sockaddr_un un;
rjwalshf5f536f2003-11-17 17:45:00 +0000564 } laddr;
nethercote73b526f2004-10-31 18:48:21 +0000565 UInt llen;
rjwalshf5f536f2003-11-17 17:45:00 +0000566
567 llen = sizeof(laddr);
568 VG_(memset)(&laddr, 0, llen);
569
570 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
571 switch(laddr.a.sa_family) {
nethercote73b526f2004-10-31 18:48:21 +0000572 case VKI_AF_INET: {
rjwalshf5f536f2003-11-17 17:45:00 +0000573 static char lname[32];
574 static char pname[32];
nethercote73b526f2004-10-31 18:48:21 +0000575 struct vki_sockaddr_in paddr;
576 UInt plen = sizeof(struct vki_sockaddr_in);
rjwalshf5f536f2003-11-17 17:45:00 +0000577
578 if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
579 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
580 inet2name(&(laddr.in), llen, lname),
581 inet2name(&paddr, plen, pname));
582 } else {
583 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
584 fd, inet2name(&(laddr.in), llen, lname));
585 }
586 return;
587 }
nethercote73b526f2004-10-31 18:48:21 +0000588 case VKI_AF_UNIX: {
rjwalshf5f536f2003-11-17 17:45:00 +0000589 static char lname[256];
590 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
591 unix2name(&(laddr.un), llen, lname));
592 return;
593 }
594 default:
595 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
596 laddr.a.sa_family, fd);
597 return;
598 }
599 }
600
601 VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
602}
603
604
nethercote3a42fb82004-08-03 18:08:50 +0000605/* Dump out a summary, and a more detailed list, of open file descriptors. */
606void VG_(show_open_fds) ()
rjwalshf5f536f2003-11-17 17:45:00 +0000607{
608 OpenFd *i = allocated_fds;
609
nethercote3a42fb82004-08-03 18:08:50 +0000610 VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open at exit.", fd_count);
rjwalshf5f536f2003-11-17 17:45:00 +0000611
612 while(i) {
613 if(i->pathname) {
614 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
615 i->pathname);
616 } else {
sewardj0a400c72005-07-23 09:22:46 +0000617 Int val;
nethercote73b526f2004-10-31 18:48:21 +0000618 UInt len = sizeof(val);
rjwalshf5f536f2003-11-17 17:45:00 +0000619
nethercote73b526f2004-10-31 18:48:21 +0000620 if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000621 VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
622 } else {
623 getsockdetails(i->fd);
624 }
625 }
626
627 if(i->where) {
628 VG_(pp_ExeContext)(i->where);
629 VG_(message)(Vg_UserMsg, "");
630 } else {
631 VG_(message)(Vg_UserMsg, " <inherited from parent>");
632 VG_(message)(Vg_UserMsg, "");
633 }
634
635 i = i->next;
636 }
637
638 VG_(message)(Vg_UserMsg, "");
639}
640
641/* If /proc/self/fd doesn't exist for some weird reason (like you've
642 got a kernel that doesn't have /proc support compiled in), then we
643 need to find out what file descriptors we inherited from our parent
644 process the hard way - by checking each fd in turn. */
645
646static
tom7c787822005-11-11 12:32:10 +0000647void do_hacky_preopened(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000648{
649 struct vki_rlimit lim;
sewardj0a400c72005-07-23 09:22:46 +0000650 UInt count;
651 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000652
nethercote620154f2004-11-12 21:21:07 +0000653 if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000654 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
655 an arbitrarily high number. 1024 happens to be the limit in
656 the 2.4 kernels. */
657 count = 1024;
658 } else {
659 count = lim.rlim_cur;
660 }
661
662 for (i = 0; i < count; i++)
663 if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
njnf845f8f2005-06-23 02:26:47 +0000664 ML_(record_fd_open_nameless)(-1, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000665}
666
667/* Initialize the list of open file descriptors with the file descriptors
668 we inherited from out parent process. */
669
670void VG_(init_preopened_fds)()
671{
sewardj0a400c72005-07-23 09:22:46 +0000672 Int ret;
rjwalshf5f536f2003-11-17 17:45:00 +0000673 struct vki_dirent d;
sewardj92645592005-07-23 09:18:34 +0000674 SysRes f;
rjwalshf5f536f2003-11-17 17:45:00 +0000675
676 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
sewardj92645592005-07-23 09:18:34 +0000677 if (f.isError) {
rjwalshf5f536f2003-11-17 17:45:00 +0000678 do_hacky_preopened();
679 return;
680 }
681
sewardj92645592005-07-23 09:18:34 +0000682 while ((ret = VG_(getdents)(f.val, &d, sizeof(d))) != 0) {
njnf845f8f2005-06-23 02:26:47 +0000683 if (ret == -1)
rjwalshf5f536f2003-11-17 17:45:00 +0000684 goto out;
685
njnf845f8f2005-06-23 02:26:47 +0000686 if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
sewardj0a400c72005-07-23 09:22:46 +0000687 Int fno = VG_(atoll)(d.d_name);
rjwalshf5f536f2003-11-17 17:45:00 +0000688
sewardj92645592005-07-23 09:18:34 +0000689 if (fno != f.val)
njnf845f8f2005-06-23 02:26:47 +0000690 if (VG_(clo_track_fds))
691 record_fd_open_named(-1, fno);
rjwalshf5f536f2003-11-17 17:45:00 +0000692 }
693
sewardj92645592005-07-23 09:18:34 +0000694 VG_(lseek)(f.val, d.d_off, VKI_SEEK_SET);
rjwalshf5f536f2003-11-17 17:45:00 +0000695 }
696
sewardj92645592005-07-23 09:18:34 +0000697 out:
698 VG_(close)(f.val);
rjwalshf5f536f2003-11-17 17:45:00 +0000699}
700
sewardjde4a1d02002-03-22 01:27:54 +0000701static
sewardj8c824512002-04-14 04:16:48 +0000702Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000703{
704 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
njn25e49d8e72002-09-23 09:36:25 +0000705 Char *result = VG_(arena_malloc) ( aid, len );
sewardjde4a1d02002-03-22 01:27:54 +0000706 VG_(strcpy) ( result, s1 );
707 VG_(strcat) ( result, s2 );
708 return result;
709}
710
711static
tom56e1c842005-07-18 22:41:33 +0000712void pre_mem_read_sendmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000713 Char *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000714{
njn9f46df62005-03-13 18:11:44 +0000715 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_CORE );
nethercoteef0c7662004-11-06 15:38:43 +0000716 PRE_MEM_READ( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000717 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000718}
719
720static
tom56e1c842005-07-18 22:41:33 +0000721void pre_mem_write_recvmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000722 Char *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000723{
njn9f46df62005-03-13 18:11:44 +0000724 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_CORE );
tom56e1c842005-07-18 22:41:33 +0000725 if ( read )
726 PRE_MEM_READ( outmsg, base, size );
727 else
728 PRE_MEM_WRITE( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000729 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000730}
731
732static
tom56e1c842005-07-18 22:41:33 +0000733void post_mem_write_recvmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000734 Char *fieldName, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000735{
tom56e1c842005-07-18 22:41:33 +0000736 if ( !read )
737 POST_MEM_WRITE( base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000738}
739
740static
sewardj8c824512002-04-14 04:16:48 +0000741void msghdr_foreachfield (
njn72718642003-07-24 08:45:32 +0000742 ThreadId tid,
nethercote73b526f2004-10-31 18:48:21 +0000743 struct vki_msghdr *msg,
tom56e1c842005-07-18 22:41:33 +0000744 void (*foreach_func)( ThreadId, Bool, Char *, Addr, SizeT )
sewardj8c824512002-04-14 04:16:48 +0000745 )
sewardjde4a1d02002-03-22 01:27:54 +0000746{
747 if ( !msg )
748 return;
749
tom56e1c842005-07-18 22:41:33 +0000750 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
751 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
752 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
753 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
754 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
755 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
756 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
sewardjde4a1d02002-03-22 01:27:54 +0000757
758 if ( msg->msg_name )
tom56e1c842005-07-18 22:41:33 +0000759 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000760 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000761 (Addr)msg->msg_name, msg->msg_namelen );
762
763 if ( msg->msg_iov ) {
nethercote73b526f2004-10-31 18:48:21 +0000764 struct vki_iovec *iov = msg->msg_iov;
sewardjde4a1d02002-03-22 01:27:54 +0000765 UInt i;
766
tom56e1c842005-07-18 22:41:33 +0000767 foreach_func ( tid, True,
sewardj8c824512002-04-14 04:16:48 +0000768 "(msg.msg_iov)",
nethercote73b526f2004-10-31 18:48:21 +0000769 (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
sewardjde4a1d02002-03-22 01:27:54 +0000770
771 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
tom56e1c842005-07-18 22:41:33 +0000772 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000773 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000774 (Addr)iov->iov_base, iov->iov_len );
775 }
776
777 if ( msg->msg_control )
tom56e1c842005-07-18 22:41:33 +0000778 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000779 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000780 (Addr)msg->msg_control, msg->msg_controllen );
781}
782
sewardjb5f6f512005-03-10 23:59:00 +0000783static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
rjwalshf5f536f2003-11-17 17:45:00 +0000784{
nethercote73b526f2004-10-31 18:48:21 +0000785 struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
rjwalshf5f536f2003-11-17 17:45:00 +0000786
787 while (cm) {
nethercote73b526f2004-10-31 18:48:21 +0000788 if (cm->cmsg_level == VKI_SOL_SOCKET &&
789 cm->cmsg_type == VKI_SCM_RIGHTS ) {
sewardj0a400c72005-07-23 09:22:46 +0000790 Int *fds = (Int *) VKI_CMSG_DATA(cm);
791 Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
rjwalshf5f536f2003-11-17 17:45:00 +0000792 / sizeof(int);
sewardj0a400c72005-07-23 09:22:46 +0000793 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000794
795 for (i = 0; i < fdc; i++)
796 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +0000797 // XXX: must we check the range on these fds with
cerion7b2c38c2005-06-23 07:52:54 +0000798 // ML_(fd_allowed)()?
njnf845f8f2005-06-23 02:26:47 +0000799 record_fd_open_named(tid, fds[i]);
rjwalshf5f536f2003-11-17 17:45:00 +0000800 }
801
nethercote73b526f2004-10-31 18:48:21 +0000802 cm = VKI_CMSG_NXTHDR(msg, cm);
rjwalshf5f536f2003-11-17 17:45:00 +0000803 }
804}
805
sewardjc483e8f2002-05-03 21:01:35 +0000806static
jsgf855d93d2003-10-13 22:26:55 +0000807void pre_mem_read_sockaddr ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +0000808 Char *description,
809 struct vki_sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +0000810{
sewardjff7c1ab2003-02-24 21:55:34 +0000811 Char *outmsg;
812
813 /* NULL/zero-length sockaddrs are legal */
814 if ( sa == NULL || salen == 0 ) return;
815
njn9f46df62005-03-13 18:11:44 +0000816 outmsg = VG_(arena_malloc) ( VG_AR_CORE,
nethercote73b526f2004-10-31 18:48:21 +0000817 VG_(strlen)( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +0000818
819 VG_(sprintf) ( outmsg, description, ".sa_family" );
nethercoteef0c7662004-11-06 15:38:43 +0000820 PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +0000821
sewardjc483e8f2002-05-03 21:01:35 +0000822 switch (sa->sa_family) {
823
nethercote73b526f2004-10-31 18:48:21 +0000824 case VKI_AF_UNIX:
sewardjc483e8f2002-05-03 21:01:35 +0000825 VG_(sprintf) ( outmsg, description, ".sun_path" );
nethercoteef0c7662004-11-06 15:38:43 +0000826 PRE_MEM_RASCIIZ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000827 (Addr) ((struct vki_sockaddr_un *) sa)->sun_path);
sewardjc483e8f2002-05-03 21:01:35 +0000828 break;
829
nethercote73b526f2004-10-31 18:48:21 +0000830 case VKI_AF_INET:
sewardjc483e8f2002-05-03 21:01:35 +0000831 VG_(sprintf) ( outmsg, description, ".sin_port" );
nethercoteef0c7662004-11-06 15:38:43 +0000832 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000833 (Addr) &((struct vki_sockaddr_in *) sa)->sin_port,
834 sizeof (((struct vki_sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000835 VG_(sprintf) ( outmsg, description, ".sin_addr" );
nethercoteef0c7662004-11-06 15:38:43 +0000836 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000837 (Addr) &((struct vki_sockaddr_in *) sa)->sin_addr,
838 sizeof (struct vki_in_addr));
sewardjc483e8f2002-05-03 21:01:35 +0000839 break;
840
nethercote73b526f2004-10-31 18:48:21 +0000841 case VKI_AF_INET6:
sewardjc483e8f2002-05-03 21:01:35 +0000842 VG_(sprintf) ( outmsg, description, ".sin6_port" );
nethercoteef0c7662004-11-06 15:38:43 +0000843 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000844 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_port,
845 sizeof (((struct vki_sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000846 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
nethercoteef0c7662004-11-06 15:38:43 +0000847 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000848 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_flowinfo,
849 sizeof (__vki_u32));
sewardjc483e8f2002-05-03 21:01:35 +0000850 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
nethercoteef0c7662004-11-06 15:38:43 +0000851 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000852 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_addr,
853 sizeof (struct vki_in6_addr));
sewardjc483e8f2002-05-03 21:01:35 +0000854 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
nethercoteef0c7662004-11-06 15:38:43 +0000855 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000856 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_scope_id,
857 sizeof (__vki_u32));
sewardjc483e8f2002-05-03 21:01:35 +0000858 break;
859
860 default:
861 VG_(sprintf) ( outmsg, description, "" );
nethercoteef0c7662004-11-06 15:38:43 +0000862 PRE_MEM_READ( outmsg, (Addr) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +0000863 break;
864 }
865
njn9f46df62005-03-13 18:11:44 +0000866 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +0000867}
868
njn25e49d8e72002-09-23 09:36:25 +0000869/* Dereference a pointer to a UInt. */
njn72718642003-07-24 08:45:32 +0000870static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000871{
872 UInt* a_p = (UInt*)a;
nethercoteef0c7662004-11-06 15:38:43 +0000873 PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +0000874 if (a_p == NULL)
875 return 0;
876 else
877 return *a_p;
878}
879
njn25e49d8e72002-09-23 09:36:25 +0000880static
njn72718642003-07-24 08:45:32 +0000881void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
njn25e49d8e72002-09-23 09:36:25 +0000882 Char* buf_s, Char* buflen_s )
883{
njn51d827b2005-05-09 01:02:08 +0000884 if (VG_(tdict).track_pre_mem_write) {
njn72718642003-07-24 08:45:32 +0000885 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +0000886 if (buflen_in > 0) {
njn51d827b2005-05-09 01:02:08 +0000887 VG_(tdict).track_pre_mem_write( Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +0000888 }
889 }
890}
891
892static
sewardja8d8e232005-06-07 20:04:56 +0000893void buf_and_len_post_check( ThreadId tid, SysRes res,
njn25e49d8e72002-09-23 09:36:25 +0000894 Addr buf_p, Addr buflen_p, Char* s )
895{
sewardja8d8e232005-06-07 20:04:56 +0000896 if (!res.isError && VG_(tdict).track_post_mem_write) {
njn72718642003-07-24 08:45:32 +0000897 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +0000898 if (buflen_out > 0 && buf_p != (Addr)NULL) {
njn51d827b2005-05-09 01:02:08 +0000899 VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +0000900 }
901 }
902}
903
904/* ---------------------------------------------------------------------
905 Data seg end, for brk()
906 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000907
sewardj45f4e7c2005-09-27 19:20:21 +0000908/* +--------+------------+
909 | anon | resvn |
910 +--------+------------+
nethercotece471262004-08-25 13:43:44 +0000911
sewardj45f4e7c2005-09-27 19:20:21 +0000912 ^ ^ ^
913 | | boundary is page aligned
914 | VG_(brk_limit) -- no alignment constraint
915 VG_(brk_base) -- page aligned -- does not move
916
917 Both the anon part and the reservation part are always at least
918 one page.
919*/
920
921/* Set the new data segment end to NEWBRK. If this succeeds, return
922 NEWBRK, else return the current data segment end. */
923
924static Addr do_brk ( Addr newbrk )
925{
926 NSegment *aseg, *rseg;
927 Addr newbrkP;
928 SizeT delta;
929 Bool ok;
930 Bool debug = False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000931
932 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000933 VG_(printf)("\ndo_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
fitzhardinge98abfc72003-12-16 02:05:15 +0000934 VG_(brk_base), VG_(brk_limit), newbrk);
935
sewardj79048ce2005-02-18 08:28:32 +0000936# if 0
sewardje517b802005-02-16 01:58:51 +0000937 if (0) show_segments("in_brk");
sewardj79048ce2005-02-18 08:28:32 +0000938# endif
sewardj548be6d2005-02-16 01:31:37 +0000939
sewardj45f4e7c2005-09-27 19:20:21 +0000940 if (newbrk < VG_(brk_base))
941 /* Clearly impossible. */
942 goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +0000943
sewardj45f4e7c2005-09-27 19:20:21 +0000944 if (newbrk >= VG_(brk_base) && newbrk < VG_(brk_limit)) {
945 /* shrinking the data segment. Be lazy and don't munmap the
946 excess area. */
947 NSegment* seg = VG_(am_find_nsegment)(newbrk);
948 if (seg && seg->hasT)
949 VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
950 "do_brk(shrink)" );
951 VG_(brk_limit) = newbrk;
952 return newbrk;
953 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000954
sewardj45f4e7c2005-09-27 19:20:21 +0000955 /* otherwise we're expanding the brk segment. */
tom8e5963d2005-10-06 14:49:21 +0000956 if (VG_(brk_limit) > VG_(brk_base))
957 aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
958 else
959 aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
sewardj45f4e7c2005-09-27 19:20:21 +0000960 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
fitzhardinge98abfc72003-12-16 02:05:15 +0000961
sewardj45f4e7c2005-09-27 19:20:21 +0000962 /* These should be assured by setup_client_dataseg in m_main. */
963 vg_assert(aseg);
964 vg_assert(rseg);
965 vg_assert(aseg->kind == SkAnonC);
966 vg_assert(rseg->kind == SkResvn);
967 vg_assert(aseg->end+1 == rseg->start);
fitzhardinge98abfc72003-12-16 02:05:15 +0000968
sewardj45f4e7c2005-09-27 19:20:21 +0000969 vg_assert(newbrk >= VG_(brk_base));
970 if (newbrk <= rseg->start) {
971 /* still fits within the anon segment. */
972 VG_(brk_limit) = newbrk;
973 return newbrk;
974 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000975
sewardj45f4e7c2005-09-27 19:20:21 +0000976 if (newbrk >= rseg->end+1 - VKI_PAGE_SIZE) {
977 /* request is too large -- the resvn would fall below 1 page,
978 which isn't allowed. */
979 goto bad;
980 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000981
sewardj45f4e7c2005-09-27 19:20:21 +0000982 newbrkP = VG_PGROUNDUP(newbrk);
983 vg_assert(newbrkP > rseg->start && newbrkP < rseg->end+1 - VKI_PAGE_SIZE);
984 delta = newbrkP - rseg->start;
985 vg_assert(delta > 0);
986 vg_assert(VG_IS_PAGE_ALIGNED(delta));
987
988 ok = VG_(am_extend_into_adjacent_reservation_client)( aseg, delta );
989 if (!ok) goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +0000990
sewardj45f4e7c2005-09-27 19:20:21 +0000991 VG_(brk_limit) = newbrk;
992 return newbrk;
fitzhardinge98abfc72003-12-16 02:05:15 +0000993
sewardj45f4e7c2005-09-27 19:20:21 +0000994 bad:
995 return VG_(brk_limit);
fitzhardinge98abfc72003-12-16 02:05:15 +0000996}
997
998
njn25e49d8e72002-09-23 09:36:25 +0000999/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00001000 Vet file descriptors for sanity
1001 ------------------------------------------------------------------ */
sewardj04236902005-10-04 22:27:22 +00001002/*
1003> - what does the "Bool soft" parameter mean?
1004
1005(Tom Hughes, 3 Oct 05):
1006
1007Whether or not to consider a file descriptor invalid if it is above
1008the current soft limit.
1009
1010Basically if we are testing whether a newly created file descriptor is
1011valid (in a post handler) then we set soft to true, and if we are
1012testing whether a file descriptor that is about to be used (in a pre
1013handler) is valid [viz, an already-existing fd] then we set it to false.
1014
1015The point is that if the (virtual) soft limit is lowered then any
1016existing descriptors can still be read/written/closed etc (so long as
1017they are below the valgrind reserved descriptors) but no new
1018descriptors can be created above the new soft limit.
1019
1020(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
1021*/
jsgf855d93d2003-10-13 22:26:55 +00001022
1023/* Return true if we're allowed to use or create this fd */
sewardj04236902005-10-04 22:27:22 +00001024Bool ML_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool isNewFd)
jsgf855d93d2003-10-13 22:26:55 +00001025{
sewardj04236902005-10-04 22:27:22 +00001026 Bool allowed = True;
1027
1028 /* hard limits always apply */
1029 if (fd < 0 || fd >= VG_(fd_hard_limit))
1030 allowed = False;
1031
1032 /* hijacking the logging fd is never allowed */
1033 if (fd == VG_(clo_log_fd))
1034 allowed = False;
1035
1036 /* if creating a new fd (rather than using an existing one), the
1037 soft limit must also be observed */
1038 if (isNewFd && fd >= VG_(fd_soft_limit))
1039 allowed = False;
1040
1041 /* this looks like it ought to be included, but causes problems: */
1042 /*
1043 if (fd == 2 && VG_(debugLog_getLevel)() > 0)
1044 allowed = False;
1045 */
1046 /* The difficulty is as follows: consider a program P which expects
1047 to be able to mess with (redirect) its own stderr (fd 2).
1048 Usually to deal with P we would issue command line flags to send
1049 logging somewhere other than stderr, so as not to disrupt P.
1050 The problem is that -d unilaterally hijacks stderr with no
1051 consultation with P. And so, if this check is enabled, P will
1052 work OK normally but fail if -d is issued.
1053
1054 Basically -d is a hack and you take your chances when using it.
1055 It's very useful for low level debugging -- particularly at
1056 startup -- and having its presence change the behaviour of the
1057 client is exactly what we don't want. */
1058
1059 /* croak? */
1060 if ((!allowed) && VG_(showing_core_errors)() ) {
jsewardd9320a42003-12-12 06:40:05 +00001061 VG_(message)(Vg_UserMsg,
1062 "Warning: invalid file descriptor %d in syscall %s()",
nethercote1543adf2004-10-25 15:43:21 +00001063 fd, syscallname);
nethercotef8548672004-06-21 12:42:35 +00001064 if (fd == VG_(clo_log_fd))
jsewardd9320a42003-12-12 06:40:05 +00001065 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001066 " Use --log-fd=<number> to select an alternative log fd.");
jsgf855d93d2003-10-13 22:26:55 +00001067 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +00001068 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
jsgf855d93d2003-10-13 22:26:55 +00001069 }
jsgf855d93d2003-10-13 22:26:55 +00001070 }
sewardj04236902005-10-04 22:27:22 +00001071
1072 return allowed;
jsgf855d93d2003-10-13 22:26:55 +00001073}
1074
1075
1076/* ---------------------------------------------------------------------
sewardj9efbbef2005-03-01 16:45:23 +00001077 Deal with a bunch of socket-related syscalls
1078 ------------------------------------------------------------------ */
1079
1080/* ------ */
1081
sewardj987a8eb2005-03-01 19:00:30 +00001082void
sewardj7eb7c582005-06-23 01:02:53 +00001083ML_(generic_PRE_sys_socketpair) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001084 UWord arg0, UWord arg1,
1085 UWord arg2, UWord arg3 )
1086{
1087 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1088 PRE_MEM_WRITE( "socketcall.socketpair(sv)",
1089 arg3, 2*sizeof(int) );
1090}
1091
sewardja8d8e232005-06-07 20:04:56 +00001092SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001093ML_(generic_POST_sys_socketpair) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001094 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001095 UWord arg0, UWord arg1,
1096 UWord arg2, UWord arg3 )
sewardj9efbbef2005-03-01 16:45:23 +00001097{
sewardja8d8e232005-06-07 20:04:56 +00001098 SysRes r = res;
sewardj9efbbef2005-03-01 16:45:23 +00001099 Int fd1 = ((Int*)arg3)[0];
1100 Int fd2 = ((Int*)arg3)[1];
tom60a4b0b2005-10-12 10:45:27 +00001101 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001102 POST_MEM_WRITE( arg3, 2*sizeof(int) );
sewardj7eb7c582005-06-23 01:02:53 +00001103 if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
1104 !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
sewardj9efbbef2005-03-01 16:45:23 +00001105 VG_(close)(fd1);
1106 VG_(close)(fd2);
sewardja8d8e232005-06-07 20:04:56 +00001107 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001108 } else {
1109 POST_MEM_WRITE( arg3, 2*sizeof(int) );
1110 if (VG_(clo_track_fds)) {
njnf845f8f2005-06-23 02:26:47 +00001111 ML_(record_fd_open_nameless)(tid, fd1);
1112 ML_(record_fd_open_nameless)(tid, fd2);
sewardj9efbbef2005-03-01 16:45:23 +00001113 }
1114 }
1115 return r;
1116}
1117
1118/* ------ */
1119
sewardja8d8e232005-06-07 20:04:56 +00001120SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001121ML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
sewardj9efbbef2005-03-01 16:45:23 +00001122{
sewardja8d8e232005-06-07 20:04:56 +00001123 SysRes r = res;
1124 vg_assert(!res.isError); /* guaranteed by caller */
sewardj7eb7c582005-06-23 01:02:53 +00001125 if (!ML_(fd_allowed)(res.val, "socket", tid, True)) {
sewardja8d8e232005-06-07 20:04:56 +00001126 VG_(close)(res.val);
1127 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001128 } else {
1129 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00001130 ML_(record_fd_open_nameless)(tid, res.val);
sewardj9efbbef2005-03-01 16:45:23 +00001131 }
1132 return r;
1133}
1134
1135/* ------ */
1136
sewardj987a8eb2005-03-01 19:00:30 +00001137void
sewardj7eb7c582005-06-23 01:02:53 +00001138ML_(generic_PRE_sys_bind) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001139 UWord arg0, UWord arg1, UWord arg2 )
1140{
1141 /* int bind(int sockfd, struct sockaddr *my_addr,
1142 int addrlen); */
1143 pre_mem_read_sockaddr(
1144 tid, "socketcall.bind(my_addr.%s)",
1145 (struct vki_sockaddr *) arg1, arg2
1146 );
1147}
1148
1149/* ------ */
1150
sewardj987a8eb2005-03-01 19:00:30 +00001151void
sewardj7eb7c582005-06-23 01:02:53 +00001152ML_(generic_PRE_sys_accept) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001153 UWord arg0, UWord arg1, UWord arg2 )
1154{
1155 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1156 Addr addr_p = arg1;
1157 Addr addrlen_p = arg2;
1158 if (addr_p != (Addr)NULL)
1159 buf_and_len_pre_check ( tid, addr_p, addrlen_p,
1160 "socketcall.accept(addr)",
1161 "socketcall.accept(addrlen_in)" );
1162}
1163
sewardja8d8e232005-06-07 20:04:56 +00001164SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001165ML_(generic_POST_sys_accept) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001166 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001167 UWord arg0, UWord arg1, UWord arg2 )
sewardj9efbbef2005-03-01 16:45:23 +00001168{
sewardja8d8e232005-06-07 20:04:56 +00001169 SysRes r = res;
1170 vg_assert(!res.isError); /* guaranteed by caller */
sewardj7eb7c582005-06-23 01:02:53 +00001171 if (!ML_(fd_allowed)(res.val, "accept", tid, True)) {
sewardja8d8e232005-06-07 20:04:56 +00001172 VG_(close)(res.val);
1173 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001174 } else {
1175 Addr addr_p = arg1;
1176 Addr addrlen_p = arg2;
1177 if (addr_p != (Addr)NULL)
1178 buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
1179 "socketcall.accept(addrlen_out)" );
1180 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00001181 ML_(record_fd_open_nameless)(tid, res.val);
sewardj9efbbef2005-03-01 16:45:23 +00001182 }
1183 return r;
1184}
1185
1186/* ------ */
1187
sewardj987a8eb2005-03-01 19:00:30 +00001188void
sewardj7eb7c582005-06-23 01:02:53 +00001189ML_(generic_PRE_sys_sendto) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001190 UWord arg0, UWord arg1, UWord arg2,
1191 UWord arg3, UWord arg4, UWord arg5 )
1192{
1193 /* int sendto(int s, const void *msg, int len,
1194 unsigned int flags,
1195 const struct sockaddr *to, int tolen); */
1196 PRE_MEM_READ( "socketcall.sendto(msg)",
1197 arg1, /* msg */
1198 arg2 /* len */ );
1199 pre_mem_read_sockaddr(
1200 tid, "socketcall.sendto(to.%s)",
1201 (struct vki_sockaddr *) arg4, arg5
1202 );
1203}
1204
1205/* ------ */
1206
sewardj987a8eb2005-03-01 19:00:30 +00001207void
sewardj7eb7c582005-06-23 01:02:53 +00001208ML_(generic_PRE_sys_send) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001209 UWord arg0, UWord arg1, UWord arg2 )
1210{
1211 /* int send(int s, const void *msg, size_t len, int flags); */
1212 PRE_MEM_READ( "socketcall.send(msg)",
1213 arg1, /* msg */
1214 arg2 /* len */ );
1215
1216}
1217
1218/* ------ */
1219
sewardj987a8eb2005-03-01 19:00:30 +00001220void
sewardj7eb7c582005-06-23 01:02:53 +00001221ML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001222 UWord arg0, UWord arg1, UWord arg2,
1223 UWord arg3, UWord arg4, UWord arg5 )
1224{
1225 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1226 struct sockaddr *from, int *fromlen); */
1227 Addr buf_p = arg1;
1228 Int len = arg2;
1229 Addr from_p = arg4;
1230 Addr fromlen_p = arg5;
1231 PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
1232 if (from_p != (Addr)NULL)
1233 buf_and_len_pre_check ( tid, from_p, fromlen_p,
1234 "socketcall.recvfrom(from)",
1235 "socketcall.recvfrom(fromlen_in)" );
1236}
1237
sewardj987a8eb2005-03-01 19:00:30 +00001238void
sewardj7eb7c582005-06-23 01:02:53 +00001239ML_(generic_POST_sys_recvfrom) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001240 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001241 UWord arg0, UWord arg1, UWord arg2,
1242 UWord arg3, UWord arg4, UWord arg5 )
1243{
1244 Addr buf_p = arg1;
1245 Int len = arg2;
1246 Addr from_p = arg4;
1247 Addr fromlen_p = arg5;
1248
sewardja8d8e232005-06-07 20:04:56 +00001249 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001250 if (from_p != (Addr)NULL)
1251 buf_and_len_post_check ( tid, res, from_p, fromlen_p,
1252 "socketcall.recvfrom(fromlen_out)" );
1253 POST_MEM_WRITE( buf_p, len );
1254}
1255
1256/* ------ */
1257
sewardj987a8eb2005-03-01 19:00:30 +00001258void
sewardj7eb7c582005-06-23 01:02:53 +00001259ML_(generic_PRE_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001260 UWord arg0, UWord arg1, UWord arg2 )
1261{
1262 /* int recv(int s, void *buf, int len, unsigned int flags); */
1263 /* man 2 recv says:
1264 The recv call is normally used only on a connected socket
1265 (see connect(2)) and is identical to recvfrom with a NULL
1266 from parameter.
1267 */
1268 PRE_MEM_WRITE( "socketcall.recv(buf)",
1269 arg1, /* buf */
1270 arg2 /* len */ );
1271}
1272
sewardj987a8eb2005-03-01 19:00:30 +00001273void
sewardj7eb7c582005-06-23 01:02:53 +00001274ML_(generic_POST_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001275 UWord res,
1276 UWord arg0, UWord arg1, UWord arg2 )
1277{
1278 if (res >= 0 && arg1 != 0) {
1279 POST_MEM_WRITE( arg1, /* buf */
1280 arg2 /* len */ );
1281 }
1282}
1283
1284/* ------ */
1285
sewardj987a8eb2005-03-01 19:00:30 +00001286void
sewardj7eb7c582005-06-23 01:02:53 +00001287ML_(generic_PRE_sys_connect) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001288 UWord arg0, UWord arg1, UWord arg2 )
1289{
1290 /* int connect(int sockfd,
1291 struct sockaddr *serv_addr, int addrlen ); */
1292 PRE_MEM_READ( "socketcall.connect(serv_addr.sa_family)",
1293 arg1, /* serv_addr */
1294 sizeof(vki_sa_family_t));
1295 pre_mem_read_sockaddr( tid,
1296 "socketcall.connect(serv_addr.%s)",
1297 (struct vki_sockaddr *) arg1, arg2);
1298}
1299
1300/* ------ */
1301
sewardj987a8eb2005-03-01 19:00:30 +00001302void
sewardj7eb7c582005-06-23 01:02:53 +00001303ML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001304 UWord arg0, UWord arg1, UWord arg2,
1305 UWord arg3, UWord arg4 )
1306{
1307 /* int setsockopt(int s, int level, int optname,
1308 const void *optval, int optlen); */
1309 PRE_MEM_READ( "socketcall.setsockopt(optval)",
1310 arg3, /* optval */
1311 arg4 /* optlen */ );
1312}
1313
1314/* ------ */
1315
sewardj987a8eb2005-03-01 19:00:30 +00001316void
sewardj7eb7c582005-06-23 01:02:53 +00001317ML_(generic_PRE_sys_getsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001318 UWord arg0, UWord arg1, UWord arg2,
1319 UWord arg3, UWord arg4 )
1320{
1321 /* int getsockopt(int s, int level, int optname,
1322 void *optval, socklen_t *optlen); */
1323 Addr optval_p = arg3;
1324 Addr optlen_p = arg4;
1325 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
tom1aa57372005-08-28 10:16:29 +00001326 if (optval_p != (Addr)NULL) {
sewardj9efbbef2005-03-01 16:45:23 +00001327 buf_and_len_pre_check ( tid, optval_p, optlen_p,
1328 "socketcall.getsockopt(optval)",
1329 "socketcall.getsockopt(optlen)" );
tom1aa57372005-08-28 10:16:29 +00001330 if (arg1 == VKI_SOL_SCTP &&
1331 (arg2 == VKI_SCTP_GET_PEER_ADDRS || arg2 == VKI_SCTP_GET_LOCAL_ADDRS)) {
1332 struct vki_sctp_getaddrs *ga = (struct vki_sctp_getaddrs*)arg3;
1333 int address_bytes = sizeof(struct vki_sockaddr_in6) * ga->addr_num;
1334 PRE_MEM_WRITE( "socketcall.getsockopt(optval.addrs)", (Addr)ga->addrs, address_bytes );
1335 }
1336 }
sewardj9efbbef2005-03-01 16:45:23 +00001337}
1338
sewardj987a8eb2005-03-01 19:00:30 +00001339void
sewardj7eb7c582005-06-23 01:02:53 +00001340ML_(generic_POST_sys_getsockopt) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001341 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001342 UWord arg0, UWord arg1, UWord arg2,
1343 UWord arg3, UWord arg4 )
1344{
1345 Addr optval_p = arg3;
1346 Addr optlen_p = arg4;
sewardja8d8e232005-06-07 20:04:56 +00001347 vg_assert(!res.isError); /* guaranteed by caller */
tom1aa57372005-08-28 10:16:29 +00001348 if (optval_p != (Addr)NULL) {
sewardj9efbbef2005-03-01 16:45:23 +00001349 buf_and_len_post_check ( tid, res, optval_p, optlen_p,
1350 "socketcall.getsockopt(optlen_out)" );
tom1aa57372005-08-28 10:16:29 +00001351 if (arg1 == VKI_SOL_SCTP &&
1352 (arg2 == VKI_SCTP_GET_PEER_ADDRS || arg2 == VKI_SCTP_GET_LOCAL_ADDRS)) {
1353 struct vki_sctp_getaddrs *ga = (struct vki_sctp_getaddrs*)arg3;
1354 struct vki_sockaddr *a = ga->addrs;
1355 int i;
1356 for (i = 0; i < ga->addr_num; i++) {
1357 int sl = 0;
1358 if (a->sa_family == VKI_AF_INET)
1359 sl = sizeof(struct vki_sockaddr_in);
1360 else if (a->sa_family == VKI_AF_INET6)
1361 sl = sizeof(struct vki_sockaddr_in6);
1362 else {
1363 VG_(message)(Vg_UserMsg, "Warning: getsockopt: unhandled address type %d", a->sa_family);
1364 }
1365 a = (struct vki_sockaddr*)((char*)a + sl);
1366 }
1367 POST_MEM_WRITE( (Addr)ga->addrs, (char*)a - (char*)ga->addrs );
1368 }
1369 }
sewardj9efbbef2005-03-01 16:45:23 +00001370}
1371
1372/* ------ */
1373
sewardj987a8eb2005-03-01 19:00:30 +00001374void
sewardj7eb7c582005-06-23 01:02:53 +00001375ML_(generic_PRE_sys_getsockname) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001376 UWord arg0, UWord arg1, UWord arg2 )
1377{
1378 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1379 Addr name_p = arg1;
1380 Addr namelen_p = arg2;
1381 /* Nb: name_p cannot be NULL */
1382 buf_and_len_pre_check ( tid, name_p, namelen_p,
1383 "socketcall.getsockname(name)",
1384 "socketcall.getsockname(namelen_in)" );
1385}
1386
sewardj987a8eb2005-03-01 19:00:30 +00001387void
sewardj7eb7c582005-06-23 01:02:53 +00001388ML_(generic_POST_sys_getsockname) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001389 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001390 UWord arg0, UWord arg1, UWord arg2 )
1391{
1392 Addr name_p = arg1;
1393 Addr namelen_p = arg2;
sewardja8d8e232005-06-07 20:04:56 +00001394 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001395 buf_and_len_post_check ( tid, res, name_p, namelen_p,
1396 "socketcall.getsockname(namelen_out)" );
1397}
1398
1399/* ------ */
1400
sewardj987a8eb2005-03-01 19:00:30 +00001401void
sewardj7eb7c582005-06-23 01:02:53 +00001402ML_(generic_PRE_sys_getpeername) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001403 UWord arg0, UWord arg1, UWord arg2 )
1404{
1405 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1406 Addr name_p = arg1;
1407 Addr namelen_p = arg2;
1408 /* Nb: name_p cannot be NULL */
1409 buf_and_len_pre_check ( tid, name_p, namelen_p,
1410 "socketcall.getpeername(name)",
1411 "socketcall.getpeername(namelen_in)" );
1412}
1413
sewardj987a8eb2005-03-01 19:00:30 +00001414void
sewardj7eb7c582005-06-23 01:02:53 +00001415ML_(generic_POST_sys_getpeername) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001416 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001417 UWord arg0, UWord arg1, UWord arg2 )
1418{
1419 Addr name_p = arg1;
1420 Addr namelen_p = arg2;
sewardja8d8e232005-06-07 20:04:56 +00001421 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001422 buf_and_len_post_check ( tid, res, name_p, namelen_p,
1423 "socketcall.getpeername(namelen_out)" );
1424}
1425
1426/* ------ */
1427
sewardj987a8eb2005-03-01 19:00:30 +00001428void
sewardj7eb7c582005-06-23 01:02:53 +00001429ML_(generic_PRE_sys_sendmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001430 UWord arg0, UWord arg1 )
1431{
1432 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1433 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1434 msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
1435}
1436
1437/* ------ */
1438
sewardj987a8eb2005-03-01 19:00:30 +00001439void
sewardj7eb7c582005-06-23 01:02:53 +00001440ML_(generic_PRE_sys_recvmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001441 UWord arg0, UWord arg1 )
1442{
1443 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1444 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1445 msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
1446}
1447
sewardj987a8eb2005-03-01 19:00:30 +00001448void
sewardj7eb7c582005-06-23 01:02:53 +00001449ML_(generic_POST_sys_recvmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001450 UWord arg0, UWord arg1 )
1451{
1452 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1453 msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
1454 check_cmsg_for_fds( tid, msg );
1455}
1456
1457
1458/* ---------------------------------------------------------------------
sewardjb369c5e2005-03-24 17:52:02 +00001459 Deal with a bunch of IPC related syscalls
1460 ------------------------------------------------------------------ */
1461
1462/* ------ */
1463
1464void
sewardj7eb7c582005-06-23 01:02:53 +00001465ML_(generic_PRE_sys_semop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001466 UWord arg0, UWord arg1, UWord arg2 )
1467{
1468 /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1469 PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1470}
1471
1472/* ------ */
1473
1474void
sewardj7eb7c582005-06-23 01:02:53 +00001475ML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001476 UWord arg0, UWord arg1,
1477 UWord arg2, UWord arg3 )
1478{
1479 /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1480 struct timespec *timeout); */
1481 PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1482 if (arg3 != 0)
1483 PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1484}
1485
1486/* ------ */
1487
1488static
1489UInt get_sem_count( Int semid )
1490{
sewardja8d8e232005-06-07 20:04:56 +00001491 struct vki_semid_ds buf;
1492 union vki_semun arg;
1493 SysRes res;
sewardjb369c5e2005-03-24 17:52:02 +00001494
sewardja8d8e232005-06-07 20:04:56 +00001495 arg.buf = &buf;
sewardjb369c5e2005-03-24 17:52:02 +00001496
sewardja8d8e232005-06-07 20:04:56 +00001497# ifdef __NR_semctl
1498 res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
1499# else
1500 res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1501 VKI_IPC_STAT, (UWord)&arg);
1502# endif
1503 if (res.isError)
1504 return 0;
sewardjb369c5e2005-03-24 17:52:02 +00001505
sewardja8d8e232005-06-07 20:04:56 +00001506 return buf.sem_nsems;
sewardjb369c5e2005-03-24 17:52:02 +00001507}
1508
1509void
sewardj7eb7c582005-06-23 01:02:53 +00001510ML_(generic_PRE_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001511 UWord arg0, UWord arg1,
1512 UWord arg2, UWord arg3 )
1513{
1514 /* int semctl(int semid, int semnum, int cmd, ...); */
1515 union vki_semun arg = *(union vki_semun *)&arg3;
1516 UInt nsems;
1517 switch (arg2 /* cmd */) {
1518 case VKI_IPC_INFO:
1519 case VKI_SEM_INFO:
1520 case VKI_IPC_INFO|VKI_IPC_64:
1521 case VKI_SEM_INFO|VKI_IPC_64:
1522 PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1523 (Addr)arg.buf, sizeof(struct vki_seminfo) );
1524 break;
1525 case VKI_IPC_STAT:
1526 case VKI_SEM_STAT:
1527 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1528 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1529 break;
1530 case VKI_IPC_STAT|VKI_IPC_64:
1531 case VKI_SEM_STAT|VKI_IPC_64:
1532 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1533 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1534 break;
1535 case VKI_IPC_SET:
1536 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1537 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1538 break;
1539 case VKI_IPC_SET|VKI_IPC_64:
1540 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1541 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1542 break;
1543 case VKI_GETALL:
1544 case VKI_GETALL|VKI_IPC_64:
1545 nsems = get_sem_count( arg0 );
1546 PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1547 (Addr)arg.array, sizeof(unsigned short) * nsems );
1548 break;
1549 case VKI_SETALL:
1550 case VKI_SETALL|VKI_IPC_64:
1551 nsems = get_sem_count( arg0 );
1552 PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1553 (Addr)arg.array, sizeof(unsigned short) * nsems );
1554 break;
1555 }
1556}
1557
1558void
sewardj7eb7c582005-06-23 01:02:53 +00001559ML_(generic_POST_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001560 UWord res,
1561 UWord arg0, UWord arg1,
1562 UWord arg2, UWord arg3 )
1563{
1564 union vki_semun arg = *(union vki_semun *)&arg3;
1565 UInt nsems;
1566 switch (arg2 /* cmd */) {
1567 case VKI_IPC_INFO:
1568 case VKI_SEM_INFO:
1569 case VKI_IPC_INFO|VKI_IPC_64:
1570 case VKI_SEM_INFO|VKI_IPC_64:
1571 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1572 break;
1573 case VKI_IPC_STAT:
1574 case VKI_SEM_STAT:
1575 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1576 break;
1577 case VKI_IPC_STAT|VKI_IPC_64:
1578 case VKI_SEM_STAT|VKI_IPC_64:
1579 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1580 break;
1581 case VKI_GETALL:
1582 case VKI_GETALL|VKI_IPC_64:
1583 nsems = get_sem_count( arg0 );
1584 POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1585 break;
1586 }
1587}
1588
1589/* ------ */
1590
sewardjb369c5e2005-03-24 17:52:02 +00001591/* ------ */
1592
1593static
1594UInt get_shm_size ( Int shmid )
1595{
sewardja8d8e232005-06-07 20:04:56 +00001596# ifdef __NR_shmctl
sewardjb369c5e2005-03-24 17:52:02 +00001597 struct vki_shmid64_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001598 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
1599# else
sewardjb369c5e2005-03-24 17:52:02 +00001600 struct vki_shmid_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001601 SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
sewardjb369c5e2005-03-24 17:52:02 +00001602 VKI_IPC_STAT, 0, (UWord)&buf);
sewardja8d8e232005-06-07 20:04:56 +00001603# endif
1604 if (__res.isError)
sewardjb369c5e2005-03-24 17:52:02 +00001605 return 0;
1606
1607 return buf.shm_segsz;
1608}
1609
1610UWord
sewardj7eb7c582005-06-23 01:02:53 +00001611ML_(generic_PRE_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001612 UWord arg0, UWord arg1, UWord arg2 )
1613{
1614 /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
sewardj45f4e7c2005-09-27 19:20:21 +00001615 UInt segmentSize = get_shm_size ( arg0 );
1616 UWord tmp;
1617 Bool ok;
1618 if (arg1 == 0) {
1619 tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
1620 if (ok)
1621 arg1 = tmp;
1622 }
sewardj7eb7c582005-06-23 01:02:53 +00001623 else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
sewardjb369c5e2005-03-24 17:52:02 +00001624 arg1 = 0;
1625 return arg1;
1626}
1627
1628void
sewardj7eb7c582005-06-23 01:02:53 +00001629ML_(generic_POST_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001630 UWord res,
1631 UWord arg0, UWord arg1, UWord arg2 )
1632{
1633 UInt segmentSize = get_shm_size ( arg0 );
1634 if ( segmentSize > 0 ) {
1635 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001636 Bool d;
sewardjb369c5e2005-03-24 17:52:02 +00001637
tomf61fea02005-10-04 12:04:06 +00001638 if (arg2 & VKI_SHM_RDONLY)
sewardjb369c5e2005-03-24 17:52:02 +00001639 prot &= ~VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001640 /* It isn't exactly correct to pass 0 for the fd and offset
1641 here. The kernel seems to think the corresponding section
1642 does have dev/ino numbers:
1643
1644 04e52000-04ec8000 rw-s 00000000 00:06 1966090 /SYSV00000000 (deleted)
1645
1646 However there is no obvious way to find them. In order to
1647 cope with the discrepancy, aspacem's sync checker omits the
1648 dev/ino correspondence check in cases where V does not know
1649 the dev/ino. */
tom1340c352005-10-04 15:59:54 +00001650 d = VG_(am_notify_client_shmat)( res, VG_PGROUNDUP(segmentSize), prot );
sewardj45f4e7c2005-09-27 19:20:21 +00001651
1652 /* we don't distinguish whether it's read-only or
1653 * read-write -- it doesn't matter really. */
1654 VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False );
1655 if (d)
1656 VG_(discard_translations)( (Addr64)res,
1657 (ULong)VG_PGROUNDUP(segmentSize),
1658 "ML_(generic_POST_sys_shmat)" );
sewardjb369c5e2005-03-24 17:52:02 +00001659 }
1660}
1661
1662/* ------ */
1663
1664Bool
sewardj7eb7c582005-06-23 01:02:53 +00001665ML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001666{
1667 /* int shmdt(const void *shmaddr); */
sewardj7eb7c582005-06-23 01:02:53 +00001668 return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
sewardjb369c5e2005-03-24 17:52:02 +00001669}
1670
1671void
sewardj7eb7c582005-06-23 01:02:53 +00001672ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001673{
sewardj45f4e7c2005-09-27 19:20:21 +00001674 NSegment* s = VG_(am_find_nsegment)(arg0);
sewardjb369c5e2005-03-24 17:52:02 +00001675
sewardj0e682c62005-09-28 20:05:31 +00001676 if (s != NULL) {
1677 Addr s_start = s->start;
1678 SizeT s_len = s->end+1 - s->start;
tom1340c352005-10-04 15:59:54 +00001679 Bool d;
1680
1681 vg_assert(s->kind == SkShmC && s->start == arg0);
1682
1683 d = VG_(am_notify_munmap)(s_start, s_len);
sewardj0e682c62005-09-28 20:05:31 +00001684 s = NULL; /* s is now invalid */
1685 VG_TRACK( die_mem_munmap, s_start, s_len );
sewardj45f4e7c2005-09-27 19:20:21 +00001686 if (d)
sewardj0e682c62005-09-28 20:05:31 +00001687 VG_(discard_translations)( (Addr64)s_start,
1688 (ULong)s_len,
sewardj45f4e7c2005-09-27 19:20:21 +00001689 "ML_(generic_POST_sys_shmdt)" );
sewardjb369c5e2005-03-24 17:52:02 +00001690 }
1691}
1692/* ------ */
1693
1694void
sewardj7eb7c582005-06-23 01:02:53 +00001695ML_(generic_PRE_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001696 UWord arg0, UWord arg1, UWord arg2 )
1697{
1698 /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
1699 switch (arg1 /* cmd */) {
1700 case VKI_IPC_INFO:
1701 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1702 arg2, sizeof(struct vki_shminfo) );
1703 break;
1704 case VKI_IPC_INFO|VKI_IPC_64:
1705 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1706 arg2, sizeof(struct vki_shminfo64) );
1707 break;
1708 case VKI_SHM_INFO:
1709 case VKI_SHM_INFO|VKI_IPC_64:
1710 PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
1711 arg2, sizeof(struct vki_shm_info) );
1712 break;
1713 case VKI_IPC_STAT:
1714 case VKI_SHM_STAT:
1715 PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
1716 arg2, sizeof(struct vki_shmid_ds) );
1717 break;
1718 case VKI_IPC_STAT|VKI_IPC_64:
1719 case VKI_SHM_STAT|VKI_IPC_64:
1720 PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
1721 arg2, sizeof(struct vki_shmid64_ds) );
1722 break;
1723 case VKI_IPC_SET:
1724 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1725 arg2, sizeof(struct vki_shmid_ds) );
1726 break;
1727 case VKI_IPC_SET|VKI_IPC_64:
1728 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1729 arg2, sizeof(struct vki_shmid64_ds) );
1730 break;
1731 }
1732}
1733
1734void
sewardj7eb7c582005-06-23 01:02:53 +00001735ML_(generic_POST_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001736 UWord res,
1737 UWord arg0, UWord arg1, UWord arg2 )
1738{
1739 switch (arg1 /* cmd */) {
1740 case VKI_IPC_INFO:
1741 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
1742 break;
1743 case VKI_IPC_INFO|VKI_IPC_64:
1744 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
1745 break;
1746 case VKI_SHM_INFO:
1747 case VKI_SHM_INFO|VKI_IPC_64:
1748 POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
1749 break;
1750 case VKI_IPC_STAT:
1751 case VKI_SHM_STAT:
1752 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
1753 break;
1754 case VKI_IPC_STAT|VKI_IPC_64:
1755 case VKI_SHM_STAT|VKI_IPC_64:
1756 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
1757 break;
1758 }
1759}
1760
1761
1762/* ---------------------------------------------------------------------
tom9548a162005-09-30 08:07:53 +00001763 Generic handler for mmap
1764 ------------------------------------------------------------------ */
1765
tom6d85b042005-09-30 16:09:12 +00001766/*
1767 * Although mmap is specified by POSIX and the argument are generally
1768 * consistent across platforms the precise details of the low level
1769 * argument passing conventions differ. For example:
1770 *
1771 * - On x86-linux there is mmap (aka old_mmap) which takes the
1772 * arguments in a memory block and the offset in bytes; and
1773 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
1774 * way and the offset in pages.
1775 *
1776 * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
1777 * arguments in the normal way and the offset in bytes; and
1778 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
1779 * way and the offset in pages.
1780 *
1781 * - On amd64-linux everything is simple and there is just the one
1782 * call, mmap (aka sys_mmap) which takes the arguments in the
1783 * normal way and the offset in bytes.
1784 *
1785 * To cope with all this we provide a generic handler function here
1786 * and then each platform implements one or more system call handlers
1787 * which call this generic routine after extracting and normalising
1788 * the arguments.
1789 */
1790
tom9548a162005-09-30 08:07:53 +00001791SysRes
1792ML_(generic_PRE_sys_mmap) ( ThreadId tid,
1793 UWord arg1, UWord arg2, UWord arg3,
sewardj274461d2005-10-02 17:01:41 +00001794 UWord arg4, UWord arg5, Off64T arg6 )
tom9548a162005-09-30 08:07:53 +00001795{
1796 Addr advised;
1797 SysRes sres;
1798 MapRequest mreq;
1799 Bool mreq_ok;
1800
1801 if (arg2 == 0) {
1802 /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
1803 shall be established. */
1804 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1805 }
1806
1807 if (!VG_IS_PAGE_ALIGNED(arg1)) {
1808 /* zap any misaligned addresses. */
1809 /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
1810 to fail. Here, we catch them all. */
1811 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1812 }
1813
sewardj7e21df82005-09-30 10:48:27 +00001814 if (!VG_IS_PAGE_ALIGNED(arg6)) {
1815 /* zap any misaligned offsets. */
1816 /* SuSV3 says: The off argument is constrained to be aligned and
1817 sized according to the value returned by sysconf() when
1818 passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
1819 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1820 }
1821
tom9548a162005-09-30 08:07:53 +00001822 /* Figure out what kind of allocation constraints there are
1823 (fixed/hint/any), and ask aspacem what we should do. */
1824 mreq.start = arg1;
1825 mreq.len = arg2;
1826 if (arg4 & VKI_MAP_FIXED) {
1827 mreq.rkind = MFixed;
1828 } else
1829 if (arg1 != 0) {
1830 mreq.rkind = MHint;
1831 } else {
1832 mreq.rkind = MAny;
1833 }
1834
1835 /* Enquire ... */
1836 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
1837 if (!mreq_ok) {
1838 /* Our request was bounced, so we'd better fail. */
1839 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1840 }
1841
1842 /* Otherwise we're OK (so far). Install aspacem's choice of
1843 address, and let the mmap go through. */
1844 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
1845 arg4 | VKI_MAP_FIXED,
1846 arg5, arg6);
1847
1848 if (!sres.isError) {
1849 /* Notify aspacem and the tool. */
1850 ML_(notify_aspacem_and_tool_of_mmap)(
1851 (Addr)sres.val, /* addr kernel actually assigned */
1852 arg2, arg3,
1853 arg4, /* the original flags value */
1854 arg5, arg6
1855 );
1856 /* Load symbols? */
sewardjf72cced2005-11-08 00:45:47 +00001857 VG_(di_notify_mmap)( (Addr)sres.val, False/*allow_SkFileV*/ );
tom9548a162005-09-30 08:07:53 +00001858 }
1859
1860 /* Stay sane */
1861 if (!sres.isError && (arg4 & VKI_MAP_FIXED))
1862 vg_assert(sres.val == arg1);
1863
1864 return sres;
1865}
1866
1867
1868/* ---------------------------------------------------------------------
nethercote4fa681f2004-11-08 17:51:39 +00001869 The Main Entertainment ... syscall wrappers
njn25e49d8e72002-09-23 09:36:25 +00001870 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001871
nethercote4fa681f2004-11-08 17:51:39 +00001872/* Note: the PRE() and POST() wrappers are for the actual functions
nethercote8ff888f2004-11-17 17:11:45 +00001873 implementing the system calls in the OS kernel. These mostly have
nethercote4fa681f2004-11-08 17:51:39 +00001874 names like sys_write(); a few have names like old_mmap(). See the
njnaf839f52005-06-23 03:27:57 +00001875 comment for ML_(syscall_table)[] for important info about the __NR_foo
nethercote8ff888f2004-11-17 17:11:45 +00001876 constants and their relationship to the sys_foo() functions.
nethercote4fa681f2004-11-08 17:51:39 +00001877
nethercote92b2fd52004-11-16 16:15:41 +00001878 Some notes about names used for syscalls and args:
1879 - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
1880 ambiguity.
1881
1882 - For error messages, we generally use a somewhat generic name
1883 for the syscall (eg. "write" rather than "sys_write"). This should be
1884 good enough for the average user to understand what is happening,
1885 without confusing them with names like "sys_write".
1886
1887 - Also, for error messages the arg names are mostly taken from the man
1888 pages (even though many of those man pages are really for glibc
nethercote8ff888f2004-11-17 17:11:45 +00001889 functions of the same name), rather than from the OS kernel source,
nethercote92b2fd52004-11-16 16:15:41 +00001890 for the same reason -- a user presented with a "bogus foo(bar)" arg
1891 will most likely look at the "foo" man page to see which is the "bar"
1892 arg.
nethercote8b76fe52004-11-08 19:20:09 +00001893
nethercote9c311eb2004-11-12 18:20:12 +00001894 Note that we use our own vki_* types. The one exception is in
1895 PRE_REG_READn calls, where pointer types haven't been changed, because
1896 they don't need to be -- eg. for "foo*" to be used, the type foo need not
1897 be visible.
1898
nethercote4fa681f2004-11-08 17:51:39 +00001899 XXX: some of these are arch-specific, and should be factored out.
1900*/
1901
sewardja8d8e232005-06-07 20:04:56 +00001902#define PRE(name) DEFN_PRE_TEMPLATE(generic, name)
1903#define POST(name) DEFN_POST_TEMPLATE(generic, name)
jsgf855d93d2003-10-13 22:26:55 +00001904
sewardje7aa4ae2005-06-09 12:43:42 +00001905// Combine two 32-bit values into a 64-bit value
1906#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
1907
sewardja8d8e232005-06-07 20:04:56 +00001908//zz //PRE(sys_exit_group, Special)
1909//zz //{
1910//zz // VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
1911//zz //}
nethercoteef0c7662004-11-06 15:38:43 +00001912
sewardja8d8e232005-06-07 20:04:56 +00001913PRE(sys_exit)
jsgf855d93d2003-10-13 22:26:55 +00001914{
sewardja8d8e232005-06-07 20:04:56 +00001915 ThreadState* tst;
sewardja922b612005-03-11 02:47:32 +00001916 /* simple; just make this thread exit */
1917 PRINT("exit( %d )", ARG1);
1918 PRE_REG_READ1(void, "exit", int, exitcode);
sewardja8d8e232005-06-07 20:04:56 +00001919 tst = VG_(get_ThreadState)(tid);
1920 /* Set the thread's status to be exiting, then claim that the
1921 syscall succeeded. */
sewardja922b612005-03-11 02:47:32 +00001922 tst->exitreason = VgSrc_ExitSyscall;
1923 tst->os_state.exitcode = ARG1;
sewardja8d8e232005-06-07 20:04:56 +00001924 SET_STATUS_Success(0);
jsgf855d93d2003-10-13 22:26:55 +00001925}
1926
sewardja8d8e232005-06-07 20:04:56 +00001927PRE(sys_ni_syscall)
nethercoteeb1c7b72004-11-11 19:43:50 +00001928{
1929 PRINT("non-existent syscall! (ni_syscall)");
1930 PRE_REG_READ0(long, "ni_syscall");
sewardja8d8e232005-06-07 20:04:56 +00001931 SET_STATUS_Failure( VKI_ENOSYS );
nethercoteeb1c7b72004-11-11 19:43:50 +00001932}
1933
sewardj696c5512005-06-08 23:38:32 +00001934PRE(sys_iopl)
1935{
1936 PRINT("sys_iopl ( %d )", ARG1);
1937 PRE_REG_READ1(long, "iopl", unsigned long, level);
1938}
1939
sewardje6d5e722005-06-10 10:27:55 +00001940// XXX: this wrapper is only suitable for 32-bit platforms
1941#if defined(VGP_x86_linux)
1942PRE(sys_lookup_dcookie)
1943{
1944 PRINT("sys_lookup_dcookie (0x%llx, %p, %d)", LOHI64(ARG1,ARG2), ARG3, ARG4);
1945 PRE_REG_READ4(long, "lookup_dcookie",
1946 vki_u32, cookie_low32, vki_u32, cookie_high32,
1947 char *, buf, vki_size_t, len);
1948 PRE_MEM_WRITE( "lookup_dcookie(buf)", ARG3, ARG4);
1949}
1950POST(sys_lookup_dcookie)
1951{
1952 vg_assert(SUCCESS);
1953 if (ARG3 != (Addr)NULL)
1954 POST_MEM_WRITE( ARG3, RES);
1955}
1956#endif
sewardj78b50e42005-06-08 01:47:28 +00001957
1958PRE(sys_fsync)
1959{
1960 *flags |= SfMayBlock;
1961 PRINT("sys_fsync ( %d )", ARG1);
1962 PRE_REG_READ1(long, "fsync", unsigned int, fd);
1963}
1964
sewardj696c5512005-06-08 23:38:32 +00001965PRE(sys_fdatasync)
1966{
1967 *flags |= SfMayBlock;
1968 PRINT("sys_fdatasync ( %d )", ARG1);
1969 PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
1970}
1971
1972PRE(sys_msync)
1973{
1974 *flags |= SfMayBlock;
1975 PRINT("sys_msync ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
1976 PRE_REG_READ3(long, "msync",
1977 unsigned long, start, vki_size_t, length, int, flags);
1978 PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
1979}
1980
sewardje6d5e722005-06-10 10:27:55 +00001981// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
1982// versions of LiS (Linux Streams). They are not part of the kernel.
1983// Therefore, we have to provide this type ourself, rather than getting it
1984// from the kernel sources.
1985struct vki_pmsg_strbuf {
1986 int maxlen; /* no. of bytes in buffer */
1987 int len; /* no. of bytes returned */
1988 vki_caddr_t buf; /* pointer to data */
1989};
1990PRE(sys_getpmsg)
1991{
1992 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
1993 struct vki_pmsg_strbuf *ctrl;
1994 struct vki_pmsg_strbuf *data;
1995 *flags |= SfMayBlock;
1996 PRINT("sys_getpmsg ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
1997 PRE_REG_READ5(int, "getpmsg",
1998 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
1999 int *, bandp, int *, flagsp);
2000 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2001 data = (struct vki_pmsg_strbuf *)ARG3;
2002 if (ctrl && ctrl->maxlen > 0)
2003 PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2004 if (data && data->maxlen > 0)
2005 PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2006 if (ARG4)
2007 PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2008 if (ARG5)
2009 PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2010}
2011POST(sys_getpmsg)
2012{
2013 struct vki_pmsg_strbuf *ctrl;
2014 struct vki_pmsg_strbuf *data;
2015 vg_assert(SUCCESS);
2016 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2017 data = (struct vki_pmsg_strbuf *)ARG3;
2018 if (RES == 0 && ctrl && ctrl->len > 0) {
2019 POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2020 }
2021 if (RES == 0 && data && data->len > 0) {
2022 POST_MEM_WRITE( (Addr)data->buf, data->len);
2023 }
2024}
2025
2026PRE(sys_putpmsg)
2027{
2028 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2029 struct vki_pmsg_strbuf *ctrl;
2030 struct vki_pmsg_strbuf *data;
2031 *flags |= SfMayBlock;
2032 PRINT("sys_putpmsg ( %d, %p, %p, %d, %d )", ARG1,ARG2,ARG3,ARG4,ARG5);
2033 PRE_REG_READ5(int, "putpmsg",
2034 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2035 int, band, int, flags);
2036 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2037 data = (struct vki_pmsg_strbuf *)ARG3;
2038 if (ctrl && ctrl->len > 0)
2039 PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2040 if (data && data->len > 0)
2041 PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2042}
sewardj696c5512005-06-08 23:38:32 +00002043
2044PRE(sys_getitimer)
2045{
2046 PRINT("sys_getitimer ( %d, %p )", ARG1, ARG2);
2047 PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
2048 PRE_MEM_WRITE( "getitimer(value)", ARG2, sizeof(struct vki_itimerval) );
2049}
sewardj696c5512005-06-08 23:38:32 +00002050POST(sys_getitimer)
2051{
2052 if (ARG2 != (Addr)NULL) {
2053 POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerval));
2054 }
2055}
2056
2057PRE(sys_setitimer)
2058{
2059 PRINT("sys_setitimer ( %d, %p, %p )", ARG1,ARG2,ARG3);
2060 PRE_REG_READ3(long, "setitimer",
2061 int, which,
2062 struct itimerval *, value, struct itimerval *, ovalue);
2063 if (ARG2 != (Addr)NULL)
2064 PRE_MEM_READ( "setitimer(value)", ARG2, sizeof(struct vki_itimerval) );
2065 if (ARG3 != (Addr)NULL)
2066 PRE_MEM_WRITE( "setitimer(ovalue)", ARG3, sizeof(struct vki_itimerval));
2067}
2068
2069POST(sys_setitimer)
2070{
2071 if (ARG3 != (Addr)NULL) {
2072 POST_MEM_WRITE(ARG3, sizeof(struct vki_itimerval));
2073 }
2074}
2075
2076PRE(sys_chroot)
2077{
2078 PRINT("sys_chroot ( %p )", ARG1);
2079 PRE_REG_READ1(long, "chroot", const char *, path);
2080 PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2081}
sewardja8d8e232005-06-07 20:04:56 +00002082
2083PRE(sys_madvise)
jsgf855d93d2003-10-13 22:26:55 +00002084{
sewardja8d8e232005-06-07 20:04:56 +00002085 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00002086 PRINT("sys_madvise ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
nethercoteac866b92004-11-15 20:23:15 +00002087 PRE_REG_READ3(long, "madvise",
2088 unsigned long, start, vki_size_t, length, int, advice);
jsgf855d93d2003-10-13 22:26:55 +00002089}
2090
sewardja8d8e232005-06-07 20:04:56 +00002091PRE(sys_mremap)
jsgf855d93d2003-10-13 22:26:55 +00002092{
nethercote27ea8bc2004-07-10 17:21:14 +00002093 // Nb: this is different to the glibc version described in the man pages,
2094 // which lacks the fifth 'new_address' argument.
nethercote06c7bd72004-11-14 19:11:56 +00002095 PRINT("sys_mremap ( %p, %llu, %d, 0x%x, %p )",
njn22cfccb2004-11-27 16:10:23 +00002096 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5);
nethercote06c7bd72004-11-14 19:11:56 +00002097 PRE_REG_READ5(unsigned long, "mremap",
2098 unsigned long, old_addr, unsigned long, old_size,
2099 unsigned long, new_size, unsigned long, flags,
2100 unsigned long, new_addr);
sewardja8d8e232005-06-07 20:04:56 +00002101 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002102 do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
sewardja8d8e232005-06-07 20:04:56 +00002103 );
jsgf855d93d2003-10-13 22:26:55 +00002104}
2105
sewardj8c9ea4e2005-06-08 10:46:56 +00002106PRE(sys_nice)
2107{
2108 PRINT("sys_nice ( %d )", ARG1);
2109 PRE_REG_READ1(long, "nice", int, inc);
2110}
sewardj78b50e42005-06-08 01:47:28 +00002111
sewardj696c5512005-06-08 23:38:32 +00002112PRE(sys_mlock)
2113{
2114 *flags |= SfMayBlock;
2115 PRINT("sys_mlock ( %p, %llu )", ARG1, (ULong)ARG2);
2116 PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2117}
2118
2119PRE(sys_munlock)
2120{
2121 *flags |= SfMayBlock;
2122 PRINT("sys_munlock ( %p, %llu )", ARG1, (ULong)ARG2);
2123 PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2124}
2125
2126PRE(sys_mlockall)
2127{
2128 *flags |= SfMayBlock;
2129 PRINT("sys_mlockall ( %x )", ARG1);
2130 PRE_REG_READ1(long, "mlockall", int, flags);
2131}
2132
sewardj696c5512005-06-08 23:38:32 +00002133PRE(sys_setpriority)
2134{
2135 PRINT("sys_setpriority ( %d, %d, %d )", ARG1, ARG2, ARG3);
2136 PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2137}
2138
2139PRE(sys_getpriority)
2140{
2141 PRINT("sys_getpriority ( %d, %d )", ARG1, ARG2);
2142 PRE_REG_READ2(long, "getpriority", int, which, int, who);
2143}
2144
tom4f08a652005-07-05 23:25:17 +00002145// The actual kernel definition of this routine takes a
2146// single 64 bit offset argument. This version is for 32 bit
2147// platforms only and treats the offset as two values - the
2148// kernel relies on stack based argument passing conventions
2149// to merge the two together.
sewardje6d5e722005-06-10 10:27:55 +00002150PRE(sys_pwrite64)
2151{
2152 *flags |= SfMayBlock;
2153 PRINT("sys_pwrite64 ( %d, %p, %llu, %lld )",
2154 ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
2155 PRE_REG_READ5(ssize_t, "pwrite64",
2156 unsigned int, fd, const char *, buf, vki_size_t, count,
2157 vki_u32, offset_low32, vki_u32, offset_high32);
2158 PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2159}
sewardj8c9ea4e2005-06-08 10:46:56 +00002160
2161PRE(sys_sync)
2162{
2163 *flags |= SfMayBlock;
2164 PRINT("sys_sync ( )");
2165 PRE_REG_READ0(long, "sync");
2166}
2167
sewardj696c5512005-06-08 23:38:32 +00002168PRE(sys_fstatfs)
2169{
2170 PRINT("sys_fstatfs ( %d, %p )",ARG1,ARG2);
2171 PRE_REG_READ2(long, "fstatfs",
2172 unsigned int, fd, struct statfs *, buf);
2173 PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2174}
2175
2176POST(sys_fstatfs)
2177{
2178 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2179}
2180
sewardje6d5e722005-06-10 10:27:55 +00002181PRE(sys_fstatfs64)
2182{
2183 PRINT("sys_fstatfs64 ( %d, %llu, %p )",ARG1,(ULong)ARG2,ARG3);
2184 PRE_REG_READ3(long, "fstatfs64",
2185 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2186 PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2187}
2188POST(sys_fstatfs64)
2189{
2190 POST_MEM_WRITE( ARG3, ARG2 );
2191}
sewardj696c5512005-06-08 23:38:32 +00002192
2193PRE(sys_getsid)
2194{
2195 PRINT("sys_getsid ( %d )", ARG1);
2196 PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2197}
2198
tom4f08a652005-07-05 23:25:17 +00002199// The actual kernel definition of this routine takes a
2200// single 64 bit offset argument. This version is for 32 bit
2201// platforms only and treats the offset as two values - the
2202// kernel relies on stack based argument passing conventions
2203// to merge the two together.
sewardje7aa4ae2005-06-09 12:43:42 +00002204PRE(sys_pread64)
2205{
2206 *flags |= SfMayBlock;
2207 PRINT("sys_pread64 ( %d, %p, %llu, %lld )",
2208 ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
2209 PRE_REG_READ5(ssize_t, "pread64",
2210 unsigned int, fd, char *, buf, vki_size_t, count,
2211 vki_u32, offset_low32, vki_u32, offset_high32);
2212 PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2213}
2214POST(sys_pread64)
2215{
2216 vg_assert(SUCCESS);
2217 if (RES > 0) {
2218 POST_MEM_WRITE( ARG2, RES );
2219 }
2220}
jsgf855d93d2003-10-13 22:26:55 +00002221
sewardja8d8e232005-06-07 20:04:56 +00002222PRE(sys_mknod)
jsgf855d93d2003-10-13 22:26:55 +00002223{
njn22cfccb2004-11-27 16:10:23 +00002224 PRINT("sys_mknod ( %p, 0x%x, 0x%x )", ARG1, ARG2, ARG3 );
nethercotec6851dd2004-11-11 18:00:47 +00002225 PRE_REG_READ3(long, "mknod",
2226 const char *, pathname, int, mode, unsigned, dev);
njn22cfccb2004-11-27 16:10:23 +00002227 PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002228}
2229
sewardj696c5512005-06-08 23:38:32 +00002230PRE(sys_flock)
2231{
2232 *flags |= SfMayBlock;
2233 PRINT("sys_flock ( %d, %d )", ARG1, ARG2 );
2234 PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2235}
2236
2237/* This surely isn't remotely generic -- move to linux-specifics? */
2238PRE(sys_init_module)
2239{
2240 *flags |= SfMayBlock;
2241 PRINT("sys_init_module ( %p, %llu, %p )", ARG1, (ULong)ARG2, ARG3 );
2242 PRE_REG_READ3(long, "init_module",
2243 void *, umod, unsigned long, len, const char *, uargs);
2244 PRE_MEM_READ( "init_module(umod)", ARG1, ARG2 );
2245 PRE_MEM_RASCIIZ( "init_module(uargs)", ARG3 );
2246}
2247
nethercotea81e9162004-02-12 14:34:14 +00002248// Pre_read a char** argument.
sewardjb5f6f512005-03-10 23:59:00 +00002249static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
nethercotea81e9162004-02-12 14:34:14 +00002250{
2251 while (True) {
njnb249fd72004-11-29 14:24:57 +00002252 Addr a_deref;
2253 Addr* a_p = (Addr*)a;
2254 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2255 a_deref = *a_p;
nethercotea81e9162004-02-12 14:34:14 +00002256 if (0 == a_deref)
2257 break;
nethercoteef0c7662004-11-06 15:38:43 +00002258 PRE_MEM_RASCIIZ( s2, a_deref );
nethercotea81e9162004-02-12 14:34:14 +00002259 a += sizeof(char*);
2260 }
2261}
2262
njn7b85dd52005-06-12 17:26:29 +00002263static Bool i_am_the_only_thread ( void )
2264{
2265 Int c = VG_(count_living_threads)();
2266 vg_assert(c >= 1); /* stay sane */
2267 return c == 1;
2268}
2269
2270/* Wait until all other threads disappear. */
2271void VG_(reap_threads)(ThreadId self)
2272{
2273 while (!i_am_the_only_thread()) {
2274 /* Let other thread(s) run */
2275 VG_(vg_yield)();
2276 VG_(poll_signals)(self);
2277 }
2278 vg_assert(i_am_the_only_thread());
2279}
2280
nethercote7310afb2004-11-12 15:41:06 +00002281// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2282// but it seems to work nonetheless...
sewardja8d8e232005-06-07 20:04:56 +00002283PRE(sys_execve)
jsgf855d93d2003-10-13 22:26:55 +00002284{
sewardj45f4e7c2005-09-27 19:20:21 +00002285 Char* path = NULL; /* path to executable */
tom13696cc2005-07-18 23:23:03 +00002286 Char** envp = NULL;
sewardj45f4e7c2005-09-27 19:20:21 +00002287 Char** argv = NULL;
2288 Char** arg2copy;
2289 Char* launcher_basename = NULL;
sewardja8d8e232005-06-07 20:04:56 +00002290 ThreadState* tst;
sewardj45f4e7c2005-09-27 19:20:21 +00002291 Int i, j, tot_args;
njn73750612005-10-14 03:11:30 +00002292 SysRes res;
sewardjb5f6f512005-03-10 23:59:00 +00002293
njn22cfccb2004-11-27 16:10:23 +00002294 PRINT("sys_execve ( %p(%s), %p, %p )", ARG1, ARG1, ARG2, ARG3);
nethercote7310afb2004-11-12 15:41:06 +00002295 PRE_REG_READ3(vki_off_t, "execve",
2296 char *, filename, char **, argv, char **, envp);
njn22cfccb2004-11-27 16:10:23 +00002297 PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
2298 if (ARG2 != 0)
2299 pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
2300 if (ARG3 != 0)
2301 pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
fitzhardingee1c06d82003-10-30 07:21:44 +00002302
sewardja8d8e232005-06-07 20:04:56 +00002303 vg_assert(VG_(is_valid_tid)(tid));
2304 tst = VG_(get_ThreadState)(tid);
2305
fitzhardingee1c06d82003-10-30 07:21:44 +00002306 /* Erk. If the exec fails, then the following will have made a
2307 mess of things which makes it hard for us to continue. The
2308 right thing to do is piece everything together again in
sewardj45f4e7c2005-09-27 19:20:21 +00002309 POST(execve), but that's close to impossible. Instead, we make
2310 an effort to check that the execve will work before actually
2311 doing it. */
fitzhardingee1c06d82003-10-30 07:21:44 +00002312
njn73750612005-10-14 03:11:30 +00002313 /* Check that the name at least begins in client-accessible storage. */
sewardj45f4e7c2005-09-27 19:20:21 +00002314 if (!VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
2315 SET_STATUS_Failure( VKI_EFAULT );
2316 return;
2317 }
2318
njn73750612005-10-14 03:11:30 +00002319 // Do the important checks: it is a file, is executable, permissions are
2320 // ok, etc.
2321 res = VG_(pre_exec_check)((const Char*)ARG1, NULL);
2322 if (res.isError) {
2323 SET_STATUS_Failure( res.val );
2324 return;
2325 }
2326
sewardj98e68a42005-10-04 23:07:33 +00002327 /* If we're tracing the child, and the launcher name looks bogus
2328 (possibly because launcher.c couldn't figure it out, see
2329 comments therein) then we have no option but to fail. */
2330 if (VG_(clo_trace_children)
2331 && (VG_(name_of_launcher) == NULL
2332 || VG_(name_of_launcher)[0] != '/')) {
2333 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2334 return;
2335 }
2336
sewardj45f4e7c2005-09-27 19:20:21 +00002337 /* After this point, we can't recover if the execve fails. */
2338 VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
2339
fitzhardingee1c06d82003-10-30 07:21:44 +00002340 /* Resistance is futile. Nuke all other threads. POSIX mandates
2341 this. (Really, nuke them all, since the new process will make
2342 its own new thread.) */
sewardjb5f6f512005-03-10 23:59:00 +00002343 VG_(nuke_all_threads_except)( tid, VgSrc_ExitSyscall );
njn7b85dd52005-06-12 17:26:29 +00002344 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002345
sewardj45f4e7c2005-09-27 19:20:21 +00002346 // Set up the child's exe path.
2347 //
2348 if (VG_(clo_trace_children)) {
2349
2350 // We want to exec the launcher. Get its pre-remembered path.
2351 path = VG_(name_of_launcher);
2352 // VG_(name_of_launcher) should have been acquired by m_main at
2353 // startup.
2354 vg_assert(path);
2355
2356 launcher_basename = VG_(strrchr)(path, '/');
2357 if (launcher_basename == NULL || launcher_basename[1] == 0) {
2358 launcher_basename = path; // hmm, tres dubious
2359 } else {
2360 launcher_basename++;
2361 }
2362
2363 } else {
2364 path = (Char*)ARG1;
2365 }
2366
2367 // Set up the child's environment.
2368 //
tom4e136952005-07-18 14:02:11 +00002369 // Remove the valgrind-specific stuff from the environment so the
njn7b4e5ba2005-08-25 22:53:57 +00002370 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
tom4e136952005-07-18 14:02:11 +00002371 // This is done unconditionally, since if we are tracing the child,
sewardj45f4e7c2005-09-27 19:20:21 +00002372 // the child valgrind will set up the appropriate client environment.
njn11106992005-07-18 14:10:12 +00002373 // Nb: we make a copy of the environment before trying to mangle it
2374 // as it might be in read-only memory (this was bug #101881).
sewardj45f4e7c2005-09-27 19:20:21 +00002375 //
2376 // Then, if tracing the child, set VALGRIND_LIB for it.
2377 //
2378 if (ARG3 == 0) {
2379 envp = NULL;
2380 } else {
tom13696cc2005-07-18 23:23:03 +00002381 envp = VG_(env_clone)( (Char**)ARG3 );
sewardj45f4e7c2005-09-27 19:20:21 +00002382 if (envp == NULL) goto hosed;
tom4e136952005-07-18 14:02:11 +00002383 VG_(env_remove_valgrind_env_stuff)( envp );
fitzhardinge5408c062004-01-04 23:52:59 +00002384 }
2385
2386 if (VG_(clo_trace_children)) {
sewardj45f4e7c2005-09-27 19:20:21 +00002387 // Set VALGRIND_LIB in ARG3 (the environment)
2388 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
fitzhardinge98abfc72003-12-16 02:05:15 +00002389 }
2390
sewardj45f4e7c2005-09-27 19:20:21 +00002391 // Set up the child's args. If not tracing it, they are
2392 // simply ARG2. Otherwise, they are
2393 //
2394 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
2395 //
2396 // except that the first VG_(args_for_valgrind_noexecpass) args
2397 // are omitted.
2398 //
2399 if (!VG_(clo_trace_children)) {
2400 argv = (Char**)ARG2;
2401 } else {
2402 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2403 vg_assert( VG_(args_for_valgrind_noexecpass)
2404 <= VG_(args_for_valgrind).used );
2405 /* how many args in total will there be? */
2406 // launcher basename
2407 tot_args = 1;
2408 // V's args
2409 tot_args += VG_(args_for_valgrind).used;
2410 tot_args -= VG_(args_for_valgrind_noexecpass);
2411 // name of client exe
2412 tot_args++;
2413 // args for client exe, skipping [0]
2414 arg2copy = (Char**)ARG2;
2415 if (arg2copy && arg2copy[0]) {
2416 for (i = 1; arg2copy[i]; i++)
2417 tot_args++;
2418 }
2419 // allocate
2420 argv = VG_(malloc)( (tot_args+1) * sizeof(HChar*) );
2421 if (argv == 0) goto hosed;
2422 // copy
2423 j = 0;
2424 argv[j++] = launcher_basename;
2425 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
2426 if (i < VG_(args_for_valgrind_noexecpass))
2427 continue;
2428 argv[j++] = VG_(args_for_valgrind).strs[i];
2429 }
2430 argv[j++] = (Char*)ARG1;
2431 if (arg2copy && arg2copy[0])
2432 for (i = 1; arg2copy[i]; i++)
2433 argv[j++] = arg2copy[i];
2434 argv[j++] = NULL;
2435 // check
2436 vg_assert(j == tot_args+1);
jsgf855d93d2003-10-13 22:26:55 +00002437 }
jsgf855d93d2003-10-13 22:26:55 +00002438
sewardjb5f6f512005-03-10 23:59:00 +00002439 /* restore the DATA rlimit for the child */
2440 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2441
2442 /*
2443 Set the signal state up for exec.
2444
2445 We need to set the real signal state to make sure the exec'd
2446 process gets SIG_IGN properly.
2447
2448 Also set our real sigmask to match the client's sigmask so that
2449 the exec'd child will get the right mask. First we need to
2450 clear out any pending signals so they they don't get delivered,
2451 which would confuse things.
fitzhardingef0dd7e12004-01-16 02:17:30 +00002452
2453 XXX This is a bug - the signals should remain pending, and be
2454 delivered to the new process after exec. There's also a
2455 race-condition, since if someone delivers us a signal between
2456 the sigprocmask and the execve, we'll still get the signal. Oh
2457 well.
2458 */
2459 {
nethercote73b526f2004-10-31 18:48:21 +00002460 vki_sigset_t allsigs;
2461 vki_siginfo_t info;
fitzhardingef0dd7e12004-01-16 02:17:30 +00002462 static const struct vki_timespec zero = { 0, 0 };
sewardjb5f6f512005-03-10 23:59:00 +00002463
sewardj45f4e7c2005-09-27 19:20:21 +00002464 for (i = 1; i < VG_(max_signal); i++) {
sewardjb5f6f512005-03-10 23:59:00 +00002465 struct vki_sigaction sa;
2466 VG_(do_sys_sigaction)(i, NULL, &sa);
2467 if (sa.ksa_handler == VKI_SIG_IGN)
2468 VG_(sigaction)(i, &sa, NULL);
2469 else {
2470 sa.ksa_handler = VKI_SIG_DFL;
2471 VG_(sigaction)(i, &sa, NULL);
2472 }
2473 }
2474
nethercote73b526f2004-10-31 18:48:21 +00002475 VG_(sigfillset)(&allsigs);
2476 while(VG_(sigtimedwait)(&allsigs, &info, &zero) > 0)
sewardjb5f6f512005-03-10 23:59:00 +00002477 ;
fitzhardingef0dd7e12004-01-16 02:17:30 +00002478
nethercote73b526f2004-10-31 18:48:21 +00002479 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
fitzhardingef0dd7e12004-01-16 02:17:30 +00002480 }
2481
sewardj45f4e7c2005-09-27 19:20:21 +00002482 if (0) {
2483 Char **cpp;
2484 VG_(printf)("exec: %s\n", path);
2485 for (cpp = argv; cpp && *cpp; cpp++)
2486 VG_(printf)("argv: %s\n", *cpp);
2487 if (0)
2488 for (cpp = envp; cpp && *cpp; cpp++)
2489 VG_(printf)("env: %s\n", *cpp);
2490 }
2491
sewardja8d8e232005-06-07 20:04:56 +00002492 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002493 VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
sewardja8d8e232005-06-07 20:04:56 +00002494 );
fitzhardingeb50068f2004-02-24 23:42:55 +00002495
sewardj45f4e7c2005-09-27 19:20:21 +00002496 /* If we got here, then the execve failed. We've already made way
2497 too much of a mess to continue, so we have to abort. */
2498 hosed:
tomdc294c32005-08-16 10:19:58 +00002499 vg_assert(FAILURE);
nethercotee70bd7d2004-08-18 14:37:17 +00002500 VG_(message)(Vg_UserMsg, "execve(%p(%s), %p, %p) failed, errno %d",
tomdc294c32005-08-16 10:19:58 +00002501 ARG1, ARG1, ARG2, ARG3, RES_unchecked);
sewardjb5f6f512005-03-10 23:59:00 +00002502 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
2503 "execve() failing, so I'm dying.");
sewardja8d8e232005-06-07 20:04:56 +00002504 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
sewardjb5f6f512005-03-10 23:59:00 +00002505 "or work out how to recover.");
2506 VG_(exit)(101);
jsgf855d93d2003-10-13 22:26:55 +00002507}
2508
sewardja8d8e232005-06-07 20:04:56 +00002509PRE(sys_access)
jsgf855d93d2003-10-13 22:26:55 +00002510{
njn22cfccb2004-11-27 16:10:23 +00002511 PRINT("sys_access ( %p(%s), %d )", ARG1,ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00002512 PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00002513 PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002514}
2515
sewardja8d8e232005-06-07 20:04:56 +00002516PRE(sys_alarm)
jsgf855d93d2003-10-13 22:26:55 +00002517{
njn22cfccb2004-11-27 16:10:23 +00002518 PRINT("sys_alarm ( %d )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00002519 PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
jsgf855d93d2003-10-13 22:26:55 +00002520}
2521
sewardja8d8e232005-06-07 20:04:56 +00002522PRE(sys_brk)
jsgf855d93d2003-10-13 22:26:55 +00002523{
fitzhardinge98abfc72003-12-16 02:05:15 +00002524 Addr brk_limit = VG_(brk_limit);
sewardja8d8e232005-06-07 20:04:56 +00002525 Addr brk_new;
fitzhardinge98abfc72003-12-16 02:05:15 +00002526
jsgf855d93d2003-10-13 22:26:55 +00002527 /* libc says: int brk(void *end_data_segment);
2528 kernel says: void* brk(void* end_data_segment); (more or less)
2529
2530 libc returns 0 on success, and -1 (and sets errno) on failure.
2531 Nb: if you ask to shrink the dataseg end below what it
2532 currently is, that always succeeds, even if the dataseg end
2533 doesn't actually change (eg. brk(0)). Unless it seg faults.
2534
2535 Kernel returns the new dataseg end. If the brk() failed, this
2536 will be unchanged from the old one. That's why calling (kernel)
2537 brk(0) gives the current dataseg end (libc brk() just returns
2538 zero in that case).
2539
2540 Both will seg fault if you shrink it back into a text segment.
2541 */
njn22cfccb2004-11-27 16:10:23 +00002542 PRINT("sys_brk ( %p )", ARG1);
nethercote9c311eb2004-11-12 18:20:12 +00002543 PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
jsgf855d93d2003-10-13 22:26:55 +00002544
sewardja8d8e232005-06-07 20:04:56 +00002545 brk_new = do_brk(ARG1);
2546 SET_STATUS_Success( brk_new );
fitzhardinge98abfc72003-12-16 02:05:15 +00002547
sewardja8d8e232005-06-07 20:04:56 +00002548 if (brk_new == ARG1) {
jsgf855d93d2003-10-13 22:26:55 +00002549 /* brk() succeeded */
sewardja8d8e232005-06-07 20:04:56 +00002550 if (brk_new < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002551 /* successfully shrunk the data segment. */
njn22cfccb2004-11-27 16:10:23 +00002552 VG_TRACK( die_mem_brk, (Addr)ARG1,
2553 brk_limit-ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002554 } else
sewardja8d8e232005-06-07 20:04:56 +00002555 if (brk_new > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002556 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00002557 VG_TRACK( new_mem_brk, brk_limit,
njn22cfccb2004-11-27 16:10:23 +00002558 ARG1-brk_limit );
jsgf855d93d2003-10-13 22:26:55 +00002559 }
jsgf855d93d2003-10-13 22:26:55 +00002560 } else {
2561 /* brk() failed */
sewardja8d8e232005-06-07 20:04:56 +00002562 vg_assert(brk_limit == brk_new);
jsgf855d93d2003-10-13 22:26:55 +00002563 }
2564}
2565
sewardja8d8e232005-06-07 20:04:56 +00002566PRE(sys_chdir)
jsgf855d93d2003-10-13 22:26:55 +00002567{
njn22cfccb2004-11-27 16:10:23 +00002568 PRINT("sys_chdir ( %p )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002569 PRE_REG_READ1(long, "chdir", const char *, path);
njn22cfccb2004-11-27 16:10:23 +00002570 PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002571}
2572
sewardja8d8e232005-06-07 20:04:56 +00002573PRE(sys_chmod)
jsgf855d93d2003-10-13 22:26:55 +00002574{
njn22cfccb2004-11-27 16:10:23 +00002575 PRINT("sys_chmod ( %p, %d )", ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00002576 PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
njn22cfccb2004-11-27 16:10:23 +00002577 PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002578}
2579
sewardje6d5e722005-06-10 10:27:55 +00002580PRE(sys_chown)
2581{
sewardje6d5e722005-06-10 10:27:55 +00002582 PRINT("sys_chown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
2583 PRE_REG_READ3(long, "chown",
2584 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2585 PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
2586}
2587
2588PRE(sys_lchown)
2589{
2590 PRINT("sys_lchown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
2591 PRE_REG_READ3(long, "lchown",
2592 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2593 PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
2594}
nethercote2e1c37d2004-11-13 13:57:12 +00002595
sewardja8d8e232005-06-07 20:04:56 +00002596PRE(sys_close)
jsgf855d93d2003-10-13 22:26:55 +00002597{
njn22cfccb2004-11-27 16:10:23 +00002598 PRINT("sys_close ( %d )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002599 PRE_REG_READ1(long, "close", unsigned int, fd);
2600
nethercotef8548672004-06-21 12:42:35 +00002601 /* Detect and negate attempts by the client to close Valgrind's log fd */
sewardj7eb7c582005-06-23 01:02:53 +00002602 if (!ML_(fd_allowed)(ARG1, "close", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00002603 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00002604}
2605
nethercote85a456f2004-11-16 17:31:56 +00002606POST(sys_close)
rjwalshf5f536f2003-11-17 17:45:00 +00002607{
njn22cfccb2004-11-27 16:10:23 +00002608 if (VG_(clo_track_fds)) record_fd_close(tid, ARG1);
rjwalshf5f536f2003-11-17 17:45:00 +00002609}
jsgf855d93d2003-10-13 22:26:55 +00002610
sewardja8d8e232005-06-07 20:04:56 +00002611PRE(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00002612{
njn22cfccb2004-11-27 16:10:23 +00002613 PRINT("sys_dup ( %d )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00002614 PRE_REG_READ1(long, "dup", unsigned int, oldfd);
jsgf855d93d2003-10-13 22:26:55 +00002615}
2616
nethercote85a456f2004-11-16 17:31:56 +00002617POST(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00002618{
sewardja8d8e232005-06-07 20:04:56 +00002619 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00002620 if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00002621 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00002622 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00002623 } else {
nethercote9a3beb92004-11-12 17:07:26 +00002624 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002625 record_fd_open_named(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00002626 }
2627}
2628
sewardja8d8e232005-06-07 20:04:56 +00002629PRE(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00002630{
njn22cfccb2004-11-27 16:10:23 +00002631 PRINT("sys_dup2 ( %d, %d )", ARG1,ARG2);
nethercote71f05f32004-11-12 18:49:27 +00002632 PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
sewardj7eb7c582005-06-23 01:02:53 +00002633 if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
sewardja8d8e232005-06-07 20:04:56 +00002634 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00002635}
2636
nethercote85a456f2004-11-16 17:31:56 +00002637POST(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00002638{
sewardja8d8e232005-06-07 20:04:56 +00002639 vg_assert(SUCCESS);
nethercote71f05f32004-11-12 18:49:27 +00002640 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002641 record_fd_open_named(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00002642}
2643
sewardj696c5512005-06-08 23:38:32 +00002644PRE(sys_fchdir)
2645{
2646 PRINT("sys_fchdir ( %d )", ARG1);
2647 PRE_REG_READ1(long, "fchdir", unsigned int, fd);
2648}
2649
sewardje6d5e722005-06-10 10:27:55 +00002650PRE(sys_fchown)
2651{
2652 PRINT("sys_fchown ( %d, %d, %d )", ARG1,ARG2,ARG3);
2653 PRE_REG_READ3(long, "fchown",
2654 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
2655}
sewardj696c5512005-06-08 23:38:32 +00002656
2657PRE(sys_fchmod)
2658{
2659 PRINT("sys_fchmod ( %d, %d )", ARG1,ARG2);
2660 PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
2661}
2662
2663PRE(sys_fcntl)
2664{
2665 switch (ARG2) {
2666 // These ones ignore ARG3.
2667 case VKI_F_GETFD:
2668 case VKI_F_GETFL:
2669 case VKI_F_GETOWN:
sewardj696c5512005-06-08 23:38:32 +00002670 case VKI_F_GETSIG:
sewardj696c5512005-06-08 23:38:32 +00002671 case VKI_F_GETLEASE:
2672 PRINT("sys_fcntl ( %d, %d )", ARG1,ARG2);
2673 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
2674 break;
2675
2676 // These ones use ARG3 as "arg".
2677 case VKI_F_DUPFD:
2678 case VKI_F_SETFD:
2679 case VKI_F_SETFL:
2680 case VKI_F_SETLEASE:
2681 case VKI_F_NOTIFY:
njn4ae40402005-08-24 13:55:59 +00002682 case VKI_F_SETOWN:
2683 case VKI_F_SETSIG:
sewardj696c5512005-06-08 23:38:32 +00002684 PRINT("sys_fcntl[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3);
2685 PRE_REG_READ3(long, "fcntl",
2686 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
2687 break;
2688
2689 // These ones use ARG3 as "lock".
2690 case VKI_F_GETLK:
2691 case VKI_F_SETLK:
2692 case VKI_F_SETLKW:
sewardje7aa4ae2005-06-09 12:43:42 +00002693# if defined(VGP_x86_linux)
sewardj696c5512005-06-08 23:38:32 +00002694 case VKI_F_GETLK64:
2695 case VKI_F_SETLK64:
2696 case VKI_F_SETLKW64:
2697# else
2698# endif
2699 PRINT("sys_fcntl[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3);
2700 PRE_REG_READ3(long, "fcntl",
2701 unsigned int, fd, unsigned int, cmd,
2702 struct flock64 *, lock);
2703 break;
2704 }
2705
2706 if (ARG2 == VKI_F_SETLKW)
2707 *flags |= SfMayBlock;
2708}
2709
2710POST(sys_fcntl)
2711{
2712 vg_assert(SUCCESS);
2713 if (ARG2 == VKI_F_DUPFD) {
sewardj7eb7c582005-06-23 01:02:53 +00002714 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
sewardj696c5512005-06-08 23:38:32 +00002715 VG_(close)(RES);
2716 SET_STATUS_Failure( VKI_EMFILE );
2717 } else {
2718 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002719 record_fd_open_named(tid, RES);
sewardj696c5512005-06-08 23:38:32 +00002720 }
2721 }
2722}
njncfb8ad52004-11-23 14:57:49 +00002723
nethercote06c7bd72004-11-14 19:11:56 +00002724// XXX: wrapper only suitable for 32-bit systems
sewardja8d8e232005-06-07 20:04:56 +00002725PRE(sys_fcntl64)
jsgf855d93d2003-10-13 22:26:55 +00002726{
njnc6168192004-11-29 13:54:10 +00002727 switch (ARG2) {
2728 // These ones ignore ARG3.
2729 case VKI_F_GETFD:
2730 case VKI_F_GETFL:
2731 case VKI_F_GETOWN:
2732 case VKI_F_SETOWN:
2733 case VKI_F_GETSIG:
2734 case VKI_F_SETSIG:
2735 case VKI_F_GETLEASE:
2736 PRINT("sys_fcntl64 ( %d, %d )", ARG1,ARG2);
2737 PRE_REG_READ2(long, "fcntl64", unsigned int, fd, unsigned int, cmd);
2738 break;
2739
2740 // These ones use ARG3 as "arg".
2741 case VKI_F_DUPFD:
2742 case VKI_F_SETFD:
2743 case VKI_F_SETFL:
2744 case VKI_F_SETLEASE:
2745 case VKI_F_NOTIFY:
2746 PRINT("sys_fcntl64[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3);
2747 PRE_REG_READ3(long, "fcntl64",
2748 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
2749 break;
2750
2751 // These ones use ARG3 as "lock".
2752 case VKI_F_GETLK:
2753 case VKI_F_SETLK:
2754 case VKI_F_SETLKW:
sewardje7aa4ae2005-06-09 12:43:42 +00002755# if defined(VGP_x86_linux)
njnc6168192004-11-29 13:54:10 +00002756 case VKI_F_GETLK64:
2757 case VKI_F_SETLK64:
2758 case VKI_F_SETLKW64:
sewardja8d8e232005-06-07 20:04:56 +00002759# endif
njnc6168192004-11-29 13:54:10 +00002760 PRINT("sys_fcntl64[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3);
2761 PRE_REG_READ3(long, "fcntl64",
2762 unsigned int, fd, unsigned int, cmd,
2763 struct flock64 *, lock);
2764 break;
2765 }
njncfb8ad52004-11-23 14:57:49 +00002766
sewardje7aa4ae2005-06-09 12:43:42 +00002767# if defined(VGP_x86_linux)
2768 if (ARG2 == VKI_F_SETLKW || ARG2 == VKI_F_SETLKW64)
2769 *flags |= SfMayBlock;
sewardja8d8e232005-06-07 20:04:56 +00002770# else
sewardje7aa4ae2005-06-09 12:43:42 +00002771 if (ARG2 == VKI_F_SETLKW)
2772 *flags |= SfMayBlock;
sewardja8d8e232005-06-07 20:04:56 +00002773# endif
rjwalshf5f536f2003-11-17 17:45:00 +00002774}
2775
nethercote85a456f2004-11-16 17:31:56 +00002776POST(sys_fcntl64)
rjwalshf5f536f2003-11-17 17:45:00 +00002777{
sewardja8d8e232005-06-07 20:04:56 +00002778 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002779 if (ARG2 == VKI_F_DUPFD) {
sewardj7eb7c582005-06-23 01:02:53 +00002780 if (!ML_(fd_allowed)(RES, "fcntl64(DUPFD)", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00002781 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00002782 SET_STATUS_Failure( VKI_EMFILE );
nethercote493dd182004-02-24 23:57:47 +00002783 } else {
2784 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002785 record_fd_open_named(tid, RES);
nethercote493dd182004-02-24 23:57:47 +00002786 }
2787 }
jsgf855d93d2003-10-13 22:26:55 +00002788}
2789
sewardj696c5512005-06-08 23:38:32 +00002790PRE(sys_newfstat)
2791{
2792 PRINT("sys_newfstat ( %d, %p )", ARG1,ARG2);
2793 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
2794 PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
2795}
2796
2797POST(sys_newfstat)
2798{
2799 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2800}
jsgf855d93d2003-10-13 22:26:55 +00002801
nethercote73b526f2004-10-31 18:48:21 +00002802static vki_sigset_t fork_saved_mask;
jsgf855d93d2003-10-13 22:26:55 +00002803
nethercote75a8c982004-11-11 19:03:34 +00002804// In Linux, the sys_fork() function varies across architectures, but we
2805// ignore the various args it gets, and so it looks arch-neutral. Hmm.
sewardja8d8e232005-06-07 20:04:56 +00002806PRE(sys_fork)
jsgf855d93d2003-10-13 22:26:55 +00002807{
nethercote73b526f2004-10-31 18:48:21 +00002808 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +00002809
nethercote75a8c982004-11-11 19:03:34 +00002810 PRINT("sys_fork ( )");
2811 PRE_REG_READ0(long, "fork");
2812
jsgf855d93d2003-10-13 22:26:55 +00002813 /* Block all signals during fork, so that we can fix things up in
2814 the child without being interrupted. */
nethercote73b526f2004-10-31 18:48:21 +00002815 VG_(sigfillset)(&mask);
2816 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
jsgf855d93d2003-10-13 22:26:55 +00002817
sewardja8d8e232005-06-07 20:04:56 +00002818 SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
sewardjb5f6f512005-03-10 23:59:00 +00002819
sewardja8d8e232005-06-07 20:04:56 +00002820 if (SUCCESS && RES == 0) {
sewardjb5f6f512005-03-10 23:59:00 +00002821 VG_(do_atfork_child)(tid);
jsgf855d93d2003-10-13 22:26:55 +00002822
2823 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00002824 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
sewardja8d8e232005-06-07 20:04:56 +00002825 }
2826 else
2827 if (SUCCESS && RES > 0) {
sewardjb5f6f512005-03-10 23:59:00 +00002828 PRINT(" fork: process %d created child %d\n", VG_(getpid)(), RES);
jsgf855d93d2003-10-13 22:26:55 +00002829
jsgf855d93d2003-10-13 22:26:55 +00002830 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00002831 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +00002832 }
2833}
2834
sewardj8c257322005-06-08 01:01:48 +00002835PRE(sys_ftruncate)
2836{
2837 *flags |= SfMayBlock;
njn68e46592005-08-26 19:42:27 +00002838 PRINT("sys_ftruncate ( %d, %ld )", ARG1,ARG2);
sewardj8c257322005-06-08 01:01:48 +00002839 PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
2840}
2841
sewardj696c5512005-06-08 23:38:32 +00002842PRE(sys_truncate)
2843{
2844 *flags |= SfMayBlock;
2845 PRINT("sys_truncate ( %p(%s), %d )", ARG1,ARG1,ARG2);
2846 PRE_REG_READ2(long, "truncate",
2847 const char *, path, unsigned long, length);
2848 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
2849}
2850
sewardje6d5e722005-06-10 10:27:55 +00002851// XXX: this wrapper is only suitable for 32-bit platforms
sewardj48db0f02005-10-07 13:30:48 +00002852#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardje6d5e722005-06-10 10:27:55 +00002853PRE(sys_ftruncate64)
2854{
2855 *flags |= SfMayBlock;
2856 PRINT("sys_ftruncate64 ( %d, %lld )", ARG1, LOHI64(ARG2,ARG3));
2857 PRE_REG_READ3(long, "ftruncate64",
2858 unsigned int, fd,
2859 vki_u32, length_low32, vki_u32, length_high32);
2860}
2861#endif
2862
2863// XXX: this wrapper is only suitable for 32-bit platforms
2864#if defined(VGP_x86_linux)
2865PRE(sys_truncate64)
2866{
2867 *flags |= SfMayBlock;
2868 PRINT("sys_truncate64 ( %p, %lld )", ARG1, LOHI64(ARG2, ARG3));
2869 PRE_REG_READ3(long, "truncate64",
2870 const char *, path,
2871 vki_u32, length_low32, vki_u32, length_high32);
2872 PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
2873}
2874#endif
sewardj78b50e42005-06-08 01:47:28 +00002875
2876PRE(sys_getdents)
2877{
2878 *flags |= SfMayBlock;
2879 PRINT("sys_getdents ( %d, %p, %d )", ARG1,ARG2,ARG3);
2880 PRE_REG_READ3(long, "getdents",
2881 unsigned int, fd, struct linux_dirent *, dirp,
2882 unsigned int, count);
2883 PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
2884}
2885
2886POST(sys_getdents)
2887{
2888 vg_assert(SUCCESS);
2889 if (RES > 0)
2890 POST_MEM_WRITE( ARG2, RES );
2891}
jsgf855d93d2003-10-13 22:26:55 +00002892
sewardja8d8e232005-06-07 20:04:56 +00002893PRE(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00002894{
sewardj78b50e42005-06-08 01:47:28 +00002895 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00002896 PRINT("sys_getdents64 ( %d, %p, %d )",ARG1,ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00002897 PRE_REG_READ3(long, "getdents64",
2898 unsigned int, fd, struct linux_dirent64 *, dirp,
2899 unsigned int, count);
njn22cfccb2004-11-27 16:10:23 +00002900 PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00002901}
2902
nethercote85a456f2004-11-16 17:31:56 +00002903POST(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00002904{
sewardja8d8e232005-06-07 20:04:56 +00002905 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002906 if (RES > 0)
2907 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00002908}
2909
sewardj78b50e42005-06-08 01:47:28 +00002910PRE(sys_getgroups)
2911{
2912 PRINT("sys_getgroups ( %d, %p )", ARG1, ARG2);
2913 PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
2914 if (ARG1 > 0)
2915 PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
2916}
2917
2918POST(sys_getgroups)
2919{
2920 vg_assert(SUCCESS);
2921 if (ARG1 > 0 && RES > 0)
2922 POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
2923}
nethercote686b5db2004-11-14 13:42:51 +00002924
sewardja8d8e232005-06-07 20:04:56 +00002925PRE(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00002926{
njn4b70e8c2005-08-14 17:36:07 +00002927 // Comment from linux/fs/dcache.c:
2928 // NOTE! The user-level library version returns a character pointer.
2929 // The kernel system call just returns the length of the buffer filled
2930 // (which includes the ending '\0' character), or a negative error
2931 // value.
2932 // Is this Linux-specific? If so it should be moved to syswrap-linux.c.
njn22cfccb2004-11-27 16:10:23 +00002933 PRINT("sys_getcwd ( %p, %llu )", ARG1,(ULong)ARG2);
nethercoteac866b92004-11-15 20:23:15 +00002934 PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
njn22cfccb2004-11-27 16:10:23 +00002935 PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00002936}
2937
nethercote85a456f2004-11-16 17:31:56 +00002938POST(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00002939{
sewardja8d8e232005-06-07 20:04:56 +00002940 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002941 if (RES != (Addr)NULL)
2942 POST_MEM_WRITE( ARG1, RES );
jsgf855d93d2003-10-13 22:26:55 +00002943}
2944
sewardja8d8e232005-06-07 20:04:56 +00002945PRE(sys_geteuid)
jsgf855d93d2003-10-13 22:26:55 +00002946{
nethercote0df495a2004-11-11 16:38:21 +00002947 PRINT("sys_geteuid ( )");
2948 PRE_REG_READ0(long, "geteuid");
jsgf855d93d2003-10-13 22:26:55 +00002949}
2950
sewardj78b50e42005-06-08 01:47:28 +00002951PRE(sys_getegid)
2952{
2953 PRINT("sys_getegid ( )");
2954 PRE_REG_READ0(long, "getegid");
2955}
2956
sewardj78b50e42005-06-08 01:47:28 +00002957PRE(sys_getgid)
2958{
2959 PRINT("sys_getgid ( )");
2960 PRE_REG_READ0(long, "getgid");
2961}
jsgf855d93d2003-10-13 22:26:55 +00002962
sewardja8d8e232005-06-07 20:04:56 +00002963PRE(sys_getpid)
jsgf855d93d2003-10-13 22:26:55 +00002964{
nethercote4e632c22004-11-09 16:45:33 +00002965 PRINT("sys_getpid ()");
2966 PRE_REG_READ0(long, "getpid");
jsgf855d93d2003-10-13 22:26:55 +00002967}
2968
sewardj696c5512005-06-08 23:38:32 +00002969PRE(sys_getpgid)
2970{
2971 PRINT("sys_getpgid ( %d )", ARG1);
2972 PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
2973}
sewardj78b50e42005-06-08 01:47:28 +00002974
2975PRE(sys_getpgrp)
2976{
2977 PRINT("sys_getpgrp ()");
2978 PRE_REG_READ0(long, "getpgrp");
2979}
jsgf855d93d2003-10-13 22:26:55 +00002980
sewardja8d8e232005-06-07 20:04:56 +00002981PRE(sys_getppid)
jsgf855d93d2003-10-13 22:26:55 +00002982{
nethercote4e632c22004-11-09 16:45:33 +00002983 PRINT("sys_getppid ()");
2984 PRE_REG_READ0(long, "getppid");
jsgf855d93d2003-10-13 22:26:55 +00002985}
2986
njncf45fd42004-11-24 16:30:22 +00002987static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
jsgf855d93d2003-10-13 22:26:55 +00002988{
nethercote620154f2004-11-12 21:21:07 +00002989 POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00002990
nethercote620154f2004-11-12 21:21:07 +00002991 switch (a1) {
2992 case VKI_RLIMIT_NOFILE:
2993 ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
2994 ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
2995 break;
nethercote535f03b2004-02-15 15:32:51 +00002996
nethercote620154f2004-11-12 21:21:07 +00002997 case VKI_RLIMIT_DATA:
2998 *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
2999 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00003000
nethercote620154f2004-11-12 21:21:07 +00003001 case VKI_RLIMIT_STACK:
3002 *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3003 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00003004 }
jsgf855d93d2003-10-13 22:26:55 +00003005}
3006
sewardj696c5512005-06-08 23:38:32 +00003007PRE(sys_old_getrlimit)
3008{
3009 PRINT("sys_old_getrlimit ( %d, %p )", ARG1,ARG2);
3010 PRE_REG_READ2(long, "old_getrlimit",
3011 unsigned int, resource, struct rlimit *, rlim);
3012 PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3013}
3014
3015POST(sys_old_getrlimit)
3016{
3017 common_post_getrlimit(tid, ARG1, ARG2);
3018}
nethercote620154f2004-11-12 21:21:07 +00003019
sewardja8d8e232005-06-07 20:04:56 +00003020PRE(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003021{
njn22cfccb2004-11-27 16:10:23 +00003022 PRINT("sys_getrlimit ( %d, %p )", ARG1,ARG2);
nethercote620154f2004-11-12 21:21:07 +00003023 PRE_REG_READ2(long, "getrlimit",
3024 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00003025 PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
nethercote620154f2004-11-12 21:21:07 +00003026}
3027
nethercote85a456f2004-11-16 17:31:56 +00003028POST(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003029{
njn22cfccb2004-11-27 16:10:23 +00003030 common_post_getrlimit(tid, ARG1, ARG2);
nethercote620154f2004-11-12 21:21:07 +00003031}
jsgf855d93d2003-10-13 22:26:55 +00003032
sewardj696c5512005-06-08 23:38:32 +00003033PRE(sys_getrusage)
3034{
sewardj696c5512005-06-08 23:38:32 +00003035 PRINT("sys_getrusage ( %d, %p )", ARG1,ARG2);
3036 PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3037 PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3038}
3039
3040POST(sys_getrusage)
3041{
3042 vg_assert(SUCCESS);
3043 if (RES == 0)
3044 POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3045}
jsgf855d93d2003-10-13 22:26:55 +00003046
sewardja8d8e232005-06-07 20:04:56 +00003047PRE(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003048{
njn22cfccb2004-11-27 16:10:23 +00003049 PRINT("sys_gettimeofday ( %p, %p )", ARG1,ARG2);
nethercote686b5db2004-11-14 13:42:51 +00003050 PRE_REG_READ2(long, "gettimeofday",
3051 struct timeval *, tv, struct timezone *, tz);
njn22cfccb2004-11-27 16:10:23 +00003052 PRE_MEM_WRITE( "gettimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
3053 if (ARG2 != 0)
3054 PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003055}
3056
nethercote85a456f2004-11-16 17:31:56 +00003057POST(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003058{
sewardja8d8e232005-06-07 20:04:56 +00003059 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003060 if (RES == 0) {
3061 POST_MEM_WRITE( ARG1, sizeof(struct vki_timeval) );
3062 if (ARG2 != 0)
3063 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003064 }
3065}
3066
sewardj696c5512005-06-08 23:38:32 +00003067PRE(sys_settimeofday)
3068{
3069 PRINT("sys_settimeofday ( %p, %p )", ARG1,ARG2);
3070 PRE_REG_READ2(long, "settimeofday",
3071 struct timeval *, tv, struct timezone *, tz);
3072 PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
3073 if (ARG2 != 0) {
3074 PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3075 /* maybe should warn if tz->tz_dsttime is non-zero? */
3076 }
3077}
nethercote686b5db2004-11-14 13:42:51 +00003078
sewardja8d8e232005-06-07 20:04:56 +00003079PRE(sys_getuid)
jsgf855d93d2003-10-13 22:26:55 +00003080{
nethercote0df495a2004-11-11 16:38:21 +00003081 PRINT("sys_getuid ( )");
3082 PRE_REG_READ0(long, "getuid");
jsgf855d93d2003-10-13 22:26:55 +00003083}
3084
nethercote2e1c37d2004-11-13 13:57:12 +00003085// XXX: I reckon some of these cases must be x86-specific
sewardja8d8e232005-06-07 20:04:56 +00003086PRE(sys_ioctl)
jsgf855d93d2003-10-13 22:26:55 +00003087{
sewardja8d8e232005-06-07 20:04:56 +00003088 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00003089 PRINT("sys_ioctl ( %d, 0x%x, %p )",ARG1,ARG2,ARG3);
nethercote9c311eb2004-11-12 18:20:12 +00003090 PRE_REG_READ3(long, "ioctl",
3091 unsigned int, fd, unsigned int, request, unsigned long, arg);
3092
njn22cfccb2004-11-27 16:10:23 +00003093 switch (ARG2 /* request */) {
nethercote73b526f2004-10-31 18:48:21 +00003094 case VKI_TCSETS:
3095 case VKI_TCSETSW:
3096 case VKI_TCSETSF:
njn22cfccb2004-11-27 16:10:23 +00003097 PRE_MEM_READ( "ioctl(TCSET{S,SW,SF})", ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003098 break;
nethercote73b526f2004-10-31 18:48:21 +00003099 case VKI_TCGETS:
njn22cfccb2004-11-27 16:10:23 +00003100 PRE_MEM_WRITE( "ioctl(TCGETS)", ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003101 break;
nethercote73b526f2004-10-31 18:48:21 +00003102 case VKI_TCSETA:
3103 case VKI_TCSETAW:
3104 case VKI_TCSETAF:
njn22cfccb2004-11-27 16:10:23 +00003105 PRE_MEM_READ( "ioctl(TCSET{A,AW,AF})", ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003106 break;
nethercote73b526f2004-10-31 18:48:21 +00003107 case VKI_TCGETA:
njn22cfccb2004-11-27 16:10:23 +00003108 PRE_MEM_WRITE( "ioctl(TCGETA)", ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003109 break;
nethercote73b526f2004-10-31 18:48:21 +00003110 case VKI_TCSBRK:
3111 case VKI_TCXONC:
3112 case VKI_TCSBRKP:
3113 case VKI_TCFLSH:
jsgf855d93d2003-10-13 22:26:55 +00003114 /* These just take an int by value */
3115 break;
nethercote73b526f2004-10-31 18:48:21 +00003116 case VKI_TIOCGWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003117 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003118 break;
nethercote73b526f2004-10-31 18:48:21 +00003119 case VKI_TIOCSWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003120 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003121 break;
nethercote73b526f2004-10-31 18:48:21 +00003122 case VKI_TIOCMBIS:
njn22cfccb2004-11-27 16:10:23 +00003123 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003124 break;
nethercote73b526f2004-10-31 18:48:21 +00003125 case VKI_TIOCMBIC:
njn22cfccb2004-11-27 16:10:23 +00003126 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003127 break;
nethercote73b526f2004-10-31 18:48:21 +00003128 case VKI_TIOCMSET:
njn22cfccb2004-11-27 16:10:23 +00003129 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003130 break;
tom62ba7582005-07-28 16:26:34 +00003131 case VKI_TIOCMGET:
3132 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
3133 break;
nethercote73b526f2004-10-31 18:48:21 +00003134 case VKI_TIOCLINUX:
njn22cfccb2004-11-27 16:10:23 +00003135 PRE_MEM_READ( "ioctl(TIOCLINUX)", ARG3, sizeof(char *) );
3136 if (*(char *)ARG3 == 11) {
3137 PRE_MEM_READ( "ioctl(TIOCLINUX, 11)", ARG3, 2 * sizeof(char *) );
jsgf855d93d2003-10-13 22:26:55 +00003138 }
3139 break;
nethercote73b526f2004-10-31 18:48:21 +00003140 case VKI_TIOCGPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003141 /* Get process group ID for foreground processing group. */
njn22cfccb2004-11-27 16:10:23 +00003142 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003143 break;
nethercote73b526f2004-10-31 18:48:21 +00003144 case VKI_TIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003145 /* Set a process group ID? */
njn22cfccb2004-11-27 16:10:23 +00003146 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003147 break;
nethercote73b526f2004-10-31 18:48:21 +00003148 case VKI_TIOCGPTN: /* Get Pty Number (of pty-mux device) */
njn22cfccb2004-11-27 16:10:23 +00003149 PRE_MEM_WRITE( "ioctl(TIOCGPTN)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003150 break;
nethercote73b526f2004-10-31 18:48:21 +00003151 case VKI_TIOCSCTTY:
jsgf855d93d2003-10-13 22:26:55 +00003152 /* Just takes an int value. */
3153 break;
nethercote73b526f2004-10-31 18:48:21 +00003154 case VKI_TIOCSPTLCK: /* Lock/unlock Pty */
njn22cfccb2004-11-27 16:10:23 +00003155 PRE_MEM_READ( "ioctl(TIOCSPTLCK)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003156 break;
nethercote73b526f2004-10-31 18:48:21 +00003157 case VKI_FIONBIO:
njn22cfccb2004-11-27 16:10:23 +00003158 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003159 break;
nethercote73b526f2004-10-31 18:48:21 +00003160 case VKI_FIOASYNC:
njn22cfccb2004-11-27 16:10:23 +00003161 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003162 break;
nethercote73b526f2004-10-31 18:48:21 +00003163 case VKI_FIONREAD: /* identical to SIOCINQ */
njn22cfccb2004-11-27 16:10:23 +00003164 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003165 break;
3166
nethercote73b526f2004-10-31 18:48:21 +00003167 case VKI_SG_SET_COMMAND_Q:
njn22cfccb2004-11-27 16:10:23 +00003168 PRE_MEM_READ( "ioctl(SG_SET_COMMAND_Q)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003169 break;
nethercote73b526f2004-10-31 18:48:21 +00003170 case VKI_SG_IO:
njn22cfccb2004-11-27 16:10:23 +00003171 PRE_MEM_WRITE( "ioctl(SG_IO)", ARG3, sizeof(vki_sg_io_hdr_t) );
jsgf855d93d2003-10-13 22:26:55 +00003172 break;
nethercote73b526f2004-10-31 18:48:21 +00003173 case VKI_SG_GET_SCSI_ID:
njn22cfccb2004-11-27 16:10:23 +00003174 PRE_MEM_WRITE( "ioctl(SG_GET_SCSI_ID)", ARG3, sizeof(vki_sg_scsi_id_t) );
jsgf855d93d2003-10-13 22:26:55 +00003175 break;
nethercote73b526f2004-10-31 18:48:21 +00003176 case VKI_SG_SET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003177 PRE_MEM_READ( "ioctl(SG_SET_RESERVED_SIZE)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003178 break;
nethercote73b526f2004-10-31 18:48:21 +00003179 case VKI_SG_SET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003180 PRE_MEM_READ( "ioctl(SG_SET_TIMEOUT)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003181 break;
nethercote73b526f2004-10-31 18:48:21 +00003182 case VKI_SG_GET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003183 PRE_MEM_WRITE( "ioctl(SG_GET_RESERVED_SIZE)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003184 break;
nethercote73b526f2004-10-31 18:48:21 +00003185 case VKI_SG_GET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003186 PRE_MEM_WRITE( "ioctl(SG_GET_TIMEOUT)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003187 break;
nethercote73b526f2004-10-31 18:48:21 +00003188 case VKI_SG_GET_VERSION_NUM:
njn22cfccb2004-11-27 16:10:23 +00003189 PRE_MEM_READ( "ioctl(SG_GET_VERSION_NUM)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003190 break;
nethercote73b526f2004-10-31 18:48:21 +00003191 case VKI_SG_EMULATED_HOST: /* 0x2203 */
njn22cfccb2004-11-27 16:10:23 +00003192 PRE_MEM_WRITE( "ioctl(SG_EMULATED_HOST)", ARG3, sizeof(int) );
thughes5b788fb2004-09-11 15:07:14 +00003193 break;
nethercote73b526f2004-10-31 18:48:21 +00003194 case VKI_SG_GET_SG_TABLESIZE: /* 0x227f */
njn22cfccb2004-11-27 16:10:23 +00003195 PRE_MEM_WRITE( "ioctl(SG_GET_SG_TABLESIZE)", ARG3, sizeof(int) );
thughes5b788fb2004-09-11 15:07:14 +00003196 break;
jsgf855d93d2003-10-13 22:26:55 +00003197
muellera4b153a2003-11-19 22:07:14 +00003198 case VKI_IIOCGETCPS:
njn22cfccb2004-11-27 16:10:23 +00003199 PRE_MEM_WRITE( "ioctl(IIOCGETCPS)", ARG3,
nethercote95a97862004-11-06 16:31:43 +00003200 VKI_ISDN_MAX_CHANNELS * 2 * sizeof(unsigned long) );
jsgf855d93d2003-10-13 22:26:55 +00003201 break;
muellera4b153a2003-11-19 22:07:14 +00003202 case VKI_IIOCNETGPN:
nethercoteef0c7662004-11-06 15:38:43 +00003203 PRE_MEM_READ( "ioctl(IIOCNETGPN)",
njn22cfccb2004-11-27 16:10:23 +00003204 (Addr)&((vki_isdn_net_ioctl_phone *)ARG3)->name,
3205 sizeof(((vki_isdn_net_ioctl_phone *)ARG3)->name) );
3206 PRE_MEM_WRITE( "ioctl(IIOCNETGPN)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003207 sizeof(vki_isdn_net_ioctl_phone) );
jsgf855d93d2003-10-13 22:26:55 +00003208 break;
3209
3210 /* These all use struct ifreq AFAIK */
nethercote73b526f2004-10-31 18:48:21 +00003211 case VKI_SIOCGIFINDEX: /* get iface index */
nethercoteef0c7662004-11-06 15:38:43 +00003212 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFINDEX)",
njn22cfccb2004-11-27 16:10:23 +00003213 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3214 PRE_MEM_WRITE( "ioctl(SIOCGIFINDEX)", ARG3, sizeof(struct vki_ifreq));
jsgf855d93d2003-10-13 22:26:55 +00003215 break;
nethercote73b526f2004-10-31 18:48:21 +00003216 case VKI_SIOCGIFFLAGS: /* get flags */
nethercoteef0c7662004-11-06 15:38:43 +00003217 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003218 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3219 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003220 break;
nethercote73b526f2004-10-31 18:48:21 +00003221 case VKI_SIOCGIFHWADDR: /* Get hardware address */
nethercoteef0c7662004-11-06 15:38:43 +00003222 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003223 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3224 PRE_MEM_WRITE( "ioctl(SIOCGIFHWADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003225 break;
nethercote73b526f2004-10-31 18:48:21 +00003226 case VKI_SIOCGIFMTU: /* get MTU size */
nethercoteef0c7662004-11-06 15:38:43 +00003227 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003228 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3229 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003230 break;
nethercote73b526f2004-10-31 18:48:21 +00003231 case VKI_SIOCGIFADDR: /* get PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003232 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
njn22cfccb2004-11-27 16:10:23 +00003233 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3234 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003235 break;
nethercote73b526f2004-10-31 18:48:21 +00003236 case VKI_SIOCGIFNETMASK: /* get network PA mask */
nethercoteef0c7662004-11-06 15:38:43 +00003237 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
njn22cfccb2004-11-27 16:10:23 +00003238 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3239 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003240 break;
nethercote73b526f2004-10-31 18:48:21 +00003241 case VKI_SIOCGIFMETRIC: /* get metric */
nethercoteef0c7662004-11-06 15:38:43 +00003242 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003243 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3244 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003245 break;
nethercote73b526f2004-10-31 18:48:21 +00003246 case VKI_SIOCGIFMAP: /* Get device parameters */
nethercoteef0c7662004-11-06 15:38:43 +00003247 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003248 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3249 PRE_MEM_WRITE( "ioctl(SIOCGIFMAP)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003250 break;
nethercote73b526f2004-10-31 18:48:21 +00003251 case VKI_SIOCGIFTXQLEN: /* Get the tx queue length */
nethercoteef0c7662004-11-06 15:38:43 +00003252 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003253 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3254 PRE_MEM_WRITE( "ioctl(SIOCGIFTXQLEN)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003255 break;
nethercote73b526f2004-10-31 18:48:21 +00003256 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003257 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
njn22cfccb2004-11-27 16:10:23 +00003258 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3259 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003260 break;
nethercote73b526f2004-10-31 18:48:21 +00003261 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003262 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
njn22cfccb2004-11-27 16:10:23 +00003263 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3264 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003265 break;
nethercote73b526f2004-10-31 18:48:21 +00003266 case VKI_SIOCGIFNAME: /* get iface name */
nethercoteef0c7662004-11-06 15:38:43 +00003267 PRE_MEM_READ( "ioctl(SIOCGIFNAME)",
tom3b86ae52005-07-29 18:42:22 +00003268 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_ifindex,
njn22cfccb2004-11-27 16:10:23 +00003269 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_ifindex) );
3270 PRE_MEM_WRITE( "ioctl(SIOCGIFNAME)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003271 break;
nethercote73b526f2004-10-31 18:48:21 +00003272 case VKI_SIOCGMIIPHY: /* get hardware entry */
nethercoteef0c7662004-11-06 15:38:43 +00003273 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMIIPHY)",
njn22cfccb2004-11-27 16:10:23 +00003274 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3275 PRE_MEM_WRITE( "ioctl(SIOCGIFMIIPHY)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003276 break;
nethercote73b526f2004-10-31 18:48:21 +00003277 case VKI_SIOCGMIIREG: /* get hardware entry registers */
nethercoteef0c7662004-11-06 15:38:43 +00003278 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003279 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003280 PRE_MEM_READ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003281 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
3282 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
nethercoteef0c7662004-11-06 15:38:43 +00003283 PRE_MEM_READ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003284 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num,
3285 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num) );
3286 PRE_MEM_WRITE( "ioctl(SIOCGIFMIIREG)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003287 sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003288 break;
nethercote73b526f2004-10-31 18:48:21 +00003289 case VKI_SIOCGIFCONF: /* get iface list */
jsgf855d93d2003-10-13 22:26:55 +00003290 /* WAS:
njn22cfccb2004-11-27 16:10:23 +00003291 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
3292 KERNEL_DO_SYSCALL(tid,RES);
3293 if (!VG_(is_kerror)(RES) && RES == 0)
3294 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
jsgf855d93d2003-10-13 22:26:55 +00003295 */
tomb9fef192005-07-18 22:45:55 +00003296 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
3297 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
3298 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
3299 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
3300 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
3301 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
njn22cfccb2004-11-27 16:10:23 +00003302 if ( ARG3 ) {
jsgf855d93d2003-10-13 22:26:55 +00003303 // TODO len must be readable and writable
3304 // buf pointer only needs to be readable
njn22cfccb2004-11-27 16:10:23 +00003305 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00003306 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
nethercote50397c22004-11-04 18:03:06 +00003307 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
jsgf855d93d2003-10-13 22:26:55 +00003308 }
3309 break;
nethercote73b526f2004-10-31 18:48:21 +00003310 case VKI_SIOCGSTAMP:
njn22cfccb2004-11-27 16:10:23 +00003311 PRE_MEM_WRITE( "ioctl(SIOCGSTAMP)", ARG3, sizeof(struct vki_timeval));
jsgf855d93d2003-10-13 22:26:55 +00003312 break;
3313 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3314 the number of bytes currently in that socket's send buffer.
3315 It writes this value as an int to the memory location
3316 indicated by the third argument of ioctl(2). */
nethercote73b526f2004-10-31 18:48:21 +00003317 case VKI_SIOCOUTQ:
njn22cfccb2004-11-27 16:10:23 +00003318 PRE_MEM_WRITE( "ioctl(SIOCOUTQ)", ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003319 break;
nethercote73b526f2004-10-31 18:48:21 +00003320 case VKI_SIOCGRARP: /* get RARP table entry */
3321 case VKI_SIOCGARP: /* get ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00003322 PRE_MEM_WRITE( "ioctl(SIOCGARP)", ARG3, sizeof(struct vki_arpreq));
jsgf855d93d2003-10-13 22:26:55 +00003323 break;
3324
nethercote73b526f2004-10-31 18:48:21 +00003325 case VKI_SIOCSIFFLAGS: /* set flags */
nethercoteef0c7662004-11-06 15:38:43 +00003326 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003327 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003328 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003329 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
3330 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
thughesbe811712004-06-17 23:04:58 +00003331 break;
nethercote73b526f2004-10-31 18:48:21 +00003332 case VKI_SIOCSIFMAP: /* Set device parameters */
nethercoteef0c7662004-11-06 15:38:43 +00003333 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003334 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003335 PRE_MEM_READ( "ioctl(SIOCSIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003336 (Addr)&((struct vki_ifreq *)ARG3)->ifr_map,
3337 sizeof(((struct vki_ifreq *)ARG3)->ifr_map) );
thughesbe811712004-06-17 23:04:58 +00003338 break;
nethercote73b526f2004-10-31 18:48:21 +00003339 case VKI_SIOCSIFTXQLEN: /* Set the tx queue length */
nethercoteef0c7662004-11-06 15:38:43 +00003340 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003341 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003342 PRE_MEM_READ( "ioctl(SIOCSIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003343 (Addr)&((struct vki_ifreq *)ARG3)->ifr_qlen,
3344 sizeof(((struct vki_ifreq *)ARG3)->ifr_qlen) );
thughesbe811712004-06-17 23:04:58 +00003345 break;
nethercote73b526f2004-10-31 18:48:21 +00003346 case VKI_SIOCSIFADDR: /* set PA address */
3347 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
3348 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
3349 case VKI_SIOCSIFNETMASK: /* set network PA mask */
nethercoteef0c7662004-11-06 15:38:43 +00003350 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
njn22cfccb2004-11-27 16:10:23 +00003351 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003352 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
njn22cfccb2004-11-27 16:10:23 +00003353 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
3354 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
jsgf855d93d2003-10-13 22:26:55 +00003355 break;
nethercote73b526f2004-10-31 18:48:21 +00003356 case VKI_SIOCSIFMETRIC: /* set metric */
nethercoteef0c7662004-11-06 15:38:43 +00003357 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003358 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003359 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003360 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
3361 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
thughesbe811712004-06-17 23:04:58 +00003362 break;
nethercote73b526f2004-10-31 18:48:21 +00003363 case VKI_SIOCSIFMTU: /* set MTU size */
nethercoteef0c7662004-11-06 15:38:43 +00003364 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003365 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003366 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003367 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
3368 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
thughesbe811712004-06-17 23:04:58 +00003369 break;
nethercote73b526f2004-10-31 18:48:21 +00003370 case VKI_SIOCSIFHWADDR: /* set hardware address */
nethercoteef0c7662004-11-06 15:38:43 +00003371 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003372 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003373 PRE_MEM_READ( "ioctl(SIOCSIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003374 (Addr)&((struct vki_ifreq *)ARG3)->ifr_hwaddr,
3375 sizeof(((struct vki_ifreq *)ARG3)->ifr_hwaddr) );
thughesbe811712004-06-17 23:04:58 +00003376 break;
nethercote73b526f2004-10-31 18:48:21 +00003377 case VKI_SIOCSMIIREG: /* set hardware entry registers */
nethercoteef0c7662004-11-06 15:38:43 +00003378 PRE_MEM_RASCIIZ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003379 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003380 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003381 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
3382 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
nethercoteef0c7662004-11-06 15:38:43 +00003383 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003384 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num,
3385 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num) );
nethercoteef0c7662004-11-06 15:38:43 +00003386 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003387 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_in,
3388 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_in) );
thughesbe811712004-06-17 23:04:58 +00003389 break;
jsgf855d93d2003-10-13 22:26:55 +00003390 /* Routing table calls. */
nethercote73b526f2004-10-31 18:48:21 +00003391 case VKI_SIOCADDRT: /* add routing table entry */
3392 case VKI_SIOCDELRT: /* delete routing table entry */
njn22cfccb2004-11-27 16:10:23 +00003393 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
nethercoteef0c7662004-11-06 15:38:43 +00003394 sizeof(struct vki_rtentry));
jsgf855d93d2003-10-13 22:26:55 +00003395 break;
3396
3397 /* RARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00003398 case VKI_SIOCDRARP: /* delete RARP table entry */
3399 case VKI_SIOCSRARP: /* set RARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00003400 /* ARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00003401 case VKI_SIOCSARP: /* set ARP table entry */
3402 case VKI_SIOCDARP: /* delete ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00003403 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
jsgf855d93d2003-10-13 22:26:55 +00003404 break;
3405
nethercote73b526f2004-10-31 18:48:21 +00003406 case VKI_SIOCGPGRP:
njn22cfccb2004-11-27 16:10:23 +00003407 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
thughes1174fed2004-09-11 15:33:17 +00003408 break;
nethercote73b526f2004-10-31 18:48:21 +00003409 case VKI_SIOCSPGRP:
njn22cfccb2004-11-27 16:10:23 +00003410 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
sewardja8d8e232005-06-07 20:04:56 +00003411 //tst->sys_flags &= ~SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00003412 break;
3413
3414 /* linux/soundcard interface (OSS) */
nethercote73b526f2004-10-31 18:48:21 +00003415 case VKI_SNDCTL_SEQ_GETOUTCOUNT:
3416 case VKI_SNDCTL_SEQ_GETINCOUNT:
3417 case VKI_SNDCTL_SEQ_PERCMODE:
3418 case VKI_SNDCTL_SEQ_TESTMIDI:
3419 case VKI_SNDCTL_SEQ_RESETSAMPLES:
3420 case VKI_SNDCTL_SEQ_NRSYNTHS:
3421 case VKI_SNDCTL_SEQ_NRMIDIS:
3422 case VKI_SNDCTL_SEQ_GETTIME:
3423 case VKI_SNDCTL_DSP_GETFMTS:
3424 case VKI_SNDCTL_DSP_GETTRIGGER:
3425 case VKI_SNDCTL_DSP_GETODELAY:
nethercote73b526f2004-10-31 18:48:21 +00003426 case VKI_SNDCTL_DSP_GETSPDIF:
nethercote73b526f2004-10-31 18:48:21 +00003427 case VKI_SNDCTL_DSP_GETCAPS:
3428 case VKI_SOUND_PCM_READ_RATE:
3429 case VKI_SOUND_PCM_READ_CHANNELS:
3430 case VKI_SOUND_PCM_READ_BITS:
cerion85665ca2005-06-20 15:51:07 +00003431#if !defined(VGA_ppc32)
nethercote73b526f2004-10-31 18:48:21 +00003432 case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
cerion85665ca2005-06-20 15:51:07 +00003433#endif
nethercote73b526f2004-10-31 18:48:21 +00003434 case VKI_SOUND_PCM_READ_FILTER:
nethercoteef0c7662004-11-06 15:38:43 +00003435 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
njn22cfccb2004-11-27 16:10:23 +00003436 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003437 break;
nethercote73b526f2004-10-31 18:48:21 +00003438 case VKI_SNDCTL_SEQ_CTRLRATE:
3439 case VKI_SNDCTL_DSP_SPEED:
3440 case VKI_SNDCTL_DSP_STEREO:
3441 case VKI_SNDCTL_DSP_GETBLKSIZE:
3442 case VKI_SNDCTL_DSP_CHANNELS:
3443 case VKI_SOUND_PCM_WRITE_FILTER:
3444 case VKI_SNDCTL_DSP_SUBDIVIDE:
3445 case VKI_SNDCTL_DSP_SETFRAGMENT:
nethercote73b526f2004-10-31 18:48:21 +00003446 case VKI_SNDCTL_DSP_GETCHANNELMASK:
nethercote73b526f2004-10-31 18:48:21 +00003447 case VKI_SNDCTL_DSP_BIND_CHANNEL:
nethercote73b526f2004-10-31 18:48:21 +00003448 case VKI_SNDCTL_TMR_TIMEBASE:
3449 case VKI_SNDCTL_TMR_TEMPO:
3450 case VKI_SNDCTL_TMR_SOURCE:
3451 case VKI_SNDCTL_MIDI_PRETIME:
3452 case VKI_SNDCTL_MIDI_MPUMODE:
nethercoteef0c7662004-11-06 15:38:43 +00003453 PRE_MEM_READ( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOWR, int))",
njn22cfccb2004-11-27 16:10:23 +00003454 ARG3, sizeof(int));
nethercoteef0c7662004-11-06 15:38:43 +00003455 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOWR, int))",
njn22cfccb2004-11-27 16:10:23 +00003456 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003457 break;
nethercote73b526f2004-10-31 18:48:21 +00003458 case VKI_SNDCTL_DSP_GETOSPACE:
3459 case VKI_SNDCTL_DSP_GETISPACE:
nethercoteef0c7662004-11-06 15:38:43 +00003460 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, audio_buf_info))",
njn22cfccb2004-11-27 16:10:23 +00003461 ARG3, sizeof(vki_audio_buf_info));
jsgf855d93d2003-10-13 22:26:55 +00003462 break;
nethercote73b526f2004-10-31 18:48:21 +00003463 case VKI_SNDCTL_DSP_SETTRIGGER:
nethercoteef0c7662004-11-06 15:38:43 +00003464 PRE_MEM_READ( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
njn22cfccb2004-11-27 16:10:23 +00003465 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003466 break;
3467
nethercote73b526f2004-10-31 18:48:21 +00003468 case VKI_SNDCTL_DSP_POST:
3469 case VKI_SNDCTL_DSP_RESET:
3470 case VKI_SNDCTL_DSP_SYNC:
3471 case VKI_SNDCTL_DSP_SETSYNCRO:
3472 case VKI_SNDCTL_DSP_SETDUPLEX:
jsgf855d93d2003-10-13 22:26:55 +00003473 break;
3474
3475 /* Real Time Clock (/dev/rtc) ioctls */
nethercote73b526f2004-10-31 18:48:21 +00003476 case VKI_RTC_UIE_ON:
3477 case VKI_RTC_UIE_OFF:
3478 case VKI_RTC_AIE_ON:
3479 case VKI_RTC_AIE_OFF:
3480 case VKI_RTC_PIE_ON:
3481 case VKI_RTC_PIE_OFF:
3482 case VKI_RTC_IRQP_SET:
jsgf855d93d2003-10-13 22:26:55 +00003483 break;
nethercote73b526f2004-10-31 18:48:21 +00003484 case VKI_RTC_RD_TIME:
3485 case VKI_RTC_ALM_READ:
nethercoteef0c7662004-11-06 15:38:43 +00003486 PRE_MEM_WRITE( "ioctl(RTC_RD_TIME/ALM_READ)",
njn22cfccb2004-11-27 16:10:23 +00003487 ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00003488 break;
nethercote73b526f2004-10-31 18:48:21 +00003489 case VKI_RTC_ALM_SET:
njn22cfccb2004-11-27 16:10:23 +00003490 PRE_MEM_READ( "ioctl(RTC_ALM_SET)", ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00003491 break;
nethercote73b526f2004-10-31 18:48:21 +00003492 case VKI_RTC_IRQP_READ:
njn22cfccb2004-11-27 16:10:23 +00003493 PRE_MEM_WRITE( "ioctl(RTC_IRQP_READ)", ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003494 break;
jsgf855d93d2003-10-13 22:26:55 +00003495
tomeafc49b2005-07-28 16:08:09 +00003496 /* Block devices */
3497 case VKI_BLKROSET:
3498 PRE_MEM_READ( "ioctl(BLKROSET)", ARG3, sizeof(int));
3499 break;
3500 case VKI_BLKROGET:
3501 PRE_MEM_WRITE( "ioctl(BLKROGET)", ARG3, sizeof(int));
3502 break;
nethercote95a97862004-11-06 16:31:43 +00003503 case VKI_BLKGETSIZE:
njn22cfccb2004-11-27 16:10:23 +00003504 PRE_MEM_WRITE( "ioctl(BLKGETSIZE)", ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003505 break;
tomeafc49b2005-07-28 16:08:09 +00003506 case VKI_BLKRASET:
3507 break;
3508 case VKI_BLKRAGET:
3509 PRE_MEM_WRITE( "ioctl(BLKRAGET)", ARG3, sizeof(long));
3510 break;
3511 case VKI_BLKFRASET:
3512 break;
3513 case VKI_BLKFRAGET:
3514 PRE_MEM_WRITE( "ioctl(BLKFRAGET)", ARG3, sizeof(long));
3515 break;
3516 case VKI_BLKSECTGET:
3517 PRE_MEM_WRITE( "ioctl(BLKSECTGET)", ARG3, sizeof(unsigned short));
3518 break;
3519 case VKI_BLKSSZGET:
3520 PRE_MEM_WRITE( "ioctl(BLKSSZGET)", ARG3, sizeof(int));
3521 break;
3522 case VKI_BLKBSZGET:
3523 PRE_MEM_WRITE( "ioctl(BLKBSZGET)", ARG3, sizeof(int));
3524 break;
3525 case VKI_BLKBSZSET:
3526 PRE_MEM_READ( "ioctl(BLKBSZSET)", ARG3, sizeof(int));
3527 break;
tomd6555642005-07-18 13:26:55 +00003528 case VKI_BLKGETSIZE64:
3529 PRE_MEM_WRITE( "ioctl(BLKGETSIZE64)", ARG3, sizeof(unsigned long long));
3530 break;
jsgf855d93d2003-10-13 22:26:55 +00003531
thughesacbbc322004-06-19 12:12:01 +00003532 /* Hard disks */
tom2c2bc252005-07-28 16:13:42 +00003533 case VKI_HDIO_GETGEO: /* 0x0301 */
3534 PRE_MEM_WRITE( "ioctl(HDIO_GETGEO)", ARG3, sizeof(struct vki_hd_geometry));
3535 break;
nethercote73b526f2004-10-31 18:48:21 +00003536 case VKI_HDIO_GET_IDENTITY: /* 0x030d */
njn22cfccb2004-11-27 16:10:23 +00003537 PRE_MEM_WRITE( "ioctl(HDIO_GET_IDENTITY)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003538 VKI_SIZEOF_STRUCT_HD_DRIVEID );
thughesacbbc322004-06-19 12:12:01 +00003539 break;
3540
jsgf855d93d2003-10-13 22:26:55 +00003541 /* CD ROM stuff (??) */
nethercote73b526f2004-10-31 18:48:21 +00003542 case VKI_CDROM_GET_MCN:
njn22cfccb2004-11-27 16:10:23 +00003543 PRE_MEM_READ( "ioctl(CDROM_GET_MCN)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003544 sizeof(struct vki_cdrom_mcn) );
nethercote671398c2004-02-22 18:08:04 +00003545 break;
nethercote73b526f2004-10-31 18:48:21 +00003546 case VKI_CDROM_SEND_PACKET:
njn22cfccb2004-11-27 16:10:23 +00003547 PRE_MEM_READ( "ioctl(CDROM_SEND_PACKET)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003548 sizeof(struct vki_cdrom_generic_command));
nethercote671398c2004-02-22 18:08:04 +00003549 break;
nethercote73b526f2004-10-31 18:48:21 +00003550 case VKI_CDROMSUBCHNL:
nethercote11e07d32004-11-06 16:17:52 +00003551 PRE_MEM_READ( "ioctl(CDROMSUBCHNL (cdsc_format, char))",
njn22cfccb2004-11-27 16:10:23 +00003552 (Addr) &(((struct vki_cdrom_subchnl*) ARG3)->cdsc_format),
3553 sizeof(((struct vki_cdrom_subchnl*) ARG3)->cdsc_format));
3554 PRE_MEM_WRITE( "ioctl(CDROMSUBCHNL)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003555 sizeof(struct vki_cdrom_subchnl));
jsgf855d93d2003-10-13 22:26:55 +00003556 break;
nethercote73b526f2004-10-31 18:48:21 +00003557 case VKI_CDROMREADMODE2:
njn22cfccb2004-11-27 16:10:23 +00003558 PRE_MEM_READ( "ioctl(CDROMREADMODE2)", ARG3, VKI_CD_FRAMESIZE_RAW0 );
nethercote671398c2004-02-22 18:08:04 +00003559 break;
nethercote73b526f2004-10-31 18:48:21 +00003560 case VKI_CDROMREADTOCHDR:
njn22cfccb2004-11-27 16:10:23 +00003561 PRE_MEM_WRITE( "ioctl(CDROMREADTOCHDR)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003562 sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00003563 break;
nethercote73b526f2004-10-31 18:48:21 +00003564 case VKI_CDROMREADTOCENTRY:
nethercote11e07d32004-11-06 16:17:52 +00003565 PRE_MEM_READ( "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
njn22cfccb2004-11-27 16:10:23 +00003566 (Addr) &(((struct vki_cdrom_tocentry*) ARG3)->cdte_format),
3567 sizeof(((struct vki_cdrom_tocentry*) ARG3)->cdte_format));
nethercote11e07d32004-11-06 16:17:52 +00003568 PRE_MEM_READ( "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
njn22cfccb2004-11-27 16:10:23 +00003569 (Addr) &(((struct vki_cdrom_tocentry*) ARG3)->cdte_track),
3570 sizeof(((struct vki_cdrom_tocentry*) ARG3)->cdte_track));
3571 PRE_MEM_WRITE( "ioctl(CDROMREADTOCENTRY)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003572 sizeof(struct vki_cdrom_tocentry));
jsgf855d93d2003-10-13 22:26:55 +00003573 break;
nethercote73b526f2004-10-31 18:48:21 +00003574 case VKI_CDROMMULTISESSION: /* 0x5310 */
njn22cfccb2004-11-27 16:10:23 +00003575 PRE_MEM_WRITE( "ioctl(CDROMMULTISESSION)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003576 sizeof(struct vki_cdrom_multisession));
thughes5b788fb2004-09-11 15:07:14 +00003577 break;
nethercote73b526f2004-10-31 18:48:21 +00003578 case VKI_CDROMVOLREAD: /* 0x5313 */
njn22cfccb2004-11-27 16:10:23 +00003579 PRE_MEM_WRITE( "ioctl(CDROMVOLREAD)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003580 sizeof(struct vki_cdrom_volctrl));
thughes5b788fb2004-09-11 15:07:14 +00003581 break;
nethercote73b526f2004-10-31 18:48:21 +00003582 case VKI_CDROMREADAUDIO: /* 0x530e */
njn22cfccb2004-11-27 16:10:23 +00003583 PRE_MEM_READ( "ioctl(CDROMREADAUDIO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003584 sizeof (struct vki_cdrom_read_audio));
njn22cfccb2004-11-27 16:10:23 +00003585 if ( ARG3 ) {
thughes5b788fb2004-09-11 15:07:14 +00003586 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003587 struct vki_cdrom_read_audio *cra = (struct vki_cdrom_read_audio *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00003588 PRE_MEM_WRITE( "ioctl(CDROMREADAUDIO).buf",
3589 (Addr)(cra->buf), cra->nframes * VKI_CD_FRAMESIZE_RAW);
thughes5b788fb2004-09-11 15:07:14 +00003590 }
3591 break;
nethercote73b526f2004-10-31 18:48:21 +00003592 case VKI_CDROMPLAYMSF:
njn22cfccb2004-11-27 16:10:23 +00003593 PRE_MEM_READ( "ioctl(CDROMPLAYMSF)", ARG3, sizeof(struct vki_cdrom_msf));
jsgf855d93d2003-10-13 22:26:55 +00003594 break;
3595 /* The following two are probably bogus (should check args
3596 for readability). JRS 20021117 */
nethercote73b526f2004-10-31 18:48:21 +00003597 case VKI_CDROM_DRIVE_STATUS: /* 0x5326 */
3598 case VKI_CDROM_CLEAR_OPTIONS: /* 0x5321 */
jsgf855d93d2003-10-13 22:26:55 +00003599 break;
thughes66d80092004-06-19 12:41:05 +00003600
nethercote73b526f2004-10-31 18:48:21 +00003601 case VKI_FIGETBSZ:
njn22cfccb2004-11-27 16:10:23 +00003602 PRE_MEM_WRITE( "ioctl(FIGETBSZ)", ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003603 break;
nethercote73b526f2004-10-31 18:48:21 +00003604 case VKI_FIBMAP:
njn22cfccb2004-11-27 16:10:23 +00003605 PRE_MEM_READ( "ioctl(FIBMAP)", ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003606 break;
3607
nethercote73b526f2004-10-31 18:48:21 +00003608 case VKI_FBIOGET_VSCREENINFO: /* 0x4600 */
njn22cfccb2004-11-27 16:10:23 +00003609 PRE_MEM_WRITE( "ioctl(FBIOGET_VSCREENINFO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003610 sizeof(struct vki_fb_var_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003611 break;
nethercote73b526f2004-10-31 18:48:21 +00003612 case VKI_FBIOGET_FSCREENINFO: /* 0x4602 */
njn22cfccb2004-11-27 16:10:23 +00003613 PRE_MEM_WRITE( "ioctl(FBIOGET_FSCREENINFO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003614 sizeof(struct vki_fb_fix_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003615 break;
jsgf855d93d2003-10-13 22:26:55 +00003616
nethercote73b526f2004-10-31 18:48:21 +00003617 case VKI_PPCLAIM:
3618 case VKI_PPEXCL:
3619 case VKI_PPYIELD:
3620 case VKI_PPRELEASE:
thughesd9895482004-08-16 19:46:55 +00003621 break;
nethercote73b526f2004-10-31 18:48:21 +00003622 case VKI_PPSETMODE:
njn22cfccb2004-11-27 16:10:23 +00003623 PRE_MEM_READ( "ioctl(PPSETMODE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003624 break;
nethercote73b526f2004-10-31 18:48:21 +00003625 case VKI_PPGETMODE:
njn22cfccb2004-11-27 16:10:23 +00003626 PRE_MEM_WRITE( "ioctl(PPGETMODE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003627 break;
nethercote73b526f2004-10-31 18:48:21 +00003628 case VKI_PPSETPHASE:
njn22cfccb2004-11-27 16:10:23 +00003629 PRE_MEM_READ( "ioctl(PPSETPHASE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003630 break;
nethercote73b526f2004-10-31 18:48:21 +00003631 case VKI_PPGETPHASE:
njn22cfccb2004-11-27 16:10:23 +00003632 PRE_MEM_WRITE( "ioctl(PPGETPHASE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003633 break;
nethercote73b526f2004-10-31 18:48:21 +00003634 case VKI_PPGETMODES:
njn22cfccb2004-11-27 16:10:23 +00003635 PRE_MEM_WRITE( "ioctl(PPGETMODES)", ARG3, sizeof(unsigned int) );
thughesd9895482004-08-16 19:46:55 +00003636 break;
nethercote73b526f2004-10-31 18:48:21 +00003637 case VKI_PPSETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00003638 PRE_MEM_READ( "ioctl(PPSETFLAGS)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003639 break;
nethercote73b526f2004-10-31 18:48:21 +00003640 case VKI_PPGETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00003641 PRE_MEM_WRITE( "ioctl(PPGETFLAGS)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003642 break;
nethercote73b526f2004-10-31 18:48:21 +00003643 case VKI_PPRSTATUS:
njn22cfccb2004-11-27 16:10:23 +00003644 PRE_MEM_WRITE( "ioctl(PPRSTATUS)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003645 break;
nethercote73b526f2004-10-31 18:48:21 +00003646 case VKI_PPRDATA:
njn22cfccb2004-11-27 16:10:23 +00003647 PRE_MEM_WRITE( "ioctl(PPRDATA)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003648 break;
nethercote73b526f2004-10-31 18:48:21 +00003649 case VKI_PPRCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003650 PRE_MEM_WRITE( "ioctl(PPRCONTROL)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003651 break;
nethercote73b526f2004-10-31 18:48:21 +00003652 case VKI_PPWDATA:
njn22cfccb2004-11-27 16:10:23 +00003653 PRE_MEM_READ( "ioctl(PPWDATA)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003654 break;
nethercote73b526f2004-10-31 18:48:21 +00003655 case VKI_PPWCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003656 PRE_MEM_READ( "ioctl(PPWCONTROL)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003657 break;
nethercote73b526f2004-10-31 18:48:21 +00003658 case VKI_PPFCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003659 PRE_MEM_READ( "ioctl(PPFCONTROL)", ARG3, 2 * sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003660 break;
nethercote73b526f2004-10-31 18:48:21 +00003661 case VKI_PPDATADIR:
njn22cfccb2004-11-27 16:10:23 +00003662 PRE_MEM_READ( "ioctl(PPDATADIR)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003663 break;
nethercote73b526f2004-10-31 18:48:21 +00003664 case VKI_PPNEGOT:
njn22cfccb2004-11-27 16:10:23 +00003665 PRE_MEM_READ( "ioctl(PPNEGOT)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003666 break;
nethercote73b526f2004-10-31 18:48:21 +00003667 case VKI_PPWCTLONIRQ:
njn22cfccb2004-11-27 16:10:23 +00003668 PRE_MEM_READ( "ioctl(PPWCTLONIRQ)",ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003669 break;
nethercote73b526f2004-10-31 18:48:21 +00003670 case VKI_PPCLRIRQ:
njn22cfccb2004-11-27 16:10:23 +00003671 PRE_MEM_WRITE( "ioctl(PPCLRIRQ)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003672 break;
nethercote73b526f2004-10-31 18:48:21 +00003673 case VKI_PPSETTIME:
njn22cfccb2004-11-27 16:10:23 +00003674 PRE_MEM_READ( "ioctl(PPSETTIME)", ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00003675 break;
nethercote73b526f2004-10-31 18:48:21 +00003676 case VKI_PPGETTIME:
njn22cfccb2004-11-27 16:10:23 +00003677 PRE_MEM_WRITE( "ioctl(PPGETTIME)", ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00003678 break;
3679
thughesb3d3bcf2004-11-13 00:36:15 +00003680 case VKI_GIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00003681 PRE_MEM_WRITE( "ioctl(GIO_FONT)", ARG3, 32 * 256 );
thughesb3d3bcf2004-11-13 00:36:15 +00003682 break;
3683 case VKI_PIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00003684 PRE_MEM_READ( "ioctl(PIO_FONT)", ARG3, 32 * 256 );
thughesb3d3bcf2004-11-13 00:36:15 +00003685 break;
3686
3687 case VKI_GIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00003688 PRE_MEM_READ( "ioctl(GIO_FONTX)", ARG3, sizeof(struct vki_consolefontdesc) );
3689 if ( ARG3 ) {
thughesb3d3bcf2004-11-13 00:36:15 +00003690 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003691 struct vki_consolefontdesc *cfd = (struct vki_consolefontdesc *)ARG3;
thughesb3d3bcf2004-11-13 00:36:15 +00003692 PRE_MEM_WRITE( "ioctl(GIO_FONTX).chardata", (Addr)cfd->chardata,
3693 32 * cfd->charcount );
3694 }
3695 break;
3696 case VKI_PIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00003697 PRE_MEM_READ( "ioctl(PIO_FONTX)", ARG3, sizeof(struct vki_consolefontdesc) );
3698 if ( ARG3 ) {
thughesb3d3bcf2004-11-13 00:36:15 +00003699 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003700 struct vki_consolefontdesc *cfd = (struct vki_consolefontdesc *)ARG3;
thughesb3d3bcf2004-11-13 00:36:15 +00003701 PRE_MEM_READ( "ioctl(PIO_FONTX).chardata", (Addr)cfd->chardata,
3702 32 * cfd->charcount );
3703 }
3704 break;
3705
3706 case VKI_PIO_FONTRESET:
3707 break;
3708
3709 case VKI_GIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00003710 PRE_MEM_WRITE( "ioctl(GIO_CMAP)", ARG3, 16 * 3 );
thughesb3d3bcf2004-11-13 00:36:15 +00003711 break;
3712 case VKI_PIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00003713 PRE_MEM_READ( "ioctl(PIO_CMAP)", ARG3, 16 * 3 );
thughesb3d3bcf2004-11-13 00:36:15 +00003714 break;
3715
3716 case VKI_KIOCSOUND:
3717 case VKI_KDMKTONE:
3718 break;
3719
3720 case VKI_KDGETLED:
njn22cfccb2004-11-27 16:10:23 +00003721 PRE_MEM_WRITE( "ioctl(KDGETLED)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003722 break;
3723 case VKI_KDSETLED:
3724 break;
3725
3726 case VKI_KDGKBTYPE:
njn22cfccb2004-11-27 16:10:23 +00003727 PRE_MEM_WRITE( "ioctl(KDGKBTYPE)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003728 break;
3729
3730 case VKI_KDADDIO:
3731 case VKI_KDDELIO:
3732 case VKI_KDENABIO:
3733 case VKI_KDDISABIO:
3734 break;
3735
3736 case VKI_KDSETMODE:
3737 break;
3738 case VKI_KDGETMODE:
njn22cfccb2004-11-27 16:10:23 +00003739 PRE_MEM_WRITE( "ioctl(KDGETMODE)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003740 break;
3741
3742 case VKI_KDMAPDISP:
3743 case VKI_KDUNMAPDISP:
3744 break;
3745
3746 case VKI_GIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003747 PRE_MEM_WRITE( "ioctl(GIO_SCRNMAP)", ARG3, VKI_E_TABSZ );
thughesb3d3bcf2004-11-13 00:36:15 +00003748 break;
3749 case VKI_PIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003750 PRE_MEM_READ( "ioctl(PIO_SCRNMAP)", ARG3, VKI_E_TABSZ );
thughesb3d3bcf2004-11-13 00:36:15 +00003751 break;
3752 case VKI_GIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003753 PRE_MEM_WRITE( "ioctl(GIO_UNISCRNMAP)", ARG3,
thughesb3d3bcf2004-11-13 00:36:15 +00003754 VKI_E_TABSZ * sizeof(unsigned short) );
3755 break;
3756 case VKI_PIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003757 PRE_MEM_READ( "ioctl(PIO_UNISCRNMAP)", ARG3,
thughesb3d3bcf2004-11-13 00:36:15 +00003758 VKI_E_TABSZ * sizeof(unsigned short) );
3759 break;
3760
3761 case VKI_KDGKBMODE:
njn22cfccb2004-11-27 16:10:23 +00003762 PRE_MEM_WRITE( "ioctl(KDGKBMODE)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003763 break;
3764 case VKI_KDSKBMODE:
3765 break;
3766
3767 case VKI_KDGKBMETA:
njn22cfccb2004-11-27 16:10:23 +00003768 PRE_MEM_WRITE( "ioctl(KDGKBMETA)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003769 break;
3770 case VKI_KDSKBMETA:
3771 break;
3772
3773 case VKI_KDGKBLED:
njn22cfccb2004-11-27 16:10:23 +00003774 PRE_MEM_WRITE( "ioctl(KDGKBLED)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003775 break;
3776 case VKI_KDSKBLED:
3777 break;
3778
3779 case VKI_KDGKBENT:
3780 PRE_MEM_READ( "ioctl(KDGKBENT).kb_table",
njn22cfccb2004-11-27 16:10:23 +00003781 (Addr)&((struct vki_kbentry *)ARG3)->kb_table,
3782 sizeof(((struct vki_kbentry *)ARG3)->kb_table) );
thughesb3d3bcf2004-11-13 00:36:15 +00003783 PRE_MEM_READ( "ioctl(KDGKBENT).kb_index",
njn22cfccb2004-11-27 16:10:23 +00003784 (Addr)&((struct vki_kbentry *)ARG3)->kb_index,
3785 sizeof(((struct vki_kbentry *)ARG3)->kb_index) );
thughesb3d3bcf2004-11-13 00:36:15 +00003786 PRE_MEM_WRITE( "ioctl(KDGKBENT).kb_value",
njn22cfccb2004-11-27 16:10:23 +00003787 (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
3788 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesb3d3bcf2004-11-13 00:36:15 +00003789 break;
3790 case VKI_KDSKBENT:
3791 PRE_MEM_READ( "ioctl(KDSKBENT).kb_table",
njn22cfccb2004-11-27 16:10:23 +00003792 (Addr)&((struct vki_kbentry *)ARG3)->kb_table,
3793 sizeof(((struct vki_kbentry *)ARG3)->kb_table) );
thughesb3d3bcf2004-11-13 00:36:15 +00003794 PRE_MEM_READ( "ioctl(KDSKBENT).kb_index",
njn22cfccb2004-11-27 16:10:23 +00003795 (Addr)&((struct vki_kbentry *)ARG3)->kb_index,
3796 sizeof(((struct vki_kbentry *)ARG3)->kb_index) );
thughesb3d3bcf2004-11-13 00:36:15 +00003797 PRE_MEM_READ( "ioctl(KDSKBENT).kb_value",
njn22cfccb2004-11-27 16:10:23 +00003798 (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
3799 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesb3d3bcf2004-11-13 00:36:15 +00003800 break;
3801
3802 case VKI_KDGKBSENT:
3803 PRE_MEM_READ( "ioctl(KDGKBSENT).kb_func",
njn22cfccb2004-11-27 16:10:23 +00003804 (Addr)&((struct vki_kbsentry *)ARG3)->kb_func,
3805 sizeof(((struct vki_kbsentry *)ARG3)->kb_func) );
thughesb3d3bcf2004-11-13 00:36:15 +00003806 PRE_MEM_WRITE( "ioctl(KDGKSENT).kb_string",
njn22cfccb2004-11-27 16:10:23 +00003807 (Addr)((struct vki_kbsentry *)ARG3)->kb_string,
3808 sizeof(((struct vki_kbsentry *)ARG3)->kb_string) );
thughesb3d3bcf2004-11-13 00:36:15 +00003809 break;
3810 case VKI_KDSKBSENT:
3811 PRE_MEM_READ( "ioctl(KDSKBSENT).kb_func",
njn22cfccb2004-11-27 16:10:23 +00003812 (Addr)&((struct vki_kbsentry *)ARG3)->kb_func,
3813 sizeof(((struct vki_kbsentry *)ARG3)->kb_func) );
thughesb3d3bcf2004-11-13 00:36:15 +00003814 PRE_MEM_RASCIIZ( "ioctl(KDSKBSENT).kb_string",
njn22cfccb2004-11-27 16:10:23 +00003815 (Addr)((struct vki_kbsentry *)ARG3)->kb_string );
thughesb3d3bcf2004-11-13 00:36:15 +00003816 break;
3817
3818 case VKI_KDGKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00003819 PRE_MEM_WRITE( "ioctl(KDGKBDIACR)", ARG3, sizeof(struct vki_kbdiacrs) );
thughesb3d3bcf2004-11-13 00:36:15 +00003820 break;
3821 case VKI_KDSKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00003822 PRE_MEM_READ( "ioctl(KDSKBDIACR)", ARG3, sizeof(struct vki_kbdiacrs) );
thughesb3d3bcf2004-11-13 00:36:15 +00003823 break;
3824
3825 case VKI_KDGETKEYCODE:
3826 PRE_MEM_READ( "ioctl(KDGETKEYCODE).scancode",
njn22cfccb2004-11-27 16:10:23 +00003827 (Addr)&((struct vki_kbkeycode *)ARG3)->scancode,
3828 sizeof(((struct vki_kbkeycode *)ARG3)->scancode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003829 PRE_MEM_WRITE( "ioctl(KDGETKEYCODE).keycode",
njn22cfccb2004-11-27 16:10:23 +00003830 (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
3831 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003832 break;
3833 case VKI_KDSETKEYCODE:
3834 PRE_MEM_READ( "ioctl(KDSETKEYCODE).scancode",
njn22cfccb2004-11-27 16:10:23 +00003835 (Addr)&((struct vki_kbkeycode *)ARG3)->scancode,
3836 sizeof(((struct vki_kbkeycode *)ARG3)->scancode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003837 PRE_MEM_READ( "ioctl(KDSETKEYCODE).keycode",
njn22cfccb2004-11-27 16:10:23 +00003838 (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
3839 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003840 break;
3841
3842 case VKI_KDSIGACCEPT:
3843 break;
3844
3845 case VKI_KDKBDREP:
njn22cfccb2004-11-27 16:10:23 +00003846 PRE_MEM_READ( "ioctl(KBKBDREP)", ARG3, sizeof(struct vki_kbd_repeat) );
thughesb3d3bcf2004-11-13 00:36:15 +00003847 break;
3848
jsgf855d93d2003-10-13 22:26:55 +00003849 /* We don't have any specific information on it, so
3850 try to do something reasonable based on direction and
3851 size bits. The encoding scheme is described in
3852 /usr/include/asm/ioctl.h.
3853
3854 According to Simon Hausmann, _IOC_READ means the kernel
3855 writes a value to the ioctl value passed from the user
3856 space and the other way around with _IOC_WRITE. */
3857 default: {
njn22cfccb2004-11-27 16:10:23 +00003858 UInt dir = _VKI_IOC_DIR(ARG2);
3859 UInt size = _VKI_IOC_SIZE(ARG2);
sewardj19617ae2005-10-20 01:09:57 +00003860 if (VG_(strstr)(VG_(clo_simulation_hints), "lax-ioctls") != NULL) {
jsgf855d93d2003-10-13 22:26:55 +00003861 /*
3862 * Be very lax about ioctl handling; the only
3863 * assumption is that the size is correct. Doesn't
3864 * require the full buffer to be initialized when
3865 * writing. Without this, using some device
3866 * drivers with a large number of strange ioctl
3867 * commands becomes very tiresome.
3868 */
nethercote73b526f2004-10-31 18:48:21 +00003869 } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
jsgf855d93d2003-10-13 22:26:55 +00003870 static Int moans = 3;
sewardj1fa7d2c2005-06-13 18:22:17 +00003871 if (moans > 0 && !VG_(clo_xml)) {
jsgf855d93d2003-10-13 22:26:55 +00003872 moans--;
3873 VG_(message)(Vg_UserMsg,
3874 "Warning: noted but unhandled ioctl 0x%x"
3875 " with no size/direction hints",
njn22cfccb2004-11-27 16:10:23 +00003876 ARG2);
jsgf855d93d2003-10-13 22:26:55 +00003877 VG_(message)(Vg_UserMsg,
3878 " This could cause spurious value errors"
3879 " to appear.");
3880 VG_(message)(Vg_UserMsg,
3881 " See README_MISSING_SYSCALL_OR_IOCTL for "
3882 "guidance on writing a proper wrapper." );
3883 }
3884 } else {
nethercote73b526f2004-10-31 18:48:21 +00003885 if ((dir & _VKI_IOC_WRITE) && size > 0)
njn22cfccb2004-11-27 16:10:23 +00003886 PRE_MEM_READ( "ioctl(generic)", ARG3, size);
nethercote73b526f2004-10-31 18:48:21 +00003887 if ((dir & _VKI_IOC_READ) && size > 0)
njn22cfccb2004-11-27 16:10:23 +00003888 PRE_MEM_WRITE( "ioctl(generic)", ARG3, size);
jsgf855d93d2003-10-13 22:26:55 +00003889 }
3890 break;
3891 }
3892 }
3893}
3894
nethercote85a456f2004-11-16 17:31:56 +00003895POST(sys_ioctl)
jsgf855d93d2003-10-13 22:26:55 +00003896{
sewardja8d8e232005-06-07 20:04:56 +00003897 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003898 switch (ARG2 /* request */) {
nethercote73b526f2004-10-31 18:48:21 +00003899 case VKI_TCSETS:
3900 case VKI_TCSETSW:
3901 case VKI_TCSETSF:
jsgf855d93d2003-10-13 22:26:55 +00003902 break;
nethercote73b526f2004-10-31 18:48:21 +00003903 case VKI_TCGETS:
njn22cfccb2004-11-27 16:10:23 +00003904 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003905 break;
nethercote73b526f2004-10-31 18:48:21 +00003906 case VKI_TCSETA:
3907 case VKI_TCSETAW:
3908 case VKI_TCSETAF:
jsgf855d93d2003-10-13 22:26:55 +00003909 break;
nethercote73b526f2004-10-31 18:48:21 +00003910 case VKI_TCGETA:
njn22cfccb2004-11-27 16:10:23 +00003911 POST_MEM_WRITE( ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003912 break;
nethercote73b526f2004-10-31 18:48:21 +00003913 case VKI_TCSBRK:
3914 case VKI_TCXONC:
3915 case VKI_TCSBRKP:
3916 case VKI_TCFLSH:
jsgf855d93d2003-10-13 22:26:55 +00003917 break;
nethercote73b526f2004-10-31 18:48:21 +00003918 case VKI_TIOCGWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003919 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003920 break;
nethercote73b526f2004-10-31 18:48:21 +00003921 case VKI_TIOCSWINSZ:
3922 case VKI_TIOCMBIS:
3923 case VKI_TIOCMBIC:
3924 case VKI_TIOCMSET:
jsgf855d93d2003-10-13 22:26:55 +00003925 break;
tom62ba7582005-07-28 16:26:34 +00003926 case VKI_TIOCMGET:
3927 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
3928 break;
nethercote73b526f2004-10-31 18:48:21 +00003929 case VKI_TIOCLINUX:
njn22cfccb2004-11-27 16:10:23 +00003930 POST_MEM_WRITE( ARG3, sizeof(char *) );
jsgf855d93d2003-10-13 22:26:55 +00003931 break;
nethercote73b526f2004-10-31 18:48:21 +00003932 case VKI_TIOCGPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003933 /* Get process group ID for foreground processing group. */
njn22cfccb2004-11-27 16:10:23 +00003934 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003935 break;
nethercote73b526f2004-10-31 18:48:21 +00003936 case VKI_TIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003937 /* Set a process group ID? */
njn22cfccb2004-11-27 16:10:23 +00003938 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003939 break;
nethercote73b526f2004-10-31 18:48:21 +00003940 case VKI_TIOCGPTN: /* Get Pty Number (of pty-mux device) */
njn22cfccb2004-11-27 16:10:23 +00003941 POST_MEM_WRITE( ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003942 break;
nethercote73b526f2004-10-31 18:48:21 +00003943 case VKI_TIOCSCTTY:
jsgf855d93d2003-10-13 22:26:55 +00003944 break;
nethercote73b526f2004-10-31 18:48:21 +00003945 case VKI_TIOCSPTLCK: /* Lock/unlock Pty */
jsgf855d93d2003-10-13 22:26:55 +00003946 break;
nethercote73b526f2004-10-31 18:48:21 +00003947 case VKI_FIONBIO:
jsgf855d93d2003-10-13 22:26:55 +00003948 break;
nethercote73b526f2004-10-31 18:48:21 +00003949 case VKI_FIOASYNC:
jsgf855d93d2003-10-13 22:26:55 +00003950 break;
nethercote73b526f2004-10-31 18:48:21 +00003951 case VKI_FIONREAD: /* identical to SIOCINQ */
njn22cfccb2004-11-27 16:10:23 +00003952 POST_MEM_WRITE( ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003953 break;
3954
nethercote73b526f2004-10-31 18:48:21 +00003955 case VKI_SG_SET_COMMAND_Q:
jsgf855d93d2003-10-13 22:26:55 +00003956 break;
nethercote73b526f2004-10-31 18:48:21 +00003957 case VKI_SG_IO:
njn22cfccb2004-11-27 16:10:23 +00003958 POST_MEM_WRITE(ARG3, sizeof(vki_sg_io_hdr_t));
jsgf855d93d2003-10-13 22:26:55 +00003959 break;
nethercote73b526f2004-10-31 18:48:21 +00003960 case VKI_SG_GET_SCSI_ID:
njn22cfccb2004-11-27 16:10:23 +00003961 POST_MEM_WRITE(ARG3, sizeof(vki_sg_scsi_id_t));
jsgf855d93d2003-10-13 22:26:55 +00003962 break;
nethercote73b526f2004-10-31 18:48:21 +00003963 case VKI_SG_SET_RESERVED_SIZE:
jsgf855d93d2003-10-13 22:26:55 +00003964 break;
nethercote73b526f2004-10-31 18:48:21 +00003965 case VKI_SG_SET_TIMEOUT:
jsgf855d93d2003-10-13 22:26:55 +00003966 break;
nethercote73b526f2004-10-31 18:48:21 +00003967 case VKI_SG_GET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003968 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003969 break;
nethercote73b526f2004-10-31 18:48:21 +00003970 case VKI_SG_GET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003971 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003972 break;
nethercote73b526f2004-10-31 18:48:21 +00003973 case VKI_SG_GET_VERSION_NUM:
jsgf855d93d2003-10-13 22:26:55 +00003974 break;
nethercote73b526f2004-10-31 18:48:21 +00003975 case VKI_SG_EMULATED_HOST:
njn22cfccb2004-11-27 16:10:23 +00003976 POST_MEM_WRITE(ARG3, sizeof(int));
thughes5b788fb2004-09-11 15:07:14 +00003977 break;
nethercote73b526f2004-10-31 18:48:21 +00003978 case VKI_SG_GET_SG_TABLESIZE:
njn22cfccb2004-11-27 16:10:23 +00003979 POST_MEM_WRITE(ARG3, sizeof(int));
thughes5b788fb2004-09-11 15:07:14 +00003980 break;
jsgf855d93d2003-10-13 22:26:55 +00003981
muellera4b153a2003-11-19 22:07:14 +00003982 case VKI_IIOCGETCPS:
njn22cfccb2004-11-27 16:10:23 +00003983 POST_MEM_WRITE( ARG3, VKI_ISDN_MAX_CHANNELS * 2 * sizeof(unsigned long) );
jsgf855d93d2003-10-13 22:26:55 +00003984 break;
muellera4b153a2003-11-19 22:07:14 +00003985 case VKI_IIOCNETGPN:
njn22cfccb2004-11-27 16:10:23 +00003986 POST_MEM_WRITE( ARG3, sizeof(vki_isdn_net_ioctl_phone) );
jsgf855d93d2003-10-13 22:26:55 +00003987 break;
3988
3989 /* These all use struct ifreq AFAIK */
nethercote73b526f2004-10-31 18:48:21 +00003990 case VKI_SIOCGIFINDEX: /* get iface index */
njn22cfccb2004-11-27 16:10:23 +00003991 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_ifindex,
3992 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_ifindex) );
thughesbe811712004-06-17 23:04:58 +00003993 break;
nethercote73b526f2004-10-31 18:48:21 +00003994 case VKI_SIOCGIFFLAGS: /* get flags */
njn22cfccb2004-11-27 16:10:23 +00003995 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
3996 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
thughesbe811712004-06-17 23:04:58 +00003997 break;
nethercote73b526f2004-10-31 18:48:21 +00003998 case VKI_SIOCGIFHWADDR: /* Get hardware address */
njn22cfccb2004-11-27 16:10:23 +00003999 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->ifr_hwaddr,
4000 sizeof(((struct vki_ifreq *)ARG3)->ifr_hwaddr) );
thughesbe811712004-06-17 23:04:58 +00004001 break;
nethercote73b526f2004-10-31 18:48:21 +00004002 case VKI_SIOCGIFMTU: /* get MTU size */
njn22cfccb2004-11-27 16:10:23 +00004003 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
4004 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
thughesbe811712004-06-17 23:04:58 +00004005 break;
nethercote73b526f2004-10-31 18:48:21 +00004006 case VKI_SIOCGIFADDR: /* get PA address */
4007 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
4008 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
4009 case VKI_SIOCGIFNETMASK: /* get network PA mask */
njncf45fd42004-11-24 16:30:22 +00004010 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004011 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
4012 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
thughesbe811712004-06-17 23:04:58 +00004013 break;
nethercote73b526f2004-10-31 18:48:21 +00004014 case VKI_SIOCGIFMETRIC: /* get metric */
njncf45fd42004-11-24 16:30:22 +00004015 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004016 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
4017 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
thughesbe811712004-06-17 23:04:58 +00004018 break;
nethercote73b526f2004-10-31 18:48:21 +00004019 case VKI_SIOCGIFMAP: /* Get device parameters */
njncf45fd42004-11-24 16:30:22 +00004020 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004021 (Addr)&((struct vki_ifreq *)ARG3)->ifr_map,
4022 sizeof(((struct vki_ifreq *)ARG3)->ifr_map) );
thughesbe811712004-06-17 23:04:58 +00004023 break;
4024 break;
nethercote73b526f2004-10-31 18:48:21 +00004025 case VKI_SIOCGIFTXQLEN: /* Get the tx queue length */
njncf45fd42004-11-24 16:30:22 +00004026 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004027 (Addr)&((struct vki_ifreq *)ARG3)->ifr_qlen,
4028 sizeof(((struct vki_ifreq *)ARG3)->ifr_qlen) );
thughesbe811712004-06-17 23:04:58 +00004029 break;
nethercote73b526f2004-10-31 18:48:21 +00004030 case VKI_SIOCGIFNAME: /* get iface name */
njncf45fd42004-11-24 16:30:22 +00004031 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004032 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_name,
4033 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_name) );
jsgf855d93d2003-10-13 22:26:55 +00004034 break;
nethercote73b526f2004-10-31 18:48:21 +00004035 case VKI_SIOCGMIIPHY: /* get hardware entry */
njncf45fd42004-11-24 16:30:22 +00004036 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004037 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
4038 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
thughesbe811712004-06-17 23:04:58 +00004039 break;
nethercote73b526f2004-10-31 18:48:21 +00004040 case VKI_SIOCGMIIREG: /* get hardware entry registers */
njncf45fd42004-11-24 16:30:22 +00004041 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004042 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_out,
4043 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_out) );
thughesbe811712004-06-17 23:04:58 +00004044 break;
nethercote73b526f2004-10-31 18:48:21 +00004045 case VKI_SIOCGIFCONF: /* get iface list */
jsgf855d93d2003-10-13 22:26:55 +00004046 /* WAS:
njn22cfccb2004-11-27 16:10:23 +00004047 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
4048 KERNEL_DO_SYSCALL(tid,RES);
4049 if (!VG_(is_kerror)(RES) && RES == 0)
4050 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
jsgf855d93d2003-10-13 22:26:55 +00004051 */
njn22cfccb2004-11-27 16:10:23 +00004052 if (RES == 0 && ARG3 ) {
4053 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
nethercote73b526f2004-10-31 18:48:21 +00004054 if (ifc->vki_ifc_buf != NULL)
nethercoteef0c7662004-11-06 15:38:43 +00004055 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
jsgf855d93d2003-10-13 22:26:55 +00004056 }
4057 break;
nethercote73b526f2004-10-31 18:48:21 +00004058 case VKI_SIOCGSTAMP:
njn22cfccb2004-11-27 16:10:23 +00004059 POST_MEM_WRITE( ARG3, sizeof(struct vki_timeval) );
jsgf855d93d2003-10-13 22:26:55 +00004060 break;
4061 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
4062 the number of bytes currently in that socket's send buffer.
4063 It writes this value as an int to the memory location
4064 indicated by the third argument of ioctl(2). */
nethercote73b526f2004-10-31 18:48:21 +00004065 case VKI_SIOCOUTQ:
njn22cfccb2004-11-27 16:10:23 +00004066 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00004067 break;
nethercote73b526f2004-10-31 18:48:21 +00004068 case VKI_SIOCGRARP: /* get RARP table entry */
4069 case VKI_SIOCGARP: /* get ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00004070 POST_MEM_WRITE(ARG3, sizeof(struct vki_arpreq));
jsgf855d93d2003-10-13 22:26:55 +00004071 break;
4072
nethercote73b526f2004-10-31 18:48:21 +00004073 case VKI_SIOCSIFFLAGS: /* set flags */
4074 case VKI_SIOCSIFMAP: /* Set device parameters */
4075 case VKI_SIOCSIFTXQLEN: /* Set the tx queue length */
4076 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
4077 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
4078 case VKI_SIOCSIFNETMASK: /* set network PA mask */
4079 case VKI_SIOCSIFMETRIC: /* set metric */
4080 case VKI_SIOCSIFADDR: /* set PA address */
4081 case VKI_SIOCSIFMTU: /* set MTU size */
4082 case VKI_SIOCSIFHWADDR: /* set hardware address */
4083 case VKI_SIOCSMIIREG: /* set hardware entry registers */
jsgf855d93d2003-10-13 22:26:55 +00004084 break;
4085 /* Routing table calls. */
nethercote73b526f2004-10-31 18:48:21 +00004086 case VKI_SIOCADDRT: /* add routing table entry */
4087 case VKI_SIOCDELRT: /* delete routing table entry */
jsgf855d93d2003-10-13 22:26:55 +00004088 break;
4089
4090 /* RARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00004091 case VKI_SIOCDRARP: /* delete RARP table entry */
4092 case VKI_SIOCSRARP: /* set RARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00004093 /* ARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00004094 case VKI_SIOCSARP: /* set ARP table entry */
4095 case VKI_SIOCDARP: /* delete ARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00004096 break;
4097
nethercote73b526f2004-10-31 18:48:21 +00004098 case VKI_SIOCGPGRP:
njn22cfccb2004-11-27 16:10:23 +00004099 POST_MEM_WRITE(ARG3, sizeof(int));
thughes1174fed2004-09-11 15:33:17 +00004100 break;
nethercote73b526f2004-10-31 18:48:21 +00004101 case VKI_SIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00004102 break;
4103
4104 /* linux/soundcard interface (OSS) */
nethercote73b526f2004-10-31 18:48:21 +00004105 case VKI_SNDCTL_SEQ_GETOUTCOUNT:
4106 case VKI_SNDCTL_SEQ_GETINCOUNT:
4107 case VKI_SNDCTL_SEQ_PERCMODE:
4108 case VKI_SNDCTL_SEQ_TESTMIDI:
4109 case VKI_SNDCTL_SEQ_RESETSAMPLES:
4110 case VKI_SNDCTL_SEQ_NRSYNTHS:
4111 case VKI_SNDCTL_SEQ_NRMIDIS:
4112 case VKI_SNDCTL_SEQ_GETTIME:
4113 case VKI_SNDCTL_DSP_GETFMTS:
4114 case VKI_SNDCTL_DSP_GETTRIGGER:
4115 case VKI_SNDCTL_DSP_GETODELAY:
4116 case VKI_SNDCTL_DSP_GETSPDIF:
4117 case VKI_SNDCTL_DSP_GETCAPS:
4118 case VKI_SOUND_PCM_READ_RATE:
4119 case VKI_SOUND_PCM_READ_CHANNELS:
4120 case VKI_SOUND_PCM_READ_BITS:
cerion85665ca2005-06-20 15:51:07 +00004121#if !defined(VGA_ppc32)
nethercote73b526f2004-10-31 18:48:21 +00004122 case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
cerion85665ca2005-06-20 15:51:07 +00004123#endif
nethercote73b526f2004-10-31 18:48:21 +00004124 case VKI_SOUND_PCM_READ_FILTER:
njn22cfccb2004-11-27 16:10:23 +00004125 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00004126 break;
nethercote73b526f2004-10-31 18:48:21 +00004127 case VKI_SNDCTL_SEQ_CTRLRATE:
4128 case VKI_SNDCTL_DSP_SPEED:
4129 case VKI_SNDCTL_DSP_STEREO:
4130 case VKI_SNDCTL_DSP_GETBLKSIZE:
4131 case VKI_SNDCTL_DSP_CHANNELS:
4132 case VKI_SOUND_PCM_WRITE_FILTER:
4133 case VKI_SNDCTL_DSP_SUBDIVIDE:
4134 case VKI_SNDCTL_DSP_SETFRAGMENT:
nethercote73b526f2004-10-31 18:48:21 +00004135 case VKI_SNDCTL_DSP_GETCHANNELMASK:
nethercote73b526f2004-10-31 18:48:21 +00004136 case VKI_SNDCTL_DSP_BIND_CHANNEL:
nethercote73b526f2004-10-31 18:48:21 +00004137 case VKI_SNDCTL_TMR_TIMEBASE:
4138 case VKI_SNDCTL_TMR_TEMPO:
4139 case VKI_SNDCTL_TMR_SOURCE:
4140 case VKI_SNDCTL_MIDI_PRETIME:
4141 case VKI_SNDCTL_MIDI_MPUMODE:
jsgf855d93d2003-10-13 22:26:55 +00004142 break;
nethercote73b526f2004-10-31 18:48:21 +00004143 case VKI_SNDCTL_DSP_GETOSPACE:
4144 case VKI_SNDCTL_DSP_GETISPACE:
njn22cfccb2004-11-27 16:10:23 +00004145 POST_MEM_WRITE(ARG3, sizeof(vki_audio_buf_info));
jsgf855d93d2003-10-13 22:26:55 +00004146 break;
nethercote73b526f2004-10-31 18:48:21 +00004147 case VKI_SNDCTL_DSP_SETTRIGGER:
jsgf855d93d2003-10-13 22:26:55 +00004148 break;
4149
nethercote73b526f2004-10-31 18:48:21 +00004150 case VKI_SNDCTL_DSP_POST:
4151 case VKI_SNDCTL_DSP_RESET:
4152 case VKI_SNDCTL_DSP_SYNC:
4153 case VKI_SNDCTL_DSP_SETSYNCRO:
4154 case VKI_SNDCTL_DSP_SETDUPLEX:
jsgf855d93d2003-10-13 22:26:55 +00004155 break;
4156
4157 /* Real Time Clock (/dev/rtc) ioctls */
nethercote73b526f2004-10-31 18:48:21 +00004158 case VKI_RTC_UIE_ON:
4159 case VKI_RTC_UIE_OFF:
4160 case VKI_RTC_AIE_ON:
4161 case VKI_RTC_AIE_OFF:
4162 case VKI_RTC_PIE_ON:
4163 case VKI_RTC_PIE_OFF:
4164 case VKI_RTC_IRQP_SET:
jsgf855d93d2003-10-13 22:26:55 +00004165 break;
nethercote73b526f2004-10-31 18:48:21 +00004166 case VKI_RTC_RD_TIME:
4167 case VKI_RTC_ALM_READ:
njn22cfccb2004-11-27 16:10:23 +00004168 POST_MEM_WRITE(ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00004169 break;
nethercote73b526f2004-10-31 18:48:21 +00004170 case VKI_RTC_ALM_SET:
jsgf855d93d2003-10-13 22:26:55 +00004171 break;
nethercote73b526f2004-10-31 18:48:21 +00004172 case VKI_RTC_IRQP_READ:
njn22cfccb2004-11-27 16:10:23 +00004173 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00004174 break;
jsgf855d93d2003-10-13 22:26:55 +00004175
tomeafc49b2005-07-28 16:08:09 +00004176 /* Block devices */
4177 case VKI_BLKROSET:
4178 break;
4179 case VKI_BLKROGET:
4180 POST_MEM_WRITE(ARG3, sizeof(int));
4181 break;
nethercote95a97862004-11-06 16:31:43 +00004182 case VKI_BLKGETSIZE:
njn22cfccb2004-11-27 16:10:23 +00004183 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00004184 break;
tomeafc49b2005-07-28 16:08:09 +00004185 case VKI_BLKRASET:
4186 break;
4187 case VKI_BLKRAGET:
4188 POST_MEM_WRITE(ARG3, sizeof(long));
4189 break;
4190 case VKI_BLKFRASET:
4191 break;
4192 case VKI_BLKFRAGET:
4193 POST_MEM_WRITE(ARG3, sizeof(long));
4194 break;
4195 case VKI_BLKSECTGET:
4196 POST_MEM_WRITE(ARG3, sizeof(unsigned short));
4197 break;
4198 case VKI_BLKSSZGET:
4199 POST_MEM_WRITE(ARG3, sizeof(int));
4200 break;
4201 case VKI_BLKBSZGET:
4202 POST_MEM_WRITE(ARG3, sizeof(int));
4203 break;
4204 case VKI_BLKBSZSET:
4205 break;
tomd6555642005-07-18 13:26:55 +00004206 case VKI_BLKGETSIZE64:
4207 POST_MEM_WRITE(ARG3, sizeof(unsigned long long));
4208 break;
jsgf855d93d2003-10-13 22:26:55 +00004209
thughesacbbc322004-06-19 12:12:01 +00004210 /* Hard disks */
tom2c2bc252005-07-28 16:13:42 +00004211 case VKI_HDIO_GETGEO: /* 0x0301 */
4212 POST_MEM_WRITE(ARG3, sizeof(struct vki_hd_geometry));
4213 break;
nethercote73b526f2004-10-31 18:48:21 +00004214 case VKI_HDIO_GET_IDENTITY: /* 0x030d */
njn22cfccb2004-11-27 16:10:23 +00004215 POST_MEM_WRITE(ARG3, VKI_SIZEOF_STRUCT_HD_DRIVEID );
thughesacbbc322004-06-19 12:12:01 +00004216 break;
4217
jsgf855d93d2003-10-13 22:26:55 +00004218 /* CD ROM stuff (??) */
nethercote73b526f2004-10-31 18:48:21 +00004219 case VKI_CDROMSUBCHNL:
njn22cfccb2004-11-27 16:10:23 +00004220 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_subchnl));
jsgf855d93d2003-10-13 22:26:55 +00004221 break;
nethercote73b526f2004-10-31 18:48:21 +00004222 case VKI_CDROMREADTOCHDR:
njn22cfccb2004-11-27 16:10:23 +00004223 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00004224 break;
nethercote73b526f2004-10-31 18:48:21 +00004225 case VKI_CDROMREADTOCENTRY:
njn22cfccb2004-11-27 16:10:23 +00004226 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00004227 break;
nethercote73b526f2004-10-31 18:48:21 +00004228 case VKI_CDROMMULTISESSION:
njn22cfccb2004-11-27 16:10:23 +00004229 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_multisession));
thughes5b788fb2004-09-11 15:07:14 +00004230 break;
nethercote73b526f2004-10-31 18:48:21 +00004231 case VKI_CDROMVOLREAD:
njn22cfccb2004-11-27 16:10:23 +00004232 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_volctrl));
thughes5b788fb2004-09-11 15:07:14 +00004233 break;
nethercote73b526f2004-10-31 18:48:21 +00004234 case VKI_CDROMREADAUDIO:
thughes5b788fb2004-09-11 15:07:14 +00004235 {
njn22cfccb2004-11-27 16:10:23 +00004236 struct vki_cdrom_read_audio *cra = (struct vki_cdrom_read_audio *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00004237 POST_MEM_WRITE( (Addr)(cra->buf), cra->nframes * VKI_CD_FRAMESIZE_RAW);
thughes5b788fb2004-09-11 15:07:14 +00004238 break;
4239 }
4240
nethercote73b526f2004-10-31 18:48:21 +00004241 case VKI_CDROMPLAYMSF:
jsgf855d93d2003-10-13 22:26:55 +00004242 break;
4243 /* The following two are probably bogus (should check args
4244 for readability). JRS 20021117 */
nethercote73b526f2004-10-31 18:48:21 +00004245 case VKI_CDROM_DRIVE_STATUS: /* 0x5326 */
4246 case VKI_CDROM_CLEAR_OPTIONS: /* 0x5321 */
jsgf855d93d2003-10-13 22:26:55 +00004247 break;
4248
nethercote73b526f2004-10-31 18:48:21 +00004249 case VKI_FIGETBSZ:
njn22cfccb2004-11-27 16:10:23 +00004250 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00004251 break;
nethercote73b526f2004-10-31 18:48:21 +00004252 case VKI_FIBMAP:
njn22cfccb2004-11-27 16:10:23 +00004253 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00004254 break;
4255
nethercote73b526f2004-10-31 18:48:21 +00004256 case VKI_FBIOGET_VSCREENINFO: //0x4600
njn22cfccb2004-11-27 16:10:23 +00004257 POST_MEM_WRITE(ARG3, sizeof(struct vki_fb_var_screeninfo));
thughes44e35582004-04-21 15:52:33 +00004258 break;
nethercote73b526f2004-10-31 18:48:21 +00004259 case VKI_FBIOGET_FSCREENINFO: //0x4602
njn22cfccb2004-11-27 16:10:23 +00004260 POST_MEM_WRITE(ARG3, sizeof(struct vki_fb_fix_screeninfo));
thughes44e35582004-04-21 15:52:33 +00004261 break;
4262
nethercote73b526f2004-10-31 18:48:21 +00004263 case VKI_PPCLAIM:
4264 case VKI_PPEXCL:
4265 case VKI_PPYIELD:
4266 case VKI_PPRELEASE:
4267 case VKI_PPSETMODE:
4268 case VKI_PPSETPHASE:
4269 case VKI_PPSETFLAGS:
4270 case VKI_PPWDATA:
4271 case VKI_PPWCONTROL:
4272 case VKI_PPFCONTROL:
4273 case VKI_PPDATADIR:
4274 case VKI_PPNEGOT:
4275 case VKI_PPWCTLONIRQ:
4276 case VKI_PPSETTIME:
thughesd9895482004-08-16 19:46:55 +00004277 break;
nethercote73b526f2004-10-31 18:48:21 +00004278 case VKI_PPGETMODE:
njn22cfccb2004-11-27 16:10:23 +00004279 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004280 break;
nethercote73b526f2004-10-31 18:48:21 +00004281 case VKI_PPGETPHASE:
njn22cfccb2004-11-27 16:10:23 +00004282 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004283 break;
nethercote73b526f2004-10-31 18:48:21 +00004284 case VKI_PPGETMODES:
njn22cfccb2004-11-27 16:10:23 +00004285 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
thughesd9895482004-08-16 19:46:55 +00004286 break;
nethercote73b526f2004-10-31 18:48:21 +00004287 case VKI_PPGETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00004288 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004289 break;
nethercote73b526f2004-10-31 18:48:21 +00004290 case VKI_PPRSTATUS:
njn22cfccb2004-11-27 16:10:23 +00004291 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004292 break;
nethercote73b526f2004-10-31 18:48:21 +00004293 case VKI_PPRDATA:
njn22cfccb2004-11-27 16:10:23 +00004294 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004295 break;
nethercote73b526f2004-10-31 18:48:21 +00004296 case VKI_PPRCONTROL:
njn22cfccb2004-11-27 16:10:23 +00004297 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004298 break;
nethercote73b526f2004-10-31 18:48:21 +00004299 case VKI_PPCLRIRQ:
njn22cfccb2004-11-27 16:10:23 +00004300 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004301 break;
nethercote73b526f2004-10-31 18:48:21 +00004302 case VKI_PPGETTIME:
njn22cfccb2004-11-27 16:10:23 +00004303 POST_MEM_WRITE( ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00004304 break;
4305
thughesc3b842d2004-11-13 10:38:04 +00004306 case VKI_GIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00004307 POST_MEM_WRITE( ARG3, 32 * 256 );
thughesc3b842d2004-11-13 10:38:04 +00004308 break;
4309 case VKI_PIO_FONT:
4310 break;
4311
4312 case VKI_GIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00004313 POST_MEM_WRITE( (Addr)((struct vki_consolefontdesc *)ARG3)->chardata,
4314 32 * ((struct vki_consolefontdesc *)ARG3)->charcount );
thughesc3b842d2004-11-13 10:38:04 +00004315 break;
4316 case VKI_PIO_FONTX:
4317 break;
4318
4319 case VKI_PIO_FONTRESET:
4320 break;
4321
4322 case VKI_GIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00004323 POST_MEM_WRITE( ARG3, 16 * 3 );
thughesc3b842d2004-11-13 10:38:04 +00004324 break;
4325 case VKI_PIO_CMAP:
4326 break;
4327
4328 case VKI_KIOCSOUND:
4329 case VKI_KDMKTONE:
4330 break;
4331
4332 case VKI_KDGETLED:
njn22cfccb2004-11-27 16:10:23 +00004333 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004334 break;
4335 case VKI_KDSETLED:
4336 break;
4337
4338 case VKI_KDGKBTYPE:
njn22cfccb2004-11-27 16:10:23 +00004339 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004340 break;
4341
4342 case VKI_KDADDIO:
4343 case VKI_KDDELIO:
4344 case VKI_KDENABIO:
4345 case VKI_KDDISABIO:
4346 break;
4347
4348 case VKI_KDSETMODE:
4349 break;
4350 case VKI_KDGETMODE:
njn22cfccb2004-11-27 16:10:23 +00004351 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004352 break;
4353
4354 case VKI_KDMAPDISP:
4355 case VKI_KDUNMAPDISP:
4356 break;
4357
4358 case VKI_GIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00004359 POST_MEM_WRITE( ARG3, VKI_E_TABSZ );
thughesc3b842d2004-11-13 10:38:04 +00004360 break;
4361 case VKI_PIO_SCRNMAP:
4362 break;
4363 case VKI_GIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00004364 POST_MEM_WRITE( ARG3, VKI_E_TABSZ * sizeof(unsigned short) );
thughesc3b842d2004-11-13 10:38:04 +00004365 break;
4366 case VKI_PIO_UNISCRNMAP:
4367 break;
4368
4369 case VKI_KDGKBMODE:
njn22cfccb2004-11-27 16:10:23 +00004370 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004371 break;
4372 case VKI_KDSKBMODE:
4373 break;
4374
4375 case VKI_KDGKBMETA:
njn22cfccb2004-11-27 16:10:23 +00004376 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004377 break;
4378 case VKI_KDSKBMETA:
4379 break;
4380
4381 case VKI_KDGKBLED:
njn22cfccb2004-11-27 16:10:23 +00004382 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004383 break;
4384 case VKI_KDSKBLED:
4385 break;
4386
4387 case VKI_KDGKBENT:
njn22cfccb2004-11-27 16:10:23 +00004388 POST_MEM_WRITE( (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
4389 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesc3b842d2004-11-13 10:38:04 +00004390 break;
4391 case VKI_KDSKBENT:
4392 break;
4393
4394 case VKI_KDGKBSENT:
njn22cfccb2004-11-27 16:10:23 +00004395 POST_MEM_WRITE( (Addr)((struct vki_kbsentry *)ARG3)->kb_string,
4396 sizeof(((struct vki_kbsentry *)ARG3)->kb_string) );
thughesc3b842d2004-11-13 10:38:04 +00004397 break;
4398 case VKI_KDSKBSENT:
4399 break;
4400
4401 case VKI_KDGKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00004402 POST_MEM_WRITE( ARG3, sizeof(struct vki_kbdiacrs) );
thughesc3b842d2004-11-13 10:38:04 +00004403 break;
4404 case VKI_KDSKBDIACR:
4405 break;
4406
4407 case VKI_KDGETKEYCODE:
njn22cfccb2004-11-27 16:10:23 +00004408 POST_MEM_WRITE( (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
4409 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesc3b842d2004-11-13 10:38:04 +00004410 break;
4411 case VKI_KDSETKEYCODE:
4412 break;
4413
4414 case VKI_KDSIGACCEPT:
4415 break;
4416
4417 case VKI_KDKBDREP:
4418 break;
4419
jsgf855d93d2003-10-13 22:26:55 +00004420 /* We don't have any specific information on it, so
4421 try to do something reasonable based on direction and
4422 size bits. The encoding scheme is described in
4423 /usr/include/asm/ioctl.h.
4424
4425 According to Simon Hausmann, _IOC_READ means the kernel
4426 writes a value to the ioctl value passed from the user
4427 space and the other way around with _IOC_WRITE. */
4428 default: {
njn22cfccb2004-11-27 16:10:23 +00004429 UInt dir = _VKI_IOC_DIR(ARG2);
4430 UInt size = _VKI_IOC_SIZE(ARG2);
nethercote73b526f2004-10-31 18:48:21 +00004431 if (size > 0 && (dir & _VKI_IOC_READ)
sewardja8d8e232005-06-07 20:04:56 +00004432 && RES == 0
njn22cfccb2004-11-27 16:10:23 +00004433 && ARG3 != (Addr)NULL)
4434 POST_MEM_WRITE(ARG3, size);
jsgf855d93d2003-10-13 22:26:55 +00004435 break;
4436 }
4437 }
4438}
4439
njn03f1e582005-03-26 20:08:06 +00004440/*
4441 If we're sending a SIGKILL to one of our own threads, then simulate
4442 it rather than really sending the signal, so that the target thread
4443 gets a chance to clean up. Returns True if we did the killing (or
4444 no killing is necessary), and False if the caller should use the
4445 normal kill syscall.
4446
4447 "pid" is any pid argument which can be passed to kill; group kills
4448 (< -1, 0), and owner kills (-1) are ignored, on the grounds that
4449 they'll most likely hit all the threads and we won't need to worry
4450 about cleanup. In truth, we can't fully emulate these multicast
4451 kills.
4452
4453 "tgid" is a thread group id. If it is not -1, then the target
4454 thread must be in that thread group.
4455 */
sewardj7eb7c582005-06-23 01:02:53 +00004456Bool ML_(do_sigkill)(Int pid, Int tgid)
njn03f1e582005-03-26 20:08:06 +00004457{
4458 ThreadState *tst;
4459 ThreadId tid;
4460
4461 if (pid <= 0)
4462 return False;
4463
4464 tid = VG_(get_lwp_tid)(pid);
4465 if (tid == VG_INVALID_THREADID)
4466 return False; /* none of our threads */
4467
4468 tst = VG_(get_ThreadState)(tid);
4469 if (tst == NULL || tst->status == VgTs_Empty)
4470 return False; /* hm, shouldn't happen */
4471
4472 if (tgid != -1 && tst->os_state.threadgroup != tgid)
4473 return False; /* not the right thread group */
4474
4475 /* Check to see that the target isn't already exiting. */
4476 if (!VG_(is_exiting)(tid)) {
4477 if (VG_(clo_trace_signals))
sewardja8d8e232005-06-07 20:04:56 +00004478 VG_(message)(Vg_DebugMsg, "Thread %d being killed with SIGKILL",
4479 tst->tid);
njn03f1e582005-03-26 20:08:06 +00004480
4481 tst->exitreason = VgSrc_FatalSig;
4482 tst->os_state.fatalsig = VKI_SIGKILL;
4483
4484 if (!VG_(is_running_thread)(tid))
4485 VG_(kill_thread)(tid);
4486 }
4487
4488 return True;
4489}
4490
sewardja8d8e232005-06-07 20:04:56 +00004491PRE(sys_kill)
jsgf855d93d2003-10-13 22:26:55 +00004492{
njn22cfccb2004-11-27 16:10:23 +00004493 PRINT("sys_kill ( %d, %d )", ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00004494 PRE_REG_READ2(long, "kill", int, pid, int, sig);
sewardj7eb7c582005-06-23 01:02:53 +00004495 if (!ML_(client_signal_OK)(ARG2)) {
sewardja8d8e232005-06-07 20:04:56 +00004496 SET_STATUS_Failure( VKI_EINVAL );
njn03f1e582005-03-26 20:08:06 +00004497 return;
4498 }
jsgf855d93d2003-10-13 22:26:55 +00004499
njn03f1e582005-03-26 20:08:06 +00004500 /* If we're sending SIGKILL, check to see if the target is one of
4501 our threads and handle it specially. */
sewardj7eb7c582005-06-23 01:02:53 +00004502 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
sewardja8d8e232005-06-07 20:04:56 +00004503 SET_STATUS_Success(0);
njn03f1e582005-03-26 20:08:06 +00004504 else
sewardja8d8e232005-06-07 20:04:56 +00004505 SET_STATUS_from_SysRes( VG_(do_syscall2)(SYSNO, ARG1, ARG2) );
njn03f1e582005-03-26 20:08:06 +00004506
sewardjb5f6f512005-03-10 23:59:00 +00004507 if (VG_(clo_trace_signals))
4508 VG_(message)(Vg_DebugMsg, "kill: sent signal %d to pid %d",
njn03f1e582005-03-26 20:08:06 +00004509 ARG2, ARG1);
sewardja8d8e232005-06-07 20:04:56 +00004510
4511 /* This kill might have given us a pending signal. Ask for a check once
4512 the syscall is done. */
4513 *flags |= SfPollAfter;
jsgf855d93d2003-10-13 22:26:55 +00004514}
4515
sewardja8d8e232005-06-07 20:04:56 +00004516PRE(sys_link)
jsgf855d93d2003-10-13 22:26:55 +00004517{
sewardja8d8e232005-06-07 20:04:56 +00004518 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004519 PRINT("sys_link ( %p, %p)", ARG1, ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00004520 PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00004521 PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
4522 PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
jsgf855d93d2003-10-13 22:26:55 +00004523}
4524
sewardj696c5512005-06-08 23:38:32 +00004525PRE(sys_newlstat)
4526{
4527 PRINT("sys_newlstat ( %p(%s), %p )", ARG1,ARG1,ARG2);
4528 PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
4529 PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
4530 PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
4531}
4532
4533POST(sys_newlstat)
4534{
4535 vg_assert(SUCCESS);
4536 if (RES == 0) {
4537 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
4538 }
4539}
jsgf855d93d2003-10-13 22:26:55 +00004540
sewardja8d8e232005-06-07 20:04:56 +00004541PRE(sys_mkdir)
jsgf855d93d2003-10-13 22:26:55 +00004542{
sewardja8d8e232005-06-07 20:04:56 +00004543 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004544 PRINT("sys_mkdir ( %p, %d )", ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00004545 PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00004546 PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004547}
4548
sewardja8d8e232005-06-07 20:04:56 +00004549PRE(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00004550{
njn22cfccb2004-11-27 16:10:23 +00004551 PRINT("sys_mprotect ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00004552 PRE_REG_READ3(long, "mprotect",
4553 unsigned long, addr, vki_size_t, len, unsigned long, prot);
fitzhardinge98abfc72003-12-16 02:05:15 +00004554
tom65505192005-11-08 16:51:55 +00004555 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
sewardja8d8e232005-06-07 20:04:56 +00004556 SET_STATUS_Failure( VKI_ENOMEM );
sewardj337556e2005-11-09 14:51:59 +00004557 }
4558 else
4559 if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
4560 /* Deal with mprotects on growable stack areas.
4561
4562 The critical files to understand all this are mm/mprotect.c
4563 in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
4564 glibc.
4565
4566 The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
4567 round the start/end address of mprotect to the start/end of
4568 the underlying vma and glibc uses that as an easy way to
4569 change the protection of the stack by calling mprotect on the
4570 last page of the stack with PROT_GROWSDOWN set.
4571
4572 The sanity check provided by the kernel is that the vma must
4573 have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */
tom65505192005-11-08 16:51:55 +00004574 UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
4575 NSegment *aseg = VG_(am_find_nsegment)(ARG1);
4576 NSegment *rseg;
4577
4578 vg_assert(aseg);
4579
4580 if (grows == VKI_PROT_GROWSDOWN) {
4581 rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ );
4582 if (rseg &&
4583 rseg->kind == SkResvn &&
4584 rseg->smode == SmUpper &&
4585 rseg->end+1 == aseg->start) {
4586 Addr end = ARG1 + ARG2;
4587 ARG1 = aseg->start;
4588 ARG2 = end - aseg->start;
4589 ARG3 &= ~VKI_PROT_GROWSDOWN;
4590 } else {
4591 SET_STATUS_Failure( VKI_EINVAL );
4592 }
4593 } else if (grows == VKI_PROT_GROWSUP) {
4594 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
4595 if (rseg &&
4596 rseg->kind == SkResvn &&
4597 rseg->smode == SmLower &&
4598 aseg->end+1 == rseg->start) {
4599 ARG2 = aseg->end - ARG1 + 1;
4600 ARG3 &= ~VKI_PROT_GROWSUP;
4601 } else {
4602 SET_STATUS_Failure( VKI_EINVAL );
4603 }
4604 } else {
sewardj337556e2005-11-09 14:51:59 +00004605 /* both GROWSUP and GROWSDOWN */
tom65505192005-11-08 16:51:55 +00004606 SET_STATUS_Failure( VKI_EINVAL );
4607 }
4608 }
jsgf855d93d2003-10-13 22:26:55 +00004609}
4610
nethercote85a456f2004-11-16 17:31:56 +00004611POST(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00004612{
njn22cfccb2004-11-27 16:10:23 +00004613 Addr a = ARG1;
4614 SizeT len = ARG2;
4615 Int prot = ARG3;
sewardj45f4e7c2005-09-27 19:20:21 +00004616 Bool rr = toBool(prot & VKI_PROT_READ);
4617 Bool ww = toBool(prot & VKI_PROT_WRITE);
4618 Bool xx = toBool(prot & VKI_PROT_EXEC);
4619 Bool d;
nethercote27ea8bc2004-07-10 17:21:14 +00004620
sewardj45f4e7c2005-09-27 19:20:21 +00004621 page_align_addr_and_len(&a, &len);
4622 d = VG_(am_notify_mprotect)(a, len, prot);
nethercote27ea8bc2004-07-10 17:21:14 +00004623 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
sewardj45f4e7c2005-09-27 19:20:21 +00004624 VG_(di_notify_mprotect)( a, len, prot );
4625 if (d)
4626 VG_(discard_translations)( (Addr64)a, (ULong)len,
4627 "POST(sys_mprotect)" );
jsgf855d93d2003-10-13 22:26:55 +00004628}
4629
sewardja8d8e232005-06-07 20:04:56 +00004630PRE(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00004631{
sewardja8d8e232005-06-07 20:04:56 +00004632 if (0) VG_(printf)(" munmap( %p )\n", ARG1);
njn22cfccb2004-11-27 16:10:23 +00004633 PRINT("sys_munmap ( %p, %llu )", ARG1,(ULong)ARG2);
nethercote06c7bd72004-11-14 19:11:56 +00004634 PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
fitzhardinge98abfc72003-12-16 02:05:15 +00004635
sewardj7eb7c582005-06-23 01:02:53 +00004636 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
sewardja8d8e232005-06-07 20:04:56 +00004637 SET_STATUS_Failure( VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00004638}
4639
nethercote85a456f2004-11-16 17:31:56 +00004640POST(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00004641{
njn22cfccb2004-11-27 16:10:23 +00004642 Addr a = ARG1;
4643 SizeT len = ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00004644 Bool d;
nethercote27ea8bc2004-07-10 17:21:14 +00004645
sewardj45f4e7c2005-09-27 19:20:21 +00004646 page_align_addr_and_len(&a, &len);
4647 d = VG_(am_notify_munmap)(a, len);
nethercote27ea8bc2004-07-10 17:21:14 +00004648 VG_TRACK( die_mem_munmap, a, len );
sewardj45f4e7c2005-09-27 19:20:21 +00004649 VG_(di_notify_munmap)( a, len );
4650 if (d)
4651 VG_(discard_translations)( (Addr64)a, (ULong)len,
4652 "POST(sys_munmap)" );
jsgf855d93d2003-10-13 22:26:55 +00004653}
4654
sewardje6d5e722005-06-10 10:27:55 +00004655PRE(sys_mincore)
4656{
4657 PRINT("sys_mincore ( %p, %llu, %p )", ARG1,(ULong)ARG2,ARG3);
4658 PRE_REG_READ3(long, "mincore",
4659 unsigned long, start, vki_size_t, length,
4660 unsigned char *, vec);
njncdaec512005-06-30 00:16:02 +00004661 PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00004662}
4663POST(sys_mincore)
4664{
njncdaec512005-06-30 00:16:02 +00004665 POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00004666}
mueller6ceb2312004-01-02 22:52:34 +00004667
sewardja8d8e232005-06-07 20:04:56 +00004668PRE(sys_nanosleep)
mueller6ceb2312004-01-02 22:52:34 +00004669{
sewardja8d8e232005-06-07 20:04:56 +00004670 *flags |= SfMayBlock|SfPostOnFail;
njn22cfccb2004-11-27 16:10:23 +00004671 PRINT("sys_nanosleep ( %p, %p )", ARG1,ARG2);
nethercote5b653bc2004-11-15 14:32:12 +00004672 PRE_REG_READ2(long, "nanosleep",
4673 struct timespec *, req, struct timespec *, rem);
njn22cfccb2004-11-27 16:10:23 +00004674 PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
4675 if (ARG2 != 0)
4676 PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004677}
4678
nethercote85a456f2004-11-16 17:31:56 +00004679POST(sys_nanosleep)
jsgf855d93d2003-10-13 22:26:55 +00004680{
sewardja8d8e232005-06-07 20:04:56 +00004681 vg_assert(SUCCESS || FAILURE);
4682 if (ARG2 != 0 && FAILURE && RES_unchecked == VKI_EINTR)
njn22cfccb2004-11-27 16:10:23 +00004683 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004684}
4685
sewardja8d8e232005-06-07 20:04:56 +00004686PRE(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00004687{
sewardj45f4e7c2005-09-27 19:20:21 +00004688 HChar name[30];
4689 SysRes sres;
4690
njn22cfccb2004-11-27 16:10:23 +00004691 if (ARG2 & VKI_O_CREAT) {
nethercotee824cc42004-11-09 16:20:46 +00004692 // 3-arg version
njn22cfccb2004-11-27 16:10:23 +00004693 PRINT("sys_open ( %p(%s), %d, %d )",ARG1,ARG1,ARG2,ARG3);
nethercotee824cc42004-11-09 16:20:46 +00004694 PRE_REG_READ3(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00004695 const char *, filename, int, flags, int, mode);
nethercotee70bd7d2004-08-18 14:37:17 +00004696 } else {
nethercotee824cc42004-11-09 16:20:46 +00004697 // 2-arg version
njn22cfccb2004-11-27 16:10:23 +00004698 PRINT("sys_open ( %p(%s), %d )",ARG1,ARG1,ARG2);
nethercotee824cc42004-11-09 16:20:46 +00004699 PRE_REG_READ2(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00004700 const char *, filename, int, flags);
nethercotee70bd7d2004-08-18 14:37:17 +00004701 }
njn22cfccb2004-11-27 16:10:23 +00004702 PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
sewardj45f4e7c2005-09-27 19:20:21 +00004703
4704 /* Handle the case where the open is of /proc/self/cmdline or
4705 /proc/<pid>/cmdline, and just give it a copy of the fd for the
4706 fake file we cooked up at startup (in m_main). Also, seek the
4707 cloned fd back to the start. */
4708
4709 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
4710 if (ML_(safe_to_deref)( (void*)ARG1, 1 )
4711 && (VG_(strcmp)((Char *)ARG1, name) == 0
4712 || VG_(strcmp)((Char *)ARG1, "/proc/self/cmdline") == 0)) {
4713 sres = VG_(dup)( VG_(cl_cmdline_fd) );
4714 SET_STATUS_from_SysRes( sres );
4715 if (!sres.isError) {
4716 OffT off = VG_(lseek)( sres.val, 0, VKI_SEEK_SET );
tomf4c23102005-10-31 17:05:21 +00004717 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +00004718 SET_STATUS_Failure( VKI_EMFILE );
4719 }
4720 return;
4721 }
4722
4723 /* Otherwise handle normally */
4724 *flags |= SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00004725}
4726
nethercote85a456f2004-11-16 17:31:56 +00004727POST(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00004728{
sewardja8d8e232005-06-07 20:04:56 +00004729 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004730 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004731 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004732 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004733 } else {
nethercote493dd182004-02-24 23:57:47 +00004734 if (VG_(clo_track_fds))
njn4279a882005-08-26 03:43:28 +00004735 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004736 }
jsgf855d93d2003-10-13 22:26:55 +00004737}
4738
sewardja8d8e232005-06-07 20:04:56 +00004739PRE(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004740{
sewardja8d8e232005-06-07 20:04:56 +00004741 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004742 PRINT("sys_read ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004743 PRE_REG_READ3(ssize_t, "read",
njnca0518d2004-11-26 19:34:36 +00004744 unsigned int, fd, char *, buf, vki_size_t, count);
jsgf855d93d2003-10-13 22:26:55 +00004745
sewardj7eb7c582005-06-23 01:02:53 +00004746 if (!ML_(fd_allowed)(ARG1, "read", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00004747 SET_STATUS_Failure( VKI_EBADF );
thughes26ab77b2004-08-14 12:10:49 +00004748 else
njn22cfccb2004-11-27 16:10:23 +00004749 PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004750}
4751
nethercote85a456f2004-11-16 17:31:56 +00004752POST(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004753{
sewardja8d8e232005-06-07 20:04:56 +00004754 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004755 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004756}
4757
sewardja8d8e232005-06-07 20:04:56 +00004758PRE(sys_write)
jsgf855d93d2003-10-13 22:26:55 +00004759{
sewardj45f4e7c2005-09-27 19:20:21 +00004760 Bool ok;
sewardja8d8e232005-06-07 20:04:56 +00004761 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004762 PRINT("sys_write ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004763 PRE_REG_READ3(ssize_t, "write",
njnca0518d2004-11-26 19:34:36 +00004764 unsigned int, fd, const char *, buf, vki_size_t, count);
sewardj45f4e7c2005-09-27 19:20:21 +00004765 /* check to see if it is allowed. If not, try for an exemption from
sewardj19617ae2005-10-20 01:09:57 +00004766 --simulation-hints=enable-outer (used for self hosting). */
sewardj45f4e7c2005-09-27 19:20:21 +00004767 ok = ML_(fd_allowed)(ARG1, "write", tid, False);
4768 if (!ok && ARG1 == 2/*stderr*/
sewardj19617ae2005-10-20 01:09:57 +00004769 && VG_(strstr)(VG_(clo_simulation_hints),"enable-outer"))
sewardj45f4e7c2005-09-27 19:20:21 +00004770 ok = True;
4771 if (!ok)
sewardja8d8e232005-06-07 20:04:56 +00004772 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004773 else
njn22cfccb2004-11-27 16:10:23 +00004774 PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004775}
4776
sewardja8d8e232005-06-07 20:04:56 +00004777PRE(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004778{
sewardja8d8e232005-06-07 20:04:56 +00004779 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004780 PRINT("sys_creat ( %p(%s), %d )", ARG1,ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00004781 PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00004782 PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004783}
4784
nethercote85a456f2004-11-16 17:31:56 +00004785POST(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004786{
sewardja8d8e232005-06-07 20:04:56 +00004787 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004788 if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004789 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004790 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004791 } else {
nethercote493dd182004-02-24 23:57:47 +00004792 if (VG_(clo_track_fds))
njn4279a882005-08-26 03:43:28 +00004793 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004794 }
jsgf855d93d2003-10-13 22:26:55 +00004795}
4796
nethercotef90953e2004-11-15 14:50:02 +00004797// XXX: x86-specific, due to pollfd struct
sewardja8d8e232005-06-07 20:04:56 +00004798PRE(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004799{
4800 /* struct pollfd {
nethercoteef0c7662004-11-06 15:38:43 +00004801 int fd; -- file descriptor
4802 short events; -- requested events
4803 short revents; -- returned events
jsgf855d93d2003-10-13 22:26:55 +00004804 };
nethercoteeb0592d2004-11-05 12:02:27 +00004805 int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
jsgf855d93d2003-10-13 22:26:55 +00004806 */
nethercoteeb0592d2004-11-05 12:02:27 +00004807 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004808 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
tom60a4b0b2005-10-12 10:45:27 +00004809 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004810 PRINT("sys_poll ( %p, %d, %d )\n", ARG1,ARG2,ARG3);
nethercotef90953e2004-11-15 14:50:02 +00004811 PRE_REG_READ3(long, "poll",
4812 struct pollfd *, ufds, unsigned int, nfds, long, timeout);
nethercoteef0c7662004-11-06 15:38:43 +00004813
njn22cfccb2004-11-27 16:10:23 +00004814 for (i = 0; i < ARG2; i++) {
nethercoteeb0592d2004-11-05 12:02:27 +00004815 // 'fd' and 'events' field are inputs; 'revents' is output.
4816 // XXX: this is x86 specific -- the pollfd struct varies across
4817 // different architectures.
nethercoteef0c7662004-11-06 15:38:43 +00004818 PRE_MEM_READ( "poll(ufds)",
4819 (Addr)(&ufds[i]), sizeof(int) + sizeof(short) );
4820 PRE_MEM_WRITE( "poll(ufds)", (Addr)(&ufds[i].revents), sizeof(short) );
4821 }
jsgf855d93d2003-10-13 22:26:55 +00004822}
4823
nethercote85a456f2004-11-16 17:31:56 +00004824POST(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004825{
njn22cfccb2004-11-27 16:10:23 +00004826 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00004827 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004828 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
nethercoteeb0592d2004-11-05 12:02:27 +00004829 // XXX: again, this is x86-specific
njn22cfccb2004-11-27 16:10:23 +00004830 for (i = 0; i < ARG2; i++)
nethercoteef0c7662004-11-06 15:38:43 +00004831 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(Short) );
jsgf855d93d2003-10-13 22:26:55 +00004832 }
4833}
4834
sewardja8d8e232005-06-07 20:04:56 +00004835PRE(sys_readlink)
jsgf855d93d2003-10-13 22:26:55 +00004836{
sewardj144c56d2005-09-30 01:09:50 +00004837 HChar name[25];
4838 Word saved = SYSNO;
4839
njn22cfccb2004-11-27 16:10:23 +00004840 PRINT("sys_readlink ( %p, %p, %llu )", ARG1,ARG2,(ULong)ARG3);
nethercote5a945af2004-11-14 18:37:07 +00004841 PRE_REG_READ3(long, "readlink",
4842 const char *, path, char *, buf, int, bufsiz);
njn22cfccb2004-11-27 16:10:23 +00004843 PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
4844 PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004845
rjwalsh17d85302004-11-18 22:56:09 +00004846 /*
rjwalsh093047d2004-11-19 02:11:56 +00004847 * Handle the case where readlink is looking at /proc/self/exe or
4848 * /proc/<pid>/exe.
rjwalsh17d85302004-11-18 22:56:09 +00004849 */
sewardj144c56d2005-09-30 01:09:50 +00004850 VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
sewardjca7a4752005-09-30 10:32:39 +00004851 if (ML_(safe_to_deref)((void*)ARG1, 1)
sewardje226b382005-09-30 01:47:12 +00004852 && (VG_(strcmp)((Char *)ARG1, name) == 0
4853 || VG_(strcmp)((Char *)ARG1, "/proc/self/exe") == 0)) {
sewardj144c56d2005-09-30 01:09:50 +00004854 VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
4855 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
4856 ARG2, ARG3));
4857 } else {
4858 /* Normal case */
4859 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
rjwalsh17d85302004-11-18 22:56:09 +00004860 }
4861
sewardja8d8e232005-06-07 20:04:56 +00004862 if (SUCCESS && RES > 0)
njn22cfccb2004-11-27 16:10:23 +00004863 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004864}
4865
sewardja8d8e232005-06-07 20:04:56 +00004866PRE(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004867{
jsgf855d93d2003-10-13 22:26:55 +00004868 Int i;
nethercote73b526f2004-10-31 18:48:21 +00004869 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00004870 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004871 PRINT("sys_readv ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00004872 PRE_REG_READ3(ssize_t, "readv",
4873 unsigned long, fd, const struct iovec *, vector,
4874 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00004875 if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00004876 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004877 } else {
njn22cfccb2004-11-27 16:10:23 +00004878 PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
nethercoted6b5a212004-11-15 17:04:14 +00004879
njn22cfccb2004-11-27 16:10:23 +00004880 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00004881 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00004882 vec = (struct vki_iovec *)ARG2;
4883 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00004884 PRE_MEM_WRITE( "readv(vector[...])",
4885 (Addr)vec[i].iov_base, vec[i].iov_len );
4886 }
jsgf855d93d2003-10-13 22:26:55 +00004887 }
4888}
4889
nethercote85a456f2004-11-16 17:31:56 +00004890POST(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004891{
sewardja8d8e232005-06-07 20:04:56 +00004892 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004893 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00004894 Int i;
njn22cfccb2004-11-27 16:10:23 +00004895 struct vki_iovec * vec = (struct vki_iovec *)ARG2;
4896 Int remains = RES;
jsgf855d93d2003-10-13 22:26:55 +00004897
njn22cfccb2004-11-27 16:10:23 +00004898 /* RES holds the number of bytes read. */
4899 for (i = 0; i < (Int)ARG3; i++) {
jsgf855d93d2003-10-13 22:26:55 +00004900 Int nReadThisBuf = vec[i].iov_len;
4901 if (nReadThisBuf > remains) nReadThisBuf = remains;
nethercoteef0c7662004-11-06 15:38:43 +00004902 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
jsgf855d93d2003-10-13 22:26:55 +00004903 remains -= nReadThisBuf;
4904 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4905 }
4906 }
4907}
4908
sewardja8d8e232005-06-07 20:04:56 +00004909PRE(sys_rename)
jsgf855d93d2003-10-13 22:26:55 +00004910{
njn22cfccb2004-11-27 16:10:23 +00004911 PRINT("sys_rename ( %p, %p )", ARG1, ARG2 );
nethercote9a3beb92004-11-12 17:07:26 +00004912 PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00004913 PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
4914 PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00004915}
4916
sewardj78b50e42005-06-08 01:47:28 +00004917PRE(sys_rmdir)
4918{
4919 *flags |= SfMayBlock;
4920 PRINT("sys_rmdir ( %p )", ARG1);
4921 PRE_REG_READ1(long, "rmdir", const char *, pathname);
4922 PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
4923}
4924
sewardja8d8e232005-06-07 20:04:56 +00004925PRE(sys_select)
jsgf855d93d2003-10-13 22:26:55 +00004926{
sewardja8d8e232005-06-07 20:04:56 +00004927 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004928 PRINT("sys_select ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotef1049bf2004-11-14 17:03:47 +00004929 PRE_REG_READ5(long, "select",
4930 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
4931 vki_fd_set *, exceptfds, struct timeval *, timeout);
4932 // XXX: this possibly understates how much memory is read.
njn22cfccb2004-11-27 16:10:23 +00004933 if (ARG2 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004934 PRE_MEM_READ( "select(readfds)",
njn22cfccb2004-11-27 16:10:23 +00004935 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
4936 if (ARG3 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004937 PRE_MEM_READ( "select(writefds)",
njn22cfccb2004-11-27 16:10:23 +00004938 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
4939 if (ARG4 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004940 PRE_MEM_READ( "select(exceptfds)",
njn22cfccb2004-11-27 16:10:23 +00004941 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
4942 if (ARG5 != 0)
4943 PRE_MEM_READ( "select(timeout)", ARG5, sizeof(struct vki_timeval) );
nethercotef1049bf2004-11-14 17:03:47 +00004944}
4945
sewardje6d5e722005-06-10 10:27:55 +00004946PRE(sys_setgid)
4947{
4948 PRINT("sys_setgid ( %d )", ARG1);
4949 PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
4950}
sewardj696c5512005-06-08 23:38:32 +00004951
4952PRE(sys_setsid)
4953{
4954 PRINT("sys_setsid ( )");
4955 PRE_REG_READ0(long, "setsid");
4956}
4957
sewardje6d5e722005-06-10 10:27:55 +00004958PRE(sys_setgroups)
4959{
4960 PRINT("setgroups ( %llu, %p )", (ULong)ARG1, ARG2);
4961 PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
4962 if (ARG1 > 0)
4963 PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
4964}
sewardj696c5512005-06-08 23:38:32 +00004965
4966PRE(sys_setpgid)
4967{
4968 PRINT("setpgid ( %d, %d )", ARG1, ARG2);
4969 PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
4970}
4971
4972PRE(sys_setregid)
4973{
4974 PRINT("sys_setregid ( %d, %d )", ARG1, ARG2);
4975 PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
4976}
4977
sewardje6d5e722005-06-10 10:27:55 +00004978PRE(sys_setreuid)
4979{
4980 PRINT("sys_setreuid ( 0x%x, 0x%x )", ARG1, ARG2);
4981 PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
4982}
nethercote9c311eb2004-11-12 18:20:12 +00004983
sewardja8d8e232005-06-07 20:04:56 +00004984PRE(sys_setrlimit)
jsgf855d93d2003-10-13 22:26:55 +00004985{
njn22cfccb2004-11-27 16:10:23 +00004986 PRINT("sys_setrlimit ( %d, %p )", ARG1,ARG2);
nethercote17258dc2004-11-12 19:55:08 +00004987 PRE_REG_READ2(long, "setrlimit",
4988 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00004989 PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
fitzhardingeb50068f2004-02-24 23:42:55 +00004990
njn22cfccb2004-11-27 16:10:23 +00004991 if (ARG1 == VKI_RLIMIT_NOFILE) {
4992 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
4993 ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
sewardja8d8e232005-06-07 20:04:56 +00004994 SET_STATUS_Failure( VKI_EPERM );
thughesad1c9562004-06-26 11:27:52 +00004995 }
4996 else {
njn22cfccb2004-11-27 16:10:23 +00004997 VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
sewardja8d8e232005-06-07 20:04:56 +00004998 SET_STATUS_Success( 0 );
thughesad1c9562004-06-26 11:27:52 +00004999 }
5000 }
njn22cfccb2004-11-27 16:10:23 +00005001 else if (ARG1 == VKI_RLIMIT_DATA) {
5002 if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max ||
5003 ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00005004 SET_STATUS_Failure( VKI_EPERM );
thughesaa4fb112004-09-11 14:19:25 +00005005 }
5006 else {
njn22cfccb2004-11-27 16:10:23 +00005007 VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00005008 SET_STATUS_Success( 0 );
thughesaa4fb112004-09-11 14:19:25 +00005009 }
fitzhardingeb50068f2004-02-24 23:42:55 +00005010 }
njn22cfccb2004-11-27 16:10:23 +00005011 else if (ARG1 == VKI_RLIMIT_STACK && tid == 1) {
5012 if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max ||
5013 ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00005014 SET_STATUS_Failure( VKI_EPERM );
thughesc37184f2004-09-11 14:16:57 +00005015 }
5016 else {
sewardja8d8e232005-06-07 20:04:56 +00005017 VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
njn22cfccb2004-11-27 16:10:23 +00005018 VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00005019 SET_STATUS_Success( 0 );
thughesc37184f2004-09-11 14:16:57 +00005020 }
5021 }
jsgf855d93d2003-10-13 22:26:55 +00005022}
5023
sewardje6d5e722005-06-10 10:27:55 +00005024PRE(sys_setuid)
5025{
5026 PRINT("sys_setuid ( %d )", ARG1);
5027 PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
5028}
jsgf855d93d2003-10-13 22:26:55 +00005029
sewardj696c5512005-06-08 23:38:32 +00005030PRE(sys_newstat)
5031{
5032 PRINT("sys_newstat ( %p(%s), %p )", ARG1,ARG1,ARG2);
5033 PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
5034 PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
5035 PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
5036}
5037
5038POST(sys_newstat)
5039{
5040 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
5041}
5042
5043PRE(sys_statfs)
5044{
5045 PRINT("sys_statfs ( %p, %p )",ARG1,ARG2);
5046 PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
5047 PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
5048 PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
5049}
sewardj696c5512005-06-08 23:38:32 +00005050POST(sys_statfs)
5051{
5052 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
5053}
5054
sewardje6d5e722005-06-10 10:27:55 +00005055PRE(sys_statfs64)
5056{
5057 PRINT("sys_statfs64 ( %p, %llu, %p )",ARG1,(ULong)ARG2,ARG3);
5058 PRE_REG_READ3(long, "statfs64",
5059 const char *, path, vki_size_t, size, struct statfs64 *, buf);
5060 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
5061 PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
5062}
5063POST(sys_statfs64)
5064{
5065 POST_MEM_WRITE( ARG3, ARG2 );
5066}
sewardj78b50e42005-06-08 01:47:28 +00005067
5068PRE(sys_symlink)
5069{
5070 *flags |= SfMayBlock;
5071 PRINT("sys_symlink ( %p, %p )",ARG1,ARG2);
5072 PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
5073 PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
5074 PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
5075}
sewardj9efbbef2005-03-01 16:45:23 +00005076
sewardja8d8e232005-06-07 20:04:56 +00005077PRE(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00005078{
5079 /* time_t time(time_t *t); */
njn22cfccb2004-11-27 16:10:23 +00005080 PRINT("sys_time ( %p )",ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00005081 PRE_REG_READ1(long, "time", int *, t);
njn22cfccb2004-11-27 16:10:23 +00005082 if (ARG1 != 0) {
5083 PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00005084 }
5085}
5086
nethercote85a456f2004-11-16 17:31:56 +00005087POST(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00005088{
njn22cfccb2004-11-27 16:10:23 +00005089 if (ARG1 != 0) {
5090 POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00005091 }
5092}
5093
sewardj78b50e42005-06-08 01:47:28 +00005094PRE(sys_times)
5095{
5096 PRINT("sys_times ( %p )", ARG1);
5097 PRE_REG_READ1(long, "times", struct tms *, buf);
tom18f19272005-07-18 11:03:35 +00005098 if (ARG1 != 0) {
5099 PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
5100 }
sewardj78b50e42005-06-08 01:47:28 +00005101}
5102
5103POST(sys_times)
5104{
5105 if (ARG1 != 0) {
5106 POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
5107 }
5108}
5109
5110PRE(sys_umask)
5111{
5112 PRINT("sys_umask ( %d )", ARG1);
5113 PRE_REG_READ1(long, "umask", int, mask);
5114}
jsgf855d93d2003-10-13 22:26:55 +00005115
sewardja8d8e232005-06-07 20:04:56 +00005116PRE(sys_unlink)
jsgf855d93d2003-10-13 22:26:55 +00005117{
sewardja8d8e232005-06-07 20:04:56 +00005118 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005119 PRINT("sys_unlink ( %p(%s) )", ARG1,ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00005120 PRE_REG_READ1(long, "unlink", const char *, pathname);
njn22cfccb2004-11-27 16:10:23 +00005121 PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00005122}
5123
sewardja8d8e232005-06-07 20:04:56 +00005124PRE(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00005125{
njn22cfccb2004-11-27 16:10:23 +00005126 PRINT("sys_newuname ( %p )", ARG1);
nethercote1a1b9b72004-11-12 11:19:36 +00005127 PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
njn22cfccb2004-11-27 16:10:23 +00005128 PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00005129}
5130
nethercote85a456f2004-11-16 17:31:56 +00005131POST(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00005132{
njn22cfccb2004-11-27 16:10:23 +00005133 if (ARG1 != 0) {
5134 POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00005135 }
5136}
5137
sewardja8d8e232005-06-07 20:04:56 +00005138PRE(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00005139{
sewardja8d8e232005-06-07 20:04:56 +00005140 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005141 PRINT("sys_waitpid ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercotec6851dd2004-11-11 18:00:47 +00005142 PRE_REG_READ3(long, "waitpid",
5143 vki_pid_t, pid, unsigned int *, status, int, options);
jsgf855d93d2003-10-13 22:26:55 +00005144
njn22cfccb2004-11-27 16:10:23 +00005145 if (ARG2 != (Addr)NULL)
5146 PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00005147}
5148
nethercote85a456f2004-11-16 17:31:56 +00005149POST(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00005150{
njn22cfccb2004-11-27 16:10:23 +00005151 if (ARG2 != (Addr)NULL)
5152 POST_MEM_WRITE( ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00005153}
5154
sewardja8d8e232005-06-07 20:04:56 +00005155PRE(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00005156{
sewardja8d8e232005-06-07 20:04:56 +00005157 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005158 PRINT("sys_wait4 ( %d, %p, %d, %p )", ARG1,ARG2,ARG3,ARG4);
jsgf855d93d2003-10-13 22:26:55 +00005159
nethercote7f7e4d12004-11-15 12:28:58 +00005160 PRE_REG_READ4(long, "wait4",
5161 vki_pid_t, pid, unsigned int *, status, int, options,
5162 struct rusage *, rusage);
njn22cfccb2004-11-27 16:10:23 +00005163 if (ARG2 != (Addr)NULL)
5164 PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
5165 if (ARG4 != (Addr)NULL)
5166 PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00005167}
5168
nethercote85a456f2004-11-16 17:31:56 +00005169POST(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00005170{
njn22cfccb2004-11-27 16:10:23 +00005171 if (ARG2 != (Addr)NULL)
5172 POST_MEM_WRITE( ARG2, sizeof(int) );
5173 if (ARG4 != (Addr)NULL)
5174 POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00005175}
5176
sewardja8d8e232005-06-07 20:04:56 +00005177PRE(sys_writev)
jsgf855d93d2003-10-13 22:26:55 +00005178{
jsgf855d93d2003-10-13 22:26:55 +00005179 Int i;
nethercote73b526f2004-10-31 18:48:21 +00005180 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00005181 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005182 PRINT("sys_writev ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00005183 PRE_REG_READ3(ssize_t, "writev",
5184 unsigned long, fd, const struct iovec *, vector,
5185 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00005186 if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00005187 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00005188 } else {
nethercoteef0c7662004-11-06 15:38:43 +00005189 PRE_MEM_READ( "writev(vector)",
njn22cfccb2004-11-27 16:10:23 +00005190 ARG2, ARG3 * sizeof(struct vki_iovec) );
5191 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00005192 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00005193 vec = (struct vki_iovec *)ARG2;
5194 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00005195 PRE_MEM_READ( "writev(vector[...])",
5196 (Addr)vec[i].iov_base, vec[i].iov_len );
5197 }
jsgf855d93d2003-10-13 22:26:55 +00005198 }
5199}
5200
sewardje6d5e722005-06-10 10:27:55 +00005201PRE(sys_utimes)
5202{
5203 PRINT("sys_utimes ( %p, %p )", ARG1,ARG2);
5204 PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
5205 PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
5206 if (ARG2 != 0)
5207 PRE_MEM_READ( "utimes(tvp)", ARG2, sizeof(struct vki_timeval) );
5208}
5209
sewardj696c5512005-06-08 23:38:32 +00005210PRE(sys_acct)
5211{
5212 PRINT("sys_acct ( %p )", ARG1);
5213 PRE_REG_READ1(long, "acct", const char *, filename);
5214 PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
5215}
muellerd3502b62003-11-19 00:43:57 +00005216
sewardja8d8e232005-06-07 20:04:56 +00005217PRE(sys_pause)
thughes2f8d5f82004-09-11 14:29:19 +00005218{
sewardja8d8e232005-06-07 20:04:56 +00005219 *flags |= SfMayBlock;
nethercote0df495a2004-11-11 16:38:21 +00005220 PRINT("sys_pause ( )");
5221 PRE_REG_READ0(long, "pause");
jsgf855d93d2003-10-13 22:26:55 +00005222}
5223
sewardja8d8e232005-06-07 20:04:56 +00005224//zz // XXX: x86-specific
5225//zz PRE(sys_sigsuspend, SfMayBlock)
5226//zz {
5227//zz /* The C library interface to sigsuspend just takes a pointer to
5228//zz a signal mask but this system call has three arguments - the first
5229//zz two don't appear to be used by the kernel and are always passed as
5230//zz zero by glibc and the third is the first word of the signal mask
5231//zz so only 32 signals are supported.
5232//zz
5233//zz In fact glibc normally uses rt_sigsuspend if it is available as
5234//zz that takes a pointer to the signal mask so supports more signals.
5235//zz */
5236//zz PRINT("sys_sigsuspend ( %d, %d, %d )", ARG1,ARG2,ARG3 );
5237//zz PRE_REG_READ3(int, "sigsuspend",
5238//zz int, history0, int, history1,
5239//zz vki_old_sigset_t, mask);
5240//zz }
jsgf855d93d2003-10-13 22:26:55 +00005241
nethercotea3a2c142004-11-14 14:13:05 +00005242// XXX: x86-specific
sewardja8d8e232005-06-07 20:04:56 +00005243PRE(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00005244{
njn22cfccb2004-11-27 16:10:23 +00005245 PRINT("sigaltstack ( %p, %p )",ARG1,ARG2);
nethercoteb77dee62004-11-16 17:13:24 +00005246 PRE_REG_READ2(int, "sigaltstack",
5247 const vki_stack_t *, ss, vki_stack_t *, oss);
njn22cfccb2004-11-27 16:10:23 +00005248 if (ARG1 != 0) {
tom92098db2005-07-18 23:18:10 +00005249 const vki_stack_t *ss = (vki_stack_t *)ARG1;
5250 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
5251 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
5252 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
jsgf855d93d2003-10-13 22:26:55 +00005253 }
njn22cfccb2004-11-27 16:10:23 +00005254 if (ARG2 != 0) {
5255 PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
jsgf855d93d2003-10-13 22:26:55 +00005256 }
5257
sewardja8d8e232005-06-07 20:04:56 +00005258 SET_STATUS_from_SysRes(
5259 VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
5260 (vki_stack_t*)ARG2)
5261 );
jsgf855d93d2003-10-13 22:26:55 +00005262}
nethercote85a456f2004-11-16 17:31:56 +00005263POST(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00005264{
sewardja8d8e232005-06-07 20:04:56 +00005265 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00005266 if (RES == 0 && ARG2 != 0)
5267 POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
jsgf855d93d2003-10-13 22:26:55 +00005268}
5269
sewardje6d5e722005-06-10 10:27:55 +00005270#undef PRE
5271#undef POST
sewardj2e93c502002-04-12 11:12:52 +00005272
sewardjde4a1d02002-03-22 01:27:54 +00005273/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00005274/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005275/*--------------------------------------------------------------------*/
sewardj45f4e7c2005-09-27 19:20:21 +00005276