syswrap openat2 for all linux arches
[valgrind.git] / coregrind / m_syswrap / syswrap-solaris.c
blobb5489644c126ba8575ad86bbfb669a745bd5849c
2 /*--------------------------------------------------------------------*/
3 /*--- Solaris-specific syscalls, etc. syswrap-solaris.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2011-2017 Petr Pavlu
11 setup@dagobah.cz
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.
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.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 /* Copyright 2013-2017, Ivo Raisr <ivosh@ivosh.net>. */
31 /* Copyright 2015-2017, Tomas Jedlicka <jedlickat@gmail.com>. */
33 /* Copyright 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
35 #if defined(VGO_solaris)
37 #include "libvex_guest_offsets.h"
38 #include "pub_core_basics.h"
39 #include "pub_core_vki.h"
40 #include "pub_core_vkiscnums.h"
41 #include "pub_core_threadstate.h"
42 #include "pub_core_aspacemgr.h"
43 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
44 #include "pub_core_debuglog.h"
45 #include "pub_core_clientstate.h"
46 #include "pub_core_gdbserver.h"
47 #include "pub_core_inner.h"
48 #include "pub_core_libcassert.h"
49 #include "pub_core_libcbase.h"
50 #include "pub_core_libcfile.h"
51 #include "pub_core_libcprint.h"
52 #include "pub_core_libcproc.h"
53 #include "pub_core_libcsignal.h"
54 #include "pub_core_machine.h" // VG_(get_SP)
55 #include "pub_core_mallocfree.h"
56 #include "pub_core_options.h"
57 #include "pub_core_tooliface.h"
58 #include "pub_core_transtab.h" // VG_(discard_translations)
59 #include "pub_core_scheduler.h"
60 #include "pub_core_sigframe.h"
61 #include "pub_core_signals.h"
62 #include "pub_core_stacks.h"
63 #include "pub_core_syscall.h"
64 #include "pub_core_syswrap.h"
65 #include "pub_core_ume.h"
66 #if defined(ENABLE_INNER_CLIENT_REQUEST)
67 #include "pub_core_clreq.h"
68 #endif
70 #include "priv_types_n_macros.h"
71 #include "priv_syswrap-generic.h"
72 #include "priv_syswrap-main.h"
73 #include "priv_syswrap-solaris.h"
75 /* Return the number of non-dead and daemon threads.
76 count_daemon == True: count daemon threads
77 count_daemon == False: count non-daemon threads */
78 static UInt count_living_daemon_threads(Bool count_daemon)
80 UInt count = 0;
81 for (ThreadId tid = 1; tid < VG_N_THREADS; tid++)
82 if (VG_(threads)[tid].status != VgTs_Empty &&
83 VG_(threads)[tid].status != VgTs_Zombie &&
84 VG_(threads)[tid].os_state.daemon_thread == count_daemon)
85 count++;
87 return count;
90 /* Note: The following functions (thread_wrapper, run_a_thread_NORETURN,
91 ML_(start_thread_NORETURN), ML_(allocstack) and
92 VG_(main_thread_wrapper_NORETURN)) are based on the code in
93 syswrap-linux.c. Keep them synchronized! */
95 /* Run a thread from beginning to end and return the thread's
96 scheduler-return-code. */
97 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
99 VgSchedReturnCode ret;
100 ThreadId tid = (ThreadId)tidW;
101 Int lwpid = VG_(gettid)();
102 ThreadState *tst = VG_(get_ThreadState)(tid);
104 VG_(debugLog)(1, "syswrap-solaris",
105 "thread_wrapper(tid=%u,lwpid=%d): entry\n",
106 tid, lwpid);
108 vg_assert(tst->status == VgTs_Init);
110 /* Make sure we get the CPU lock before doing anything significant. */
111 VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)");
113 if (0)
114 VG_(printf)("thread tid %u started: stack = %p\n", tid, (void *)&tid);
116 /* Make sure error reporting is enabled in the new thread. */
117 tst->err_disablement_level = 0;
119 if (tid == 1)
120 VG_TRACK(pre_thread_first_insn, tid);
121 else {
122 /* For newly created threads, VG_TRACK(pre_thread_first_insn, tid) is
123 invoked later from PRE(sys_getsetcontext)() when setucontext()
124 called from _thrp_setup() concludes new thread setup. Invoking it
125 here would be way too early - new thread has no stack, yet. */
128 tst->os_state.lwpid = lwpid;
129 tst->os_state.threadgroup = VG_(getpid)();
131 /* Thread created with all signals blocked; scheduler will set the
132 appropriate mask. */
134 ret = VG_(scheduler)(tid);
136 vg_assert(VG_(is_exiting)(tid));
138 vg_assert(tst->status == VgTs_Runnable);
139 vg_assert(VG_(is_running_thread)(tid));
141 VG_(debugLog)(1, "syswrap-solaris",
142 "thread_wrapper(tid=%u,lwpid=%d): exit, schedreturncode %s\n",
143 tid, lwpid, VG_(name_of_VgSchedReturnCode)(ret));
145 /* Return to caller, still holding the lock. */
146 return ret;
149 /* Run a thread all the way to the end, then do appropriate exit actions
150 (this is the last-one-out-turn-off-the-lights bit). */
151 static void run_a_thread_NORETURN(Word tidW)
153 ThreadId tid = (ThreadId)tidW;
154 VgSchedReturnCode src;
155 Int c;
156 ThreadState *tst;
157 #ifdef ENABLE_INNER_CLIENT_REQUEST
158 Int registered_vgstack_id;
159 #endif
161 VG_(debugLog)(1, "syswrap-solaris",
162 "run_a_thread_NORETURN(tid=%u): pre-thread_wrapper\n",
163 tid);
165 tst = VG_(get_ThreadState)(tid);
166 vg_assert(tst);
168 /* A thread has two stacks:
169 * the simulated stack (used by the synthetic cpu. Guest process
170 is using this stack).
171 * the valgrind stack (used by the real cpu. Valgrind code is running
172 on this stack).
173 When Valgrind runs as an inner, it must signal that its (real) stack
174 is the stack to use by the outer to e.g. do stacktraces.
176 INNER_REQUEST
177 (registered_vgstack_id
178 = VALGRIND_STACK_REGISTER(tst->os_state.valgrind_stack_base,
179 tst->os_state.valgrind_stack_init_SP));
181 /* Run the thread all the way through. */
182 src = thread_wrapper(tid);
184 VG_(debugLog)(1, "syswrap-solaris",
185 "run_a_thread_NORETURN(tid=%u): post-thread_wrapper\n",
186 tid);
188 c = count_living_daemon_threads(False);
189 vg_assert(c >= 1); /* Stay sane. */
191 /* Tell the tool that schedctl data belonging to this thread are gone. */
192 Addr a = tst->os_state.schedctl_data;
193 if (a != 0)
194 VG_TRACK(die_mem_munmap, a, sizeof(struct vki_sc_shared));
196 /* Deregister thread's stack. */
197 if (tst->os_state.stk_id != NULL_STK_ID)
198 VG_(deregister_stack)(tst->os_state.stk_id);
200 /* Tell the tool this thread is exiting. */
201 VG_TRACK(pre_thread_ll_exit, tid);
203 /* If the thread is exiting with errors disabled, complain loudly;
204 doing so is bad (does the user know this has happened?) Also, in all
205 cases, be paranoid and clear the flag anyway so that the thread slot is
206 safe in this respect if later reallocated. This should be unnecessary
207 since the flag should be cleared when the slot is reallocated, in
208 thread_wrapper(). */
209 if (tst->err_disablement_level > 0) {
210 VG_(umsg)(
211 "WARNING: exiting thread has error reporting disabled.\n"
212 "WARNING: possibly as a result of some mistake in the use\n"
213 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
215 VG_(debugLog)(
216 1, "syswrap-solaris",
217 "run_a_thread_NORETURN(tid=%u): "
218 "WARNING: exiting thread has err_disablement_level = %u\n",
219 tid, tst->err_disablement_level
222 tst->err_disablement_level = 0;
224 if (c == 1) {
225 UInt daemon_threads = count_living_daemon_threads(True);
226 if (daemon_threads == 0)
227 VG_(debugLog)(1, "syswrap-solaris",
228 "run_a_thread_NORETURN(tid=%u): "
229 "last one standing\n",
230 tid);
231 else
232 VG_(debugLog)(1, "syswrap-solaris",
233 "run_a_thread_NORETURN(tid=%u): "
234 "last non-daemon thread standing "
235 "[daemon threads=%u]\n",
236 tid, daemon_threads);
238 /* We are the last non-daemon thread standing. Keep hold of the lock and
239 carry on to show final tool results, then exit the entire system.
240 Use the continuation pointer set at startup in m_main. */
241 if ((src == VgSrc_ExitThread) && (daemon_threads > 0))
242 src = VgSrc_ExitProcess;
243 (*VG_(address_of_m_main_shutdown_actions_NORETURN))(tid, src);
245 else {
246 VG_(debugLog)(1, "syswrap-solaris",
247 "run_a_thread_NORETURN(tid=%u): "
248 "not last one standing\n",
249 tid);
251 /* OK, thread is dead, but others still exist. Just exit. */
253 /* This releases the run lock. */
254 VG_(exit_thread)(tid);
255 vg_assert(tst->status == VgTs_Zombie);
256 vg_assert(sizeof(tst->status) == 4);
258 INNER_REQUEST(VALGRIND_STACK_DEREGISTER(registered_vgstack_id));
260 /* We have to use this sequence to terminate the thread to
261 prevent a subtle race. If VG_(exit_thread)() had left the
262 ThreadState as Empty, then it could have been reallocated, reusing
263 the stack while we're doing these last cleanups. Instead,
264 VG_(exit_thread) leaves it as Zombie to prevent reallocation. We
265 need to make sure we don't touch the stack between marking it Empty
266 and exiting. Hence the assembler. */
267 #if defined(VGP_x86_solaris)
268 /* Luckily lwp_exit doesn't take any arguments so we don't have to mess
269 with the stack. */
270 __asm__ __volatile__ (
271 "movl %[EMPTY], %[status]\n" /* set tst->status = VgTs_Empty */
272 "movl $"VG_STRINGIFY(__NR_lwp_exit)", %%eax\n"
273 "int $0x91\n" /* lwp_exit() */
274 : [status] "=m" (tst->status)
275 : [EMPTY] "n" (VgTs_Empty)
276 : "eax", "edx", "cc", "memory");
277 #elif defined(VGP_amd64_solaris)
278 __asm__ __volatile__ (
279 "movl %[EMPTY], %[status]\n" /* set tst->status = VgTs_Empty */
280 "movq $"VG_STRINGIFY(__NR_lwp_exit)", %%rax\n"
281 "syscall\n" /* lwp_exit() */
282 : [status] "=m" (tst->status)
283 : [EMPTY] "n" (VgTs_Empty)
284 : "rax", "rdx", "cc", "memory");
285 #else
286 # error "Unknown platform"
287 #endif
289 VG_(core_panic)("Thread exit failed?\n");
292 /*NOTREACHED*/
293 vg_assert(0);
296 Word ML_(start_thread_NORETURN)(void *arg)
298 ThreadState *tst = (ThreadState*)arg;
299 ThreadId tid = tst->tid;
301 run_a_thread_NORETURN((Word)tid);
302 /*NOTREACHED*/
303 vg_assert(0);
306 /* Allocate a stack for this thread, if it doesn't already have one.
307 They're allocated lazily, and never freed. Returns the initial stack
308 pointer value to use, or 0 if allocation failed. */
309 Addr ML_(allocstack)(ThreadId tid)
311 ThreadState *tst = VG_(get_ThreadState)(tid);
312 VgStack *stack;
313 Addr initial_SP;
315 /* Either the stack_base and stack_init_SP are both zero (in which
316 case a stack hasn't been allocated) or they are both non-zero,
317 in which case it has. */
319 if (tst->os_state.valgrind_stack_base == 0)
320 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
322 if (tst->os_state.valgrind_stack_base != 0)
323 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
325 /* If no stack is present, allocate one. */
327 if (tst->os_state.valgrind_stack_base == 0) {
328 stack = VG_(am_alloc_VgStack)( &initial_SP );
329 if (stack) {
330 tst->os_state.valgrind_stack_base = (Addr)stack;
331 tst->os_state.valgrind_stack_init_SP = initial_SP;
335 if (0)
336 VG_(printf)("stack for tid %u at %p; init_SP=%p\n",
337 tid,
338 (void*)tst->os_state.valgrind_stack_base,
339 (void*)tst->os_state.valgrind_stack_init_SP);
341 return tst->os_state.valgrind_stack_init_SP;
344 /* Allocate a stack for the main thread, and run it all the way to the
345 end. Although we already have a working VgStack (VG_(interim_stack)) it's
346 better to allocate a new one, so that overflow detection works uniformly
347 for all threads. Also initialize the GDT (for normal threads, this is done
348 in the PRE wrapper of lwp_create). */
349 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
351 Addr sp;
353 VG_(debugLog)(1, "syswrap-solaris",
354 "entering VG_(main_thread_wrapper_NORETURN)\n");
356 sp = ML_(allocstack)(tid);
357 #if defined(ENABLE_INNER_CLIENT_REQUEST)
359 // we must register the main thread stack before the call
360 // to ML_(call_on_new_stack_0_1), otherwise the outer valgrind
361 // reports 'write error' on the non registered stack.
362 ThreadState *tst = VG_(get_ThreadState)(tid);
363 INNER_REQUEST
364 ((void)
365 VALGRIND_STACK_REGISTER(tst->os_state.valgrind_stack_base,
366 tst->os_state.valgrind_stack_init_SP));
368 #endif
370 #if defined(VGP_x86_solaris)
372 ThreadState *tst = VG_(get_ThreadState)(tid);
373 ML_(setup_gdt)(&tst->arch.vex);
374 ML_(update_gdt_lwpgs)(tid);
376 #elif defined(VGP_amd64_solaris)
377 /* Nothing to do. */
378 #else
379 # error "Unknown platform"
380 #endif
382 /* If we can't even allocate the first thread's stack, we're hosed.
383 Give up. */
384 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
386 /* Shouldn't be any other threads around yet. */
387 vg_assert(VG_(count_living_threads)() == 1);
389 ML_(call_on_new_stack_0_1)(
390 (Addr)sp, /* stack */
391 0, /* bogus return address */
392 run_a_thread_NORETURN, /* fn to call */
393 (Word)tid /* arg to give it */
396 /*NOTREACHED*/
397 vg_assert(0);
400 /* Deallocate the GDT for a thread. */
401 void VG_(cleanup_thread)(ThreadArchState *arch)
403 #if defined(VGP_x86_solaris)
404 ML_(cleanup_gdt)(&arch->vex);
405 #elif defined(VGP_amd64_solaris)
406 /* Nothing to do. */
407 #else
408 # error "Unknown platform"
409 #endif
413 * Notify core about spring cleaning of schedctl data pages for all threads
414 * in child post-fork handler. Libc will issue new schedctl syscalls for threads
415 * in the child when needs arise.
417 * See also POST(schedctl) and run_a_thread_NORETURN() when a thread exits.
419 static void clean_schedctl_data(ThreadId tid)
421 UInt i;
422 for (i = 0; i < VG_N_THREADS; i++) {
423 ThreadState *tst = &VG_(threads)[i];
424 if (tst->status != VgTs_Empty) {
425 Addr a = tst->os_state.schedctl_data;
426 if (a != 0) {
427 tst->os_state.schedctl_data = 0;
428 a = VG_PGROUNDDN(a);
429 if (VG_(am_find_anon_segment)(a))
430 VG_(am_notify_munmap)(a, VKI_PAGE_SIZE);
436 void VG_(syswrap_init)(void)
438 VG_(atfork)(NULL, NULL, clean_schedctl_data);
441 /* Changes ownership of a memory mapping shared between kernel and the client
442 process. This mapping should have already been pre-arranged during process
443 address space initialization happening in kernel. Valgrind on startup created
444 a segment for this mapping categorized as Valgrind's owned anonymous.
445 Size of this mapping typically varies among Solaris versions but should be
446 page aligned.
447 If 'once_only' is 'True', it is expected this function is called once only
448 and the mapping ownership has not been changed, yet [useful during
449 initialization]. If 'False', this function can be called many times but does
450 change ownership only upon the first invocation [useful in syscall wrappers].
452 void VG_(change_mapping_ownership)(Addr addr, Bool once_only)
454 const NSegment *seg = VG_(am_find_anon_segment)(addr);
455 vg_assert(seg != NULL);
456 vg_assert(seg->start == addr);
457 vg_assert(VG_IS_PAGE_ALIGNED(seg->start));
458 vg_assert(VG_IS_PAGE_ALIGNED(seg->end + 1));
459 SizeT size = seg->end - seg->start + 1;
460 vg_assert(size > 0);
462 Bool do_change = False;
463 if (once_only) {
464 vg_assert(VG_(am_is_valid_for_valgrind)(addr, size, VKI_PROT_READ));
465 do_change = True;
466 } else {
467 if (!VG_(am_is_valid_for_client)(addr, size, VKI_PROT_READ))
468 do_change = True;
471 if (do_change) {
472 Bool change_ownership_OK = VG_(am_change_ownership_v_to_c)(addr, size);
473 vg_assert(change_ownership_OK);
475 /* Tell the tool about just discovered mapping. */
476 VG_TRACK(new_mem_startup,
477 addr, size,
478 True /* readable? */,
479 False /* writable? */,
480 False /* executable? */,
481 0 /* di_handle */);
485 /* Calculate the Fletcher-32 checksum of a given buffer. */
486 UInt ML_(fletcher32)(UShort *buf, SizeT blocks)
488 UInt sum1 = 0;
489 UInt sum2 = 0;
490 SizeT i;
492 for (i = 0; i < blocks; i++) {
493 sum1 = (sum1 + buf[i]) % 0xffff;
494 sum2 = (sum2 + sum1) % 0xffff;
497 return (sum2 << 16) | sum1;
500 /* Calculate the Fletcher-64 checksum of a given buffer. */
501 ULong ML_(fletcher64)(UInt *buf, SizeT blocks)
503 ULong sum1 = 0;
504 ULong sum2 = 0;
505 SizeT i;
507 for (i = 0; i < blocks; i++) {
508 sum1 = (sum1 + buf[i]) % 0xffffffff;
509 sum2 = (sum2 + sum1) % 0xffffffff;
511 return (sum2 << 32) | sum1;
514 /* Save a complete context (VCPU state, sigmask) of a given client thread
515 into the vki_ucontext_t structure. This structure is supposed to be
516 allocated in the client memory, a caller must make sure that the memory can
517 be dereferenced. The active tool is informed about the save. */
518 void VG_(save_context)(ThreadId tid, vki_ucontext_t *uc, CorePart part)
520 ThreadState *tst = VG_(get_ThreadState)(tid);
522 VG_TRACK(pre_mem_write, part, tid, "save_context(uc)", (Addr)uc,
523 sizeof(*uc));
525 uc->uc_flags = VKI_UC_ALL;
526 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_flags,
527 sizeof(uc->uc_flags));
529 /* Old context */
530 uc->uc_link = tst->os_state.oldcontext;
531 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_link,
532 sizeof(uc->uc_link));
534 /* Clear uc->vki_uc_signo. This slot is used by the signal machinery to
535 store a signal number. */
536 VKI_UC_SIGNO(uc) = 0;
538 /* Sigmask */
539 uc->uc_sigmask = tst->sig_mask;
540 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_sigmask,
541 sizeof(uc->uc_sigmask));
543 /* Stack */
545 if (tst->os_state.ustack
546 && ML_(safe_to_deref)(tst->os_state.ustack, sizeof(vki_stack_t))
547 && tst->os_state.ustack->ss_size) {
548 /* If ustack points to a valid stack copy it to ucontext. */
549 uc->uc_stack = *tst->os_state.ustack;
551 else {
552 /* Ustack is not valid. A correct stack has to be figured out
553 manually. */
554 SysRes res;
555 vki_stack_t altstack;
557 /* Get information about alternate stack. */
558 res = VG_(do_sys_sigaltstack)(tid, NULL, &altstack);
559 vg_assert(!sr_isError(res));
561 if (altstack.ss_flags == VKI_SS_ONSTACK) {
562 /* If the alternate stack is active copy it to ucontext. */
563 uc->uc_stack = altstack;
565 else {
566 /* No information about stack is present, save information about
567 current main stack to ucontext. This branch should be reached
568 only by the main thread. */
569 ThreadState *tst2 = VG_(get_ThreadState)(1);
570 uc->uc_stack.ss_sp = (void*)(tst2->client_stack_highest_byte + 1
571 - tst2->client_stack_szB);
572 uc->uc_stack.ss_size = tst2->client_stack_szB;
573 uc->uc_stack.ss_flags = 0;
577 VG_TRACK(post_mem_write, part, tid, (Addr)&uc->uc_stack,
578 sizeof(uc->uc_stack));
581 /* Save the architecture-specific part of the context. */
582 ML_(save_machine_context)(tid, uc, part);
585 /* Set a complete context (VCPU state, sigmask) of a given client thread
586 according to values passed in the vki_ucontext_t structure. This structure
587 is supposed to be allocated in the client memory, a caller must make sure
588 that the memory can be dereferenced. The active tool is informed about
589 what parts of the structure are read.
591 This function is a counterpart to VG_(save_context)(). */
592 void VG_(restore_context)(ThreadId tid, vki_ucontext_t *uc, CorePart part,
593 Bool esp_is_thrptr)
595 ThreadState *tst = VG_(get_ThreadState)(tid);
596 Addr old_esp = VG_(get_SP)(tid);
598 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_flags)",
599 (Addr)&uc->uc_flags, sizeof(uc->uc_flags));
601 /* Old context */
602 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_link)",
603 (Addr)&uc->uc_link, sizeof(uc->uc_link));
604 tst->os_state.oldcontext = uc->uc_link;
606 /* Sigmask */
607 if (uc->uc_flags & VKI_UC_SIGMASK) {
608 SysRes res;
610 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_sigmask)",
611 (Addr)&uc->uc_sigmask, sizeof(uc->uc_sigmask));
612 res = VG_(do_sys_sigprocmask)(tid, VKI_SIG_SETMASK, &uc->uc_sigmask,
613 NULL);
614 /* Setting signal mask should never fail. */
615 vg_assert(!sr_isError(res));
618 /* Stack */
619 if (uc->uc_flags & VKI_UC_STACK) {
620 VG_TRACK(pre_mem_read, part, tid, "restore_context(uc->uc_stack)",
621 (Addr)&uc->uc_stack, sizeof(uc->uc_stack));
623 if (uc->uc_stack.ss_flags == VKI_SS_ONSTACK) {
624 /* This seems to be a little bit dangerous but it is what the kernel
625 does. */
626 if (VG_(clo_trace_signals))
627 VG_(dmsg)("restore_context, sigaltstack: tid %u, "
628 "ss %p{%p,sz=%lu,flags=%#x}\n",
629 tid, &uc->uc_stack, uc->uc_stack.ss_sp,
630 (SizeT)uc->uc_stack.ss_size, (UInt)uc->uc_stack.ss_flags);
632 tst->altstack.ss_sp = uc->uc_stack.ss_sp;
633 tst->altstack.ss_size = uc->uc_stack.ss_size;
634 /* Do not copy ss_flags, they are calculated dynamically by
635 Valgrind. */
638 /* Copyout the new stack. */
639 if (tst->os_state.ustack
640 && VG_(am_is_valid_for_client)((Addr)tst->os_state.ustack,
641 sizeof(*tst->os_state.ustack),
642 VKI_PROT_WRITE)) {
643 *tst->os_state.ustack = uc->uc_stack;
644 VG_TRACK(post_mem_write, part, tid, (Addr)&tst->os_state.ustack,
645 sizeof(tst->os_state.ustack));
649 /* Restore the architecture-specific part of the context. */
650 ML_(restore_machine_context)(tid, uc, part, esp_is_thrptr);
652 /* If the thread stack is already known, kill the deallocated stack area.
653 This is important when returning from a signal handler. */
654 if (tst->client_stack_highest_byte && tst->client_stack_szB) {
655 Addr end = tst->client_stack_highest_byte;
656 Addr start = end + 1 - tst->client_stack_szB;
657 Addr new_esp = VG_(get_SP)(tid);
659 /* Make sure that the old and new stack pointer are on the same (active)
660 stack. Alternate stack is currently never affected by this code. */
661 if (start <= old_esp && old_esp <= end
662 && start <= new_esp && new_esp <= end
663 && new_esp > old_esp)
664 VG_TRACK(die_mem_stack, old_esp - VG_STACK_REDZONE_SZB,
665 (new_esp - old_esp) + VG_STACK_REDZONE_SZB);
669 /* Set a client stack associated with a given thread id according to values
670 passed in the vki_stack_t structure. */
671 static void set_stack(ThreadId tid, vki_stack_t *st)
673 ThreadState *tst = VG_(get_ThreadState)(tid);
674 Addr new_start, new_end;
675 SizeT new_size;
676 Addr cur_start;
677 SizeT cur_size;
679 VG_(debugLog)(2, "syswrap-solaris",
680 "set stack: sp=%#lx, size=%#lx.\n",
681 (Addr)st->ss_sp, (SizeT)st->ss_size);
683 /* Stay sane. */
684 vg_assert(st->ss_flags == 0);
686 new_start = (Addr)st->ss_sp;
687 new_end = new_start + st->ss_size - 1;
688 new_size = st->ss_size;
689 cur_start = tst->client_stack_highest_byte + 1
690 - tst->client_stack_szB;
691 cur_size = tst->client_stack_szB;
693 if (new_start == cur_start && new_size == cur_size) {
694 /* No change is requested, bail out. */
695 return;
698 if (tid == 1 && (new_size == 0 || new_size > VG_(clstk_max_size))) {
699 /* The main thread requests to use a stack without any size checking, or
700 too big stack. Fallback to the maximum allocated client stack. */
702 /* TODO I think it is possible to give up on setting main stack anyway.
703 Valgrind knows where it is located and it is already registered as
704 VG_(clstk_id). */
706 new_size = VG_(clstk_max_size);
707 new_end = tst->client_stack_highest_byte;
708 new_start = new_end + 1 - new_size;
711 if (tst->os_state.stk_id == NULL_STK_ID) {
712 /* This thread doesn't have a stack set yet. */
713 VG_(debugLog)(2, "syswrap-solaris",
714 "Stack set to %#lx-%#lx (new) for thread %u.\n",
715 new_start, new_end, tid);
716 tst->os_state.stk_id = VG_(register_stack)(new_start, new_end);
717 } else {
718 /* Change a thread stack. */
719 VG_(debugLog)(2, "syswrap-solaris",
720 "Stack set to %#lx-%#lx (change) for thread %u.\n",
721 new_start, new_end, tid);
722 VG_(change_stack)(tst->os_state.stk_id, new_start, new_end);
724 tst->client_stack_highest_byte = new_end;
725 tst->client_stack_szB = new_size;
728 /* ---------------------------------------------------------------------
729 Door tracking. Used mainly for server side where door_return()
730 parameters alone do not contain sufficient information.
731 Also used on client side when new door descriptors are passed via
732 door_call() in desc_ptr. Not used for tracking door descriptors
733 explicitly open()'ed [generic fd tracking is used in that case].
734 ------------------------------------------------------------------ */
736 /* One of these is allocated for each created door. */
737 typedef struct OpenDoor
739 Bool server; /* TRUE = server door, FALSE = client door */
740 Int fd; /* The file descriptor. */
741 union {
742 /* Server side. */
743 struct {
744 Addr server_procedure; /* The door server procedure. */
745 HChar *pathname; /* NULL if unknown. */
747 /* Client side. */
748 struct {
749 /* Hook called during PRE door_call()
750 to check contents of params->data_ptr. */
751 void (*pre_mem_hook)(ThreadId tid, Int fd,
752 void *data_ptr, SizeT data_size);
753 /* Hook called during POST door_call()
754 to define contents of params->rbuf. */
755 void (*post_mem_hook)(ThreadId tid, Int fd,
756 void *rbuf, SizeT rsize);
759 struct OpenDoor *next, *prev;
760 } OpenDoor;
762 /* List of allocated door fds. */
763 static OpenDoor *doors_recorded = NULL;
764 static UInt nr_doors_recorded = 0;
766 static OpenDoor *door_record_create(void)
768 OpenDoor *d = VG_(malloc)("syswrap.door_record_create.1", sizeof(OpenDoor));
769 d->prev = NULL;
770 d->next = doors_recorded;
771 if (doors_recorded != NULL)
772 doors_recorded->prev = d;
773 doors_recorded = d;
774 nr_doors_recorded += 1;
776 return d;
779 /* Records a server door. */
780 static void door_record_server(ThreadId tid, Addr server_procedure, Int fd)
782 OpenDoor *d = doors_recorded;
784 while (d != NULL) {
785 if ((d->server == TRUE) && (d->server_procedure == server_procedure)) {
786 if (d->pathname) {
787 VG_(free)(d->pathname);
789 break;
791 d = d->next;
794 if (d == NULL)
795 d = door_record_create();
796 vg_assert(d != NULL);
798 d->server = TRUE;
799 d->fd = fd;
800 d->server_procedure = server_procedure;
801 d->pathname = NULL;
804 /* Records a client door. */
805 static void door_record_client(ThreadId tid, Int fd,
806 void (*pre_mem_hook)(ThreadId tid, Int fd, void *data_ptr, SizeT data_size),
807 void (*post_mem_hook)(ThreadId tid, Int fd, void *rbuf, SizeT rsize))
809 OpenDoor *d = doors_recorded;
811 while (d != NULL) {
812 if ((d->server == FALSE) && (d->fd == fd))
813 break;
814 d = d->next;
817 if (d == NULL)
818 d = door_record_create();
819 vg_assert(d != NULL);
821 d->server = FALSE;
822 d->fd = fd;
823 d->pre_mem_hook = pre_mem_hook;
824 d->post_mem_hook = post_mem_hook;
827 /* Revokes an open door, be it server side or client side. */
828 static void door_record_revoke(ThreadId tid, Int fd)
830 OpenDoor *d = doors_recorded;
832 while (d != NULL) {
833 if (d->fd == fd) {
834 if (d->prev != NULL)
835 d->prev->next = d->next;
836 else
837 doors_recorded = d->next;
838 if (d->next != NULL)
839 d->next->prev = d->prev;
841 if ((d->server == TRUE) && (d->pathname != NULL))
842 VG_(free)(d->pathname);
843 VG_(free)(d);
844 nr_doors_recorded -= 1;
845 return;
847 d = d->next;
851 /* Attaches a server door to a filename. */
852 static void door_record_server_fattach(Int fd, HChar *pathname)
854 OpenDoor *d = doors_recorded;
856 while (d != NULL) {
857 if (d->fd == fd) {
858 vg_assert(d->server == TRUE);
860 if (d->pathname != NULL)
861 VG_(free)(d->pathname);
862 d->pathname = VG_(strdup)("syswrap.door_server_fattach.1", pathname);
863 return;
865 d = d->next;
869 /* Finds a server door based on server procedure. */
870 static const OpenDoor *door_find_by_proc(Addr server_procedure)
872 OpenDoor *d = doors_recorded;
874 while (d != NULL) {
875 if ((d->server) && (d->server_procedure == server_procedure))
876 return d;
877 d = d->next;
880 return NULL;
883 /* Finds a client door based on fd. */
884 static const OpenDoor *door_find_by_fd(Int fd)
886 OpenDoor *d = doors_recorded;
888 while (d != NULL) {
889 if ((d->server == FALSE) && (d->fd == fd))
890 return d;
891 d = d->next;
894 return NULL;
897 /* ---------------------------------------------------------------------
898 PRE/POST wrappers for Solaris-specific syscalls
899 ------------------------------------------------------------------ */
901 #define PRE(name) DEFN_PRE_TEMPLATE(solaris, name)
902 #define POST(name) DEFN_POST_TEMPLATE(solaris, name)
904 /* prototypes */
905 DECL_TEMPLATE(solaris, sys_exit);
906 #if defined(SOLARIS_SPAWN_SYSCALL)
907 DECL_TEMPLATE(solaris, sys_spawn);
908 #endif /* SOLARIS_SPAWN_SYSCALL */
909 #if defined(SOLARIS_OLD_SYSCALLS)
910 DECL_TEMPLATE(solaris, sys_open);
911 #endif /* SOLARIS_OLD_SYSCALLS */
912 DECL_TEMPLATE(solaris, sys_close);
913 DECL_TEMPLATE(solaris, sys_linkat);
914 DECL_TEMPLATE(solaris, sys_symlinkat);
915 DECL_TEMPLATE(solaris, sys_time);
916 DECL_TEMPLATE(solaris, sys_brk);
917 DECL_TEMPLATE(solaris, sys_stat);
918 DECL_TEMPLATE(solaris, sys_lseek);
919 DECL_TEMPLATE(solaris, sys_mount);
920 DECL_TEMPLATE(solaris, sys_readlinkat);
921 DECL_TEMPLATE(solaris, sys_stime);
922 DECL_TEMPLATE(solaris, sys_fstat);
923 #if defined(SOLARIS_FREALPATHAT_SYSCALL)
924 DECL_TEMPLATE(solaris, sys_frealpathat);
925 #endif /* SOLARIS_FREALPATHAT_SYSCALL */
926 DECL_TEMPLATE(solaris, sys_stty);
927 DECL_TEMPLATE(solaris, sys_gtty);
928 DECL_TEMPLATE(solaris, sys_pgrpsys);
929 DECL_TEMPLATE(solaris, sys_pipe);
930 DECL_TEMPLATE(solaris, sys_faccessat);
931 DECL_TEMPLATE(solaris, sys_mknodat);
932 DECL_TEMPLATE(solaris, sys_sysi86);
933 DECL_TEMPLATE(solaris, sys_shmsys);
934 DECL_TEMPLATE(solaris, sys_semsys);
935 DECL_TEMPLATE(solaris, sys_ioctl);
936 DECL_TEMPLATE(solaris, sys_fchownat);
937 DECL_TEMPLATE(solaris, sys_fdsync);
938 DECL_TEMPLATE(solaris, sys_execve);
939 DECL_TEMPLATE(solaris, sys_fcntl);
940 DECL_TEMPLATE(solaris, sys_renameat);
941 DECL_TEMPLATE(solaris, sys_unlinkat);
942 DECL_TEMPLATE(solaris, sys_fstatat);
943 DECL_TEMPLATE(solaris, sys_openat);
944 DECL_TEMPLATE(solaris, sys_tasksys);
945 DECL_TEMPLATE(solaris, sys_getpagesizes);
946 DECL_TEMPLATE(solaris, sys_lwp_park);
947 DECL_TEMPLATE(solaris, sys_sendfilev);
948 #if defined(SOLARIS_LWP_NAME_SYSCALL)
949 DECL_TEMPLATE(solaris, sys_lwp_name);
950 #endif /* SOLARIS_LWP_NAME_SYSCALL */
951 DECL_TEMPLATE(solaris, sys_privsys);
952 DECL_TEMPLATE(solaris, sys_ucredsys);
953 DECL_TEMPLATE(solaris, sys_sysfs);
954 DECL_TEMPLATE(solaris, sys_getmsg);
955 DECL_TEMPLATE(solaris, sys_putmsg);
956 DECL_TEMPLATE(solaris, sys_lstat);
957 DECL_TEMPLATE(solaris, sys_sigprocmask);
958 DECL_TEMPLATE(solaris, sys_sigsuspend);
959 DECL_TEMPLATE(solaris, sys_sigaction);
960 DECL_TEMPLATE(solaris, sys_sigpending);
961 DECL_TEMPLATE(solaris, sys_getsetcontext);
962 DECL_TEMPLATE(solaris, sys_fchmodat);
963 DECL_TEMPLATE(solaris, sys_mkdirat);
964 DECL_TEMPLATE(solaris, sys_statvfs);
965 DECL_TEMPLATE(solaris, sys_fstatvfs);
966 DECL_TEMPLATE(solaris, sys_nfssys);
967 DECL_TEMPLATE(solaris, sys_waitid);
968 DECL_TEMPLATE(solaris, sys_sigsendsys);
969 #if defined(SOLARIS_UTIMESYS_SYSCALL)
970 DECL_TEMPLATE(solaris, sys_utimesys);
971 #endif /* SOLARIS_UTIMESYS_SYSCALL */
972 #if defined(SOLARIS_UTIMENSAT_SYSCALL)
973 DECL_TEMPLATE(solaris, sys_utimensat);
974 #endif /* SOLARIS_UTIMENSAT_SYSCALL */
975 DECL_TEMPLATE(solaris, sys_sigresend);
976 DECL_TEMPLATE(solaris, sys_priocntlsys);
977 DECL_TEMPLATE(solaris, sys_pathconf);
978 DECL_TEMPLATE(solaris, sys_mmap);
979 #if defined(SOLARIS_UUIDSYS_SYSCALL)
980 DECL_TEMPLATE(solaris, sys_uuidsys);
981 #endif /* SOLARIS_UUIDSYS_SYSCALL */
982 DECL_TEMPLATE(solaris, sys_mmapobj);
983 DECL_TEMPLATE(solaris, sys_memcntl);
984 DECL_TEMPLATE(solaris, sys_getpmsg);
985 DECL_TEMPLATE(solaris, sys_putpmsg);
986 #if defined(SOLARIS_OLD_SYSCALLS)
987 DECL_TEMPLATE(solaris, sys_rename);
988 #endif /* SOLARIS_OLD_SYSCALLS */
989 DECL_TEMPLATE(solaris, sys_uname);
990 DECL_TEMPLATE(solaris, sys_setegid);
991 DECL_TEMPLATE(solaris, sys_sysconfig);
992 DECL_TEMPLATE(solaris, sys_systeminfo);
993 DECL_TEMPLATE(solaris, sys_seteuid);
994 DECL_TEMPLATE(solaris, sys_forksys);
995 #if defined(SOLARIS_GETRANDOM_SYSCALL)
996 DECL_TEMPLATE(solaris, sys_getrandom);
997 #endif /* SOLARIS_GETRANDOM_SYSCALL */
998 DECL_TEMPLATE(solaris, sys_sigtimedwait);
999 DECL_TEMPLATE(solaris, sys_yield);
1000 DECL_TEMPLATE(solaris, sys_lwp_sema_post);
1001 DECL_TEMPLATE(solaris, sys_lwp_sema_trywait);
1002 DECL_TEMPLATE(solaris, sys_lwp_detach);
1003 DECL_TEMPLATE(solaris, sys_modctl);
1004 DECL_TEMPLATE(solaris, sys_fchroot);
1005 #if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
1006 DECL_TEMPLATE(solaris, sys_system_stats);
1007 #endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
1008 DECL_TEMPLATE(solaris, sys_gettimeofday);
1009 DECL_TEMPLATE(solaris, sys_lwp_create);
1010 DECL_TEMPLATE(solaris, sys_lwp_exit);
1011 DECL_TEMPLATE(solaris, sys_lwp_suspend);
1012 DECL_TEMPLATE(solaris, sys_lwp_continue);
1013 #if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
1014 DECL_TEMPLATE(solaris, sys_lwp_sigqueue);
1015 #else
1016 DECL_TEMPLATE(solaris, sys_lwp_kill);
1017 #endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
1018 DECL_TEMPLATE(solaris, sys_lwp_self);
1019 DECL_TEMPLATE(solaris, sys_lwp_sigmask);
1020 DECL_TEMPLATE(solaris, sys_lwp_private);
1021 DECL_TEMPLATE(solaris, sys_lwp_wait);
1022 DECL_TEMPLATE(solaris, sys_lwp_mutex_wakeup);
1023 DECL_TEMPLATE(solaris, sys_lwp_cond_wait);
1024 DECL_TEMPLATE(solaris, sys_lwp_cond_signal);
1025 DECL_TEMPLATE(solaris, sys_lwp_cond_broadcast);
1026 DECL_TEMPLATE(solaris, sys_pread);
1027 DECL_TEMPLATE(solaris, sys_pwrite);
1028 DECL_TEMPLATE(solaris, sys_lgrpsys);
1029 DECL_TEMPLATE(solaris, sys_rusagesys);
1030 DECL_TEMPLATE(solaris, sys_port);
1031 DECL_TEMPLATE(solaris, sys_pollsys);
1032 DECL_TEMPLATE(solaris, sys_labelsys);
1033 DECL_TEMPLATE(solaris, sys_acl);
1034 DECL_TEMPLATE(solaris, sys_auditsys);
1035 DECL_TEMPLATE(solaris, sys_p_online);
1036 DECL_TEMPLATE(solaris, sys_sigqueue);
1037 DECL_TEMPLATE(solaris, sys_clock_gettime);
1038 DECL_TEMPLATE(solaris, sys_clock_settime);
1039 DECL_TEMPLATE(solaris, sys_clock_getres);
1040 DECL_TEMPLATE(solaris, sys_timer_create);
1041 DECL_TEMPLATE(solaris, sys_timer_delete);
1042 DECL_TEMPLATE(solaris, sys_timer_settime);
1043 DECL_TEMPLATE(solaris, sys_timer_gettime);
1044 DECL_TEMPLATE(solaris, sys_timer_getoverrun);
1045 DECL_TEMPLATE(solaris, sys_facl);
1046 DECL_TEMPLATE(solaris, sys_door);
1047 DECL_TEMPLATE(solaris, sys_schedctl);
1048 DECL_TEMPLATE(solaris, sys_pset);
1049 DECL_TEMPLATE(solaris, sys_resolvepath);
1050 DECL_TEMPLATE(solaris, sys_lwp_mutex_timedlock);
1051 DECL_TEMPLATE(solaris, sys_lwp_rwlock_sys);
1052 DECL_TEMPLATE(solaris, sys_lwp_sema_timedwait);
1053 DECL_TEMPLATE(solaris, sys_zone);
1054 DECL_TEMPLATE(solaris, sys_getcwd);
1055 DECL_TEMPLATE(solaris, sys_so_socket);
1056 DECL_TEMPLATE(solaris, sys_so_socketpair);
1057 DECL_TEMPLATE(solaris, sys_bind);
1058 DECL_TEMPLATE(solaris, sys_listen);
1059 DECL_TEMPLATE(solaris, sys_accept);
1060 DECL_TEMPLATE(solaris, sys_connect);
1061 DECL_TEMPLATE(solaris, sys_shutdown);
1062 DECL_TEMPLATE(solaris, sys_recv);
1063 DECL_TEMPLATE(solaris, sys_recvfrom);
1064 DECL_TEMPLATE(solaris, sys_recvmsg);
1065 DECL_TEMPLATE(solaris, sys_send);
1066 DECL_TEMPLATE(solaris, sys_sendmsg);
1067 DECL_TEMPLATE(solaris, sys_sendto);
1068 DECL_TEMPLATE(solaris, sys_getpeername);
1069 DECL_TEMPLATE(solaris, sys_getsockname);
1070 DECL_TEMPLATE(solaris, sys_getsockopt);
1071 DECL_TEMPLATE(solaris, sys_setsockopt);
1072 DECL_TEMPLATE(solaris, sys_lwp_mutex_unlock);
1073 DECL_TEMPLATE(solaris, sys_lwp_mutex_register);
1074 DECL_TEMPLATE(solaris, sys_uucopy);
1075 DECL_TEMPLATE(solaris, sys_umount2);
1077 DECL_TEMPLATE(solaris, fast_gethrtime);
1078 DECL_TEMPLATE(solaris, fast_gethrvtime);
1079 DECL_TEMPLATE(solaris, fast_gethrestime);
1080 DECL_TEMPLATE(solaris, fast_getlgrp);
1081 #if defined(SOLARIS_GETHRT_FASTTRAP)
1082 DECL_TEMPLATE(solaris, fast_gethrt);
1083 #endif /* SOLARIS_GETHRT_FASTTRAP */
1084 #if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
1085 DECL_TEMPLATE(solaris, fast_getzoneoffset);
1086 #endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
1088 /* implementation */
1089 PRE(sys_exit)
1091 /* void exit(int status); */
1092 ThreadId t;
1094 PRINT("sys_exit( %ld )", SARG1);
1095 PRE_REG_READ1(void, "exit", int, status);
1097 for (t = 1; t < VG_N_THREADS; t++) {
1098 if (VG_(threads)[t].status == VgTs_Empty)
1099 continue;
1101 /* Assign the exit code, VG_(nuke_all_threads_except) will assign
1102 the exitreason. */
1103 VG_(threads)[t].os_state.exitcode = ARG1;
1106 /* Indicate in all other threads that the process is exiting.
1107 Then wait using VG_(reap_threads) for these threads to disappear.
1108 See comments in syswrap-linux.c, PRE(sys_exit_group) wrapper,
1109 for reasoning why this cannot give a deadlock. */
1110 VG_(nuke_all_threads_except)(tid, VgSrc_ExitProcess);
1111 VG_(reap_threads)(tid);
1112 VG_(threads)[tid].exitreason = VgSrc_ExitThread;
1113 /* We do assign VgSrc_ExitThread and not VgSrc_ExitProcess, as this thread
1114 is the thread calling exit_group and so its registers must be considered
1115 as not reachable. See pub_tool_machine.h VG_(apply_to_GP_regs). */
1117 /* We have to claim the syscall already succeeded. */
1118 SET_STATUS_Success(0);
1121 #if defined(SOLARIS_SPAWN_SYSCALL)
1122 static Bool spawn_pre_check_kfa(ThreadId tid, SyscallStatus *status,
1123 vki_kfile_attr_t *kfa)
1125 PRE_FIELD_READ("spawn(attrs->kfa_size)", kfa->kfa_size);
1126 PRE_FIELD_READ("spawn(attrs->kfa_type)", kfa->kfa_type);
1128 if (ML_(safe_to_deref)(kfa, kfa->kfa_size)) {
1129 switch (kfa->kfa_type) {
1130 case VKI_FA_DUP2:
1131 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1132 PRE_FIELD_READ("spawn(attrs->kfa_newfiledes)", kfa->kfa_newfiledes);
1133 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(dup2)", tid, False) ||
1134 !ML_(fd_allowed)(kfa->kfa_newfiledes, "spawn(dup2)", tid, False)) {
1135 SET_STATUS_Failure(VKI_EBADF);
1136 return False;
1138 break;
1139 case VKI_FA_CLOSE:
1140 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1141 /* If doing -d style logging (which is to fd = 2 = stderr),
1142 don't allow that filedes to be closed. See ML_(fd_allowed)(). */
1143 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(close)", tid, False) ||
1144 (kfa->kfa_filedes == 2 && VG_(debugLog_getLevel)() > 0)) {
1145 SET_STATUS_Failure(VKI_EBADF);
1146 return False;
1148 break;
1149 case VKI_FA_CLOSEFROM:
1150 /* :TODO: All file descriptors greater than or equal to
1151 kfa->kfa_filedes would have to be checked. */
1152 VG_(unimplemented)("Support for spawn() with file attribute type "
1153 "FA_CLOSEFROM.");
1154 break;
1155 case VKI_FA_OPEN:
1156 PRE_FIELD_READ("spawn(attrs->kfa_filedes)", kfa->kfa_filedes);
1157 PRE_FIELD_READ("spawn(attrs->kfa_oflag)", kfa->kfa_oflag);
1158 PRE_FIELD_READ("spawn(attrs->kfa_mode)", kfa->kfa_mode);
1159 if (!ML_(fd_allowed)(kfa->kfa_filedes, "spawn(open)", tid, False)) {
1160 SET_STATUS_Failure(VKI_EBADF);
1161 return False;
1163 /* fallthrough */
1164 case VKI_FA_CHDIR:
1165 PRE_FIELD_READ("spawn(attrs->kfa_pathsize)", kfa->kfa_pathsize);
1166 if (kfa->kfa_pathsize != 0) {
1167 PRE_MEM_RASCIIZ("spawn(attrs->kfa_data)", (Addr) kfa->kfa_data);
1169 break;
1170 default:
1171 VG_(unimplemented)("Support for spawn() with file attribute type %u.",
1172 kfa->kfa_type);
1176 return True;
1179 PRE(sys_spawn)
1181 /* int spawn(char *path, void *attrs, size_t attrsize,
1182 char *argenv, size_t aesize); */
1183 PRINT("sys_spawn ( %#lx(%s), %#lx, %lu, %#lx, %lu )",
1184 ARG1, (HChar *) ARG1, ARG2, ARG3, ARG4, ARG5);
1185 PRE_REG_READ5(long, "spawn", const char *, path, void *, attrs,
1186 size_t, attrsize, char *, argenv, size_t, aesize);
1188 /* First check input arguments. */
1189 PRE_MEM_RASCIIZ("spawn(path)", ARG1);
1190 if (ARG3 > 0) {
1191 /* --- vki_kspawn_attr_t --
1192 | ksa_version |
1193 | ksa_size |
1194 | ksa_attr_off | -----| (only if != 0)
1195 | ksa_attr_size | |
1196 | ksa_path_off | =====|====| (only if != 0)
1197 | ksa_path_size | | |
1198 | ksa_shell_off | -----|----|----| (only if != 0)
1199 | ksa_shell_size | | | |
1200 | ksa_data[0] | | | |
1201 ------------------------ | | |
1202 | vki_spawn_attr_t | <----| | |
1203 ------------------------ | |
1204 | path | <---------| |
1205 ------------------------ |
1206 | shell | <---------------
1207 ------------------------
1208 | file actions | (not included in ksa_size, only in ARG3)
1209 ------------------------
1211 ksa_size = sizeof(vki_kspawn_attr_t) + ksa_attr_size + ksa_path_size +
1212 ksa_shell_size
1213 attrs_size (ARG3) = ksa_size + file actions size */
1215 vki_kspawn_attr_t *attrs = (vki_kspawn_attr_t *) ARG2;
1216 PRE_FIELD_READ("spawn(attrs->ksa_version)", attrs->ksa_version);
1217 PRE_FIELD_READ("spawn(attrs->ksa_size)", attrs->ksa_size);
1218 PRE_FIELD_READ("spawn(attrs->ksa_attr_off)", attrs->ksa_attr_off);
1219 PRE_FIELD_READ("spawn(attrs->ksa_path_off)", attrs->ksa_path_off);
1220 PRE_FIELD_READ("spawn(attrs->ksa_shell_off)", attrs->ksa_shell_off);
1222 if (ML_(safe_to_deref)(attrs, sizeof(vki_kspawn_attr_t))) {
1223 if (attrs->ksa_version != VKI_SPAWN_VERSION) {
1224 VG_(unimplemented)("Support for spawn() with attributes "
1225 "version %u.", attrs->ksa_version);
1228 if (attrs->ksa_attr_off != 0) {
1229 PRE_FIELD_READ("spawn(attrs->ksa_attr_size)", attrs->ksa_attr_size);
1230 vki_spawn_attr_t *sap =
1231 (vki_spawn_attr_t *) ((Addr) attrs + attrs->ksa_attr_off);
1232 PRE_MEM_READ("spawn(attrs->ksa_attr)",
1233 (Addr) sap, attrs->ksa_attr_size);
1234 if (ML_(safe_to_deref)(sap, sizeof(vki_spawn_attr_t))) {
1235 if (sap->sa_psflags & VKI_POSIX_SPAWN_SETVAMASK_NP) {
1236 VG_(unimplemented)("Support for spawn() with attributes flag "
1237 "including POSIX_SPAWN_SETVAMASK_NP.");
1239 /* paranoia */
1240 Int rem = sap->sa_psflags & ~(
1241 VKI_POSIX_SPAWN_RESETIDS | VKI_POSIX_SPAWN_SETPGROUP |
1242 VKI_POSIX_SPAWN_SETSIGDEF | VKI_POSIX_SPAWN_SETSIGMASK |
1243 VKI_POSIX_SPAWN_SETSCHEDPARAM | VKI_POSIX_SPAWN_SETSCHEDULER |
1244 VKI_POSIX_SPAWN_SETSID_NP | VKI_POSIX_SPAWN_SETVAMASK_NP |
1245 VKI_POSIX_SPAWN_SETSIGIGN_NP | VKI_POSIX_SPAWN_NOSIGCHLD_NP |
1246 VKI_POSIX_SPAWN_WAITPID_NP | VKI_POSIX_SPAWN_NOEXECERR_NP);
1247 if (rem != 0) {
1248 VG_(unimplemented)("Support for spawn() with attributes flag "
1249 "%#x.", sap->sa_psflags);
1254 if (attrs->ksa_path_off != 0) {
1255 PRE_FIELD_READ("spawn(attrs->ksa_path_size)", attrs->ksa_path_size);
1256 PRE_MEM_RASCIIZ("spawn(attrs->ksa_path)",
1257 (Addr) attrs + attrs->ksa_path_off);
1260 if (attrs->ksa_shell_off != 0) {
1261 PRE_FIELD_READ("spawn(attrs->ksa_shell_size)",
1262 attrs->ksa_shell_size);
1263 PRE_MEM_RASCIIZ("spawn(attrs->ksa_shell)",
1264 (Addr) attrs + attrs->ksa_shell_off);
1267 vki_kfile_attr_t *kfa = (vki_kfile_attr_t *) (ARG2 + attrs->ksa_size);
1268 while ((Addr) kfa < ARG2 + ARG3) {
1269 if (spawn_pre_check_kfa(tid, status, kfa) == False) {
1270 return;
1272 kfa = (vki_kfile_attr_t *) ((Addr) kfa + kfa->kfa_size);
1276 PRE_MEM_READ("spawn(argenv)", ARG4, ARG5);
1278 /* Check that the name at least begins in client-accessible storage. */
1279 if ((ARG1 == 0) || !ML_(safe_to_deref)((HChar *) ARG1, 1)) {
1280 SET_STATUS_Failure(VKI_EFAULT);
1281 return;
1284 /* Check that attrs reside in client-accessible storage. */
1285 if (ARG2 != 0) {
1286 if (!VG_(am_is_valid_for_client)(ARG2, ARG3, VKI_PROT_READ)) {
1287 SET_STATUS_Failure(VKI_EFAULT);
1288 return;
1292 /* Check that the argenv reside in client-accessible storage.
1293 Solaris disallows to perform spawn() without any arguments & environment
1294 variables specified. */
1295 if ((ARG4 == 0) /* obviously bogus */ ||
1296 !VG_(am_is_valid_for_client)(ARG4, ARG5, VKI_PROT_READ)) {
1297 SET_STATUS_Failure(VKI_EFAULT);
1298 return;
1301 /* Copy existing attrs or create empty minimal ones. */
1302 vki_kspawn_attr_t *attrs;
1303 SizeT attrs_size;
1304 if (ARG2 == 0) {
1305 /* minimalistic kspawn_attr_t + spawn_attr_t */
1306 attrs_size = sizeof(vki_kspawn_attr_t) + sizeof(vki_spawn_attr_t);
1307 attrs = VG_(calloc)("syswrap.spawn.1", 1, attrs_size);
1308 attrs->ksa_version = VKI_SPAWN_VERSION;
1309 attrs->ksa_size = attrs_size;
1310 attrs->ksa_attr_off = sizeof(vki_kspawn_attr_t);
1311 attrs->ksa_attr_size = sizeof(vki_spawn_attr_t);
1312 } else if (((vki_kspawn_attr_t *) ARG2)->ksa_attr_off == 0) {
1313 /* existing kspawn_attr_t but missing spawn_attr_t */
1314 attrs_size = ARG3 + sizeof(vki_spawn_attr_t);
1315 attrs = VG_(calloc)("syswrap.spawn.2", 1, attrs_size);
1316 VG_(memcpy)(attrs, (void *) ARG2, sizeof(vki_kspawn_attr_t));
1317 SizeT file_actions_size = ARG3 - attrs->ksa_size;
1318 attrs->ksa_size += sizeof(vki_spawn_attr_t);
1319 attrs->ksa_attr_off = sizeof(vki_kspawn_attr_t);
1320 attrs->ksa_attr_size = sizeof(vki_spawn_attr_t);
1321 if (attrs->ksa_path_off != 0) {
1322 VG_(memcpy)((HChar *) attrs + attrs->ksa_path_off +
1323 sizeof(vki_spawn_attr_t), (HChar *) ARG2 +
1324 attrs->ksa_path_off, attrs->ksa_path_size);
1325 attrs->ksa_path_off += sizeof(vki_spawn_attr_t);
1327 if (attrs->ksa_shell_off != 0) {
1328 VG_(memcpy)((HChar *) attrs + attrs->ksa_shell_off +
1329 sizeof(vki_spawn_attr_t), (HChar *) ARG2 +
1330 attrs->ksa_shell_off, attrs->ksa_shell_size);
1331 attrs->ksa_shell_off += sizeof(vki_spawn_attr_t);
1333 if (file_actions_size > 0) {
1334 VG_(memcpy)((HChar *) attrs + attrs_size - file_actions_size,
1335 (HChar *) ARG2 + ARG3 - file_actions_size,
1336 file_actions_size);
1338 } else {
1339 /* existing kspawn_attr_t + spawn_attr_t */
1340 attrs_size = ARG3;
1341 attrs = VG_(malloc)("syswrap.spawn.3", attrs_size);
1342 VG_(memcpy)(attrs, (void *) ARG2, attrs_size);
1344 vki_spawn_attr_t *spa = (vki_spawn_attr_t *) ((HChar *) attrs +
1345 attrs->ksa_attr_off);
1347 /* Convert argv and envp parts of argenv into their separate XArray's.
1348 Duplicate strings because argv and envp will be then modified. */
1349 XArray *argv = VG_(newXA)(VG_(malloc), "syswrap.spawn.4",
1350 VG_(free), sizeof(HChar *));
1351 XArray *envp = VG_(newXA)(VG_(malloc), "syswrap.spawn.5",
1352 VG_(free), sizeof(HChar *));
1354 HChar *argenv = (HChar *) ARG4;
1355 XArray *current_xa = argv;
1356 while ((Addr) argenv < ARG4 + ARG5) {
1357 if (*argenv == '\0') {
1358 argenv += 1;
1359 if (current_xa == argv) {
1360 current_xa = envp;
1361 if ((*argenv == '\0') && ((Addr) argenv == ARG4 + ARG5 - 1)) {
1362 /* envp part is empty, it contained only {NULL}. */
1363 break;
1365 } else {
1366 if ((Addr) argenv != ARG4 + ARG5) {
1367 if (VG_(clo_trace_syscalls))
1368 VG_(debugLog)(3, "syswrap-solaris", "spawn: bogus argenv\n");
1369 SET_STATUS_Failure(VKI_EINVAL);
1370 goto exit;
1372 break;
1376 if (*argenv != '\1') {
1377 if (VG_(clo_trace_syscalls))
1378 VG_(debugLog)(3, "syswrap-solaris", "spawn: bogus argenv\n");
1379 SET_STATUS_Failure(VKI_EINVAL);
1380 goto exit;
1382 argenv += 1;
1384 HChar *duplicate = VG_(strdup)("syswrap.spawn.6", argenv);
1385 VG_(addToXA)(current_xa, &duplicate);
1386 argenv += VG_(strlen)(argenv) + 1;
1389 /* Debug-only printing. */
1390 if (0) {
1391 VG_(printf)("\nARG1 = %#lx(%s)\n", ARG1, (HChar *) ARG1);
1392 VG_(printf)("ARG4 (argv) = ");
1393 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1394 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(argv, i));
1397 VG_(printf)("\nARG4 (envp) = ");
1398 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1399 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(envp, i));
1401 VG_(printf)("\n");
1404 /* Decide whether or not we want to trace the spawned child.
1405 Omit the executable name itself from child_argv. */
1406 const HChar **child_argv = VG_(malloc)("syswrap.spawn.7",
1407 (VG_(sizeXA)(argv) - 1) * sizeof(HChar *));
1408 for (Word i = 1; i < VG_(sizeXA)(argv); i++) {
1409 child_argv[i - 1] = *(HChar **) VG_(indexXA)(argv, i);
1411 Bool trace_this_child = VG_(should_we_trace_this_child)((HChar *) ARG1,
1412 child_argv);
1413 VG_(free)(child_argv);
1415 /* If we're tracing the child, and the launcher name looks bogus (possibly
1416 because launcher.c couldn't figure it out, see comments therein) then we
1417 have no option but to fail. */
1418 if (trace_this_child &&
1419 (!VG_(name_of_launcher) || VG_(name_of_launcher)[0] != '/')) {
1420 SET_STATUS_Failure(VKI_ECHILD); /* "No child processes." */
1421 goto exit;
1424 /* Set up the child's exe path. */
1425 const HChar *path = (const HChar *) ARG1;
1426 const HChar *launcher_basename = NULL;
1427 if (trace_this_child) {
1428 /* We want to exec the launcher. */
1429 path = VG_(name_of_launcher);
1430 vg_assert(path != NULL);
1432 launcher_basename = VG_(strrchr)(path, '/');
1433 if ((launcher_basename == NULL) || (launcher_basename[1] == '\0')) {
1434 launcher_basename = path; /* hmm, tres dubious */
1435 } else {
1436 launcher_basename++;
1440 /* Set up the child's environment.
1442 Remove the valgrind-specific stuff from the environment so the child
1443 doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. This is done
1444 unconditionally, since if we are tracing the child, the child valgrind
1445 will set up the appropriate client environment.
1447 Then, if tracing the child, set VALGRIND_LIB for it. */
1448 HChar **child_envp = VG_(calloc)("syswrap.spawn.8",
1449 VG_(sizeXA)(envp) + 1, sizeof(HChar *));
1450 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1451 child_envp[i] = *(HChar **) VG_(indexXA)(envp, i);
1453 VG_(env_remove_valgrind_env_stuff)(child_envp, /* ro_strings */ False,
1454 VG_(free));
1456 /* Stuff was removed from child_envp, reflect that in envp XArray. */
1457 VG_(dropTailXA)(envp, VG_(sizeXA)(envp));
1458 for (UInt i = 0; child_envp[i] != NULL; i++) {
1459 VG_(addToXA)(envp, &child_envp[i]);
1461 VG_(free)(child_envp);
1463 if (trace_this_child) {
1464 /* Set VALGRIND_LIB in envp. */
1465 SizeT len = VG_(strlen)(VALGRIND_LIB) + VG_(strlen)(VG_(libdir)) + 2;
1466 HChar *valstr = VG_(malloc)("syswrap.spawn.9", len);
1467 VG_(sprintf)(valstr, "%s=%s", VALGRIND_LIB, VG_(libdir));
1468 VG_(addToXA)(envp, &valstr);
1471 /* Set up the child's args. If not tracing it, they are left untouched.
1472 Otherwise, they are:
1474 [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG4[1..],
1476 except that the first VG_(args_for_valgrind_noexecpass) args are
1477 omitted. */
1478 if (trace_this_child) {
1479 vg_assert(VG_(args_for_valgrind) != NULL);
1480 vg_assert(VG_(args_for_valgrind_noexecpass) >= 0);
1481 vg_assert(VG_(args_for_valgrind_noexecpass)
1482 <= VG_(sizeXA)(VG_(args_for_valgrind)));
1484 /* So what args will there be? Bear with me... */
1485 /* ... launcher basename, ... */
1486 HChar *duplicate = VG_(strdup)("syswrap.spawn.10", launcher_basename);
1487 VG_(insertIndexXA)(argv, 0, &duplicate);
1489 /* ... Valgrind's args, ... */
1490 UInt v_args = VG_(sizeXA)(VG_(args_for_valgrind));
1491 v_args -= VG_(args_for_valgrind_noexecpass);
1492 for (Word i = VG_(args_for_valgrind_noexecpass);
1493 i < VG_(sizeXA)(VG_(args_for_valgrind)); i++) {
1494 duplicate = VG_(strdup)("syswrap.spawn.11",
1495 *(HChar **) VG_(indexXA)(VG_(args_for_valgrind), i));
1496 VG_(insertIndexXA)(argv, 1 + i, &duplicate);
1499 /* ... name of client executable, ... */
1500 duplicate = VG_(strdup)("syswrap.spawn.12", (HChar *) ARG1);
1501 VG_(insertIndexXA)(argv, 1 + v_args, &duplicate);
1503 /* ... and args for client executable (without [0]). */
1504 duplicate = *(HChar **) VG_(indexXA)(argv, 1 + v_args + 1);
1505 VG_(free)(duplicate);
1506 VG_(removeIndexXA)(argv, 1 + v_args + 1);
1509 /* Debug-only printing. */
1510 if (0) {
1511 VG_(printf)("\npath = %s\n", path);
1512 VG_(printf)("argv = ");
1513 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1514 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(argv, i));
1517 VG_(printf)("\nenvp = ");
1518 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1519 VG_(printf)("%s ", *(HChar **) VG_(indexXA)(envp, i));
1521 VG_(printf)("\n");
1524 /* Set the signal state up for spawned child.
1526 Signals set to be caught are equivalent to signals set to the default
1527 action, from the child's perspective.
1529 Therefore query SCSS and prepare default (DFL) and ignore (IGN) signal
1530 sets. Then combine these sets with those passed from client, if flags
1531 POSIX_SPAWN_SETSIGDEF, or POSIX_SPAWN_SETSIGIGN_NP have been specified.
1533 vki_sigset_t sig_default;
1534 vki_sigset_t sig_ignore;
1535 VG_(sigemptyset)(&sig_default);
1536 VG_(sigemptyset)(&sig_ignore);
1537 for (Int i = 1; i < VG_(max_signal); i++) {
1538 vki_sigaction_fromK_t sa;
1539 VG_(do_sys_sigaction)(i, NULL, &sa); /* query SCSS */
1540 if (sa.sa_handler == VKI_SIG_IGN) {
1541 VG_(sigaddset)(&sig_ignore, i);
1542 } else {
1543 VG_(sigaddset)(&sig_default, i);
1547 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGDEF) {
1548 VG_(sigaddset_from_set)(&spa->sa_sigdefault, &sig_default);
1549 } else {
1550 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGDEF;
1551 spa->sa_sigdefault = sig_default;
1554 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGIGN_NP) {
1555 VG_(sigaddset_from_set)(&spa->sa_sigignore, &sig_ignore);
1556 } else {
1557 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGIGN_NP;
1558 spa->sa_sigignore = sig_ignore;
1561 /* Set the signal mask for spawned child.
1563 Analogous to signal handlers: query SCSS for blocked signals mask
1564 and combine this mask with that passed from client, if flag
1565 POSIX_SPAWN_SETSIGMASK has been specified. */
1566 vki_sigset_t *sigmask = &VG_(get_ThreadState)(tid)->sig_mask;
1567 if (spa->sa_psflags & VKI_POSIX_SPAWN_SETSIGMASK) {
1568 VG_(sigaddset_from_set)(&spa->sa_sigmask, sigmask);
1569 } else {
1570 spa->sa_psflags |= VKI_POSIX_SPAWN_SETSIGMASK;
1571 spa->sa_sigmask = *sigmask;
1574 /* Lastly, reconstruct argenv from argv + envp. */
1575 SizeT argenv_size = 1 + 1;
1576 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1577 argenv_size += VG_(strlen)(*(HChar **) VG_(indexXA)(argv, i)) + 2;
1579 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1580 argenv_size += VG_(strlen)(*(HChar **) VG_(indexXA)(envp, i)) + 2;
1583 argenv = VG_(malloc)("syswrap.spawn.13", argenv_size);
1584 HChar *current = argenv;
1585 #define COPY_CHAR_TO_ARGENV(dst, character) \
1586 do { \
1587 *(dst) = character; \
1588 (dst) += 1; \
1589 } while (0)
1590 #define COPY_STRING_TO_ARGENV(dst, src) \
1591 do { \
1592 COPY_CHAR_TO_ARGENV(dst, '\1'); \
1593 SizeT src_len = VG_(strlen)((src)) + 1; \
1594 VG_(memcpy)((dst), (src), src_len); \
1595 (dst) += src_len; \
1596 } while (0)
1598 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1599 COPY_STRING_TO_ARGENV(current, *(HChar **) VG_(indexXA)(argv, i));
1601 COPY_CHAR_TO_ARGENV(current, '\0');
1602 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1603 COPY_STRING_TO_ARGENV(current, *(HChar **) VG_(indexXA)(envp, i));
1605 COPY_CHAR_TO_ARGENV(current, '\0');
1606 vg_assert(current == argenv + argenv_size);
1607 #undef COPY_CHAR_TO_ARGENV
1608 #undef COPY_STRING_TOARGENV
1610 /* Actual spawn() syscall. */
1611 SysRes res = VG_(do_syscall5)(__NR_spawn, (UWord) path, (UWord) attrs,
1612 attrs_size, (UWord) argenv, argenv_size);
1613 SET_STATUS_from_SysRes(res);
1614 VG_(free)(argenv);
1616 if (SUCCESS) {
1617 PRINT(" spawn: process %d spawned child %ld\n", VG_(getpid)(), RES);
1620 exit:
1621 VG_(free)(attrs);
1622 for (Word i = 0; i < VG_(sizeXA)(argv); i++) {
1623 VG_(free)(*(HChar **) VG_(indexXA)(argv, i));
1625 for (Word i = 0; i < VG_(sizeXA)(envp); i++) {
1626 VG_(free)(*(HChar **) VG_(indexXA)(envp, i));
1628 VG_(deleteXA)(argv);
1629 VG_(deleteXA)(envp);
1631 #endif /* SOLARIS_SPAWN_SYSCALL */
1633 /* Handles the case where the open is of /proc/self/psinfo or
1634 /proc/<pid>/psinfo. Fetch fresh contents into psinfo_t,
1635 fake fname, psargs, argc and argv. Write the structure to the fake
1636 file we cooked up at startup (in m_main) and give out a copy of this
1637 fd. Also seek the cloned fd back to the start. */
1638 static Bool handle_psinfo_open(SyscallStatus *status,
1639 Bool use_openat,
1640 const HChar *filename,
1641 Int arg1, UWord arg3, UWord arg4)
1643 if (!ML_(safe_to_deref)((const void *) filename, 1))
1644 return False;
1646 HChar name[VKI_PATH_MAX]; // large enough
1647 VG_(sprintf)(name, "/proc/%d/psinfo", VG_(getpid)());
1649 if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/psinfo"))
1650 return False;
1652 /* Use original arguments to open() or openat(). */
1653 SysRes sres;
1654 #if defined(SOLARIS_OLD_SYSCALLS)
1655 if (use_openat)
1656 sres = VG_(do_syscall4)(SYS_openat, arg1, (UWord) filename,
1657 arg3, arg4);
1658 else
1659 sres = VG_(do_syscall3)(SYS_open, (UWord) filename, arg3, arg4);
1660 #else
1661 vg_assert(use_openat == True);
1662 sres = VG_(do_syscall4)(SYS_openat, arg1, (UWord) filename,
1663 arg3, arg4);
1664 #endif /* SOLARIS_OLD_SYSCALLS */
1666 if (sr_isError(sres)) {
1667 SET_STATUS_from_SysRes(sres);
1668 return True;
1670 Int fd = sr_Res(sres);
1672 vki_psinfo_t psinfo;
1673 sres = VG_(do_syscall3)(SYS_read, fd, (UWord) &psinfo, sizeof(psinfo));
1674 if (sr_isError(sres)) {
1675 SET_STATUS_from_SysRes(sres);
1676 VG_(close)(fd);
1677 return True;
1679 if (sr_Res(sres) != sizeof(psinfo)) {
1680 SET_STATUS_Failure(VKI_ENODATA);
1681 VG_(close)(fd);
1682 return True;
1685 VG_(close)(fd);
1687 VG_(client_fname)(psinfo.pr_fname, sizeof(psinfo.pr_fname), True);
1688 VG_(client_cmd_and_args)(psinfo.pr_psargs, sizeof(psinfo.pr_psargs));
1690 Addr *ptr = (Addr *) VG_(get_initial_client_SP)();
1691 psinfo.pr_argc = *ptr++;
1692 psinfo.pr_argv = (Addr) ptr;
1694 sres = VG_(do_syscall4)(SYS_pwrite, VG_(cl_psinfo_fd),
1695 (UWord) &psinfo, sizeof(psinfo), 0);
1696 if (sr_isError(sres)) {
1697 SET_STATUS_from_SysRes(sres);
1698 return True;
1701 sres = VG_(dup)(VG_(cl_psinfo_fd));
1702 SET_STATUS_from_SysRes(sres);
1703 if (!sr_isError(sres)) {
1704 OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
1705 if (off < 0)
1706 SET_STATUS_Failure(VKI_EMFILE);
1709 return True;
1712 #if defined(SOLARIS_PROC_CMDLINE)
1713 /* Handles the case where the open is of /proc/self/cmdline or
1714 /proc/<pid>/cmdline. Just give it a copy of VG_(cl_cmdline_fd) for the
1715 fake file we cooked up at startup (in m_main). Also, seek the
1716 cloned fd back to the start. */
1717 static Bool handle_cmdline_open(SyscallStatus *status, const HChar *filename)
1719 if (!ML_(safe_to_deref)((const void *) filename, 1))
1720 return False;
1722 HChar name[VKI_PATH_MAX]; // large enough
1723 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
1725 if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/cmdline"))
1726 return False;
1728 SysRes sres = VG_(dup)(VG_(cl_cmdline_fd));
1729 SET_STATUS_from_SysRes(sres);
1730 if (!sr_isError(sres)) {
1731 OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
1732 if (off < 0)
1733 SET_STATUS_Failure(VKI_EMFILE);
1736 return True;
1738 #endif /* SOLARIS_PROC_CMDLINE */
1741 #if defined(SOLARIS_OLD_SYSCALLS)
1742 PRE(sys_open)
1744 /* int open(const char *filename, int flags);
1745 int open(const char *filename, int flags, mode_t mode); */
1747 if (ARG2 & VKI_O_CREAT) {
1748 /* 3-arg version */
1749 PRINT("sys_open ( %#lx(%s), %ld, %lu )", ARG1, (HChar *) ARG1,
1750 SARG2, ARG3);
1751 PRE_REG_READ3(long, "open", const char *, filename,
1752 int, flags, vki_mode_t, mode);
1753 } else {
1754 /* 2-arg version */
1755 PRINT("sys_open ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
1756 PRE_REG_READ2(long, "open", const char *, filename, int, flags);
1759 PRE_MEM_RASCIIZ("open(filename)", ARG1);
1761 if (ML_(handle_auxv_open)(status, (const HChar*)ARG1, ARG2))
1762 return;
1764 if (handle_psinfo_open(status, False /*use_openat*/, (const HChar*)ARG1, 0,
1765 ARG2, ARG3))
1766 return;
1768 *flags |= SfMayBlock;
1771 POST(sys_open)
1773 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
1774 VG_(close)(RES);
1775 SET_STATUS_Failure(VKI_EMFILE);
1776 } else if (VG_(clo_track_fds))
1777 ML_(record_fd_open_with_given_name)(tid, RES, (HChar *) ARG1);
1779 #endif /* SOLARIS_OLD_SYSCALLS */
1781 PRE(sys_close)
1783 WRAPPER_PRE_NAME(generic, sys_close)(tid, layout, arrghs, status,
1784 flags);
1787 POST(sys_close)
1789 WRAPPER_POST_NAME(generic, sys_close)(tid, arrghs, status);
1790 door_record_revoke(tid, ARG1);
1791 /* Possibly an explicitly open'ed client door fd was just closed.
1792 Generic sys_close wrapper calls this only if VG_(clo_track_fds) = True. */
1793 if (!VG_(clo_track_fds))
1794 ML_(record_fd_close)(ARG1);
1797 PRE(sys_linkat)
1799 /* int linkat(int fd1, const char *path1, int fd2,
1800 const char *path2, int flag);
1803 /* Interpret the first and third arguments as 32-bit values even on 64-bit
1804 architecture. This is different from Linux, for example, where glibc
1805 sign-extends them. */
1806 Int fd1 = (Int) ARG1;
1807 Int fd2 = (Int) ARG3;
1809 PRINT("sys_linkat ( %d, %#lx(%s), %d, %#lx(%s), %ld )",
1810 fd1, ARG2, (HChar *) ARG2, fd2, ARG4, (HChar *) ARG4, SARG5);
1811 PRE_REG_READ5(long, "linkat", int, fd1, const char *, path1,
1812 int, fd2, const char *, path2, int, flags);
1813 PRE_MEM_RASCIIZ("linkat(path1)", ARG2);
1814 PRE_MEM_RASCIIZ("linkat(path2)", ARG4);
1816 /* Be strict but ignore fd1/fd2 for absolute path1/path2. */
1817 if (fd1 != VKI_AT_FDCWD
1818 && ML_(safe_to_deref)((void *) ARG2, 1)
1819 && ((HChar *) ARG2)[0] != '/'
1820 && !ML_(fd_allowed)(fd1, "linkat", tid, False)) {
1821 SET_STATUS_Failure(VKI_EBADF);
1823 if (fd2 != VKI_AT_FDCWD
1824 && ML_(safe_to_deref)((void *) ARG4, 1)
1825 && ((HChar *) ARG4)[0] != '/'
1826 && !ML_(fd_allowed)(fd2, "linkat", tid, False)) {
1827 SET_STATUS_Failure(VKI_EBADF);
1830 *flags |= SfMayBlock;
1833 PRE(sys_symlinkat)
1835 /* int symlinkat(const char *path1, int fd, const char *path2); */
1837 /* Interpret the second argument as 32-bit value even on 64-bit architecture.
1838 This is different from Linux, for example, where glibc sign-extends it. */
1839 Int fd = (Int) ARG2;
1841 PRINT("sys_symlinkat ( %#lx(%s), %d, %#lx(%s) )",
1842 ARG1, (HChar *) ARG1, fd, ARG3, (HChar *) ARG3);
1843 PRE_REG_READ3(long, "symlinkat", const char *, path1, int, fd,
1844 const char *, path2);
1845 PRE_MEM_RASCIIZ("symlinkat(path1)", ARG1);
1846 PRE_MEM_RASCIIZ("symlinkat(path2)", ARG3);
1848 /* Be strict but ignore fd for absolute path2. */
1849 if (fd != VKI_AT_FDCWD
1850 && ML_(safe_to_deref)((void *) ARG3, 1)
1851 && ((HChar *) ARG3)[0] != '/'
1852 && !ML_(fd_allowed)(fd, "symlinkat", tid, False))
1853 SET_STATUS_Failure(VKI_EBADF);
1855 *flags |= SfMayBlock;
1858 PRE(sys_time)
1860 /* time_t time(); */
1861 PRINT("sys_time ( )");
1862 PRE_REG_READ0(long, "time");
1865 /* Data segment for brk (heap). It is an expandable anonymous mapping
1866 abutting a 1-page reservation. The data segment starts at VG_(brk_base)
1867 and runs up to VG_(brk_limit). None of these two values have to be
1868 page-aligned.
1869 Initial data segment is established (see initimg-solaris.c for rationale):
1870 - directly during client program image initialization,
1871 - or on demand when the executed program is the runtime linker itself,
1872 after it has loaded its target dynamic executable (see PRE(sys_mmapobj)),
1873 or when the first brk() syscall is made.
1875 Notable facts:
1876 - VG_(brk_base) is not page aligned; does not move
1877 - VG_(brk_limit) moves between [VG_(brk_base), data segment end]
1878 - data segment end is always page aligned
1879 - right after data segment end is 1-page reservation
1881 | heap | 1 page
1882 +------+------+--------------+-------+
1883 | BSS | anon | anon | resvn |
1884 +------+------+--------------+-------+
1886 ^ ^ ^ ^
1887 | | | |
1888 | | | data segment end
1889 | | VG_(brk_limit) -- no alignment constraint
1890 | brk_base_pgup -- page aligned
1891 VG_(brk_base) -- not page aligned -- does not move
1893 Because VG_(brk_base) is not page-aligned and is initially located within
1894 pre-established BSS (data) segment, special care has to be taken in the code
1895 below to handle this feature.
1897 Reservation segment is used to protect the data segment merging with
1898 a pre-existing segment. This should be no problem because address space
1899 manager ensures that requests for client address space are satisfied from
1900 the highest available addresses. However when memory is low, data segment
1901 can meet with mmap'ed objects and the reservation segment separates these.
1902 The page that contains VG_(brk_base) is already allocated by the program's
1903 loaded data segment. The brk syscall wrapper handles this special case. */
1905 static Bool brk_segment_established = False;
1907 /* Establishes initial data segment for brk (heap). */
1908 Bool VG_(setup_client_dataseg)(void)
1910 /* Segment size is initially at least 1 MB and at most 8 MB. */
1911 SizeT m1 = 1024 * 1024;
1912 SizeT m8 = 8 * m1;
1913 SizeT initial_size = VG_(client_rlimit_data).rlim_cur;
1914 VG_(debugLog)(1, "syswrap-solaris", "Setup client data (brk) segment "
1915 "at %#lx\n", VG_(brk_base));
1916 if (initial_size < m1)
1917 initial_size = m1;
1918 if (initial_size > m8)
1919 initial_size = m8;
1920 initial_size = VG_PGROUNDUP(initial_size);
1922 Addr anon_start = VG_PGROUNDUP(VG_(brk_base));
1923 SizeT anon_size = VG_PGROUNDUP(initial_size);
1924 Addr resvn_start = anon_start + anon_size;
1925 SizeT resvn_size = VKI_PAGE_SIZE;
1927 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
1928 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
1929 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
1930 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
1931 vg_assert(VG_(brk_base) == VG_(brk_limit));
1933 /* Find the loaded data segment and remember its protection. */
1934 const NSegment *seg = VG_(am_find_nsegment)(VG_(brk_base) - 1);
1935 vg_assert(seg != NULL);
1936 UInt prot = (seg->hasR ? VKI_PROT_READ : 0)
1937 | (seg->hasW ? VKI_PROT_WRITE : 0)
1938 | (seg->hasX ? VKI_PROT_EXEC : 0);
1940 /* Try to create the data segment and associated reservation where
1941 VG_(brk_base) says. */
1942 Bool ok = VG_(am_create_reservation)(resvn_start, resvn_size, SmLower,
1943 anon_size);
1944 if (!ok) {
1945 /* That didn't work, we're hosed. */
1946 return False;
1949 /* Map the data segment. */
1950 SysRes sres = VG_(am_mmap_anon_fixed_client)(anon_start, anon_size, prot);
1951 vg_assert(!sr_isError(sres));
1952 vg_assert(sr_Res(sres) == anon_start);
1954 brk_segment_established = True;
1955 return True;
1958 /* Tell the tool about the client data segment and then kill it which will
1959 make it initially inaccessible/unaddressable. */
1960 void VG_(track_client_dataseg)(ThreadId tid)
1962 const NSegment *seg = VG_(am_find_nsegment)(VG_PGROUNDUP(VG_(brk_base)));
1963 vg_assert(seg != NULL);
1964 vg_assert(seg->kind == SkAnonC);
1966 VG_TRACK(new_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base), tid);
1967 VG_TRACK(die_mem_brk, VG_(brk_base), seg->end + 1 - VG_(brk_base));
1970 static void PRINTF_CHECK(1, 2)
1971 possibly_complain_brk(const HChar *format, ...)
1973 static Bool alreadyComplained = False;
1974 if (!alreadyComplained) {
1975 alreadyComplained = True;
1976 if (VG_(clo_verbosity) > 0) {
1977 va_list vargs;
1978 va_start(vargs, format);
1979 VG_(vmessage)(Vg_UserMsg, format, vargs);
1980 va_end(vargs);
1981 VG_(umsg)("(See section Limitations in the user manual.)\n");
1982 VG_(umsg)("NOTE: further instances of this message will not be "
1983 "shown.\n");
1988 PRE(sys_brk)
1990 /* unsigned long brk(caddr_t end_data_segment); */
1991 /* The Solaris kernel returns 0 on success.
1992 In addition to this, brk(0) returns current data segment end. This is
1993 very different from the Linux kernel, for example. */
1995 Addr old_brk_limit = VG_(brk_limit);
1996 /* If VG_(brk_base) is page-aligned then old_brk_base_pgup is equal to
1997 VG_(brk_base). */
1998 Addr old_brk_base_pgup = VG_PGROUNDUP(VG_(brk_base));
1999 Addr new_brk = ARG1;
2000 const NSegment *seg, *seg2;
2002 PRINT("sys_brk ( %#lx )", ARG1);
2003 PRE_REG_READ1(unsigned long, "brk", vki_caddr_t, end_data_segment);
2005 if (new_brk == 0) {
2006 /* brk(0) - specific to Solaris 11 only. */
2007 SET_STATUS_Success(old_brk_limit);
2008 return;
2011 /* Handle some trivial cases. */
2012 if (new_brk == old_brk_limit) {
2013 SET_STATUS_Success(0);
2014 return;
2016 if (new_brk < VG_(brk_base)) {
2017 /* Clearly impossible. */
2018 SET_STATUS_Failure(VKI_ENOMEM);
2019 return;
2021 if (new_brk - VG_(brk_base) > VG_(client_rlimit_data).rlim_cur) {
2022 SET_STATUS_Failure(VKI_ENOMEM);
2023 return;
2026 /* The brk base and limit must have been already set. */
2027 vg_assert(VG_(brk_base) != -1);
2028 vg_assert(VG_(brk_limit) != -1);
2030 if (!brk_segment_established) {
2031 /* Stay sane (because there should have been no brk activity yet). */
2032 vg_assert(VG_(brk_base) == VG_(brk_limit));
2034 if (!VG_(setup_client_dataseg)()) {
2035 possibly_complain_brk("Cannot map memory to initialize brk segment in "
2036 "thread #%u at %#lx\n", tid, VG_(brk_base));
2037 SET_STATUS_Failure(VKI_ENOMEM);
2038 return;
2041 VG_(track_client_dataseg)(tid);
2044 if (new_brk < old_brk_limit) {
2045 /* Shrinking the data segment. Be lazy and don't munmap the excess
2046 area. */
2047 if (old_brk_limit > old_brk_base_pgup) {
2048 /* Calculate new local brk (=MAX(new_brk, old_brk_base_pgup)). */
2049 Addr new_brk_local;
2050 if (new_brk < old_brk_base_pgup)
2051 new_brk_local = old_brk_base_pgup;
2052 else
2053 new_brk_local = new_brk;
2055 /* Find a segment at the beginning and at the end of the shrinked
2056 range. */
2057 seg = VG_(am_find_nsegment)(new_brk_local);
2058 seg2 = VG_(am_find_nsegment)(old_brk_limit - 1);
2059 vg_assert(seg);
2060 vg_assert(seg->kind == SkAnonC);
2061 vg_assert(seg2);
2062 vg_assert(seg == seg2);
2064 /* Discard any translations and zero-out the area. */
2065 if (seg->hasT)
2066 VG_(discard_translations)(new_brk_local,
2067 old_brk_limit - new_brk_local,
2068 "do_brk(shrink)");
2069 /* Since we're being lazy and not unmapping pages, we have to zero out
2070 the area, so that if the area later comes back into circulation, it
2071 will be filled with zeroes, as if it really had been unmapped and
2072 later remapped. Be a bit paranoid and try hard to ensure we're not
2073 going to segfault by doing the write - check that segment is
2074 writable. */
2075 if (seg->hasW)
2076 VG_(memset)((void*)new_brk_local, 0, old_brk_limit - new_brk_local);
2079 /* Fixup code if the VG_(brk_base) is not page-aligned. */
2080 if (new_brk < old_brk_base_pgup) {
2081 /* Calculate old local brk (=MIN(old_brk_limit, old_brk_base_up)). */
2082 Addr old_brk_local;
2083 if (old_brk_limit < old_brk_base_pgup)
2084 old_brk_local = old_brk_limit;
2085 else
2086 old_brk_local = old_brk_base_pgup;
2088 /* Find a segment at the beginning and at the end of the shrinked
2089 range. */
2090 seg = VG_(am_find_nsegment)(new_brk);
2091 seg2 = VG_(am_find_nsegment)(old_brk_local - 1);
2092 vg_assert(seg);
2093 vg_assert(seg2);
2094 vg_assert(seg == seg2);
2096 /* Discard any translations and zero-out the area. */
2097 if (seg->hasT)
2098 VG_(discard_translations)(new_brk, old_brk_local - new_brk,
2099 "do_brk(shrink)");
2100 if (seg->hasW)
2101 VG_(memset)((void*)new_brk, 0, old_brk_local - new_brk);
2104 /* We are done, update VG_(brk_limit), tell the tool about the changes,
2105 and leave. */
2106 VG_(brk_limit) = new_brk;
2107 VG_TRACK(die_mem_brk, new_brk, old_brk_limit - new_brk);
2108 SET_STATUS_Success(0);
2109 return;
2112 /* We are expanding the brk segment. */
2114 /* Fixup code if the VG_(brk_base) is not page-aligned. */
2115 if (old_brk_limit < old_brk_base_pgup) {
2116 /* Calculate new local brk (=MIN(new_brk, old_brk_base_pgup)). */
2117 Addr new_brk_local;
2118 if (new_brk < old_brk_base_pgup)
2119 new_brk_local = new_brk;
2120 else
2121 new_brk_local = old_brk_base_pgup;
2123 /* Find a segment at the beginning and at the end of the expanded
2124 range. */
2125 seg = VG_(am_find_nsegment)(old_brk_limit);
2126 seg2 = VG_(am_find_nsegment)(new_brk_local - 1);
2127 vg_assert(seg);
2128 vg_assert(seg2);
2129 vg_assert(seg == seg2);
2131 /* Nothing else to do. */
2134 if (new_brk > old_brk_base_pgup) {
2135 /* Calculate old local brk (=MAX(old_brk_limit, old_brk_base_pgup)). */
2136 Addr old_brk_local;
2137 if (old_brk_limit < old_brk_base_pgup)
2138 old_brk_local = old_brk_base_pgup;
2139 else
2140 old_brk_local = old_brk_limit;
2142 /* Find a segment at the beginning of the expanded range. */
2143 if (old_brk_local > old_brk_base_pgup)
2144 seg = VG_(am_find_nsegment)(old_brk_local - 1);
2145 else
2146 seg = VG_(am_find_nsegment)(old_brk_local);
2147 vg_assert(seg);
2148 vg_assert(seg->kind == SkAnonC);
2150 /* Find the 1-page reservation segment. */
2151 seg2 = VG_(am_next_nsegment)(seg, True/*forwards*/);
2152 vg_assert(seg2);
2153 vg_assert(seg2->kind == SkResvn);
2154 vg_assert(seg->end + 1 == seg2->start);
2155 vg_assert(seg2->end - seg2->start + 1 == VKI_PAGE_SIZE);
2157 if (new_brk <= seg2->start) {
2158 /* Still fits within the existing anon segment, nothing to do. */
2159 } else {
2160 /* Data segment limit was already checked. */
2161 Addr anon_start = seg->end + 1;
2162 Addr resvn_start = VG_PGROUNDUP(new_brk);
2163 SizeT anon_size = resvn_start - anon_start;
2164 SizeT resvn_size = VKI_PAGE_SIZE;
2165 SysRes sres;
2167 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
2168 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
2169 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
2170 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
2171 vg_assert(anon_size > 0);
2173 /* Address space manager checks for free address space for us;
2174 reservation would not be otherwise created. */
2175 Bool ok = VG_(am_create_reservation)(resvn_start, resvn_size, SmLower,
2176 anon_size);
2177 if (!ok) {
2178 possibly_complain_brk("brk segment overflow in thread #%u: can not "
2179 "grow to %#lx\n", tid, new_brk);
2180 SET_STATUS_Failure(VKI_ENOMEM);
2181 return;
2184 /* Establish protection from the existing segment. */
2185 UInt prot = (seg->hasR ? VKI_PROT_READ : 0)
2186 | (seg->hasW ? VKI_PROT_WRITE : 0)
2187 | (seg->hasX ? VKI_PROT_EXEC : 0);
2189 /* Address space manager will merge old and new data segments. */
2190 sres = VG_(am_mmap_anon_fixed_client)(anon_start, anon_size, prot);
2191 if (sr_isError(sres)) {
2192 possibly_complain_brk("Cannot map memory to grow brk segment in "
2193 "thread #%u to %#lx\n", tid, new_brk);
2194 SET_STATUS_Failure(VKI_ENOMEM);
2195 return;
2197 vg_assert(sr_Res(sres) == anon_start);
2199 seg = VG_(am_find_nsegment)(old_brk_base_pgup);
2200 seg2 = VG_(am_find_nsegment)(VG_PGROUNDUP(new_brk) - 1);
2201 vg_assert(seg);
2202 vg_assert(seg2);
2203 vg_assert(seg == seg2);
2204 vg_assert(new_brk <= seg->end + 1);
2208 /* We are done, update VG_(brk_limit), tell the tool about the changes, and
2209 leave. */
2210 VG_(brk_limit) = new_brk;
2211 VG_TRACK(new_mem_brk, old_brk_limit, new_brk - old_brk_limit, tid);
2212 SET_STATUS_Success(0);
2215 PRE(sys_stat)
2217 /* int stat(const char *path, struct stat *buf); */
2218 /* Note: We could use here the sys_newstat generic wrapper, but the 'new'
2219 in its name is rather confusing in the Solaris context, thus we provide
2220 our own wrapper. */
2221 PRINT("sys_stat ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
2222 PRE_REG_READ2(long, "stat", const char *, path, struct stat *, buf);
2224 PRE_MEM_RASCIIZ("stat(path)", ARG1);
2225 PRE_MEM_WRITE("stat(buf)", ARG2, sizeof(struct vki_stat));
2228 POST(sys_stat)
2230 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
2233 PRE(sys_lseek)
2235 /* off_t lseek(int fildes, off_t offset, int whence); */
2236 PRINT("sys_lseek ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
2237 PRE_REG_READ3(long, "lseek", int, fildes, vki_off_t, offset, int, whence);
2239 /* Stay sane. */
2240 if (!ML_(fd_allowed)(ARG1, "lseek", tid, False))
2241 SET_STATUS_Failure(VKI_EBADF);
2244 PRE(sys_mount)
2246 /* int mount(const char *spec, const char *dir, int mflag, char *fstype,
2247 char *dataptr, int datalen, char *optptr, int optlen); */
2248 *flags |= SfMayBlock;
2249 if (ARG3 & VKI_MS_OPTIONSTR) {
2250 /* 8-argument mount */
2251 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s), %#lx, %lu, "
2252 "%#lx(%s), %ld )", ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3,
2253 ARG4, (HChar *) ARG4, ARG5, ARG6, ARG7, (HChar *) ARG7, SARG8);
2254 PRE_REG_READ8(long, "mount", const char *, spec, const char *, dir,
2255 int, mflag, char *, fstype, char *, dataptr, int, datalen,
2256 char *, optptr, int, optlen);
2258 else if (ARG3 & VKI_MS_DATA) {
2259 /* 6-argument mount */
2260 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s), %#lx, %ld )",
2261 ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3, ARG4,
2262 (HChar *) ARG4, ARG5, SARG6);
2263 PRE_REG_READ6(long, "mount", const char *, spec, const char *, dir,
2264 int, mflag, char *, fstype, char *, dataptr,
2265 int, datalen);
2267 else {
2268 /* 4-argument mount */
2269 PRINT("sys_mount ( %#lx(%s), %#lx(%s), %ld, %#lx(%s) )", ARG1,
2270 (HChar *) ARG1, ARG2, (HChar *) ARG2, SARG3, ARG4, (HChar *) ARG4);
2271 PRE_REG_READ4(long, "mount", const char *, spec, const char *, dir,
2272 int, mflag, char *, fstype);
2274 if (ARG1)
2275 PRE_MEM_RASCIIZ("mount(spec)", ARG1);
2276 PRE_MEM_RASCIIZ("mount(dir)", ARG2);
2277 if (ARG4 && ARG4 >= 256) {
2278 /* If ARG4 < 256, then it's an index to a fs table in the kernel. */
2279 PRE_MEM_RASCIIZ("mount(fstype)", ARG4);
2281 if (ARG3 & (VKI_MS_DATA | VKI_MS_OPTIONSTR)) {
2282 if (ARG5)
2283 PRE_MEM_READ("mount(dataptr)", ARG5, ARG6);
2284 if ((ARG3 & VKI_MS_OPTIONSTR) && ARG7) {
2285 /* in/out buffer */
2286 PRE_MEM_RASCIIZ("mount(optptr)", ARG7);
2287 PRE_MEM_WRITE("mount(optptr)", ARG7, ARG8);
2292 POST(sys_mount)
2294 if (ARG3 & VKI_MS_OPTIONSTR) {
2295 POST_MEM_WRITE(ARG7, VG_(strlen)((HChar*)ARG7) + 1);
2296 } else if (ARG3 & VKI_MS_DATA) {
2297 if ((ARG2) &&
2298 (ARG3 & MS_NOMNTTAB) &&
2299 (VG_STREQ((HChar *) ARG4, "namefs")) &&
2300 (ARG6 == sizeof(struct vki_namefd)) &&
2301 ML_(safe_to_deref)((void *) ARG5, ARG6)) {
2302 /* Most likely an fattach() call for a door file descriptor. */
2303 door_record_server_fattach(((struct vki_namefd *) ARG5)->fd,
2304 (HChar *) ARG2);
2309 PRE(sys_readlinkat)
2311 /* ssize_t readlinkat(int dfd, const char *path, char *buf,
2312 size_t bufsiz); */
2313 HChar name[30]; // large enough
2314 Word saved = SYSNO;
2316 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2317 This is different from Linux, for example, where glibc sign-extends it. */
2318 Int dfd = (Int) ARG1;
2320 PRINT("sys_readlinkat ( %d, %#lx(%s), %#lx, %ld )", dfd, ARG2,
2321 (HChar *) ARG2, ARG3, SARG4);
2322 PRE_REG_READ4(long, "readlinkat", int, dfd, const char *, path,
2323 char *, buf, int, bufsiz);
2324 PRE_MEM_RASCIIZ("readlinkat(path)", ARG2);
2325 PRE_MEM_WRITE("readlinkat(buf)", ARG3, ARG4);
2327 /* Be strict but ignore dfd for absolute path. */
2328 if (dfd != VKI_AT_FDCWD
2329 && ML_(safe_to_deref)((void *) ARG2, 1)
2330 && ((HChar *) ARG2)[0] != '/'
2331 && !ML_(fd_allowed)(dfd, "readlinkat", tid, False)) {
2332 SET_STATUS_Failure(VKI_EBADF);
2333 return;
2336 /* Handle the case where readlinkat is looking at /proc/self/path/a.out or
2337 /proc/<pid>/path/a.out. */
2338 VG_(sprintf)(name, "/proc/%d/path/a.out", VG_(getpid)());
2339 if (ML_(safe_to_deref)((void*)ARG2, 1) &&
2340 (!VG_(strcmp)((HChar*)ARG2, name) ||
2341 !VG_(strcmp)((HChar*)ARG2, "/proc/self/path/a.out"))) {
2342 VG_(sprintf)(name, "/proc/self/path/%d", VG_(cl_exec_fd));
2343 SET_STATUS_from_SysRes(VG_(do_syscall4)(saved, dfd, (UWord)name, ARG3,
2344 ARG4));
2348 POST(sys_readlinkat)
2350 POST_MEM_WRITE(ARG3, RES);
2353 PRE(sys_stime)
2355 /* Kernel: int stime(time_t time); */
2356 PRINT("sys_stime ( %lu )", ARG1);
2357 PRE_REG_READ1(long, "stime", vki_time_t, time);
2360 PRE(sys_fstat)
2362 /* int fstat(int fildes, struct stat *buf); */
2363 /* Note: We could use here the sys_newfstat generic wrapper, but the 'new'
2364 in its name is rather confusing in the Solaris context, thus we provide
2365 our own wrapper. */
2366 PRINT("sys_fstat ( %ld, %#lx )", SARG1, ARG2);
2367 PRE_REG_READ2(long, "fstat", int, fildes, struct stat *, buf);
2368 PRE_MEM_WRITE("fstat(buf)", ARG2, sizeof(struct vki_stat));
2370 /* Be strict. */
2371 if (!ML_(fd_allowed)(ARG1, "fstat", tid, False))
2372 SET_STATUS_Failure(VKI_EBADF);
2375 POST(sys_fstat)
2377 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
2380 #if defined(SOLARIS_FREALPATHAT_SYSCALL)
2381 PRE(sys_frealpathat)
2383 /* int frealpathat(int fd, char *path, char *buf, size_t buflen); */
2385 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2386 This is different from Linux, for example, where glibc sign-extends it. */
2387 Int fd = (Int) ARG1;
2389 PRINT("sys_frealpathat ( %d, %#lx(%s), %#lx, %lu )",
2390 fd, ARG2, (HChar *) ARG2, ARG3, ARG4);
2391 PRE_REG_READ4(long, "frealpathat", int, fd, char *, path,
2392 char *, buf, vki_size_t, buflen);
2393 PRE_MEM_RASCIIZ("frealpathat(path)", ARG2);
2394 PRE_MEM_WRITE("frealpathat(buf)", ARG3, ARG4);
2396 /* Be strict but ignore fd for absolute path. */
2397 if (fd != VKI_AT_FDCWD
2398 && ML_(safe_to_deref)((void *) ARG2, 1)
2399 && ((HChar *) ARG2)[0] != '/'
2400 && !ML_(fd_allowed)(fd, "frealpathat", tid, False))
2401 SET_STATUS_Failure(VKI_EBADF);
2404 POST(sys_frealpathat)
2406 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
2408 #endif /* SOLARIS_FREALPATHAT_SYSCALL */
2410 PRE(sys_stty)
2412 /* int stty(int fd, const struct sgttyb *tty); */
2413 PRINT("sys_stty ( %ld, %#lx )", SARG1, ARG2);
2414 PRE_REG_READ2(long, "stty", int, fd,
2415 const struct vki_sgttyb *, tty);
2416 PRE_MEM_READ("stty(tty)", ARG2, sizeof(struct vki_sgttyb));
2418 /* Be strict. */
2419 if (!ML_(fd_allowed)(ARG1, "stty", tid, False))
2420 SET_STATUS_Failure(VKI_EBADF);
2423 PRE(sys_gtty)
2425 /* int gtty(int fd, struct sgttyb *tty); */
2426 PRINT("sys_gtty ( %ld, %#lx )", SARG1, ARG2);
2427 PRE_REG_READ2(long, "gtty", int, fd, struct vki_sgttyb *, tty);
2428 PRE_MEM_WRITE("gtty(tty)", ARG2, sizeof(struct vki_sgttyb));
2430 /* Be strict. */
2431 if (!ML_(fd_allowed)(ARG1, "gtty", tid, False))
2432 SET_STATUS_Failure(VKI_EBADF);
2435 POST(sys_gtty)
2437 POST_MEM_WRITE(ARG2, sizeof(struct vki_sgttyb));
2440 PRE(sys_pgrpsys)
2442 /* Kernel: int setpgrp(int flag, int pid, int pgid); */
2443 switch (ARG1 /*flag*/) {
2444 case 0:
2445 /* Libc: pid_t getpgrp(void); */
2446 PRINT("sys_pgrpsys ( %ld )", SARG1);
2447 PRE_REG_READ1(long, SC2("pgrpsys", "getpgrp"), int, flag);
2448 break;
2449 case 1:
2450 /* Libc: pid_t setpgrp(void); */
2451 PRINT("sys_pgrpsys ( %ld )", SARG1);
2452 PRE_REG_READ1(long, SC2("pgrpsys", "setpgrp"), int, flag);
2453 break;
2454 case 2:
2455 /* Libc: pid_t getsid(pid_t pid); */
2456 PRINT("sys_pgrpsys ( %ld, %ld )", SARG1, SARG2);
2457 PRE_REG_READ2(long, SC2("pgrpsys", "getsid"), int, flag,
2458 vki_pid_t, pid);
2459 break;
2460 case 3:
2461 /* Libc: pid_t setsid(void); */
2462 PRINT("sys_pgrpsys ( %ld )", SARG1);
2463 PRE_REG_READ1(long, SC2("pgrpsys", "setsid"), int, flag);
2464 break;
2465 case 4:
2466 /* Libc: pid_t getpgid(pid_t pid); */
2467 PRINT("sys_pgrpsys ( %ld, %ld )", SARG1, SARG2);
2468 PRE_REG_READ2(long, SC2("pgrpsys", "getpgid"), int, flag,
2469 vki_pid_t, pid);
2470 break;
2471 case 5:
2472 /* Libc: int setpgid(pid_t pid, pid_t pgid); */
2473 PRINT("sys_pgrpsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
2474 PRE_REG_READ3(long, SC2("pgrpsys", "setpgid"), int, flag,
2475 vki_pid_t, pid, vki_pid_t, pgid);
2476 break;
2477 default:
2478 VG_(unimplemented)("Syswrap of the pgrpsys call with flag %ld.", SARG1);
2479 /*NOTREACHED*/
2480 break;
2484 PRE(sys_pipe)
2486 #if defined(SOLARIS_NEW_PIPE_SYSCALL)
2487 /* int pipe(int fildes[2], int flags); */
2488 PRINT("sys_pipe ( %#lx, %ld )", ARG1, SARG2);
2489 PRE_REG_READ2(long, "pipe", int *, fildes, int, flags);
2490 PRE_MEM_WRITE("pipe(fildes)", ARG1, 2 * sizeof(int));
2491 #else
2492 /* longlong_t pipe(); */
2493 PRINT("sys_pipe ( )");
2494 PRE_REG_READ0(long, "pipe");
2495 #endif /* SOLARIS_NEW_PIPE_SYSCALL */
2498 POST(sys_pipe)
2500 Int p0, p1;
2502 #if defined(SOLARIS_NEW_PIPE_SYSCALL)
2503 int *fds = (int*)ARG1;
2504 p0 = fds[0];
2505 p1 = fds[1];
2506 POST_MEM_WRITE(ARG1, 2 * sizeof(int));
2507 #else
2508 p0 = RES;
2509 p1 = RESHI;
2510 #endif /* SOLARIS_NEW_PIPE_SYSCALL */
2512 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
2513 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
2514 VG_(close)(p0);
2515 VG_(close)(p1);
2516 SET_STATUS_Failure(VKI_EMFILE);
2518 else if (VG_(clo_track_fds)) {
2519 ML_(record_fd_open_nameless)(tid, p0);
2520 ML_(record_fd_open_nameless)(tid, p1);
2524 PRE(sys_faccessat)
2526 /* int faccessat(int fd, const char *path, int amode, int flag); */
2528 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2529 This is different from Linux, for example, where glibc sign-extends it. */
2530 Int fd = (Int) ARG1;
2532 PRINT("sys_faccessat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2,
2533 (HChar *) ARG2, SARG3, SARG4);
2534 PRE_REG_READ4(long, "faccessat", int, fd, const char *, path,
2535 int, amode, int, flag);
2536 PRE_MEM_RASCIIZ("faccessat(path)", ARG2);
2538 /* Be strict but ignore fd for absolute path. */
2539 if (fd != VKI_AT_FDCWD
2540 && ML_(safe_to_deref)((void *) ARG2, 1)
2541 && ((HChar *) ARG2)[0] != '/'
2542 && !ML_(fd_allowed)(fd, "faccessat", tid, False))
2543 SET_STATUS_Failure(VKI_EBADF);
2546 PRE(sys_mknodat)
2548 /* int mknodat(int fd, char *fname, mode_t fmode, dev_t dev); */
2550 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
2551 This is different from Linux, for example, where glibc sign-extends it. */
2552 Int fd = (Int) ARG1;
2554 PRINT("sys_mknodat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2,
2555 (HChar *) ARG2, SARG3, SARG4);
2556 PRE_REG_READ4(long, "mknodat", int, fd, const char *, fname,
2557 vki_mode_t, fmode, vki_dev_t, dev);
2558 PRE_MEM_RASCIIZ("mknodat(fname)", ARG2);
2560 /* Be strict but ignore fd for absolute path. */
2561 if (fd != VKI_AT_FDCWD
2562 && ML_(safe_to_deref)((void *) ARG2, 1)
2563 && ((HChar *) ARG2)[0] != '/'
2564 && !ML_(fd_allowed)(fd, "mknodat", tid, False))
2565 SET_STATUS_Failure(VKI_EBADF);
2567 *flags |= SfMayBlock;
2570 POST(sys_mknodat)
2572 if (!ML_(fd_allowed)(RES, "mknodat", tid, True)) {
2573 VG_(close)(RES);
2574 SET_STATUS_Failure(VKI_EMFILE);
2575 } else if (VG_(clo_track_fds))
2576 ML_(record_fd_open_with_given_name)(tid, RES, (HChar *) ARG2);
2579 PRE(sys_sysi86)
2581 /* int sysi86(int cmd, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3); */
2582 PRINT("sys_sysi86 ( %ld, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
2583 PRE_REG_READ4(long, "sysi86", int, cmd, uintptr_t, arg1, uintptr_t, arg2,
2584 uintptr_t, arg3);
2586 switch (ARG1 /*cmd*/) {
2587 case VKI_SI86FPSTART:
2588 PRE_MEM_WRITE("sysi86(fp_hw)", ARG2, sizeof(vki_uint_t));
2589 /* ARG3 is a desired x87 FCW value, ARG4 is a desired SSE MXCSR value.
2590 They are passed to the kernel but V will change them later anyway
2591 (this is a general Valgrind limitation described in the official
2592 documentation). */
2593 break;
2594 default:
2595 VG_(unimplemented)("Syswrap of the sysi86 call with cmd %ld.", SARG1);
2596 /*NOTREACHED*/
2597 break;
2601 POST(sys_sysi86)
2603 switch (ARG1 /*cmd*/) {
2604 case VKI_SI86FPSTART:
2605 POST_MEM_WRITE(ARG2, sizeof(vki_uint_t));
2606 break;
2607 default:
2608 vg_assert(0);
2609 break;
2613 PRE(sys_shmsys)
2615 /* Kernel: uintptr_t shmsys(int opcode, uintptr_t a0, uintptr_t a1,
2616 uintptr_t a2, uintptr_t a3);
2618 *flags |= SfMayBlock;
2620 switch (ARG1 /*opcode*/) {
2621 case VKI_SHMAT:
2622 /* Libc: void *shmat(int shmid, const void *shmaddr, int shmflg); */
2623 PRINT("sys_shmsys ( %ld, %ld, %#lx, %ld )",
2624 SARG1, SARG2, ARG3, SARG4);
2625 PRE_REG_READ4(long, SC2("shmsys", "shmat"), int, opcode,
2626 int, shmid, const void *, shmaddr, int, shmflg);
2628 UWord addr = ML_(generic_PRE_sys_shmat)(tid, ARG2, ARG3, ARG4);
2629 if (addr == 0)
2630 SET_STATUS_Failure(VKI_EINVAL);
2631 else
2632 ARG3 = addr;
2633 break;
2635 case VKI_SHMCTL:
2636 /* Libc: int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
2637 switch (ARG3 /* cmd */) {
2638 case VKI_SHM_LOCK:
2639 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
2640 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "lock"),
2641 int, opcode, int, shmid, int, cmd);
2642 break;
2643 case VKI_SHM_UNLOCK:
2644 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
2645 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "unlock"),
2646 int, opcode, int, shmid, int, cmd);
2647 break;
2648 case VKI_IPC_RMID:
2649 PRINT("sys_shmsys ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
2650 PRE_REG_READ3(long, SC3("shmsys", "shmctl", "rmid"),
2651 int, opcode, int, shmid, int, cmd);
2652 break;
2653 case VKI_IPC_SET:
2654 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
2655 SARG1, SARG2, SARG3, ARG4);
2656 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "set"),
2657 int, opcode, int, shmid, int, cmd,
2658 struct vki_shmid_ds *, buf);
2660 struct vki_shmid_ds *buf = (struct vki_shmid_ds *) ARG4;
2661 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.uid)",
2662 buf->shm_perm.uid);
2663 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.gid)",
2664 buf->shm_perm.gid);
2665 PRE_FIELD_READ("shmsys(shmctl, ipc_set, buf->shm_perm.mode)",
2666 buf->shm_perm.mode);
2667 break;
2668 case VKI_IPC_STAT:
2669 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
2670 SARG1, SARG2, SARG3, ARG4);
2671 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "stat"),
2672 int, opcode, int, shmid, int, cmd,
2673 struct vki_shmid_ds *, buf);
2674 PRE_MEM_WRITE("shmsys(shmctl, ipc_stat, buf)", ARG4,
2675 sizeof(struct vki_shmid_ds));
2676 break;
2677 case VKI_IPC_SET64:
2678 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
2679 SARG1, SARG2, SARG3, ARG4);
2680 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "set64"),
2681 int, opcode, int, shmid, int, cmd,
2682 struct vki_shmid_ds64 *, buf);
2684 struct vki_shmid_ds64 *buf64 = (struct vki_shmid_ds64 *) ARG4;
2685 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2686 "buf->shmx_perm.ipcx_uid)",
2687 buf64->shmx_perm.ipcx_uid);
2688 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2689 "buf->shmx_perm.ipcx_gid)",
2690 buf64->shmx_perm.ipcx_gid);
2691 PRE_FIELD_READ("shmsys(shmctl, ipc_set64, "
2692 "buf->shmx_perm.ipcx_mode)",
2693 buf64->shmx_perm.ipcx_mode);
2694 break;
2695 case VKI_IPC_STAT64:
2696 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
2697 SARG1, SARG2, SARG3, ARG4);
2698 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "stat64"),
2699 int, opcode, int, shmid, int, cmd,
2700 struct vki_shmid_ds64 *, buf);
2701 PRE_MEM_WRITE("shmsys(shmctl, ipc_stat64, buf)", ARG4,
2702 sizeof(struct vki_shmid_ds64));
2703 break;
2704 #if defined(SOLARIS_SHM_NEW)
2705 case VKI_IPC_XSTAT64:
2706 PRINT("sys_shmsys ( %ld, %ld, %ld, %#lx )",
2707 SARG1, SARG2, SARG3, ARG4);
2708 PRE_REG_READ4(long, SC3("shmsys", "shmctl", "xstat64"),
2709 int, opcode, int, shmid, int, cmd,
2710 struct vki_shmid_ds64 *, buf);
2711 PRE_MEM_WRITE("shmsys(shmctl, ipc_xstat64, buf)", ARG4,
2712 sizeof(struct vki_shmid_xds64));
2713 break;
2714 #endif /* SOLARIS_SHM_NEW */
2715 default:
2716 VG_(unimplemented)("Syswrap of the shmsys(shmctl) call with "
2717 "cmd %ld.", SARG3);
2718 /*NOTREACHED*/
2719 break;
2721 break;
2723 case VKI_SHMDT:
2724 /* Libc: int shmdt(const void *shmaddr); */
2725 PRINT("sys_shmsys ( %ld, %#lx )", SARG1, ARG2);
2726 PRE_REG_READ2(long, SC2("shmsys", "shmdt"), int, opcode,
2727 const void *, shmaddr);
2729 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG2))
2730 SET_STATUS_Failure(VKI_EINVAL);
2731 break;
2733 case VKI_SHMGET:
2734 /* Libc: int shmget(key_t key, size_t size, int shmflg); */
2735 PRINT("sys_shmsys ( %ld, %ld, %lu, %lu )",
2736 SARG1, SARG2, ARG3, ARG4);
2737 PRE_REG_READ4(long, SC2("shmsys", "shmget"), int, opcode,
2738 vki_key_t, key, vki_size_t, size, int, shmflg);
2739 break;
2741 case VKI_SHMIDS:
2742 /* Libc: int shmids(int *buf, uint_t nids, uint_t *pnids); */
2743 PRINT("sys_shmsys ( %ld, %#lx, %lu, %#lx )",
2744 SARG1, ARG2, ARG3, ARG4);
2745 PRE_REG_READ4(long, SC2("shmsys", "shmids"), int, opcode,
2746 int *, buf, vki_uint_t, nids, vki_uint_t *, pnids);
2748 PRE_MEM_WRITE("shmsys(shmids, buf)", ARG2, ARG3 * sizeof(int *));
2749 PRE_MEM_WRITE("shmsys(shmids, pnids)", ARG4, sizeof(vki_uint_t));
2750 break;
2752 #if defined(SOLARIS_SHM_NEW)
2753 case VKI_SHMADV:
2754 /* Libc: int shmadv(int shmid, uint_t cmd, uint_t *advice); */
2755 PRINT("sys_shmsys ( %ld, %ld, %lu, %ld )",
2756 SARG1, SARG2, ARG3, ARG4);
2757 PRE_REG_READ4(long, SC2("shmsys", "shmadv"), int, opcode,
2758 int, shmid, vki_uint_t, cmd, vki_uint_t *, advice);
2760 switch (ARG3 /*cmd*/) {
2761 case VKI_SHM_ADV_GET:
2762 PRE_MEM_WRITE("shmsys(shmadv, advice)", ARG4,
2763 sizeof(vki_uint_t));
2764 break;
2765 case VKI_SHM_ADV_SET:
2766 PRE_MEM_READ("shmsys(shmadv, advice)", ARG4,
2767 sizeof(vki_uint_t));
2768 break;
2769 default:
2770 VG_(unimplemented)("Syswrap of the shmsys(shmadv) call with "
2771 "cmd %lu.", ARG3);
2772 /*NOTREACHED*/
2773 break;
2775 break;
2777 case VKI_SHMGET_OSM:
2778 /* Libc: int shmget_osm(key_t key, size_t size, int shmflg,
2779 size_t granule_sz);
2781 PRINT("sys_shmsys ( %ld, %ld, %lu, %ld, %lu )",
2782 SARG1, SARG2, ARG3, SARG4, ARG5);
2783 PRE_REG_READ5(long, SC2("shmsys", "shmget_osm"), int, opcode,
2784 vki_key_t, key, vki_size_t, size, int, shmflg,
2785 vki_size_t, granule_sz);
2786 break;
2787 #endif /* SOLARIS_SHM_NEW */
2789 default:
2790 VG_(unimplemented)("Syswrap of the shmsys call with opcode %ld.",
2791 SARG1);
2792 /*NOTREACHED*/
2793 break;
2797 POST(sys_shmsys)
2799 switch (ARG1 /*opcode*/) {
2800 case VKI_SHMAT:
2801 ML_(generic_POST_sys_shmat)(tid, RES, ARG2, ARG3, ARG4);
2802 break;
2804 case VKI_SHMCTL:
2805 switch (ARG3 /*cmd*/) {
2806 case VKI_SHM_LOCK:
2807 case VKI_SHM_UNLOCK:
2808 case VKI_IPC_RMID:
2809 case VKI_IPC_SET:
2810 break;
2811 case VKI_IPC_STAT:
2812 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_ds));
2813 break;
2814 case VKI_IPC_SET64:
2815 break;
2816 case VKI_IPC_STAT64:
2817 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_ds64));
2818 break;
2819 #if defined(SOLARIS_SHM_NEW)
2820 case VKI_IPC_XSTAT64:
2821 POST_MEM_WRITE(ARG4, sizeof(struct vki_shmid_xds64));
2822 break;
2823 #endif /* SOLARIS_SHM_NEW */
2824 default:
2825 vg_assert(0);
2826 break;
2828 break;
2830 case VKI_SHMDT:
2831 ML_(generic_POST_sys_shmdt)(tid, RES, ARG2);
2832 break;
2834 case VKI_SHMGET:
2835 break;
2837 case VKI_SHMIDS:
2839 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
2841 uint_t *pnids = (vki_uint_t *) ARG4;
2842 if (*pnids <= ARG3)
2843 POST_MEM_WRITE(ARG2, *pnids * sizeof(int *));
2845 break;
2847 #if defined(SOLARIS_SHM_NEW)
2848 case VKI_SHMADV:
2849 switch (ARG3 /*cmd*/) {
2850 case VKI_SHM_ADV_GET:
2851 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
2852 break;
2853 case VKI_SHM_ADV_SET:
2854 break;
2855 default:
2856 vg_assert(0);
2857 break;
2859 break;
2861 case VKI_SHMGET_OSM:
2862 break;
2863 #endif /* SOLARIS_SHM_NEW */
2865 default:
2866 vg_assert(0);
2867 break;
2871 PRE(sys_semsys)
2873 /* Kernel: int semsys(int opcode, uintptr_t a1, uintptr_t a2, uintptr_t a3,
2874 uintptr_t a4);
2876 *flags |= SfMayBlock;
2878 switch (ARG1 /*opcode*/) {
2879 case VKI_SEMCTL:
2880 /* Libc: int semctl(int semid, int semnum, int cmd...); */
2881 switch (ARG4) {
2882 case VKI_IPC_STAT:
2883 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
2884 SARG1, SARG2, SARG3, SARG4, ARG5);
2885 PRE_REG_READ5(long, SC3("semsys", "semctl", "stat"), int, opcode,
2886 int, semid, int, semnum, int, cmd,
2887 struct vki_semid_ds *, arg);
2888 break;
2889 case VKI_IPC_SET:
2890 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
2891 SARG1, SARG2, SARG3, SARG4, ARG5);
2892 PRE_REG_READ5(long, SC3("semsys", "semctl", "set"), int, opcode,
2893 int, semid, int, semnum, int, cmd,
2894 struct vki_semid_ds *, arg);
2895 break;
2896 case VKI_IPC_STAT64:
2897 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
2898 SARG1, SARG2, SARG3, SARG4, ARG5);
2899 PRE_REG_READ5(long, SC3("semsys", "semctl", "stat64"), int, opcode,
2900 int, semid, int, semnum, int, cmd,
2901 struct vki_semid64_ds *, arg);
2902 break;
2903 case VKI_IPC_SET64:
2904 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
2905 SARG1, SARG2, SARG3, SARG4, ARG5);
2906 PRE_REG_READ5(long, SC3("semsys", "semctl", "set64"), int, opcode,
2907 int, semid, int, semnum, int, cmd,
2908 struct vki_semid64_ds *, arg);
2909 break;
2910 case VKI_IPC_RMID:
2911 PRINT("sys_semsys ( %ld, %ld, %ld )", SARG1, SARG3, SARG4);
2912 PRE_REG_READ3(long, SC3("semsys", "semctl", "rmid"), int, opcode,
2913 int, semid, int, cmd);
2914 break;
2915 case VKI_GETALL:
2916 PRINT("sys_semsys ( %ld, %ld, %ld, %#lx )",
2917 SARG1, SARG2, SARG4, ARG5);
2918 PRE_REG_READ4(long, SC3("semsys", "semctl", "getall"), int, opcode,
2919 int, semid, int, cmd, ushort_t *, arg);
2920 break;
2921 case VKI_SETALL:
2922 PRINT("sys_semsys ( %ld, %ld, %ld, %#lx )",
2923 SARG1, SARG2, SARG4, ARG5);
2924 PRE_REG_READ4(long, SC3("semsys", "semctl", "setall"), int, opcode,
2925 int, semid, int, cmd, ushort_t *, arg);
2926 break;
2927 case VKI_GETVAL:
2928 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
2929 SARG1, SARG2, SARG3, SARG4);
2930 PRE_REG_READ4(long, SC3("semsys", "semctl", "getval"), int, opcode,
2931 int, semid, int, semnum, int, cmd);
2932 break;
2933 case VKI_SETVAL:
2934 PRINT("sys_semsys ( %ld, %ld, %ld, %ld, %#lx )",
2935 SARG1, SARG2, SARG3, SARG4, ARG5);
2936 PRE_REG_READ5(long, SC3("semsys", "semctl", "setval"), int, opcode,
2937 int, semid, int, semnum, int, cmd,
2938 union vki_semun *, arg);
2939 break;
2940 case VKI_GETPID:
2941 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
2942 SARG1, SARG2, SARG3, SARG4);
2943 PRE_REG_READ4(long, SC3("semsys", "semctl", "getpid"), int, opcode,
2944 int, semid, int, semnum, int, cmd);
2945 break;
2946 case VKI_GETNCNT:
2947 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
2948 SARG1, SARG2, SARG3, SARG4);
2949 PRE_REG_READ4(long, SC3("semsys", "semctl", "getncnt"),
2950 int, opcode, int, semid, int, semnum, int, cmd);
2951 break;
2952 case VKI_GETZCNT:
2953 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )",
2954 SARG1, SARG2, SARG3, SARG4);
2955 PRE_REG_READ4(long, SC3("semsys", "semctl", "getzcnt"),
2956 int, opcode, int, semid, int, semnum, int, cmd);
2957 break;
2958 default:
2959 VG_(unimplemented)("Syswrap of the semsys(semctl) call "
2960 "with cmd %ld.", SARG4);
2961 /*NOTREACHED*/
2962 break;
2964 ML_(generic_PRE_sys_semctl)(tid, ARG2, ARG3, ARG4, ARG5);
2965 break;
2966 case VKI_SEMGET:
2967 /* Libc: int semget(key_t key, int nsems, int semflg); */
2968 PRINT("sys_semsys ( %ld, %ld, %ld, %ld )", SARG1, SARG2, SARG3, SARG4);
2969 PRE_REG_READ4(long, SC2("semsys", "semget"), int, opcode,
2970 vki_key_t, key, int, nsems, int, semflg);
2971 break;
2972 case VKI_SEMOP:
2973 /* Libc: int semop(int semid, struct sembuf *sops, size_t nsops); */
2974 PRINT("sys_semsys ( %ld, %ld, %#lx, %lu )", SARG1, SARG2, ARG3, ARG4);
2975 PRE_REG_READ4(long, SC2("semsys", "semop"), int, opcode, int, semid,
2976 struct vki_sembuf *, sops, vki_size_t, nsops);
2977 ML_(generic_PRE_sys_semop)(tid, ARG2, ARG3, ARG4);
2978 break;
2979 case VKI_SEMIDS:
2980 /* Libc: int semids(int *buf, uint_t nids, uint_t *pnids); */
2981 PRINT("sys_semsys ( %ld, %#lx, %lu, %#lx )", SARG1, ARG2, ARG3, ARG4);
2982 PRE_REG_READ4(long, SC2("semsys", "semids"), int, opcode, int *, buf,
2983 vki_uint_t, nids, vki_uint_t *, pnids);
2985 PRE_MEM_WRITE("semsys(semids, buf)", ARG2, ARG3 * sizeof(int *));
2986 PRE_MEM_WRITE("semsys(semids, pnids)", ARG4, sizeof(vki_uint_t));
2987 break;
2988 case VKI_SEMTIMEDOP:
2989 /* Libc: int semtimedop(int semid, struct sembuf *sops, size_t nsops,
2990 const struct timespec *timeout);
2992 PRINT("sys_semsys ( %ld, %ld, %#lx, %lu, %#lx )", SARG1, SARG2, ARG3,
2993 ARG4, ARG5);
2994 PRE_REG_READ5(long, SC2("semsys", "semtimedop"), int, opcode,
2995 int, semid, struct vki_sembuf *, sops, vki_size_t, nsops,
2996 struct vki_timespec *, timeout);
2997 ML_(generic_PRE_sys_semtimedop)(tid, ARG2, ARG3, ARG4, ARG5);
2998 break;
2999 default:
3000 VG_(unimplemented)("Syswrap of the semsys call with opcode %ld.", SARG1);
3001 /*NOTREACHED*/
3002 break;
3006 POST(sys_semsys)
3008 switch (ARG1 /*opcode*/) {
3009 case VKI_SEMCTL:
3010 ML_(generic_POST_sys_semctl)(tid, RES, ARG2, ARG3, ARG4, ARG5);
3011 break;
3012 case VKI_SEMGET:
3013 case VKI_SEMOP:
3014 break;
3015 case VKI_SEMIDS:
3017 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
3019 uint_t *pnids = (uint_t *)ARG4;
3020 if (*pnids <= ARG3)
3021 POST_MEM_WRITE(ARG2, *pnids * sizeof(int *));
3023 break;
3024 case VKI_SEMTIMEDOP:
3025 break;
3026 default:
3027 vg_assert(0);
3028 break;
3032 /* ---------------------------------------------------------------------
3033 ioctl wrappers
3034 ------------------------------------------------------------------ */
3036 PRE(sys_ioctl)
3038 /* int ioctl(int fildes, int request, ...); */
3039 *flags |= SfMayBlock;
3041 /* Prevent sign extending the switch case values to 64-bits on 64-bits
3042 architectures. */
3043 Int cmd = (Int) ARG2;
3045 switch (cmd /*request*/) {
3046 /* Handle 2-arg specially here (they do not use ARG3 at all). */
3047 case VKI_DINFOIDENT:
3048 case VKI_TIOCNOTTY:
3049 case VKI_TIOCSCTTY:
3050 PRINT("sys_ioctl ( %ld, %#lx )", SARG1, ARG2);
3051 PRE_REG_READ2(long, "ioctl", int, fd, int, request);
3052 break;
3053 /* And now come the 3-arg ones. */
3054 default:
3055 PRINT("sys_ioctl ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3056 PRE_REG_READ3(long, "ioctl", int, fd, int, request, intptr_t, arg);
3057 break;
3060 switch (cmd /*request*/) {
3061 /* pools */
3062 case VKI_POOL_STATUSQ:
3063 PRE_MEM_WRITE("ioctl(POOL_STATUSQ)", ARG3, sizeof(vki_pool_status_t));
3064 break;
3066 /* mntio */
3067 case VKI_MNTIOC_GETEXTMNTENT:
3069 PRE_MEM_READ("ioctl(MNTIOC_GETEXTMNTENT)",
3070 ARG3, sizeof(struct vki_mntentbuf));
3072 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3073 if (ML_(safe_to_deref(embuf, sizeof(*embuf)))) {
3074 PRE_MEM_WRITE("ioctl(MNTIOC_GETEXTMNTENT, embuf->mbuf_emp)",
3075 (Addr) embuf->mbuf_emp, sizeof(struct vki_extmnttab));
3076 PRE_MEM_WRITE("ioctl(MNTIOC_GETEXTMNTENT, embuf->mbuf_buf)",
3077 (Addr) embuf->mbuf_buf, embuf->mbuf_bufsize);
3080 break;
3082 case VKI_MNTIOC_GETMNTANY:
3084 PRE_MEM_READ("ioctl(MNTIOC_GETMNTANY)",
3085 ARG3, sizeof(struct vki_mntentbuf));
3087 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3088 if (ML_(safe_to_deref(embuf, sizeof(*embuf)))) {
3089 PRE_MEM_READ("ioctl(MNTIOC_GETMNTANY, embuf->mbuf_emp)",
3090 (Addr) embuf->mbuf_emp, sizeof(struct vki_mnttab));
3091 PRE_MEM_WRITE("ioctl(MNTIOC_GETMNTANY, embuf->mbuf_buf)",
3092 (Addr) embuf->mbuf_buf, embuf->mbuf_bufsize);
3094 struct vki_mnttab *mnt = (struct vki_mnttab *) embuf->mbuf_emp;
3095 if (ML_(safe_to_deref(mnt, sizeof(struct vki_mnttab)))) {
3096 if (mnt->mnt_special != NULL)
3097 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_special)",
3098 (Addr) mnt->mnt_special);
3099 if (mnt->mnt_mountp != NULL)
3100 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_mountp)",
3101 (Addr) mnt->mnt_mountp);
3102 if (mnt->mnt_fstype != NULL)
3103 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_fstype)",
3104 (Addr) mnt->mnt_fstype);
3105 if (mnt->mnt_mntopts != NULL)
3106 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_mntopts)",
3107 (Addr) mnt->mnt_mntopts);
3108 if (mnt->mnt_time != NULL)
3109 PRE_MEM_RASCIIZ("ioctl(MNTIOC_GETMNTANY, mnt->mnt_time)",
3110 (Addr) mnt->mnt_time);
3114 break;
3116 /* termio/termios */
3117 case VKI_TCGETA:
3118 PRE_MEM_WRITE("ioctl(TCGETA)", ARG3, sizeof(struct vki_termio));
3119 break;
3120 case VKI_TCGETS:
3121 PRE_MEM_WRITE("ioctl(TCGETS)", ARG3, sizeof(struct vki_termios));
3122 break;
3123 case VKI_TCSETS:
3124 PRE_MEM_READ("ioctl(TCSETS)", ARG3, sizeof(struct vki_termios));
3125 break;
3126 case VKI_TCSETSW:
3127 PRE_MEM_READ("ioctl(TCSETSW)", ARG3, sizeof(struct vki_termios));
3128 break;
3129 case VKI_TCSETSF:
3130 PRE_MEM_READ("ioctl(TCSETSF)", ARG3, sizeof(struct vki_termios));
3131 break;
3132 case VKI_TIOCGWINSZ:
3133 PRE_MEM_WRITE("ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize));
3134 break;
3135 case VKI_TIOCSWINSZ:
3136 PRE_MEM_READ("ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize));
3137 break;
3138 case VKI_TIOCGPGRP:
3139 PRE_MEM_WRITE("ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t));
3140 break;
3141 case VKI_TIOCSPGRP:
3142 PRE_MEM_READ("ioctl(TIOCSPGRP)", ARG3, sizeof(vki_pid_t));
3143 break;
3144 case VKI_TIOCGSID:
3145 PRE_MEM_WRITE("ioctl(TIOCGSID)", ARG3, sizeof(vki_pid_t));
3146 break;
3147 case VKI_TIOCNOTTY:
3148 case VKI_TIOCSCTTY:
3149 break;
3151 /* STREAMS */
3152 case VKI_I_PUSH:
3153 PRE_MEM_RASCIIZ("ioctl(I_PUSH)", ARG3);
3154 break;
3155 case VKI_I_FLUSH:
3156 break;
3157 case VKI_I_STR:
3159 PRE_MEM_READ("ioctl(I_STR)", ARG3, sizeof(struct vki_strioctl));
3161 struct vki_strioctl *p = (struct vki_strioctl *) ARG3;
3162 if (ML_(safe_to_deref(p, sizeof(*p)))) {
3163 if ((p->ic_dp != NULL) && (p->ic_len > 0)) {
3164 PRE_MEM_READ("ioctl(I_STR, strioctl->ic_dp)",
3165 (Addr) p->ic_dp, p->ic_len);
3169 break;
3170 case VKI_I_FIND:
3171 PRE_MEM_RASCIIZ("ioctl(I_FIND)", ARG3);
3172 break;
3173 case VKI_I_PEEK:
3175 /* Try hard not to mark strpeek->*buf.len members as being read. */
3176 struct vki_strpeek *p = (struct vki_strpeek*)ARG3;
3178 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->ctlbuf.maxlen)",
3179 p->ctlbuf.maxlen);
3180 PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->ctlbuf.len)",
3181 p->ctlbuf.len);
3182 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->ctlbuf.buf)",
3183 p->ctlbuf.buf);
3184 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->databuf.maxlen)",
3185 p->databuf.maxlen);
3186 PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->databuf.len)",
3187 p->databuf.len);
3188 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->databuf.buf)",
3189 p->databuf.buf);
3190 PRE_FIELD_READ("ioctl(I_PEEK, strpeek->flags)", p->flags);
3191 /*PRE_FIELD_WRITE("ioctl(I_PEEK, strpeek->flags)", p->flags);*/
3193 if (ML_(safe_to_deref(p, sizeof(*p)))) {
3194 if (p->ctlbuf.buf && p->ctlbuf.maxlen > 0)
3195 PRE_MEM_WRITE("ioctl(I_PEEK, strpeek->ctlbuf.buf)",
3196 (Addr)p->ctlbuf.buf, p->ctlbuf.maxlen);
3197 if (p->databuf.buf && p->databuf.maxlen > 0)
3198 PRE_MEM_WRITE("ioctl(I_PEEK, strpeek->databuf.buf)",
3199 (Addr)p->databuf.buf, p->databuf.maxlen);
3202 break;
3203 case VKI_I_CANPUT:
3204 break;
3206 /* sockio */
3207 case VKI_SIOCGIFCONF:
3209 struct vki_ifconf *p = (struct vki_ifconf *) ARG3;
3210 PRE_FIELD_READ("ioctl(SIOCGIFCONF, ifconf->ifc_len)", p->ifc_len);
3211 PRE_FIELD_READ("ioctl(SIOCGIFCONF, ifconf->ifc_buf)", p->ifc_buf);
3212 if (ML_(safe_to_deref)(p, sizeof(*p))) {
3213 if ((p->ifc_buf != NULL) && (p->ifc_len > 0))
3214 PRE_MEM_WRITE("ioctl(SIOCGIFCONF, ifconf->ifc_buf)",
3215 (Addr) p->ifc_buf, p->ifc_len);
3217 /* ifc_len gets also written to during SIOCGIFCONF ioctl. */
3219 break;
3220 case VKI_SIOCGIFFLAGS:
3222 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3223 PRE_FIELD_READ("ioctl(SIOCGIFFLAGS, ifreq->ifr_name)", p->ifr_name);
3224 PRE_FIELD_WRITE("ioctl(SIOCGIFFLAGS, ifreq->ifr_flags)", p->ifr_flags);
3226 break;
3227 case VKI_SIOCGIFNETMASK:
3229 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3230 PRE_FIELD_READ("ioctl(SIOCGIFFLAGS, ifreq->ifr_name)", p->ifr_name);
3231 PRE_FIELD_WRITE("ioctl(SIOCGIFFLAGS, ifreq->ifr_addr)", p->ifr_addr);
3233 break;
3234 case VKI_SIOCGIFNUM:
3235 PRE_MEM_WRITE("ioctl(SIOCGIFNUM)", ARG3, sizeof(int));
3236 break;
3237 case VKI_SIOCGLIFBRDADDR:
3239 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3240 PRE_FIELD_READ("ioctl(SIOCGLIFBRDADDR, lifreq->lifr_name)",
3241 p->lifr_name);
3242 PRE_FIELD_WRITE("ioctl(SIOCGLIFBRDADDR, lifreq->lifr_addr)",
3243 p->lifr_addr);
3245 break;
3246 case VKI_SIOCGLIFCONF:
3248 struct vki_lifconf *p = (struct vki_lifconf *) ARG3;
3249 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_len)", p->lifc_len);
3250 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_buf)", p->lifc_buf);
3251 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_family)",
3252 p->lifc_family);
3253 PRE_FIELD_READ("ioctl(SIOCGLIFCONF, lifconf->lifc_flags)",
3254 p->lifc_flags);
3255 if (ML_(safe_to_deref)(p, sizeof(*p))) {
3256 if ((p->lifc_buf != NULL) && (p->lifc_len > 0))
3257 PRE_MEM_WRITE("ioctl(SIOCGLIFCONF, lifconf->lifc_buf)",
3258 (Addr) p->lifc_buf, p->lifc_len);
3260 /* lifc_len gets also written to during SIOCGLIFCONF ioctl. */
3262 break;
3263 case VKI_SIOCGLIFFLAGS:
3265 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3266 PRE_FIELD_READ("ioctl(SIOCGLIFFLAGS, lifreq->lifr_name)",
3267 p->lifr_name);
3268 PRE_FIELD_WRITE("ioctl(SIOCGLIFFLAGS, lifreq->lifr_flags)",
3269 p->lifr_flags);
3271 break;
3272 case VKI_SIOCGLIFNETMASK:
3274 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3275 PRE_FIELD_READ("ioctl(SIOCGLIFNETMASK, lifreq->lifr_name)",
3276 p->lifr_name);
3277 PRE_FIELD_WRITE("ioctl(SIOCGLIFNETMASK, lifreq->lifr_addr)",
3278 p->lifr_addr);
3280 break;
3281 case VKI_SIOCGLIFNUM:
3283 struct vki_lifnum *p = (struct vki_lifnum *) ARG3;
3284 PRE_FIELD_READ("ioctl(SIOCGLIFNUM, lifn->lifn_family)",
3285 p->lifn_family);
3286 PRE_FIELD_READ("ioctl(SIOCGLIFNUM, lifn->lifn_flags)",
3287 p->lifn_flags);
3288 PRE_FIELD_WRITE("ioctl(SIOCGLIFNUM, lifn->lifn_count)",
3289 p->lifn_count);
3291 break;
3293 /* filio */
3294 case VKI_FIOSETOWN:
3295 PRE_MEM_READ("ioctl(FIOSETOWN)", ARG3, sizeof(vki_pid_t));
3296 break;
3297 case VKI_FIOGETOWN:
3298 PRE_MEM_WRITE("ioctl(FIOGETOWN)", ARG3, sizeof(vki_pid_t));
3299 break;
3301 /* CRYPTO */
3302 case VKI_CRYPTO_GET_PROVIDER_LIST:
3304 vki_crypto_get_provider_list_t *pl =
3305 (vki_crypto_get_provider_list_t *) ARG3;
3306 PRE_FIELD_READ("ioctl(CRYPTO_GET_PROVIDER_LIST, pl->pl_count)",
3307 pl->pl_count);
3309 if (ML_(safe_to_deref)(pl, sizeof(*pl))) {
3310 PRE_MEM_WRITE("ioctl(CRYPTO_GET_PROVIDER_LIST)", ARG3,
3311 MAX(1, pl->pl_count) *
3312 sizeof(vki_crypto_get_provider_list_t));
3314 /* Save the requested count to unused ARG4 below,
3315 when we know pre-handler succeeded.
3318 break;
3320 /* dtrace */
3321 case VKI_DTRACEHIOC_REMOVE:
3322 break;
3323 case VKI_DTRACEHIOC_ADDDOF:
3325 vki_dof_helper_t *dh = (vki_dof_helper_t *) ARG3;
3326 PRE_MEM_RASCIIZ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_mod)",
3327 (Addr) dh->dofhp_mod);
3328 PRE_FIELD_READ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_addr",
3329 dh->dofhp_addr);
3330 PRE_FIELD_READ("ioctl(DTRACEHIOC_ADDDOF, dh->dofhp_dof",
3331 dh->dofhp_dof);
3333 break;
3335 /* devinfo */
3336 case VKI_DINFOUSRLD:
3337 /* We should do PRE_MEM_WRITE here but the question is for how many? */
3338 break;
3339 case VKI_DINFOIDENT:
3340 break;
3342 default:
3343 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3344 break;
3347 /* Be strict. */
3348 if (!ML_(fd_allowed)(ARG1, "ioctl", tid, False)) {
3349 SET_STATUS_Failure(VKI_EBADF);
3350 } else if (ARG2 == VKI_CRYPTO_GET_PROVIDER_LIST) {
3351 /* Save the requested count to unused ARG4 now. */
3352 ARG4 = ARG3;
3356 POST(sys_ioctl)
3358 /* Prevent sign extending the switch case values to 64-bits on 64-bits
3359 architectures. */
3360 Int cmd = (Int) ARG2;
3362 switch (cmd /*request*/) {
3363 /* pools */
3364 case VKI_POOL_STATUSQ:
3365 POST_MEM_WRITE(ARG3, sizeof(vki_pool_status_t));
3366 break;
3368 /* mntio */
3369 case VKI_MNTIOC_GETEXTMNTENT:
3371 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3372 struct vki_extmnttab *mnt = (struct vki_extmnttab *) embuf->mbuf_emp;
3374 POST_MEM_WRITE((Addr) mnt, sizeof(struct vki_extmnttab));
3375 if (mnt != NULL) {
3376 if (mnt->mnt_special != NULL)
3377 POST_MEM_WRITE((Addr) mnt->mnt_special,
3378 VG_(strlen)(mnt->mnt_special) + 1);
3379 if (mnt->mnt_mountp != NULL)
3380 POST_MEM_WRITE((Addr) mnt->mnt_mountp,
3381 VG_(strlen)(mnt->mnt_mountp) + 1);
3382 if (mnt->mnt_fstype != NULL)
3383 POST_MEM_WRITE((Addr) mnt->mnt_fstype,
3384 VG_(strlen)(mnt->mnt_fstype) + 1);
3385 if (mnt->mnt_mntopts != NULL)
3386 POST_MEM_WRITE((Addr) mnt->mnt_mntopts,
3387 VG_(strlen)(mnt->mnt_mntopts) + 1);
3388 if (mnt->mnt_time != NULL)
3389 POST_MEM_WRITE((Addr) mnt->mnt_time,
3390 VG_(strlen)(mnt->mnt_time) + 1);
3393 break;
3395 case VKI_MNTIOC_GETMNTANY:
3397 struct vki_mntentbuf *embuf = (struct vki_mntentbuf *) ARG3;
3398 struct vki_mnttab *mnt = (struct vki_mnttab *) embuf->mbuf_emp;
3400 POST_MEM_WRITE((Addr) mnt, sizeof(struct vki_mnttab));
3401 if (mnt != NULL) {
3402 if (mnt->mnt_special != NULL)
3403 POST_MEM_WRITE((Addr) mnt->mnt_special,
3404 VG_(strlen)(mnt->mnt_special) + 1);
3405 if (mnt->mnt_mountp != NULL)
3406 POST_MEM_WRITE((Addr) mnt->mnt_mountp,
3407 VG_(strlen)(mnt->mnt_mountp) + 1);
3408 if (mnt->mnt_fstype != NULL)
3409 POST_MEM_WRITE((Addr) mnt->mnt_fstype,
3410 VG_(strlen)(mnt->mnt_fstype) + 1);
3411 if (mnt->mnt_mntopts != NULL)
3412 POST_MEM_WRITE((Addr) mnt->mnt_mntopts,
3413 VG_(strlen)(mnt->mnt_mntopts) + 1);
3414 if (mnt->mnt_time != NULL)
3415 POST_MEM_WRITE((Addr) mnt->mnt_time,
3416 VG_(strlen)(mnt->mnt_time) + 1);
3419 break;
3421 /* termio/termios */
3422 case VKI_TCGETA:
3423 POST_MEM_WRITE(ARG3, sizeof(struct vki_termio));
3424 break;
3425 case VKI_TCGETS:
3426 POST_MEM_WRITE(ARG3, sizeof(struct vki_termios));
3427 break;
3428 case VKI_TCSETS:
3429 break;
3430 case VKI_TCSETSW:
3431 break;
3432 case VKI_TCSETSF:
3433 break;
3434 case VKI_TIOCGWINSZ:
3435 POST_MEM_WRITE(ARG3, sizeof(struct vki_winsize));
3436 break;
3437 case VKI_TIOCSWINSZ:
3438 break;
3439 case VKI_TIOCGPGRP:
3440 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3441 break;
3442 case VKI_TIOCSPGRP:
3443 break;
3444 case VKI_TIOCGSID:
3445 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3446 break;
3447 case VKI_TIOCNOTTY:
3448 case VKI_TIOCSCTTY:
3449 break;
3451 /* STREAMS */
3452 case VKI_I_PUSH:
3453 break;
3454 case VKI_I_FLUSH:
3455 break;
3456 case VKI_I_STR:
3458 struct vki_strioctl *p = (struct vki_strioctl *) ARG3;
3460 POST_FIELD_WRITE(p->ic_len);
3461 if ((p->ic_dp != NULL) && (p->ic_len > 0))
3462 POST_MEM_WRITE((Addr) p->ic_dp, p->ic_len);
3464 break;
3465 case VKI_I_FIND:
3466 break;
3467 case VKI_I_PEEK:
3469 struct vki_strpeek *p = (struct vki_strpeek*)ARG3;
3471 POST_FIELD_WRITE(p->ctlbuf.len);
3472 POST_FIELD_WRITE(p->databuf.len);
3473 POST_FIELD_WRITE(p->flags);
3475 if (p->ctlbuf.buf && p->ctlbuf.len > 0)
3476 POST_MEM_WRITE((Addr)p->ctlbuf.buf, p->ctlbuf.len);
3477 if (p->databuf.buf && p->databuf.len > 0)
3478 POST_MEM_WRITE((Addr)p->databuf.buf, p->databuf.len);
3480 break;
3481 case VKI_I_CANPUT:
3482 break;
3484 /* sockio */
3485 case VKI_SIOCGIFCONF:
3487 struct vki_ifconf *p = (struct vki_ifconf *) ARG3;
3488 POST_FIELD_WRITE(p->ifc_len);
3489 POST_FIELD_WRITE(p->ifc_req);
3490 if ((p->ifc_req != NULL) && (p->ifc_len > 0))
3491 POST_MEM_WRITE((Addr) p->ifc_req, p->ifc_len);
3493 break;
3494 case VKI_SIOCGIFFLAGS:
3496 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3497 POST_FIELD_WRITE(p->ifr_flags);
3499 break;
3500 case VKI_SIOCGIFNETMASK:
3502 struct vki_ifreq *p = (struct vki_ifreq *) ARG3;
3503 POST_FIELD_WRITE(p->ifr_addr);
3505 break;
3506 case VKI_SIOCGIFNUM:
3507 POST_MEM_WRITE(ARG3, sizeof(int));
3508 break;
3509 case VKI_SIOCGLIFBRDADDR:
3511 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3512 POST_FIELD_WRITE(p->lifr_addr);
3514 break;
3515 case VKI_SIOCGLIFCONF:
3517 struct vki_lifconf *p = (struct vki_lifconf *) ARG3;
3518 POST_FIELD_WRITE(p->lifc_len);
3519 POST_FIELD_WRITE(p->lifc_req);
3520 if ((p->lifc_req != NULL) && (p->lifc_len > 0))
3521 POST_MEM_WRITE((Addr) p->lifc_req, p->lifc_len);
3523 break;
3524 case VKI_SIOCGLIFFLAGS:
3526 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3527 POST_FIELD_WRITE(p->lifr_flags);
3529 break;
3530 case VKI_SIOCGLIFNETMASK:
3532 struct vki_lifreq *p = (struct vki_lifreq *) ARG3;
3533 POST_FIELD_WRITE(p->lifr_addr);
3535 break;
3536 case VKI_SIOCGLIFNUM:
3538 struct vki_lifnum *p = (struct vki_lifnum *) ARG3;
3539 POST_FIELD_WRITE(p->lifn_count);
3541 break;
3543 /* filio */
3544 case VKI_FIOSETOWN:
3545 break;
3546 case VKI_FIOGETOWN:
3547 POST_MEM_WRITE(ARG3, sizeof(vki_pid_t));
3548 break;
3550 /* CRYPTO */
3551 case VKI_CRYPTO_GET_PROVIDER_LIST:
3553 vki_crypto_get_provider_list_t *pl =
3554 (vki_crypto_get_provider_list_t *) ARG3;
3556 POST_FIELD_WRITE(pl->pl_count);
3557 POST_FIELD_WRITE(pl->pl_return_value);
3559 if ((ARG4 > 0) && (pl->pl_return_value == VKI_CRYPTO_SUCCESS))
3560 POST_MEM_WRITE((Addr) pl->pl_list, pl->pl_count *
3561 sizeof(vki_crypto_provider_entry_t));
3563 break;
3565 /* dtrace */
3566 case VKI_DTRACEHIOC_REMOVE:
3567 case VKI_DTRACEHIOC_ADDDOF:
3568 break;
3570 /* devinfo */
3571 case VKI_DINFOUSRLD:
3572 POST_MEM_WRITE(ARG3, RES);
3573 break;
3574 case VKI_DINFOIDENT:
3575 break;
3577 default:
3578 /* Not really anything to do since ioctl direction hints are hardly used
3579 on Solaris. */
3580 break;
3584 PRE(sys_fchownat)
3586 /* int fchownat(int fd, const char *path, uid_t owner, gid_t group,
3587 int flag); */
3589 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
3590 This is different from Linux, for example, where glibc sign-extends it. */
3591 Int fd = (Int) ARG1;
3593 PRINT("sys_fchownat ( %d, %#lx(%s), %ld, %ld, %lu )", fd,
3594 ARG2, (HChar *) ARG2, SARG3, SARG4, ARG5);
3595 PRE_REG_READ5(long, "fchownat", int, fd, const char *, path,
3596 vki_uid_t, owner, vki_gid_t, group, int, flag);
3598 if (ARG2)
3599 PRE_MEM_RASCIIZ("fchownat(path)", ARG2);
3601 /* Be strict but ignore fd for absolute path. */
3602 if (fd != VKI_AT_FDCWD
3603 && ML_(safe_to_deref)((void *) ARG2, 1)
3604 && ((HChar *) ARG2)[0] != '/'
3605 && !ML_(fd_allowed)(fd, "fchownat", tid, False))
3606 SET_STATUS_Failure(VKI_EBADF);
3609 PRE(sys_fdsync)
3611 /* int fdsync(int fd, int flag); */
3612 PRINT("sys_fdsync ( %ld, %ld )", SARG1, SARG2);
3613 PRE_REG_READ2(long, "fdsync", int, fd, int, flag);
3615 /* Be strict. */
3616 if (!ML_(fd_allowed)(ARG1, "fdsync", tid, False))
3617 SET_STATUS_Failure(VKI_EBADF);
3620 PRE(sys_execve)
3622 Int i, j;
3623 Addr arg_2_check;
3624 const char* str2 = "execve(argv)";
3625 const char* str3 = "execve(argv[0])";
3626 const char* str4 = "execve(argv[i])";
3627 /* This is a Solaris specific version of the generic pre-execve wrapper. */
3629 #if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3630 /* int execve(uintptr_t file, const char **argv, const char **envp,
3631 int flags); */
3632 PRINT("sys_execve ( %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3, SARG4);
3633 PRE_REG_READ4(long, "execve", uintptr_t, file, const char **, argv,
3634 const char **, envp, int, flags);
3636 #else
3638 /* int execve(const char *fname, const char **argv, const char **envp); */
3639 PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )",
3640 ARG1, (HChar *) ARG1, ARG2, ARG3);
3641 PRE_REG_READ3(long, "execve", const char *, file, const char **, argv,
3642 const char **, envp);
3643 #endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3645 Bool ARG1_is_fd = False;
3646 #if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3647 if (ARG4 & VKI_EXEC_DESCRIPTOR) {
3648 ARG1_is_fd = True;
3650 #endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3652 if (ARG1_is_fd == False)
3653 PRE_MEM_RASCIIZ("execve(filename)", ARG1);
3655 /* Erk. If the exec fails, then the following will have made a mess of
3656 things which makes it hard for us to continue. The right thing to do is
3657 piece everything together again in POST(execve), but that's close to
3658 impossible. Instead, we make an effort to check that the execve will
3659 work before actually doing it. */
3661 const HChar *fname = (const HChar *) ARG1;
3662 if (ARG1_is_fd) {
3663 if (!ML_(fd_allowed)(ARG1, "execve", tid, False)) {
3664 SET_STATUS_Failure(VKI_EBADF);
3665 return;
3668 if (VG_(resolve_filename)(ARG1, &fname) == False) {
3669 SET_STATUS_Failure(VKI_EBADF);
3670 return;
3673 struct vg_stat stats;
3674 if (VG_(fstat)(ARG1, &stats) != 0) {
3675 SET_STATUS_Failure(VKI_EBADF);
3676 return;
3679 if (stats.nlink > 1)
3680 VG_(unimplemented)("Syswrap of execve where fd points to a hardlink.");
3683 arg_2_check = (Addr)ARG2;
3685 /* argv[] should not be NULL and valid. */
3686 PRE_MEM_READ(str2, arg_2_check, sizeof(Addr));
3688 /* argv[0] should not be NULL and valid. */
3689 if (ML_(safe_to_deref)((HChar **) (Addr)arg_2_check, sizeof(HChar *))) {
3690 Addr argv0 = *(Addr*)arg_2_check;
3691 PRE_MEM_RASCIIZ( str3, argv0 );
3692 /* The rest of argv can be NULL or a valid string pointer. */
3693 if (VG_(am_is_valid_for_client)(arg_2_check, sizeof(HChar), VKI_PROT_READ)) {
3694 arg_2_check += sizeof(HChar*);
3695 ML_(pre_argv_envp)( arg_2_check, tid, str2, str4 );
3697 } else {
3698 SET_STATUS_Failure(VKI_EFAULT);
3699 return;
3702 if (ARG3 != 0) {
3703 /* At least the terminating NULL must be addressable. */
3704 if (!ML_(safe_to_deref)((HChar **) (Addr)ARG3, sizeof(HChar *))) {
3705 SET_STATUS_Failure(VKI_EFAULT);
3706 return;
3708 ML_(pre_argv_envp)( ARG3, tid, "execve(envp)", "execve(envp[i])" );
3711 /* Check that the name at least begins in client-accessible storage. */
3712 if (ARG1_is_fd == False) {
3713 if ((fname == NULL) || !ML_(safe_to_deref)(fname, 1)) {
3714 SET_STATUS_Failure(VKI_EFAULT);
3715 return;
3719 /* Check that the args at least begin in client-accessible storage.
3720 Solaris disallows to perform the exec without any arguments specified.
3722 if (!ARG2 /* obviously bogus */ ||
3723 !VG_(am_is_valid_for_client)(ARG2, 1, VKI_PROT_READ)) {
3724 SET_STATUS_Failure(VKI_EFAULT);
3725 return;
3728 /* Debug-only printing. */
3729 if (0) {
3730 VG_(printf)("ARG1 = %#lx(%s)\n", ARG1, fname);
3731 if (ARG2) {
3732 Int q;
3733 HChar** vec = (HChar**)ARG2;
3735 VG_(printf)("ARG2 = ");
3736 for (q = 0; vec[q]; q++)
3737 VG_(printf)("%p(%s) ", vec[q], vec[q]);
3738 VG_(printf)("\n");
3740 else
3741 VG_(printf)("ARG2 = null\n");
3744 /* Decide whether or not we want to follow along. */
3745 /* Make 'child_argv' be a pointer to the child's arg vector (skipping the
3746 exe name) */
3747 const HChar **child_argv = (const HChar **) ARG2;
3748 if (child_argv[0] == NULL)
3749 child_argv = NULL;
3750 Bool trace_this_child = VG_(should_we_trace_this_child)(fname, child_argv);
3752 /* Do the important checks: it is a file, is executable, permissions are
3753 ok, etc. We allow setuid executables to run only in the case when
3754 we are not simulating them, that is, they to be run natively. */
3755 Bool setuid_allowed = trace_this_child ? False : True;
3756 SysRes res = VG_(pre_exec_check)(fname, NULL, setuid_allowed);
3757 if (sr_isError(res)) {
3758 SET_STATUS_Failure(sr_Err(res));
3759 return;
3762 /* If we're tracing the child, and the launcher name looks bogus (possibly
3763 because launcher.c couldn't figure it out, see comments therein) then we
3764 have no option but to fail. */
3765 if (trace_this_child &&
3766 (!VG_(name_of_launcher) || VG_(name_of_launcher)[0] != '/')) {
3767 SET_STATUS_Failure(VKI_ECHILD); /* "No child processes." */
3768 return;
3771 /* After this point, we can't recover if the execve fails. */
3772 VG_(debugLog)(1, "syswrap", "Exec of %s\n", fname);
3774 /* Terminate gdbserver if it is active. */
3775 if (VG_(clo_vgdb) != Vg_VgdbNo) {
3776 /* If the child will not be traced, we need to terminate gdbserver to
3777 cleanup the gdbserver resources (e.g. the FIFO files). If child will
3778 be traced, we also terminate gdbserver: the new Valgrind will start a
3779 fresh gdbserver after exec. */
3780 VG_(gdbserver)(0);
3783 /* Resistance is futile. Nuke all other threads. POSIX mandates this.
3784 (Really, nuke them all, since the new process will make its own new
3785 thread.) */
3786 VG_(nuke_all_threads_except)(tid, VgSrc_ExitThread);
3787 VG_(reap_threads)(tid);
3789 /* Set up the child's exe path. */
3790 const HChar *path = fname;
3791 const HChar *launcher_basename = NULL;
3792 if (trace_this_child) {
3793 /* We want to exec the launcher. Get its pre-remembered path. */
3794 path = VG_(name_of_launcher);
3795 /* VG_(name_of_launcher) should have been acquired by m_main at
3796 startup. */
3797 vg_assert(path);
3799 launcher_basename = VG_(strrchr)(path, '/');
3800 if (!launcher_basename || launcher_basename[1] == '\0')
3801 launcher_basename = path; /* hmm, tres dubious */
3802 else
3803 launcher_basename++;
3806 /* Set up the child's environment.
3808 Remove the valgrind-specific stuff from the environment so the child
3809 doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. This is done
3810 unconditionally, since if we are tracing the child, the child valgrind
3811 will set up the appropriate client environment. Nb: we make a copy of
3812 the environment before trying to mangle it as it might be in read-only
3813 memory (bug #101881).
3815 Then, if tracing the child, set VALGRIND_LIB for it. */
3816 HChar **envp = NULL;
3817 if (ARG3 != 0) {
3818 envp = VG_(env_clone)((HChar**)ARG3);
3819 vg_assert(envp != NULL);
3820 VG_(env_remove_valgrind_env_stuff)(envp, True /*ro_strings*/, NULL);
3823 if (trace_this_child) {
3824 /* Set VALGRIND_LIB in ARG3 (the environment). */
3825 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3828 /* Set up the child's args. If not tracing it, they are simply ARG2.
3829 Otherwise, they are:
3831 [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..],
3833 except that the first VG_(args_for_valgrind_noexecpass) args are
3834 omitted. */
3835 HChar **argv = NULL;
3836 if (!trace_this_child)
3837 argv = (HChar **) ARG2;
3838 else {
3839 Int tot_args;
3841 vg_assert(VG_(args_for_valgrind));
3842 vg_assert(VG_(args_for_valgrind_noexecpass) >= 0);
3843 vg_assert(VG_(args_for_valgrind_noexecpass)
3844 <= VG_(sizeXA)(VG_(args_for_valgrind)));
3846 /* How many args in total will there be? */
3847 /* launcher basename */
3848 tot_args = 1;
3849 /* V's args */
3850 tot_args += VG_(sizeXA)(VG_(args_for_valgrind));
3851 tot_args -= VG_(args_for_valgrind_noexecpass);
3852 /* name of client exe */
3853 tot_args++;
3854 /* args for client exe, skipping [0] */
3855 HChar **arg2copy = (HChar **) ARG2;
3856 if (arg2copy[0] != NULL)
3857 for (i = 1; arg2copy[i]; i++)
3858 tot_args++;
3859 /* allocate */
3860 argv = VG_(malloc)("syswrap.exec.5", (tot_args + 1) * sizeof(HChar*));
3861 /* copy */
3862 j = 0;
3863 argv[j++] = CONST_CAST(HChar *, launcher_basename);
3864 for (i = 0; i < VG_(sizeXA)(VG_(args_for_valgrind)); i++) {
3865 if (i < VG_(args_for_valgrind_noexecpass))
3866 continue;
3867 argv[j++] = *(HChar**)VG_(indexXA)(VG_(args_for_valgrind), i);
3869 argv[j++] = CONST_CAST(HChar *, fname);
3870 if (arg2copy[0] != NULL)
3871 for (i = 1; arg2copy[i]; i++)
3872 argv[j++] = arg2copy[i];
3873 argv[j++] = NULL;
3874 /* check */
3875 vg_assert(j == tot_args + 1);
3878 /* Set the signal state up for exec.
3880 We need to set the real signal state to make sure the exec'd process
3881 gets SIG_IGN properly.
3883 Also set our real sigmask to match the client's sigmask so that the
3884 exec'd child will get the right mask. First we need to clear out any
3885 pending signals so they they don't get delivered, which would confuse
3886 things.
3888 XXX This is a bug - the signals should remain pending, and be delivered
3889 to the new process after exec. There's also a race-condition, since if
3890 someone delivers us a signal between the sigprocmask and the execve,
3891 we'll still get the signal. Oh well.
3894 vki_sigset_t allsigs;
3895 vki_siginfo_t info;
3897 /* What this loop does: it queries SCSS (the signal state that the
3898 client _thinks_ the kernel is in) by calling VG_(do_sys_sigaction),
3899 and modifies the real kernel signal state accordingly. */
3900 for (i = 1; i < VG_(max_signal); i++) {
3901 vki_sigaction_fromK_t sa_f;
3902 vki_sigaction_toK_t sa_t;
3903 VG_(do_sys_sigaction)(i, NULL, &sa_f);
3904 VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t);
3905 VG_(sigaction)(i, &sa_t, NULL);
3908 VG_(sigfillset)(&allsigs);
3909 while (VG_(sigtimedwait_zero)(&allsigs, &info) > 0)
3912 ThreadState *tst = VG_(get_ThreadState)(tid);
3913 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
3916 /* Debug-only printing. */
3917 if (0) {
3918 HChar **cpp;
3919 VG_(printf)("exec: %s\n", path);
3920 for (cpp = argv; cpp && *cpp; cpp++)
3921 VG_(printf)("argv: %s\n", *cpp);
3922 if (0)
3923 for (cpp = envp; cpp && *cpp; cpp++)
3924 VG_(printf)("env: %s\n", *cpp);
3927 #if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3928 res = VG_(do_syscall4)(__NR_execve, (UWord) path, (UWord) argv,
3929 (UWord) envp, ARG4 & ~VKI_EXEC_DESCRIPTOR);
3930 #else
3931 res = VG_(do_syscall3)(__NR_execve, (UWord) path, (UWord) argv,
3932 (UWord) envp);
3933 #endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3934 SET_STATUS_from_SysRes(res);
3936 /* If we got here, then the execve failed. We've already made way too much
3937 of a mess to continue, so we have to abort. */
3938 vg_assert(FAILURE);
3939 #if defined(SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS)
3940 if (ARG1_is_fd)
3941 VG_(message)(Vg_UserMsg, "execve(%ld, %#lx, %#lx, %lu) failed, "
3942 "errno %ld\n", SARG1, ARG2, ARG3, ARG4, ERR);
3943 else
3944 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx, %ld) failed, errno"
3945 " %lu\n", ARG1, (HChar *) ARG1, ARG2, ARG3, SARG4, ERR);
3946 #else
3947 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %lu\n",
3948 ARG1, (HChar *) ARG1, ARG2, ARG3, ERR);
3949 #endif /* SOLARIS_EXECVE_SYSCALL_TAKES_FLAGS */
3950 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
3951 "execve() failing, so I'm dying.\n");
3952 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
3953 "or work out how to recover.\n");
3954 VG_(exit)(101);
3955 /*NOTREACHED*/
3958 static void pre_mem_read_flock(ThreadId tid, struct vki_flock *lock)
3960 PRE_FIELD_READ("fcntl(lock->l_type)", lock->l_type);
3961 PRE_FIELD_READ("fcntl(lock->l_whence)", lock->l_whence);
3962 PRE_FIELD_READ("fcntl(lock->l_start)", lock->l_start);
3963 PRE_FIELD_READ("fcntl(lock->l_len)", lock->l_len);
3966 #if defined(VGP_x86_solaris)
3967 static void pre_mem_read_flock64(ThreadId tid, struct vki_flock64 *lock)
3969 PRE_FIELD_READ("fcntl(lock->l_type)", lock->l_type);
3970 PRE_FIELD_READ("fcntl(lock->l_whence)", lock->l_whence);
3971 PRE_FIELD_READ("fcntl(lock->l_start)", lock->l_start);
3972 PRE_FIELD_READ("fcntl(lock->l_len)", lock->l_len);
3974 #endif /* VGP_x86_solaris */
3976 PRE(sys_fcntl)
3978 /* int fcntl(int fildes, int cmd, ...); */
3980 switch (ARG2 /*cmd*/) {
3981 /* These ones ignore ARG3. */
3982 case VKI_F_GETFD:
3983 case VKI_F_GETFL:
3984 case VKI_F_GETXFL:
3985 PRINT("sys_fcntl ( %ld, %ld )", SARG1, SARG2);
3986 PRE_REG_READ2(long, "fcntl", int, fildes, int, cmd);
3987 break;
3989 /* These ones use ARG3 as "arg". */
3990 case VKI_F_DUPFD:
3991 case VKI_F_DUPFD_CLOEXEC:
3992 case VKI_F_SETFD:
3993 case VKI_F_SETFL:
3994 case VKI_F_DUP2FD:
3995 case VKI_F_BADFD:
3996 PRINT("sys_fcntl ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
3997 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd, int, arg);
3998 /* Check if a client program isn't going to poison any of V's output
3999 fds. */
4000 if (ARG2 == VKI_F_DUP2FD &&
4001 !ML_(fd_allowed)(ARG3, "fcntl(F_DUP2FD)", tid, False)) {
4002 SET_STATUS_Failure(VKI_EBADF);
4003 return;
4005 break;
4007 /* These ones use ARG3 as "native lock" (input only). */
4008 case VKI_F_SETLK:
4009 case VKI_F_SETLKW:
4010 case VKI_F_ALLOCSP:
4011 case VKI_F_FREESP:
4012 case VKI_F_SETLK_NBMAND:
4013 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4014 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4015 struct flock *, lock);
4016 pre_mem_read_flock(tid, (struct vki_flock*)ARG3);
4017 break;
4019 /* This one uses ARG3 as "native lock" (input&output). */
4020 case VKI_F_GETLK:
4021 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4022 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4023 struct flock *, lock);
4024 pre_mem_read_flock(tid, (struct vki_flock*)ARG3);
4025 PRE_MEM_WRITE("fcntl(lock)", ARG3, sizeof(struct vki_flock));
4026 break;
4028 #if defined(VGP_x86_solaris)
4029 /* These ones use ARG3 as "transitional 64b lock" (input only). */
4030 case VKI_F_SETLK64:
4031 case VKI_F_SETLKW64:
4032 case VKI_F_ALLOCSP64:
4033 case VKI_F_FREESP64:
4034 case VKI_F_SETLK64_NBMAND:
4035 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4036 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4037 struct flock64 *, lock);
4038 pre_mem_read_flock64(tid, (struct vki_flock64*)ARG3);
4039 break;
4041 /* This one uses ARG3 as "transitional 64b lock" (input&output). */
4042 case VKI_F_GETLK64:
4043 PRINT("sys_fcntl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4044 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4045 struct flock64 *, lock);
4046 pre_mem_read_flock64(tid, (struct vki_flock64*)ARG3);
4047 PRE_MEM_WRITE("fcntl(lock)", ARG3, sizeof(struct vki_flock64));
4048 break;
4049 #endif /* VGP_x86_solaris */
4051 /* These ones use ARG3 as "fshare". */
4052 case VKI_F_SHARE:
4053 case VKI_F_UNSHARE:
4054 case VKI_F_SHARE_NBMAND:
4055 PRINT("sys_fcntl[ARG3=='fshare'] ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4056 PRE_REG_READ3(long, "fcntl", int, fildes, int, cmd,
4057 struct fshare *, sh);
4058 PRE_MEM_READ("fcntl(fshare)", ARG3, sizeof(struct vki_fshare));
4059 break;
4061 default:
4062 VG_(unimplemented)("Syswrap of the fcntl call with cmd %ld.", SARG2);
4063 /*NOTREACHED*/
4064 break;
4067 if (ARG2 == VKI_F_SETLKW
4068 #if defined(VGP_x86_solaris)
4069 || ARG2 == VKI_F_SETLKW64
4070 #endif /* VGP_x86_solaris */
4072 *flags |= SfMayBlock;
4074 /* Be strict. */
4075 if (!ML_(fd_allowed)(ARG1, "fcntl", tid, False))
4076 SET_STATUS_Failure(VKI_EBADF);
4079 POST(sys_fcntl)
4081 switch (ARG2 /*cmd*/) {
4082 case VKI_F_DUPFD:
4083 if (!ML_(fd_allowed)(RES, "fcntl(F_DUPFD)", tid, True)) {
4084 VG_(close)(RES);
4085 SET_STATUS_Failure(VKI_EMFILE);
4086 } else if (VG_(clo_track_fds))
4087 ML_(record_fd_open_named)(tid, RES);
4088 break;
4090 case VKI_F_DUPFD_CLOEXEC:
4091 if (!ML_(fd_allowed)(RES, "fcntl(F_DUPFD_CLOEXEC)", tid, True)) {
4092 VG_(close)(RES);
4093 SET_STATUS_Failure(VKI_EMFILE);
4094 } else if (VG_(clo_track_fds))
4095 ML_(record_fd_open_named)(tid, RES);
4096 break;
4098 case VKI_F_DUP2FD:
4099 if (!ML_(fd_allowed)(RES, "fcntl(F_DUP2FD)", tid, True)) {
4100 VG_(close)(RES);
4101 SET_STATUS_Failure(VKI_EMFILE);
4102 } else if (VG_(clo_track_fds))
4103 ML_(record_fd_open_named)(tid, RES);
4104 break;
4106 /* This one uses ARG3 as "native lock" (input&output). */
4107 case VKI_F_GETLK:
4108 POST_MEM_WRITE(ARG3, sizeof(struct vki_flock));
4109 break;
4111 #if defined(VGP_x86_solaris)
4112 /* This one uses ARG3 as "transitional 64b lock" (input&output). */
4113 case VKI_F_GETLK64:
4114 POST_MEM_WRITE(ARG3, sizeof(struct vki_flock64));
4115 break;
4116 #endif /* VGP_x86_solaris */
4118 default:
4119 break;
4123 PRE(sys_renameat)
4125 /* int renameat(int fromfd, const char *old, int tofd, const char *new); */
4127 /* Interpret the first and third arguments as 32-bit values even on 64-bit
4128 architecture. This is different from Linux, for example, where glibc
4129 sign-extends them. */
4130 Int fromfd = (Int) ARG1;
4131 Int tofd = (Int) ARG3;
4133 *flags |= SfMayBlock;
4134 PRINT("sys_renameat ( %d, %#lx(%s), %d, %#lx(%s) )", fromfd,
4135 ARG2, (HChar *) ARG2, tofd, ARG4, (HChar *) ARG4);
4136 PRE_REG_READ4(long, "renameat", int, fromfd, const char *, old,
4137 int, tofd, const char *, new);
4139 PRE_MEM_RASCIIZ("renameat(old)", ARG2);
4140 PRE_MEM_RASCIIZ("renameat(new)", ARG4);
4142 /* Be strict but ignore fromfd/tofd for absolute old/new. */
4143 if (fromfd != VKI_AT_FDCWD
4144 && ML_(safe_to_deref)((void *) ARG2, 1)
4145 && ((HChar *) ARG2)[0] != '/'
4146 && !ML_(fd_allowed)(fromfd, "renameat", tid, False)) {
4147 SET_STATUS_Failure(VKI_EBADF);
4149 if (tofd != VKI_AT_FDCWD
4150 && ML_(safe_to_deref)((void *) ARG4, 1)
4151 && ((HChar *) ARG4)[0] != '/'
4152 && !ML_(fd_allowed)(tofd, "renameat", tid, False)) {
4153 SET_STATUS_Failure(VKI_EBADF);
4157 PRE(sys_unlinkat)
4159 /* int unlinkat(int dirfd, const char *pathname, int flags); */
4161 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4162 This is different from Linux, for example, where glibc sign-extends it. */
4163 Int dfd = (Int) ARG1;
4165 *flags |= SfMayBlock;
4166 PRINT("sys_unlinkat ( %d, %#lx(%s), %ld )", dfd, ARG2, (HChar *) ARG2,
4167 SARG3);
4168 PRE_REG_READ3(long, "unlinkat", int, dirfd, const char *, pathname,
4169 int, flags);
4170 PRE_MEM_RASCIIZ("unlinkat(pathname)", ARG2);
4172 /* Be strict but ignore dfd for absolute pathname. */
4173 if (dfd != VKI_AT_FDCWD
4174 && ML_(safe_to_deref)((void *) ARG2, 1)
4175 && ((HChar *) ARG2)[0] != '/'
4176 && !ML_(fd_allowed)(dfd, "unlinkat", tid, False))
4177 SET_STATUS_Failure(VKI_EBADF);
4180 PRE(sys_fstatat)
4182 /* int fstatat(int fildes, const char *path, struct stat *buf,
4183 int flag); */
4185 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4186 This is different from Linux, for example, where glibc sign-extends it. */
4187 Int fd = (Int) ARG1;
4189 PRINT("sys_fstatat ( %d, %#lx(%s), %#lx, %ld )", fd, ARG2,
4190 (HChar *) ARG2, ARG3, SARG4);
4191 PRE_REG_READ4(long, "fstatat", int, fildes, const char *, path,
4192 struct stat *, buf, int, flag);
4193 if (ARG2) {
4194 /* Only test ARG2 if it isn't NULL. The kernel treats the NULL-case as
4195 fstat(fildes, buf). */
4196 PRE_MEM_RASCIIZ("fstatat(path)", ARG2);
4198 PRE_MEM_WRITE("fstatat(buf)", ARG3, sizeof(struct vki_stat));
4200 /* Be strict but ignore fildes for absolute path. */
4201 if (fd != VKI_AT_FDCWD
4202 && ML_(safe_to_deref)((void *) ARG2, 1)
4203 && ((HChar *) ARG2)[0] != '/'
4204 && !ML_(fd_allowed)(fd, "fstatat", tid, False))
4205 SET_STATUS_Failure(VKI_EBADF);
4208 POST(sys_fstatat)
4210 POST_MEM_WRITE(ARG3, sizeof(struct vki_stat));
4213 PRE(sys_openat)
4215 /* int openat(int fildes, const char *filename, int flags);
4216 int openat(int fildes, const char *filename, int flags, mode_t mode); */
4218 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
4219 This is different from Linux, for example, where glibc sign-extends it. */
4220 Int fd = (Int) ARG1;
4222 if (ARG3 & VKI_O_CREAT) {
4223 /* 4-arg version */
4224 PRINT("sys_openat ( %d, %#lx(%s), %ld, %ld )", fd, ARG2, (HChar *) ARG2,
4225 SARG3, SARG4);
4226 PRE_REG_READ4(long, "openat", int, fildes, const char *, filename,
4227 int, flags, vki_mode_t, mode);
4229 else {
4230 /* 3-arg version */
4231 PRINT("sys_openat ( %d, %#lx(%s), %ld )", fd, ARG2, (HChar *) ARG2,
4232 SARG3);
4233 PRE_REG_READ3(long, "openat", int, fildes, const char *, filename,
4234 int, flags);
4237 PRE_MEM_RASCIIZ("openat(filename)", ARG2);
4239 /* Be strict but ignore fildes for absolute pathname. */
4240 if (fd != VKI_AT_FDCWD
4241 && ML_(safe_to_deref)((void *) ARG2, 1)
4242 && ((HChar *) ARG2)[0] != '/'
4243 && !ML_(fd_allowed)(fd, "openat", tid, False)) {
4244 SET_STATUS_Failure(VKI_EBADF);
4245 return;
4248 if (ML_(handle_auxv_open)(status, (const HChar *) ARG2, ARG3))
4249 return;
4251 if (handle_psinfo_open(status, True /*use_openat*/, (const HChar *) ARG2,
4252 fd, ARG3, ARG4))
4253 return;
4255 #if defined(SOLARIS_PROC_CMDLINE)
4256 if (handle_cmdline_open(status, (const HChar *) ARG2))
4257 return;
4258 #endif /* SOLARIS_PROC_CMDLINE */
4260 *flags |= SfMayBlock;
4263 POST(sys_openat)
4265 if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
4266 VG_(close)(RES);
4267 SET_STATUS_Failure(VKI_EMFILE);
4269 else if (VG_(clo_track_fds))
4270 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG2);
4273 PRE(sys_tasksys)
4275 /* Kernel: long tasksys(int code, projid_t projid, uint_t flags,
4276 void *projidbuf, size_t pbufsz);
4278 switch (ARG1 /*code*/) {
4279 case 0:
4280 /* Libc: taskid_t settaskid(projid_t project, uint_t flags); */
4281 PRINT("sys_tasksys ( %ld, %ld, %lu )", SARG1, SARG2, ARG3);
4282 PRE_REG_READ3(long, SC2("tasksys", "settaskid"), int, code,
4283 vki_projid_t, projid, vki_uint_t, flags);
4284 break;
4285 case 1:
4286 /* Libc: taskid_t gettaskid(void); */
4287 PRINT("sys_tasksys ( %ld )", SARG1);
4288 PRE_REG_READ1(long, SC2("tasksys", "gettaskid"), int, code);
4289 break;
4290 case 2:
4291 /* Libc: projid_t getprojid(void); */
4292 PRINT("sys_tasksys ( %ld )", SARG1);
4293 PRE_REG_READ1(long, SC2("tasksys", "getprojid"), int, code);
4294 break;
4295 case 3:
4296 /* Libproject: size_t projlist(id_t *idbuf, size_t idbufsz); */
4297 PRINT("sys_tasksys ( %ld, %#lx, %lu )", SARG1, ARG4, ARG5);
4298 PRE_REG_READ3(long, SC2("tasksys", "projlist"), int, code,
4299 vki_id_t *, idbuf, vki_size_t, idbufsz);
4300 PRE_MEM_WRITE("tasksys(idbuf)", ARG4, ARG5);
4301 break;
4302 default:
4303 VG_(unimplemented)("Syswrap of the tasksys call with code %ld.", SARG1);
4304 /*NOTREACHED*/
4305 break;
4309 POST(sys_tasksys)
4311 switch (ARG1 /*code*/) {
4312 case 0:
4313 case 1:
4314 case 2:
4315 break;
4316 case 3:
4317 if ((ARG4 != 0) && (ARG5 != 0))
4318 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
4319 break;
4320 default:
4321 vg_assert(0);
4322 break;
4326 PRE(sys_lwp_park)
4328 /* Kernel: int lwp_park(int which, uintptr_t arg1, uintptr_t arg2);
4330 *flags |= SfMayBlock;
4331 switch (ARG1 /*which*/) {
4332 case 0:
4333 /* Libc: int lwp_park(timespec_t *timeout, id_t lwpid); */
4334 PRINT("sys_lwp_park ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
4335 PRE_REG_READ3(long, SC2("lwp_park", "lwp_park"), int, which,
4336 timespec_t *, timeout, vki_id_t, lwpid);
4337 if (ARG2) {
4338 PRE_MEM_READ("lwp_park(timeout)", ARG2, sizeof(vki_timespec_t));
4339 /*PRE_MEM_WRITE("lwp_park(timeout)", ARG2,
4340 sizeof(vki_timespec_t));*/
4342 break;
4343 case 1:
4344 /* Libc: int lwp_unpark(id_t lwpid); */
4345 PRINT("sys_lwp_park ( %ld, %ld )", SARG1, SARG2);
4346 PRE_REG_READ2(long, SC2("lwp_park", "lwp_unpark"), int, which,
4347 vki_id_t, lwpid);
4348 break;
4349 case 2:
4350 /* Libc: int lwp_unpark_all(id_t *lwpid, int nids); */
4351 PRINT("sys_lwp_park ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
4352 PRE_REG_READ3(long, SC2("lwp_park", "lwp_unpark_all"), int, which,
4353 id_t *, lwpid, int, nids);
4354 PRE_MEM_READ("lwp_park(lwpid)", ARG2, ARG3 * sizeof(vki_id_t));
4355 break;
4356 default:
4357 VG_(unimplemented)("Syswrap of the lwp_park call with which %ld.", SARG1);
4358 /*NOTREACHED*/
4359 break;
4363 POST(sys_lwp_park)
4365 switch (ARG1 /*which*/) {
4366 case 0:
4367 if (ARG2)
4368 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
4369 break;
4370 case 1:
4371 case 2:
4372 break;
4373 default:
4374 vg_assert(0);
4375 break;
4379 PRE(sys_sendfilev)
4381 /* Kernel: ssize_t sendfilev(int opcode, int fd,
4382 const struct sendfilevec *vec,
4383 int sfvcnt, size_t *xferred);
4385 PRINT("sys_sendfilev ( %ld, %ld, %#lx, %ld, %#lx )",
4386 SARG1, SARG2, ARG3, SARG4, ARG5);
4388 switch (ARG1 /*opcode*/) {
4389 case VKI_SENDFILEV:
4391 PRE_REG_READ5(long, "sendfilev", int, opcode, int, fd,
4392 const struct vki_sendfilevec *, vec,
4393 int, sfvcnt, vki_size_t *, xferred);
4395 PRE_MEM_READ("sendfilev(vec)", ARG3,
4396 ARG4 * sizeof(struct vki_sendfilevec));
4397 PRE_MEM_WRITE("sendfilev(xferred)", ARG5, sizeof(vki_size_t));
4399 struct vki_sendfilevec *vec = (struct vki_sendfilevec *) ARG3;
4400 if (ML_(safe_to_deref)(vec, ARG4 *
4401 sizeof(struct vki_sendfilevec))) {
4402 UInt i;
4403 for (i = 0; i < ARG4; i++) {
4404 HChar desc[35]; // large enough
4405 if (vec[i].sfv_fd == VKI_SFV_FD_SELF) {
4406 VG_(snprintf)(desc, sizeof(desc),
4407 "sendfilev(vec[%u].sfv_off", i);
4408 PRE_MEM_READ(desc, vec[i].sfv_off, vec[i].sfv_len);
4409 } else {
4410 VG_(snprintf)(desc, sizeof(desc),
4411 "sendfilev(vec[%u].sfv_fd)", i);
4412 if (!ML_(fd_allowed)(vec[i].sfv_fd, desc, tid, False))
4413 SET_STATUS_Failure(VKI_EBADF);
4418 break;
4419 case VKI_SENDFILEV64:
4421 PRE_REG_READ5(long, "sendfilev", int, opcode, int, fd,
4422 const struct vki_sendfilevec64 *, vec,
4423 int, sfvcnt, vki_size_t *, xferred);
4425 PRE_MEM_READ("sendfilev(vec)", ARG3,
4426 ARG4 * sizeof(struct vki_sendfilevec64));
4427 PRE_MEM_WRITE("sendfilev(xferred)", ARG5, sizeof(vki_size_t));
4429 struct vki_sendfilevec64 *vec64 =
4430 (struct vki_sendfilevec64 *) ARG3;
4431 if (ML_(safe_to_deref)(vec64, ARG4 *
4432 sizeof(struct vki_sendfilevec64))) {
4433 UInt i;
4434 for (i = 0; i < ARG4; i++) {
4435 HChar desc[35]; // large enough
4436 if (vec64[i].sfv_fd == VKI_SFV_FD_SELF) {
4437 VG_(snprintf)(desc, sizeof(desc),
4438 "sendfilev(vec[%u].sfv_off", i);
4439 PRE_MEM_READ(desc, vec64[i].sfv_off, vec64[i].sfv_len);
4440 } else {
4441 VG_(snprintf)(desc, sizeof(desc),
4442 "sendfilev(vec[%u].sfv_fd)", i);
4443 if (!ML_(fd_allowed)(vec64[i].sfv_fd, desc,
4444 tid, False))
4445 SET_STATUS_Failure(VKI_EBADF);
4450 break;
4451 default:
4452 VG_(unimplemented)("Syswrap of the sendfilev call with "
4453 "opcode %ld.", SARG1);
4454 /*NOTREACHED*/
4455 break;
4458 /* Be strict. */
4459 if (!ML_(fd_allowed)(ARG2, "sendfilev(fd)", tid, False))
4460 SET_STATUS_Failure(VKI_EBADF);
4462 *flags |= SfMayBlock;
4465 POST(sys_sendfilev)
4467 POST_MEM_WRITE(ARG5, sizeof(vki_size_t));
4470 #if defined(SOLARIS_LWP_NAME_SYSCALL)
4471 PRE(sys_lwp_name)
4473 /* int lwp_name(int opcode, id_t lwpid, char *name, size_t len); */
4474 PRINT("sys_lwp_name ( %ld, %ld, %#lx, %lu )", SARG1, SARG2, ARG3, ARG4);
4476 switch (ARG1 /*opcode*/) {
4477 case 0:
4478 /* lwp_setname */
4479 PRE_REG_READ3(long, "lwp_name", int, opcode, vki_id_t, lwpid,
4480 char *, name);
4481 PRE_MEM_RASCIIZ("lwp_name(name)", ARG3);
4482 break;
4483 case 1:
4484 /* lwp_getname */
4485 PRE_REG_READ4(long, "lwp_name", int, opcode, vki_id_t, lwpid,
4486 char *, name, vki_size_t, len);
4487 PRE_MEM_WRITE("lwp_name(name)", ARG3, ARG4);
4488 break;
4489 default:
4490 VG_(unimplemented)("Syswrap of the lwp_name call with opcode %ld.", SARG1);
4491 /*NOTREACHED*/
4492 break;
4496 POST(sys_lwp_name)
4498 switch (ARG1 /*opcode*/) {
4499 case 0:
4500 if (ARG3) { // Paranoia
4501 const HChar *new_name = (const HChar *) ARG3;
4502 ThreadState *tst = VG_(get_ThreadState)(tid);
4503 SizeT new_len = VG_(strlen)(new_name);
4505 /* Don't bother reusing the memory. This is a rare event. */
4506 tst->thread_name = VG_(realloc)("syswrap.lwp_name", tst->thread_name,
4507 new_len + 1);
4508 VG_(strcpy)(tst->thread_name, new_name);
4510 break;
4511 case 1:
4512 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
4513 break;
4514 default:
4515 vg_assert(0);
4516 break;
4519 #endif /* SOLARIS_LWP_NAME_SYSCALL */
4521 PRE(sys_privsys)
4523 /* Kernel: int privsys(int code, priv_op_t op, priv_ptype_t type,
4524 void *buf, size_t bufsize, int itype);
4526 switch (ARG1 /*code*/) {
4527 case VKI_PRIVSYS_SETPPRIV:
4528 /* Libc: int setppriv(priv_op_t op, priv_ptype_t type,
4529 const priv_set_t *pset);
4531 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
4532 ARG4, ARG5);
4533 PRE_REG_READ5(long, SC2("privsys", "setppriv"), int, code,
4534 vki_priv_op_t, op, vki_priv_ptype_t, type,
4535 const priv_set_t *, pset, vki_size_t, bufsize);
4536 PRE_MEM_READ("privsys(pset)", ARG4, ARG5);
4537 break;
4538 case VKI_PRIVSYS_GETPPRIV:
4539 /* Libc: int getppriv(priv_ptype_t type, priv_set_t *pset);
4540 priv_set_t *pset -> void *buf
4542 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
4543 ARG4, ARG5);
4544 PRE_REG_READ5(long, SC2("privsys", "getppriv"), int, code,
4545 vki_priv_op_t, op, vki_priv_ptype_t, type, priv_set_t *, pset,
4546 vki_size_t, bufsize);
4547 PRE_MEM_WRITE("privsys(pset)", ARG4, ARG5);
4548 break;
4549 case VKI_PRIVSYS_GETIMPLINFO:
4550 /* Libc: int getprivinfo(priv_impl_info_t *buf, size_t bufsize);
4551 priv_impl_info_t *buf -> void *buf
4553 PRINT("sys_privsys ( %ld, %ld, %ld, %#lx, %lu )", SARG1, SARG2, SARG3,
4554 ARG4, ARG5);
4555 PRE_REG_READ5(long, SC2("privsys", "getprivinfo"), int, code,
4556 vki_priv_op_t, op, vki_priv_ptype_t, type,
4557 priv_impl_info_t *, buf, vki_size_t, bufsize);
4558 PRE_MEM_WRITE("privsys(buf)", ARG4, ARG5);
4559 break;
4560 case VKI_PRIVSYS_SETPFLAGS:
4561 /* Libc: int setpflags(uint_t flag, uint_t val);
4562 uint_t flag -> priv_op_t op
4563 uint_t val -> priv_ptype_t type
4565 PRINT("sys_privsys ( %ld, %lu, %lu )", SARG1, ARG2, ARG3);
4566 PRE_REG_READ3(long, SC2("privsys", "setpflags"), int, code,
4567 vki_uint_t, flag, vki_uint_t, val);
4568 break;
4569 case VKI_PRIVSYS_GETPFLAGS:
4570 /* Libc: uint_t getpflags(uint_t flag);
4571 uint_t flag -> priv_op_t op
4573 PRINT("sys_privsys ( %ld, %lu )", SARG1, ARG2);
4574 PRE_REG_READ2(long, SC2("privsys", "setpflags"), int, code,
4575 vki_uint_t, flag);
4576 break;
4577 case VKI_PRIVSYS_ISSETUGID:
4578 /* Libc: int issetugid(void); */
4579 PRINT("sys_privsys ( %ld )", SARG1);
4580 PRE_REG_READ1(long, SC2("privsys", "issetugid"), int, code);
4581 break;
4582 case VKI_PRIVSYS_PFEXEC_REG:
4583 /* Libc: int register_pfexec(int did);
4584 int did -> priv_op_t op
4586 PRINT("sys_privsys ( %ld, %ld )", SARG1, SARG2);
4587 PRE_REG_READ2(long, SC2("privsys", "register_pfexec"), int, code,
4588 int, did);
4589 break;
4590 case VKI_PRIVSYS_PFEXEC_UNREG:
4591 /* Libc: int unregister_pfexec(int did); */
4592 PRINT("sys_privsys ( %ld, %ld )", SARG1, SARG2);
4593 PRE_REG_READ2(long, SC2("privsys", "unregister_pfexec"), int, code,
4594 int, did);
4595 break;
4596 default:
4597 VG_(unimplemented)("Syswrap of the privsys call with code %ld.", SARG1);
4598 /*NOTREACHED*/
4599 break;
4602 /* Be strict. */
4603 if ((ARG1 == VKI_PRIVSYS_PFEXEC_REG ||
4604 ARG1 == VKI_PRIVSYS_PFEXEC_UNREG) &&
4605 !ML_(fd_allowed)(ARG2, "privsys", tid, False))
4606 SET_STATUS_Failure(VKI_EBADF);
4609 POST(sys_privsys)
4611 switch (ARG1 /*code*/) {
4612 case VKI_PRIVSYS_SETPPRIV:
4613 break;
4614 case VKI_PRIVSYS_GETPPRIV:
4615 POST_MEM_WRITE(ARG4, sizeof(vki_priv_set_t));
4616 break;
4617 case VKI_PRIVSYS_GETIMPLINFO:
4618 /* The kernel copy outs data of size min(bufsize, privinfosize).
4619 Unfortunately, it does not seem to be possible to easily obtain the
4620 privinfosize value. The code below optimistically marks all ARG5
4621 bytes (aka bufsize) as written by the kernel. */
4622 POST_MEM_WRITE(ARG4, ARG5);
4623 break;
4624 case VKI_PRIVSYS_SETPFLAGS:
4625 case VKI_PRIVSYS_GETPFLAGS:
4626 case VKI_PRIVSYS_ISSETUGID:
4627 case VKI_PRIVSYS_PFEXEC_REG:
4628 case VKI_PRIVSYS_PFEXEC_UNREG:
4629 break;
4630 default:
4631 vg_assert(0);
4632 break;
4636 PRE(sys_ucredsys)
4638 /* Kernel: int ucredsys(int code, int obj, void *buf); */
4639 PRINT("sys_ucredsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
4641 switch (ARG1 /*code*/) {
4642 case VKI_UCREDSYS_UCREDGET:
4643 /* Libc: ucred_t *ucred_get(pid_t pid); */
4644 PRE_REG_READ3(long, SC2("ucredsys", "ucredget"), int, code,
4645 vki_pid_t, pid, vki_ucred_t *, buf);
4646 PRE_MEM_WRITE("ucredsys(buf)", ARG3, sizeof(vki_ucred_t));
4647 break;
4649 case VKI_UCREDSYS_GETPEERUCRED:
4650 /* Libc: int getpeerucred(int fd, ucred_t **ucred); */
4651 PRE_REG_READ3(long, SC2("ucredsys", "getpeerucred"), int, code,
4652 int, fd, vki_ucred_t *, buf);
4653 PRE_MEM_WRITE("ucredsys(buf)", ARG3, sizeof(vki_ucred_t));
4655 /* Be strict. */
4656 if (!ML_(fd_allowed)(ARG2, "ucredsys", tid, False))
4657 SET_STATUS_Failure(VKI_EBADF);
4658 break;
4660 default:
4661 VG_(unimplemented)("Syswrap of the ucredsys call with code %ld.", SARG1);
4662 /*NOTREACHED*/
4663 break;
4667 POST(sys_ucredsys)
4669 switch (ARG1 /*code*/) {
4670 case VKI_UCREDSYS_UCREDGET:
4671 case VKI_UCREDSYS_GETPEERUCRED:
4672 vg_assert(ARG3 != 0);
4673 POST_MEM_WRITE(ARG3, ((vki_ucred_t *) ARG3)->uc_size);
4674 break;
4676 default:
4677 vg_assert(0);
4678 break;
4682 PRE(sys_sysfs)
4684 /* Kernel: int sysfs(int opcode, long a1, long a2); */
4685 PRINT("sys_sysfs ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
4687 switch (ARG1 /*opcode*/) {
4688 case VKI_GETFSIND:
4689 /* Libc: int sysfs(int opcode, const char *fsname); */
4690 PRE_REG_READ2(long, SC2("sysfs", "getfsind"), int, opcode,
4691 const char *, fsname);
4692 PRE_MEM_RASCIIZ("sysfs(fsname)", ARG2);
4693 break;
4694 case VKI_GETFSTYP:
4695 /* Libc: int sysfs(int opcode, int fs_index, char *buf); */
4696 PRE_REG_READ3(long, SC2("sysfs", "getfstyp"), int, opcode,
4697 int, fs_index, char *, buf);
4698 PRE_MEM_WRITE("sysfs(buf)", ARG3, VKI_FSTYPSZ + 1);
4699 break;
4700 case VKI_GETNFSTYP:
4701 /* Libc: int sysfs(int opcode); */
4702 PRE_REG_READ1(long, SC2("sysfs", "getnfstyp"), int, opcode);
4703 break;
4704 default:
4705 VG_(unimplemented)("Syswrap of the sysfs call with opcode %ld.", SARG1);
4706 /*NOTREACHED*/
4707 break;
4711 POST(sys_sysfs)
4713 switch (ARG1 /*opcode*/) {
4714 case VKI_GETFSIND:
4715 case VKI_GETNFSTYP:
4716 break;
4717 case VKI_GETFSTYP:
4718 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
4719 break;
4720 default:
4721 vg_assert(0);
4722 break;
4727 PRE(sys_getmsg)
4729 /* int getmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
4730 int *flagsp); */
4731 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4732 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4733 *flags |= SfMayBlock;
4734 PRINT("sys_getmsg ( %ld, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
4735 PRE_REG_READ4(long, "getmsg", int, fildes, struct vki_strbuf *, ctlptr,
4736 struct vki_strbuf *, dataptr, int *, flagsp);
4737 if (ctrlptr) {
4738 PRE_FIELD_READ("getmsg(ctrlptr->maxlen)", ctrlptr->maxlen);
4739 PRE_FIELD_WRITE("getmsg(ctrlptr->len)", ctrlptr->len);
4740 PRE_FIELD_READ("getmsg(ctrlptr->buf)", ctrlptr->buf);
4741 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
4742 && ctrlptr->maxlen > 0)
4743 PRE_MEM_WRITE("getmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
4744 ctrlptr->maxlen);
4746 if (dataptr) {
4747 PRE_FIELD_READ("getmsg(dataptr->maxlen)", dataptr->maxlen);
4748 PRE_FIELD_WRITE("getmsg(dataptr->len)", dataptr->len);
4749 PRE_FIELD_READ("getmsg(dataptr->buf)", dataptr->buf);
4750 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
4751 && dataptr->maxlen > 0)
4752 PRE_MEM_WRITE("getmsg(dataptr->buf)", (Addr)dataptr->buf,
4753 dataptr->maxlen);
4755 PRE_MEM_READ("getmsg(flagsp)", ARG4, sizeof(int));
4756 /*PRE_MEM_WRITE("getmsg(flagsp)", ARG4, sizeof(int));*/
4758 /* Be strict. */
4759 if (!ML_(fd_allowed)(ARG1, "getmsg", tid, False))
4760 SET_STATUS_Failure(VKI_EBADF);
4763 POST(sys_getmsg)
4765 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4766 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4768 if (ctrlptr && ctrlptr->len > 0)
4769 POST_MEM_WRITE((Addr)ctrlptr->buf, ctrlptr->len);
4770 if (dataptr && dataptr->len > 0)
4771 POST_MEM_WRITE((Addr)dataptr->buf, dataptr->len);
4772 POST_MEM_WRITE(ARG4, sizeof(int));
4775 PRE(sys_putmsg)
4777 /* int putmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
4778 int flags); */
4779 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
4780 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
4781 *flags |= SfMayBlock;
4782 PRINT("sys_putmsg ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
4783 PRE_REG_READ4(long, "putmsg", int, fildes, struct vki_strbuf *, ctrlptr,
4784 struct vki_strbuf *, dataptr, int, flags);
4785 if (ctrlptr) {
4786 PRE_FIELD_READ("putmsg(ctrlptr->len)", ctrlptr->len);
4787 PRE_FIELD_READ("putmsg(ctrlptr->buf)", ctrlptr->buf);
4788 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
4789 && ctrlptr->len > 0)
4790 PRE_MEM_READ("putmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
4791 ctrlptr->len);
4793 if (dataptr) {
4794 PRE_FIELD_READ("putmsg(dataptr->len)", dataptr->len);
4795 PRE_FIELD_READ("putmsg(dataptr->buf)", dataptr->buf);
4796 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
4797 && dataptr->len > 0)
4798 PRE_MEM_READ("putmsg(dataptr->buf)", (Addr)dataptr->buf,
4799 dataptr->len);
4802 /* Be strict. */
4803 if (!ML_(fd_allowed)(ARG1, "putmsg", tid, False))
4804 SET_STATUS_Failure(VKI_EBADF);
4807 PRE(sys_lstat)
4809 /* int lstat(const char *path, struct stat *buf); */
4810 /* Note: We could use here the sys_newlstat generic wrapper, but the 'new'
4811 in its name is rather confusing in the Solaris context, thus we provide
4812 our own wrapper. */
4813 PRINT("sys_lstat ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
4814 PRE_REG_READ2(long, "lstat", const char *, path, struct stat *, buf);
4816 PRE_MEM_RASCIIZ("lstat(path)", ARG1);
4817 PRE_MEM_WRITE("lstat(buf)", ARG2, sizeof(struct vki_stat));
4820 POST(sys_lstat)
4822 POST_MEM_WRITE(ARG2, sizeof(struct vki_stat));
4825 PRE(sys_sigprocmask)
4827 /* int sigprocmask(int how, const sigset_t *set, sigset_t *oset); */
4828 PRINT("sys_sigprocmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
4829 PRE_REG_READ3(long, "sigprocmask",
4830 int, how, vki_sigset_t *, set, vki_sigset_t *, oset);
4831 if (ARG2)
4832 PRE_MEM_READ("sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4833 if (ARG3)
4834 PRE_MEM_WRITE("sigprocmask(oset)", ARG3, sizeof(vki_sigset_t));
4836 /* Be safe. */
4837 if (ARG2 && !ML_(safe_to_deref((void*)ARG2, sizeof(vki_sigset_t)))) {
4838 SET_STATUS_Failure(VKI_EFAULT);
4840 if (ARG3 && !ML_(safe_to_deref((void*)ARG3, sizeof(vki_sigset_t)))) {
4841 SET_STATUS_Failure(VKI_EFAULT);
4844 if (!FAILURE)
4845 SET_STATUS_from_SysRes(
4846 VG_(do_sys_sigprocmask)(tid, ARG1 /*how*/, (vki_sigset_t*)ARG2,
4847 (vki_sigset_t*)ARG3)
4850 if (SUCCESS)
4851 *flags |= SfPollAfter;
4854 POST(sys_sigprocmask)
4856 if (ARG3)
4857 POST_MEM_WRITE(ARG3, sizeof(vki_sigset_t));
4860 PRE(sys_sigsuspend)
4862 *flags |= SfMayBlock;
4864 /* int sigsuspend(const sigset_t *set); */
4865 PRINT("sys_sigsuspend ( %#lx )", ARG1);
4866 PRE_REG_READ1(long, "sigsuspend", vki_sigset_t *, set);
4867 PRE_MEM_READ("sigsuspend(set)", ARG1, sizeof(vki_sigset_t));
4869 /* Be safe. */
4870 if (ARG1 && ML_(safe_to_deref((void *) ARG1, sizeof(vki_sigset_t)))) {
4871 VG_(sigdelset)((vki_sigset_t *) ARG1, VG_SIGVGKILL);
4872 /* We cannot mask VG_SIGVGKILL, as otherwise this thread would not
4873 be killable by VG_(nuke_all_threads_except).
4874 We thus silently ignore the user request to mask this signal.
4875 Note that this is similar to what is done for e.g.
4876 sigprocmask (see m_signals.c calculate_SKSS_from_SCSS). */
4880 PRE(sys_sigaction)
4882 /* int sigaction(int signal, const struct sigaction *act,
4883 struct sigaction *oact); */
4884 PRINT("sys_sigaction ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
4885 PRE_REG_READ3(long, "sigaction", int, signal,
4886 const struct sigaction *, act, struct sigaction *, oact);
4888 /* Note that on Solaris, vki_sigaction_toK_t and vki_sigaction_fromK_t are
4889 both typedefs of 'struct sigaction'. */
4891 if (ARG2) {
4892 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t*)ARG2;
4893 PRE_FIELD_READ("sigaction(act->sa_flags)", sa->sa_flags);
4894 PRE_FIELD_READ("sigaction(act->sa_handler)", sa->ksa_handler);
4895 PRE_FIELD_READ("sigaction(act->sa_mask)", sa->sa_mask);
4897 if (ARG3)
4898 PRE_MEM_WRITE("sigaction(oact)", ARG3, sizeof(vki_sigaction_fromK_t));
4900 /* Be safe. */
4901 if (ARG2 && !ML_(safe_to_deref((void*)ARG2,
4902 sizeof(vki_sigaction_toK_t)))) {
4903 SET_STATUS_Failure(VKI_EFAULT);
4905 if (ARG3 && !ML_(safe_to_deref((void*)ARG3,
4906 sizeof(vki_sigaction_fromK_t)))) {
4907 SET_STATUS_Failure(VKI_EFAULT);
4910 if (!FAILURE)
4911 SET_STATUS_from_SysRes(
4912 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t*)ARG2,
4913 (vki_sigaction_fromK_t*)ARG3));
4916 POST(sys_sigaction)
4918 if (ARG3)
4919 POST_MEM_WRITE(ARG3, sizeof(vki_sigaction_fromK_t));
4922 PRE(sys_sigpending)
4924 /* int sigpending(int flag, sigset_t *setp); */
4925 PRINT("sys_sigpending ( %ld, %#lx )", SARG1, ARG2);
4926 PRE_REG_READ2(long, "sigpending", int, flag, sigset_t *, setp);
4927 PRE_MEM_WRITE("sigpending(setp)", ARG2, sizeof(vki_sigset_t));
4930 POST(sys_sigpending)
4932 POST_MEM_WRITE(ARG2, sizeof(vki_sigset_t));
4935 PRE(sys_getsetcontext)
4937 /* Kernel: int getsetcontext(int flag, void *arg) */
4938 ThreadState *tst = VG_(get_ThreadState)(tid);
4939 PRINT("sys_getsetcontext ( %ld, %#lx )", SARG1, ARG2);
4940 switch (ARG1 /*flag*/) {
4941 case VKI_GETCONTEXT:
4942 /* Libc: int getcontext(ucontext_t *ucp); */
4943 PRE_REG_READ2(long, SC2("getsetcontext", "getcontext"), int, flag,
4944 ucontext_t *, ucp);
4945 PRE_MEM_WRITE("getsetcontext(ucp)", ARG2, sizeof(vki_ucontext_t));
4947 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_ucontext_t)))) {
4948 SET_STATUS_Failure(VKI_EFAULT);
4949 return;
4951 VG_(save_context)(tid, (vki_ucontext_t*)ARG2, Vg_CoreSysCall);
4952 SET_STATUS_Success(0);
4953 break;
4954 case VKI_SETCONTEXT:
4955 /* Libc: int setcontext(const ucontext_t *ucp); */
4956 PRE_REG_READ2(long, SC2("getsetcontext", "setcontext"), int, flag,
4957 const ucontext_t *, ucp);
4959 if (!ARG2) {
4960 /* Setting NULL context causes thread exit. */
4961 tst->exitreason = VgSrc_ExitThread;
4962 tst->os_state.exitcode = 0;
4963 SET_STATUS_Success(0);
4964 return;
4967 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_ucontext_t)))) {
4968 SET_STATUS_Failure(VKI_EFAULT);
4969 return;
4972 VG_(restore_context)(tid, (vki_ucontext_t*)ARG2,
4973 Vg_CoreSysCall, False/*esp_is_thrptr*/);
4974 /* Tell the driver not to update the guest state with the "result". */
4975 *flags |= SfNoWriteResult;
4976 /* Check to see if any signals arose as a result of this. */
4977 *flags |= SfPollAfter;
4979 /* Check if this is a possible return from a signal handler. */
4980 VG_(sigframe_return)(tid, (vki_ucontext_t*)ARG2);
4982 SET_STATUS_Success(0);
4983 break;
4984 case VKI_GETUSTACK:
4985 /* Libc: int getustack(stack_t **spp); */
4986 PRE_REG_READ2(long, SC2("getsetcontext", "getustack"), int, flag,
4987 stack_t **, spp);
4988 PRE_MEM_WRITE("getsetcontext(spp)", ARG2, sizeof(vki_stack_t*));
4990 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_stack_t*)))) {
4991 SET_STATUS_Failure(VKI_EFAULT);
4992 return;
4995 *(vki_stack_t**)ARG2 = tst->os_state.ustack;
4996 POST_MEM_WRITE(ARG2, sizeof(vki_stack_t*));
4997 SET_STATUS_Success(0);
4998 break;
4999 case VKI_SETUSTACK:
5001 /* Libc: int setustack(stack_t *sp); */
5002 PRE_REG_READ2(long, SC2("getsetcontext", "setustack"), int, flag,
5003 stack_t *, sp);
5005 /* The kernel does not read the stack data instantly but it can read
5006 them later so it is better to make sure the data are defined. */
5007 PRE_MEM_READ("getsetcontext_setustack(sp)", ARG2, sizeof(vki_stack_t));
5009 if (!ML_(safe_to_deref((void*)ARG2, sizeof(vki_stack_t)))) {
5010 SET_STATUS_Failure(VKI_EFAULT);
5011 return;
5014 vki_stack_t *old_stack = tst->os_state.ustack;
5015 tst->os_state.ustack = (vki_stack_t*)ARG2;
5017 /* The thread is setting the ustack pointer. It is a good time to get
5018 information about its stack. */
5019 if (tst->os_state.ustack->ss_flags == 0) {
5020 /* If the sanity check of ss_flags passed set the stack. */
5021 set_stack(tid, tst->os_state.ustack);
5023 if ((old_stack == NULL) && (tid > 1)) {
5024 /* New thread creation is now completed. Inform the tool. */
5025 VG_TRACK(pre_thread_first_insn, tid);
5029 SET_STATUS_Success(0);
5031 break;
5032 default:
5033 VG_(unimplemented)("Syswrap of the context call with flag %ld.", SARG1);
5034 /*NOTREACHED*/
5035 break;
5039 PRE(sys_fchmodat)
5041 /* int fchmodat(int fd, const char *path, mode_t mode, int flag); */
5043 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5044 This is different from Linux, for example, where glibc sign-extends it. */
5045 Int fd = (Int) ARG1;
5047 PRINT("sys_fchmodat ( %d, %#lx(%s), %ld, %ld )",
5048 fd, ARG2, (HChar *) ARG2, SARG3, SARG4);
5049 PRE_REG_READ4(long, "fchmodat",
5050 int, fd, const char *, path, vki_mode_t, mode, int, flag);
5052 if (ARG2)
5053 PRE_MEM_RASCIIZ("fchmodat(path)", ARG2);
5055 /* Be strict but ignore fd for absolute path. */
5056 if (fd != VKI_AT_FDCWD
5057 && ML_(safe_to_deref)((void *) ARG2, 1)
5058 && ((HChar *) ARG2)[0] != '/'
5059 && !ML_(fd_allowed)(fd, "fchmodat", tid, False))
5060 SET_STATUS_Failure(VKI_EBADF);
5063 PRE(sys_mkdirat)
5065 /* int mkdirat(int fd, const char *path, mode_t mode); */
5067 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5068 This is different from Linux, for example, where glibc sign-extends it. */
5069 Int fd = (Int) ARG1;
5071 *flags |= SfMayBlock;
5072 PRINT("sys_mkdirat ( %d, %#lx(%s), %ld )", fd, ARG2, (HChar *) ARG2, SARG3);
5073 PRE_REG_READ3(long, "mkdirat", int, fd, const char *, path,
5074 vki_mode_t, mode);
5075 PRE_MEM_RASCIIZ("mkdirat(path)", ARG2);
5077 /* Be strict but ignore fd for absolute path. */
5078 if (fd != VKI_AT_FDCWD
5079 && ML_(safe_to_deref)((void *) ARG2, 1)
5080 && ((HChar *) ARG2)[0] != '/'
5081 && !ML_(fd_allowed)(fd, "mkdirat", tid, False))
5082 SET_STATUS_Failure(VKI_EBADF);
5085 static void do_statvfs_post(struct vki_statvfs *stats, ThreadId tid)
5087 POST_FIELD_WRITE(stats->f_bsize);
5088 POST_FIELD_WRITE(stats->f_frsize);
5089 POST_FIELD_WRITE(stats->f_blocks);
5090 POST_FIELD_WRITE(stats->f_bfree);
5091 POST_FIELD_WRITE(stats->f_bavail);
5092 POST_FIELD_WRITE(stats->f_files);
5093 POST_FIELD_WRITE(stats->f_ffree);
5094 POST_FIELD_WRITE(stats->f_favail);
5095 POST_FIELD_WRITE(stats->f_fsid);
5096 POST_MEM_WRITE((Addr) stats->f_basetype, VG_(strlen)(stats->f_basetype) + 1);
5097 POST_FIELD_WRITE(stats->f_flag);
5098 POST_FIELD_WRITE(stats->f_namemax);
5099 POST_MEM_WRITE((Addr) stats->f_fstr, VG_(strlen)(stats->f_fstr) + 1);
5102 PRE(sys_statvfs)
5104 /* int statvfs(const char *path, struct statvfs *buf); */
5105 *flags |= SfMayBlock;
5106 PRINT("sys_statvfs ( %#lx(%s), %#lx )", ARG1, (HChar *) ARG1, ARG2);
5107 PRE_REG_READ2(long, "statvfs", const char *, path,
5108 struct vki_statvfs *, buf);
5109 PRE_MEM_RASCIIZ("statvfs(path)", ARG1);
5110 PRE_MEM_WRITE("statvfs(buf)", ARG2, sizeof(struct vki_statvfs));
5113 POST(sys_statvfs)
5115 do_statvfs_post((struct vki_statvfs *) ARG2, tid);
5118 PRE(sys_fstatvfs)
5120 /* int fstatvfs(int fd, struct statvfs *buf); */
5121 *flags |= SfMayBlock;
5122 PRINT("sys_fstatvfs ( %ld, %#lx )", SARG1, ARG2);
5123 PRE_REG_READ2(long, "fstatvfs", int, fd, struct vki_statvfs *, buf);
5124 PRE_MEM_WRITE("fstatvfs(buf)", ARG2, sizeof(struct vki_statvfs));
5126 /* Be strict. */
5127 if (!ML_(fd_allowed)(ARG1, "fstatvfs", tid, False))
5128 SET_STATUS_Failure(VKI_EBADF);
5131 POST(sys_fstatvfs)
5133 do_statvfs_post((struct vki_statvfs *) ARG2, tid);
5136 PRE(sys_nfssys)
5138 /* int nfssys(enum nfssys_op opcode, void *arg); */
5139 *flags |= SfMayBlock;
5140 PRINT("sys_nfssys ( %ld, %#lx )", SARG1, ARG2);
5142 switch (ARG1 /*opcode*/) {
5143 case VKI_NFS_REVAUTH:
5144 PRE_REG_READ2(long, SC2("nfssys", "nfs_revauth"), int, opcode,
5145 struct vki_nfs_revauth_args *, args);
5146 PRE_MEM_READ("nfssys(arg)", ARG2,
5147 sizeof(struct vki_nfs_revauth_args));
5148 break;
5149 default:
5150 VG_(unimplemented)("Syswrap of the nfssys call with opcode %ld.", SARG1);
5151 /*NOTREACHED*/
5152 break;
5156 POST(sys_nfssys)
5158 switch (ARG1 /*opcode*/) {
5159 case VKI_NFS_REVAUTH:
5160 break;
5161 default:
5162 vg_assert(0);
5163 break;
5167 PRE(sys_waitid)
5169 /* int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); */
5170 *flags |= SfMayBlock;
5171 PRINT("sys_waitid( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
5172 PRE_REG_READ4(long, "waitid", vki_idtype_t, idtype, vki_id_t, id,
5173 siginfo_t *, infop, int, options);
5174 PRE_MEM_WRITE("waitid(infop)", ARG3, sizeof(vki_siginfo_t));
5177 POST(sys_waitid)
5179 POST_MEM_WRITE(ARG3, sizeof(vki_siginfo_t));
5182 PRE(sys_sigsendsys)
5184 /* int sigsendsys(procset_t *psp, int sig); */
5185 PRINT("sys_sigsendsys( %#lx, %ld )", ARG1, SARG2);
5186 PRE_REG_READ2(long, "sigsendsys", vki_procset_t *, psp, int, signal);
5187 PRE_MEM_READ("sigsendsys(psp)", ARG1, sizeof(vki_procset_t));
5189 if (!ML_(client_signal_OK)(ARG1)) {
5190 SET_STATUS_Failure(VKI_EINVAL);
5192 if (!ML_(safe_to_deref)((void *) ARG1, sizeof(vki_procset_t))) {
5193 SET_STATUS_Failure(VKI_EFAULT);
5196 /* Exit early if there are problems. */
5197 if (FAILURE)
5198 return;
5200 vki_procset_t *psp = (vki_procset_t *) ARG1;
5201 switch (psp->p_op) {
5202 case VKI_POP_AND:
5203 break;
5204 default:
5205 VG_(unimplemented)("Syswrap of the sigsendsys call with op %u.",
5206 psp->p_op);
5209 UInt pid;
5210 if ((psp->p_lidtype == VKI_P_PID) && (psp->p_ridtype == VKI_P_ALL)) {
5211 pid = psp->p_lid;
5212 } else if ((psp->p_lidtype == VKI_P_ALL) && (psp->p_ridtype == VKI_P_PID)) {
5213 pid = psp->p_rid;
5214 } else {
5215 VG_(unimplemented)("Syswrap of the sigsendsys call with lidtype %u and"
5216 "ridtype %u.", psp->p_lidtype, psp->p_ridtype);
5219 if (VG_(clo_trace_signals))
5220 VG_(message)(Vg_DebugMsg, "sigsendsys: sending signal to process %u\n",
5221 pid);
5223 /* Handle SIGKILL specially. */
5224 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(pid, -1)) {
5225 SET_STATUS_Success(0);
5226 return;
5229 /* Check to see if this gave us a pending signal. */
5230 *flags |= SfPollAfter;
5233 #if defined(SOLARIS_UTIMESYS_SYSCALL)
5234 PRE(sys_utimesys)
5236 /* Kernel: int utimesys(int code, uintptr_t arg1, uintptr_t arg2,
5237 uintptr_t arg3, uintptr_t arg4);
5240 switch (ARG1 /*code*/) {
5241 case 0:
5242 /* Libc: int futimens(int fd, const timespec_t times[2]); */
5243 PRINT("sys_utimesys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
5244 PRE_REG_READ3(long, "utimesys", int, code, int, fd,
5245 const vki_timespec_t *, times);
5246 if (ARG3)
5247 PRE_MEM_READ("utimesys(times)", ARG3, 2 * sizeof(vki_timespec_t));
5249 /* Be strict. */
5250 if (!ML_(fd_allowed)(ARG2, "utimesys", tid, False))
5251 SET_STATUS_Failure(VKI_EBADF);
5252 break;
5253 case 1:
5255 /* Libc: int utimensat(int fd, const char *path,
5256 const timespec_t times[2], int flag);
5259 /* Interpret the second argument as 32-bit value even on 64-bit
5260 architecture. This is different from Linux, for example, where glibc
5261 sign-extends it. */
5262 Int fd = (Int) ARG2;
5264 PRINT("sys_utimesys ( %ld, %d, %#lx(%s), %#lx, %ld )",
5265 SARG1, fd, ARG3, (HChar *) ARG3, ARG4, SARG5);
5266 PRE_REG_READ5(long, "utimesys", int, code, int, fd, const char *, path,
5267 const vki_timespec_t *, times, int, flag);
5268 if (ARG3)
5269 PRE_MEM_RASCIIZ("utimesys(path)", ARG3);
5270 if (ARG4)
5271 PRE_MEM_READ("utimesys(times)", ARG4, 2 * sizeof(vki_timespec_t));
5273 /* Be strict but ignore fd for absolute path. */
5274 if (fd != VKI_AT_FDCWD
5275 && ML_(safe_to_deref)((void *) ARG3, 1)
5276 && ((HChar *) ARG3)[0] != '/'
5277 && !ML_(fd_allowed)(fd, "utimesys", tid, False))
5278 SET_STATUS_Failure(VKI_EBADF);
5279 break;
5281 default:
5282 VG_(unimplemented)("Syswrap of the utimesys call with code %ld.", SARG1);
5283 /*NOTREACHED*/
5284 break;
5287 #endif /* SOLARIS_UTIMESYS_SYSCALL */
5289 #if defined(SOLARIS_UTIMENSAT_SYSCALL)
5290 PRE(sys_utimensat)
5292 /* int utimensat(int fd, const char *path, const timespec_t times[2],
5293 int flag);
5296 /* Interpret the first argument as 32-bit value even on 64-bit architecture.
5297 This is different from Linux, for example, where glibc sign-extends it. */
5298 Int fd = (Int) ARG1;
5300 PRINT("sys_utimensat ( %d, %#lx(%s), %#lx, %ld )",
5301 fd, ARG2, (HChar *) ARG2, ARG3, SARG4);
5302 PRE_REG_READ4(long, "utimensat", int, fd, const char *, path,
5303 const vki_timespec_t *, times, int, flag);
5304 if (ARG2)
5305 PRE_MEM_RASCIIZ("utimensat(path)", ARG2);
5306 if (ARG3)
5307 PRE_MEM_READ("utimensat(times)", ARG3, 2 * sizeof(vki_timespec_t));
5309 /* Be strict but ignore fd for absolute path. */
5310 if (fd != VKI_AT_FDCWD
5311 && ML_(safe_to_deref)((void *) ARG2, 1)
5312 && ((HChar *) ARG2)[0] != '/'
5313 && !ML_(fd_allowed)(fd, "utimensat", tid, False))
5314 SET_STATUS_Failure(VKI_EBADF);
5316 #endif /* SOLARIS_UTIMENSAT_SYSCALL */
5318 PRE(sys_sigresend)
5320 /* int sigresend(int signal, siginfo_t *siginfo, sigset_t *mask); */
5321 /* Sends a signal to the calling thread, the mask parameter specifies a new
5322 signal mask. */
5324 /* Static (const) mask accessible from outside of this function. */
5325 static vki_sigset_t block_all;
5327 PRINT("sys_sigresend( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
5328 PRE_REG_READ3(long, "sigresend", int, signal, vki_siginfo_t *, siginfo,
5329 vki_sigset_t *, mask);
5331 if (ARG2)
5332 PRE_MEM_READ("sigresend(siginfo)", ARG2, sizeof(vki_siginfo_t));
5333 PRE_MEM_WRITE("sigresend(mask)", ARG3, sizeof(vki_sigset_t));
5335 /* Check the signal and mask. */
5336 if (!ML_(client_signal_OK)(ARG1)) {
5337 SET_STATUS_Failure(VKI_EINVAL);
5339 if (!ML_(safe_to_deref)((void*)ARG3, sizeof(vki_sigset_t))) {
5340 SET_STATUS_Failure(VKI_EFAULT);
5343 /* Exit early if there are problems. */
5344 if (FAILURE)
5345 return;
5347 /* Save the requested mask to unused ARG4. */
5348 ARG4 = ARG3;
5350 /* Fake the requested sigmask with a block-all mask. If the syscall
5351 succeeds then we will block "all" signals for a few instructions (in
5352 syscall-x86-solaris.S) but the correct mask will be almost instantly set
5353 again by a call to sigprocmask (also in syscall-x86-solaris.S). If the
5354 syscall fails then the mask is not changed, so everything is ok too. */
5355 VG_(sigfillset)(&block_all);
5356 ARG3 = (UWord)&block_all;
5358 /* Check to see if this gave us a pending signal. */
5359 *flags |= SfPollAfter;
5361 if (VG_(clo_trace_signals))
5362 VG_(message)(Vg_DebugMsg, "sigresend: resending signal %lu\n", ARG1);
5364 /* Handle SIGKILL specially. */
5365 if (ARG1 == VKI_SIGKILL && ML_(do_sigkill)(tid, -1)) {
5366 SET_STATUS_Success(0);
5367 return;
5370 /* Ask to handle this syscall via the slow route, since that's the only one
5371 that sets tst->status to VgTs_WaitSys. If the result of doing the
5372 syscall is an immediate run of async_signalhandler() in m_signals.c,
5373 then we need the thread to be properly tidied away. */
5374 *flags |= SfMayBlock;
5377 POST(sys_sigresend)
5379 /* The syscall succeeded, set the requested mask. */
5380 VG_(do_sys_sigprocmask)(tid, VKI_SIG_SETMASK, (vki_sigset_t*)ARG4, NULL);
5382 if (VG_(clo_trace_signals))
5383 VG_(message)(Vg_DebugMsg, "sigresend: resent signal %lu\n", ARG1);
5386 static void mem_priocntlsys_parm_ok(ThreadId tid, Bool pre, Bool reade,
5387 vki_pc_vaparm_t *parm)
5389 if (reade)
5390 return;
5392 if (pre)
5393 PRE_FIELD_WRITE("priocntlsys(parm)", parm->pc_parm);
5394 else
5395 POST_FIELD_WRITE(parm->pc_parm);
5398 static void mem_priocntlsys_parm(ThreadId tid, Bool pre, Bool reade,
5399 const HChar *clname,
5400 vki_pc_vaparm_t *parm)
5402 /* This function is used to handle the PC_SETXPARMS and PC_GETXPARMS
5403 parameters. In the case of PC_SETXPARMS, the code below merely checks
5404 if all parameters are scalar, PRE_MEM_READ() for these parameters is
5405 already done by the PC_SETXPARMS handler in PRE(sys_priocntlsys).
5407 A caller of this function is responsible for checking that clname and
5408 &parm->key can be dereferenced. */
5410 if (VG_STREQ(clname, "RT")) {
5411 switch (parm->pc_key) {
5412 case VKI_RT_KY_PRI:
5413 case VKI_RT_KY_TQSECS:
5414 case VKI_RT_KY_TQNSECS:
5415 case VKI_RT_KY_TQSIG:
5416 /* Scalar values that are stored directly in pc_parm. */
5417 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5418 return;
5421 else if (VG_STREQ(clname, "TS")) {
5422 switch (parm->pc_key) {
5423 case VKI_TS_KY_UPRILIM:
5424 case VKI_TS_KY_UPRI:
5425 /* Scalar values that are stored directly in pc_parm. */
5426 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5427 return;
5430 else if (VG_STREQ(clname, "IA")) {
5431 switch (parm->pc_key) {
5432 case VKI_IA_KY_UPRILIM:
5433 case VKI_IA_KY_UPRI:
5434 case VKI_IA_KY_MODE:
5435 /* Scalar values that are stored directly in pc_parm. */
5436 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5437 return;
5440 else if (VG_STREQ(clname, "FSS")) {
5441 switch (parm->pc_key) {
5442 case VKI_FSS_KY_UPRILIM:
5443 case VKI_FSS_KY_UPRI:
5444 /* Scalar values that are stored directly in pc_parm. */
5445 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5446 return;
5449 else if (VG_STREQ(clname, "FX")) {
5450 switch (parm->pc_key) {
5451 case VKI_FX_KY_UPRILIM:
5452 case VKI_FX_KY_UPRI:
5453 case VKI_FX_KY_TQSECS:
5454 case VKI_FX_KY_TQNSECS:
5455 /* Scalar values that are stored directly in pc_parm. */
5456 mem_priocntlsys_parm_ok(tid, pre, reade, parm);
5457 return;
5460 else {
5461 /* Unknown class. */
5462 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s.",
5463 clname);
5464 /*NOTREACHED*/
5467 /* The class is known but pc_key is unknown. */
5468 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s "
5469 "and pc_key=%d.", clname, parm->pc_key);
5470 /*NOTREACHED*/
5473 PRE(sys_priocntlsys)
5475 /* long priocntlsys(int pc_version, procset_t *psp, int cmd, caddr_t arg,
5476 caddr_t arg2); */
5478 if (ARG1 != 1) {
5479 /* Only the first version of priocntlsys is supported by the code below.
5481 VG_(unimplemented)("Syswrap of the priocntlsys where pc_version=%lu.",
5482 ARG1);
5483 /*NOTREACHED*/
5486 PRINT("sys_priocntlsys ( %ld, %#lx, %ld, %#lx, %#lx )", SARG1, ARG2, SARG3,
5487 ARG4, ARG5);
5488 PRE_REG_READ5(long, "priocntlsys", int, pc_version, procset_t *, psp,
5489 int, cmd, void *, arg, void *, arg2);
5491 switch (ARG3 /*cmd*/) {
5492 case VKI_PC_GETCID:
5493 if (ARG4) {
5494 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5495 PRE_MEM_RASCIIZ("priocntlsys(clname)", (Addr)info->pc_clname);
5496 /* The next line says that the complete pcinfo_t structure can be
5497 written, but this actually isn't true for pc_clname which is
5498 always only read. */
5499 PRE_MEM_WRITE("priocntlsys(pcinfo)", ARG4, sizeof(vki_pcinfo_t));
5501 break;
5502 case VKI_PC_GETCLINFO:
5503 if (ARG4) {
5504 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5505 PRE_FIELD_READ("priocntlsys(cid)", info->pc_cid);
5506 /* The next line says that the complete pcinfo_t structure can be
5507 written, but this actually isn't true for pc_cid which is
5508 always only read. */
5509 PRE_MEM_WRITE("priocntlsys(pcinfo)", ARG4, sizeof(vki_pcinfo_t));
5511 break;
5512 case VKI_PC_SETPARMS:
5513 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5514 /* The next line says that the complete pcparms_t structure is read
5515 which is never actually true (we are too pessimistic here).
5516 Unfortunately we can't do better because we don't know what
5517 process class is involved. */
5518 PRE_MEM_READ("priocntlsys(parms)", ARG4, sizeof(vki_pcparms_t));
5519 break;
5520 case VKI_PC_GETPARMS:
5521 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5522 PRE_MEM_WRITE("priocntlsys(parms)", ARG4, sizeof(vki_pcparms_t));
5523 break;
5524 case VKI_PC_GETPRIRANGE:
5526 vki_pcpri_t *pcpri = (vki_pcpri_t*)ARG4;
5527 PRE_FIELD_READ("priocntlsys(cid)", pcpri->pc_cid);
5529 PRE_MEM_WRITE("priocntlsys(pri)", ARG4, sizeof(vki_pcpri_t));
5530 break;
5531 case VKI_PC_DONICE:
5532 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5534 vki_pcnice_t *nicee = (vki_pcnice_t*)ARG4;
5535 PRE_FIELD_READ("priocntlsys(op)", nicee->pc_op);
5536 if (ML_(safe_to_deref)(&nicee->pc_op, sizeof(nicee->pc_op))) {
5537 switch (nicee->pc_op) {
5538 case VKI_PC_GETNICE:
5539 PRE_FIELD_WRITE("priocntlsys(val)", nicee->pc_val);
5540 break;
5541 case VKI_PC_SETNICE:
5542 PRE_FIELD_READ("priocntlsys(val)", nicee->pc_val);
5543 break;
5544 default:
5545 VG_(unimplemented)("Syswrap of the priocntlsys call where "
5546 "cmd=PC_DONICE and pc_op=%d", nicee->pc_op);
5547 /*NOTREACHED*/
5548 break;
5552 break;
5553 case VKI_PC_SETXPARMS:
5554 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5555 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5556 if (ARG5) {
5557 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5558 PRE_FIELD_READ("priocntlsys(vaparmscnt)", parms->pc_vaparmscnt);
5559 if (ML_(safe_to_deref)(&parms->pc_vaparmscnt,
5560 sizeof(parms->pc_vaparmscnt))) {
5561 vki_uint_t i;
5562 PRE_MEM_READ("priocntlsys(parms)", (Addr)parms->pc_parms,
5563 parms->pc_vaparmscnt * sizeof(parms->pc_parms[0]));
5564 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5565 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5566 if (ML_(safe_to_deref)(parm, sizeof(*parm)) &&
5567 ML_(safe_to_deref)((void*)ARG4, 1))
5568 mem_priocntlsys_parm(tid, True /*pre*/, True /*read*/,
5569 (HChar*)ARG4, parm);
5573 break;
5574 case VKI_PC_GETXPARMS:
5575 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5576 if (ARG4)
5577 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5578 if (ARG5) {
5579 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5580 PRE_FIELD_READ("priocntlsys(vaparmscnt)", parms->pc_vaparmscnt);
5581 if (ML_(safe_to_deref)(&parms->pc_vaparmscnt,
5582 sizeof(parms->pc_vaparmscnt))) {
5583 vki_uint_t i;
5584 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5585 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5586 PRE_MEM_READ("priocntlsys(parms)", (Addr)&parm->pc_key,
5587 parms->pc_vaparmscnt * sizeof(parm->pc_key));
5588 if (ML_(safe_to_deref)(&parm->pc_key,
5589 sizeof(parm->pc_key))) {
5590 /* First handle PC_KY_CLNAME, then class specific keys.
5591 Note that PC_KY_CLNAME can be used only with
5592 ARG4==NULL && parms->pc_vaparmscnt==1. We are not so
5593 strict here and handle this special case as a regular
5594 one which makes the code simpler. */
5595 if (parm->pc_key == VKI_PC_KY_CLNAME)
5596 PRE_MEM_WRITE("priocntlsys(clname)", parm->pc_parm,
5597 VKI_PC_CLNMSZ);
5598 else if (ARG4 && ML_(safe_to_deref)((void*)ARG4, 1))
5599 mem_priocntlsys_parm(tid, True /*pre*/,
5600 False /*read*/, (HChar*)ARG4,
5601 parm);
5606 break;
5607 case VKI_PC_SETDFLCL:
5608 PRE_MEM_RASCIIZ("priocntlsys(clname)", ARG4);
5609 break;
5610 case VKI_PC_GETDFLCL:
5611 if (ARG4) {
5612 /* GETDFLCL writes to the ARG4 buffer only if ARG4 isn't NULL. Also
5613 note that if ARG4 is NULL then the syscall succeeds. */
5614 PRE_MEM_WRITE("priocntlsys(clname)", ARG4, VKI_PC_CLNMSZ);
5616 break;
5617 case VKI_PC_DOPRIO:
5618 PRE_MEM_READ("priocntlsys(psp)", ARG2, sizeof(vki_procset_t));
5620 vki_pcprio_t *prio = (vki_pcprio_t*)ARG4;
5621 PRE_FIELD_READ("priocntlsys(op)", prio->pc_op);
5622 if (ML_(safe_to_deref)(&prio->pc_op, sizeof(prio->pc_op))) {
5623 switch (prio->pc_op) {
5624 case VKI_PC_GETPRIO:
5625 PRE_FIELD_WRITE("priocntlsys(cid)", prio->pc_cid);
5626 PRE_FIELD_WRITE("priocntlsys(val)", prio->pc_val);
5627 break;
5628 case VKI_PC_SETPRIO:
5629 PRE_FIELD_READ("priocntlsys(cid)", prio->pc_cid);
5630 PRE_FIELD_READ("priocntlsys(val)", prio->pc_val);
5631 break;
5632 default:
5633 VG_(unimplemented)("Syswrap of the priocntlsys call where "
5634 "cmd=PC_DOPRIO and pc_op=%d", prio->pc_op);
5635 /*NOTREACHED*/
5636 break;
5640 break;
5641 case VKI_PC_ADMIN:
5642 default:
5643 VG_(unimplemented)("Syswrap of the priocntlsys call with cmd %ld.", SARG3);
5644 /*NOTREACHED*/
5645 break;
5649 static void post_mem_write_priocntlsys_clinfo(ThreadId tid,
5650 const HChar *clname, Addr clinfo)
5652 if (VG_STREQ(clname, "RT"))
5653 POST_MEM_WRITE(clinfo, sizeof(vki_rtinfo_t));
5654 else if (VG_STREQ(clname, "TS"))
5655 POST_MEM_WRITE(clinfo, sizeof(vki_tsinfo_t));
5656 else if (VG_STREQ(clname, "IA"))
5657 POST_MEM_WRITE(clinfo, sizeof(vki_iainfo_t));
5658 else if (VG_STREQ(clname, "FSS"))
5659 POST_MEM_WRITE(clinfo, sizeof(vki_fssinfo_t));
5660 else if (VG_STREQ(clname, "FX"))
5661 POST_MEM_WRITE(clinfo, sizeof(vki_fxinfo_t));
5662 else if (VG_STREQ(clname, "SDC")) {
5663 /* Relax. */
5665 else {
5666 VG_(unimplemented)("Syswrap of the priocntlsys call where clname=%s.",
5667 clname);
5668 /*NOTREACHED*/
5672 POST(sys_priocntlsys)
5674 switch (ARG3 /*cmd*/) {
5675 case VKI_PC_GETCID:
5676 if (ARG4) {
5677 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5678 POST_FIELD_WRITE(info->pc_cid);
5679 post_mem_write_priocntlsys_clinfo(tid, info->pc_clname,
5680 (Addr)&info->pc_clinfo);
5682 break;
5683 case VKI_PC_GETCLINFO:
5684 if (ARG4) {
5685 vki_pcinfo_t *info = (vki_pcinfo_t*)ARG4;
5686 POST_MEM_WRITE((Addr)info->pc_clname,
5687 VG_(strlen)((HChar*)info->pc_clname) + 1);
5688 post_mem_write_priocntlsys_clinfo(tid, info->pc_clname,
5689 (Addr)&info->pc_clinfo);
5691 break;
5692 case VKI_PC_SETPARMS:
5693 /* Relax. */
5694 break;
5695 case VKI_PC_GETPARMS:
5696 /* The next line says that the complete pcparms_t structure is
5697 written which is never actually true (we are too optimistic here).
5698 Unfortunately we can't do better because we don't know what
5699 process class is involved. */
5700 POST_MEM_WRITE(ARG4, sizeof(vki_pcparms_t));
5701 break;
5702 case VKI_PC_GETPRIRANGE:
5703 POST_MEM_WRITE(ARG4, sizeof(vki_pcpri_t));
5704 break;
5705 case VKI_PC_DONICE:
5707 vki_pcnice_t *nicee = (vki_pcnice_t*)ARG4;
5708 if (nicee->pc_op == VKI_PC_GETNICE)
5709 POST_FIELD_WRITE(nicee->pc_val);
5711 break;
5712 case VKI_PC_SETXPARMS:
5713 /* Relax. */
5714 break;
5715 case VKI_PC_GETXPARMS:
5717 vki_pc_vaparms_t *parms = (vki_pc_vaparms_t*)ARG5;
5718 vki_uint_t i;
5719 for (i = 0; i < parms->pc_vaparmscnt; i++) {
5720 vki_pc_vaparm_t *parm = &parms->pc_parms[i];
5721 if (parm->pc_key == VKI_PC_KY_CLNAME)
5722 POST_MEM_WRITE(parm->pc_parm,
5723 VG_(strlen)((HChar*)(Addr)parm->pc_parm) + 1);
5724 else if (ARG4)
5725 mem_priocntlsys_parm(tid, False /*pre*/, False /*read*/,
5726 (HChar*)ARG4, parm);
5729 break;
5730 case VKI_PC_SETDFLCL:
5731 /* Relax. */
5732 break;
5733 case VKI_PC_GETDFLCL:
5734 if (ARG4)
5735 POST_MEM_WRITE(ARG4, VG_(strlen)((HChar*)ARG4) + 1);
5736 break;
5737 case VKI_PC_DOPRIO:
5739 vki_pcprio_t *prio = (vki_pcprio_t*)ARG4;
5740 if (prio->pc_op == VKI_PC_GETPRIO) {
5741 POST_FIELD_WRITE(prio->pc_cid);
5742 POST_FIELD_WRITE(prio->pc_val);
5745 break;
5746 case VKI_PC_ADMIN:
5747 default:
5748 vg_assert(0);
5749 break;
5753 PRE(sys_pathconf)
5755 /* long pathconf(const char *path, int name); */
5756 PRINT("sys_pathconf ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
5757 PRE_REG_READ2(long, "pathconf", const char *, path, int, name);
5758 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
5761 PRE(sys_mmap)
5763 /* void *mmap(void *addr, size_t len, int prot, int flags,
5764 int fildes, off_t off); */
5765 SysRes r;
5766 OffT offset;
5768 /* Stay sane. */
5769 vg_assert(VKI_PAGE_SIZE == 4096);
5770 vg_assert(sizeof(offset) == sizeof(ARG6));
5772 PRINT("sys_mmap ( %#lx, %#lx, %#lx, %#lx, %ld, %#lx )",
5773 ARG1, ARG2, ARG3, ARG4, SARG5, ARG6);
5774 PRE_REG_READ6(long, "mmap", void *, start, vki_size_t, length,
5775 int, prot, int, flags, int, fd, vki_off_t, offset);
5777 /* Make sure that if off < 0 then it's passed correctly to the generic mmap
5778 wraper. */
5779 offset = *(OffT*)&ARG6;
5781 r = ML_(generic_PRE_sys_mmap)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, offset);
5782 SET_STATUS_from_SysRes(r);
5785 #if defined(SOLARIS_UUIDSYS_SYSCALL)
5786 PRE(sys_uuidsys)
5788 /* int uuidsys(struct uuid *uuid); */
5789 PRINT("sys_uuidsys ( %#lx )", ARG1);
5790 PRE_REG_READ1(long, "uuidsys", struct vki_uuid *, uuid);
5791 PRE_MEM_WRITE("uuidsys(uuid)", ARG1, sizeof(struct vki_uuid));
5794 POST(sys_uuidsys)
5796 POST_MEM_WRITE(ARG1, sizeof(struct vki_uuid));
5798 #endif /* SOLARIS_UUIDSYS_SYSCALL */
5800 /* Syscall mmapobj emulation. Processes ELF program headers
5801 and maps them into correct place in memory. Not an easy task, though.
5802 ELF program header of PT_LOAD/PT_SUNWBSS type specifies:
5803 o p_vaddr - actually a memory offset
5804 o p_memsz - total segment size, including text, data and BSS
5805 o p_filesz - file-based segment size mapping (includes only text and data);
5806 p_memsz - p_filesz is the size of BSS
5807 o p_offset - offset into the ELF file where the file-based mapping starts
5809 Several problematic areas to cover here:
5810 1. p_offset can contain a value which is not page-aligned. In that case
5811 we mmap a part of the file prior to p_offset to make the start address
5812 page-aligned.
5813 2. Partially unused page after the file-based mapping must be zeroed.
5814 3. The first mapping is flagged with MR_HDR_ELF and needs to contain
5815 the ELF header. This information is used and verified by the dynamic
5816 linker (ld.so.1). */
5817 static SysRes mmapobj_process_phdrs(ThreadId tid, Int fd,
5818 vki_mmapobj_result_t *storage,
5819 vki_uint_t *elements,
5820 const VKI_ESZ(Ehdr) *ehdr,
5821 const VKI_ESZ(Phdr) *phdrs)
5823 #define ADVANCE_PHDR(ehdr, phdr) \
5824 (const VKI_ESZ(Phdr) *) ((const HChar *) (phdr) + (ehdr)->e_phentsize)
5826 SysRes res;
5827 Int i;
5828 Int first_segment_idx = -1;
5829 UInt idx;
5830 UInt segments = 0; /* loadable segments */
5831 Addr start_addr = 0;
5832 Addr end_addr = 0;
5833 Addr elfbrk = 0;
5834 SizeT max_align = VKI_PAGE_SIZE;
5836 /* 1. First pass over phdrs - determine number, span and max alignment. */
5837 const VKI_ESZ(Phdr) *phdr = phdrs;
5838 for (idx = 0; idx < ehdr->e_phnum; idx++, phdr = ADVANCE_PHDR(ehdr, phdr)) {
5839 /* Skip this header if no memory is requested. */
5840 if (phdr->p_memsz == 0)
5841 continue;
5843 if ((phdr->p_type == VKI_PT_LOAD) || (phdr->p_type == VKI_PT_SUNWBSS)) {
5844 Off64T offset = 0;
5846 if (VG_(clo_trace_syscalls))
5847 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: "
5848 "program header #%u: addr=%#lx type=%#lx "
5849 "prot=%#lx memsz=%#lx filesz=%#lx file "
5850 "offset=%#lx\n", idx, phdr->p_vaddr,
5851 (UWord) phdr->p_type, (UWord) phdr->p_flags,
5852 phdr->p_memsz, phdr->p_filesz, phdr->p_offset);
5854 if (segments == 0) {
5855 first_segment_idx = idx;
5857 if (phdr->p_filesz == 0) {
5858 VG_(unimplemented)("Syswrap of the mmapobj call with the first "
5859 "loadable ELF program header specifying "
5860 "p_filesz == 0");
5861 /*NOTREACHED*/
5862 return res;
5865 /* Address of the first segment must be either NULL or within the
5866 first page. */
5867 if ((ehdr->e_type == VKI_ET_DYN) &&
5868 ((phdr->p_vaddr & VKI_PAGEMASK) != 0)) {
5869 if (VG_(clo_trace_syscalls))
5870 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5871 "ELF program header #%u does not land on "
5872 "the first page (vaddr=%#lx)\n", idx,
5873 phdr->p_vaddr);
5874 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5877 start_addr = phdr->p_vaddr;
5878 /* The first segment is mapped from the beginning of the file (to
5879 include also the ELF header), so include this memory as well.
5880 Later on we flag this mapping with MR_HDR_ELF. */
5881 offset = phdr->p_offset;
5884 if (phdr->p_align > 1) {
5885 if ((phdr->p_vaddr % phdr->p_align) !=
5886 (phdr->p_offset % phdr->p_align)) {
5887 if (VG_(clo_trace_syscalls))
5888 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5889 "ELF program header #%u does not have "
5890 "congruent offset and vaddr (vaddr=%#lx "
5891 "file offset=%#lx align=%#lx)\n", idx,
5892 phdr->p_vaddr, phdr->p_offset,
5893 phdr->p_align);
5894 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5898 if (phdr->p_vaddr < end_addr) {
5899 if (VG_(clo_trace_syscalls))
5900 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5901 "ELF program header #%u specifies overlaping "
5902 "address (vaddr=%#lx end_addr=%#lx)\n",
5903 idx, phdr->p_vaddr, end_addr);
5904 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5907 end_addr = elfbrk = phdr->p_vaddr + phdr->p_memsz + offset;
5908 end_addr = VG_PGROUNDUP(end_addr);
5909 if (phdr->p_align > max_align) {
5910 max_align = phdr->p_align;
5913 segments += 1;
5917 /* Alignment check - it should be power of two. */
5918 if ((max_align & (max_align - 1)) != 0) {
5919 if (VG_(clo_trace_syscalls))
5920 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: alignment "
5921 "is not a power of 2 (%#lx)\n", max_align);
5922 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5924 vg_assert(max_align >= VKI_PAGE_SIZE);
5926 #if defined(VGP_x86_solaris)
5927 if (max_align > VKI_UINT_MAX) {
5928 if (VG_(clo_trace_syscalls))
5929 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: alignment "
5930 "for 32-bit ELF is >32-bits (%#lx)\n", max_align);
5931 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5933 #endif /* VGP_x86_solaris */
5935 if (segments == 0) {
5936 if (VG_(clo_trace_syscalls))
5937 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: nothing "
5938 "to map (0 loadable segments)");
5939 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5942 vg_assert(end_addr >= start_addr);
5943 SizeT span = end_addr - start_addr;
5944 if (span == 0) {
5945 if (VG_(clo_trace_syscalls))
5946 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: nothing "
5947 "to map (%u loadable segments spanning 0 bytes)\n",
5948 segments);
5949 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
5951 vg_assert(first_segment_idx >= 0);
5953 if (segments > *elements) {
5954 if (VG_(clo_trace_syscalls))
5955 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: too many "
5956 "segments (%u)\n", segments);
5957 return VG_(mk_SysRes_Error)(VKI_E2BIG);
5960 if (VG_(clo_trace_syscalls))
5961 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: there "
5962 "are %u loadable segments spanning %#lx bytes; max "
5963 "align is %#lx\n", segments, span, max_align);
5965 /* Now get the aspacemgr oraculum advisory.
5966 Later on we mmap file-based and BSS mappings into this address space area
5967 as required and leave the holes unmapped. */
5968 if (ehdr->e_type == VKI_ET_DYN) {
5969 MapRequest mreq = {MAlign, max_align, span};
5970 Bool ok;
5971 start_addr = VG_(am_get_advisory)(&mreq, True /* forClient */, &ok);
5972 if (!ok) {
5973 if (VG_(clo_trace_syscalls))
5974 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
5975 "failed to reserve address space of %#lx bytes "
5976 "with alignment %#lx\n", span, max_align);
5977 return VG_(mk_SysRes_Error)(VKI_ENOMEM);
5979 vg_assert(VG_ROUNDUP(start_addr, max_align) == start_addr);
5981 if (VG_(clo_trace_syscalls))
5982 VG_(debugLog)(2, "syswrap-solaris", "PRE(sys_mmapobj): address space "
5983 "reserved at: vaddr=%#lx size=%#lx\n",
5984 start_addr, span);
5985 } else {
5986 vg_assert(ehdr->e_type == VKI_ET_EXEC);
5987 /* ET_EXEC uses fixed mappings. Will be checked when processing phdrs. */
5990 /* This is an utterly ugly hack, the aspacemgr assumes that only one
5991 segment is added at the time. However we add here multiple segments so
5992 AM_SANITY_CHECK inside the aspacemgr can easily fail. We want to
5993 prevent that thus we disable these checks. The scheduler will check the
5994 aspacemgr sanity after the syscall. */
5995 UInt sanity_level = VG_(clo_sanity_level);
5996 VG_(clo_sanity_level) = 1;
5998 /* 2. Second pass over phdrs - map the program headers and fill in
5999 the mmapobj_result_t array. */
6000 phdr = phdrs;
6001 *elements = 0;
6002 for (idx = 0; idx < ehdr->e_phnum; idx++, phdr = ADVANCE_PHDR(ehdr, phdr)) {
6003 /* Skip this header if no memory is requested. */
6004 if (phdr->p_memsz == 0)
6005 continue;
6007 if ((phdr->p_type == VKI_PT_LOAD) || (phdr->p_type == VKI_PT_SUNWBSS)) {
6008 UInt prot = 0;
6009 if (phdr->p_flags & VKI_PF_R)
6010 prot |= VKI_PROT_READ;
6011 if (phdr->p_flags & VKI_PF_W)
6012 prot |= VKI_PROT_WRITE;
6013 if (phdr->p_flags & VKI_PF_X)
6014 prot |= VKI_PROT_EXEC;
6016 vki_mmapobj_result_t *mrp = &storage[*elements];
6017 mrp->mr_msize = phdr->p_memsz;
6018 mrp->mr_fsize = phdr->p_filesz;
6019 mrp->mr_offset = 0;
6020 mrp->mr_prot = prot;
6021 mrp->mr_flags = 0;
6022 Off64T file_offset = phdr->p_offset;
6023 if (idx == first_segment_idx) {
6024 mrp->mr_flags = VKI_MR_HDR_ELF;
6025 if (ehdr->e_type == VKI_ET_DYN) {
6026 if (phdr->p_offset > 0) {
6027 /* Include the ELF header into the first segment.
6028 This means we ignore p_offset from the program header
6029 and map from file offset 0. */
6030 mrp->mr_msize += phdr->p_offset;
6031 mrp->mr_fsize += phdr->p_offset;
6032 file_offset = 0;
6034 } else {
6035 vg_assert(ehdr->e_type == VKI_ET_EXEC);
6036 start_addr = phdr->p_vaddr;
6040 /* p_vaddr is absolute for ET_EXEC, and relative for ET_DYN. */
6041 mrp->mr_addr = (vki_caddr_t) phdr->p_vaddr;
6042 if (ehdr->e_type == VKI_ET_DYN) {
6043 mrp->mr_addr += start_addr;
6046 SizeT page_offset = (Addr) mrp->mr_addr & VKI_PAGEOFFSET;
6047 if (page_offset > 0) {
6048 vg_assert(file_offset >= page_offset);
6049 /* Mapping address does not start at the beginning of a page.
6050 Therefore include some bytes before to make it page aligned. */
6051 mrp->mr_addr -= page_offset;
6052 mrp->mr_msize += page_offset;
6053 mrp->mr_offset = page_offset;
6054 file_offset -= page_offset;
6056 SizeT file_size = mrp->mr_fsize + mrp->mr_offset;
6057 if (VG_(clo_trace_syscalls))
6058 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_process_phdrs: "
6059 "mmapobj result #%u: addr=%#lx msize=%#lx "
6060 "fsize=%#lx mr_offset=%#lx prot=%#x flags=%#x\n",
6061 *elements, (Addr) mrp->mr_addr,
6062 (UWord) mrp->mr_msize, (UWord) mrp->mr_fsize,
6063 (UWord) mrp->mr_offset, mrp->mr_prot,
6064 mrp->mr_flags);
6066 UInt flags = VKI_MAP_PRIVATE | VKI_MAP_FIXED;
6067 if ((mrp->mr_prot & (VKI_PROT_WRITE | VKI_PROT_EXEC)) ==
6068 VKI_PROT_EXEC) {
6069 flags |= VKI_MAP_TEXT;
6070 } else {
6071 flags |= VKI_MAP_INITDATA;
6074 /* Determine if there will be partially unused page after file-based
6075 mapping. If so, then we need to zero it explicitly afterwards. */
6076 Addr mapping_end = (Addr) mrp->mr_addr + file_size;
6077 SizeT zeroed_size = VG_PGROUNDUP(mapping_end) - mapping_end;
6078 Bool mprotect_needed = False;
6079 if ((zeroed_size > 0) && ((prot & VKI_PROT_WRITE) == 0)) {
6080 prot |= VKI_PROT_WRITE;
6081 mprotect_needed = True;
6084 if (ehdr->e_type == VKI_ET_EXEC) {
6085 /* Now check if the requested address space is available. */
6086 if (!VG_(am_is_free_or_resvn)((Addr) mrp->mr_addr, mrp->mr_msize)) {
6087 if (VG_(clo_trace_syscalls))
6088 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6089 "requested segment at %#lx with size of "
6090 "%#lx bytes is not available\n",
6091 (Addr) mrp->mr_addr, (UWord) mrp->mr_msize);
6092 res = VG_(mk_SysRes_Error)(VKI_EADDRINUSE);
6093 goto mmap_error;
6097 if (file_size > 0) {
6098 res = VG_(am_mmap_file_fixed_client_flags)((Addr) mrp->mr_addr,
6099 file_size, prot, flags, fd, file_offset);
6100 if (sr_isError(res)) {
6101 if (VG_(clo_trace_syscalls))
6102 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6103 "mmap failed: addr=%#lx size=%#lx prot=%#x "
6104 "flags=%#x fd=%d file offset=%#llx\n",
6105 (Addr) mrp->mr_addr, file_size,
6106 prot, flags, fd, (unsigned long long)file_offset);
6107 goto mmap_error;
6110 VG_(debugLog)(1, "syswrap-solaris", "PRE(sys_mmapobj): new "
6111 "segment: vaddr=%#lx size=%#lx prot=%#x "
6112 "flags=%#x fd=%d file offset=%#llx\n",
6113 (Addr) mrp->mr_addr, file_size, mrp->mr_prot,
6114 flags, fd, (unsigned long long)file_offset);
6117 if (zeroed_size > 0) {
6118 /* Now zero out the end of partially used page. */
6119 VG_(memset)((void *) mapping_end, 0, zeroed_size);
6120 if (mprotect_needed) {
6121 prot &= ~VKI_PROT_WRITE;
6122 res = VG_(do_syscall3)(SYS_mprotect, (Addr) mrp->mr_addr,
6123 file_size, prot);
6124 if (sr_isError(res)) {
6125 if (VG_(clo_trace_syscalls))
6126 VG_(debugLog)(3, "syswrap-solaris",
6127 "mmapobj_process_phdrs: mprotect failed: "
6128 "addr=%#lx size=%#lx prot=%#x",
6129 (Addr) mrp->mr_addr, file_size, prot);
6130 /* Mapping for this segment was already established. */
6131 idx += 1;
6132 goto mmap_error;
6137 if (file_size > 0) {
6138 ML_(notify_core_and_tool_of_mmap)((Addr) mrp->mr_addr, file_size,
6139 prot, flags, fd, file_offset);
6142 /* Page(s) after the mapping backed up by the file are part of BSS.
6143 They need to be mmap'ed over with correct flags and will be
6144 implicitly zeroed. */
6145 mapping_end = VG_PGROUNDUP(mrp->mr_addr + mrp->mr_msize);
6146 Addr page_end = VG_PGROUNDUP(mrp->mr_addr + file_size);
6147 vg_assert(mapping_end >= page_end);
6148 zeroed_size = mapping_end - page_end;
6149 if (zeroed_size > 0) {
6150 flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS;
6151 res = VG_(am_mmap_anon_fixed_client)(page_end, zeroed_size, prot);
6152 if (sr_isError(res)) {
6153 if (VG_(clo_trace_syscalls))
6154 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_process_phdrs: "
6155 "mmap_anon failed: addr=%#lx size=%#lx "
6156 "prot=%#x\n", page_end, zeroed_size, prot);
6157 idx += 1; /* mapping for this segment was already established */
6158 goto mmap_error;
6161 VG_(debugLog)(1, "syswrap-solaris", "PRE(sys_mmapobj): new "
6162 "anonymous segment (BSS): vaddr=%#lx size=%#lx "
6163 "prot=%#x\n", page_end, zeroed_size, prot);
6164 ML_(notify_core_and_tool_of_mmap)(page_end, zeroed_size,
6165 prot, flags, -1, 0);
6168 VG_(di_notify_mmap)((Addr) mrp->mr_addr, False /*allow_SkFileV*/, fd);
6170 *elements += 1;
6171 vg_assert(*elements <= segments);
6175 if ((ehdr->e_type == VKI_ET_EXEC) && (!brk_segment_established)) {
6176 vg_assert(VG_(brk_base) == VG_(brk_limit));
6177 vg_assert(VG_(brk_base) == -1);
6178 VG_(brk_base) = VG_(brk_limit) = elfbrk;
6180 if (!VG_(setup_client_dataseg)()) {
6181 VG_(umsg)("Cannot map memory to initialize brk segment in thread #%u "
6182 "at %#lx\n", tid, VG_(brk_base));
6183 res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
6184 goto mmap_error;
6187 VG_(track_client_dataseg)(tid);
6190 /* Restore VG_(clo_sanity_level). The scheduler will perform the aspacemgr
6191 sanity check after the syscall. */
6192 VG_(clo_sanity_level) = sanity_level;
6194 return VG_(mk_SysRes_Success)(0);
6196 mmap_error:
6197 for (i = idx - 1; i > 0; i--) {
6198 Bool discard_translations;
6199 Addr addr = (Addr) storage[i].mr_addr;
6201 VG_(am_munmap_client)(&discard_translations, addr, storage[i].mr_msize);
6202 ML_(notify_core_and_tool_of_munmap)(addr, storage[i].mr_msize);
6204 *elements = 0;
6205 return res;
6207 #undef ADVANCE_PHDR
6210 static SysRes mmapobj_interpret(ThreadId tid, Int fd,
6211 vki_mmapobj_result_t *storage,
6212 vki_uint_t *elements)
6214 SysRes res;
6216 struct vg_stat stats;
6217 if (VG_(fstat)(fd, &stats) != 0) {
6218 return VG_(mk_SysRes_Error)(VKI_EBADF);
6221 if (stats.size < sizeof(VKI_ESZ(Ehdr))) {
6222 if (VG_(clo_trace_syscalls))
6223 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: insufficient "
6224 "file size (%lld)\n", stats.size);
6225 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6228 /* Align the header buffer appropriately. */
6229 vki_ulong_t lheader[sizeof(VKI_ESZ(Ehdr)) / sizeof(vki_ulong_t) + 1];
6230 HChar *header = (HChar *) &lheader;
6232 res = VG_(pread)(fd, header, sizeof(VKI_ESZ(Ehdr)), 0);
6233 if (sr_isError(res)) {
6234 if (VG_(clo_trace_syscalls))
6235 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6236 "header failed\n");
6237 return res;
6238 } else if (sr_Res(res) != sizeof(VKI_ESZ(Ehdr))) {
6239 if (VG_(clo_trace_syscalls))
6240 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6241 "header failed - only %lu bytes out of %lu\n",
6242 sr_Res(res), (UWord) sizeof(VKI_ESZ(Ehdr)));
6243 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6246 /* Verify file type is ELF. */
6247 if ((header[VKI_EI_MAG0] != VKI_ELFMAG0) ||
6248 (header[VKI_EI_MAG1] != VKI_ELFMAG1) ||
6249 (header[VKI_EI_MAG2] != VKI_ELFMAG2) ||
6250 (header[VKI_EI_MAG3] != VKI_ELFMAG3)) {
6251 if (VG_(clo_trace_syscalls))
6252 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF header "
6253 "missing magic\n");
6254 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6257 if (header[VKI_EI_CLASS] != VG_ELF_CLASS) {
6258 if (VG_(clo_trace_syscalls))
6259 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF class "
6260 "mismatch (%d vs %d)\n", header[VKI_EI_CLASS],
6261 VG_ELF_CLASS);
6262 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6265 VKI_ESZ(Ehdr) *ehdr = (VKI_ESZ(Ehdr) *) header;
6266 if ((ehdr->e_type != VKI_ET_EXEC) && (ehdr->e_type != VKI_ET_DYN)) {
6267 VG_(unimplemented)("Syswrap of the mmapobj call with ELF type %u.",
6268 ehdr->e_type);
6269 /*NOTREACHED*/
6270 return res;
6273 if (ehdr->e_phnum == VKI_PN_XNUM) {
6274 VG_(unimplemented)("Syswrap of the mmapobj call with number of ELF "
6275 "program headers == PN_XNUM");
6276 /*NOTREACHED*/
6277 return res;
6280 /* Check alignment. */
6281 #if defined(VGP_x86_solaris)
6282 if (!VG_IS_4_ALIGNED(ehdr->e_phentsize)) {
6283 #elif defined(VGP_amd64_solaris)
6284 if (!VG_IS_8_ALIGNED(ehdr->e_phentsize)) {
6285 #else
6286 # error "Unknown platform"
6287 #endif
6288 if (VG_(clo_trace_syscalls))
6289 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: ELF header "
6290 "phentsize not aligned properly (%u)\n",
6291 ehdr->e_phentsize);
6292 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6295 SizeT phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
6296 if (phdrs_size == 0) {
6297 if (VG_(clo_trace_syscalls))
6298 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: no ELF "
6299 "program headers\n");
6300 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6303 VKI_ESZ(Phdr) *phdrs = VG_(malloc)("syswrap.mi.1", phdrs_size);
6304 res = VG_(pread)(fd, phdrs, phdrs_size, ehdr->e_phoff);
6305 if (sr_isError(res)) {
6306 if (VG_(clo_trace_syscalls))
6307 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6308 "program headers failed\n");
6309 VG_(free)(phdrs);
6310 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6311 } else if (sr_Res(res) != phdrs_size) {
6312 if (VG_(clo_trace_syscalls))
6313 VG_(debugLog)(3, "syswrap-solaris", "mmapobj_interpret: read of ELF "
6314 "program headers failed - only %lu bytes out of %lu\n",
6315 sr_Res(res), phdrs_size);
6316 VG_(free)(phdrs);
6317 return VG_(mk_SysRes_Error)(VKI_ENOTSUP);
6320 if (VG_(clo_trace_syscalls))
6321 VG_(debugLog)(2, "syswrap-solaris", "mmapobj_interpret: %u ELF "
6322 "program headers with total size of %lu bytes\n",
6323 ehdr->e_phnum, phdrs_size);
6325 /* Now process the program headers. */
6326 res = mmapobj_process_phdrs(tid, fd, storage, elements, ehdr, phdrs);
6327 VG_(free)(phdrs);
6328 return res;
6331 PRE(sys_mmapobj)
6333 /* int mmapobj(int fd, uint_t flags, mmapobj_result_t *storage,
6334 uint_t *elements, void *arg); */
6335 PRINT("sys_mmapobj ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
6336 ARG4, ARG5);
6337 PRE_REG_READ5(long, "mmapobj", int, fd, vki_uint_t, flags,
6338 mmapobj_result_t *, storage, uint_t *, elements,
6339 void *, arg);
6341 PRE_MEM_READ("mmapobj(elements)", ARG4, sizeof(vki_uint_t));
6342 /*PRE_MEM_WRITE("mmapobj(elements)", ARG4, sizeof(vki_uint_t));*/
6343 if (ML_(safe_to_deref)((void*)ARG4, sizeof(vki_uint_t))) {
6344 vki_uint_t *u = (vki_uint_t*)ARG4;
6345 PRE_MEM_WRITE("mmapobj(storage)", ARG3,
6346 *u * sizeof(vki_mmapobj_result_t));
6349 if (ARG2 & VKI_MMOBJ_PADDING)
6350 PRE_MEM_READ("mmapobj(arg)", ARG5, sizeof(vki_size_t));
6352 /* Be strict. */
6353 if (!ML_(fd_allowed)(ARG1, "mmapobj", tid, False)) {
6354 SET_STATUS_Failure(VKI_EBADF);
6355 return;
6358 /* We cannot advise mmapobj about desired address(es). Unfortunately
6359 kernel places mappings from mmapobj at the end of process address
6360 space, defeating memcheck's optimized fast 2-level array algorithm.
6361 So we need to emulate what mmapobj does in the kernel. */
6363 /* Sanity check on parameters. */
6364 if ((ARG2 & ~VKI_MMOBJ_ALL_FLAGS) != 0) {
6365 SET_STATUS_Failure(VKI_EINVAL);
6366 return;
6369 if (!ML_(safe_to_deref)((void *) ARG4, sizeof(vki_uint_t))) {
6370 SET_STATUS_Failure(VKI_EFAULT);
6371 return;
6373 vki_uint_t *elements = (vki_uint_t *) ARG4;
6375 if (*elements > 0) {
6376 if (!ML_(safe_to_deref)((void *) ARG3,
6377 *elements * sizeof(vki_mmapobj_result_t))) {
6378 SET_STATUS_Failure(VKI_EFAULT);
6379 return;
6383 /* For now, supported is only MMOBJ_INTERPRET and no MMOBJ_PADDING. */
6384 if (ARG2 != VKI_MMOBJ_INTERPRET) {
6385 VG_(unimplemented)("Syswrap of the mmapobj call with flags %lu.", ARG2);
6386 /*NOTREACHED*/
6387 return;
6390 SysRes res = mmapobj_interpret(tid, (Int) ARG1,
6391 (vki_mmapobj_result_t *) ARG3, elements);
6392 SET_STATUS_from_SysRes(res);
6394 if (!sr_isError(res)) {
6395 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
6397 UInt idx;
6398 for (idx = 0; idx < *(vki_uint_t *) ARG4; idx++) {
6399 vki_mmapobj_result_t *mrp = &((vki_mmapobj_result_t *) ARG3)[idx];
6400 POST_FIELD_WRITE(mrp->mr_addr);
6401 POST_FIELD_WRITE(mrp->mr_msize);
6402 POST_FIELD_WRITE(mrp->mr_fsize);
6403 POST_FIELD_WRITE(mrp->mr_prot);
6404 POST_FIELD_WRITE(mrp->mr_flags);
6405 POST_FIELD_WRITE(mrp->mr_offset);
6410 PRE(sys_memcntl)
6412 /* int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg,
6413 int attr, int mask); */
6414 PRINT("sys_memcntl ( %#lx, %#lx, %ld, %#lx, %#lx, %#lx )", ARG1, ARG2,
6415 SARG3, ARG4, ARG5, ARG6);
6416 PRE_REG_READ6(long, "memcntl", void *, addr, vki_size_t, len, int, cmd,
6417 void *, arg, int, attr, int, mask);
6419 if (ARG3 != VKI_MC_LOCKAS && ARG3 != VKI_MC_UNLOCKAS &&
6420 !ML_(valid_client_addr)(ARG1, ARG2, tid, "memcntl")) {
6421 /* MC_LOCKAS and MC_UNLOCKAS work on the complete address space thus we
6422 don't check the address range validity if these commands are
6423 requested. */
6424 SET_STATUS_Failure(VKI_ENOMEM);
6425 return;
6428 if (ARG3 == VKI_MC_HAT_ADVISE)
6429 PRE_MEM_READ("memcntl(arg)", ARG4, sizeof(struct vki_memcntl_mha));
6432 PRE(sys_getpmsg)
6434 /* int getpmsg(int fildes, struct strbuf *ctlptr, struct strbuf *dataptr,
6435 int *bandp, int *flagsp); */
6436 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6437 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6438 *flags |= SfMayBlock;
6439 PRINT("sys_getpmsg ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
6440 ARG4, ARG5);
6441 PRE_REG_READ5(long, "getpmsg", int, fildes, struct vki_strbuf *, ctlptr,
6442 struct vki_strbuf *, dataptr, int *, bandp, int *, flagsp);
6443 if (ctrlptr) {
6444 PRE_FIELD_READ("getpmsg(ctrlptr->maxlen)", ctrlptr->maxlen);
6445 PRE_FIELD_WRITE("getpmsg(ctrlptr->len)", ctrlptr->len);
6446 PRE_FIELD_READ("getpmsg(ctrlptr->buf)", ctrlptr->buf);
6447 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
6448 && ctrlptr->maxlen > 0)
6449 PRE_MEM_WRITE("getpmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
6450 ctrlptr->maxlen);
6452 if (dataptr) {
6453 PRE_FIELD_READ("getpmsg(dataptr->maxlen)", dataptr->maxlen);
6454 PRE_FIELD_WRITE("getpmsg(dataptr->len)", dataptr->len);
6455 PRE_FIELD_READ("getpmsg(dataptr->buf)", dataptr->buf);
6456 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
6457 && dataptr->maxlen > 0)
6458 PRE_MEM_WRITE("getpmsg(dataptr->buf)", (Addr)dataptr->buf,
6459 dataptr->maxlen);
6461 PRE_MEM_READ("getpmsg(bandp)", ARG4, sizeof(int));
6462 /*PRE_MEM_WRITE("getpmsg(bandp)", ARG4, sizeof(int));*/
6463 PRE_MEM_READ("getpmsg(flagsp)", ARG5, sizeof(int));
6464 /*PRE_MEM_WRITE("getpmsg(flagsp)", ARG5, sizeof(int));*/
6466 /* Be strict. */
6467 if (!ML_(fd_allowed)(ARG1, "getpmsg", tid, False))
6468 SET_STATUS_Failure(VKI_EBADF);
6471 POST(sys_getpmsg)
6473 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6474 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6476 if (ctrlptr && ctrlptr->len > 0)
6477 POST_MEM_WRITE((Addr)ctrlptr->buf, ctrlptr->len);
6478 if (dataptr && dataptr->len > 0)
6479 POST_MEM_WRITE((Addr)dataptr->buf, dataptr->len);
6480 POST_MEM_WRITE(ARG4, sizeof(int));
6481 POST_MEM_WRITE(ARG5, sizeof(int));
6484 PRE(sys_putpmsg)
6486 /* int putpmsg(int fildes, const struct strbuf *ctlptr,
6487 const struct strbuf *dataptr, int band, int flags); */
6488 struct vki_strbuf *ctrlptr = (struct vki_strbuf *)ARG2;
6489 struct vki_strbuf *dataptr = (struct vki_strbuf *)ARG3;
6490 *flags |= SfMayBlock;
6491 PRINT("sys_putpmsg ( %ld, %#lx, %#lx, %ld, %ld )", SARG1, ARG2, ARG3, SARG4,
6492 SARG5);
6493 PRE_REG_READ5(long, "putpmsg", int, fildes, struct vki_strbuf *, ctrlptr,
6494 struct vki_strbuf *, dataptr, int, band, int, flags);
6495 if (ctrlptr) {
6496 PRE_FIELD_READ("putpmsg(ctrlptr->len)", ctrlptr->len);
6497 PRE_FIELD_READ("putpmsg(ctrlptr->buf)", ctrlptr->buf);
6498 if (ML_(safe_to_deref)((void*)ARG2, sizeof(struct vki_strbuf))
6499 && ctrlptr->len > 0)
6500 PRE_MEM_READ("putpmsg(ctrlptr->buf)", (Addr)ctrlptr->buf,
6501 ctrlptr->len);
6503 if (dataptr) {
6504 PRE_FIELD_READ("putpmsg(dataptr->len)", dataptr->len);
6505 PRE_FIELD_READ("putpmsg(dataptr->buf)", dataptr->buf);
6506 if (ML_(safe_to_deref)((void*)ARG3, sizeof(struct vki_strbuf))
6507 && dataptr->len > 0)
6508 PRE_MEM_READ("putpmsg(dataptr->buf)", (Addr)dataptr->buf,
6509 dataptr->len);
6512 /* Be strict. */
6513 if (!ML_(fd_allowed)(ARG1, "putpmsg", tid, False))
6514 SET_STATUS_Failure(VKI_EBADF);
6517 #if defined(SOLARIS_OLD_SYSCALLS)
6518 PRE(sys_rename)
6520 /* int rename(const char *from, const char *to); */
6522 *flags |= SfMayBlock;
6523 PRINT("sys_rename ( %#lx(%s), %#lx(%s) )",
6524 ARG1, (HChar *) ARG1, ARG2, (HChar *) ARG2);
6525 PRE_REG_READ2(long, "rename", const char *, from, const char *, to);
6527 PRE_MEM_RASCIIZ("rename(from)", ARG1);
6528 PRE_MEM_RASCIIZ("rename(to)", ARG2);
6530 #endif /* SOLARIS_OLD_SYSCALLS */
6532 PRE(sys_uname)
6534 /* int uname(struct utsname *name); */
6535 PRINT("sys_uname ( %#lx )", ARG1);
6536 PRE_REG_READ1(long, "uname", struct vki_utsname *, name);
6537 PRE_MEM_WRITE("uname(name)", ARG1, sizeof(struct vki_utsname));
6540 POST(sys_uname)
6542 struct vki_utsname *name = (struct vki_utsname *) ARG1;
6543 POST_MEM_WRITE((Addr) name->sysname, VG_(strlen)(name->sysname) + 1);
6544 POST_MEM_WRITE((Addr) name->nodename, VG_(strlen)(name->nodename) + 1);
6545 POST_MEM_WRITE((Addr) name->release, VG_(strlen)(name->release) + 1);
6546 POST_MEM_WRITE((Addr) name->version, VG_(strlen)(name->version) + 1);
6547 POST_MEM_WRITE((Addr) name->machine, VG_(strlen)(name->machine) + 1);
6550 PRE(sys_setegid)
6552 /* int setegid(gid_t egid); */
6553 PRINT("sys_setegid ( %ld )", SARG1);
6554 PRE_REG_READ1(long, "setegid", vki_gid_t, egid);
6557 PRE(sys_sysconfig)
6559 /* long sysconf(int name); */
6560 PRINT("sys_sysconfig ( %ld )", SARG1);
6561 PRE_REG_READ1(long, "sysconf", int, name);
6563 if (ARG1 == VKI_CONFIG_OPEN_FILES)
6564 SET_STATUS_Success(VG_(fd_soft_limit));
6567 PRE(sys_systeminfo)
6569 /* int sysinfo(int command, char *buf, long count); */
6570 PRINT("sys_systeminfo ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
6571 PRE_REG_READ3(long, "sysinfo", int, command, char *, buf, long, count);
6573 switch (ARG1 /*command*/) {
6574 case VKI_SI_SYSNAME:
6575 case VKI_SI_HOSTNAME:
6576 case VKI_SI_RELEASE:
6577 case VKI_SI_VERSION:
6578 case VKI_SI_MACHINE:
6579 case VKI_SI_ARCHITECTURE:
6580 case VKI_SI_HW_SERIAL:
6581 case VKI_SI_HW_PROVIDER:
6582 case VKI_SI_SRPC_DOMAIN:
6583 case VKI_SI_PLATFORM:
6584 case VKI_SI_ISALIST:
6585 case VKI_SI_DHCP_CACHE:
6586 case VKI_SI_ARCHITECTURE_32:
6587 case VKI_SI_ARCHITECTURE_64:
6588 case VKI_SI_ARCHITECTURE_K:
6589 case VKI_SI_ARCHITECTURE_NATIVE:
6590 PRE_MEM_WRITE("sysinfo(buf)", ARG2, ARG3);
6591 break;
6593 case VKI_SI_SET_HOSTNAME:
6594 case VKI_SI_SET_SRCP_DOMAIN:
6595 PRE_MEM_RASCIIZ("sysinfo(buf)", ARG2);
6596 break;
6598 default:
6599 VG_(unimplemented)("Syswrap of the sysinfo call with command %ld.", SARG1);
6600 /*NOTREACHED*/
6601 break;
6605 POST(sys_systeminfo)
6607 if (ARG1 != VKI_SI_SET_HOSTNAME && ARG1 != VKI_SI_SET_SRCP_DOMAIN)
6608 POST_MEM_WRITE(ARG2, MIN(RES, ARG3));
6611 PRE(sys_seteuid)
6613 /* int seteuid(uid_t euid); */
6614 PRINT("sys_seteuid ( %ld )", SARG1);
6615 PRE_REG_READ1(long, "seteuid", vki_uid_t, euid);
6618 PRE(sys_forksys)
6620 /* int64_t forksys(int subcode, int flags); */
6621 Int fds[2];
6622 Int res;
6623 PRINT("sys_forksys ( %ld, %ld )", SARG1, SARG2);
6624 PRE_REG_READ2(long, "forksys", int, subcode, int, flags);
6626 if (ARG1 == 1) {
6627 /* Support for forkall() requires changes to the big lock processing
6628 which are not yet implemented. */
6629 VG_(unimplemented)("Support for forkall().");
6630 /*NOTREACHED*/
6631 return;
6634 if (ARG1 != 0 && ARG1 != 2) {
6635 VG_(unimplemented)("Syswrap of the forksys call where subcode=%ld.",
6636 SARG1);
6637 /*NOTREACHED*/
6640 if (ARG1 == 2) {
6641 /* vfork() is requested. Translate it to a normal fork() but work around
6642 a problem with posix_spawn() which relies on the real vfork()
6643 behaviour. See a description in vg_preloaded.c for details. */
6644 res = VG_(pipe)(fds);
6645 vg_assert(res == 0);
6647 vg_assert(fds[0] != fds[1]);
6649 /* Move to Valgrind fds and set close-on-exec flag on both of them (done
6650 by VG_(safe_fd). */
6651 fds[0] = VG_(safe_fd)(fds[0]);
6652 fds[1] = VG_(safe_fd)(fds[1]);
6653 vg_assert(fds[0] != fds[1]);
6655 vg_assert(VG_(vfork_fildes_addr) != NULL);
6656 vg_assert(*VG_(vfork_fildes_addr) == -1);
6657 *VG_(vfork_fildes_addr) = fds[0];
6660 VG_(do_atfork_pre)(tid);
6661 SET_STATUS_from_SysRes(VG_(do_syscall2)(__NR_forksys, 0, ARG2));
6663 if (!SUCCESS) {
6664 /* vfork */
6665 if (ARG1 == 2) {
6666 VG_(close)(fds[0]);
6667 VG_(close)(fds[1]);
6670 return;
6673 if (RESHI) {
6674 VG_(do_atfork_child)(tid);
6676 /* vfork */
6677 if (ARG1 == 2)
6678 VG_(close)(fds[1]);
6680 # if defined(SOLARIS_PT_SUNDWTRACE_THRP)
6681 /* Kernel can map a new page as a scratch space of the DTrace fasttrap
6682 provider. There is no way we can directly get its address - it's all
6683 private to the kernel. Fish it the slow way. */
6684 Addr addr;
6685 SizeT size;
6686 UInt prot;
6687 Bool found = VG_(am_search_for_new_segment)(&addr, &size, &prot);
6688 if (found) {
6689 VG_(debugLog)(1, "syswrap-solaris", "PRE(forksys), new segment: "
6690 "vaddr=%#lx, size=%#lx, prot=%#x\n", addr, size, prot);
6691 vg_assert(prot == (VKI_PROT_READ | VKI_PROT_EXEC));
6692 vg_assert(size == VKI_PAGE_SIZE);
6693 ML_(notify_core_and_tool_of_mmap)(addr, size, prot, VKI_MAP_ANONYMOUS,
6694 -1, 0);
6696 /* Note: We don't notify the debuginfo reader about this mapping
6697 because there is no debug information stored in this segment. */
6699 # endif /* SOLARIS_PT_SUNDWTRACE_THRP */
6701 else {
6702 VG_(do_atfork_parent)(tid);
6704 /* Print information about the fork. */
6705 PRINT(" fork: process %d created child %d\n", VG_(getpid)(),
6706 (Int)RES);
6708 /* vfork */
6709 if (ARG1 == 2) {
6710 /* Wait for the child to finish (exec or exit). */
6711 UChar w;
6713 VG_(close)(fds[0]);
6715 res = VG_(read)(fds[1], &w, 1);
6716 if (res == 1)
6717 SET_STATUS_Failure(w);
6718 VG_(close)(fds[1]);
6720 *VG_(vfork_fildes_addr) = -1;
6725 #if defined(SOLARIS_GETRANDOM_SYSCALL)
6726 PRE(sys_getrandom)
6728 /* int getrandom(void *buf, size_t buflen, uint_t flags); */
6729 PRINT("sys_getrandom ( %#lx, %lu, %lu )", ARG1, ARG2, ARG3);
6730 PRE_REG_READ3(long, "getrandom", void *, buf, vki_size_t, buflen,
6731 vki_uint_t, flags);
6732 PRE_MEM_WRITE("getrandom(buf)", ARG1, ARG2);
6735 POST(sys_getrandom)
6737 POST_MEM_WRITE(ARG1, RES);
6739 #endif /* SOLARIS_GETRANDOM_SYSCALL */
6741 PRE(sys_sigtimedwait)
6743 /* int sigtimedwait(const sigset_t *set, siginfo_t *info,
6744 const timespec_t *timeout); */
6745 *flags |= SfMayBlock;
6746 PRINT("sys_sigtimedwait ( %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3);
6747 PRE_REG_READ3(long, "sigtimedwait", vki_sigset_t *, set,
6748 vki_siginfo_t *, info, vki_timespec_t *, timeout);
6749 PRE_MEM_READ("sigtimewait(set)", ARG1, sizeof(vki_sigset_t));
6750 if (ARG2)
6751 PRE_MEM_WRITE("sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t));
6752 if (ARG3)
6753 PRE_MEM_READ("sigtimedwait(timeout)", ARG3, sizeof(vki_timespec_t));
6756 POST(sys_sigtimedwait)
6758 if (ARG2)
6759 POST_MEM_WRITE(ARG2, sizeof(vki_siginfo_t));
6762 PRE(sys_yield)
6764 /* void yield(void); */
6765 *flags |= SfMayBlock;
6766 PRINT("sys_yield ( )");
6767 PRE_REG_READ0(long, "yield");
6770 PRE(sys_lwp_sema_post)
6772 /* int lwp_sema_post(lwp_sema_t *sema); */
6773 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6774 *flags |= SfMayBlock;
6775 PRINT("sys_lwp_sema_post ( %#lx )", ARG1);
6776 PRE_REG_READ1(long, "lwp_sema_post", lwp_sema_t *, sema);
6778 PRE_FIELD_READ("lwp_sema_post(sema->type)", sema->vki_sema_type);
6779 PRE_FIELD_READ("lwp_sema_post(sema->count)", sema->vki_sema_count);
6780 /*PRE_FIELD_WRITE("lwp_sema_post(sema->count)", sema->vki_sema_count);*/
6781 PRE_FIELD_READ("lwp_sema_post(sema->waiters)", sema->vki_sema_waiters);
6782 /*PRE_FIELD_WRITE("lwp_sema_post(sema->waiters)", sema->vki_sema_waiters);*/
6785 POST(sys_lwp_sema_post)
6787 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6788 POST_FIELD_WRITE(sema->vki_sema_count);
6789 POST_FIELD_WRITE(sema->vki_sema_waiters);
6792 PRE(sys_lwp_sema_trywait)
6794 /* int lwp_sema_trywait(lwp_sema_t *sema); */
6795 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6796 PRINT("sys_lwp_sema_trywait ( %#lx )", ARG1);
6797 PRE_REG_READ1(long, "lwp_sema_trywait", lwp_sema_t *, sema);
6799 PRE_FIELD_READ("lwp_sema_trywait(sema->type)", sema->vki_sema_type);
6800 PRE_FIELD_READ("lwp_sema_trywait(sema->count)", sema->vki_sema_count);
6801 /*PRE_FIELD_WRITE("lwp_sema_trywait(sema->count)", sema->vki_sema_count);*/
6802 PRE_FIELD_READ("lwp_sema_trywait(sema->waiters)", sema->vki_sema_waiters);
6803 /*PRE_FIELD_WRITE("lwp_sema_trywait(sema->waiters)",
6804 sema->vki_sema_waiters);*/
6807 POST(sys_lwp_sema_trywait)
6809 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
6810 POST_FIELD_WRITE(sema->vki_sema_count);
6811 POST_FIELD_WRITE(sema->vki_sema_waiters);
6814 PRE(sys_lwp_detach)
6816 /* int lwp_detach(id_t lwpid); */
6817 PRINT("sys_lwp_detach ( %ld )", SARG1);
6818 PRE_REG_READ1(long, "lwp_detach", vki_id_t, lwpid);
6821 PRE(sys_modctl)
6823 /* int modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6824 uintptr_t a4, uintptr_t a5); */
6825 *flags |= SfMayBlock;
6827 switch (ARG1 /*cmd*/) {
6828 case VKI_MODLOAD:
6829 /* int modctl_modload(int use_path, char *filename, int *rvp); */
6830 PRINT("sys_modctl ( %ld, %lu, %#lx(%s), %#lx )",
6831 SARG1, ARG2, ARG3, (HChar *) ARG3, ARG4);
6832 PRE_REG_READ4(long, SC2("modctl", "modload"),
6833 int, cmd, int, use_path, char *, filename, int *, rvp);
6834 PRE_MEM_RASCIIZ("modctl(filaneme)", ARG3);
6835 if (ARG4 != 0) {
6836 PRE_MEM_WRITE("modctl(rvp)", ARG4, sizeof(int *));
6838 break;
6839 case VKI_MODUNLOAD:
6840 /* int modctl_modunload(modid_t id); */
6841 PRINT("sys_modctl ( %ld, %ld )", SARG1, SARG2);
6842 PRE_REG_READ2(long, SC2("modctl", "modunload"),
6843 int, cmd, vki_modid_t, id);
6844 break;
6845 case VKI_MODINFO: {
6846 /* int modctl_modinfo(modid_t id, struct modinfo *umodi); */
6847 PRINT("sys_modctl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
6848 PRE_REG_READ3(long, SC2("modctl", "modinfo"),
6849 int, cmd, vki_modid_t, id, struct modinfo *, umodi);
6851 struct vki_modinfo *umodi = (struct vki_modinfo *) ARG3;
6852 PRE_FIELD_READ("modctl(umodi->mi_info)", umodi->mi_info);
6853 PRE_FIELD_READ("modctl(umodi->mi_id)", umodi->mi_id);
6854 PRE_FIELD_READ("modctl(umodi->mi_nextid)", umodi->mi_nextid);
6855 PRE_MEM_WRITE("modctl(umodi)", ARG3, sizeof(struct vki_modinfo));
6856 break;
6859 # if defined(SOLARIS_MODCTL_MODNVL)
6860 case VKI_MODNVL_DEVLINKSYNC:
6861 /* int modnvl_devlinksync(sysnvl_op_t a1, uintptr_t a2, uintptr_t a3,
6862 uintptr_t a4); */
6863 switch (ARG2 /*op*/) {
6865 # if defined(HAVE_SYS_SYSNVL_H)
6866 case VKI_SYSNVL_OP_GET:
6867 PRE_REG_READ5(long, SC3("modctl", "modnvl_devlinksync", "get"),
6868 int, cmd, sysnvl_op_t, a1, char *, bufp,
6869 uint64_t *, buflenp, uint64_t *, genp);
6870 # else
6871 case VKI_MODCTL_NVL_OP_GET:
6872 PRE_REG_READ5(long, SC3("modctl", "modnvl_devlinksync", "get"),
6873 int, cmd, modctl_nvl_op_t, a1, char *, bufp,
6874 uint64_t *, buflenp, uint64_t *, genp);
6875 # endif /* HAVE_SYS_SYSNVL_H */
6877 PRINT("sys_modctl ( %ld, %lu, %#lx, %#lx, %#lx )",
6878 SARG1, ARG2, ARG3, ARG4, ARG5);
6879 PRE_MEM_WRITE("modctl(buflenp)", ARG4, sizeof(vki_uint64_t));
6880 if (ML_(safe_to_deref)((vki_uint64_t *) ARG4, sizeof(vki_uint64_t))) {
6881 if (ARG3 != 0) {
6882 PRE_MEM_WRITE("modctl(bufp)", ARG3, *(vki_uint64_t *) ARG4);
6885 if (ARG5 != 0) {
6886 PRE_MEM_WRITE("modctl(genp)", ARG5, sizeof(vki_uint64_t));
6888 break;
6890 # if defined(HAVE_SYS_SYSNVL_H)
6891 case VKI_SYSNVL_OP_UPDATE:
6892 PRE_REG_READ4(long, SC3("modctl", "modnvl_devlinksync", "update"),
6893 int, cmd, sysnvl_op_t, a1, char *, bufp,
6894 uint64_t *, buflenp);
6895 # else
6896 case VKI_MODCTL_NVL_OP_UPDATE:
6897 PRE_REG_READ4(long, SC3("modctl", "modnvl_devlinksync", "update"),
6898 int, cmd, modctl_nvl_op_t, a1, char *, bufp,
6899 uint64_t *, buflenp);
6900 # endif /* HAVE_SYS_SYSNVL_H */
6902 PRINT("sys_modctl ( %ld, %lu, %#lx, %#lx )", SARG1, ARG2, ARG3, ARG4);
6903 PRE_MEM_READ("modctl(buflenp)", ARG4, sizeof(vki_uint64_t));
6904 if (ML_(safe_to_deref)((vki_uint64_t *) ARG4, sizeof(vki_uint64_t))) {
6905 PRE_MEM_READ("modctl(bufp)", ARG3, *(vki_uint64_t *) ARG4);
6907 break;
6909 default:
6910 VG_(unimplemented)("Syswrap of the modctl call with command "
6911 "MODNVL_DEVLINKSYNC and op %ld.", ARG2);
6912 /*NOTREACHED*/
6913 break;
6915 break;
6917 case VKI_MODDEVINFO_CACHE_TS:
6918 /* int modctl_devinfo_cache_ts(uint64_t *utsp); */
6919 PRINT("sys_modctl ( %ld, %#lx )", SARG1, ARG2);
6920 PRE_REG_READ2(long, SC2("modctl", "moddevinfo_cache_ts"),
6921 int, cmd, uint64_t *, utsp);
6922 PRE_MEM_WRITE("modctl(utsp)", ARG2, sizeof(vki_uint64_t));
6923 break;
6924 # endif /* SOLARIS_MODCTL_MODNVL */
6926 default:
6927 VG_(unimplemented)("Syswrap of the modctl call with command %ld.", SARG1);
6928 /*NOTREACHED*/
6929 break;
6933 POST(sys_modctl)
6935 switch (ARG1 /*cmd*/) {
6936 case VKI_MODLOAD:
6937 if (ARG4 != 0) {
6938 POST_MEM_WRITE(ARG4, sizeof(int *));
6940 break;
6941 case VKI_MODUNLOAD:
6942 break;
6943 case VKI_MODINFO:
6944 POST_MEM_WRITE(ARG3, sizeof(struct vki_modinfo));
6945 break;
6946 # if defined(SOLARIS_MODCTL_MODNVL)
6947 case VKI_MODNVL_DEVLINKSYNC:
6948 switch (ARG2 /*op*/) {
6950 # if defined(HAVE_SYS_SYSNVL_H)
6951 case VKI_SYSNVL_OP_GET:
6952 # else
6953 case VKI_MODCTL_NVL_OP_GET:
6954 # endif /* HAVE_SYS_SYSNVL_H */
6956 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
6957 if (ARG3 != 0) {
6958 POST_MEM_WRITE(ARG3, *(vki_uint64_t *) ARG4);
6960 if (ARG5 != 0) {
6961 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
6963 break;
6965 # if defined(HAVE_SYS_SYSNVL_H)
6966 case VKI_SYSNVL_OP_UPDATE:
6967 # else
6968 case VKI_MODCTL_NVL_OP_UPDATE:
6969 # endif /* HAVE_SYS_SYSNVL_H */
6970 break;
6972 default:
6973 vg_assert(0);
6974 break;
6976 break;
6977 case VKI_MODDEVINFO_CACHE_TS:
6978 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
6979 break;
6980 # endif /* SOLARIS_MODCTL_MODNVL */
6982 default:
6983 vg_assert(0);
6984 break;
6988 PRE(sys_fchroot)
6990 /* int fchroot(int fd); */
6991 PRINT("sys_fchroot ( %ld )", SARG1);
6992 PRE_REG_READ1(long, "fchroot", int, fd);
6994 /* Be strict. */
6995 if (!ML_(fd_allowed)(ARG1, "fchroot", tid, False))
6996 SET_STATUS_Failure(VKI_EBADF);
6999 #if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
7000 PRE(sys_system_stats)
7002 /* void system_stats(int flag); */
7003 PRINT("sys_system_stats ( %ld )", SARG1);
7004 PRE_REG_READ1(void, "system_stats", int, flag);
7006 #endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
7008 PRE(sys_gettimeofday)
7010 /* Kernel: int gettimeofday(struct timeval *tp); */
7011 PRINT("sys_gettimeofday ( %#lx )", ARG1);
7012 PRE_REG_READ1(long, "gettimeofday", struct timeval *, tp);
7013 if (ARG1)
7014 PRE_timeval_WRITE("gettimeofday(tp)", ARG1);
7017 POST(sys_gettimeofday)
7019 if (ARG1)
7020 POST_timeval_WRITE(ARG1);
7023 PRE(sys_lwp_create)
7025 /* int lwp_create(ucontext_t *ucp, int flags, id_t *new_lwp) */
7027 ThreadId ctid;
7028 ThreadState *ptst;
7029 ThreadState *ctst;
7030 Addr stack;
7031 SysRes res;
7032 vki_ucontext_t uc;
7033 Bool tool_informed = False;
7035 PRINT("sys_lwp_create ( %#lx, %lu, %#lx )", ARG1, ARG2, ARG3);
7036 PRE_REG_READ3(long, "lwp_create", ucontext_t *, ucp, int, flags,
7037 id_t *, new_lwp);
7039 if (ARG3 != 0)
7040 PRE_MEM_WRITE("lwp_create(new_lwp)", ARG3, sizeof(vki_id_t));
7042 /* If we can't deref ucontext_t then we can't do anything. */
7043 if (!ML_(safe_to_deref)((void*)ARG1, sizeof(vki_ucontext_t))) {
7044 SET_STATUS_Failure(VKI_EINVAL);
7045 return;
7048 ctid = VG_(alloc_ThreadState)();
7049 ptst = VG_(get_ThreadState)(tid);
7050 ctst = VG_(get_ThreadState)(ctid);
7052 /* Stay sane. */
7053 vg_assert(VG_(is_running_thread)(tid));
7054 vg_assert(VG_(is_valid_tid)(ctid));
7056 stack = ML_(allocstack)(ctid);
7057 if (!stack) {
7058 res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
7059 goto out;
7062 /* First inherit parent's guest state */
7063 ctst->arch.vex = ptst->arch.vex;
7064 ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
7065 ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
7067 /* Set up some values. */
7068 ctst->os_state.parent = tid;
7069 ctst->os_state.threadgroup = ptst->os_state.threadgroup;
7070 ctst->sig_mask = ptst->sig_mask;
7071 ctst->tmp_sig_mask = ptst->sig_mask;
7073 /* No stack definition should be currently present. The stack will be set
7074 later by libc by a setustack() call (the getsetcontext syscall). */
7075 ctst->client_stack_highest_byte = 0;
7076 ctst->client_stack_szB = 0;
7077 vg_assert(ctst->os_state.stk_id == NULL_STK_ID);
7079 /* Inform a tool that a new thread is created. This has to be done before
7080 any other core->tool event is sent. */
7081 vg_assert(VG_(owns_BigLock_LL)(tid));
7082 VG_TRACK(pre_thread_ll_create, tid, ctid);
7083 tool_informed = True;
7085 #if defined(VGP_x86_solaris)
7086 /* Set up GDT (this has to be done before calling
7087 VG_(restore_context)(). */
7088 ML_(setup_gdt)(&ctst->arch.vex);
7089 #elif defined(VGP_amd64_solaris)
7090 /* Nothing to do. */
7091 #else
7092 # error "Unknown platform"
7093 #endif
7095 /* Now set up the new thread according to ucontext_t. */
7096 VG_(restore_context)(ctid, (vki_ucontext_t*)ARG1, Vg_CoreSysCall,
7097 True/*esp_is_thrptr*/);
7099 /* Set up V thread (this also tells the kernel to block all signals in the
7100 thread). */
7101 ML_(setup_start_thread_context)(ctid, &uc);
7103 /* Actually create the new thread. */
7104 res = VG_(do_syscall3)(__NR_lwp_create, (UWord)&uc, ARG2, ARG3);
7106 if (!sr_isError(res)) {
7107 if (ARG3 != 0)
7108 POST_MEM_WRITE(ARG3, sizeof(vki_id_t));
7109 if (ARG2 & VKI_LWP_DAEMON)
7110 ctst->os_state.daemon_thread = True;
7113 out:
7114 if (sr_isError(res)) {
7115 if (tool_informed) {
7116 /* Tell a tool the thread exited in a hurry. */
7117 VG_TRACK(pre_thread_ll_exit, ctid);
7120 /* lwp_create failed. */
7121 VG_(cleanup_thread)(&ctst->arch);
7122 ctst->status = VgTs_Empty;
7125 SET_STATUS_from_SysRes(res);
7128 PRE(sys_lwp_exit)
7130 /* void syslwp_exit(); */
7131 ThreadState *tst = VG_(get_ThreadState)(tid);
7132 PRINT("sys_lwp_exit ( )");
7133 PRE_REG_READ0(long, "lwp_exit");
7135 /* Set the thread's status to be exiting, then claim that the syscall
7136 succeeded. */
7137 tst->exitreason = VgSrc_ExitThread;
7138 tst->os_state.exitcode = 0;
7139 SET_STATUS_Success(0);
7142 PRE(sys_lwp_suspend)
7144 /* int lwp_suspend(id_t lwpid); */
7145 ThreadState *tst = VG_(get_ThreadState)(tid);
7146 PRINT("sys_lwp_suspend ( %ld )", SARG1);
7147 PRE_REG_READ1(long, "lwp_suspend", vki_id_t, lwpid);
7149 if (ARG1 == tst->os_state.lwpid) {
7150 /* Set the SfMayBlock flag only if the currently running thread should
7151 be suspended. If this flag was used also when suspending other
7152 threads then it could happen that a thread holding the_BigLock would
7153 be suspended and Valgrind would hang. */
7154 *flags |= SfMayBlock;
7158 PRE(sys_lwp_continue)
7160 /* int lwp_continue(id_t target_lwp); */
7161 PRINT("sys_lwp_continue ( %ld )", SARG1);
7162 PRE_REG_READ1(long, "lwp_continue", vki_id_t, target_lwp);
7165 static void
7166 do_lwp_sigqueue(const HChar *syscall_name, UWord target_lwp, UWord signo,
7167 SyscallStatus *status, UWord *flags)
7169 if (!ML_(client_signal_OK)(signo)) {
7170 SET_STATUS_Failure(VKI_EINVAL);
7171 return;
7174 /* Check to see if this gave us a pending signal. */
7175 *flags |= SfPollAfter;
7177 if (VG_(clo_trace_signals))
7178 VG_(message)(Vg_DebugMsg, "%s: sending signal %lu to thread %lu\n",
7179 syscall_name, signo, target_lwp);
7181 /* If we're sending SIGKILL, check to see if the target is one of our
7182 threads and handle it specially. */
7183 if (signo == VKI_SIGKILL && ML_(do_sigkill)(target_lwp, -1)) {
7184 SET_STATUS_Success(0);
7185 return;
7188 /* Ask to handle this syscall via the slow route, since that's the only one
7189 that sets tst->status to VgTs_WaitSys. If the result of doing the
7190 syscall is an immediate run of async_signalhandler() in m_signals.c,
7191 then we need the thread to be properly tidied away. */
7192 *flags |= SfMayBlock;
7195 #if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
7196 #if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID)
7197 PRE(sys_lwp_sigqueue)
7199 /* int lwp_sigqueue(pid_t target_pid, id_t target_lwp, int signal,
7200 void *value, int si_code, timespec_t *timeout);
7202 PRINT("sys_lwp_sigqueue ( %ld, %ld, %ld, %#lx, %ld, %#lx )",
7203 SARG1, SARG2, SARG3, ARG4, SARG5, ARG6);
7204 PRE_REG_READ6(long, "lwp_sigqueue", vki_pid_t, target_pid,
7205 vki_id_t, target_lwp, int, signal, void *, value, int, si_code,
7206 vki_timespec_t *, timeout);
7208 if (ARG6)
7209 PRE_MEM_READ("lwp_sigqueue(timeout)", ARG6, sizeof(vki_timespec_t));
7211 if ((ARG1 == 0) || (ARG1 == VG_(getpid)())) {
7212 do_lwp_sigqueue("lwp_sigqueue", ARG2, ARG3, status, flags);
7213 } else {
7214 /* Signal is sent to a different process. */
7215 if (VG_(clo_trace_signals))
7216 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sending signal %ld to "
7217 "process %ld, thread %ld\n", SARG3, SARG1, SARG2);
7218 *flags |= SfMayBlock;
7222 POST(sys_lwp_sigqueue)
7224 if (VG_(clo_trace_signals))
7225 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sent signal %ld to process %ld, "
7226 "thread %ld\n", SARG3, SARG1, SARG2);
7229 #else
7231 PRE(sys_lwp_sigqueue)
7233 /* int lwp_sigqueue(id_t target_lwp, int signal, void *value,
7234 int si_code, timespec_t *timeout);
7236 PRINT("sys_lwp_sigqueue ( %ld, %ld, %#lx, %ld, %#lx )",
7237 SARG1, SARG2, ARG3, SARG4, ARG5);
7238 PRE_REG_READ5(long, "lwp_sigqueue", vki_id_t, target_lwp, int, signal,
7239 void *, value, int, si_code, vki_timespec_t *, timeout);
7241 if (ARG5)
7242 PRE_MEM_READ("lwp_sigqueue(timeout)", ARG5, sizeof(vki_timespec_t));
7244 do_lwp_sigqueue("lwp_sigqueue", ARG1, ARG2, status, flags);
7247 POST(sys_lwp_sigqueue)
7249 if (VG_(clo_trace_signals))
7250 VG_(message)(Vg_DebugMsg, "lwp_sigqueue: sent signal %lu to thread %lu\n",
7251 ARG2, ARG1);
7255 #endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID */
7257 #else
7259 PRE(sys_lwp_kill)
7261 /* int lwp_kill(id_t target_lwp, int signal); */
7262 PRINT("sys_lwp_kill ( %ld, %ld )", SARG1, SARG2);
7263 PRE_REG_READ2(long, "lwp_kill", vki_id_t, target_lwp, int, signal);
7265 do_lwp_sigqueue("lwp_kill", ARG1, ARG2, status, flags);
7268 POST(sys_lwp_kill)
7270 if (VG_(clo_trace_signals))
7271 VG_(message)(Vg_DebugMsg, "lwp_kill: sent signal %lu to thread %lu\n",
7272 ARG2, ARG1);
7274 #endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
7276 PRE(sys_lwp_self)
7278 /* id_t lwp_self(void); */
7279 PRINT("sys_lwp_self ( )");
7280 PRE_REG_READ0(long, "lwp_self");
7283 PRE(sys_lwp_sigmask)
7285 /* int64_t lwp_sigmask(int how, uint_t bits0, uint_t bits1, uint_t bits2,
7286 uint_t bits3); */
7287 vki_sigset_t sigset;
7288 PRINT("sys_lwp_sigmask ( %ld, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
7289 ARG4, ARG5);
7290 PRE_REG_READ5(long, "lwp_sigmask", int, how, vki_uint_t, bits0,
7291 vki_uint_t, bits1, vki_uint_t, bits2, vki_uint_t, bits3);
7293 sigset.__sigbits[0] = ARG2;
7294 sigset.__sigbits[1] = ARG3;
7295 sigset.__sigbits[2] = ARG4;
7296 sigset.__sigbits[3] = ARG5;
7298 SET_STATUS_from_SysRes(
7299 VG_(do_sys_sigprocmask)(tid, ARG1 /*how*/, &sigset, NULL)
7302 if (SUCCESS)
7303 *flags |= SfPollAfter;
7306 PRE(sys_lwp_private)
7308 /* int lwp_private(int cmd, int which, uintptr_t base); */
7309 ThreadState *tst = VG_(get_ThreadState)(tid);
7310 Int supported_base, supported_sel;
7311 PRINT("sys_lwp_private ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7312 PRE_REG_READ3(long, "lwp_private", int, cmd, int, which,
7313 uintptr_t, base);
7315 /* Note: Only the %gs base is currently supported on x86 and the %fs base
7316 on amd64. Support for the %fs base on x86 and for the %gs base on amd64
7317 should be added. Anything else is probably a client program error. */
7318 #if defined(VGP_x86_solaris)
7319 supported_base = VKI_LWP_GSBASE;
7320 supported_sel = VKI_LWPGS_SEL;
7321 #elif defined(VGP_amd64_solaris)
7322 supported_base = VKI_LWP_FSBASE;
7323 supported_sel = 0;
7324 #else
7325 #error "Unknown platform"
7326 #endif
7327 if (ARG2 != supported_base) {
7328 VG_(unimplemented)("Syswrap of the lwp_private call where which=%ld.",
7329 SARG2);
7330 /*NOTREACHED*/
7333 switch (ARG1 /*cmd*/) {
7334 case VKI_LWP_SETPRIVATE:
7335 #if defined(VGP_x86_solaris)
7336 tst->os_state.thrptr = ARG3;
7337 ML_(update_gdt_lwpgs)(tid);
7338 #elif defined(VGP_amd64_solaris)
7339 tst->arch.vex.guest_FS_CONST = ARG3;
7340 #else
7341 #error "Unknown platform"
7342 #endif
7343 SET_STATUS_Success(supported_sel);
7344 break;
7345 case VKI_LWP_GETPRIVATE:
7347 int thrptr;
7348 #if defined(VGP_x86_solaris)
7349 thrptr = tst->os_state.thrptr;
7350 #elif defined(VGP_amd64_solaris)
7351 thrptr = tst->arch.vex.guest_FS_CONST;
7352 #else
7353 #error "Unknown platform"
7354 #endif
7356 if (thrptr == 0) {
7357 SET_STATUS_Failure(VKI_EINVAL);
7358 return;
7361 #if defined(VGP_x86_solaris)
7362 if (tst->arch.vex.guest_GS != supported_sel) {
7363 SET_STATUS_Failure(VKI_EINVAL);
7364 return;
7366 #elif defined(VGP_amd64_solaris)
7367 /* Valgrind on amd64 does not allow to change the gs register so
7368 a check that guest_GS is equal to supported_sel is not needed
7369 here. */
7370 #else
7371 #error "Unknown platform"
7372 #endif
7374 PRE_MEM_WRITE("lwp_private(base)", ARG3, sizeof(Addr));
7375 if (!ML_(safe_to_deref((void*)ARG3, sizeof(Addr)))) {
7376 SET_STATUS_Failure(VKI_EFAULT);
7377 return;
7379 *(Addr*)ARG3 = thrptr;
7380 POST_MEM_WRITE((Addr)ARG3, sizeof(Addr));
7381 SET_STATUS_Success(0);
7382 break;
7384 default:
7385 VG_(unimplemented)("Syswrap of the lwp_private call where cmd=%ld.",
7386 SARG1);
7387 /*NOTREACHED*/
7388 break;
7392 PRE(sys_lwp_wait)
7394 /* int lwp_wait(id_t lwpid, id_t *departed); */
7395 *flags |= SfMayBlock;
7396 PRINT("sys_lwp_wait ( %ld, %#lx )", SARG1, ARG2);
7397 PRE_REG_READ2(long, "lwp_wait", vki_id_t, lwpid, vki_id_t *, departed);
7398 if (ARG2)
7399 PRE_MEM_WRITE("lwp_wait(departed)", ARG2, sizeof(vki_id_t));
7402 POST(sys_lwp_wait)
7404 POST_MEM_WRITE(ARG2, sizeof(vki_id_t));
7407 PRE(sys_lwp_mutex_wakeup)
7409 /* int lwp_mutex_wakeup(lwp_mutex_t *lp, int release_all); */
7410 *flags |= SfMayBlock;
7411 PRINT("sys_lwp_mutex_wakeup ( %#lx, %ld )", ARG1, SARG2);
7412 PRE_REG_READ2(long, "lwp_mutex_wakeup", vki_lwp_mutex_t *, lp,
7413 int, release_all);
7414 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *) ARG1;
7415 PRE_FIELD_READ("lwp_mutex_wakeup(lp->mutex_type)", lp->vki_mutex_type);
7416 PRE_FIELD_WRITE("lwp_mutex_wakeup(lp->mutex_waiters)",
7417 lp->vki_mutex_waiters);
7420 POST(sys_lwp_mutex_wakeup)
7422 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *) ARG1;
7423 POST_FIELD_WRITE(lp->vki_mutex_waiters);
7426 PRE(sys_lwp_cond_wait)
7428 /* int lwp_cond_wait(lwp_cond_t *cvp, lwp_mutex_t *mp, timespec_t *tsp,
7429 int check_park); */
7430 *flags |= SfMayBlock;
7431 PRINT("sys_lwp_cond_wait( %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3, SARG4);
7432 PRE_REG_READ4(long, "lwp_cond_wait", vki_lwp_cond_t *, cvp,
7433 vki_lwp_mutex_t *, mp, vki_timespec_t *, tsp, int, check_part);
7435 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7436 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t *) ARG2;
7437 PRE_FIELD_READ("lwp_cond_wait(cvp->type)", cvp->vki_cond_type);
7438 PRE_FIELD_READ("lwp_cond_wait(cvp->waiters_kernel)",
7439 cvp->vki_cond_waiters_kernel);
7440 PRE_FIELD_READ("lwp_cond_wait(mp->mutex_type)", mp->vki_mutex_type);
7441 PRE_FIELD_WRITE("lwp_cond_wait(mp->mutex_waiters)", mp->vki_mutex_waiters);
7442 if (ARG3 != 0)
7443 PRE_MEM_READ("lwp_cond_wait(tsp)", ARG3, sizeof(vki_timespec_t));
7446 POST(sys_lwp_cond_wait)
7448 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7449 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t *) ARG2;
7450 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7451 POST_FIELD_WRITE(mp->vki_mutex_waiters);
7452 if (ARG3 != 0)
7453 POST_MEM_WRITE(ARG3, sizeof(vki_timespec_t));
7456 PRE(sys_lwp_cond_signal)
7458 /* int lwp_cond_signal(lwp_cond_t *cvp); */
7459 *flags |= SfMayBlock;
7460 PRINT("sys_lwp_cond_signal( %#lx )", ARG1);
7461 PRE_REG_READ1(long, "lwp_cond_signal", vki_lwp_cond_t *, cvp);
7463 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7464 PRE_FIELD_READ("lwp_cond_signal(cvp->type)", cvp->vki_cond_type);
7465 PRE_FIELD_READ("lwp_cond_signal(cvp->waiters_kernel)",
7466 cvp->vki_cond_waiters_kernel);
7469 POST(sys_lwp_cond_signal)
7471 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7472 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7475 PRE(sys_lwp_cond_broadcast)
7477 /* int lwp_cond_broadcast(lwp_cond_t *cvp); */
7478 *flags |= SfMayBlock;
7479 PRINT("sys_lwp_cond_broadcast ( %#lx )", ARG1);
7480 PRE_REG_READ1(long, "lwp_cond_broadcast", vki_lwp_cond_t *, cvp);
7482 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7483 PRE_FIELD_READ("lwp_cond_broadcast(cvp->type)", cvp->vki_cond_type);
7484 PRE_FIELD_READ("lwp_cond_broadcast(cvp->waiters_kernel)",
7485 cvp->vki_cond_waiters_kernel);
7486 /*PRE_FIELD_WRITE("lwp_cond_broadcast(cvp->waiters_kernel)",
7487 cvp->vki_cond_waiters_kernel);*/
7490 POST(sys_lwp_cond_broadcast)
7492 vki_lwp_cond_t *cvp = (vki_lwp_cond_t *) ARG1;
7493 POST_FIELD_WRITE(cvp->vki_cond_waiters_kernel);
7496 PRE(sys_pread)
7498 /* ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); */
7499 *flags |= SfMayBlock;
7500 PRINT("sys_pread ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
7501 PRE_REG_READ4(long, "pread", int, fildes, void *, buf,
7502 vki_size_t, nbyte, vki_off_t, offset);
7503 PRE_MEM_WRITE("pread(buf)", ARG2, ARG3);
7505 /* Be strict. */
7506 if (!ML_(fd_allowed)(ARG1, "pread", tid, False))
7507 SET_STATUS_Failure(VKI_EBADF);
7510 POST(sys_pread)
7512 POST_MEM_WRITE(ARG2, RES);
7515 PRE(sys_pwrite)
7517 /* ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
7518 off_t offset); */
7519 *flags |= SfMayBlock;
7520 PRINT("sys_pwrite ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
7521 PRE_REG_READ4(long, "pwrite", int, fildes, const void *, buf,
7522 vki_size_t, nbyte, vki_off_t, offset);
7523 PRE_MEM_READ("pwrite(buf)", ARG2, ARG3);
7525 /* Be strict. */
7526 if (!ML_(fd_allowed)(ARG1, "pwrite", tid, False))
7527 SET_STATUS_Failure(VKI_EBADF);
7530 PRE(sys_getpagesizes)
7532 /* int getpagesizes(int legacy, size_t *buf, int nelem); */
7533 PRINT("sys_getpagesizes ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
7534 PRE_REG_READ3(long, "getpagesizes", int, legacy, size_t *, buf,
7535 int, nelem);
7536 if (ARG2)
7537 PRE_MEM_WRITE("getpagesizes(buf)", ARG2, ARG3 * sizeof(vki_size_t));
7540 POST(sys_getpagesizes)
7542 if (ARG2)
7543 POST_MEM_WRITE(ARG2, RES * sizeof(vki_size_t));
7546 PRE(sys_lgrpsys)
7548 /* Kernel: int lgrpsys(int subcode, long ia, void *ap); */
7549 switch (ARG1 /*subcode*/) {
7550 case VKI_LGRP_SYS_MEMINFO:
7551 PRINT("sys_lgrpsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7552 PRE_REG_READ3(long, SC2("lgrpsys", "meminfo"), int, subcode,
7553 int, addr_count, vki_meminfo_t *, minfo);
7554 PRE_MEM_READ("lgrpsys(minfo)", ARG3, sizeof(vki_meminfo_t));
7556 if (ML_(safe_to_deref)((vki_meminfo_t *) ARG3, sizeof(vki_meminfo_t))) {
7557 vki_meminfo_t *minfo = (vki_meminfo_t *) ARG3;
7558 PRE_MEM_READ("lgrpsys(minfo->mi_inaddr)",
7559 (Addr) minfo->mi_inaddr, SARG2 * sizeof(vki_uint64_t));
7560 PRE_MEM_READ("lgrpsys(minfo->mi_info_req)", (Addr) minfo->mi_info_req,
7561 minfo->mi_info_count * sizeof(vki_uint_t));
7562 PRE_MEM_WRITE("lgrpsys(minfo->mi_outdata)", (Addr) minfo->mi_outdata,
7563 SARG2 * minfo->mi_info_count * sizeof(vki_uint64_t));
7564 PRE_MEM_WRITE("lgrpsys(minfo->mi_validity)",
7565 (Addr) minfo->mi_validity, SARG2 * sizeof(vki_uint_t));
7567 break;
7568 case VKI_LGRP_SYS_GENERATION:
7569 /* Liblgrp: lgrp_gen_t lgrp_generation(lgrp_view_t view); */
7570 PRINT("sys_lgrpsys ( %ld, %ld )", SARG1, SARG2);
7571 PRE_REG_READ2(long, SC2("lgrpsys", "generation"), int, subcode,
7572 vki_lgrp_view_t, view);
7573 break;
7574 case VKI_LGRP_SYS_VERSION:
7575 /* Liblgrp: int lgrp_version(int version); */
7576 PRINT("sys_lgrpsys ( %ld, %ld )", SARG1, SARG2);
7577 PRE_REG_READ2(long, SC2("lgrpsys", "version"), int, subcode,
7578 int, version);
7579 break;
7580 case VKI_LGRP_SYS_SNAPSHOT:
7581 /* Liblgrp: int lgrp_snapshot(void *buf, size_t bufsize); */
7582 PRINT("sys_lgrpsys ( %ld, %lu, %#lx )", SARG1, ARG2, ARG3);
7583 PRE_REG_READ3(long, SC2("lgrpsys", "snapshot"), int, subcode,
7584 vki_size_t, bufsize, void *, buf);
7585 PRE_MEM_WRITE("lgrpsys(buf)", ARG3, ARG2);
7586 break;
7587 default:
7588 VG_(unimplemented)("Syswrap of the lgrpsys call with subcode %ld.",
7589 SARG1);
7590 /*NOTREACHED*/
7591 break;
7595 POST(sys_lgrpsys)
7597 switch (ARG1 /*subcode*/) {
7598 case VKI_LGRP_SYS_MEMINFO:
7600 vki_meminfo_t *minfo = (vki_meminfo_t *) ARG3;
7601 POST_MEM_WRITE((Addr) minfo->mi_outdata,
7602 SARG2 * minfo->mi_info_count * sizeof(vki_uint64_t));
7603 POST_MEM_WRITE((Addr) minfo->mi_validity, SARG2 * sizeof(vki_uint_t));
7605 break;
7606 case VKI_LGRP_SYS_GENERATION:
7607 case VKI_LGRP_SYS_VERSION:
7608 break;
7609 case VKI_LGRP_SYS_SNAPSHOT:
7610 POST_MEM_WRITE(ARG3, RES);
7611 break;
7612 default:
7613 vg_assert(0);
7614 break;
7618 PRE(sys_rusagesys)
7620 /* Kernel: int rusagesys(int code, void *arg1, void *arg2,
7621 void *arg3, void *arg4); */
7622 switch (ARG1 /*code*/) {
7623 case VKI__RUSAGESYS_GETRUSAGE:
7624 case VKI__RUSAGESYS_GETRUSAGE_CHLD:
7625 case VKI__RUSAGESYS_GETRUSAGE_LWP:
7626 /* Libc: int getrusage(int who, struct rusage *r_usage); */
7627 PRINT("sys_rusagesys ( %ld, %#lx )", SARG1, ARG2);
7628 PRE_REG_READ2(long, SC2("rusagesys", "getrusage"), int, code,
7629 struct vki_rusage *, r_usage);
7630 PRE_MEM_WRITE("rusagesys(r_usage)", ARG2, sizeof(struct vki_rusage));
7631 break;
7633 case VKI__RUSAGESYS_GETVMUSAGE:
7634 /* Libc: int getvmusage(uint_t flags, time_t age,
7635 vmusage_t *buf, size_t *nres); */
7636 PRINT("sys_rusagesys ( %ld, %lu, %ld, %#lx, %#lx )",
7637 SARG1, ARG2, SARG3, ARG4, ARG5);
7638 PRE_REG_READ5(long, SC2("rusagesys", "getvmusage"), int, code,
7639 vki_uint_t, flags, vki_time_t, age,
7640 vki_vmusage_t *, buf, vki_size_t *, nres);
7641 PRE_MEM_READ("rusagesys(nres)", ARG5, sizeof(vki_size_t));
7642 /* PRE_MEM_WRITE("rusagesys(nres)", ARG5, sizeof(vki_size_t)); */
7644 if (ML_(safe_to_deref)((void *) ARG5, sizeof(vki_size_t))) {
7645 vki_size_t *nres = (vki_size_t *) ARG5;
7646 PRE_MEM_WRITE("rusagesys(buf)", ARG4,
7647 *nres * sizeof(vki_vmusage_t));
7649 *flags |= SfMayBlock;
7650 break;
7652 default:
7653 VG_(unimplemented)("Syswrap of the rusagesys call with code %ld.", SARG1);
7654 /*NOTREACHED*/
7655 break;
7659 POST(sys_rusagesys)
7661 switch (ARG1 /*code*/) {
7662 case VKI__RUSAGESYS_GETRUSAGE:
7663 case VKI__RUSAGESYS_GETRUSAGE_CHLD:
7664 case VKI__RUSAGESYS_GETRUSAGE_LWP:
7665 POST_MEM_WRITE(ARG2, sizeof(struct vki_rusage));
7666 break;
7667 case VKI__RUSAGESYS_GETVMUSAGE:
7669 vki_size_t *nres = (vki_size_t *) ARG5;
7670 POST_MEM_WRITE(ARG5, sizeof(vki_size_t));
7671 POST_MEM_WRITE(ARG4, *nres * sizeof(vki_vmusage_t));
7673 break;
7674 default:
7675 vg_assert(0);
7676 break;
7680 PRE(sys_port)
7682 /* Kernel: int64_t portfs(int opcode, uintptr_t a0, uintptr_t a1,
7683 uintptr_t a2, uintptr_t a3, uintptr_t a4); */
7684 Int opcode = ARG1 & VKI_PORT_CODE_MASK;
7685 *flags |= SfMayBlock;
7686 switch (opcode) {
7687 case VKI_PORT_CREATE:
7688 PRINT("sys_port ( %ld )", SARG1);
7689 PRE_REG_READ1(long, SC2("port", "create"), int, opcode);
7690 break;
7691 case VKI_PORT_ASSOCIATE:
7692 case VKI_PORT_DISSOCIATE:
7693 PRINT("sys_port ( %ld, %ld, %ld, %#lx, %ld, %#lx )", SARG1, SARG2, SARG3,
7694 ARG4, SARG5, ARG6);
7695 if (opcode == VKI_PORT_ASSOCIATE) {
7696 PRE_REG_READ6(long, SC2("port", "associate"), int, opcode, int, a0,
7697 int, a1, uintptr_t, a2, int, a3, void *, a4);
7699 else {
7700 PRE_REG_READ6(long, SC2("port", "dissociate"), int, opcode, int, a0,
7701 int, a1, uintptr_t, a2, int, a3, void *, a4);
7704 switch (ARG3 /*source*/) {
7705 case VKI_PORT_SOURCE_FD:
7706 if (!ML_(fd_allowed)(ARG4, "port", tid, False)) {
7707 SET_STATUS_Failure(VKI_EBADF);
7709 break;
7710 case VKI_PORT_SOURCE_FILE:
7712 struct vki_file_obj *fo = (struct vki_file_obj *)ARG4;
7713 PRE_MEM_READ("port(file_obj)", ARG4, sizeof(struct vki_file_obj));
7714 if (ML_(safe_to_deref)(&fo->fo_name, sizeof(fo->fo_name)))
7715 PRE_MEM_RASCIIZ("port(file_obj->fo_name)", (Addr)fo->fo_name);
7717 break;
7718 default:
7719 VG_(unimplemented)("Syswrap of the port_associate/dissociate call "
7720 "type %ld.", SARG3);
7721 /*NOTREACHED*/
7722 break;
7724 break;
7725 case VKI_PORT_SEND:
7726 PRINT("sys_port ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
7727 PRE_REG_READ4(long, SC2("port", "send"), int, opcode, int, a0, int, a1,
7728 void *, a2);
7729 break;
7730 case VKI_PORT_SENDN:
7731 PRINT("sys_port ( %ld, %#lx, %#lx, %lu, %lx, %#lx)", SARG1, ARG2, ARG3,
7732 ARG4, ARG5, ARG6);
7733 PRE_REG_READ6(long, SC2("port", "sendn"), int, opcode, int *, a0,
7734 int *, a1, vki_uint_t, a2, int, a3, void *, a4);
7735 PRE_MEM_READ("port(ports)", ARG2, ARG4 * sizeof(int));
7736 PRE_MEM_WRITE("port(errors)", ARG3, ARG4 * sizeof(int));
7737 break;
7738 case VKI_PORT_GET:
7739 PRINT("sys_port ( %ld, %ld, %#lx, %ld, %ld, %#lx )", SARG1, SARG2, ARG3,
7740 SARG4, SARG5, ARG6);
7741 PRE_REG_READ6(long, SC2("port", "get"), int, opcode, int, a0,
7742 port_event_t *, a1, vki_time_t, a2, long, a3,
7743 timespec_t *, a4);
7744 PRE_MEM_WRITE("port(uevp)", ARG3, sizeof(vki_port_event_t));
7745 break;
7746 case VKI_PORT_GETN:
7747 PRINT("sys_port ( %ld, %ld, %#lx, %lu, %lu, %#lx )", SARG1, SARG2, ARG3,
7748 ARG4, ARG5, ARG6);
7749 PRE_REG_READ6(long, SC2("port", "getn"), int, opcode, int, a0,
7750 port_event_t *, a1, vki_uint_t, a2, vki_uint_t, a3,
7751 timespec_t *, a4);
7752 if (ARG6)
7753 PRE_MEM_READ("port(timeout)", ARG6, sizeof(vki_timespec_t));
7754 PRE_MEM_WRITE("port(uevp)", ARG3, ARG4 * sizeof(vki_port_event_t));
7755 break;
7756 case VKI_PORT_ALERT:
7757 PRINT("sys_port ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, SARG4,
7758 ARG5);
7759 PRE_REG_READ5(long, SC2("port", "alert"), int, opcode, int, a0, int, a1,
7760 int, a2, void *, a3);
7761 break;
7762 case VKI_PORT_DISPATCH:
7763 // FIXME: check order: SARG2, SARG1 or SARG1, SARG2 ??
7764 PRINT("sys_port ( %ld, %ld, %ld, %ld, %#lx, %#lx )", SARG2, SARG1, SARG3,
7765 SARG4, ARG5, ARG6);
7766 PRE_REG_READ6(long, SC2("port", "dispatch"), int, opcode, int, a0,
7767 int, a1, int, a2, uintptr_t, a3, void *, a4);
7768 break;
7769 default:
7770 VG_(unimplemented)("Syswrap of the port call with opcode %ld.", SARG1);
7771 /*NOTREACHED*/
7772 break;
7775 /* Be strict. */
7776 if ((opcode != VKI_PORT_CREATE && opcode != VKI_PORT_SENDN) &&
7777 !ML_(fd_allowed)(ARG2, "port", tid, False))
7778 SET_STATUS_Failure(VKI_EBADF);
7781 POST(sys_port)
7783 Int opcode = ARG1 & VKI_PORT_CODE_MASK;
7784 switch (opcode) {
7785 case VKI_PORT_CREATE:
7786 if (!ML_(fd_allowed)(RES, "port", tid, True)) {
7787 VG_(close)(RES);
7788 SET_STATUS_Failure(VKI_EMFILE);
7790 else if (VG_(clo_track_fds))
7791 ML_(record_fd_open_named)(tid, RES);
7792 break;
7793 case VKI_PORT_ASSOCIATE:
7794 case VKI_PORT_DISSOCIATE:
7795 case VKI_PORT_SEND:
7796 break;
7797 case VKI_PORT_SENDN:
7798 if (RES != ARG4) {
7799 /* If there is any error then the whole errors area is written. */
7800 POST_MEM_WRITE(ARG3, ARG4 * sizeof(int));
7802 break;
7803 case VKI_PORT_GET:
7804 POST_MEM_WRITE(ARG3, sizeof(vki_port_event_t));
7805 break;
7806 case VKI_PORT_GETN:
7807 POST_MEM_WRITE(ARG3, RES * sizeof(vki_port_event_t));
7808 break;
7809 case VKI_PORT_ALERT:
7810 case VKI_PORT_DISPATCH:
7811 break;
7812 default:
7813 VG_(unimplemented)("Syswrap of the port call with opcode %lu.", ARG1);
7814 /*NOTREACHED*/
7815 break;
7819 PRE(sys_pollsys)
7821 /* int pollsys(pollfd_t *fds, nfds_t nfds, timespec_t *timeout,
7822 sigset_t *set); */
7823 UWord i;
7824 struct vki_pollfd *ufds = (struct vki_pollfd *)ARG1;
7826 *flags |= SfMayBlock | SfPostOnFail;
7828 PRINT("sys_pollsys ( %#lx, %lu, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4);
7829 PRE_REG_READ4(long, "poll", pollfd_t *, fds, vki_nfds_t, nfds,
7830 timespec_t *, timeout, sigset_t *, set);
7832 for (i = 0; i < ARG2; i++) {
7833 vki_pollfd_t *u = &ufds[i];
7834 PRE_FIELD_READ("poll(ufds.fd)", u->fd);
7835 if (ML_(safe_to_deref)(&ufds[i].fd, sizeof(ufds[i].fd)) && ufds[i].fd >= 0) {
7836 PRE_FIELD_READ("poll(ufds.events)", u->events);
7838 PRE_FIELD_WRITE("poll(ufds.revents)", u->revents);
7841 if (ARG3)
7842 PRE_MEM_READ("poll(timeout)", ARG3, sizeof(vki_timespec_t));
7844 if (ARG4) {
7845 PRE_MEM_READ("poll(set)", ARG4, sizeof(vki_sigset_t));
7847 const vki_sigset_t *guest_sigmask = (vki_sigset_t *) ARG4;
7848 if (!ML_(safe_to_deref)(guest_sigmask, sizeof(vki_sigset_t))) {
7849 ARG4 = 1; /* Something recognisable to POST() hook. */
7850 } else {
7851 vki_sigset_t *vg_sigmask =
7852 VG_(malloc)("syswrap.pollsys.1", sizeof(vki_sigset_t));
7853 ARG4 = (Addr) vg_sigmask;
7854 *vg_sigmask = *guest_sigmask;
7855 VG_(sanitize_client_sigmask)(vg_sigmask);
7860 POST(sys_pollsys)
7862 vg_assert(SUCCESS || FAILURE);
7864 if (SUCCESS && (RES >= 0)) {
7865 UWord i;
7866 vki_pollfd_t *ufds = (vki_pollfd_t*)ARG1;
7867 for (i = 0; i < ARG2; i++)
7868 POST_FIELD_WRITE(ufds[i].revents);
7871 if ((ARG4 != 0) && (ARG4 != 1)) {
7872 VG_(free)((vki_sigset_t *) ARG4);
7876 PRE(sys_labelsys)
7878 /* Kernel: int labelsys(int op, void *a1, void *a2, void *a3,
7879 void *a4, void *a5); */
7881 switch (ARG1 /*op*/) {
7882 case VKI_TSOL_SYSLABELING:
7883 /* Libc: int is_system_labeled(void); */
7884 PRINT("sys_labelsys ( %ld )", SARG1);
7885 PRE_REG_READ1(long, SC2("labelsys", "syslabeling"), int, op);
7886 break;
7888 case VKI_TSOL_TNRH:
7889 /* Libtsnet: int tnrh(int cmd, tsol_rhent_t *buf); */
7890 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7891 PRE_REG_READ3(long, SC2("labelsys", "tnrh"), int, op, int, cmd,
7892 vki_tsol_rhent_t *, buf);
7893 if (ARG2 != VKI_TNDB_FLUSH)
7894 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_rhent_t));
7895 break;
7897 case VKI_TSOL_TNRHTP:
7898 /* Libtsnet: int tnrhtp(int cmd, tsol_tpent_t *buf); */
7899 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7900 PRE_REG_READ3(long, SC2("labelsys", "tnrhtp"), int, op, int, cmd,
7901 vki_tsol_tpent_t *, buf);
7902 if (ARG2 != VKI_TNDB_FLUSH)
7903 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_tpent_t));
7904 break;
7906 case VKI_TSOL_TNMLP:
7907 /* Libtsnet: int tnmlp(int cmd, tsol_mlpent_t *buf); */
7908 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7909 PRE_REG_READ3(long, SC2("labelsys", "tnmlp"), int, op, int, cmd,
7910 vki_tsol_mlpent_t *, buf);
7911 PRE_MEM_READ("labelsys(buf)", ARG3, sizeof(vki_tsol_mlpent_t));
7912 break;
7914 case VKI_TSOL_GETLABEL:
7915 /* Libtsol: int getlabel(const char *path, bslabel_t *label); */
7916 PRINT("sys_labelsys ( %ld, %#lx(%s), %#lx )",
7917 SARG1, ARG2, (HChar *) ARG2, ARG3);
7918 PRE_REG_READ3(long, SC2("labelsys", "getlabel"), int, op,
7919 const char *, path, vki_bslabel_t *, label);
7920 PRE_MEM_RASCIIZ("labelsys(path)", ARG2);
7921 PRE_MEM_WRITE("labelsys(label)", ARG3, sizeof(vki_bslabel_t));
7922 break;
7924 case VKI_TSOL_FGETLABEL:
7925 /* Libtsol: int fgetlabel(int fd, bslabel_t *label); */
7926 PRINT("sys_labelsys ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
7927 PRE_REG_READ3(long, SC2("labelsys", "fgetlabel"), int, op,
7928 int, fd, vki_bslabel_t *, label);
7929 /* Be strict. */
7930 if (!ML_(fd_allowed)(ARG2, "labelsys(fgetlabel)", tid, False))
7931 SET_STATUS_Failure(VKI_EBADF);
7932 PRE_MEM_WRITE("labelsys(label)", ARG3, sizeof(vki_bslabel_t));
7933 break;
7935 #if defined(SOLARIS_TSOL_CLEARANCE)
7936 case VKI_TSOL_GETCLEARANCE:
7937 /* Libtsol: int getclearance(bslabel_t *clearance); */
7938 PRINT("sys_labelsys ( %ld, %#lx )", SARG1, ARG2);
7939 PRE_REG_READ2(long, SC2("labelsys", "getclearance"), int, op,
7940 vki_bslabel_t *, clearance);
7941 PRE_MEM_WRITE("labelsys(clearance)", ARG2, sizeof(vki_bslabel_t));
7942 break;
7944 case VKI_TSOL_SETCLEARANCE:
7945 /* Libtsol: int setclearance(bslabel_t *clearance); */
7946 PRINT("sys_labelsys ( %ld, %#lx )", SARG1, ARG2);
7947 PRE_REG_READ2(long, SC2("labelsys", "setclearance"), int, op,
7948 vki_bslabel_t *, clearance);
7949 PRE_MEM_READ("labelsys(clearance)", ARG2, sizeof(vki_bslabel_t));
7950 break;
7951 #endif /* SOLARIS_TSOL_CLEARANCE */
7953 default:
7954 VG_(unimplemented)("Syswrap of the labelsys call with op %ld.", SARG1);
7955 /*NOTREACHED*/
7956 break;
7960 POST(sys_labelsys)
7962 switch (ARG1 /*op*/) {
7963 case VKI_TSOL_SYSLABELING:
7964 break;
7966 case VKI_TSOL_TNRH:
7967 switch (ARG2 /*cmd*/) {
7968 case VKI_TNDB_LOAD:
7969 case VKI_TNDB_DELETE:
7970 case VKI_TNDB_FLUSH:
7971 break;
7972 #if defined(SOLARIS_TNDB_GET_TNIP)
7973 case TNDB_GET_TNIP:
7974 #endif /* SOLARIS_TNDB_GET_TNIP */
7975 case VKI_TNDB_GET:
7976 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_rhent_t));
7977 break;
7978 default:
7979 vg_assert(0);
7980 break;
7982 break;
7984 case VKI_TSOL_TNRHTP:
7985 switch (ARG2 /*cmd*/) {
7986 case VKI_TNDB_LOAD:
7987 case VKI_TNDB_DELETE:
7988 case VKI_TNDB_FLUSH:
7989 break;
7990 case VKI_TNDB_GET:
7991 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_tpent_t));
7992 break;
7993 default:
7994 vg_assert(0);
7995 break;
7997 break;
7999 case VKI_TSOL_TNMLP:
8000 switch (ARG2 /*cmd*/) {
8001 case VKI_TNDB_LOAD:
8002 case VKI_TNDB_DELETE:
8003 case VKI_TNDB_FLUSH:
8004 break;
8005 case VKI_TNDB_GET:
8006 POST_MEM_WRITE(ARG3, sizeof(vki_tsol_mlpent_t));
8007 break;
8008 default:
8009 vg_assert(0);
8010 break;
8012 break;
8014 case VKI_TSOL_GETLABEL:
8015 case VKI_TSOL_FGETLABEL:
8016 POST_MEM_WRITE(ARG3, sizeof(vki_bslabel_t));
8017 break;
8019 #if defined(SOLARIS_TSOL_CLEARANCE)
8020 case VKI_TSOL_GETCLEARANCE:
8021 POST_MEM_WRITE(ARG2, sizeof(vki_bslabel_t));
8022 break;
8024 case VKI_TSOL_SETCLEARANCE:
8025 break;
8026 #endif /* SOLARIS_TSOL_CLEARANCE */
8028 default:
8029 vg_assert(0);
8030 break;
8034 PRE(sys_acl)
8036 /* int acl(char *pathp, int cmd, int nentries, void *aclbufp); */
8037 PRINT("sys_acl ( %#lx(%s), %ld, %ld, %#lx )", ARG1, (HChar *) ARG1, SARG2,
8038 SARG3, ARG4);
8040 PRE_REG_READ4(long, "acl", char *, pathp, int, cmd,
8041 int, nentries, void *, aclbufp);
8042 PRE_MEM_RASCIIZ("acl(pathp)", ARG1);
8044 switch (ARG2 /*cmd*/) {
8045 case VKI_SETACL:
8046 if (ARG4)
8047 PRE_MEM_READ("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8048 break;
8049 case VKI_GETACL:
8050 PRE_MEM_WRITE("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8051 break;
8052 case VKI_GETACLCNT:
8053 break;
8054 case VKI_ACE_SETACL:
8055 if (ARG4)
8056 PRE_MEM_READ("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8057 break;
8058 case VKI_ACE_GETACL:
8059 PRE_MEM_WRITE("acl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8060 break;
8061 case VKI_ACE_GETACLCNT:
8062 break;
8063 default:
8064 VG_(unimplemented)("Syswrap of the acl call with cmd %ld.", SARG2);
8065 /*NOTREACHED*/
8066 break;
8070 POST(sys_acl)
8072 switch (ARG2 /*cmd*/) {
8073 case VKI_SETACL:
8074 break;
8075 case VKI_GETACL:
8076 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_aclent_t));
8077 break;
8078 case VKI_GETACLCNT:
8079 break;
8080 case VKI_ACE_SETACL:
8081 break;
8082 case VKI_ACE_GETACL:
8083 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_ace_t));
8084 break;
8085 case VKI_ACE_GETACLCNT:
8086 break;
8087 default:
8088 vg_assert(0);
8089 break;
8093 PRE(sys_auditsys)
8095 /* Kernel: int auditsys(long code, long a1, long a2, long a3, long a4); */
8096 switch (ARG1 /*code*/) {
8097 case VKI_BSM_GETAUID:
8098 /* Libbsm: int getauid(au_id_t *auid); */
8099 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
8100 PRE_REG_READ2(long, SC2("auditsys", "getauid"), long, code,
8101 vki_au_id_t *, auid);
8102 PRE_MEM_WRITE("auditsys(auid)", ARG2, sizeof(vki_au_id_t));
8103 break;
8104 case VKI_BSM_SETAUID:
8105 /* Libbsm: int setauid(au_id_t *auid); */
8106 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
8107 PRE_REG_READ2(long, SC2("auditsys", "setauid"), long, code,
8108 vki_au_id_t *, auid);
8109 PRE_MEM_READ("auditsys(auid)", ARG2, sizeof(vki_au_id_t));
8110 break;
8111 case VKI_BSM_GETAUDIT:
8112 /* Libbsm: int getaudit(auditinfo_t *ai); */
8113 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
8114 PRE_REG_READ2(long, SC2("auditsys", "getaudit"), long, code,
8115 vki_auditinfo_t *, ai);
8116 PRE_MEM_WRITE("auditsys(ai)", ARG2, sizeof(vki_auditinfo_t));
8117 break;
8118 case VKI_BSM_SETAUDIT:
8119 /* Libbsm: int setaudit(auditinfo_t *ai); */
8120 PRINT("sys_auditsys ( %ld, %#lx )", SARG1, ARG2);
8121 PRE_REG_READ2(long, SC2("auditsys", "setaudit"), long, code,
8122 vki_auditinfo_t *, ai);
8123 PRE_MEM_READ("auditsys(ai)", ARG2, sizeof(vki_auditinfo_t));
8124 break;
8125 case VKI_BSM_AUDIT:
8126 /* Libbsm: int audit(void *record, int length); */
8127 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
8128 PRE_REG_READ3(long, SC2("auditsys", "audit"), long, code,
8129 void *, record, int, length);
8130 PRE_MEM_READ("auditsys(record)", ARG2, ARG3);
8131 break;
8132 case VKI_BSM_AUDITCTL:
8133 /* Libbsm: int auditon(int cmd, caddr_t data, int length); */
8134 PRINT("sys_auditsys ( %ld, %ld, %#lx, %ld )",
8135 SARG1, SARG2, ARG3, SARG4);
8137 switch (ARG2 /*cmd*/) {
8138 case VKI_A_GETPOLICY:
8139 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getpolicy"),
8140 long, code, int, cmd, vki_uint32_t *, policy);
8141 PRE_MEM_WRITE("auditsys(policy)", ARG3, sizeof(vki_uint32_t));
8142 break;
8143 case VKI_A_SETPOLICY:
8144 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setpolicy"),
8145 long, code, int, cmd, vki_uint32_t *, policy);
8146 PRE_MEM_READ("auditsys(policy)", ARG3, sizeof(vki_uint32_t));
8147 break;
8148 case VKI_A_GETKMASK:
8149 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getkmask"),
8150 long, code, int, cmd, vki_au_mask_t *, kmask);
8151 PRE_MEM_WRITE("auditsys(kmask)", ARG3, sizeof(vki_au_mask_t));
8152 break;
8153 case VKI_A_SETKMASK:
8154 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setkmask"),
8155 long, code, int, cmd, vki_au_mask_t *, kmask);
8156 PRE_MEM_READ("auditsys(kmask)", ARG3, sizeof(vki_au_mask_t));
8157 break;
8158 case VKI_A_GETQCTRL:
8159 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getqctrl"),
8160 long, code, int, cmd,
8161 struct vki_au_qctrl *, qctrl);
8162 PRE_MEM_WRITE("auditsys(qctrl)", ARG3,
8163 sizeof(struct vki_au_qctrl));
8164 break;
8165 case VKI_A_SETQCTRL:
8166 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setqctrl"),
8167 long, code, int, cmd,
8168 struct vki_au_qctrl *, qctrl);
8169 PRE_MEM_READ("auditsys(qctrl)", ARG3,
8170 sizeof(struct vki_au_qctrl));
8171 break;
8172 case VKI_A_GETCWD:
8173 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getcwd"),
8174 long, code, int, cmd, char *, data, int, length);
8175 PRE_MEM_WRITE("auditsys(data)", ARG3, ARG4);
8176 break;
8177 case VKI_A_GETCAR:
8178 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getcar"),
8179 long, code, int, cmd, char *, data, int, length);
8180 PRE_MEM_WRITE("auditsys(data)", ARG3, ARG4);
8181 break;
8182 #if defined(SOLARIS_AUDITON_STAT)
8183 case VKI_A_GETSTAT:
8184 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getstat"),
8185 long, code, int, cmd, vki_au_stat_t *, stats);
8186 PRE_MEM_WRITE("auditsys(stats)", ARG3, sizeof(vki_au_stat_t));
8187 break;
8188 case VKI_A_SETSTAT:
8189 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setstat"),
8190 long, code, int, cmd, vki_au_stat_t *, stats);
8191 PRE_MEM_READ("auditsys(stats)", ARG3, sizeof(vki_au_stat_t));
8192 break;
8193 #endif /* SOLARIS_AUDITON_STAT */
8194 case VKI_A_SETUMASK:
8195 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setumask"),
8196 long, code, int, cmd, vki_auditinfo_t *, umask);
8197 PRE_MEM_READ("auditsys(umask)", ARG3, sizeof(vki_auditinfo_t));
8198 break;
8199 case VKI_A_SETSMASK:
8200 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setsmask"),
8201 long, code, int, cmd, vki_auditinfo_t *, smask);
8202 PRE_MEM_READ("auditsys(smask)", ARG3, sizeof(vki_auditinfo_t));
8203 break;
8204 case VKI_A_GETCOND:
8205 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getcond"),
8206 long, code, int, cmd, int *, cond);
8207 PRE_MEM_WRITE("auditsys(cond)", ARG3, sizeof(int));
8208 break;
8209 case VKI_A_SETCOND:
8210 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setcond"),
8211 long, code, int, cmd, int *, state);
8212 PRE_MEM_READ("auditsys(cond)", ARG3, sizeof(int));
8213 break;
8214 case VKI_A_GETCLASS:
8215 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getclass"),
8216 long, code, int, cmd,
8217 vki_au_evclass_map_t *, classmap);
8219 if (ML_(safe_to_deref((void *) ARG3,
8220 sizeof(vki_au_evclass_map_t)))) {
8221 vki_au_evclass_map_t *classmap =
8222 (vki_au_evclass_map_t *) ARG3;
8223 PRE_FIELD_READ("auditsys(classmap.ec_number)",
8224 classmap->ec_number);
8225 PRE_MEM_WRITE("auditsys(classmap)", ARG3,
8226 sizeof(vki_au_evclass_map_t));
8228 break;
8229 case VKI_A_SETCLASS:
8230 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setclass"),
8231 long, code, int, cmd,
8232 vki_au_evclass_map_t *, classmap);
8234 if (ML_(safe_to_deref((void *) ARG3,
8235 sizeof(vki_au_evclass_map_t)))) {
8236 vki_au_evclass_map_t *classmap =
8237 (vki_au_evclass_map_t *) ARG3;
8238 PRE_FIELD_READ("auditsys(classmap.ec_number)",
8239 classmap->ec_number);
8240 PRE_FIELD_READ("auditsys(classmap.ec_class)",
8241 classmap->ec_class);
8243 break;
8244 case VKI_A_GETPINFO:
8245 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getpinfo"),
8246 long, code, int, cmd,
8247 struct vki_auditpinfo *, apinfo);
8249 if (ML_(safe_to_deref((void *) ARG3,
8250 sizeof(struct vki_auditpinfo)))) {
8251 struct vki_auditpinfo *apinfo =
8252 (struct vki_auditpinfo *) ARG3;
8253 PRE_FIELD_READ("auditsys(apinfo.ap_pid)", apinfo->ap_pid);
8254 PRE_MEM_WRITE("auditsys(apinfo)", ARG3,
8255 sizeof(struct vki_auditpinfo));
8257 break;
8258 case VKI_A_SETPMASK:
8259 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setpmask"),
8260 long, code, int, cmd,
8261 struct vki_auditpinfo *, apinfo);
8262 PRE_MEM_WRITE("auditsys(apinfo)", ARG3,
8263 sizeof(struct vki_auditpinfo));
8264 break;
8265 case VKI_A_GETPINFO_ADDR:
8266 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getpinfo_addr"),
8267 long, code, int, cmd,
8268 struct vki_auditpinfo_addr *, apinfo, int, length);
8270 if (ML_(safe_to_deref((void *) ARG3,
8271 sizeof(struct vki_auditpinfo_addr)))) {
8272 struct vki_auditpinfo_addr *apinfo_addr =
8273 (struct vki_auditpinfo_addr *) ARG3;
8274 PRE_FIELD_READ("auditsys(apinfo_addr.ap_pid)",
8275 apinfo_addr->ap_pid);
8276 PRE_MEM_WRITE("auditsys(apinfo_addr)", ARG3, ARG4);
8278 break;
8279 case VKI_A_GETKAUDIT:
8280 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "getkaudit"),
8281 long, code, int, cmd,
8282 vki_auditinfo_addr_t *, kaudit, int, length);
8283 PRE_MEM_WRITE("auditsys(kaudit)", ARG3, ARG4);
8284 break;
8285 case VKI_A_SETKAUDIT:
8286 PRE_REG_READ4(long, SC3("auditsys", "auditctl", "setkaudit"),
8287 long, code, int, cmd,
8288 vki_auditinfo_addr_t *, kaudit, int, length);
8289 PRE_MEM_READ("auditsys(kaudit)", ARG3, ARG4);
8290 break;
8291 case VKI_A_GETAMASK:
8292 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "getamask"),
8293 long, code, int, cmd, vki_au_mask_t *, amask);
8294 PRE_MEM_WRITE("auditsys(amask)", ARG3, sizeof(vki_au_mask_t));
8295 break;
8296 case VKI_A_SETAMASK:
8297 PRE_REG_READ3(long, SC3("auditsys", "auditctl", "setamask"),
8298 long, code, int, cmd, vki_au_mask_t *, amask);
8299 PRE_MEM_READ("auditsys(amask)", ARG3, sizeof(vki_au_mask_t));
8300 break;
8301 default:
8302 VG_(unimplemented)("Syswrap of the auditsys(auditctl) call "
8303 "with cmd %lu.", ARG2);
8304 /*NOTREACHED*/
8305 break;
8307 break;
8308 case VKI_BSM_GETAUDIT_ADDR:
8309 /* Libbsm: int getaudit_addr(auditinfo_addr_t *ai, int len); */
8310 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
8311 PRE_REG_READ3(long, SC2("auditsys", "getaudit_addr"), long, code,
8312 vki_auditinfo_addr_t *, ai, int, len);
8313 PRE_MEM_WRITE("auditsys(ai)", ARG2, ARG3);
8314 break;
8315 case VKI_BSM_SETAUDIT_ADDR:
8316 /* Libbsm: int setaudit_addr(auditinfo_addr_t *ai, int len); */
8317 PRINT("sys_auditsys ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
8318 PRE_REG_READ3(long, SC2("auditsys", "setaudit_addr"), long, code,
8319 vki_auditinfo_addr_t *, ai, int, len);
8320 PRE_MEM_READ("auditsys(ai)", ARG2, ARG3);
8321 break;
8322 case VKI_BSM_AUDITDOOR:
8323 /* Libbsm: int auditdoor(int fd); */
8324 PRINT("sys_auditsys ( %ld, %ld )", SARG1, SARG2);
8325 PRE_REG_READ2(long, SC2("auditsys", "door"), long, code, int, fd);
8327 /* Be strict. */
8328 if (!ML_(fd_allowed)(ARG2, SC2("auditsys", "door")"(fd)",
8329 tid, False))
8330 SET_STATUS_Failure(VKI_EBADF);
8331 break;
8332 default:
8333 VG_(unimplemented)("Syswrap of the auditsys call with code %lu.", ARG1);
8334 /*NOTREACHED*/
8335 break;
8339 POST(sys_auditsys)
8341 switch (ARG1 /*code*/) {
8342 case VKI_BSM_GETAUID:
8343 POST_MEM_WRITE(ARG2, sizeof(vki_au_id_t));
8344 break;
8345 case VKI_BSM_SETAUID:
8346 break;
8347 case VKI_BSM_GETAUDIT:
8348 POST_MEM_WRITE(ARG2, sizeof(vki_auditinfo_t));
8349 break;
8350 case VKI_BSM_SETAUDIT:
8351 case VKI_BSM_AUDIT:
8352 break;
8353 case VKI_BSM_AUDITCTL:
8354 switch (ARG2 /*cmd*/) {
8355 case VKI_A_GETPOLICY:
8356 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
8357 break;
8358 case VKI_A_SETPOLICY:
8359 break;
8360 case VKI_A_GETKMASK:
8361 POST_MEM_WRITE(ARG3, sizeof(vki_au_mask_t));
8362 break;
8363 case VKI_A_SETKMASK:
8364 break;
8365 case VKI_A_GETQCTRL:
8366 POST_MEM_WRITE(ARG3, sizeof(struct vki_au_qctrl));
8367 break;
8368 case VKI_A_SETQCTRL:
8369 break;
8370 case VKI_A_GETCWD:
8371 case VKI_A_GETCAR:
8372 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
8373 break;
8374 #if defined(SOLARIS_AUDITON_STAT)
8375 case VKI_A_GETSTAT:
8376 POST_MEM_WRITE(ARG3, sizeof(vki_au_stat_t));
8377 break;
8378 case VKI_A_SETSTAT:
8379 #endif /* SOLARIS_AUDITON_STAT */
8380 case VKI_A_SETUMASK:
8381 case VKI_A_SETSMASK:
8382 break;
8383 case VKI_A_GETCOND:
8384 POST_MEM_WRITE(ARG3, sizeof(int));
8385 break;
8386 case VKI_A_SETCOND:
8387 break;
8388 case VKI_A_GETCLASS:
8389 POST_MEM_WRITE(ARG3, sizeof(vki_au_evclass_map_t));
8390 break;
8391 case VKI_A_SETCLASS:
8392 break;
8393 case VKI_A_GETPINFO:
8394 POST_MEM_WRITE(ARG3, sizeof(struct vki_auditpinfo));
8395 break;
8396 case VKI_A_SETPMASK:
8397 break;
8398 case VKI_A_GETPINFO_ADDR:
8399 POST_MEM_WRITE(ARG3, sizeof(struct auditpinfo_addr));
8400 break;
8401 case VKI_A_GETKAUDIT:
8402 POST_MEM_WRITE(ARG3, sizeof(vki_auditinfo_addr_t));
8403 break;
8404 case VKI_A_SETKAUDIT:
8405 break;
8406 case VKI_A_GETAMASK:
8407 POST_MEM_WRITE(ARG3, sizeof(vki_au_mask_t));
8408 break;
8409 case VKI_A_SETAMASK:
8410 break;
8412 break;
8413 case VKI_BSM_GETAUDIT_ADDR:
8414 POST_MEM_WRITE(ARG2, sizeof(vki_auditinfo_addr_t));
8415 break;
8416 case VKI_BSM_SETAUDIT_ADDR:
8417 break;
8418 case VKI_BSM_AUDITDOOR:
8419 break;
8423 PRE(sys_p_online)
8425 /* int p_online(processorid_t processorid, int flag); */
8426 PRINT("sys_p_online ( %ld, %ld )", SARG1, SARG2);
8427 PRE_REG_READ2(long, "p_online", vki_processorid_t, processorid, int, flag);
8430 PRE(sys_sigqueue)
8432 /* int sigqueue(pid_t pid, int signo, void *value,
8433 int si_code, timespec_t *timeout);
8435 PRINT("sys_sigqueue ( %ld, %ld, %#lx, %ld, %#lx )",
8436 SARG1, SARG2, ARG3, SARG4, ARG5);
8437 PRE_REG_READ5(long, "sigqueue", vki_pid_t, pid, int, signo,
8438 void *, value, int, si_code,
8439 vki_timespec_t *, timeout);
8441 if (ARG5)
8442 PRE_MEM_READ("sigqueue(timeout)", ARG5, sizeof(vki_timespec_t));
8444 if (!ML_(client_signal_OK)(ARG2)) {
8445 SET_STATUS_Failure(VKI_EINVAL);
8446 return;
8449 /* If we're sending SIGKILL, check to see if the target is one of
8450 our threads and handle it specially. */
8451 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) {
8452 SET_STATUS_Success(0);
8453 } else {
8454 SysRes res = VG_(do_syscall5)(SYSNO, ARG1, ARG2, ARG3, ARG4,
8455 ARG5);
8456 SET_STATUS_from_SysRes(res);
8459 if (VG_(clo_trace_signals))
8460 VG_(message)(Vg_DebugMsg,
8461 "sigqueue: signal %ld queued for pid %ld\n",
8462 SARG2, SARG1);
8464 /* Check to see if this gave us a pending signal. */
8465 *flags |= SfPollAfter;
8468 PRE(sys_clock_gettime)
8470 /* int clock_gettime(clockid_t clock_id, struct timespec *tp); */
8471 PRINT("sys_clock_gettime ( %ld, %#lx )", SARG1, ARG2);
8472 PRE_REG_READ2(long, "clock_gettime", vki_clockid_t, clock_id,
8473 struct timespec *, tp);
8474 PRE_MEM_WRITE("clock_gettime(tp)", ARG2, sizeof(struct vki_timespec));
8477 POST(sys_clock_gettime)
8479 POST_MEM_WRITE(ARG2, sizeof(struct vki_timespec));
8482 PRE(sys_clock_settime)
8484 /* int clock_settime(clockid_t clock_id, const struct timespec *tp); */
8485 PRINT("sys_clock_settime ( %ld, %#lx )", SARG1, ARG2);
8486 PRE_REG_READ2(long, "clock_settime", vki_clockid_t, clock_id,
8487 const struct timespec *, tp);
8488 PRE_MEM_READ("clock_settime(tp)", ARG2, sizeof(struct vki_timespec));
8491 PRE(sys_clock_getres)
8493 /* int clock_getres(clockid_t clock_id, struct timespec *res); */
8494 PRINT("sys_clock_getres ( %ld, %#lx )", SARG1, ARG2);
8495 PRE_REG_READ2(long, "clock_getres", vki_clockid_t, clock_id,
8496 struct timespec *, res);
8498 if (ARG2)
8499 PRE_MEM_WRITE("clock_getres(res)", ARG2, sizeof(struct vki_timespec));
8502 POST(sys_clock_getres)
8504 if (ARG2)
8505 POST_MEM_WRITE(ARG2, sizeof(struct vki_timespec));
8508 PRE(sys_timer_create)
8510 /* int timer_create(clockid_t clock_id,
8511 struct sigevent *evp, timer_t *timerid);
8513 PRINT("sys_timer_create ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
8514 PRE_REG_READ3(long, "timer_create", vki_clockid_t, clock_id,
8515 struct vki_sigevent *, evp, vki_timer_t *, timerid);
8517 if (ARG2) {
8518 struct vki_sigevent *evp = (struct vki_sigevent *) ARG2;
8519 PRE_FIELD_READ("timer_create(evp.sigev_notify)", evp->sigev_notify);
8520 PRE_FIELD_READ("timer_create(evp.sigev_signo)", evp->sigev_signo);
8521 PRE_FIELD_READ("timer_create(evp.sigev_value.sival_int)",
8522 evp->sigev_value.sival_int);
8524 /* Be safe. */
8525 if (ML_(safe_to_deref(evp, sizeof(struct vki_sigevent)))) {
8526 if ((evp->sigev_notify == VKI_SIGEV_PORT) ||
8527 (evp->sigev_notify == VKI_SIGEV_THREAD))
8528 PRE_MEM_READ("timer_create(evp.sigev_value.sival_ptr)",
8529 (Addr) evp->sigev_value.sival_ptr,
8530 sizeof(vki_port_notify_t));
8534 PRE_MEM_WRITE("timer_create(timerid)", ARG3, sizeof(vki_timer_t));
8537 POST(sys_timer_create)
8539 POST_MEM_WRITE(ARG3, sizeof(vki_timer_t));
8542 PRE(sys_timer_delete)
8544 /* int timer_delete(timer_t timerid); */
8545 PRINT("sys_timer_delete ( %ld )", SARG1);
8546 PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid);
8549 PRE(sys_timer_settime)
8551 /* int timer_settime(timer_t timerid, int flags,
8552 const struct itimerspec *value,
8553 struct itimerspec *ovalue);
8555 PRINT("sys_timer_settime ( %ld, %ld, %#lx, %#lx )",
8556 SARG1, SARG2, ARG3, ARG4);
8557 PRE_REG_READ4(long, "timer_settime", vki_timer_t, timerid,
8558 int, flags, const struct vki_itimerspec *, value,
8559 struct vki_itimerspec *, ovalue);
8560 PRE_MEM_READ("timer_settime(value)",
8561 ARG3, sizeof(struct vki_itimerspec));
8562 if (ARG4)
8563 PRE_MEM_WRITE("timer_settime(ovalue)",
8564 ARG4, sizeof(struct vki_itimerspec));
8567 POST(sys_timer_settime)
8569 if (ARG4)
8570 POST_MEM_WRITE(ARG4, sizeof(struct vki_itimerspec));
8573 PRE(sys_timer_gettime)
8575 /* int timer_gettime(timer_t timerid, struct itimerspec *value); */
8576 PRINT("sys_timer_gettime ( %ld, %#lx )", SARG1, ARG2);
8577 PRE_REG_READ2(long, "timer_gettime", vki_timer_t, timerid,
8578 struct vki_itimerspec *, value);
8579 PRE_MEM_WRITE("timer_gettime(value)",
8580 ARG2, sizeof(struct vki_itimerspec));
8583 POST(sys_timer_gettime)
8585 POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerspec));
8588 PRE(sys_timer_getoverrun)
8590 /* int timer_getoverrun(timer_t timerid); */
8591 PRINT("sys_timer_getoverrun ( %ld )", SARG1);
8592 PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid);
8595 PRE(sys_facl)
8597 /* int facl(int fildes, int cmd, int nentries, void *aclbufp); */
8598 PRINT("sys_facl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
8600 PRE_REG_READ4(long, "facl", int, fildes, int, cmd,
8601 int, nentries, void *, aclbufp);
8603 switch (ARG2 /*cmd*/) {
8604 case VKI_SETACL:
8605 if (ARG4)
8606 PRE_MEM_READ("facl(aclbufp)", ARG4, sizeof(vki_aclent_t));
8607 break;
8608 case VKI_GETACL:
8609 PRE_MEM_WRITE("facl(aclbufp)", ARG4, ARG3 * sizeof(vki_aclent_t));
8610 break;
8611 case VKI_GETACLCNT:
8612 break;
8613 case VKI_ACE_SETACL:
8614 if (ARG4)
8615 PRE_MEM_READ("facl(aclbufp)", ARG4, sizeof(vki_ace_t));
8616 break;
8617 case VKI_ACE_GETACL:
8618 PRE_MEM_WRITE("facl(aclbufp)", ARG4, ARG3 * sizeof(vki_ace_t));
8619 break;
8620 case VKI_ACE_GETACLCNT:
8621 break;
8622 default:
8623 VG_(unimplemented)("Syswrap of the facl call with cmd %ld.", SARG2);
8624 /*NOTREACHED*/
8625 break;
8628 /* Be strict. */
8629 if (!ML_(fd_allowed)(ARG1, "facl", tid, False))
8630 SET_STATUS_Failure(VKI_EBADF);
8633 POST(sys_facl)
8635 switch (ARG2 /*cmd*/) {
8636 case VKI_SETACL:
8637 break;
8638 case VKI_GETACL:
8639 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_aclent_t));
8640 break;
8641 case VKI_GETACLCNT:
8642 break;
8643 case VKI_ACE_SETACL:
8644 break;
8645 case VKI_ACE_GETACL:
8646 POST_MEM_WRITE(ARG4, ARG3 * sizeof(vki_ace_t));
8647 break;
8648 case VKI_ACE_GETACLCNT:
8649 break;
8650 default:
8651 vg_assert(0);
8652 break;
8656 static Int pre_check_and_close_fds(ThreadId tid, const HChar *name,
8657 vki_door_desc_t *desc_ptr,
8658 vki_uint_t desc_num)
8660 vki_uint_t i;
8662 /* Verify passed file descriptors. */
8663 for (i = 0; i < desc_num; i++) {
8664 vki_door_desc_t *desc = &desc_ptr[i];
8665 if ((desc->d_attributes & DOOR_DESCRIPTOR) &&
8666 (desc->d_attributes & DOOR_RELEASE)) {
8667 Int fd = desc->d_data.d_desc.d_descriptor;
8669 /* Detect and negate attempts by the client to close Valgrind's fds.
8670 Also if doing -d style logging (which is to fd = 2 = stderr),
8671 don't allow that to be closed either. */
8672 if (!ML_(fd_allowed)(fd, name, tid, False) ||
8673 (fd == 2 && VG_(debugLog_getLevel)() > 0))
8674 return VKI_EBADF;
8678 /* All fds are allowed, record information about the closed ones.
8680 Note: Recording information about any closed fds should generally happen
8681 in a post wrapper but it is not possible in this case because door calls
8682 are "very blocking", if the information was recorded after the syscall
8683 finishes then it would be out-of-date during the call, i.e. while the
8684 syscall is blocked in the kernel. Therefore, we record closed fds for
8685 this specific syscall in the PRE wrapper. Unfortunately, this creates
8686 a problem when the syscall fails, for example, door_call() can fail with
8687 EBADF or EFAULT and then no fds are released. If that happens the
8688 information about opened fds is incorrect. This should be very rare (I
8689 hope) and such a condition is also reported in the post wrapper. */
8690 if (VG_(clo_track_fds)) {
8691 for (i = 0; i < desc_num; i++) {
8692 vki_door_desc_t *desc = &desc_ptr[i];
8693 if ((desc->d_attributes & DOOR_DESCRIPTOR) &&
8694 (desc->d_attributes & DOOR_RELEASE)) {
8695 Int fd = desc->d_data.d_desc.d_descriptor;
8696 ML_(record_fd_close)(fd);
8701 return 0;
8704 static void post_record_fds(ThreadId tid, const HChar *name,
8705 vki_door_desc_t *desc_ptr, vki_uint_t desc_num)
8707 vki_uint_t i;
8709 /* Record returned file descriptors. */
8710 for (i = 0; i < desc_num; i++) {
8711 vki_door_desc_t *desc = &desc_ptr[i];
8712 if (desc->d_attributes & DOOR_DESCRIPTOR) {
8713 Int fd = desc->d_data.d_desc.d_descriptor;
8714 if (!ML_(fd_allowed)(fd, name, tid, True)) {
8715 /* Unfortunately, we cannot recover at this point and have to fail
8716 hard. */
8717 VG_(message)(Vg_UserMsg, "The %s syscall returned an unallowed"
8718 "file descriptor %d.\n", name, fd);
8719 VG_(exit)(101);
8721 else if (VG_(clo_track_fds))
8722 ML_(record_fd_open_named)(tid, fd);
8727 /* Handles repository door protocol request over client door fd. */
8728 static void repository_door_pre_mem_door_call_hook(ThreadId tid, Int fd,
8729 void *data_ptr,
8730 SizeT data_size)
8732 vki_rep_protocol_request_t *p = (vki_rep_protocol_request_t *) data_ptr;
8733 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8734 "request->rpr_request)", p->rpr_request);
8736 if (ML_(safe_to_deref)(p, sizeof(vki_rep_protocol_request_t))) {
8737 switch (p->rpr_request) {
8738 case VKI_REP_PROTOCOL_CLOSE:
8739 break;
8740 case VKI_REP_PROTOCOL_ENTITY_SETUP:
8742 struct vki_rep_protocol_entity_setup *r =
8743 (struct vki_rep_protocol_entity_setup *) p;
8744 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8745 "entity_setup->rpr_entityid)", r->rpr_entityid);
8746 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8747 "entity_setup->rpr_entitytype)", r->rpr_entitytype);
8749 break;
8750 case VKI_REP_PROTOCOL_ENTITY_NAME:
8752 struct vki_rep_protocol_entity_name *r =
8753 (struct vki_rep_protocol_entity_name *) p;
8754 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8755 "entity_name->rpr_entityid)", r->rpr_entityid);
8756 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8757 "entity_name->rpr_answertype)", r->rpr_answertype);
8759 break;
8760 #if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 24) && (SOLARIS_REPCACHE_PROTOCOL_VERSION <= 30)
8761 case VKI_REP_PROTOCOL_ENTITY_FMRI:
8763 struct vki_rep_protocol_entity_fmri *r =
8764 (struct vki_rep_protocol_entity_fmri *) p;
8765 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8766 "entity_fmri->rpr_entityid)", r->rpr_entityid);
8768 break;
8769 #endif /* 24 <= SOLARIS_REPCACHE_PROTOCOL_VERSION =< 30 */
8770 #if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 25)
8771 case VKI_REP_PROTOCOL_ENTITY_GET_ROOT:
8773 struct vki_rep_protocol_entity_root *r =
8774 (struct vki_rep_protocol_entity_root *) p;
8775 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8776 "entity_root->rpr_entityid)", r->rpr_entityid);
8777 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8778 "entity_root->rpr_outid)", r->rpr_outid);
8780 break;
8781 #endif /* SOLARIS_REPCACHE_PROTOCOL_VERSION >= 25 */
8782 case VKI_REP_PROTOCOL_ENTITY_GET:
8784 struct vki_rep_protocol_entity_get *r =
8785 (struct vki_rep_protocol_entity_get *) p;
8786 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8787 "entity_get->rpr_entityid)", r->rpr_entityid);
8788 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8789 "entity_get->rpr_object)", r->rpr_object);
8791 break;
8792 case VKI_REP_PROTOCOL_ENTITY_GET_CHILD:
8793 #if (SOLARIS_REPCACHE_PROTOCOL_VERSION >= 31)
8794 case VKI_REP_PROTOCOL_ENTITY_GET_CHILD_COMPOSED:
8795 #endif
8797 struct vki_rep_protocol_entity_get_child *r =
8798 (struct vki_rep_protocol_entity_get_child *) p;
8799 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8800 "entity_get_child->rpr_entityid)", r->rpr_entityid);
8801 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8802 "entity_get_child->rpr_childid)", r->rpr_childid);
8803 PRE_MEM_RASCIIZ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8804 "entity_get_child->rpr_name)", (Addr) r->rpr_name);
8806 break;
8807 case VKI_REP_PROTOCOL_ENTITY_GET_PARENT:
8809 struct vki_rep_protocol_entity_parent *r =
8810 (struct vki_rep_protocol_entity_parent *) p;
8811 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8812 "entity_get_parent->rpr_entityid)", r->rpr_entityid);
8813 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8814 "entity_get_parent->rpr_outid)", r->rpr_outid);
8816 break;
8817 case VKI_REP_PROTOCOL_ENTITY_RESET:
8819 struct vki_rep_protocol_entity_reset *r =
8820 (struct vki_rep_protocol_entity_reset *) p;
8821 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8822 "entity_reset->rpr_entityid)", r->rpr_entityid);
8824 break;
8825 case VKI_REP_PROTOCOL_ENTITY_TEARDOWN:
8827 struct vki_rep_protocol_entity_teardown *r =
8828 (struct vki_rep_protocol_entity_teardown *) p;
8829 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8830 "entity_teardown->rpr_entityid)", r->rpr_entityid);
8832 break;
8833 case VKI_REP_PROTOCOL_ITER_READ:
8835 struct vki_rep_protocol_iter_read *r =
8836 (struct vki_rep_protocol_iter_read *) p;
8837 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8838 "iter_read->rpr_iterid)", r->rpr_iterid);
8839 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8840 "iter_read->rpr_sequence)", r->rpr_sequence);
8841 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8842 "iter_read->rpr_entityid)", r->rpr_entityid);
8844 break;
8845 case VKI_REP_PROTOCOL_ITER_READ_VALUE:
8847 struct vki_rep_protocol_iter_read_value *r =
8848 (struct vki_rep_protocol_iter_read_value *) p;
8849 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8850 "iter_read_value->rpr_iterid)", r->rpr_iterid);
8851 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8852 "iter_read_value->rpr_sequence)", r->rpr_sequence);
8854 break;
8855 case VKI_REP_PROTOCOL_ITER_RESET:
8856 case VKI_REP_PROTOCOL_ITER_SETUP:
8857 case VKI_REP_PROTOCOL_ITER_TEARDOWN:
8859 struct vki_rep_protocol_iter_request *r =
8860 (struct vki_rep_protocol_iter_request *) p;
8861 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8862 "iter_request->rpr_iterid)", r->rpr_iterid);
8864 break;
8865 case VKI_REP_PROTOCOL_ITER_START:
8867 struct vki_rep_protocol_iter_start *r =
8868 (struct vki_rep_protocol_iter_start *) p;
8869 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8870 "iter_start->rpr_iterid)", r->rpr_iterid);
8871 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8872 "iter_start->rpr_entity)", r->rpr_entity);
8873 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8874 "iter_start->rpr_itertype)", r->rpr_itertype);
8875 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8876 "iter_start->rpr_flags)", r->rpr_flags);
8877 PRE_MEM_RASCIIZ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8878 "iter_start->rpr_pattern)", (Addr) r->rpr_pattern);
8880 break;
8881 case VKI_REP_PROTOCOL_PROPERTY_GET_TYPE:
8882 case VKI_REP_PROTOCOL_PROPERTY_GET_VALUE:
8884 struct vki_rep_protocol_property_request *r =
8885 (struct vki_rep_protocol_property_request *) p;
8886 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
8887 "property_request->rpr_entityid)", r->rpr_entityid);
8889 break;
8890 default:
8891 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME
8892 " where rpr_request=%#x.", p->rpr_request);
8893 /* NOTREACHED */
8894 break;
8899 /* Handles repository door protocol response over client door fd. */
8900 static void repository_door_post_mem_door_call_hook(ThreadId tid, Int fd,
8901 void *rbuf, SizeT rsize)
8903 /* :TODO: Ideally we would need to match the response type with the
8904 previous request because response itself does not contain any
8905 type identification.
8906 For now simply make defined whole response buffer. */
8907 POST_MEM_WRITE((Addr) rbuf, rsize);
8910 /* Pre-syscall checks for params->data_ptr contents of a door_call(). */
8911 static void door_call_pre_mem_params_data(ThreadId tid, Int fd,
8912 void *data_ptr, SizeT data_size)
8914 const HChar *pathname;
8916 /* Get pathname of the door file descriptor, if not already done.
8917 Needed to dissect door service on the pathname below. */
8918 if (!VG_(clo_track_fds) && !ML_(fd_recorded)(fd)) {
8919 ML_(record_fd_open_named)(tid, fd);
8921 pathname = ML_(find_fd_recorded_by_fd)(fd);
8923 /* Debug-only printing. */
8924 if (0) {
8925 VG_(printf)("PRE(door_call) with fd=%d and filename=%s\n",
8926 fd, pathname);
8929 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
8930 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
8932 PRE_FIELD_READ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8933 "kcf_door_arg_t->da_version)", p->da_version);
8934 PRE_FIELD_READ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8935 "kcf_door_arg_t->da_iskernel)", p->da_iskernel);
8936 PRE_MEM_RASCIIZ("door_call(\"" VKI__PATH_KCFD_DOOR "\", "
8937 "kcf_door_arg_t->da_u.filename)",
8938 (Addr) p->vki_da_u.filename);
8939 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
8940 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
8942 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8943 "nss_pheader->nsc_callnumber)", p->nsc_callnumber);
8944 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
8945 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
8946 /* request from an application towards nscd */
8947 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8948 "nss_pheader->p_version)", p->p_version);
8949 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8950 "nss_pheader->dbd_off)", p->dbd_off);
8951 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8952 "nss_pheader->dbd_len)", p->dbd_len);
8953 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8954 "nss_pheader->key_off)", p->key_off);
8955 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8956 "nss_pheader->key_len)", p->key_len);
8957 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8958 "nss_pheader->data_off)", p->data_off);
8959 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8960 "nss_pheader->data_len)", p->data_len);
8961 /* Fields ext_off and ext_len are set only sporadically. */
8962 PRE_FIELD_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", "
8963 "nss_pheader->pbufsiz)", p->pbufsiz);
8964 PRE_MEM_WRITE("door_call(\"" VKI_NAME_SERVICE_DOOR "\", pbuf)",
8965 (Addr) p, p->pbufsiz);
8967 if (p->dbd_len > 0) {
8968 vki_nss_dbd_t *dbd
8969 = (vki_nss_dbd_t *) ((HChar *) p + p->dbd_off);
8971 PRE_MEM_READ("door_call(\"" VKI_NAME_SERVICE_DOOR
8972 "\", nss_dbd)", (Addr) dbd, sizeof(vki_nss_dbd_t));
8973 if (ML_(safe_to_deref)(dbd, sizeof(vki_nss_dbd_t))) {
8974 if (dbd->o_name != 0)
8975 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8976 "\", nss_dbd->o_name)", (Addr) ((HChar *) p
8977 + p->dbd_off + dbd->o_name));
8978 if (dbd->o_config_name != 0)
8979 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8980 "\", nss_dbd->o_config_name)",
8981 (Addr) ((HChar *) p + p->dbd_off
8982 + dbd->o_config_name));
8983 if (dbd->o_default_config != 0)
8984 PRE_MEM_RASCIIZ("door_call(\"" VKI_NAME_SERVICE_DOOR
8985 "\", nss_dbd->o_default_config)",
8986 (Addr) ((HChar *) p + p->dbd_off +
8987 dbd->o_default_config));
8991 PRE_MEM_READ("door_call(\"" VKI_NAME_SERVICE_DOOR "\", nss->key)",
8992 (Addr) ((HChar *) p + p->key_off), p->key_len);
8993 } else {
8994 /* request from a child nscd towards parent nscd */
8995 VG_(unimplemented)("Door wrapper of child/parent nscd.");
8998 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
8999 vki_repository_door_request_t *p =
9000 (vki_repository_door_request_t *) data_ptr;
9002 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
9003 "request->rdr_version)", p->rdr_version);
9004 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
9005 "request->rdr_request)", p->rdr_request);
9006 if (ML_(safe_to_deref)(p, sizeof(vki_repository_door_request_t))) {
9007 if (p->rdr_version == VKI_REPOSITORY_DOOR_VERSION) {
9008 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
9009 "request->rdr_flags)", p->rdr_flags);
9010 PRE_FIELD_READ("door_call(\"" VKI_REPOSITORY_DOOR_NAME "\", "
9011 "request->rdr_debug)", p->rdr_debug);
9012 } else {
9013 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME
9014 " where version=%u.", p->rdr_version);
9017 } else {
9018 const OpenDoor *open_door = door_find_by_fd(fd);
9019 if ((open_door != NULL) && (open_door->pre_mem_hook != NULL)) {
9020 open_door->pre_mem_hook(tid, fd, data_ptr, data_size);
9021 } else {
9022 if (SimHintiS(SimHint_lax_doors, VG_(clo_sim_hints))) {
9024 * Be very lax about door syscall handling over unrecognized
9025 * door file descriptors. Does not require that full buffer
9026 * is initialized when writing. Without this, programs using
9027 * libdoor(3LIB) functionality with completely proprietary
9028 * semantics may report large number of false positives.
9030 } else {
9031 static Int moans = 3;
9033 /* generic default */
9034 if (moans > 0 && !VG_(clo_xml)) {
9035 moans--;
9036 VG_(umsg)(
9037 "Warning: noted and generically handled door call\n"
9038 " on file descriptor %d (filename: %s).\n"
9039 " This could cause spurious value errors to appear.\n"
9040 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.\n"
9041 " Alternatively you may find '--sim-hints=lax-doors' option useful.\n",
9042 fd, pathname);
9044 PRE_MEM_READ("door_call(params->data_ptr)",
9045 (Addr) data_ptr, data_size);
9051 /* Post-syscall checks for params->rbuf contents of a door_call(). */
9052 static void door_call_post_mem_params_rbuf(ThreadId tid, Int fd,
9053 void *rbuf, SizeT rsize,
9054 const vki_door_desc_t *desc_ptr,
9055 vki_uint_t desc_num)
9057 const HChar *pathname = ML_(find_fd_recorded_by_fd)(fd);
9059 /* Debug-only printing. */
9060 if (0) {
9061 VG_(printf)("POST(door_call) with fd=%d and filename=%s\n",
9062 fd, pathname);
9065 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9066 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) rbuf;
9068 POST_FIELD_WRITE(p->da_version);
9069 POST_FIELD_WRITE(p->vki_da_u.result.status);
9070 POST_MEM_WRITE((Addr) p->vki_da_u.result.signature,
9071 p->vki_da_u.result.siglen);
9072 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9073 vki_nss_pheader_t *p = (vki_nss_pheader_t *) rbuf;
9075 POST_FIELD_WRITE(p->nsc_callnumber);
9076 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9077 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9078 /* response from nscd to an application */
9079 POST_FIELD_WRITE(p->p_status);
9080 POST_FIELD_WRITE(p->p_errno);
9081 POST_FIELD_WRITE(p->p_herrno);
9082 POST_FIELD_WRITE(p->dbd_off);
9083 POST_FIELD_WRITE(p->dbd_len);
9084 POST_FIELD_WRITE(p->key_off);
9085 POST_FIELD_WRITE(p->key_len);
9086 POST_FIELD_WRITE(p->data_off);
9087 POST_FIELD_WRITE(p->data_len);
9088 POST_FIELD_WRITE(p->ext_off);
9089 POST_FIELD_WRITE(p->ext_len);
9090 POST_FIELD_WRITE(p->pbufsiz);
9092 if (p->pbufsiz <= rsize) {
9093 if (p->dbd_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9094 SizeT len = MIN(p->dbd_len, p->pbufsiz - p->dbd_off);
9095 POST_MEM_WRITE((Addr) ((HChar *) p + p->dbd_off), len);
9098 if (p->key_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9099 SizeT len = MIN(p->key_len, p->pbufsiz - p->key_off);
9100 POST_MEM_WRITE((Addr) ((HChar *) p + p->key_off), len);
9103 if (p->data_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9104 SizeT len = MIN(p->data_len, p->pbufsiz - p->data_off);
9105 POST_MEM_WRITE((Addr) ((HChar *) p + p->data_off), len);
9108 if (p->ext_off < p->pbufsiz - sizeof(vki_nss_pheader_t)) {
9109 SizeT len = MIN(p->ext_len, p->pbufsiz - p->ext_off);
9110 POST_MEM_WRITE((Addr) ((HChar *) p + p->ext_off), len);
9113 } else {
9114 /* response from parent nscd to a child nscd */
9115 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9118 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9119 POST_FIELD_WRITE(((vki_repository_door_response_t *) rbuf)->rdr_status);
9120 /* A new client door fd is passed over the global repository door. */
9121 if ((desc_ptr != NULL) && (desc_num > 0)) {
9122 if (desc_ptr[0].d_attributes & DOOR_DESCRIPTOR) {
9123 door_record_client(tid, desc_ptr[0].d_data.d_desc.d_descriptor,
9124 repository_door_pre_mem_door_call_hook,
9125 repository_door_post_mem_door_call_hook);
9128 } else {
9129 const OpenDoor *open_door = door_find_by_fd(fd);
9130 if ((open_door != NULL) && (open_door->post_mem_hook != NULL)) {
9131 open_door->post_mem_hook(tid, fd, rbuf, rsize);
9132 } else {
9133 /* generic default */
9134 POST_MEM_WRITE((Addr) rbuf, rsize);
9139 /* Pre-syscall checks for data_ptr contents in a door_return(). */
9140 static void door_return_pre_mem_data(ThreadId tid, Addr server_procedure,
9141 void *data_ptr, SizeT data_size)
9143 if ((data_size == 0) || (server_procedure == 0)) {
9144 /* There is nothing to check. This usually happens during thread's
9145 first call to door_return(). */
9146 return;
9149 /* Get pathname of the door file descriptor based on the
9150 door server procedure (that's all we have).
9151 Needed to dissect door service on the pathname below. */
9152 const OpenDoor *open_door = door_find_by_proc(server_procedure);
9153 const HChar *pathname = (open_door != NULL) ? open_door->pathname : NULL;
9154 Int fd = (open_door != NULL) ? open_door->fd : -1;
9156 /* Debug-only printing. */
9157 if (0) {
9158 VG_(printf)("PRE(door_return) with fd=%d and filename=%s "
9159 "(nr_doors_recorded=%u)\n",
9160 fd, pathname, nr_doors_recorded);
9163 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9164 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
9166 PRE_FIELD_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9167 "kcf_door_arg_t->da_version)", p->da_version);
9168 PRE_FIELD_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9169 "kcf_door_arg_t->da_u.result.status)",
9170 p->vki_da_u.result.status);
9171 PRE_MEM_READ("door_return(\"" VKI__PATH_KCFD_DOOR "\", "
9172 "kcf_door_arg_t->da_u.result.signature)",
9173 (Addr) p->vki_da_u.result.signature,
9174 p->vki_da_u.result.siglen);
9175 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9176 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
9178 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9179 "nss_pheader->nsc_callnumber)", p->nsc_callnumber);
9180 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9181 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9182 /* response from nscd to an application */
9183 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9184 "nss_pheader->p_status)", p->p_status);
9185 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9186 "nss_pheader->p_errno)", p->p_errno);
9187 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9188 "nss_pheader->p_herrno)", p->p_herrno);
9189 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9190 "nss_pheader->dbd_off)", p->dbd_off);
9191 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9192 "nss_pheader->dbd_len)", p->dbd_len);
9193 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9194 "nss_pheader->data_off)", p->data_off);
9195 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9196 "nss_pheader->data_len)", p->data_len);
9197 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9198 "nss_pheader->ext_off)", p->ext_off);
9199 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9200 "nss_pheader->ext_len)", p->ext_len);
9201 PRE_FIELD_READ("door_return(\"" VKI_NAME_SERVICE_DOOR "\", "
9202 "nss_pheader->pbufsiz)", p->pbufsiz);
9203 PRE_MEM_WRITE("door_return(\"" VKI_NAME_SERVICE_DOOR "\", pbuf)",
9204 (Addr) p, p->pbufsiz);
9205 PRE_MEM_READ("door_return(\"" VKI_NAME_SERVICE_DOOR
9206 "\", nss->data)",
9207 (Addr) ((HChar *) p + p->data_off), p->data_len);
9208 PRE_MEM_READ("door_return(\"" VKI_NAME_SERVICE_DOOR
9209 "\", nss->ext)",
9210 (Addr) ((HChar *) p + p->ext_off), p->ext_len);
9211 } else {
9212 /* response from parent nscd to a child nscd */
9213 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9216 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9217 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME);
9218 } else {
9219 if (SimHintiS(SimHint_lax_doors, VG_(clo_sim_hints))) {
9221 * Be very lax about door syscall handling over unrecognized
9222 * door file descriptors. Does not require that full buffer
9223 * is initialized when writing. Without this, programs using
9224 * libdoor(3LIB) functionality with completely proprietary
9225 * semantics may report large number of false positives.
9227 } else {
9228 static Int moans = 3;
9230 /* generic default */
9231 if (moans > 0 && !VG_(clo_xml)) {
9232 moans--;
9233 VG_(umsg)(
9234 "Warning: noted and generically handled door return\n"
9235 " on file descriptor %d (filename: %s).\n"
9236 " This could cause spurious value errors to appear.\n"
9237 " See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.\n"
9238 " Alternatively you may find '--sim-hints=lax-doors' option useful.\n",
9239 fd, pathname);
9241 PRE_MEM_READ("door_return(data_ptr)",
9242 (Addr) data_ptr, data_size);
9247 /* Post-syscall checks for data_ptr contents in a door_return(). */
9248 static void door_return_post_mem_data(ThreadId tid, Addr server_procedure,
9249 void *data_ptr, SizeT data_size)
9251 const OpenDoor *open_door = door_find_by_proc(server_procedure);
9252 const HChar *pathname = (open_door != NULL) ? open_door->pathname : NULL;
9254 /* Debug-only printing. */
9255 if (0) {
9256 Int fd = (open_door != NULL) ? open_door->fd : -1;
9257 VG_(printf)("POST(door_return) with fd=%d and filename=%s "
9258 "(nr_doors_recorded=%u)\n",
9259 fd, pathname, nr_doors_recorded);
9262 if (VG_STREQ(pathname, VKI__PATH_KCFD_DOOR)) {
9263 vki_kcf_door_arg_t *p = (vki_kcf_door_arg_t *) data_ptr;
9265 POST_FIELD_WRITE(p->da_version);
9266 POST_FIELD_WRITE(p->da_iskernel);
9267 POST_MEM_WRITE((Addr) p->vki_da_u.filename,
9268 VG_(strlen)(p->vki_da_u.filename) + 1);
9269 } else if (VG_STREQ(pathname, VKI_NAME_SERVICE_DOOR)) {
9270 vki_nss_pheader_t *p = (vki_nss_pheader_t *) data_ptr;
9272 POST_FIELD_WRITE(p->nsc_callnumber);
9273 if (ML_(safe_to_deref)(p, sizeof(vki_nss_pheader_t))) {
9274 if ((p->nsc_callnumber & VKI_NSCDV2CATMASK) == VKI_NSCD_CALLCAT_APP) {
9275 /* request from an application towards nscd */
9276 POST_FIELD_WRITE(p->p_version);
9277 POST_FIELD_WRITE(p->dbd_off);
9278 POST_FIELD_WRITE(p->dbd_len);
9279 POST_FIELD_WRITE(p->key_off);
9280 POST_FIELD_WRITE(p->key_len);
9281 POST_FIELD_WRITE(p->data_off);
9282 POST_FIELD_WRITE(p->data_len);
9283 POST_FIELD_WRITE(p->ext_off);
9284 POST_FIELD_WRITE(p->ext_len);
9285 POST_FIELD_WRITE(p->pbufsiz);
9287 if (p->dbd_len > 0) {
9288 vki_nss_dbd_t *dbd
9289 = (vki_nss_dbd_t *) ((HChar *) p + p->dbd_off);
9291 POST_MEM_WRITE((Addr) dbd, sizeof(vki_nss_dbd_t));
9292 if (ML_(safe_to_deref)(dbd, sizeof(vki_nss_dbd_t))) {
9293 SizeT headers_size = sizeof(vki_nss_pheader_t)
9294 + sizeof(vki_nss_dbd_t);
9296 if (dbd->o_name != 0) {
9297 HChar *name = (HChar *) p + p->dbd_off + dbd->o_name;
9298 SizeT name_len = VG_(strlen)(name) + 1;
9299 if (name_len <= data_size - headers_size)
9300 POST_MEM_WRITE((Addr) name, name_len);
9302 if (dbd->o_config_name != 0) {
9303 HChar *name = (HChar *) p + p->dbd_off + dbd->o_config_name;
9304 SizeT name_len = VG_(strlen)(name) + 1;
9305 if (name_len <= data_size - headers_size)
9306 POST_MEM_WRITE((Addr) name, name_len);
9308 if (dbd->o_default_config != 0) {
9309 HChar *name = (HChar *) p + p->dbd_off
9310 + dbd->o_default_config;
9311 SizeT name_len = VG_(strlen)(name) + 1;
9312 if (name_len <= data_size - headers_size)
9313 POST_MEM_WRITE((Addr) name, name_len);
9318 if (p->key_len <= data_size - p->key_off)
9319 POST_MEM_WRITE((Addr) ((HChar *) p + p->key_off), p->key_len);
9320 } else {
9321 /* request from a child nscd towards parent nscd */
9322 VG_(unimplemented)("Door wrapper of child/parent nscd.");
9325 } else if (VG_STREQ(pathname, VKI_REPOSITORY_DOOR_NAME)) {
9326 VG_(unimplemented)("Door wrapper of " VKI_REPOSITORY_DOOR_NAME);
9327 } else {
9328 /* generic default */
9329 POST_MEM_WRITE((Addr) data_ptr, data_size);
9333 PRE(sys_door)
9335 /* int doorfs(long arg1, long arg2, long arg3, long arg4, long arg5,
9336 long subcode); */
9337 ThreadState *tst = VG_(get_ThreadState)(tid);
9338 *flags |= SfMayBlock | SfPostOnFail;
9340 PRINT("sys_door ( %#lx, %#lx, %#lx, %#lx, %#lx, %ld )", ARG1, ARG2, ARG3,
9341 ARG4, ARG5, SARG6);
9343 /* Macro PRE_REG_READ6 cannot be simply used because not all ARGs are used
9344 in door() syscall variants. Note that ARG6 (subcode) is used always. */
9345 #define PRE_REG_READ_SIXTH_ONLY \
9346 if (VG_(tdict).track_pre_reg_read) { \
9347 PRA6("door", long, subcode); \
9350 switch (ARG6 /*subcode*/) {
9351 case VKI_DOOR_CREATE:
9352 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9353 PRE_REG_READ_SIXTH_ONLY;
9354 /* Note: the first argument to DOOR_CREATE is a server procedure.
9355 This could lead to a problem if the kernel tries to force the
9356 execution of this procedure, similarly to how signal handlers are
9357 executed. Fortunately, the kernel never does that (for user-space
9358 server procedures). The procedure is always executed by the standard
9359 library. */
9360 break;
9361 case VKI_DOOR_REVOKE:
9362 PRE_REG_READ1(long, "door", long, arg1);
9363 PRE_REG_READ_SIXTH_ONLY;
9364 if (!ML_(fd_allowed)(ARG1, "door_revoke", tid, False))
9365 SET_STATUS_Failure(VKI_EBADF);
9366 break;
9367 case VKI_DOOR_INFO:
9368 PRE_REG_READ2(long, "door", long, arg1, long, arg2);
9369 PRE_REG_READ_SIXTH_ONLY;
9370 PRE_MEM_WRITE("door_info(info)", ARG2, sizeof(vki_door_info_t));
9371 break;
9372 case VKI_DOOR_CALL:
9374 PRE_REG_READ2(long, "door", long, arg1, long, arg2);
9375 PRE_REG_READ_SIXTH_ONLY;
9377 Int rval = 0;
9378 vki_door_arg_t *params = (vki_door_arg_t*)ARG2;
9380 if (!ML_(fd_allowed)(ARG1, "door_call", tid, False))
9381 rval = VKI_EBADF;
9383 PRE_FIELD_READ("door_call(params->data_ptr)", params->data_ptr);
9384 PRE_FIELD_READ("door_call(params->data_size)", params->data_size);
9385 PRE_FIELD_READ("door_call(params->desc_ptr)", params->desc_ptr);
9386 PRE_FIELD_READ("door_call(params->desc_num)", params->desc_num);
9387 PRE_FIELD_READ("door_call(params->rbuf)", params->rbuf);
9388 PRE_FIELD_READ("door_call(params->rsize)", params->rsize);
9390 if (ML_(safe_to_deref)(params, sizeof(*params))) {
9391 if (params->data_ptr)
9392 door_call_pre_mem_params_data(tid, ARG1, params->data_ptr,
9393 params->data_size);
9395 if (params->desc_ptr) {
9396 SizeT desc_size = params->desc_num * sizeof(*params->desc_ptr);
9397 PRE_MEM_READ("door_call(params->desc_ptr)",
9398 (Addr)params->desc_ptr, desc_size);
9400 /* Do not record information about closed fds if we are going
9401 to fail the syscall and so no fds will be closed. */
9402 if ((rval == 0) &&
9403 (ML_(safe_to_deref)(params->desc_ptr, desc_size))) {
9404 rval = pre_check_and_close_fds(tid, "door_call",
9405 params->desc_ptr,
9406 params->desc_num);
9410 if (params->rbuf)
9411 PRE_MEM_WRITE("door_call(params->rbuf)", (Addr)params->rbuf,
9412 params->rsize);
9415 if (rval)
9416 SET_STATUS_Failure(rval);
9418 break;
9419 case VKI_DOOR_BIND:
9420 PRE_REG_READ1(long, "door", long, arg1);
9421 PRE_REG_READ_SIXTH_ONLY;
9422 VG_(unimplemented)("DOOR_BIND");
9423 break;
9424 case VKI_DOOR_UNBIND:
9425 PRE_REG_READ0(long, "door");
9426 PRE_REG_READ_SIXTH_ONLY;
9427 VG_(unimplemented)("DOOR_UNBIND");
9428 break;
9429 case VKI_DOOR_UNREFSYS:
9430 PRE_REG_READ0(long, "door");
9431 PRE_REG_READ_SIXTH_ONLY;
9432 VG_(unimplemented)("DOOR_UNREFSYS");
9433 break;
9434 case VKI_DOOR_UCRED:
9435 PRE_REG_READ1(long, "door", long, arg1);
9436 PRE_REG_READ_SIXTH_ONLY;
9437 VG_(unimplemented)("DOOR_UCRED");
9438 break;
9439 case VKI_DOOR_RETURN:
9440 PRE_REG_READ6(long, "door", long, arg1, long, arg2, long, arg3,
9441 long, arg4, long, arg5, long, subcode);
9443 /* Register %esp/%rsp is read and modified by the syscall. */
9444 VG_TRACK(pre_reg_read, Vg_CoreSysCall, tid, "door_return(sp)",
9445 VG_O_STACK_PTR, sizeof(UWord));
9446 /* Register %ebp/%rbp is not really read by the syscall, it is only
9447 written by it, but it is hard to determine when it is written so we
9448 make sure it is always valid prior to making the syscall. */
9449 VG_TRACK(pre_reg_read, Vg_CoreSysCall, tid, "door_return(bp)",
9450 VG_O_FRAME_PTR, sizeof(UWord));
9452 door_return_pre_mem_data(tid, tst->os_state.door_return_procedure,
9453 (void *) ARG1, ARG2);
9455 /* Do not tell the tool where the syscall is going to write the
9456 resulting data. It is necessary to skip this check because the data
9457 area starting at ARG4-ARG5 (of length ARG5) is usually on a client
9458 thread stack below the stack pointer and therefore it can be marked
9459 by a tool (for example, Memcheck) as inaccessible. It is ok to skip
9460 this check in this case because if there is something wrong with the
9461 data area then the syscall will fail or the error will be handled by
9462 POST_MEM_WRITE() in the post wrapper. */
9463 /*PRE_MEM_WRITE("door_return(sp)", ARG4 - ARG5, ARG5);*/
9465 if (ARG3) {
9466 vki_door_return_desc_t *desc_env = (vki_door_return_desc_t*)ARG3;
9468 PRE_MEM_READ("door_return(desc_env)", ARG3,
9469 sizeof(vki_door_return_desc_t));
9471 if (ML_(safe_to_deref)(desc_env, sizeof(*desc_env)) &&
9472 desc_env->desc_ptr) {
9473 Int rval;
9475 PRE_MEM_READ("door_return(desc_env->desc_ptr)",
9476 (Addr)desc_env->desc_ptr,
9477 desc_env->desc_num * sizeof(*desc_env->desc_ptr));
9479 rval = pre_check_and_close_fds(tid, "door_return",
9480 desc_env->desc_ptr,
9481 desc_env->desc_num);
9482 if (rval)
9483 SET_STATUS_Failure(rval);
9486 tst->os_state.in_door_return = True;
9487 tst->os_state.door_return_procedure = 0;
9488 break;
9489 case VKI_DOOR_GETPARAM:
9490 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9491 PRE_REG_READ_SIXTH_ONLY;
9492 VG_(unimplemented)("DOOR_GETPARAM");
9493 break;
9494 case VKI_DOOR_SETPARAM:
9495 PRE_REG_READ3(long, "door", long, arg1, long, arg2, long, arg3);
9496 PRE_REG_READ_SIXTH_ONLY;
9497 if (!ML_(fd_allowed)(ARG1, "door_setparam", tid, False))
9498 SET_STATUS_Failure(VKI_EBADF);
9499 break;
9500 default:
9501 VG_(unimplemented)("Syswrap of the door call with subcode %ld.", SARG6);
9502 /*NOTREACHED*/
9503 break;
9506 #undef PRE_REG_READ_SIXTH_ONLY
9509 POST(sys_door)
9511 ThreadState *tst = VG_(get_ThreadState)(tid);
9513 vg_assert(SUCCESS || FAILURE);
9515 /* Alter the tst->os_state.in_door_return flag. */
9516 if (ARG6 == VKI_DOOR_RETURN) {
9517 vg_assert(tst->os_state.in_door_return == True);
9518 tst->os_state.in_door_return = False;
9520 /* Inform the tool that %esp/%rsp and %ebp/%rbp were (potentially)
9521 modified. */
9522 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, VG_O_STACK_PTR,
9523 sizeof(UWord));
9524 VG_TRACK(post_reg_write, Vg_CoreSysCall, tid, VG_O_FRAME_PTR,
9525 sizeof(UWord));
9527 else
9528 vg_assert(tst->os_state.in_door_return == False);
9530 if (FAILURE) {
9531 if (VG_(clo_track_fds)) {
9532 /* See the discussion in pre_check_and_close_fds() to understand this
9533 part. */
9534 Bool loss = False;
9535 switch (ARG6 /*subcode*/) {
9536 case VKI_DOOR_CALL:
9537 if (ERR == VKI_EFAULT || ERR == VKI_EBADF)
9538 loss = True;
9539 break;
9540 case VKI_DOOR_RETURN:
9541 if (ERR == VKI_EFAULT || ERR == VKI_EINVAL)
9542 loss = True;
9543 break;
9544 default:
9545 break;
9547 if (loss)
9548 VG_(message)(Vg_UserMsg, "The door call failed with an "
9549 "unexpected error and information "
9550 "about open file descriptors can be "
9551 "now imprecise.\n");
9554 return;
9557 vg_assert(SUCCESS);
9559 switch (ARG6 /*subcode*/) {
9560 case VKI_DOOR_CREATE:
9561 door_record_server(tid, ARG1, RES);
9562 break;
9563 case VKI_DOOR_REVOKE:
9564 door_record_revoke(tid, ARG1);
9565 if (VG_(clo_track_fds))
9566 ML_(record_fd_close)(ARG1);
9567 break;
9568 case VKI_DOOR_INFO:
9569 POST_MEM_WRITE(ARG2, sizeof(vki_door_info_t));
9570 break;
9571 case VKI_DOOR_CALL:
9573 /* Note that all returned values are stored in the rbuf, i.e.
9574 data_ptr and desc_ptr points into this buffer. */
9575 vki_door_arg_t *params = (vki_door_arg_t*)ARG2;
9577 if (params->rbuf) {
9578 Addr addr = (Addr)params->rbuf;
9579 if (!VG_(am_find_anon_segment)(addr)) {
9580 /* This segment is new and was mapped by the kernel. */
9581 UInt prot, flags;
9582 SizeT size;
9584 prot = VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC;
9585 flags = VKI_MAP_ANONYMOUS;
9586 size = VG_PGROUNDUP(params->rsize);
9588 VG_(debugLog)(1, "syswrap-solaris", "POST(sys_door), "
9589 "new segment: vaddr=%#lx, size=%#lx, "
9590 "prot=%#x, flags=%#x, fd=%lu, offset=%#llx\n",
9591 addr, size, prot, flags, (UWord)-1, (ULong)0);
9593 ML_(notify_core_and_tool_of_mmap)(addr, size, prot, flags,
9594 -1, 0);
9596 /* Note: We don't notify the debuginfo reader about this
9597 mapping because there is no debug information stored in
9598 this segment. */
9601 door_call_post_mem_params_rbuf(tid, ARG1, (void *) addr,
9602 params->rsize, params->desc_ptr,
9603 params->desc_num);
9606 if (params->desc_ptr) {
9607 POST_MEM_WRITE((Addr)params->desc_ptr,
9608 params->desc_num * sizeof(vki_door_desc_t));
9609 post_record_fds(tid, "door_call", params->desc_ptr,
9610 params->desc_num);
9613 break;
9614 case VKI_DOOR_BIND:
9615 break;
9616 case VKI_DOOR_UNBIND:
9617 break;
9618 case VKI_DOOR_UNREFSYS:
9619 break;
9620 case VKI_DOOR_UCRED:
9621 break;
9622 case VKI_DOOR_RETURN:
9624 struct vki_door_results *results
9625 = (struct vki_door_results*)VG_(get_SP)(tid);
9627 tst->os_state.door_return_procedure = (Addr)results->pc;
9629 POST_MEM_WRITE((Addr)results, sizeof(*results));
9630 if (results->data_ptr)
9631 door_return_post_mem_data(tid,
9632 tst->os_state.door_return_procedure,
9633 results->data_ptr,
9634 results->data_size);
9635 if (results->desc_ptr) {
9636 POST_MEM_WRITE((Addr)results->desc_ptr,
9637 results->desc_num * sizeof(vki_door_desc_t));
9638 post_record_fds(tid, "door_return", results->desc_ptr,
9639 results->desc_num);
9642 POST_MEM_WRITE((Addr)results->door_info,
9643 sizeof(*results->door_info));
9645 break;
9646 case VKI_DOOR_GETPARAM:
9647 break;
9648 case VKI_DOOR_SETPARAM:
9649 break;
9650 default:
9651 vg_assert(0);
9652 break;
9656 PRE(sys_schedctl)
9658 /* caddr_t schedctl(void); */
9659 /* This syscall returns an address that points to struct sc_shared.
9660 This per-thread structure is used as an interface between the libc and
9661 the kernel. */
9662 PRINT("sys_schedctl ( )");
9663 PRE_REG_READ0(long, "schedctl");
9666 POST(sys_schedctl)
9668 Addr a = RES;
9669 ThreadState *tst = VG_(get_ThreadState)(tid);
9671 /* Stay sane. */
9672 vg_assert((tst->os_state.schedctl_data == 0) ||
9673 (tst->os_state.schedctl_data == a));
9674 tst->os_state.schedctl_data = a;
9676 /* Returned address points to a block in a mapped page. */
9677 if (!VG_(am_find_anon_segment)(a)) {
9678 Addr page = VG_PGROUNDDN(a);
9679 UInt prot = VKI_PROT_READ | VKI_PROT_WRITE;
9680 # if defined(SOLARIS_SCHEDCTL_PAGE_EXEC)
9681 prot |= VKI_PROT_EXEC;
9682 # endif /* SOLARIS_SCHEDCTL_PAGE_EXEC */
9683 UInt flags = VKI_MAP_ANONYMOUS;
9684 /* The kernel always allocates one page for the sc_shared struct. */
9685 SizeT size = VKI_PAGE_SIZE;
9687 VG_(debugLog)(1, "syswrap-solaris", "POST(sys_schedctl), new segment: "
9688 "vaddr=%#lx, size=%#lx, prot=%#x, flags=%#x, fd=-1, "
9689 "offset=0\n", page, size, prot, flags);
9691 /* The kernel always places redzone before and after the allocated page.
9692 Check this assertion now; the tool can later request to allocate
9693 a Valgrind segment and aspacemgr will place it adjacent. */
9694 const NSegment *seg = VG_(am_find_nsegment)(page - 1);
9695 vg_assert(seg == NULL || seg->kind == SkResvn);
9696 seg = VG_(am_find_nsegment)(page + VKI_PAGE_SIZE);
9697 vg_assert(seg == NULL || seg->kind == SkResvn);
9699 /* The address space manager works with whole pages. */
9700 VG_(am_notify_client_mmap)(page, size, prot, flags, -1, 0);
9702 /* Note: It isn't needed to notify debuginfo about the new mapping
9703 because it's only an anonymous mapping. */
9704 /* Note: schedctl data are cleaned in two places:
9705 - for the tool when the thread exits
9706 - for the core in child's post-fork handler clean_schedctl_data(). */
9709 /* The tool needs per-thread granularity, not whole pages. */
9710 VG_TRACK(new_mem_mmap, a, sizeof(struct vki_sc_shared), True, True, True, 0);
9711 POST_MEM_WRITE(a, sizeof(struct vki_sc_shared));
9714 PRE(sys_pset)
9716 /* Kernel: int pset(int subcode, long arg1, long arg2, long arg3,
9717 long arg4); */
9718 switch (ARG1 /* subcode */) {
9719 case VKI_PSET_CREATE:
9720 /* Libc: int pset_create(psetid_t *newpset); */
9721 PRINT("sys_pset ( %ld, %#lx )", SARG1, ARG2);
9722 PRE_REG_READ2(long, SC2("pset", "create"), int, subcode,
9723 vki_psetid_t *, newpset);
9724 PRE_MEM_WRITE("pset(newpset)", ARG2, sizeof(vki_psetid_t));
9725 break;
9726 case VKI_PSET_DESTROY:
9727 /* Libc: int pset_destroy(psetid_t pset); */
9728 PRINT("sys_pset ( %ld, %ld )", SARG1, SARG2);
9729 PRE_REG_READ2(long, SC2("pset", "destroy"), int, subcode,
9730 vki_psetid_t, pset);
9731 break;
9732 case VKI_PSET_ASSIGN:
9733 /* Libc: int pset_assign(psetid_t pset, processorid_t cpu,
9734 psetid_t *opset); */
9735 PRINT("sys_pset ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
9736 PRE_REG_READ4(long, SC2("pset", "assign"), int, subcode,
9737 vki_psetid_t, pset, vki_processorid_t, cpu,
9738 vki_psetid_t *, opset);
9739 if (ARG4 != 0)
9740 PRE_MEM_WRITE("pset(opset)", ARG4, sizeof(vki_psetid_t));
9741 break;
9742 case VKI_PSET_INFO:
9743 /* Libc: int pset_info(psetid_t pset, int *type, uint_t *numcpus,
9744 processorid_t *cpulist); */
9745 PRINT("sys_pset ( %ld, %ld, %#lx, %#lx, %#lx )", SARG1, SARG2, ARG3,
9746 ARG4, ARG5);
9747 PRE_REG_READ5(long, SC2("pset", "info"), int, subcode, vki_psetid_t, pset,
9748 int *, type, vki_uint_t *, numcpus,
9749 vki_processorid_t *, cpulist);
9750 if (ARG3 != 0)
9751 PRE_MEM_WRITE("pset(type)", ARG3, sizeof(int));
9752 if (ARG4 != 0)
9753 PRE_MEM_WRITE("pset(numcpus)", ARG4, sizeof(vki_uint_t));
9754 if ((ARG4 != 0) && (ARG5 != 0)) {
9755 vki_uint_t *numcpus = (vki_uint_t *) ARG4;
9756 if (ML_(safe_to_deref(numcpus, sizeof(vki_uint_t)))) {
9757 PRE_MEM_WRITE("pset(cpulist)", ARG5,
9758 *numcpus * sizeof(vki_processorid_t));
9759 /* If cpulist buffer is not large enough, it will hold only as many
9760 entries as fit in the buffer. However numcpus will contain the
9761 real number of cpus which will be greater than originally passed
9762 in. Stash the original value in unused ARG6. */
9763 ARG6 = *numcpus;
9766 break;
9767 case VKI_PSET_BIND:
9768 /* Libc: int pset_bind(psetid_t pset, idtype_t idtype, id_t id,
9769 psetid_t *opset); */
9770 PRINT("sys_pset ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3,
9771 SARG4, ARG5);
9772 PRE_REG_READ5(long, SC2("pset", "bind"), int, subcode, vki_psetid_t, pset,
9773 vki_idtype_t, idtype, vki_id_t, id, vki_psetid_t *, opset);
9774 if (ARG5 != 0)
9775 PRE_MEM_WRITE("pset(opset)", ARG5, sizeof(vki_psetid_t));
9776 break;
9777 case VKI_PSET_BIND_LWP:
9778 /* Libc: int pset_bind_lwp(psetid_t pset, id_t id, pid_t pid,
9779 psetid_t *opset); */
9780 PRINT("sys_pset ( %ld, %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3,
9781 SARG4, ARG5);
9782 PRE_REG_READ5(long, SC2("pset", "bind_lwp"), int, subcode,
9783 vki_psetid_t, pset, vki_id_t, id, vki_pid_t, pid,
9784 vki_psetid_t *, opset);
9785 if (ARG5 != 0)
9786 PRE_MEM_WRITE("pset(opset)", ARG5, sizeof(vki_psetid_t));
9787 break;
9788 case VKI_PSET_GETLOADAVG:
9789 /* Libc: int pset_getloadavg(psetid_t pset, double loadavg[],
9790 int nelem); */
9791 PRINT("sys_pset ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
9792 PRE_REG_READ4(long, SC2("pset", "getloadavg"), int, subcode,
9793 vki_psetid_t, pset, int *, buf, int, nelem);
9794 if (ARG3 != 0)
9795 PRE_MEM_WRITE("pset(buf)", ARG3, SARG4 * sizeof(int));
9796 break;
9797 case VKI_PSET_LIST:
9798 /* Libc: int pset_list(psetid_t *psetlist, uint_t *numpsets); */
9799 PRINT("sys_pset ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
9800 PRE_REG_READ3(long, SC2("pset", "list"), int, subcode,
9801 vki_psetid_t *, psetlist, vki_uint_t *, numpsets);
9802 if (ARG3 != 0)
9803 PRE_MEM_WRITE("pset(numpsets)", ARG3, sizeof(vki_uint_t));
9804 if ((ARG2 != 0) && (ARG3 != 0)) {
9805 vki_uint_t *numpsets = (vki_uint_t *) ARG3;
9806 if (ML_(safe_to_deref(numpsets, sizeof(vki_uint_t)))) {
9807 PRE_MEM_WRITE("pset(psetlist)", ARG2,
9808 *numpsets * sizeof(vki_psetid_t));
9809 /* If psetlist buffer is not large enough, it will hold only as many
9810 entries as fit in the buffer. However numpsets will contain the
9811 real number of processor sets which will be greater than
9812 originally passed in. Stash the original value in unused ARG6. */
9813 ARG6 = *numpsets;
9816 break;
9817 # if defined(SOLARIS_PSET_GET_NAME)
9818 case VKI_PSET_GET_NAME:
9819 /* Libc: int pset_get_name(psetid_t psetid, char *buf, uint_t len); */
9820 PRINT("sys_pset ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
9821 PRE_REG_READ4(long, SC2("pset", "get_name"), int, subcode,
9822 vki_psetid_t, pset, char *, buf, vki_uint_t, len);
9823 PRE_MEM_WRITE("pset(buf)", ARG3, ARG4);
9824 break;
9825 # endif /* SOLARIS_PSET_GET_NAME */
9826 case VKI_PSET_SETATTR:
9827 /* Libc: int pset_setattr(psetid_t pset, uint_t attr); */
9828 PRINT("sys_pset ( %ld, %ld, %lu )", SARG1, SARG2, ARG3);
9829 PRE_REG_READ3(long, SC2("pset", "setattr"), int, subcode,
9830 vki_psetid_t, pset, vki_uint_t, attr);
9831 break;
9832 case VKI_PSET_GETATTR:
9833 /* Libc: int pset_getattr(psetid_t pset, uint_t *attr); */
9834 PRINT("sys_pset ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
9835 PRE_REG_READ3(long, SC2("pset", "getattr"), int, subcode,
9836 vki_psetid_t, pset, vki_uint_t *, attr);
9837 PRE_MEM_WRITE("pset(attr)", ARG3, sizeof(vki_uint_t));
9838 break;
9839 case VKI_PSET_ASSIGN_FORCED:
9840 /* Libc: int pset_assign_forced(psetid_t pset, processorid_t cpu,
9841 psetid_t *opset); */
9842 PRINT("sys_pset ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
9843 PRE_REG_READ4(long, SC2("pset", "assign_forced"), int, subcode,
9844 vki_psetid_t, pset, vki_processorid_t, cpu,
9845 vki_psetid_t *, opset);
9846 if (ARG4 != 0)
9847 PRE_MEM_WRITE("pset(opset)", ARG4, sizeof(vki_psetid_t));
9848 break;
9849 default:
9850 VG_(unimplemented)("Syswrap of pset syscall with subcode %ld.", SARG1);
9851 /*NOTREACHED*/
9852 break;
9856 POST(sys_pset)
9858 switch (ARG1 /*subcode*/) {
9859 case VKI_PSET_CREATE:
9860 POST_MEM_WRITE(ARG2, sizeof(vki_psetid_t));
9861 break;
9862 case VKI_PSET_DESTROY:
9863 break;
9864 case VKI_PSET_ASSIGN:
9865 if (ARG4 != 0)
9866 POST_MEM_WRITE(ARG4, sizeof(vki_psetid_t));
9867 break;
9868 case VKI_PSET_INFO:
9869 if (ARG3 != 0)
9870 POST_MEM_WRITE(ARG3, sizeof(int));
9871 if (ARG4 != 0)
9872 POST_MEM_WRITE(ARG4, sizeof(vki_uint_t));
9873 if ((ARG4 != 0) && (ARG5 != 0)) {
9874 vki_uint_t *numcpus = (vki_uint_t *) ARG4;
9875 POST_MEM_WRITE(ARG5, MIN(*numcpus, ARG6) * sizeof(vki_processorid_t));
9877 break;
9878 case VKI_PSET_BIND:
9879 if (ARG5 != 0)
9880 POST_MEM_WRITE(ARG5, sizeof(vki_psetid_t));
9881 break;
9882 case VKI_PSET_BIND_LWP:
9883 if (ARG5 != 0)
9884 POST_MEM_WRITE(ARG5, sizeof(vki_psetid_t));
9885 break;
9886 case VKI_PSET_GETLOADAVG:
9887 if (ARG3 != 0)
9888 POST_MEM_WRITE(ARG3, MIN(SARG4, VKI_LOADAVG_NSTATS) * sizeof(int));
9889 break;
9890 case VKI_PSET_LIST:
9891 if (ARG3 != 0)
9892 POST_MEM_WRITE(ARG3, sizeof(vki_uint_t));
9893 if ((ARG2 != 0) && (ARG3 != 0)) {
9894 vki_uint_t *numpsets = (vki_uint_t *) ARG3;
9895 POST_MEM_WRITE(ARG2, MIN(*numpsets, ARG6) * sizeof(vki_psetid_t));
9897 break;
9898 # if defined(SOLARIS_PSET_GET_NAME)
9899 case VKI_PSET_GET_NAME:
9900 POST_MEM_WRITE(ARG3, VG_(strlen)((HChar *) ARG3) + 1);
9901 break;
9902 # endif /* SOLARIS_PSET_GET_NAME */
9903 case VKI_PSET_SETATTR:
9904 break;
9905 case VKI_PSET_GETATTR:
9906 POST_MEM_WRITE(ARG3, sizeof(vki_uint_t));
9907 break;
9908 case VKI_PSET_ASSIGN_FORCED:
9909 if (ARG4 != 0)
9910 POST_MEM_WRITE(ARG4, sizeof(vki_psetid_t));
9911 break;
9912 default:
9913 vg_assert(0);
9914 break;
9918 PRE(sys_resolvepath)
9920 /* int resolvepath(const char *path, char *buf, size_t bufsiz); */
9921 PRINT("sys_resolvepath ( %#lx(%s), %#lx, %lu )", ARG1, (HChar *) ARG1, ARG2,
9922 ARG3);
9923 PRE_REG_READ3(long, "resolvepath", const char *, path, char *, buf,
9924 vki_size_t, bufsiz);
9926 PRE_MEM_RASCIIZ("resolvepath(path)", ARG1);
9927 PRE_MEM_WRITE("resolvepath(buf)", ARG2, ARG3);
9930 POST(sys_resolvepath)
9932 POST_MEM_WRITE(ARG2, RES);
9935 PRE(sys_lwp_mutex_timedlock)
9937 /* int lwp_mutex_timedlock(lwp_mutex_t *lp, timespec_t *tsp,
9938 uintptr_t owner); */
9939 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *)ARG1;
9940 *flags |= SfMayBlock;
9941 PRINT("lwp_mutex_timedlock ( %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3);
9942 PRE_REG_READ3(long, "lwp_mutex_timedlock", lwp_mutex_t *, lp,
9943 timespec_t *, tsp, uintptr_t, owner);
9945 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_flag)", lp->vki_mutex_flag);
9946 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_type)", lp->vki_mutex_type);
9947 PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_owner)",
9948 lp->vki_mutex_owner);
9949 PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_ownerpid)",
9950 lp->vki_mutex_ownerpid);
9951 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_lockw)", lp->vki_mutex_lockw);
9952 /*PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_lockw)",
9953 lp->vki_mutex_lockw);*/
9954 PRE_FIELD_READ("lwp_mutex_timedlock(lp->mutex_waiters)",
9955 lp->vki_mutex_waiters);
9956 /*PRE_FIELD_WRITE("lwp_mutex_timedlock(lp->mutex_waiters)",
9957 lp->vki_mutex_waiters);*/
9958 if (ARG2) {
9959 PRE_MEM_READ("lwp_mutex_timedlock(tsp)", ARG2, sizeof(vki_timespec_t));
9960 /*PRE_MEM_WRITE("lwp_mutex_timedlock(tsp)", ARG2,
9961 sizeof(vki_timespec_t));*/
9965 POST(sys_lwp_mutex_timedlock)
9967 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t *)ARG1;
9968 POST_FIELD_WRITE(lp->vki_mutex_owner);
9969 POST_FIELD_WRITE(lp->vki_mutex_ownerpid);
9970 POST_FIELD_WRITE(lp->vki_mutex_lockw);
9971 POST_FIELD_WRITE(lp->vki_mutex_waiters);
9972 if (ARG2)
9973 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
9976 PRE(sys_lwp_rwlock_sys)
9978 /* int lwp_rwlock_sys(int subcode, lwp_rwlock_t *rwlp, timespec_t *tsp); */
9979 vki_lwp_rwlock_t *rwlp = (vki_lwp_rwlock_t *)ARG2;
9980 switch (ARG1 /*subcode*/) {
9981 case 0:
9982 case 1:
9983 case 2:
9984 case 3:
9985 *flags |= SfMayBlock;
9986 switch (ARG1 /*subcode*/) {
9987 case 0:
9988 PRINT("sys_lwp_rwlock ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
9989 PRE_REG_READ3(long, SC2("lwp_rwlock", "rdlock"), int, subcode,
9990 lwp_rwlock_t *, rwlp, timespec_t *, tsp);
9991 break;
9992 case 1:
9993 PRINT("sys_lwp_rwlock ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
9994 PRE_REG_READ3(long, SC2("lwp_rwlock", "wrlock"), int, subcode,
9995 lwp_rwlock_t *, rwlp, timespec_t *, tsp);
9996 break;
9997 case 2:
9998 PRINT("sys_lwp_rwlock ( %ld, %#lx )", SARG1, ARG2);
9999 PRE_REG_READ2(long, SC2("lwp_rwlock", "tryrdlock"), int, subcode,
10000 lwp_rwlock_t *, rwlp);
10001 break;
10002 case 3:
10003 PRINT("sys_lwp_rwlock ( %ld, %#lx )", SARG1, ARG2);
10004 PRE_REG_READ2(long, SC2("lwp_rwlock", "trywrlock"), int, subcode,
10005 lwp_rwlock_t *, rwlp);
10006 break;
10007 default:
10008 vg_assert(0);
10009 break;
10012 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_type)", rwlp->vki_rwlock_type);
10013 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_readers)",
10014 rwlp->vki_rwlock_readers);
10015 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->rwlock_readers)",
10016 rwlp->vki_rwlock_readers);*/
10018 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_type)",
10019 rwlp->mutex.vki_mutex_type);
10020 PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_owner)",
10021 rwlp->mutex.vki_mutex_owner);
10022 PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_ownerpid)",
10023 rwlp->mutex.vki_mutex_ownerpid);
10024 /* The mutex_lockw member is not really read by the kernel for this
10025 syscall but it seems better to mark it that way because when locking
10026 an rwlock the associated mutex has to be locked. */
10027 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_lockw)",
10028 rwlp->mutex.vki_mutex_lockw);
10029 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_lockw)",
10030 rwlp->mutex.vki_mutex_lockw);*/
10031 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_waiters)",
10032 rwlp->mutex.vki_mutex_waiters);
10033 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->mutex.mutex_waiters)",
10034 rwlp->mutex.vki_mutex_waiters);*/
10036 if ((ARG1 == 0 || ARG1 == 1) && ARG3)
10037 PRE_MEM_READ("lwp_rwlock(tsp)", ARG3, sizeof(vki_timespec_t));
10038 break;
10039 case 4:
10040 PRINT("sys_lwp_rwlock( %ld, %#lx )", SARG1, ARG2);
10041 PRE_REG_READ2(long, SC2("lwp_rwlock", "unlock"), int, subcode,
10042 lwp_rwlock_t *, rwlp);
10043 PRE_FIELD_READ("lwp_rwlock(rwlp->mutex.mutex_type)",
10044 rwlp->mutex.vki_mutex_type);
10045 PRE_FIELD_READ("lwp_rwlock(rwlp->rwlock_readers)",
10046 rwlp->vki_rwlock_readers);
10047 /*PRE_FIELD_WRITE("lwp_rwlock(rwlp->rwlock_readers)",
10048 rwlp->vki_rwlock_readers);*/
10049 break;
10050 default:
10051 VG_(unimplemented)("Syswrap of the lwp_rwlock_sys call with subcode %ld.",
10052 SARG1);
10053 /*NOTREACHED*/
10054 break;
10058 POST(sys_lwp_rwlock_sys)
10060 vki_lwp_rwlock_t *rwlp = (vki_lwp_rwlock_t *)ARG2;
10061 switch (ARG1 /*subcode*/) {
10062 case 0:
10063 case 1:
10064 case 2:
10065 case 3:
10066 POST_FIELD_WRITE(rwlp->vki_rwlock_readers);
10067 POST_FIELD_WRITE(rwlp->vki_rwlock_owner);
10068 POST_FIELD_WRITE(rwlp->vki_rwlock_ownerpid);
10069 POST_FIELD_WRITE(rwlp->mutex.vki_mutex_lockw);
10070 POST_FIELD_WRITE(rwlp->mutex.vki_mutex_waiters);
10071 break;
10072 case 4:
10073 POST_FIELD_WRITE(rwlp->vki_rwlock_readers);
10074 break;
10075 default:
10076 vg_assert(0);
10077 break;
10081 PRE(sys_lwp_sema_timedwait)
10083 /* int lwp_sema_timedwait(lwp_sema_t *sema, timespec_t *timeout,
10084 int check_park); */
10085 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
10086 *flags |= SfMayBlock;
10087 PRINT("sys_lwp_sema_timewait ( %#lx, %#lx, %ld )", ARG1, ARG2, SARG3);
10088 PRE_REG_READ3(long, "lwp_sema_timedwait", lwp_sema_t *, sema,
10089 timespec_t *, timeout, int, check_park);
10091 PRE_FIELD_READ("lwp_sema_timedwait(sema->type)", sema->vki_sema_type);
10092 PRE_FIELD_READ("lwp_sema_timedwait(sema->count)", sema->vki_sema_count);
10093 /*PRE_FIELD_WRITE("lwp_sema_timedwait(sema->count)",
10094 sema->vki_sema_count);*/
10095 PRE_FIELD_READ("lwp_sema_timedwait(sema->waiters)", sema->vki_sema_waiters);
10096 /*PRE_FIELD_WRITE("lwp_sema_timedwait(sema->waiters)",
10097 sema->vki_sema_waiters);*/
10098 if (ARG2) {
10099 PRE_MEM_READ("lwp_sema_timedwait(timeout)", ARG2,
10100 sizeof(vki_timespec_t));
10101 /*PRE_MEM_WRITE("lwp_sema_timedwait(timeout)", ARG2,
10102 sizeof(vki_timespec_t));*/
10106 POST(sys_lwp_sema_timedwait)
10108 vki_lwp_sema_t *sema = (vki_lwp_sema_t*)ARG1;
10109 POST_FIELD_WRITE(sema->vki_sema_count);
10110 POST_FIELD_WRITE(sema->vki_sema_waiters);
10111 if (ARG2)
10112 POST_MEM_WRITE(ARG2, sizeof(vki_timespec_t));
10115 PRE(sys_zone)
10117 /* Kernel: long zone(int cmd, void *arg1, void *arg2, void *arg3,
10118 void *arg4);
10120 switch (ARG1 /*cmd*/) {
10121 case VKI_ZONE_CREATE:
10122 /* Libc: zoneid_t zone_create(const char *name, const char *root,
10123 const struct priv_set *privs,
10124 const char *rctls, size_t rctlsz,
10125 const char *zfs, size_t zfssz,
10126 int *extended_error, int match,
10127 int doi, const bslabel_t *label,
10128 int flags);
10129 Kernel: zoneid_t zone_create(zone_def *zd);
10131 PRINT("sys_zone ( %ld, %#lx )", SARG1, ARG2);
10132 PRE_REG_READ2(long, SC2("zone", "create"), int, cmd,
10133 vki_zone_def *, zd);
10135 vki_zone_def *zd = (vki_zone_def *) ARG2;
10136 PRE_FIELD_READ("zone(zd.zone_name)", zd->zone_name);
10137 PRE_FIELD_READ("zone(zd.zone_root)", zd->zone_root);
10138 PRE_FIELD_READ("zone(zd.zone_privs)", zd->zone_privs);
10139 PRE_FIELD_READ("zone(zd.zone_privssz)", zd->zone_privssz);
10140 PRE_FIELD_READ("zone(zd.rctlbuf)", zd->rctlbuf);
10141 PRE_FIELD_READ("zone(zd.rctlbufsz)", zd->rctlbufsz);
10142 PRE_FIELD_READ("zone(zd.zfsbuf)", zd->zfsbuf);
10143 PRE_FIELD_READ("zone(zd.zfsbufsz)", zd->zfsbufsz);
10144 PRE_FIELD_READ("zone(zd.extended_error)", zd->extended_error);
10145 PRE_FIELD_READ("zone(zd.match)", zd->match);
10146 PRE_FIELD_READ("zone(zd.doi)", zd->doi);
10147 PRE_FIELD_READ("zone(zd.label)", zd->label);
10148 PRE_FIELD_READ("zone(zd.flags)", zd->flags);
10150 if (ML_(safe_to_deref((void *)ARG2, sizeof(vki_zone_def)))) {
10151 if (zd->zone_name)
10152 PRE_MEM_RASCIIZ("zone(zd.zone_name)", (Addr) zd->zone_name);
10153 if (zd->zone_root)
10154 PRE_MEM_RASCIIZ("zone(zd.zone_root)", (Addr) zd->zone_root);
10155 PRE_MEM_READ("zone(zd.zone_privs)", (Addr) zd->zone_privs,
10156 zd->zone_privssz);
10157 PRE_MEM_READ("zone(zd.rctlbuf)", (Addr) zd->rctlbuf,
10158 zd->rctlbufsz);
10159 PRE_MEM_READ("zone(zd.zfsbuf)",
10160 (Addr) zd->zfsbuf, zd->zfsbufsz);
10161 if (zd->label)
10162 PRE_MEM_READ("zone(zd.label)", (Addr) zd->label,
10163 sizeof(vki_bslabel_t));
10165 break;
10166 case VKI_ZONE_DESTROY:
10167 /* Libc: int zone_destroy(zoneid_t zoneid); */
10168 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
10169 PRE_REG_READ2(long, SC2("zone", "destroy"), int, cmd,
10170 vki_zoneid_t, zoneid);
10171 break;
10172 case VKI_ZONE_GETATTR:
10173 /* Libc: ssize_t zone_getattr(zoneid_t zoneid, int attr,
10174 void *valp, size_t size);
10176 PRINT("sys_zone ( %ld, %ld, %ld, %#lx, %ld )",
10177 SARG1, SARG2, SARG3, ARG4, SARG5);
10178 PRE_REG_READ5(long, SC2("zone", "getattr"), int, cmd,
10179 vki_zoneid_t, zoneid, int, attr, void *, valp,
10180 vki_size_t, size);
10181 PRE_MEM_WRITE("zone(valp)", ARG4, ARG5);
10182 break;
10183 case VKI_ZONE_ENTER:
10184 /* Libc: int zone_enter(zoneid_t zoneid); */
10185 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
10186 PRE_REG_READ2(long, SC2("zone", "enter"), int, cmd,
10187 vki_zoneid_t, zoneid);
10188 break;
10189 case VKI_ZONE_LIST:
10190 /* Libc: int zone_list(zoneid_t *zonelist, uint_t *numzones); */
10191 PRINT("sys_zone ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
10192 PRE_REG_READ3(long, SC2("zone", "list"), int, cmd,
10193 vki_zoneid_t *, zonelist, vki_uint_t *, numzones);
10195 PRE_MEM_WRITE("zone(numzones)", ARG3, sizeof(vki_uint_t));
10197 if (ML_(safe_to_deref((void *) ARG3, sizeof(vki_uint_t)))) {
10198 if (ARG2)
10199 PRE_MEM_WRITE("zone(zonelist)", ARG2,
10200 *(vki_uint_t *) ARG3 * sizeof(vki_zoneid_t));
10202 break;
10203 case VKI_ZONE_SHUTDOWN:
10204 /* Libc: int zone_shutdown(zoneid_t zoneid); */
10205 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
10206 PRE_REG_READ2(long, SC2("zone", "shutdown"), int, cmd,
10207 vki_zoneid_t, zoneid);
10208 break;
10209 case VKI_ZONE_LOOKUP:
10210 /* Libc: zoneid_t zone_lookup(const char *name); */
10211 PRINT("sys_zone ( %ld, %#lx(%s) )", SARG1, ARG2, (HChar *) ARG2);
10212 PRE_REG_READ2(long, SC2("zone", "lookup"), int, cmd,
10213 const char *, name);
10214 if (ARG2)
10215 PRE_MEM_RASCIIZ("zone(name)", ARG2);
10216 break;
10217 case VKI_ZONE_BOOT:
10218 /* Libc: int zone_boot(zoneid_t zoneid); */
10219 PRINT("sys_zone ( %ld, %ld )", SARG1, SARG2);
10220 PRE_REG_READ2(long, SC2("zone", "boot"), int, cmd,
10221 vki_zoneid_t, zoneid);
10222 break;
10223 case VKI_ZONE_SETATTR:
10224 /* Libc: int zone_setattr(zoneid_t zoneid, int attr, void *valp,
10225 size_t size);
10227 PRINT("sys_zone ( %ld, %ld, %ld, %#lx, %lu )",
10228 SARG1, SARG2, SARG3, ARG4, ARG5);
10229 PRE_REG_READ5(long, SC2("zone", "setattr"), int, cmd,
10230 vki_zoneid_t, zoneid, int, attr, void *, valp,
10231 vki_size_t, size);
10232 PRE_MEM_READ("zone(valp)", ARG4, ARG5);
10233 break;
10234 case VKI_ZONE_ADD_DATALINK:
10235 /* Libc: int zone_add_datalink(zoneid_t zoneid,
10236 datalink_id_t linkid);
10238 PRINT("sys_zone ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
10239 PRE_REG_READ3(long, SC2("zone", "add_datalink"), int, cmd,
10240 vki_zoneid_t, zoneid, vki_datalink_id_t, linkid);
10241 break;
10242 case VKI_ZONE_DEL_DATALINK:
10243 /* Libc: int zone_remove_datalink(zoneid_t zoneid,
10244 datalink_id_t linkid);
10246 PRINT("sys_zone ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
10247 PRE_REG_READ3(long, SC2("zone", "del_datalink"), int, cmd,
10248 vki_zoneid_t, zoneid, vki_datalink_id_t, linkid);
10249 break;
10250 case VKI_ZONE_CHECK_DATALINK:
10251 /* Libc: int zone_check_datalink(zoneid_t *zoneidp,
10252 datalink_id_t linkid);
10254 PRINT("sys_zone ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
10255 PRE_REG_READ3(long, SC2("zone", "check_datalink"), int, cmd,
10256 vki_zoneid_t *, zoneidp, vki_datalink_id_t, linkid);
10257 PRE_MEM_WRITE("zone(zoneidp)", ARG2, sizeof(vki_zoneid_t));
10258 break;
10259 case VKI_ZONE_LIST_DATALINK:
10260 /* Libc: int zone_list_datalink(zoneid_t zoneid, int *dlnump,
10261 datalink_id_t *linkids);
10263 PRINT("sys_zone ( %ld, %ld, %#lx, %#lx )", SARG1, SARG2, ARG3, ARG4);
10264 PRE_REG_READ4(long, SC2("zone", "list_datalink"), int, cmd,
10265 vki_zoneid_t, zoneid, int *, dlnump,
10266 vki_datalink_id_t *, linkids);
10268 PRE_MEM_WRITE("zone(dlnump)", ARG3, sizeof(int));
10269 if (ML_(safe_to_deref((void *) ARG3, sizeof(int)))) {
10270 if (ARG4)
10271 PRE_MEM_WRITE("zone(linkids)", ARG4,
10272 *(int *) ARG3 * sizeof(vki_datalink_id_t));
10274 break;
10275 #if defined(SOLARIS_ZONE_DEFUNCT)
10276 case VKI_ZONE_LIST_DEFUNCT:
10277 /* Libc: int zone_list_defunct(uint64_t *uniqidlist,
10278 uint_t *numzones);
10280 PRINT("sys_zone ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
10281 PRE_REG_READ3(long, SC2("zone", "list_defunct"), int, cmd,
10282 vki_uint64_t *, uniqidlist, vki_uint_t *, numzones);
10284 PRE_MEM_WRITE("zone(numzones)", ARG3, sizeof(vki_uint_t));
10286 if (ML_(safe_to_deref((void *) ARG3, sizeof(vki_uint_t)))) {
10287 if (ARG2)
10288 PRE_MEM_WRITE("zone(uniqidlist)", ARG2,
10289 *(vki_uint_t *) ARG3 * sizeof(vki_uint64_t));
10291 break;
10292 case VKI_ZONE_GETATTR_DEFUNCT:
10293 /* Libc: ssize_t zone_getattr_defunct(uint64_t uniqid, int attr,
10294 void *valp, size_t size);
10295 Kernel: ssize_t zone_getattr_defunct(uint64_t *uniqid, int attr,
10296 void *valp, size_t size);
10298 PRINT("sys_zone ( %ld, %#lx, %ld, %#lx, %lu )",
10299 SARG1, ARG2, SARG3, ARG4, ARG5);
10300 PRE_REG_READ5(long, SC2("zone", "getattr_defunct"), int, cmd,
10301 vki_uint64_t *, uniqid, int, attr,
10302 void *, valp, vki_size_t, size);
10304 PRE_MEM_READ("zone(uniqid)", ARG2, sizeof(vki_uint64_t));
10305 PRE_MEM_WRITE("zone(valp)", ARG4, ARG5);
10306 break;
10307 #endif /* SOLARIS_ZONE_DEFUNCT */
10308 default:
10309 VG_(unimplemented)("Syswrap of the zone call with cmd %ld.", SARG1);
10310 /*NOTREACHED*/
10311 break;
10316 POST(sys_zone)
10318 switch (ARG1 /*cmd*/) {
10319 case VKI_ZONE_CREATE:
10320 case VKI_ZONE_DESTROY:
10321 break;
10322 case VKI_ZONE_GETATTR:
10323 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
10324 break;
10325 case VKI_ZONE_ENTER:
10326 break;
10327 case VKI_ZONE_LIST:
10328 POST_MEM_WRITE(ARG2, *(vki_uint_t *) ARG3 * sizeof(vki_zoneid_t));
10329 break;
10330 case VKI_ZONE_SHUTDOWN:
10331 case VKI_ZONE_LOOKUP:
10332 case VKI_ZONE_BOOT:
10333 case VKI_ZONE_SETATTR:
10334 case VKI_ZONE_ADD_DATALINK:
10335 case VKI_ZONE_DEL_DATALINK:
10336 break;
10337 case VKI_ZONE_CHECK_DATALINK:
10338 POST_MEM_WRITE(ARG2, sizeof(vki_zoneid_t));
10339 break;
10340 case VKI_ZONE_LIST_DATALINK:
10341 POST_MEM_WRITE(ARG4, *(int *) ARG3 * sizeof(vki_datalink_id_t));
10342 break;
10343 #if defined(SOLARIS_ZONE_DEFUNCT)
10344 case VKI_ZONE_LIST_DEFUNCT:
10345 POST_MEM_WRITE(ARG2, *(vki_uint_t *) ARG3 * sizeof(vki_uint64_t));
10346 break;
10347 case VKI_ZONE_GETATTR_DEFUNCT:
10348 POST_MEM_WRITE(ARG4, MIN(RES, ARG5));
10349 break;
10350 #endif /* SOLARIS_ZONE_DEFUNCT */
10351 default:
10352 vg_assert(0);
10353 break;
10357 PRE(sys_getcwd)
10359 /* int getcwd(char *buf, size_t size); */
10360 /* Note: Generic getcwd() syswrap can't be used because it expects
10361 a different return value. */
10362 PRINT("sys_getcwd ( %#lx, %lu )", ARG1, ARG2);
10363 PRE_REG_READ2(long, "getcwd", char *, buf, vki_size_t, size);
10364 PRE_MEM_WRITE("getcwd(buf)", ARG1, ARG2);
10367 POST(sys_getcwd)
10369 POST_MEM_WRITE(ARG1, VG_(strlen)((HChar*)ARG1) + 1);
10372 PRE(sys_so_socket)
10374 /* int so_socket(int family, int type, int protocol, char *devpath,
10375 int version); */
10376 PRINT("sys_so_socket ( %ld, %ld, %ld, %#lx(%s), %ld)", SARG1, SARG2, SARG3,
10377 ARG4, (HChar *) ARG4, SARG5);
10378 PRE_REG_READ5(long, "socket", int, family, int, type, int, protocol,
10379 char *, devpath, int, version);
10380 if (ARG4)
10381 PRE_MEM_RASCIIZ("socket(devpath)", ARG4);
10384 POST(sys_so_socket)
10386 SysRes r;
10387 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
10388 SET_STATUS_from_SysRes(r);
10391 PRE(sys_so_socketpair)
10393 /* int so_socketpair(int sv[2]); */
10394 /* This syscall is used to connect two already created sockets together. */
10395 PRINT("sys_so_socketpair ( %#lx )", ARG1);
10396 PRE_REG_READ1(long, "socketpair", int *, sv);
10397 PRE_MEM_READ("socketpair(sv)", ARG1, 2 * sizeof(int));
10398 /*PRE_MEM_WRITE("socketpair(sv)", ARG1, 2 * sizeof(int));*/
10399 if (ML_(safe_to_deref)((void*)ARG1, 2 * sizeof(int))) {
10400 int *fds = (int*)ARG1;
10401 if (!ML_(fd_allowed)(fds[0], "socketpair", tid, False))
10402 SET_STATUS_Failure(VKI_EBADF);
10403 else if (!ML_(fd_allowed)(fds[1], "socketpair", tid, False))
10404 SET_STATUS_Failure(VKI_EBADF);
10408 POST(sys_so_socketpair)
10410 /* The kernel can return new file descriptors, in such a case we have to
10411 validate them. */
10412 int *fds = (int*)ARG1;
10413 POST_MEM_WRITE(ARG1, 2 * sizeof(int));
10414 if (!ML_(fd_allowed)(fds[0], "socketpair", tid, True))
10415 SET_STATUS_Failure(VKI_EMFILE);
10416 if (!ML_(fd_allowed)(fds[1], "socketpair", tid, True))
10417 SET_STATUS_Failure(VKI_EMFILE);
10418 if (FAILURE) {
10419 /* One or both of the file descriptors weren't allowed, close newly
10420 created file descriptors but don't close the already recorded
10421 ones. */
10422 if (!ML_(fd_recorded)(fds[0]))
10423 VG_(close)(fds[0]);
10424 if (!ML_(fd_recorded)(fds[1]))
10425 VG_(close)(fds[1]);
10427 else if (VG_(clo_track_fds)) {
10428 /* Everything went better than expected, record the newly created file
10429 descriptors. Note: If the kernel actually returns the original file
10430 descriptors, then ML_(record_fd_open_nameless) notices that these
10431 file descriptors have been already recorded. */
10432 ML_(record_fd_open_nameless)(tid, fds[0]);
10433 ML_(record_fd_open_nameless)(tid, fds[1]);
10437 PRE(sys_bind)
10439 /* int bind(int s, struct sockaddr *name, socklen_t namelen,
10440 int version); */
10441 PRINT("sys_bind ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
10442 PRE_REG_READ4(long, "bind", int, s, struct sockaddr *, name,
10443 vki_socklen_t, namelen, int, version);
10444 ML_(generic_PRE_sys_bind)(tid, ARG1, ARG2, ARG3);
10447 PRE(sys_listen)
10449 /* int listen(int s, int backlog, int version); */
10450 PRINT("sys_listen ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
10451 PRE_REG_READ3(long, "listen", int, s, int, backlog, int, version);
10454 PRE(sys_accept)
10456 #if defined(SOLARIS_NEW_ACCEPT_SYSCALL)
10457 /* int accept(int s, struct sockaddr *addr, socklen_t *addrlen,
10458 int version, int flags); */
10459 *flags |= SfMayBlock;
10460 PRINT("sys_accept ( %ld, %#lx, %#lx, %ld, %ld )", SARG1, ARG2, ARG3, SARG4,
10461 SARG5);
10462 PRE_REG_READ5(long, "accept", int, s, struct sockaddr *, addr,
10463 socklen_t *, addrlen, int, version, int, flags);
10464 #else
10465 /* int accept(int s, struct sockaddr *addr, socklen_t *addrlen,
10466 int version); */
10467 *flags |= SfMayBlock;
10468 PRINT("sys_accept ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
10469 PRE_REG_READ4(long, "accept", int, s, struct sockaddr *, addr,
10470 socklen_t *, addrlen, int, version);
10471 #endif /* SOLARIS_NEW_ACCEPT_SYSCALL */
10472 ML_(generic_PRE_sys_accept)(tid, ARG1, ARG2, ARG3);
10475 POST(sys_accept)
10477 SysRes r;
10478 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
10479 ARG1, ARG2, ARG3);
10480 SET_STATUS_from_SysRes(r);
10483 PRE(sys_connect)
10485 /* int connect(int s, struct sockaddr *name, socklen_t namelen,
10486 int version); */
10487 *flags |= SfMayBlock;
10488 PRINT("sys_connect ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
10489 PRE_REG_READ4(long, "connect", int, s, struct sockaddr *, name,
10490 vki_socklen_t, namelen, int, version);
10491 ML_(generic_PRE_sys_connect)(tid, ARG1, ARG2, ARG3);
10494 PRE(sys_shutdown)
10496 /* Kernel: int shutdown(int sock, int how, int version);
10497 Libc: int shutdown(int sock, int how);
10499 *flags |= SfMayBlock;
10500 PRINT("sys_shutdown ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
10501 PRE_REG_READ3(int, "shutdown", int, sock, int, how, int, version);
10503 /* Be strict. */
10504 if (!ML_(fd_allowed)(ARG1, "shutdown", tid, False))
10505 SET_STATUS_Failure(VKI_EBADF);
10508 PRE(sys_recv)
10510 /* ssize_t recv(int s, void *buf, size_t len, int flags); */
10511 *flags |= SfMayBlock;
10512 PRINT("sys_recv ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
10513 PRE_REG_READ4(long, "recv", int, s, void *, buf, vki_size_t, len,
10514 int, flags);
10515 ML_(generic_PRE_sys_recv)(tid, ARG1, ARG2, ARG3);
10518 POST(sys_recv)
10520 ML_(generic_POST_sys_recv)(tid, RES, ARG1, ARG2, ARG3);
10523 PRE(sys_recvfrom)
10525 /* ssize_t recvfrom(int s, void *buf, size_t len, int flags,
10526 struct sockaddr *from, socklen_t *fromlen); */
10527 *flags |= SfMayBlock;
10528 PRINT("sys_recvfrom ( %ld, %#lx, %lu, %ld, %#lx, %#lx )", SARG1, ARG2, ARG3,
10529 SARG4, ARG5, ARG6);
10530 PRE_REG_READ6(long, "recvfrom", int, s, void *, buf, vki_size_t, len,
10531 int, flags, struct sockaddr *, from, socklen_t *, fromlen);
10532 ML_(generic_PRE_sys_recvfrom)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10535 POST(sys_recvfrom)
10537 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
10538 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10541 PRE(sys_recvmsg)
10543 /* ssize_t recvmsg(int s, struct msghdr *msg, int flags); */
10544 *flags |= SfMayBlock;
10545 PRINT("sys_recvmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
10546 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
10547 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr*)ARG2);
10550 POST(sys_recvmsg)
10552 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr*)ARG2, RES);
10555 PRE(sys_send)
10557 /* ssize_t send(int s, const void *msg, size_t len, int flags); */
10558 *flags |= SfMayBlock;
10559 PRINT("sys_send ( %ld, %#lx, %lu, %ld )", SARG1, ARG2, ARG3, SARG4);
10560 PRE_REG_READ4(long, "send", int, s, const void *, msg, vki_size_t, len,
10561 int, flags);
10562 ML_(generic_PRE_sys_send)(tid, ARG1, ARG2, ARG3);
10565 PRE(sys_sendmsg)
10567 /* ssize_t sendmsg(int s, const struct msghdr *msg, int flags); */
10568 *flags |= SfMayBlock;
10569 PRINT("sys_sendmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
10570 PRE_REG_READ3(long, "sendmsg", int, s, const struct msghdr *, msg,
10571 int, flags);
10572 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr*)ARG2);
10575 PRE(sys_sendto)
10577 /* ssize_t sendto(int s, const void *msg, size_t len, int flags,
10578 const struct sockaddr *to, int tolen); */
10579 *flags |= SfMayBlock;
10580 PRINT("sys_sendto ( %ld, %#lx, %lu, %ld, %#lx, %ld )", SARG1, ARG2, ARG3,
10581 SARG4, ARG5, SARG6);
10582 PRE_REG_READ6(long, "sendto", int, s, const void *, msg, vki_size_t, len,
10583 int, flags, const struct sockaddr *, to, int, tolen);
10584 ML_(generic_PRE_sys_sendto)(tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10587 PRE(sys_getpeername)
10589 /* Kernel: int getpeername(int s, struct sockaddr *name,
10590 socklen_t *namelen, int version);
10591 Libc: int getpeername(int s, struct sockaddr *name,
10592 socklen_t *namelen);
10594 *flags |= SfMayBlock;
10595 PRINT("sys_getpeername ( %ld, %#lx, %#lx, %ld )",
10596 SARG1, ARG2, ARG3, SARG4);
10597 PRE_REG_READ4(long, "getpeername", int, s, struct vki_sockaddr *, name,
10598 vki_socklen_t *, namelen, int, version);
10599 ML_(buf_and_len_pre_check)(tid, ARG2, ARG3, "getpeername(name)",
10600 "getpeername(namelen)");
10602 /* Be strict. */
10603 if (!ML_(fd_allowed)(ARG1, "getpeername", tid, False))
10604 SET_STATUS_Failure(VKI_EBADF);
10607 POST(sys_getpeername)
10609 ML_(buf_and_len_post_check)(tid, VG_(mk_SysRes_Success)(RES),
10610 ARG2, ARG3, "getpeername(namelen)");
10613 PRE(sys_getsockname)
10615 /* int getsockname(int s, struct sockaddr *name, socklen_t *namelen,
10616 int version); */
10617 PRINT("sys_getsockname ( %ld, %#lx, %#lx, %ld )", SARG1, ARG2, ARG3, SARG4);
10618 PRE_REG_READ4(long, "getsockname", int, s, struct sockaddr *, name,
10619 socklen_t *, namelen, int, version);
10620 ML_(generic_PRE_sys_getsockname)(tid, ARG1, ARG2, ARG3);
10623 POST(sys_getsockname)
10625 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
10626 ARG1, ARG2, ARG3);
10629 PRE(sys_getsockopt)
10631 /* int getsockopt(int s, int level, int optname, void *optval,
10632 socklen_t *optlen, int version); */
10633 PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx, %ld )", SARG1, SARG2,
10634 SARG3, ARG4, ARG5, SARG6);
10635 PRE_REG_READ6(long, "getsockopt", int, s, int, level, int, optname,
10636 void *, optval, socklen_t *, option, int, version);
10637 if (ARG4)
10638 ML_(buf_and_len_pre_check)(tid, ARG4, ARG5, "getsockopt(optval)",
10639 "getsockopt(optlen)");
10642 POST(sys_getsockopt)
10644 if (ARG4)
10645 ML_(buf_and_len_post_check)(tid, VG_(mk_SysRes_Success)(RES), ARG4,
10646 ARG5, "getsockopt(optlen_out)");
10649 PRE(sys_setsockopt)
10651 /* int setsockopt(int s, int level, int optname, const void *optval,
10652 socklen_t optlen, int version); */
10653 PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %lu, %ld )", SARG1, SARG2,
10654 SARG3, ARG4, ARG5, SARG6);
10655 PRE_REG_READ6(long, "setsockopt", int, s, int, level, int, optname,
10656 const void *, optval, vki_socklen_t, optlen, int, version);
10657 ML_(generic_PRE_sys_setsockopt)(tid, ARG1, ARG2, ARG3, ARG4, ARG5);
10660 PRE(sys_lwp_mutex_register)
10662 /* int lwp_mutex_register(lwp_mutex_t *mp, caddr_t uaddr); */
10663 vki_lwp_mutex_t *mp = (vki_lwp_mutex_t*)ARG1;
10664 PRINT("sys_lwp_mutex_register ( %#lx, %#lx )", ARG1, ARG2);
10665 PRE_REG_READ2(long, "lwp_mutex_register", lwp_mutex_t *, mp,
10666 void *, uaddr);
10667 PRE_FIELD_READ("lwp_mutex_register(mp->mutex_type)", mp->vki_mutex_type);
10670 PRE(sys_lwp_mutex_unlock)
10672 /* int lwp_mutex_unlock(lwp_mutex_t *lp); */
10673 /* see https://github.com/illumos/illumos-gate/blob/master/usr/src/uts/common/syscall/lwp_sobj.c#L3137-L3138
10674 * (illumos, obviously) */
10675 vki_lwp_mutex_t *lp = (vki_lwp_mutex_t*)ARG1;
10676 PRINT("sys_lwp_mutex_unlock ( %#lx )", ARG1);
10677 PRE_REG_READ1(int, "lwp_mutex_unlock", lwp_mutex_t *, lp);
10678 PRE_MEM_READ("lwp_mutex_unlock(lp)", (Addr)lp, sizeof(vki_lwp_mutex_t));
10679 PRE_MEM_WRITE("lwp_mutex_unlock(lp)", (Addr)lp, sizeof(vki_lwp_mutex_t));
10682 POST(sys_lwp_mutex_unlock)
10684 POST_MEM_WRITE(ARG1, sizeof(vki_lwp_mutex_t));
10687 PRE(sys_uucopy)
10689 /* int uucopy(const void *s1, void *s2, size_t n); */
10690 PRINT("sys_uucopy ( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
10691 PRE_REG_READ3(long, "uucopy", const void *, s1, void *, s2, vki_size_t, n);
10693 /* Stay away from V segments. */
10694 if (!ML_(valid_client_addr)(ARG1, ARG3, tid, "uucopy(s1)")) {
10695 SET_STATUS_Failure(VKI_EFAULT);
10697 if (!ML_(valid_client_addr)(ARG2, ARG3, tid, "uucopy(s2)")) {
10698 SET_STATUS_Failure(VKI_EFAULT);
10701 if (FAILURE)
10702 return;
10704 /* XXX This is actually incorrect, we should be able to copy undefined
10705 values through to their new destination. */
10706 PRE_MEM_READ("uucopy(s1)", ARG1, ARG3);
10707 PRE_MEM_WRITE("uucopy(s2)", ARG2, ARG3);
10710 POST(sys_uucopy)
10712 POST_MEM_WRITE(ARG2, ARG3);
10715 PRE(sys_umount2)
10717 /* int umount2(const char *file, int mflag); */
10718 *flags |= SfMayBlock;
10719 PRINT("sys_umount2 ( %#lx(%s), %ld )", ARG1, (HChar *) ARG1, SARG2);
10720 PRE_REG_READ2(long, "umount2", const char *, file, int, mflag);
10721 PRE_MEM_RASCIIZ("umount2(file)", ARG1);
10724 PRE(fast_gethrtime)
10726 PRINT("fast_gethrtime ( )");
10727 PRE_REG_READ0(long, "gethrtime");
10730 PRE(fast_gethrvtime)
10732 PRINT("fast_gethrvtime ( )");
10733 PRE_REG_READ0(long, "gethrvtime");
10736 PRE(fast_gethrestime)
10738 /* Used by gettimeofday(3C). */
10739 PRINT("fast_gethrestime ( )");
10740 PRE_REG_READ0(long, "gethrestime");
10743 PRE(fast_getlgrp)
10745 /* Fasttrap number shared between gethomelgroup() and getcpuid(). */
10746 PRINT("fast_getlgrp ( )");
10747 PRE_REG_READ0(long, "getlgrp");
10750 #if defined(SOLARIS_GETHRT_FASTTRAP)
10751 PRE(fast_gethrt)
10753 /* Used by gethrtime(3C) when tsp & tscp HWCAPs are present. */
10754 PRINT("fast_gethrt ( )");
10755 PRE_REG_READ0(long, "gethrt");
10758 POST(fast_gethrt)
10760 if (RES == 0)
10761 return;
10763 VG_(change_mapping_ownership)(RES, False);
10765 #endif /* SOLARIS_GETHRT_FASTTRAP */
10767 #if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
10768 PRE(fast_getzoneoffset)
10770 /* Returns kernel's time zone offset data. */
10771 PRINT("fast_getzoneoffset ( )");
10772 PRE_REG_READ0(long, "get_zone_offset");
10775 POST(fast_getzoneoffset)
10777 if (RES == 0)
10778 return;
10780 VG_(change_mapping_ownership)(RES, False);
10782 #endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
10784 #undef PRE
10785 #undef POST
10787 /* ---------------------------------------------------------------------
10788 The Solaris syscall table
10789 ------------------------------------------------------------------ */
10791 /* Add a Solaris-specific, arch-independent wrapper to a syscall table. */
10792 #define SOLX_(sysno, name) \
10793 WRAPPER_ENTRY_X_(solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10794 #define SOLXY(sysno, name) \
10795 WRAPPER_ENTRY_XY(solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10797 #if defined(VGP_x86_solaris)
10798 /* Add an x86-solaris specific wrapper to a syscall table. */
10799 #define PLAX_(sysno, name) \
10800 WRAPPER_ENTRY_X_(x86_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10801 #define PLAXY(sysno, name) \
10802 WRAPPER_ENTRY_XY(x86_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10804 #elif defined(VGP_amd64_solaris)
10805 /* Add an amd64-solaris specific wrapper to a syscall table. */
10806 #define PLAX_(sysno, name) \
10807 WRAPPER_ENTRY_X_(amd64_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10808 #define PLAXY(sysno, name) \
10809 WRAPPER_ENTRY_XY(amd64_solaris, VG_SOLARIS_SYSNO_INDEX(sysno), name)
10811 #else
10812 # error "Unknown platform"
10813 #endif
10816 GEN : handlers are in syswrap-generic.c
10817 SOL : handlers are in this file
10818 X_ : PRE handler only
10819 XY : PRE and POST handlers
10822 static SyscallTableEntry syscall_table[] = {
10823 SOLX_(__NR_exit, sys_exit), /* 1 */
10824 #if defined(SOLARIS_SPAWN_SYSCALL)
10825 SOLX_(__NR_spawn, sys_spawn), /* 2 */
10826 #endif /* SOLARIS_SPAWN_SYSCALL */
10827 GENXY(__NR_read, sys_read), /* 3 */
10828 GENX_(__NR_write, sys_write), /* 4 */
10829 #if defined(SOLARIS_OLD_SYSCALLS)
10830 SOLXY(__NR_open, sys_open), /* 5 */
10831 #endif /* SOLARIS_OLD_SYSCALLS */
10832 SOLXY(__NR_close, sys_close), /* 6 */
10833 SOLX_(__NR_linkat, sys_linkat), /* 7 */
10834 #if defined(SOLARIS_OLD_SYSCALLS)
10835 GENX_(__NR_link, sys_link), /* 9 */
10836 GENX_(__NR_unlink, sys_unlink), /* 10 */
10837 #endif /* SOLARIS_OLD_SYSCALLS */
10838 SOLX_(__NR_symlinkat, sys_symlinkat), /* 11 */
10839 GENX_(__NR_chdir, sys_chdir), /* 12 */
10840 SOLX_(__NR_time, sys_time), /* 13 */
10841 #if defined(SOLARIS_OLD_SYSCALLS)
10842 GENX_(__NR_chmod, sys_chmod), /* 15 */
10843 GENX_(__NR_chown, sys_chown), /* 16 */
10844 #endif /* SOLARIS_OLD_SYSCALLS */
10845 SOLX_(__NR_brk, sys_brk), /* 17 */
10846 #if defined(SOLARIS_OLD_SYSCALLS)
10847 SOLXY(__NR_stat, sys_stat), /* 18 */
10848 #endif /* SOLARIS_OLD_SYSCALLS */
10849 SOLX_(__NR_lseek, sys_lseek), /* 19 */
10850 GENX_(__NR_getpid, sys_getpid), /* 20 */
10851 SOLXY(__NR_mount, sys_mount), /* 21 */
10852 SOLXY(__NR_readlinkat, sys_readlinkat), /* 22 */
10853 GENX_(__NR_setuid, sys_setuid), /* 23 */
10854 GENX_(__NR_getuid, sys_getuid), /* 24 */
10855 SOLX_(__NR_stime, sys_stime), /* 25 */
10856 GENX_(__NR_alarm, sys_alarm), /* 27 */
10857 #if defined(SOLARIS_OLD_SYSCALLS)
10858 SOLXY(__NR_fstat, sys_fstat), /* 28 */
10859 #endif /* SOLARIS_OLD_SYSCALLS */
10860 GENX_(__NR_pause, sys_pause), /* 29 */
10861 #if defined(SOLARIS_FREALPATHAT_SYSCALL)
10862 SOLXY(__NR_frealpathat, sys_frealpathat), /* 30 */
10863 #endif /* SOLARIS_FREALPATHAT_SYSCALL */
10864 SOLX_(__NR_stty, sys_stty), /* 31 */
10865 SOLXY(__NR_gtty, sys_gtty), /* 32 */
10866 #if defined(SOLARIS_OLD_SYSCALLS)
10867 GENX_(__NR_access, sys_access), /* 33 */
10868 #endif /* SOLARIS_OLD_SYSCALLS */
10869 GENX_(__NR_kill, sys_kill), /* 37 */
10870 SOLX_(__NR_pgrpsys, sys_pgrpsys), /* 39 */
10871 SOLXY(__NR_pipe, sys_pipe), /* 42 */
10872 GENXY(__NR_times, sys_times), /* 43 */
10873 SOLX_(__NR_faccessat, sys_faccessat), /* 45 */
10874 GENX_(__NR_setgid, sys_setgid), /* 46 */
10875 GENX_(__NR_getgid, sys_getgid), /* 47 */
10876 SOLXY(__NR_mknodat, sys_mknodat), /* 48 */
10877 SOLXY(__NR_sysi86, sys_sysi86), /* 50 */
10878 SOLXY(__NR_shmsys, sys_shmsys), /* 52 */
10879 SOLXY(__NR_semsys, sys_semsys), /* 53 */
10880 SOLXY(__NR_ioctl, sys_ioctl), /* 54 */
10881 SOLX_(__NR_fchownat, sys_fchownat), /* 56 */
10882 SOLX_(__NR_fdsync, sys_fdsync), /* 58 */
10883 SOLX_(__NR_execve, sys_execve), /* 59 */
10884 GENX_(__NR_umask, sys_umask), /* 60 */
10885 GENX_(__NR_chroot, sys_chroot), /* 61 */
10886 SOLXY(__NR_fcntl, sys_fcntl), /* 62 */
10887 SOLX_(__NR_renameat, sys_renameat), /* 64 */
10888 SOLX_(__NR_unlinkat, sys_unlinkat), /* 65 */
10889 SOLXY(__NR_fstatat, sys_fstatat), /* 66 */
10890 #if defined(VGP_x86_solaris)
10891 PLAXY(__NR_fstatat64, sys_fstatat64), /* 67 */
10892 #endif /* VGP_x86_solaris */
10893 SOLXY(__NR_openat, sys_openat), /* 68 */
10894 #if defined(VGP_x86_solaris)
10895 PLAXY(__NR_openat64, sys_openat64), /* 69 */
10896 #endif /* VGP_x86_solaris */
10897 SOLXY(__NR_tasksys, sys_tasksys), /* 70 */
10898 SOLXY(__NR_getpagesizes, sys_getpagesizes), /* 73 */
10899 SOLXY(__NR_lwp_park, sys_lwp_park), /* 77 */
10900 SOLXY(__NR_sendfilev, sys_sendfilev), /* 78 */
10901 #if defined(SOLARIS_LWP_NAME_SYSCALL)
10902 SOLXY(__NR_lwp_name, sys_lwp_name), /* 79 */
10903 #endif /* SOLARIS_LWP_NAME_SYSCALL */
10904 #if defined(SOLARIS_OLD_SYSCALLS)
10905 GENX_(__NR_rmdir, sys_rmdir), /* 79 */
10906 GENX_(__NR_mkdir, sys_mkdir), /* 80 */
10907 #endif /* SOLARIS_OLD_SYSCALLS */
10908 GENXY(__NR_getdents, sys_getdents), /* 81 */
10909 SOLXY(__NR_privsys, sys_privsys), /* 82 */
10910 SOLXY(__NR_ucredsys, sys_ucredsys), /* 83 */
10911 SOLXY(__NR_sysfs, sys_sysfs), /* 84 */
10912 SOLXY(__NR_getmsg, sys_getmsg), /* 85 */
10913 SOLX_(__NR_putmsg, sys_putmsg), /* 86 */
10914 #if defined(SOLARIS_OLD_SYSCALLS)
10915 SOLXY(__NR_lstat, sys_lstat), /* 88 */
10916 GENX_(__NR_symlink, sys_symlink), /* 89 */
10917 GENX_(__NR_readlink, sys_readlink), /* 90 */
10918 #endif /* SOLARIS_OLD_SYSCALLS */
10919 GENX_(__NR_setgroups, sys_setgroups), /* 91 */
10920 GENXY(__NR_getgroups, sys_getgroups), /* 92 */
10921 #if defined(SOLARIS_OLD_SYSCALLS)
10922 GENX_(__NR_fchmod, sys_fchmod), /* 93 */
10923 GENX_(__NR_fchown, sys_fchown), /* 94 */
10924 #endif /* SOLARIS_OLD_SYSCALLS */
10925 SOLXY(__NR_sigprocmask, sys_sigprocmask), /* 95 */
10926 SOLX_(__NR_sigsuspend, sys_sigsuspend), /* 96 */
10927 GENXY(__NR_sigaltstack, sys_sigaltstack), /* 97 */
10928 SOLXY(__NR_sigaction, sys_sigaction), /* 98 */
10929 SOLXY(__NR_sigpending, sys_sigpending), /* 99 */
10930 SOLX_(__NR_context, sys_getsetcontext), /* 100 */
10931 SOLX_(__NR_fchmodat, sys_fchmodat), /* 101 */
10932 SOLX_(__NR_mkdirat, sys_mkdirat), /* 102 */
10933 SOLXY(__NR_statvfs, sys_statvfs), /* 103 */
10934 SOLXY(__NR_fstatvfs, sys_fstatvfs), /* 104 */
10935 SOLXY(__NR_nfssys, sys_nfssys), /* 106 */
10936 SOLXY(__NR_waitid, sys_waitid), /* 107 */
10937 SOLX_(__NR_sigsendsys, sys_sigsendsys), /* 108 */
10938 #if defined(SOLARIS_UTIMESYS_SYSCALL)
10939 SOLX_(__NR_utimesys, sys_utimesys), /* 110 */
10940 #endif /* SOLARIS_UTIMESYS_SYSCALL */
10941 #if defined(SOLARIS_UTIMENSAT_SYSCALL)
10942 SOLX_(__NR_utimensat, sys_utimensat), /* 110 */
10943 #endif /* SOLARIS_UTIMENSAT_SYSCALL */
10944 SOLXY(__NR_sigresend, sys_sigresend), /* 111 */
10945 SOLXY(__NR_priocntlsys, sys_priocntlsys), /* 112 */
10946 SOLX_(__NR_pathconf, sys_pathconf), /* 113 */
10947 SOLX_(__NR_mmap, sys_mmap), /* 115 */
10948 GENXY(__NR_mprotect, sys_mprotect), /* 116 */
10949 GENXY(__NR_munmap, sys_munmap), /* 117 */
10950 GENX_(__NR_fchdir, sys_fchdir), /* 120 */
10951 GENXY(__NR_readv, sys_readv), /* 121 */
10952 GENX_(__NR_writev, sys_writev), /* 122 */
10953 #if defined(SOLARIS_UUIDSYS_SYSCALL)
10954 SOLXY(__NR_uuidsys, sys_uuidsys), /* 124 */
10955 #endif /* SOLARIS_UUIDSYS_SYSCALL */
10956 SOLX_(__NR_mmapobj, sys_mmapobj), /* 127 */
10957 GENX_(__NR_setrlimit, sys_setrlimit), /* 128 */
10958 GENXY(__NR_getrlimit, sys_getrlimit), /* 129 */
10959 #if defined(SOLARIS_OLD_SYSCALLS)
10960 GENX_(__NR_lchown, sys_lchown), /* 130 */
10961 #endif /* SOLARIS_OLD_SYSCALLS */
10962 SOLX_(__NR_memcntl, sys_memcntl), /* 131 */
10963 SOLXY(__NR_getpmsg, sys_getpmsg), /* 132 */
10964 SOLX_(__NR_putpmsg, sys_putpmsg), /* 133 */
10965 #if defined(SOLARIS_OLD_SYSCALLS)
10966 SOLX_(__NR_rename, sys_rename), /* 134 */
10967 #endif /* SOLARIS_OLD_SYSCALLS */
10968 SOLXY(__NR_uname, sys_uname), /* 135 */
10969 SOLX_(__NR_setegid, sys_setegid), /* 136 */
10970 SOLX_(__NR_sysconfig, sys_sysconfig), /* 137 */
10971 SOLXY(__NR_systeminfo, sys_systeminfo), /* 139 */
10972 SOLX_(__NR_seteuid, sys_seteuid), /* 141 */
10973 SOLX_(__NR_forksys, sys_forksys), /* 142 */
10974 #if defined(SOLARIS_GETRANDOM_SYSCALL)
10975 SOLXY(__NR_getrandom, sys_getrandom), /* 143 */
10976 #endif /* SOLARIS_GETRANDOM_SYSCALL */
10977 SOLXY(__NR_sigtimedwait, sys_sigtimedwait), /* 144 */
10978 SOLX_(__NR_yield, sys_yield), /* 146 */
10979 SOLXY(__NR_lwp_sema_post, sys_lwp_sema_post), /* 148 */
10980 SOLXY(__NR_lwp_sema_trywait, sys_lwp_sema_trywait), /* 149 */
10981 SOLX_(__NR_lwp_detach, sys_lwp_detach), /* 150 */
10982 SOLXY(__NR_modctl, sys_modctl), /* 152 */
10983 SOLX_(__NR_fchroot, sys_fchroot), /* 153 */
10984 #if defined(SOLARIS_SYSTEM_STATS_SYSCALL)
10985 SOLX_(__NR_system_stats, sys_system_stats), /* 154 */
10986 #endif /* SOLARIS_SYSTEM_STATS_SYSCALL */
10987 SOLXY(__NR_gettimeofday, sys_gettimeofday), /* 156 */
10988 GENXY(__NR_getitimer, sys_getitimer), /* 157 */
10989 GENXY(__NR_setitimer, sys_setitimer), /* 158 */
10990 SOLX_(__NR_lwp_create, sys_lwp_create), /* 159 */
10991 SOLX_(__NR_lwp_exit, sys_lwp_exit), /* 160 */
10992 SOLX_(__NR_lwp_suspend, sys_lwp_suspend), /* 161 */
10993 SOLX_(__NR_lwp_continue, sys_lwp_continue), /* 162 */
10994 #if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
10995 SOLXY(__NR_lwp_sigqueue, sys_lwp_sigqueue), /* 163 */
10996 #else
10997 SOLXY(__NR_lwp_kill, sys_lwp_kill), /* 163 */
10998 #endif /* SOLARIS_LWP_SIGQUEUE_SYSCALL */
10999 SOLX_(__NR_lwp_self, sys_lwp_self), /* 164 */
11000 SOLX_(__NR_lwp_sigmask, sys_lwp_sigmask), /* 165 */
11001 SOLX_(__NR_lwp_private, sys_lwp_private), /* 166 */
11002 SOLXY(__NR_lwp_wait, sys_lwp_wait), /* 167 */
11003 SOLXY(__NR_lwp_mutex_wakeup, sys_lwp_mutex_wakeup), /* 168 */
11004 SOLXY(__NR_lwp_cond_wait, sys_lwp_cond_wait), /* 170 */
11005 SOLXY(__NR_lwp_cond_signal, sys_lwp_cond_signal), /* 171 */
11006 SOLX_(__NR_lwp_cond_broadcast, sys_lwp_cond_broadcast), /* 172 */
11007 SOLXY(__NR_pread, sys_pread), /* 173 */
11008 SOLX_(__NR_pwrite, sys_pwrite), /* 174 */
11009 #if defined(VGP_x86_solaris)
11010 PLAX_(__NR_llseek, sys_llseek32), /* 175 */
11011 #endif /* VGP_x86_solaris */
11012 SOLXY(__NR_lgrpsys, sys_lgrpsys), /* 180 */
11013 SOLXY(__NR_rusagesys, sys_rusagesys), /* 181 */
11014 SOLXY(__NR_port, sys_port), /* 182 */
11015 SOLXY(__NR_pollsys, sys_pollsys), /* 183 */
11016 SOLXY(__NR_labelsys, sys_labelsys), /* 184 */
11017 SOLXY(__NR_acl, sys_acl), /* 185 */
11018 SOLXY(__NR_auditsys, sys_auditsys), /* 186 */
11019 SOLX_(__NR_p_online, sys_p_online), /* 189 */
11020 SOLX_(__NR_sigqueue, sys_sigqueue), /* 190 */
11021 SOLXY(__NR_clock_gettime, sys_clock_gettime), /* 191 */
11022 SOLX_(__NR_clock_settime, sys_clock_settime), /* 192 */
11023 SOLXY(__NR_clock_getres, sys_clock_getres), /* 193 */
11024 SOLXY(__NR_timer_create, sys_timer_create), /* 194 */
11025 SOLX_(__NR_timer_delete, sys_timer_delete), /* 195 */
11026 SOLXY(__NR_timer_settime, sys_timer_settime), /* 196 */
11027 SOLXY(__NR_timer_gettime, sys_timer_gettime), /* 197 */
11028 SOLX_(__NR_timer_getoverrun, sys_timer_getoverrun), /* 198 */
11029 GENXY(__NR_nanosleep, sys_nanosleep), /* 199 */
11030 SOLXY(__NR_facl, sys_facl), /* 200 */
11031 SOLXY(__NR_door, sys_door), /* 201 */
11032 GENX_(__NR_setreuid, sys_setreuid), /* 202 */
11033 GENX_(__NR_setregid, sys_setregid), /* 202 */
11034 SOLXY(__NR_schedctl, sys_schedctl), /* 206 */
11035 SOLXY(__NR_pset, sys_pset), /* 207 */
11036 SOLXY(__NR_resolvepath, sys_resolvepath), /* 209 */
11037 SOLXY(__NR_lwp_mutex_timedlock, sys_lwp_mutex_timedlock), /* 210 */
11038 SOLXY(__NR_lwp_sema_timedwait, sys_lwp_sema_timedwait), /* 211 */
11039 SOLXY(__NR_lwp_rwlock_sys, sys_lwp_rwlock_sys), /* 212 */
11040 #if defined(VGP_x86_solaris)
11041 GENXY(__NR_getdents64, sys_getdents64), /* 213 */
11042 PLAX_(__NR_mmap64, sys_mmap64), /* 214 */
11043 #if defined(SOLARIS_OLD_SYSCALLS)
11044 PLAXY(__NR_stat64, sys_stat64), /* 215 */
11045 PLAXY(__NR_lstat64, sys_lstat64), /* 216 */
11046 PLAXY(__NR_fstat64, sys_fstat64), /* 217 */
11047 #endif /* SOLARIS_OLD_SYSCALLS */
11048 PLAXY(__NR_statvfs64, sys_statvfs64), /* 218 */
11049 PLAXY(__NR_fstatvfs64, sys_fstatvfs64), /* 219 */
11050 #endif /* VGP_x86_solaris */
11051 #if defined(VGP_x86_solaris)
11052 PLAX_(__NR_setrlimit64, sys_setrlimit64), /* 220 */
11053 PLAXY(__NR_getrlimit64, sys_getrlimit64), /* 221 */
11054 PLAXY(__NR_pread64, sys_pread64), /* 222 */
11055 PLAX_(__NR_pwrite64, sys_pwrite64), /* 223 */
11056 #if defined(SOLARIS_OLD_SYSCALLS)
11057 PLAXY(__NR_open64, sys_open64), /* 225 */
11058 #endif /* SOLARIS_OLD_SYSCALLS */
11059 #endif /* VGP_x86_solaris */
11060 SOLXY(__NR_zone, sys_zone), /* 227 */
11061 SOLXY(__NR_getcwd, sys_getcwd), /* 229 */
11062 SOLXY(__NR_so_socket, sys_so_socket), /* 230 */
11063 SOLXY(__NR_so_socketpair, sys_so_socketpair), /* 231 */
11064 SOLX_(__NR_bind, sys_bind), /* 232 */
11065 SOLX_(__NR_listen, sys_listen), /* 233 */
11066 SOLXY(__NR_accept, sys_accept), /* 234 */
11067 SOLX_(__NR_connect, sys_connect), /* 235 */
11068 SOLX_(__NR_shutdown, sys_shutdown), /* 236 */
11069 SOLXY(__NR_recv, sys_recv), /* 237 */
11070 SOLXY(__NR_recvfrom, sys_recvfrom), /* 238 */
11071 SOLXY(__NR_recvmsg, sys_recvmsg), /* 239 */
11072 SOLX_(__NR_send, sys_send), /* 240 */
11073 SOLX_(__NR_sendmsg, sys_sendmsg), /* 241 */
11074 SOLX_(__NR_sendto, sys_sendto), /* 242 */
11075 SOLXY(__NR_getpeername, sys_getpeername), /* 243 */
11076 SOLXY(__NR_getsockname, sys_getsockname), /* 244 */
11077 SOLXY(__NR_getsockopt, sys_getsockopt), /* 245 */
11078 SOLX_(__NR_setsockopt, sys_setsockopt), /* 246 */
11079 SOLXY(__NR_lwp_mutex_unlock, sys_lwp_mutex_unlock), /* 250 */
11080 SOLX_(__NR_lwp_mutex_register, sys_lwp_mutex_register), /* 252 */
11081 SOLXY(__NR_uucopy, sys_uucopy), /* 254 */
11082 SOLX_(__NR_umount2, sys_umount2) /* 255 */
11085 static SyscallTableEntry fasttrap_table[] = {
11086 SOLX_(__NR_gethrtime, fast_gethrtime), /* 3 */
11087 SOLX_(__NR_gethrvtime, fast_gethrvtime), /* 4 */
11088 SOLX_(__NR_gethrestime, fast_gethrestime), /* 5 */
11089 SOLX_(__NR_getlgrp, fast_getlgrp) /* 6 */
11090 #if defined(SOLARIS_GETHRT_FASTTRAP)
11092 SOLXY(__NR_gethrt, fast_gethrt) /* 7 */
11093 #endif /* SOLARIS_GETHRT_FASTTRAP */
11094 #if defined(SOLARIS_GETZONEOFFSET_FASTTRAP)
11096 SOLXY(__NR_getzoneoffset, fast_getzoneoffset) /* 8 */
11097 #endif /* SOLARIS_GETZONEOFFSET_FASTTRAP */
11101 SyscallTableEntry *ML_(get_solaris_syscall_entry)(UInt sysno)
11103 const UInt syscall_table_size
11104 = sizeof(syscall_table) / sizeof(syscall_table[0]);
11105 const UInt fasttrap_table_size
11106 = sizeof(fasttrap_table) / sizeof(fasttrap_table[0]);
11108 SyscallTableEntry *table;
11109 Int size;
11111 switch (VG_SOLARIS_SYSNO_CLASS(sysno)) {
11112 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC:
11113 table = syscall_table;
11114 size = syscall_table_size;
11115 break;
11116 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP:
11117 table = fasttrap_table;
11118 size = fasttrap_table_size;
11119 break;
11120 default:
11121 vg_assert(0);
11122 break;
11124 sysno = VG_SOLARIS_SYSNO_INDEX(sysno);
11125 if (sysno < size) {
11126 SyscallTableEntry *sys = &table[sysno];
11127 if (!sys->before)
11128 return NULL; /* no entry */
11129 return sys;
11132 /* Can't find a wrapper. */
11133 return NULL;
11136 #endif // defined(VGO_solaris)
11138 /*--------------------------------------------------------------------*/
11139 /*--- end ---*/
11140 /*--------------------------------------------------------------------*/