nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
njn | c1b0181 | 2005-06-17 22:19:06 +0000 | [diff] [blame] | 3 | /*--- Linux-specific syscalls, etc. syswrap-linux.c ---*/ |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
njn | b9c427c | 2004-12-01 14:14:42 +0000 | [diff] [blame] | 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 9 | |
sewardj | e4b0bf0 | 2006-06-05 23:21:15 +0000 | [diff] [blame] | 10 | Copyright (C) 2000-2006 Nicholas Nethercote |
njn | 2bc1012 | 2005-05-08 02:10:27 +0000 | [diff] [blame] | 11 | njn@valgrind.org |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 12 | |
| 13 | This program is free software; you can redistribute it and/or |
| 14 | modify it under the terms of the GNU General Public License as |
| 15 | published by the Free Software Foundation; either version 2 of the |
| 16 | License, or (at your option) any later version. |
| 17 | |
| 18 | This program is distributed in the hope that it will be useful, but |
| 19 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 21 | General Public License for more details. |
| 22 | |
| 23 | You should have received a copy of the GNU General Public License |
| 24 | along with this program; if not, write to the Free Software |
| 25 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 26 | 02111-1307, USA. |
| 27 | |
| 28 | The GNU General Public License is contained in the file COPYING. |
| 29 | */ |
| 30 | |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame] | 31 | #include "pub_core_basics.h" |
| 32 | #include "pub_core_threadstate.h" |
sewardj | 55f9d1a | 2005-04-25 11:11:44 +0000 | [diff] [blame] | 33 | #include "pub_core_aspacemgr.h" |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 34 | #include "pub_core_debuginfo.h" // VG_(di_notify_*) |
| 35 | #include "pub_core_transtab.h" // VG_(discard_translations) |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 36 | #include "pub_core_clientstate.h" |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 37 | #include "pub_core_debuglog.h" |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 38 | #include "pub_core_libcbase.h" |
njn | 132bfcc | 2005-06-04 19:16:06 +0000 | [diff] [blame] | 39 | #include "pub_core_libcassert.h" |
njn | eb8896b | 2005-06-04 20:03:55 +0000 | [diff] [blame] | 40 | #include "pub_core_libcfile.h" |
njn | 36a20fa | 2005-06-03 03:08:39 +0000 | [diff] [blame] | 41 | #include "pub_core_libcprint.h" |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 42 | #include "pub_core_libcproc.h" |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 43 | #include "pub_core_libcsignal.h" |
njn | af1d7df | 2005-06-11 01:31:52 +0000 | [diff] [blame] | 44 | #include "pub_core_mallocfree.h" |
njn | 43b9a8a | 2005-05-10 04:37:01 +0000 | [diff] [blame] | 45 | #include "pub_core_tooliface.h" |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 46 | #include "pub_core_options.h" |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame] | 47 | #include "pub_core_scheduler.h" |
njn | cd405ea | 2005-08-31 02:44:31 +0000 | [diff] [blame] | 48 | #include "pub_core_signals.h" |
njn | 9abd608 | 2005-06-17 21:31:45 +0000 | [diff] [blame] | 49 | #include "pub_core_syscall.h" |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 50 | #include "pub_core_syswrap.h" |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 51 | |
| 52 | #include "priv_types_n_macros.h" |
njn | c1b0181 | 2005-06-17 22:19:06 +0000 | [diff] [blame] | 53 | #include "priv_syswrap-generic.h" |
| 54 | #include "priv_syswrap-linux.h" |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 55 | |
sewardj | 4eee476 | 2006-10-14 15:51:32 +0000 | [diff] [blame^] | 56 | #include "pub_core_vkiscnums.h" /* for the __NR_* constants */ |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 57 | |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 58 | // Run a thread from beginning to end and return the thread's |
| 59 | // scheduler-return-code. |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 60 | static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 61 | { |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 62 | VgSchedReturnCode ret; |
| 63 | ThreadId tid = (ThreadId)tidW; |
| 64 | ThreadState* tst = VG_(get_ThreadState)(tid); |
| 65 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 66 | VG_(debugLog)(1, "syswrap-linux", |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 67 | "thread_wrapper(tid=%lld): entry\n", |
tom | 60a4b0b | 2005-10-12 10:45:27 +0000 | [diff] [blame] | 68 | (ULong)tidW); |
| 69 | |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 70 | vg_assert(tst->status == VgTs_Init); |
| 71 | |
| 72 | /* make sure we get the CPU lock before doing anything significant */ |
| 73 | VG_(set_running)(tid); |
| 74 | |
| 75 | if (0) |
| 76 | VG_(printf)("thread tid %d started: stack = %p\n", |
| 77 | tid, &tid); |
| 78 | |
| 79 | VG_TRACK ( post_thread_create, tst->os_state.parent, tid ); |
| 80 | |
| 81 | tst->os_state.lwpid = VG_(gettid)(); |
| 82 | tst->os_state.threadgroup = VG_(getpid)(); |
| 83 | |
| 84 | /* Thread created with all signals blocked; scheduler will set the |
| 85 | appropriate mask */ |
| 86 | |
| 87 | ret = VG_(scheduler)(tid); |
| 88 | |
| 89 | vg_assert(VG_(is_exiting)(tid)); |
| 90 | |
| 91 | vg_assert(tst->status == VgTs_Runnable); |
| 92 | vg_assert(VG_(is_running_thread)(tid)); |
| 93 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 94 | VG_(debugLog)(1, "syswrap-linux", |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 95 | "thread_wrapper(tid=%lld): exit\n", |
njn | 7b85dd5 | 2005-06-12 17:26:29 +0000 | [diff] [blame] | 96 | (ULong)tidW); |
| 97 | |
| 98 | /* Return to caller, still holding the lock. */ |
| 99 | return ret; |
| 100 | } |
| 101 | |
| 102 | |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 103 | /* --------------------------------------------------------------------- |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 104 | clone-related stuff |
| 105 | ------------------------------------------------------------------ */ |
| 106 | |
| 107 | /* Run a thread all the way to the end, then do appropriate exit actions |
| 108 | (this is the last-one-out-turn-off-the-lights bit). */ |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 109 | static void run_a_thread_NORETURN ( Word tidW ) |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 110 | { |
| 111 | ThreadId tid = (ThreadId)tidW; |
| 112 | VgSchedReturnCode src; |
| 113 | Int c; |
| 114 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 115 | VG_(debugLog)(1, "syswrap-linux", |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 116 | "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n", |
| 117 | (ULong)tidW); |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 118 | |
| 119 | /* Run the thread all the way through. */ |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 120 | src = thread_wrapper(tid); |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 121 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 122 | VG_(debugLog)(1, "syswrap-linux", |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 123 | "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n", |
| 124 | (ULong)tidW); |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 125 | |
| 126 | c = VG_(count_living_threads)(); |
| 127 | vg_assert(c >= 1); /* stay sane */ |
| 128 | |
| 129 | if (c == 1) { |
| 130 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 131 | VG_(debugLog)(1, "syswrap-linux", |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 132 | "run_a_thread_NORETURN(tid=%lld): " |
| 133 | "last one standing\n", |
| 134 | (ULong)tidW); |
| 135 | |
| 136 | /* We are the last one standing. Keep hold of the lock and |
| 137 | carry on to show final tool results, then exit the entire system. |
| 138 | Use the continuation pointer set at startup in m_main. */ |
| 139 | ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); |
| 140 | |
| 141 | } else { |
| 142 | |
| 143 | ThreadState *tst; |
| 144 | |
sewardj | d98f68d | 2005-11-09 14:09:14 +0000 | [diff] [blame] | 145 | VG_(debugLog)(1, "syswrap-linux", |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 146 | "run_a_thread_NORETURN(tid=%lld): " |
| 147 | "not last one standing\n", |
| 148 | (ULong)tidW); |
| 149 | |
| 150 | /* OK, thread is dead, but others still exist. Just exit. */ |
| 151 | tst = VG_(get_ThreadState)(tid); |
| 152 | |
| 153 | /* This releases the run lock */ |
| 154 | VG_(exit_thread)(tid); |
| 155 | vg_assert(tst->status == VgTs_Zombie); |
| 156 | |
| 157 | /* We have to use this sequence to terminate the thread to |
| 158 | prevent a subtle race. If VG_(exit_thread)() had left the |
| 159 | ThreadState as Empty, then it could have been reallocated, |
| 160 | reusing the stack while we're doing these last cleanups. |
| 161 | Instead, VG_(exit_thread) leaves it as Zombie to prevent |
| 162 | reallocation. We need to make sure we don't touch the stack |
| 163 | between marking it Empty and exiting. Hence the |
| 164 | assembler. */ |
| 165 | #if defined(VGP_x86_linux) |
| 166 | asm volatile ( |
| 167 | "movl %1, %0\n" /* set tst->status = VgTs_Empty */ |
| 168 | "movl %2, %%eax\n" /* set %eax = __NR_exit */ |
| 169 | "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */ |
| 170 | "int $0x80\n" /* exit(tst->os_state.exitcode) */ |
| 171 | : "=m" (tst->status) |
| 172 | : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); |
| 173 | #elif defined(VGP_amd64_linux) |
| 174 | asm volatile ( |
| 175 | "movl %1, %0\n" /* set tst->status = VgTs_Empty */ |
| 176 | "movq %2, %%rax\n" /* set %rax = __NR_exit */ |
| 177 | "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */ |
| 178 | "syscall\n" /* exit(tst->os_state.exitcode) */ |
| 179 | : "=m" (tst->status) |
| 180 | : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); |
sewardj | 2c48c7b | 2005-11-29 13:05:56 +0000 | [diff] [blame] | 181 | #elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 182 | { UInt vgts_empty = (UInt)VgTs_Empty; |
| 183 | asm volatile ( |
| 184 | "stw %1,%0\n\t" /* set tst->status = VgTs_Empty */ |
| 185 | "li 0,%2\n\t" /* set r0 = __NR_exit */ |
| 186 | "lwz 3,%3\n\t" /* set r3 = tst->os_state.exitcode */ |
| 187 | "sc\n\t" /* exit(tst->os_state.exitcode) */ |
| 188 | : "=m" (tst->status) |
| 189 | : "r" (vgts_empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); |
| 190 | } |
| 191 | #else |
| 192 | # error Unknown platform |
| 193 | #endif |
| 194 | |
| 195 | VG_(core_panic)("Thread exit failed?\n"); |
| 196 | } |
| 197 | |
| 198 | /*NOTREACHED*/ |
| 199 | vg_assert(0); |
| 200 | } |
| 201 | |
njn | ffd9c1d | 2005-11-10 04:02:19 +0000 | [diff] [blame] | 202 | Word ML_(start_thread_NORETURN) ( void* arg ) |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 203 | { |
| 204 | ThreadState* tst = (ThreadState*)arg; |
| 205 | ThreadId tid = tst->tid; |
| 206 | |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 207 | run_a_thread_NORETURN ( (Word)tid ); |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 208 | /*NOTREACHED*/ |
| 209 | vg_assert(0); |
| 210 | } |
| 211 | |
| 212 | /* Allocate a stack for this thread, if it doesn't already have one. |
| 213 | They're allocated lazily, and never freed. Returns the initial stack |
| 214 | pointer value to use, or 0 if allocation failed. */ |
| 215 | Addr ML_(allocstack)(ThreadId tid) |
| 216 | { |
| 217 | ThreadState* tst = VG_(get_ThreadState)(tid); |
| 218 | VgStack* stack; |
| 219 | Addr initial_SP; |
| 220 | |
| 221 | /* Either the stack_base and stack_init_SP are both zero (in which |
| 222 | case a stack hasn't been allocated) or they are both non-zero, |
| 223 | in which case it has. */ |
| 224 | |
| 225 | if (tst->os_state.valgrind_stack_base == 0) |
| 226 | vg_assert(tst->os_state.valgrind_stack_init_SP == 0); |
| 227 | |
| 228 | if (tst->os_state.valgrind_stack_base != 0) |
| 229 | vg_assert(tst->os_state.valgrind_stack_init_SP != 0); |
| 230 | |
| 231 | /* If no stack is present, allocate one. */ |
| 232 | |
| 233 | if (tst->os_state.valgrind_stack_base == 0) { |
| 234 | stack = VG_(am_alloc_VgStack)( &initial_SP ); |
| 235 | if (stack) { |
| 236 | tst->os_state.valgrind_stack_base = (Addr)stack; |
| 237 | tst->os_state.valgrind_stack_init_SP = initial_SP; |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | if (0) |
| 242 | VG_(printf)( "stack for tid %d at %p; init_SP=%p\n", |
| 243 | tid, |
| 244 | (void*)tst->os_state.valgrind_stack_base, |
| 245 | (void*)tst->os_state.valgrind_stack_init_SP ); |
| 246 | |
| 247 | return tst->os_state.valgrind_stack_init_SP; |
| 248 | } |
| 249 | |
| 250 | /* Allocate a stack for the main thread, and run it all the way to the |
| 251 | end. Although we already have a working VgStack |
| 252 | (VG_(interim_stack)) it's better to allocate a new one, so that |
| 253 | overflow detection works uniformly for all threads. |
| 254 | */ |
| 255 | void VG_(main_thread_wrapper_NORETURN)(ThreadId tid) |
| 256 | { |
| 257 | Addr sp; |
| 258 | VG_(debugLog)(1, "syswrap-linux", |
| 259 | "entering VG_(main_thread_wrapper_NORETURN)\n"); |
| 260 | |
| 261 | sp = ML_(allocstack)(tid); |
| 262 | |
| 263 | #if defined(VGP_ppc32_linux) |
| 264 | /* make a stack frame */ |
| 265 | sp -= 16; |
| 266 | sp &= ~0xF; |
| 267 | *(UWord *)sp = 0; |
cerion | 2108204 | 2005-12-06 19:07:08 +0000 | [diff] [blame] | 268 | #elif defined(VGP_ppc64_linux) |
| 269 | /* make a stack frame */ |
| 270 | sp -= 112; |
| 271 | sp &= ~((Addr)0xF); |
| 272 | *(UWord *)sp = 0; |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 273 | #endif |
| 274 | |
| 275 | /* If we can't even allocate the first thread's stack, we're hosed. |
| 276 | Give up. */ |
| 277 | vg_assert2(sp != 0, "Cannot allocate main thread's stack."); |
| 278 | |
| 279 | /* shouldn't be any other threads around yet */ |
| 280 | vg_assert( VG_(count_living_threads)() == 1 ); |
| 281 | |
| 282 | ML_(call_on_new_stack_0_1)( |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 283 | (Addr)sp, /* stack */ |
| 284 | 0, /* bogus return address */ |
| 285 | run_a_thread_NORETURN, /* fn to call */ |
| 286 | (Word)tid /* arg to give it */ |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 287 | ); |
| 288 | |
| 289 | /*NOTREACHED*/ |
| 290 | vg_assert(0); |
| 291 | } |
| 292 | |
| 293 | |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 294 | /* Do a clone which is really a fork() */ |
| 295 | SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, |
| 296 | Int* parent_tidptr, Int* child_tidptr ) |
| 297 | { |
| 298 | vki_sigset_t fork_saved_mask; |
| 299 | vki_sigset_t mask; |
| 300 | SysRes res; |
| 301 | |
| 302 | if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM |
| 303 | | VKI_CLONE_FILES | VKI_CLONE_VFORK)) |
| 304 | return VG_(mk_SysRes_Error)( VKI_EINVAL ); |
| 305 | |
| 306 | /* Block all signals during fork, so that we can fix things up in |
| 307 | the child without being interrupted. */ |
| 308 | VG_(sigfillset)(&mask); |
| 309 | VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask); |
| 310 | |
| 311 | /* Since this is the fork() form of clone, we don't need all that |
| 312 | VG_(clone) stuff */ |
sewardj | 2c48c7b | 2005-11-29 13:05:56 +0000 | [diff] [blame] | 313 | #if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 314 | res = VG_(do_syscall5)( __NR_clone, flags, |
| 315 | (UWord)NULL, (UWord)parent_tidptr, |
| 316 | (UWord)NULL, (UWord)child_tidptr ); |
| 317 | #elif defined(VGP_amd64_linux) |
| 318 | /* note that the last two arguments are the opposite way round to x86 and |
| 319 | ppc32 as the amd64 kernel expects the arguments in a different order */ |
| 320 | res = VG_(do_syscall5)( __NR_clone, flags, |
| 321 | (UWord)NULL, (UWord)parent_tidptr, |
| 322 | (UWord)child_tidptr, (UWord)NULL ); |
njn | e148666 | 2005-11-10 02:48:04 +0000 | [diff] [blame] | 323 | #else |
| 324 | # error Unknown platform |
| 325 | #endif |
| 326 | |
| 327 | if (!res.isError && res.val == 0) { |
| 328 | /* child */ |
| 329 | VG_(do_atfork_child)(tid); |
| 330 | |
| 331 | /* restore signal mask */ |
| 332 | VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); |
| 333 | } |
| 334 | else |
| 335 | if (!res.isError && res.val > 0) { |
| 336 | /* parent */ |
| 337 | if (VG_(clo_trace_syscalls)) |
| 338 | VG_(printf)(" clone(fork): process %d created child %d\n", |
| 339 | VG_(getpid)(), res.val); |
| 340 | |
| 341 | /* restore signal mask */ |
| 342 | VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); |
| 343 | } |
| 344 | |
| 345 | return res; |
| 346 | } |
| 347 | |
| 348 | |
njn | a3afdfb | 2005-11-09 04:49:28 +0000 | [diff] [blame] | 349 | /* --------------------------------------------------------------------- |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 350 | PRE/POST wrappers for arch-generic, Linux-specific syscalls |
| 351 | ------------------------------------------------------------------ */ |
| 352 | |
| 353 | // Nb: See the comment above the generic PRE/POST wrappers in |
njn | c1b0181 | 2005-06-17 22:19:06 +0000 | [diff] [blame] | 354 | // m_syswrap/syswrap-generic.c for notes about how they work. |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 355 | |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 356 | #define PRE(name) DEFN_PRE_TEMPLATE(linux, name) |
| 357 | #define POST(name) DEFN_POST_TEMPLATE(linux, name) |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 358 | |
tom | 20d3572 | 2005-07-27 22:57:18 +0000 | [diff] [blame] | 359 | // Combine two 32-bit values into a 64-bit value |
| 360 | #define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) |
| 361 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 362 | /* --------------------------------------------------------------------- |
| 363 | *mount wrappers |
| 364 | ------------------------------------------------------------------ */ |
sewardj | b5f6f51 | 2005-03-10 23:59:00 +0000 | [diff] [blame] | 365 | |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 366 | PRE(sys_mount) |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 367 | { |
| 368 | // Nb: depending on 'flags', the 'type' and 'data' args may be ignored. |
| 369 | // We are conservative and check everything, except the memory pointed to |
| 370 | // by 'data'. |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 371 | *flags |= SfMayBlock; |
sewardj | b5f6f51 | 2005-03-10 23:59:00 +0000 | [diff] [blame] | 372 | PRINT( "sys_mount( %p, %p, %p, %p, %p )" ,ARG1,ARG2,ARG3,ARG4,ARG5); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 373 | PRE_REG_READ5(long, "mount", |
| 374 | char *, source, char *, target, char *, type, |
| 375 | unsigned long, flags, void *, data); |
njn | 22cfccb | 2004-11-27 16:10:23 +0000 | [diff] [blame] | 376 | PRE_MEM_RASCIIZ( "mount(source)", ARG1); |
| 377 | PRE_MEM_RASCIIZ( "mount(target)", ARG2); |
| 378 | PRE_MEM_RASCIIZ( "mount(type)", ARG3); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 379 | } |
| 380 | |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 381 | PRE(sys_oldumount) |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 382 | { |
njn | 22cfccb | 2004-11-27 16:10:23 +0000 | [diff] [blame] | 383 | PRINT("sys_oldumount( %p )", ARG1); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 384 | PRE_REG_READ1(long, "umount", char *, path); |
njn | 22cfccb | 2004-11-27 16:10:23 +0000 | [diff] [blame] | 385 | PRE_MEM_RASCIIZ( "umount(path)", ARG1); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 386 | } |
| 387 | |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 388 | PRE(sys_umount) |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 389 | { |
njn | 4ae4040 | 2005-08-24 13:55:59 +0000 | [diff] [blame] | 390 | PRINT("sys_umount( %p, %d )", ARG1, ARG2); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 391 | PRE_REG_READ2(long, "umount2", char *, path, int, flags); |
njn | 22cfccb | 2004-11-27 16:10:23 +0000 | [diff] [blame] | 392 | PRE_MEM_RASCIIZ( "umount2(path)", ARG1); |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 393 | } |
| 394 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 395 | /* --------------------------------------------------------------------- |
| 396 | 16- and 32-bit uid/gid wrappers |
| 397 | ------------------------------------------------------------------ */ |
sewardj | 696c551 | 2005-06-08 23:38:32 +0000 | [diff] [blame] | 398 | |
| 399 | PRE(sys_setfsuid16) |
| 400 | { |
| 401 | PRINT("sys_setfsuid16 ( %d )", ARG1); |
| 402 | PRE_REG_READ1(long, "setfsuid16", vki_old_uid_t, uid); |
| 403 | } |
| 404 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 405 | PRE(sys_setfsuid) |
| 406 | { |
| 407 | PRINT("sys_setfsuid ( %d )", ARG1); |
| 408 | PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid); |
| 409 | } |
sewardj | 696c551 | 2005-06-08 23:38:32 +0000 | [diff] [blame] | 410 | |
| 411 | PRE(sys_setfsgid16) |
| 412 | { |
| 413 | PRINT("sys_setfsgid16 ( %d )", ARG1); |
| 414 | PRE_REG_READ1(long, "setfsgid16", vki_old_gid_t, gid); |
| 415 | } |
| 416 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 417 | PRE(sys_setfsgid) |
| 418 | { |
| 419 | PRINT("sys_setfsgid ( %d )", ARG1); |
| 420 | PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid); |
| 421 | } |
| 422 | |
| 423 | PRE(sys_setresuid16) |
| 424 | { |
| 425 | PRINT("sys_setresuid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); |
| 426 | PRE_REG_READ3(long, "setresuid16", |
| 427 | vki_old_uid_t, ruid, vki_old_uid_t, euid, vki_old_uid_t, suid); |
| 428 | } |
| 429 | |
| 430 | PRE(sys_setresuid) |
| 431 | { |
| 432 | PRINT("sys_setresuid ( %d, %d, %d )", ARG1, ARG2, ARG3); |
| 433 | PRE_REG_READ3(long, "setresuid", |
| 434 | vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid); |
| 435 | } |
| 436 | |
| 437 | PRE(sys_getresuid16) |
| 438 | { |
| 439 | PRINT("sys_getresuid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); |
| 440 | PRE_REG_READ3(long, "getresuid16", |
| 441 | vki_old_uid_t *, ruid, vki_old_uid_t *, euid, |
| 442 | vki_old_uid_t *, suid); |
| 443 | PRE_MEM_WRITE( "getresuid16(ruid)", ARG1, sizeof(vki_old_uid_t) ); |
| 444 | PRE_MEM_WRITE( "getresuid16(euid)", ARG2, sizeof(vki_old_uid_t) ); |
| 445 | PRE_MEM_WRITE( "getresuid16(suid)", ARG3, sizeof(vki_old_uid_t) ); |
| 446 | } |
| 447 | POST(sys_getresuid16) |
| 448 | { |
| 449 | vg_assert(SUCCESS); |
| 450 | if (RES == 0) { |
| 451 | POST_MEM_WRITE( ARG1, sizeof(vki_old_uid_t) ); |
| 452 | POST_MEM_WRITE( ARG2, sizeof(vki_old_uid_t) ); |
| 453 | POST_MEM_WRITE( ARG3, sizeof(vki_old_uid_t) ); |
| 454 | } |
| 455 | } |
sewardj | 78b50e4 | 2005-06-08 01:47:28 +0000 | [diff] [blame] | 456 | |
| 457 | PRE(sys_getresuid) |
| 458 | { |
| 459 | PRINT("sys_getresuid ( %p, %p, %p )", ARG1,ARG2,ARG3); |
| 460 | PRE_REG_READ3(long, "getresuid", |
| 461 | vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid); |
| 462 | PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) ); |
| 463 | PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) ); |
| 464 | PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) ); |
| 465 | } |
sewardj | 78b50e4 | 2005-06-08 01:47:28 +0000 | [diff] [blame] | 466 | POST(sys_getresuid) |
| 467 | { |
| 468 | vg_assert(SUCCESS); |
| 469 | if (RES == 0) { |
| 470 | POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) ); |
| 471 | POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) ); |
| 472 | POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) ); |
| 473 | } |
| 474 | } |
| 475 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 476 | PRE(sys_setresgid16) |
| 477 | { |
| 478 | PRINT("sys_setresgid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); |
| 479 | PRE_REG_READ3(long, "setresgid16", |
| 480 | vki_old_gid_t, rgid, |
| 481 | vki_old_gid_t, egid, vki_old_gid_t, sgid); |
| 482 | } |
| 483 | |
| 484 | PRE(sys_setresgid) |
| 485 | { |
| 486 | PRINT("sys_setresgid ( %d, %d, %d )", ARG1, ARG2, ARG3); |
| 487 | PRE_REG_READ3(long, "setresgid", |
| 488 | vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid); |
| 489 | } |
| 490 | |
| 491 | PRE(sys_getresgid16) |
| 492 | { |
| 493 | PRINT("sys_getresgid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); |
| 494 | PRE_REG_READ3(long, "getresgid16", |
| 495 | vki_old_gid_t *, rgid, vki_old_gid_t *, egid, |
| 496 | vki_old_gid_t *, sgid); |
| 497 | PRE_MEM_WRITE( "getresgid16(rgid)", ARG1, sizeof(vki_old_gid_t) ); |
| 498 | PRE_MEM_WRITE( "getresgid16(egid)", ARG2, sizeof(vki_old_gid_t) ); |
| 499 | PRE_MEM_WRITE( "getresgid16(sgid)", ARG3, sizeof(vki_old_gid_t) ); |
| 500 | } |
| 501 | POST(sys_getresgid16) |
| 502 | { |
| 503 | vg_assert(SUCCESS); |
| 504 | if (RES == 0) { |
| 505 | POST_MEM_WRITE( ARG1, sizeof(vki_old_gid_t) ); |
| 506 | POST_MEM_WRITE( ARG2, sizeof(vki_old_gid_t) ); |
| 507 | POST_MEM_WRITE( ARG3, sizeof(vki_old_gid_t) ); |
| 508 | } |
| 509 | } |
sewardj | 78b50e4 | 2005-06-08 01:47:28 +0000 | [diff] [blame] | 510 | |
| 511 | PRE(sys_getresgid) |
| 512 | { |
| 513 | PRINT("sys_getresgid ( %p, %p, %p )", ARG1,ARG2,ARG3); |
| 514 | PRE_REG_READ3(long, "getresgid", |
| 515 | vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid); |
| 516 | PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) ); |
| 517 | PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) ); |
| 518 | PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) ); |
| 519 | } |
sewardj | 78b50e4 | 2005-06-08 01:47:28 +0000 | [diff] [blame] | 520 | POST(sys_getresgid) |
| 521 | { |
| 522 | vg_assert(SUCCESS); |
| 523 | if (RES == 0) { |
| 524 | POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) ); |
| 525 | POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) ); |
| 526 | POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) ); |
| 527 | } |
| 528 | } |
| 529 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 530 | /* --------------------------------------------------------------------- |
| 531 | miscellaneous wrappers |
| 532 | ------------------------------------------------------------------ */ |
| 533 | |
| 534 | PRE(sys_exit_group) |
| 535 | { |
| 536 | ThreadId t; |
| 537 | ThreadState* tst; |
| 538 | |
| 539 | PRINT("exit_group( %d )", ARG1); |
| 540 | PRE_REG_READ1(void, "exit_group", int, exit_code); |
| 541 | |
| 542 | tst = VG_(get_ThreadState)(tid); |
| 543 | |
| 544 | /* A little complex; find all the threads with the same threadgroup |
| 545 | as this one (including this one), and mark them to exit */ |
| 546 | for (t = 1; t < VG_N_THREADS; t++) { |
| 547 | if ( /* not alive */ |
| 548 | VG_(threads)[t].status == VgTs_Empty |
| 549 | || |
| 550 | /* not our group */ |
| 551 | VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup |
| 552 | ) |
| 553 | continue; |
| 554 | |
| 555 | VG_(threads)[t].exitreason = VgSrc_ExitSyscall; |
| 556 | VG_(threads)[t].os_state.exitcode = ARG1; |
| 557 | |
| 558 | if (t != tid) |
| 559 | VG_(kill_thread)(t); /* unblock it, if blocked */ |
| 560 | } |
| 561 | |
| 562 | /* We have to claim the syscall already succeeded. */ |
| 563 | SET_STATUS_Success(0); |
| 564 | } |
| 565 | |
| 566 | PRE(sys_llseek) |
| 567 | { |
| 568 | PRINT("sys_llseek ( %d, 0x%x, 0x%x, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5); |
| 569 | PRE_REG_READ5(long, "llseek", |
| 570 | unsigned int, fd, unsigned long, offset_high, |
| 571 | unsigned long, offset_low, vki_loff_t *, result, |
| 572 | unsigned int, whence); |
| 573 | PRE_MEM_WRITE( "llseek(result)", ARG4, sizeof(vki_loff_t)); |
| 574 | } |
| 575 | POST(sys_llseek) |
| 576 | { |
| 577 | vg_assert(SUCCESS); |
| 578 | if (RES == 0) |
| 579 | POST_MEM_WRITE( ARG4, sizeof(vki_loff_t) ); |
| 580 | } |
| 581 | |
| 582 | //zz PRE(sys_adjtimex, 0) |
| 583 | //zz { |
| 584 | //zz struct vki_timex *tx = (struct vki_timex *)ARG1; |
| 585 | //zz PRINT("sys_adjtimex ( %p )", ARG1); |
| 586 | //zz PRE_REG_READ1(long, "adjtimex", struct timex *, buf); |
| 587 | //zz PRE_MEM_READ( "adjtimex(timex->modes)", ARG1, sizeof(tx->modes)); |
| 588 | //zz |
| 589 | #if 0 //zz (avoiding warnings about multi-line comments) |
| 590 | zz #define ADJX(bit,field) \ |
| 591 | zz if (tx->modes & bit) \ |
| 592 | zz PRE_MEM_READ( "adjtimex(timex->"#field")", \ |
| 593 | zz (Addr)&tx->field, sizeof(tx->field)) |
| 594 | #endif |
| 595 | //zz ADJX(ADJ_FREQUENCY, freq); |
| 596 | //zz ADJX(ADJ_MAXERROR, maxerror); |
| 597 | //zz ADJX(ADJ_ESTERROR, esterror); |
| 598 | //zz ADJX(ADJ_STATUS, status); |
| 599 | //zz ADJX(ADJ_TIMECONST, constant); |
| 600 | //zz ADJX(ADJ_TICK, tick); |
| 601 | //zz #undef ADJX |
| 602 | //zz |
| 603 | //zz PRE_MEM_WRITE( "adjtimex(timex)", ARG1, sizeof(struct vki_timex)); |
| 604 | //zz } |
| 605 | //zz |
| 606 | //zz POST(sys_adjtimex) |
| 607 | //zz { |
| 608 | //zz POST_MEM_WRITE( ARG1, sizeof(struct vki_timex) ); |
| 609 | //zz } |
| 610 | |
sewardj | 696c551 | 2005-06-08 23:38:32 +0000 | [diff] [blame] | 611 | PRE(sys_ioperm) |
| 612 | { |
| 613 | PRINT("sys_ioperm ( %d, %d, %d )", ARG1, ARG2, ARG3 ); |
| 614 | PRE_REG_READ3(long, "ioperm", |
| 615 | unsigned long, from, unsigned long, num, int, turn_on); |
| 616 | } |
| 617 | |
| 618 | PRE(sys_syslog) |
| 619 | { |
| 620 | *flags |= SfMayBlock; |
| 621 | PRINT("sys_syslog (%d, %p, %d)", ARG1,ARG2,ARG3); |
| 622 | PRE_REG_READ3(long, "syslog", int, type, char *, bufp, int, len); |
| 623 | switch (ARG1) { |
| 624 | // The kernel uses magic numbers here, rather than named constants, |
| 625 | // therefore so do we. |
| 626 | case 2: case 3: case 4: |
| 627 | PRE_MEM_WRITE( "syslog(bufp)", ARG2, ARG3); |
| 628 | break; |
| 629 | default: |
| 630 | break; |
| 631 | } |
| 632 | } |
sewardj | 696c551 | 2005-06-08 23:38:32 +0000 | [diff] [blame] | 633 | POST(sys_syslog) |
| 634 | { |
| 635 | switch (ARG1) { |
| 636 | case 2: case 3: case 4: |
| 637 | POST_MEM_WRITE( ARG2, ARG3 ); |
| 638 | break; |
| 639 | default: |
| 640 | break; |
| 641 | } |
| 642 | } |
| 643 | |
| 644 | PRE(sys_vhangup) |
| 645 | { |
| 646 | PRINT("sys_vhangup ( )"); |
| 647 | PRE_REG_READ0(long, "vhangup"); |
| 648 | } |
| 649 | |
| 650 | PRE(sys_sysinfo) |
| 651 | { |
| 652 | PRINT("sys_sysinfo ( %p )",ARG1); |
| 653 | PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info); |
| 654 | PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) ); |
| 655 | } |
sewardj | 696c551 | 2005-06-08 23:38:32 +0000 | [diff] [blame] | 656 | POST(sys_sysinfo) |
| 657 | { |
| 658 | POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) ); |
| 659 | } |
| 660 | |
| 661 | PRE(sys_personality) |
| 662 | { |
| 663 | PRINT("sys_personality ( %llu )", (ULong)ARG1); |
| 664 | PRE_REG_READ1(long, "personality", vki_u_long, persona); |
| 665 | } |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 666 | |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 667 | PRE(sys_sysctl) |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 668 | { |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 669 | struct __vki_sysctl_args *args; |
sewardj | f308fd8 | 2005-03-14 19:52:16 +0000 | [diff] [blame] | 670 | PRINT("sys_sysctl ( %p )", ARG1 ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 671 | args = (struct __vki_sysctl_args *)ARG1; |
| 672 | PRE_REG_READ1(long, "sysctl", struct __sysctl_args *, args); |
njn | 22cfccb | 2004-11-27 16:10:23 +0000 | [diff] [blame] | 673 | PRE_MEM_WRITE( "sysctl(args)", ARG1, sizeof(struct __vki_sysctl_args) ); |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 674 | if (!VG_(am_is_valid_for_client)(ARG1, sizeof(struct __vki_sysctl_args), |
| 675 | VKI_PROT_READ)) { |
sewardj | a8d8e23 | 2005-06-07 20:04:56 +0000 | [diff] [blame] | 676 | SET_STATUS_Failure( VKI_EFAULT ); |
sewardj | b5f6f51 | 2005-03-10 23:59:00 +0000 | [diff] [blame] | 677 | return; |
| 678 | } |
| 679 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 680 | PRE_MEM_READ("sysctl(name)", (Addr)args->name, args->nlen * sizeof(*args->name)); |
| 681 | if (args->newval != NULL) |
| 682 | PRE_MEM_READ("sysctl(newval)", (Addr)args->newval, args->newlen); |
| 683 | if (args->oldlenp != NULL) { |
| 684 | PRE_MEM_READ("sysctl(oldlenp)", (Addr)args->oldlenp, sizeof(*args->oldlenp)); |
| 685 | PRE_MEM_WRITE("sysctl(oldval)", (Addr)args->oldval, *args->oldlenp); |
sewardj | b5f6f51 | 2005-03-10 23:59:00 +0000 | [diff] [blame] | 686 | } |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 687 | } |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 688 | POST(sys_sysctl) |
| 689 | { |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 690 | struct __vki_sysctl_args *args; |
| 691 | args = (struct __vki_sysctl_args *)ARG1; |
| 692 | if (args->oldlenp != NULL) { |
| 693 | POST_MEM_WRITE((Addr)args->oldlenp, sizeof(*args->oldlenp)); |
| 694 | POST_MEM_WRITE((Addr)args->oldval, 1 + *args->oldlenp); |
sewardj | b5f6f51 | 2005-03-10 23:59:00 +0000 | [diff] [blame] | 695 | } |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 696 | } |
| 697 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 698 | PRE(sys_prctl) |
| 699 | { |
| 700 | *flags |= SfMayBlock; |
| 701 | PRINT( "prctl ( %d, %d, %d, %d, %d )", ARG1, ARG2, ARG3, ARG4, ARG5 ); |
| 702 | // XXX: too simplistic, often not all args are used |
| 703 | // Nb: can't use "ARG2".."ARG5" here because that's our own macro... |
| 704 | PRE_REG_READ5(long, "prctl", |
| 705 | int, option, unsigned long, arg2, unsigned long, arg3, |
| 706 | unsigned long, arg4, unsigned long, arg5); |
| 707 | // XXX: totally wrong... we need to look at the 'option' arg, and do |
| 708 | // PRE_MEM_READs/PRE_MEM_WRITEs as necessary... |
| 709 | } |
| 710 | |
| 711 | PRE(sys_sendfile) |
| 712 | { |
| 713 | *flags |= SfMayBlock; |
njn | 68e4659 | 2005-08-26 19:42:27 +0000 | [diff] [blame] | 714 | PRINT("sys_sendfile ( %d, %d, %p, %lu )", ARG1,ARG2,ARG3,ARG4); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 715 | PRE_REG_READ4(ssize_t, "sendfile", |
| 716 | int, out_fd, int, in_fd, vki_off_t *, offset, |
| 717 | vki_size_t, count); |
| 718 | if (ARG3 != 0) |
| 719 | PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) ); |
| 720 | } |
| 721 | POST(sys_sendfile) |
| 722 | { |
| 723 | if (ARG3 != 0 ) { |
| 724 | POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) ); |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | PRE(sys_sendfile64) |
| 729 | { |
| 730 | *flags |= SfMayBlock; |
njn | 68e4659 | 2005-08-26 19:42:27 +0000 | [diff] [blame] | 731 | PRINT("sendfile64 ( %d, %d, %p, %lu )",ARG1,ARG2,ARG3,ARG4); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 732 | PRE_REG_READ4(ssize_t, "sendfile64", |
| 733 | int, out_fd, int, in_fd, vki_loff_t *, offset, |
| 734 | vki_size_t, count); |
| 735 | if (ARG3 != 0) |
| 736 | PRE_MEM_WRITE( "sendfile64(offset)", ARG3, sizeof(vki_loff_t) ); |
| 737 | } |
| 738 | POST(sys_sendfile64) |
| 739 | { |
| 740 | if (ARG3 != 0 ) { |
| 741 | POST_MEM_WRITE( ARG3, sizeof(vki_loff_t) ); |
| 742 | } |
| 743 | } |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 744 | |
| 745 | PRE(sys_futex) |
| 746 | { |
| 747 | /* |
| 748 | arg param used by ops |
| 749 | |
| 750 | ARG1 - u32 *futex all |
| 751 | ARG2 - int op |
| 752 | ARG3 - int val WAIT,WAKE,FD,REQUEUE,CMP_REQUEUE |
| 753 | ARG4 - struct timespec *utime WAIT:time* REQUEUE,CMP_REQUEUE:val2 |
| 754 | ARG5 - u32 *uaddr2 REQUEUE,CMP_REQUEUE |
| 755 | ARG6 - int val3 CMP_REQUEUE |
| 756 | */ |
| 757 | PRINT("sys_futex ( %p, %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); |
tom | f26b6bf | 2006-06-07 17:47:51 +0000 | [diff] [blame] | 758 | switch(ARG2) { |
| 759 | case VKI_FUTEX_CMP_REQUEUE: |
| 760 | PRE_REG_READ6(long, "futex", |
| 761 | vki_u32 *, futex, int, op, int, val, |
| 762 | struct timespec *, utime, vki_u32 *, uaddr2, int, val3); |
| 763 | break; |
| 764 | case VKI_FUTEX_REQUEUE: |
| 765 | PRE_REG_READ5(long, "futex", |
| 766 | vki_u32 *, futex, int, op, int, val, |
| 767 | struct timespec *, utime, vki_u32 *, uaddr2); |
| 768 | break; |
| 769 | case VKI_FUTEX_WAIT: |
| 770 | PRE_REG_READ4(long, "futex", |
| 771 | vki_u32 *, futex, int, op, int, val, |
| 772 | struct timespec *, utime); |
| 773 | break; |
| 774 | case VKI_FUTEX_WAKE: |
| 775 | case VKI_FUTEX_FD: |
| 776 | PRE_REG_READ3(long, "futex", |
| 777 | vki_u32 *, futex, int, op, int, val); |
| 778 | break; |
| 779 | default: |
| 780 | PRE_REG_READ2(long, "futex", vki_u32 *, futex, int, op); |
| 781 | break; |
| 782 | } |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 783 | |
| 784 | PRE_MEM_READ( "futex(futex)", ARG1, sizeof(Int) ); |
| 785 | |
| 786 | *flags |= SfMayBlock; |
| 787 | |
| 788 | switch(ARG2) { |
| 789 | case VKI_FUTEX_WAIT: |
| 790 | if (ARG4 != 0) |
| 791 | PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) ); |
| 792 | break; |
| 793 | |
| 794 | case VKI_FUTEX_REQUEUE: |
| 795 | case VKI_FUTEX_CMP_REQUEUE: |
| 796 | PRE_MEM_READ( "futex(futex2)", ARG5, sizeof(Int) ); |
| 797 | break; |
| 798 | |
| 799 | case VKI_FUTEX_WAKE: |
| 800 | case VKI_FUTEX_FD: |
| 801 | /* no additional pointers */ |
| 802 | break; |
| 803 | |
| 804 | default: |
| 805 | SET_STATUS_Failure( VKI_ENOSYS ); // some futex function we don't understand |
| 806 | break; |
| 807 | } |
| 808 | } |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 809 | POST(sys_futex) |
| 810 | { |
| 811 | vg_assert(SUCCESS); |
| 812 | POST_MEM_WRITE( ARG1, sizeof(int) ); |
| 813 | if (ARG2 == VKI_FUTEX_FD) { |
sewardj | 7eb7c58 | 2005-06-23 01:02:53 +0000 | [diff] [blame] | 814 | if (!ML_(fd_allowed)(RES, "futex", tid, True)) { |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 815 | VG_(close)(RES); |
| 816 | SET_STATUS_Failure( VKI_EMFILE ); |
| 817 | } else { |
| 818 | if (VG_(clo_track_fds)) |
njn | f845f8f | 2005-06-23 02:26:47 +0000 | [diff] [blame] | 819 | ML_(record_fd_open_nameless)(tid, RES); |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 820 | } |
| 821 | } |
| 822 | } |
| 823 | |
tom | 05b1f9a | 2006-05-17 14:24:12 +0000 | [diff] [blame] | 824 | PRE(sys_set_robust_list) |
| 825 | { |
| 826 | PRINT("sys_set_robust_list ( %p, %d )", ARG1,ARG2); |
| 827 | PRE_REG_READ2(long, "set_robust_list", |
| 828 | struct vki_robust_list_head *, head, vki_size_t, len); |
| 829 | |
| 830 | /* Just check the robust_list_head structure is readable - don't |
| 831 | try and chase the list as the kernel will only read it when |
| 832 | the thread exits so the current contents is irrelevant. */ |
| 833 | if (ARG1 != 0) |
| 834 | PRE_MEM_READ("set_robust_list(head)", ARG1, ARG2); |
| 835 | } |
| 836 | |
| 837 | PRE(sys_get_robust_list) |
| 838 | { |
| 839 | PRINT("sys_get_robust_list ( %d, %p, %d )", ARG1,ARG2,ARG3); |
| 840 | PRE_REG_READ3(long, "get_robust_list", |
| 841 | int, pid, |
| 842 | struct vki_robust_list_head **, head_ptr, |
| 843 | vki_size_t *, len_ptr); |
| 844 | PRE_MEM_WRITE("get_robust_list(head_ptr)", |
| 845 | ARG2, sizeof(struct vki_robust_list_head *)); |
| 846 | PRE_MEM_WRITE("get_robust_list(len_ptr)", |
| 847 | ARG3, sizeof(struct vki_size_t *)); |
| 848 | } |
| 849 | POST(sys_get_robust_list) |
| 850 | { |
| 851 | POST_MEM_WRITE(ARG2, sizeof(struct vki_robust_list_head *)); |
| 852 | POST_MEM_WRITE(ARG3, sizeof(struct vki_size_t *)); |
| 853 | } |
| 854 | |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 855 | PRE(sys_pselect6) |
| 856 | { |
| 857 | *flags |= SfMayBlock; |
| 858 | PRINT("sys_pselect6 ( %d, %p, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); |
| 859 | PRE_REG_READ6(long, "pselect6", |
| 860 | int, n, vki_fd_set *, readfds, vki_fd_set *, writefds, |
| 861 | vki_fd_set *, exceptfds, struct vki_timeval *, timeout, |
| 862 | void *, sig); |
| 863 | // XXX: this possibly understates how much memory is read. |
| 864 | if (ARG2 != 0) |
| 865 | PRE_MEM_READ( "pselect6(readfds)", |
| 866 | ARG2, ARG1/8 /* __FD_SETSIZE/8 */ ); |
| 867 | if (ARG3 != 0) |
| 868 | PRE_MEM_READ( "pselect6(writefds)", |
| 869 | ARG3, ARG1/8 /* __FD_SETSIZE/8 */ ); |
| 870 | if (ARG4 != 0) |
| 871 | PRE_MEM_READ( "pselect6(exceptfds)", |
| 872 | ARG4, ARG1/8 /* __FD_SETSIZE/8 */ ); |
| 873 | if (ARG5 != 0) |
| 874 | PRE_MEM_READ( "pselect6(timeout)", ARG5, sizeof(struct vki_timeval) ); |
| 875 | if (ARG6 != 0) |
| 876 | PRE_MEM_READ( "pselect6(sig)", ARG6, sizeof(void *)+sizeof(vki_size_t) ); |
| 877 | } |
| 878 | |
| 879 | PRE(sys_ppoll) |
| 880 | { |
| 881 | UInt i; |
| 882 | struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1; |
| 883 | *flags |= SfMayBlock; |
| 884 | PRINT("sys_ppoll ( %p, %d, %p, %p, %llu )\n", ARG1,ARG2,ARG3,ARG4,ARG5); |
| 885 | PRE_REG_READ5(long, "ppoll", |
| 886 | struct vki_pollfd *, ufds, unsigned int, nfds, |
| 887 | struct vki_timespec *, tsp, vki_sigset_t *, sigmask, |
| 888 | vki_size_t, sigsetsize); |
| 889 | |
| 890 | for (i = 0; i < ARG2; i++) { |
| 891 | PRE_MEM_READ( "ppoll(ufds.fd)", |
| 892 | (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) ); |
| 893 | PRE_MEM_READ( "ppoll(ufds.events)", |
| 894 | (Addr)(&ufds[i].events), sizeof(ufds[i].events) ); |
| 895 | PRE_MEM_WRITE( "ppoll(ufd.reventss)", |
| 896 | (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); |
| 897 | } |
| 898 | |
| 899 | if (ARG3) |
| 900 | PRE_MEM_READ( "ppoll(tsp)", ARG3, sizeof(struct vki_timespec) ); |
| 901 | if (ARG4) |
| 902 | PRE_MEM_READ( "ppoll(sigmask)", ARG4, sizeof(vki_sigset_t) ); |
| 903 | } |
| 904 | |
| 905 | POST(sys_ppoll) |
| 906 | { |
| 907 | if (RES > 0) { |
| 908 | UInt i; |
| 909 | struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1; |
| 910 | for (i = 0; i < ARG2; i++) |
| 911 | POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); |
| 912 | } |
| 913 | } |
| 914 | |
njn | 5c69175 | 2005-08-31 03:00:40 +0000 | [diff] [blame] | 915 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 916 | /* --------------------------------------------------------------------- |
| 917 | epoll_* wrappers |
| 918 | ------------------------------------------------------------------ */ |
| 919 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 920 | PRE(sys_epoll_create) |
| 921 | { |
| 922 | PRINT("sys_epoll_create ( %d )", ARG1); |
| 923 | PRE_REG_READ1(long, "epoll_create", int, size); |
| 924 | } |
| 925 | POST(sys_epoll_create) |
| 926 | { |
| 927 | vg_assert(SUCCESS); |
sewardj | 7eb7c58 | 2005-06-23 01:02:53 +0000 | [diff] [blame] | 928 | if (!ML_(fd_allowed)(RES, "epoll_create", tid, True)) { |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 929 | VG_(close)(RES); |
| 930 | SET_STATUS_Failure( VKI_EMFILE ); |
| 931 | } else { |
| 932 | if (VG_(clo_track_fds)) |
njn | f845f8f | 2005-06-23 02:26:47 +0000 | [diff] [blame] | 933 | ML_(record_fd_open_nameless) (tid, RES); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 934 | } |
| 935 | } |
| 936 | |
| 937 | PRE(sys_epoll_ctl) |
| 938 | { |
| 939 | static const HChar* epoll_ctl_s[3] = { |
| 940 | "EPOLL_CTL_ADD", |
| 941 | "EPOLL_CTL_DEL", |
| 942 | "EPOLL_CTL_MOD" |
| 943 | }; |
| 944 | PRINT("sys_epoll_ctl ( %d, %s, %d, %p )", |
| 945 | ARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), ARG3, ARG4); |
| 946 | PRE_REG_READ4(long, "epoll_ctl", |
njn | 40e7358 | 2005-06-24 21:41:28 +0000 | [diff] [blame] | 947 | int, epfd, int, op, int, fd, struct vki_epoll_event *, event); |
| 948 | if (ARG2 != VKI_EPOLL_CTL_DEL) |
| 949 | PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct vki_epoll_event) ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 950 | } |
| 951 | |
| 952 | PRE(sys_epoll_wait) |
| 953 | { |
| 954 | *flags |= SfMayBlock; |
| 955 | PRINT("sys_epoll_wait ( %d, %p, %d, %d )", ARG1, ARG2, ARG3, ARG4); |
| 956 | PRE_REG_READ4(long, "epoll_wait", |
njn | 40e7358 | 2005-06-24 21:41:28 +0000 | [diff] [blame] | 957 | int, epfd, struct vki_epoll_event *, events, |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 958 | int, maxevents, int, timeout); |
njn | 40e7358 | 2005-06-24 21:41:28 +0000 | [diff] [blame] | 959 | PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 960 | } |
| 961 | POST(sys_epoll_wait) |
| 962 | { |
| 963 | vg_assert(SUCCESS); |
| 964 | if (RES > 0) |
njn | 40e7358 | 2005-06-24 21:41:28 +0000 | [diff] [blame] | 965 | POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ; |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 966 | } |
sewardj | 8c25732 | 2005-06-08 01:01:48 +0000 | [diff] [blame] | 967 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 968 | /* --------------------------------------------------------------------- |
| 969 | tid-related wrappers |
| 970 | ------------------------------------------------------------------ */ |
| 971 | |
sewardj | 8c25732 | 2005-06-08 01:01:48 +0000 | [diff] [blame] | 972 | PRE(sys_gettid) |
| 973 | { |
| 974 | PRINT("sys_gettid ()"); |
| 975 | PRE_REG_READ0(long, "gettid"); |
| 976 | } |
| 977 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 978 | PRE(sys_set_tid_address) |
| 979 | { |
| 980 | PRINT("sys_set_tid_address ( %p )", ARG1); |
| 981 | PRE_REG_READ1(long, "set_tid_address", int *, tidptr); |
| 982 | } |
| 983 | |
tom | c8cfca6 | 2006-02-15 10:34:50 +0000 | [diff] [blame] | 984 | PRE(sys_tkill) |
| 985 | { |
| 986 | PRINT("sys_tgkill ( %d, %d )", ARG1,ARG2); |
| 987 | PRE_REG_READ2(long, "tkill", int, tid, int, sig); |
| 988 | if (!ML_(client_signal_OK)(ARG2)) { |
| 989 | SET_STATUS_Failure( VKI_EINVAL ); |
| 990 | return; |
| 991 | } |
| 992 | |
| 993 | /* Check to see if this kill gave us a pending signal */ |
| 994 | *flags |= SfPollAfter; |
| 995 | |
| 996 | if (VG_(clo_trace_signals)) |
| 997 | VG_(message)(Vg_DebugMsg, "tkill: sending signal %d to pid %d", |
| 998 | ARG2, ARG1); |
| 999 | |
| 1000 | /* If we're sending SIGKILL, check to see if the target is one of |
| 1001 | our threads and handle it specially. */ |
| 1002 | if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) { |
| 1003 | SET_STATUS_Success(0); |
| 1004 | return; |
| 1005 | } |
| 1006 | |
| 1007 | /* Ask to handle this syscall via the slow route, since that's the |
| 1008 | only one that sets tst->status to VgTs_WaitSys. If the result |
| 1009 | of doing the syscall is an immediate run of |
| 1010 | async_signalhandler() in m_signals, then we need the thread to |
| 1011 | be properly tidied away. I have the impression the previous |
| 1012 | version of this wrapper worked on x86/amd64 only because the |
| 1013 | kernel did not immediately deliver the async signal to this |
| 1014 | thread (on ppc it did, which broke the assertion re tst->status |
| 1015 | at the top of async_signalhandler()). */ |
| 1016 | *flags |= SfMayBlock; |
| 1017 | } |
| 1018 | POST(sys_tkill) |
| 1019 | { |
| 1020 | if (VG_(clo_trace_signals)) |
| 1021 | VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d", |
| 1022 | ARG2, ARG1); |
| 1023 | } |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1024 | |
| 1025 | PRE(sys_tgkill) |
| 1026 | { |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1027 | PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3); |
| 1028 | PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig); |
sewardj | 7eb7c58 | 2005-06-23 01:02:53 +0000 | [diff] [blame] | 1029 | if (!ML_(client_signal_OK)(ARG3)) { |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1030 | SET_STATUS_Failure( VKI_EINVAL ); |
| 1031 | return; |
| 1032 | } |
| 1033 | |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1034 | /* Check to see if this kill gave us a pending signal */ |
| 1035 | *flags |= SfPollAfter; |
sewardj | d6e91bc | 2005-11-17 14:26:52 +0000 | [diff] [blame] | 1036 | |
| 1037 | if (VG_(clo_trace_signals)) |
| 1038 | VG_(message)(Vg_DebugMsg, "tgkill: sending signal %d to pid %d/%d", |
| 1039 | ARG3, ARG1, ARG2); |
| 1040 | |
| 1041 | /* If we're sending SIGKILL, check to see if the target is one of |
| 1042 | our threads and handle it specially. */ |
| 1043 | if (ARG3 == VKI_SIGKILL && ML_(do_sigkill)(ARG2, ARG1)) { |
| 1044 | SET_STATUS_Success(0); |
| 1045 | return; |
| 1046 | } |
| 1047 | |
| 1048 | /* Ask to handle this syscall via the slow route, since that's the |
| 1049 | only one that sets tst->status to VgTs_WaitSys. If the result |
| 1050 | of doing the syscall is an immediate run of |
| 1051 | async_signalhandler() in m_signals, then we need the thread to |
| 1052 | be properly tidied away. I have the impression the previous |
| 1053 | version of this wrapper worked on x86/amd64 only because the |
| 1054 | kernel did not immediately deliver the async signal to this |
| 1055 | thread (on ppc it did, which broke the assertion re tst->status |
| 1056 | at the top of async_signalhandler()). */ |
| 1057 | *flags |= SfMayBlock; |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1058 | } |
sewardj | bc22cf7 | 2005-06-08 00:02:49 +0000 | [diff] [blame] | 1059 | POST(sys_tgkill) |
| 1060 | { |
| 1061 | if (VG_(clo_trace_signals)) |
| 1062 | VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d", |
| 1063 | ARG3, ARG1, ARG2); |
| 1064 | } |
| 1065 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1066 | /* --------------------------------------------------------------------- |
| 1067 | fadvise64* wrappers |
| 1068 | ------------------------------------------------------------------ */ |
| 1069 | |
tom | 7244083 | 2005-06-15 10:31:10 +0000 | [diff] [blame] | 1070 | PRE(sys_fadvise64) |
| 1071 | { |
tom | 20d3572 | 2005-07-27 22:57:18 +0000 | [diff] [blame] | 1072 | PRINT("sys_fadvise64 ( %d, %lld, %lu, %d )", |
| 1073 | ARG1, LOHI64(ARG2,ARG3), ARG4, ARG5); |
| 1074 | PRE_REG_READ5(long, "fadvise64", |
| 1075 | int, fd, vki_u32, offset_low, vki_u32, offset_high, |
| 1076 | vki_size_t, len, int, advice); |
tom | 7244083 | 2005-06-15 10:31:10 +0000 | [diff] [blame] | 1077 | } |
| 1078 | |
| 1079 | PRE(sys_fadvise64_64) |
| 1080 | { |
tom | 20d3572 | 2005-07-27 22:57:18 +0000 | [diff] [blame] | 1081 | PRINT("sys_fadvise64_64 ( %d, %lld, %lld, %d )", |
| 1082 | ARG1, LOHI64(ARG2,ARG3), LOHI64(ARG4,ARG5), ARG6); |
| 1083 | PRE_REG_READ6(long, "fadvise64_64", |
| 1084 | int, fd, vki_u32, offset_low, vki_u32, offset_high, |
| 1085 | vki_u32, len_low, vki_u32, len_high, int, advice); |
tom | 7244083 | 2005-06-15 10:31:10 +0000 | [diff] [blame] | 1086 | } |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1087 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1088 | /* --------------------------------------------------------------------- |
| 1089 | io_* wrappers |
| 1090 | ------------------------------------------------------------------ */ |
| 1091 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1092 | // Nb: this wrapper has to pad/unpad memory around the syscall itself, |
| 1093 | // and this allows us to control exactly the code that gets run while |
| 1094 | // the padding is in place. |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1095 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1096 | PRE(sys_io_setup) |
| 1097 | { |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1098 | PRINT("sys_io_setup ( %u, %p )", ARG1,ARG2); |
| 1099 | PRE_REG_READ2(long, "io_setup", |
| 1100 | unsigned, nr_events, vki_aio_context_t *, ctxp); |
| 1101 | PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) ); |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1102 | } |
| 1103 | |
| 1104 | POST(sys_io_setup) |
| 1105 | { |
| 1106 | SizeT size; |
| 1107 | struct vki_aio_ring *r; |
| 1108 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1109 | size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + |
| 1110 | ARG1*sizeof(struct vki_io_event)); |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1111 | r = *(struct vki_aio_ring **)ARG2; |
| 1112 | vg_assert(ML_(valid_client_addr)((Addr)r, size, tid, "io_setup")); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1113 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1114 | ML_(notify_aspacem_and_tool_of_mmap)( (Addr)r, size, |
| 1115 | VKI_PROT_READ | VKI_PROT_WRITE, |
| 1116 | VKI_MAP_ANONYMOUS, -1, 0 ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1117 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1118 | POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1119 | } |
| 1120 | |
| 1121 | // Nb: This wrapper is "Special" because we need 'size' to do the unmap |
| 1122 | // after the syscall. We must get 'size' from the aio_ring structure, |
| 1123 | // before the syscall, while the aio_ring structure still exists. (And we |
| 1124 | // know that we must look at the aio_ring structure because Tom inspected the |
| 1125 | // kernel and glibc sources to see what they do, yuk.) |
| 1126 | // |
| 1127 | // XXX This segment can be implicitly unmapped when aio |
| 1128 | // file-descriptors are closed... |
| 1129 | PRE(sys_io_destroy) |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1130 | { |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1131 | struct vki_aio_ring *r; |
| 1132 | SizeT size; |
| 1133 | |
| 1134 | PRINT("sys_io_destroy ( %llu )", (ULong)ARG1); |
| 1135 | PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx); |
| 1136 | |
| 1137 | // If we are going to seg fault (due to a bogus ARG1) do it as late as |
| 1138 | // possible... |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1139 | r = (struct vki_aio_ring *)ARG1; |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1140 | size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + |
| 1141 | r->nr*sizeof(struct vki_io_event)); |
| 1142 | |
| 1143 | SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) ); |
| 1144 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1145 | if (SUCCESS && RES == 0) { |
| 1146 | Bool d = VG_(am_notify_munmap)( ARG1, size ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1147 | VG_TRACK( die_mem_munmap, ARG1, size ); |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 1148 | if (d) |
| 1149 | VG_(discard_translations)( (Addr64)ARG1, (ULong)size, |
| 1150 | "PRE(sys_io_destroy)" ); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1151 | } |
| 1152 | } |
| 1153 | |
| 1154 | PRE(sys_io_getevents) |
| 1155 | { |
| 1156 | *flags |= SfMayBlock; |
| 1157 | PRINT("sys_io_getevents ( %llu, %lld, %lld, %p, %p )", |
| 1158 | (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5); |
| 1159 | PRE_REG_READ5(long, "io_getevents", |
| 1160 | vki_aio_context_t, ctx_id, long, min_nr, long, nr, |
| 1161 | struct io_event *, events, |
| 1162 | struct timespec *, timeout); |
| 1163 | if (ARG3 > 0) |
| 1164 | PRE_MEM_WRITE( "io_getevents(events)", |
| 1165 | ARG4, sizeof(struct vki_io_event)*ARG3 ); |
| 1166 | if (ARG5 != 0) |
| 1167 | PRE_MEM_READ( "io_getevents(timeout)", |
| 1168 | ARG5, sizeof(struct vki_timespec)); |
| 1169 | } |
| 1170 | POST(sys_io_getevents) |
| 1171 | { |
| 1172 | Int i; |
| 1173 | vg_assert(SUCCESS); |
| 1174 | if (RES > 0) { |
| 1175 | POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES ); |
| 1176 | for (i = 0; i < RES; i++) { |
| 1177 | const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i; |
| 1178 | const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj; |
| 1179 | |
| 1180 | switch (cb->aio_lio_opcode) { |
| 1181 | case VKI_IOCB_CMD_PREAD: |
| 1182 | if (vev->result > 0) |
| 1183 | POST_MEM_WRITE( cb->aio_buf, vev->result ); |
| 1184 | break; |
| 1185 | |
| 1186 | case VKI_IOCB_CMD_PWRITE: |
| 1187 | break; |
| 1188 | |
| 1189 | default: |
| 1190 | VG_(message)(Vg_DebugMsg, |
| 1191 | "Warning: unhandled io_getevents opcode: %u\n", |
| 1192 | cb->aio_lio_opcode); |
| 1193 | break; |
| 1194 | } |
| 1195 | } |
| 1196 | } |
| 1197 | } |
| 1198 | |
| 1199 | PRE(sys_io_submit) |
| 1200 | { |
| 1201 | Int i; |
| 1202 | |
njn | 68e4659 | 2005-08-26 19:42:27 +0000 | [diff] [blame] | 1203 | PRINT("sys_io_submit ( %llu, %ld, %p )", (ULong)ARG1,ARG2,ARG3); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1204 | PRE_REG_READ3(long, "io_submit", |
| 1205 | vki_aio_context_t, ctx_id, long, nr, |
| 1206 | struct iocb **, iocbpp); |
| 1207 | PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) ); |
| 1208 | if (ARG3 != 0) { |
| 1209 | for (i = 0; i < ARG2; i++) { |
| 1210 | struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i]; |
| 1211 | PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) ); |
| 1212 | switch (cb->aio_lio_opcode) { |
| 1213 | case VKI_IOCB_CMD_PREAD: |
| 1214 | PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes ); |
| 1215 | break; |
| 1216 | |
| 1217 | case VKI_IOCB_CMD_PWRITE: |
| 1218 | PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes ); |
| 1219 | break; |
| 1220 | |
| 1221 | default: |
| 1222 | VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n", |
| 1223 | cb->aio_lio_opcode); |
| 1224 | break; |
| 1225 | } |
| 1226 | } |
| 1227 | } |
| 1228 | } |
| 1229 | |
| 1230 | PRE(sys_io_cancel) |
| 1231 | { |
tom | a1d5680 | 2005-07-25 15:28:36 +0000 | [diff] [blame] | 1232 | PRINT("sys_io_cancel ( %llu, %p, %p )", (ULong)ARG1,ARG2,ARG3); |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1233 | PRE_REG_READ3(long, "io_cancel", |
| 1234 | vki_aio_context_t, ctx_id, struct iocb *, iocb, |
| 1235 | struct io_event *, result); |
| 1236 | PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) ); |
| 1237 | PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) ); |
| 1238 | } |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 1239 | POST(sys_io_cancel) |
| 1240 | { |
| 1241 | POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) ); |
| 1242 | } |
| 1243 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1244 | /* --------------------------------------------------------------------- |
| 1245 | *_mempolicy wrappers |
| 1246 | ------------------------------------------------------------------ */ |
| 1247 | |
tom | 70a5cb0 | 2005-10-20 17:00:23 +0000 | [diff] [blame] | 1248 | PRE(sys_mbind) |
| 1249 | { |
| 1250 | PRINT("sys_mbind ( %p, %lu, %d, %p, %lu, %u )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); |
| 1251 | PRE_REG_READ6(long, "mbind", |
| 1252 | unsigned long, start, unsigned long, len, |
| 1253 | unsigned long, policy, unsigned long *, nodemask, |
| 1254 | unsigned long, maxnode, unsigned, flags); |
| 1255 | if (ARG1 != 0) |
| 1256 | PRE_MEM_READ( "mbind(nodemask)", ARG4, |
| 1257 | VG_ROUNDUP( ARG5, sizeof(UWord) ) / sizeof(UWord) ); |
| 1258 | } |
| 1259 | |
tom | 2af58f2 | 2005-07-22 15:04:14 +0000 | [diff] [blame] | 1260 | PRE(sys_set_mempolicy) |
| 1261 | { |
tom | a1d5680 | 2005-07-25 15:28:36 +0000 | [diff] [blame] | 1262 | PRINT("sys_set_mempolicy ( %d, %p, %d )", ARG1,ARG2,ARG3); |
tom | 2af58f2 | 2005-07-22 15:04:14 +0000 | [diff] [blame] | 1263 | PRE_REG_READ3(long, "set_mempolicy", |
| 1264 | int, policy, unsigned long *, nodemask, |
| 1265 | unsigned long, maxnode); |
| 1266 | PRE_MEM_READ( "set_mempolicy(nodemask)", ARG2, |
| 1267 | VG_ROUNDUP( ARG3, sizeof(UWord) ) / sizeof(UWord) ); |
| 1268 | } |
| 1269 | |
| 1270 | PRE(sys_get_mempolicy) |
| 1271 | { |
tom | a1d5680 | 2005-07-25 15:28:36 +0000 | [diff] [blame] | 1272 | PRINT("sys_get_mempolicy ( %p, %p, %d, %p, %x )", ARG1,ARG2,ARG3,ARG4,ARG5); |
tom | 2af58f2 | 2005-07-22 15:04:14 +0000 | [diff] [blame] | 1273 | PRE_REG_READ5(long, "get_mempolicy", |
| 1274 | int *, policy, unsigned long *, nodemask, |
| 1275 | unsigned long, maxnode, unsigned long, addr, |
| 1276 | unsigned long, flags); |
| 1277 | if (ARG1 != 0) |
| 1278 | PRE_MEM_WRITE( "get_mempolicy(policy)", ARG1, sizeof(Int) ); |
| 1279 | if (ARG2 != 0) |
| 1280 | PRE_MEM_WRITE( "get_mempolicy(nodemask)", ARG2, |
| 1281 | VG_ROUNDUP( ARG3, sizeof(UWord) * 8 ) / sizeof(UWord) ); |
| 1282 | } |
| 1283 | POST(sys_get_mempolicy) |
| 1284 | { |
| 1285 | if (ARG1 != 0) |
| 1286 | POST_MEM_WRITE( ARG1, sizeof(Int) ); |
| 1287 | if (ARG2 != 0) |
| 1288 | POST_MEM_WRITE( ARG2, VG_ROUNDUP( ARG3, sizeof(UWord) * 8 ) / sizeof(UWord) ); |
| 1289 | } |
| 1290 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1291 | /* --------------------------------------------------------------------- |
| 1292 | inotify_* wrappers |
| 1293 | ------------------------------------------------------------------ */ |
| 1294 | |
tom | 0bcaf2a | 2005-07-25 15:21:41 +0000 | [diff] [blame] | 1295 | PRE(sys_inotify_init) |
| 1296 | { |
| 1297 | PRINT("sys_inotify_init ( )"); |
| 1298 | PRE_REG_READ0(long, "inotify_init"); |
| 1299 | } |
| 1300 | POST(sys_inotify_init) |
| 1301 | { |
| 1302 | vg_assert(SUCCESS); |
| 1303 | if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) { |
| 1304 | VG_(close)(RES); |
| 1305 | SET_STATUS_Failure( VKI_EMFILE ); |
| 1306 | } else { |
| 1307 | if (VG_(clo_track_fds)) |
| 1308 | ML_(record_fd_open_nameless) (tid, RES); |
| 1309 | } |
| 1310 | } |
| 1311 | |
| 1312 | PRE(sys_inotify_add_watch) |
| 1313 | { |
tom | a1d5680 | 2005-07-25 15:28:36 +0000 | [diff] [blame] | 1314 | PRINT( "sys_inotify_add_watch ( %d, %p, %x )", ARG1,ARG2,ARG3); |
tom | 0bcaf2a | 2005-07-25 15:21:41 +0000 | [diff] [blame] | 1315 | PRE_REG_READ3(long, "inotify_add_watch", int, fd, char *, path, int, mask); |
| 1316 | PRE_MEM_RASCIIZ( "inotify_add_watch(path)", ARG2 ); |
| 1317 | } |
| 1318 | |
| 1319 | PRE(sys_inotify_rm_watch) |
| 1320 | { |
tom | a1d5680 | 2005-07-25 15:28:36 +0000 | [diff] [blame] | 1321 | PRINT( "sys_inotify_rm_watch ( %d, %x )", ARG1,ARG2); |
tom | 0bcaf2a | 2005-07-25 15:21:41 +0000 | [diff] [blame] | 1322 | PRE_REG_READ2(long, "inotify_rm_watch", int, fd, int, wd); |
| 1323 | } |
| 1324 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1325 | /* --------------------------------------------------------------------- |
| 1326 | mq_* wrappers |
| 1327 | ------------------------------------------------------------------ */ |
| 1328 | |
njn | 4279a88 | 2005-08-26 03:43:28 +0000 | [diff] [blame] | 1329 | PRE(sys_mq_open) |
| 1330 | { |
| 1331 | PRINT("sys_mq_open( %p(%s), %d, %lld, %p )", |
| 1332 | ARG1,ARG1,ARG2,(ULong)ARG3,ARG4); |
| 1333 | PRE_REG_READ4(long, "mq_open", |
| 1334 | const char *, name, int, oflag, vki_mode_t, mode, |
| 1335 | struct mq_attr *, attr); |
| 1336 | PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 ); |
| 1337 | if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) { |
| 1338 | const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4; |
| 1339 | PRE_MEM_READ( "mq_open(attr->mq_maxmsg)", |
| 1340 | (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); |
| 1341 | PRE_MEM_READ( "mq_open(attr->mq_msgsize)", |
| 1342 | (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); |
| 1343 | } |
| 1344 | } |
njn | 4279a88 | 2005-08-26 03:43:28 +0000 | [diff] [blame] | 1345 | POST(sys_mq_open) |
| 1346 | { |
| 1347 | vg_assert(SUCCESS); |
| 1348 | if (!ML_(fd_allowed)(RES, "mq_open", tid, True)) { |
| 1349 | VG_(close)(RES); |
| 1350 | SET_STATUS_Failure( VKI_EMFILE ); |
| 1351 | } else { |
| 1352 | if (VG_(clo_track_fds)) |
| 1353 | ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); |
| 1354 | } |
| 1355 | } |
| 1356 | |
| 1357 | PRE(sys_mq_unlink) |
| 1358 | { |
| 1359 | PRINT("sys_mq_unlink ( %p(%s) )", ARG1,ARG1); |
| 1360 | PRE_REG_READ1(long, "mq_unlink", const char *, name); |
| 1361 | PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 ); |
| 1362 | } |
| 1363 | |
| 1364 | PRE(sys_mq_timedsend) |
| 1365 | { |
| 1366 | *flags |= SfMayBlock; |
| 1367 | PRINT("sys_mq_timedsend ( %d, %p, %llu, %d, %p )", |
| 1368 | ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); |
| 1369 | PRE_REG_READ5(long, "mq_timedsend", |
| 1370 | vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len, |
| 1371 | unsigned int, msg_prio, const struct timespec *, abs_timeout); |
| 1372 | if (!ML_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) { |
| 1373 | SET_STATUS_Failure( VKI_EBADF ); |
| 1374 | } else { |
| 1375 | PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 ); |
| 1376 | if (ARG5 != 0) |
| 1377 | PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5, |
| 1378 | sizeof(struct vki_timespec) ); |
| 1379 | } |
| 1380 | } |
| 1381 | |
| 1382 | PRE(sys_mq_timedreceive) |
| 1383 | { |
| 1384 | *flags |= SfMayBlock; |
| 1385 | PRINT("sys_mq_timedreceive( %d, %p, %llu, %p, %p )", |
| 1386 | ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); |
| 1387 | PRE_REG_READ5(ssize_t, "mq_timedreceive", |
| 1388 | vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len, |
| 1389 | unsigned int *, msg_prio, |
| 1390 | const struct timespec *, abs_timeout); |
| 1391 | if (!ML_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) { |
| 1392 | SET_STATUS_Failure( VKI_EBADF ); |
| 1393 | } else { |
| 1394 | PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 ); |
| 1395 | if (ARG4 != 0) |
| 1396 | PRE_MEM_WRITE( "mq_timedreceive(msg_prio)", |
| 1397 | ARG4, sizeof(unsigned int) ); |
| 1398 | if (ARG5 != 0) |
| 1399 | PRE_MEM_READ( "mq_timedreceive(abs_timeout)", |
| 1400 | ARG5, sizeof(struct vki_timespec) ); |
| 1401 | } |
| 1402 | } |
njn | 4279a88 | 2005-08-26 03:43:28 +0000 | [diff] [blame] | 1403 | POST(sys_mq_timedreceive) |
| 1404 | { |
| 1405 | POST_MEM_WRITE( ARG2, ARG3 ); |
| 1406 | if (ARG4 != 0) |
| 1407 | POST_MEM_WRITE( ARG4, sizeof(unsigned int) ); |
| 1408 | } |
| 1409 | |
| 1410 | PRE(sys_mq_notify) |
| 1411 | { |
| 1412 | PRINT("sys_mq_notify( %d, %p )", ARG1,ARG2 ); |
| 1413 | PRE_REG_READ2(long, "mq_notify", |
| 1414 | vki_mqd_t, mqdes, const struct sigevent *, notification); |
| 1415 | if (!ML_(fd_allowed)(ARG1, "mq_notify", tid, False)) |
| 1416 | SET_STATUS_Failure( VKI_EBADF ); |
| 1417 | else if (ARG2 != 0) |
| 1418 | PRE_MEM_READ( "mq_notify(notification)", |
| 1419 | ARG2, sizeof(struct vki_sigevent) ); |
| 1420 | } |
| 1421 | |
| 1422 | PRE(sys_mq_getsetattr) |
| 1423 | { |
| 1424 | PRINT("sys_mq_getsetattr( %d, %p, %p )", ARG1,ARG2,ARG3 ); |
| 1425 | PRE_REG_READ3(long, "mq_getsetattr", |
| 1426 | vki_mqd_t, mqdes, const struct mq_attr *, mqstat, |
| 1427 | struct mq_attr *, omqstat); |
| 1428 | if (!ML_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) { |
| 1429 | SET_STATUS_Failure( VKI_EBADF ); |
| 1430 | } else { |
| 1431 | if (ARG2 != 0) { |
| 1432 | const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2; |
| 1433 | PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)", |
| 1434 | (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); |
| 1435 | } |
| 1436 | if (ARG3 != 0) |
| 1437 | PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3, |
| 1438 | sizeof(struct vki_mq_attr) ); |
| 1439 | } |
| 1440 | } |
njn | 4279a88 | 2005-08-26 03:43:28 +0000 | [diff] [blame] | 1441 | POST(sys_mq_getsetattr) |
| 1442 | { |
| 1443 | if (ARG3 != 0) |
| 1444 | POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) ); |
| 1445 | } |
| 1446 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1447 | /* --------------------------------------------------------------------- |
| 1448 | clock_* wrappers |
| 1449 | ------------------------------------------------------------------ */ |
| 1450 | |
njn | 1588bc0 | 2005-08-26 03:49:43 +0000 | [diff] [blame] | 1451 | PRE(sys_clock_settime) |
| 1452 | { |
| 1453 | PRINT("sys_clock_settime( %d, %p )", ARG1,ARG2); |
| 1454 | PRE_REG_READ2(long, "clock_settime", |
| 1455 | vki_clockid_t, clk_id, const struct timespec *, tp); |
| 1456 | PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) ); |
| 1457 | } |
| 1458 | |
| 1459 | PRE(sys_clock_gettime) |
| 1460 | { |
| 1461 | PRINT("sys_clock_gettime( %d, %p )" , ARG1,ARG2); |
| 1462 | PRE_REG_READ2(long, "clock_gettime", |
| 1463 | vki_clockid_t, clk_id, struct timespec *, tp); |
| 1464 | PRE_MEM_WRITE( "clock_gettime(tp)", ARG2, sizeof(struct vki_timespec) ); |
| 1465 | } |
| 1466 | POST(sys_clock_gettime) |
| 1467 | { |
| 1468 | POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); |
| 1469 | } |
| 1470 | |
| 1471 | PRE(sys_clock_getres) |
| 1472 | { |
| 1473 | PRINT("sys_clock_getres( %d, %p )" , ARG1,ARG2); |
| 1474 | // Nb: we can't use "RES" as the param name because that's a macro |
| 1475 | // defined above! |
| 1476 | PRE_REG_READ2(long, "clock_getres", |
| 1477 | vki_clockid_t, clk_id, struct timespec *, res); |
| 1478 | if (ARG2 != 0) |
| 1479 | PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) ); |
| 1480 | } |
| 1481 | POST(sys_clock_getres) |
| 1482 | { |
| 1483 | if (ARG2 != 0) |
| 1484 | POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); |
| 1485 | } |
| 1486 | |
| 1487 | PRE(sys_clock_nanosleep) |
| 1488 | { |
| 1489 | *flags |= SfMayBlock|SfPostOnFail; |
| 1490 | PRINT("sys_clock_nanosleep( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4); |
| 1491 | PRE_REG_READ4(int32_t, "clock_nanosleep", |
| 1492 | vki_clockid_t, clkid, int, flags, |
| 1493 | const struct timespec *, rqtp, struct timespec *, rmtp); |
| 1494 | PRE_MEM_READ( "clock_nanosleep(rqtp)", ARG3, sizeof(struct vki_timespec) ); |
| 1495 | if (ARG4 != 0) |
| 1496 | PRE_MEM_WRITE( "clock_nanosleep(rmtp)", ARG4, sizeof(struct vki_timespec) ); |
| 1497 | } |
| 1498 | POST(sys_clock_nanosleep) |
| 1499 | { |
| 1500 | if (ARG4 != 0 && FAILURE && RES_unchecked == VKI_EINTR) |
| 1501 | POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) ); |
| 1502 | } |
| 1503 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1504 | /* --------------------------------------------------------------------- |
| 1505 | timer_* wrappers |
| 1506 | ------------------------------------------------------------------ */ |
| 1507 | |
njn | 424c056 | 2005-08-26 03:54:30 +0000 | [diff] [blame] | 1508 | PRE(sys_timer_create) |
| 1509 | { |
| 1510 | PRINT("sys_timer_create( %d, %p, %p )", ARG1,ARG2,ARG3); |
| 1511 | PRE_REG_READ3(long, "timer_create", |
| 1512 | vki_clockid_t, clockid, struct sigevent *, evp, |
| 1513 | vki_timer_t *, timerid); |
| 1514 | if (ARG2 != 0) |
| 1515 | PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) ); |
| 1516 | PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) ); |
| 1517 | } |
| 1518 | POST(sys_timer_create) |
| 1519 | { |
| 1520 | POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) ); |
| 1521 | } |
| 1522 | |
| 1523 | PRE(sys_timer_settime) |
| 1524 | { |
| 1525 | PRINT("sys_timer_settime( %lld, %d, %p, %p )", (ULong)ARG1,ARG2,ARG3,ARG4); |
| 1526 | PRE_REG_READ4(long, "timer_settime", |
| 1527 | vki_timer_t, timerid, int, flags, |
| 1528 | const struct itimerspec *, value, |
| 1529 | struct itimerspec *, ovalue); |
| 1530 | PRE_MEM_READ( "timer_settime(value)", ARG3, |
| 1531 | sizeof(struct vki_itimerspec) ); |
| 1532 | if (ARG4 != 0) |
| 1533 | PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4, |
| 1534 | sizeof(struct vki_itimerspec) ); |
| 1535 | } |
| 1536 | POST(sys_timer_settime) |
| 1537 | { |
| 1538 | if (ARG4 != 0) |
| 1539 | POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) ); |
| 1540 | } |
| 1541 | |
| 1542 | PRE(sys_timer_gettime) |
| 1543 | { |
| 1544 | PRINT("sys_timer_gettime( %lld, %p )", (ULong)ARG1,ARG2); |
| 1545 | PRE_REG_READ2(long, "timer_gettime", |
| 1546 | vki_timer_t, timerid, struct itimerspec *, value); |
| 1547 | PRE_MEM_WRITE( "timer_gettime(value)", ARG2, |
| 1548 | sizeof(struct vki_itimerspec)); |
| 1549 | } |
| 1550 | POST(sys_timer_gettime) |
| 1551 | { |
| 1552 | POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) ); |
| 1553 | } |
| 1554 | |
| 1555 | PRE(sys_timer_getoverrun) |
| 1556 | { |
| 1557 | PRINT("sys_timer_getoverrun( %p )", ARG1); |
| 1558 | PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid); |
| 1559 | } |
| 1560 | |
| 1561 | PRE(sys_timer_delete) |
| 1562 | { |
| 1563 | PRINT("sys_timer_delete( %p )", ARG1); |
| 1564 | PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); |
| 1565 | } |
| 1566 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1567 | /* --------------------------------------------------------------------- |
| 1568 | capabilities wrappers |
| 1569 | ------------------------------------------------------------------ */ |
| 1570 | |
njn | 9fe7b12 | 2005-08-26 04:03:04 +0000 | [diff] [blame] | 1571 | PRE(sys_capget) |
| 1572 | { |
| 1573 | PRINT("sys_capget ( %p, %p )", ARG1, ARG2 ); |
| 1574 | PRE_REG_READ2(long, "capget", |
| 1575 | vki_cap_user_header_t, header, vki_cap_user_data_t, data); |
| 1576 | PRE_MEM_READ( "capget(header)", ARG1, |
| 1577 | sizeof(struct __vki_user_cap_header_struct) ); |
| 1578 | PRE_MEM_WRITE( "capget(data)", ARG2, |
| 1579 | sizeof(struct __vki_user_cap_data_struct) ); |
| 1580 | } |
| 1581 | POST(sys_capget) |
| 1582 | { |
| 1583 | if (ARG2 != (Addr)NULL) |
| 1584 | POST_MEM_WRITE( ARG2, sizeof(struct __vki_user_cap_data_struct) ); |
| 1585 | } |
| 1586 | |
| 1587 | PRE(sys_capset) |
| 1588 | { |
| 1589 | PRINT("sys_capset ( %p, %p )", ARG1, ARG2 ); |
| 1590 | PRE_REG_READ2(long, "capset", |
| 1591 | vki_cap_user_header_t, header, |
| 1592 | const vki_cap_user_data_t, data); |
| 1593 | PRE_MEM_READ( "capset(header)", |
| 1594 | ARG1, sizeof(struct __vki_user_cap_header_struct) ); |
| 1595 | PRE_MEM_READ( "capset(data)", |
| 1596 | ARG2, sizeof(struct __vki_user_cap_data_struct) ); |
| 1597 | } |
| 1598 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1599 | /* --------------------------------------------------------------------- |
| 1600 | 16-bit uid/gid/groups wrappers |
| 1601 | ------------------------------------------------------------------ */ |
| 1602 | |
njn | a3b67b7 | 2005-08-26 04:27:54 +0000 | [diff] [blame] | 1603 | PRE(sys_getuid16) |
| 1604 | { |
| 1605 | PRINT("sys_getuid16 ( )"); |
| 1606 | PRE_REG_READ0(long, "getuid16"); |
| 1607 | } |
| 1608 | |
| 1609 | PRE(sys_setuid16) |
| 1610 | { |
| 1611 | PRINT("sys_setuid16 ( %d )", ARG1); |
| 1612 | PRE_REG_READ1(long, "setuid16", vki_old_uid_t, uid); |
| 1613 | } |
| 1614 | |
| 1615 | PRE(sys_getgid16) |
| 1616 | { |
| 1617 | PRINT("sys_getgid16 ( )"); |
| 1618 | PRE_REG_READ0(long, "getgid16"); |
| 1619 | } |
| 1620 | |
| 1621 | PRE(sys_setgid16) |
| 1622 | { |
| 1623 | PRINT("sys_setgid16 ( %d )", ARG1); |
| 1624 | PRE_REG_READ1(long, "setgid16", vki_old_gid_t, gid); |
| 1625 | } |
| 1626 | |
| 1627 | PRE(sys_geteuid16) |
| 1628 | { |
| 1629 | PRINT("sys_geteuid16 ( )"); |
| 1630 | PRE_REG_READ0(long, "geteuid16"); |
| 1631 | } |
| 1632 | |
| 1633 | PRE(sys_getegid16) |
| 1634 | { |
| 1635 | PRINT("sys_getegid16 ( )"); |
| 1636 | PRE_REG_READ0(long, "getegid16"); |
| 1637 | } |
| 1638 | |
| 1639 | PRE(sys_setreuid16) |
| 1640 | { |
| 1641 | PRINT("setreuid16 ( 0x%x, 0x%x )", ARG1, ARG2); |
| 1642 | PRE_REG_READ2(long, "setreuid16", vki_old_uid_t, ruid, vki_old_uid_t, euid); |
| 1643 | } |
| 1644 | |
| 1645 | PRE(sys_setregid16) |
| 1646 | { |
| 1647 | PRINT("sys_setregid16 ( %d, %d )", ARG1, ARG2); |
| 1648 | PRE_REG_READ2(long, "setregid16", vki_old_gid_t, rgid, vki_old_gid_t, egid); |
| 1649 | } |
| 1650 | |
| 1651 | PRE(sys_getgroups16) |
| 1652 | { |
| 1653 | PRINT("sys_getgroups16 ( %d, %p )", ARG1, ARG2); |
| 1654 | PRE_REG_READ2(long, "getgroups16", int, size, vki_old_gid_t *, list); |
| 1655 | if (ARG1 > 0) |
| 1656 | PRE_MEM_WRITE( "getgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); |
| 1657 | } |
| 1658 | POST(sys_getgroups16) |
| 1659 | { |
| 1660 | vg_assert(SUCCESS); |
| 1661 | if (ARG1 > 0 && RES > 0) |
| 1662 | POST_MEM_WRITE( ARG2, RES * sizeof(vki_old_gid_t) ); |
| 1663 | } |
| 1664 | |
| 1665 | PRE(sys_setgroups16) |
| 1666 | { |
| 1667 | PRINT("sys_setgroups16 ( %llu, %p )", (ULong)ARG1, ARG2); |
| 1668 | PRE_REG_READ2(long, "setgroups16", int, size, vki_old_gid_t *, list); |
| 1669 | if (ARG1 > 0) |
| 1670 | PRE_MEM_READ( "setgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); |
| 1671 | } |
| 1672 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1673 | /* --------------------------------------------------------------------- |
| 1674 | *chown16 wrappers |
| 1675 | ------------------------------------------------------------------ */ |
| 1676 | |
njn | efc957c | 2005-08-26 04:36:10 +0000 | [diff] [blame] | 1677 | PRE(sys_chown16) |
| 1678 | { |
| 1679 | PRINT("sys_chown16 ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); |
| 1680 | PRE_REG_READ3(long, "chown16", |
| 1681 | const char *, path, |
| 1682 | vki_old_uid_t, owner, vki_old_gid_t, group); |
| 1683 | PRE_MEM_RASCIIZ( "chown16(path)", ARG1 ); |
| 1684 | } |
| 1685 | |
| 1686 | PRE(sys_fchown16) |
| 1687 | { |
| 1688 | PRINT("sys_fchown16 ( %d, %d, %d )", ARG1,ARG2,ARG3); |
| 1689 | PRE_REG_READ3(long, "fchown16", |
| 1690 | unsigned int, fd, vki_old_uid_t, owner, vki_old_gid_t, group); |
| 1691 | } |
| 1692 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1693 | /* --------------------------------------------------------------------- |
| 1694 | *xattr wrappers |
| 1695 | ------------------------------------------------------------------ */ |
| 1696 | |
njn | 65ccc50 | 2005-08-30 01:53:54 +0000 | [diff] [blame] | 1697 | PRE(sys_setxattr) |
| 1698 | { |
| 1699 | *flags |= SfMayBlock; |
| 1700 | PRINT("sys_setxattr ( %p, %p, %p, %llu, %d )", |
| 1701 | ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); |
| 1702 | PRE_REG_READ5(long, "setxattr", |
| 1703 | char *, path, char *, name, |
| 1704 | void *, value, vki_size_t, size, int, flags); |
| 1705 | PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 ); |
| 1706 | PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 ); |
| 1707 | PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 ); |
| 1708 | } |
| 1709 | |
| 1710 | PRE(sys_lsetxattr) |
| 1711 | { |
| 1712 | *flags |= SfMayBlock; |
| 1713 | PRINT("sys_lsetxattr ( %p, %p, %p, %llu, %d )", |
| 1714 | ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); |
| 1715 | PRE_REG_READ5(long, "lsetxattr", |
| 1716 | char *, path, char *, name, |
| 1717 | void *, value, vki_size_t, size, int, flags); |
| 1718 | PRE_MEM_RASCIIZ( "lsetxattr(path)", ARG1 ); |
| 1719 | PRE_MEM_RASCIIZ( "lsetxattr(name)", ARG2 ); |
| 1720 | PRE_MEM_READ( "lsetxattr(value)", ARG3, ARG4 ); |
| 1721 | } |
| 1722 | |
| 1723 | PRE(sys_fsetxattr) |
| 1724 | { |
| 1725 | *flags |= SfMayBlock; |
| 1726 | PRINT("sys_fsetxattr ( %d, %p, %p, %llu, %d )", |
| 1727 | ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); |
| 1728 | PRE_REG_READ5(long, "fsetxattr", |
| 1729 | int, fd, char *, name, void *, value, |
| 1730 | vki_size_t, size, int, flags); |
| 1731 | PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 ); |
| 1732 | PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 ); |
| 1733 | } |
| 1734 | |
| 1735 | PRE(sys_getxattr) |
| 1736 | { |
| 1737 | *flags |= SfMayBlock; |
| 1738 | PRINT("sys_getxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4); |
| 1739 | PRE_REG_READ4(ssize_t, "getxattr", |
| 1740 | char *, path, char *, name, void *, value, vki_size_t, size); |
| 1741 | PRE_MEM_RASCIIZ( "getxattr(path)", ARG1 ); |
| 1742 | PRE_MEM_RASCIIZ( "getxattr(name)", ARG2 ); |
| 1743 | PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4 ); |
| 1744 | } |
| 1745 | POST(sys_getxattr) |
| 1746 | { |
| 1747 | vg_assert(SUCCESS); |
| 1748 | if (RES > 0 && ARG3 != (Addr)NULL) { |
| 1749 | POST_MEM_WRITE( ARG3, RES ); |
| 1750 | } |
| 1751 | } |
| 1752 | |
| 1753 | PRE(sys_lgetxattr) |
| 1754 | { |
| 1755 | *flags |= SfMayBlock; |
| 1756 | PRINT("sys_lgetxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4); |
| 1757 | PRE_REG_READ4(ssize_t, "lgetxattr", |
| 1758 | char *, path, char *, name, void *, value, vki_size_t, size); |
| 1759 | PRE_MEM_RASCIIZ( "lgetxattr(path)", ARG1 ); |
| 1760 | PRE_MEM_RASCIIZ( "lgetxattr(name)", ARG2 ); |
| 1761 | PRE_MEM_WRITE( "lgetxattr(value)", ARG3, ARG4 ); |
| 1762 | } |
| 1763 | POST(sys_lgetxattr) |
| 1764 | { |
| 1765 | vg_assert(SUCCESS); |
| 1766 | if (RES > 0 && ARG3 != (Addr)NULL) { |
| 1767 | POST_MEM_WRITE( ARG3, RES ); |
| 1768 | } |
| 1769 | } |
| 1770 | |
| 1771 | PRE(sys_fgetxattr) |
| 1772 | { |
| 1773 | *flags |= SfMayBlock; |
| 1774 | PRINT("sys_fgetxattr ( %d, %p, %p, %llu )", ARG1, ARG2, ARG3, (ULong)ARG4); |
| 1775 | PRE_REG_READ4(ssize_t, "fgetxattr", |
| 1776 | int, fd, char *, name, void *, value, vki_size_t, size); |
| 1777 | PRE_MEM_RASCIIZ( "fgetxattr(name)", ARG2 ); |
| 1778 | PRE_MEM_WRITE( "fgetxattr(value)", ARG3, ARG4 ); |
| 1779 | } |
| 1780 | POST(sys_fgetxattr) |
| 1781 | { |
| 1782 | if (RES > 0 && ARG3 != (Addr)NULL) |
| 1783 | POST_MEM_WRITE( ARG3, RES ); |
| 1784 | } |
| 1785 | |
| 1786 | PRE(sys_listxattr) |
| 1787 | { |
| 1788 | *flags |= SfMayBlock; |
| 1789 | PRINT("sys_listxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); |
| 1790 | PRE_REG_READ3(ssize_t, "listxattr", |
| 1791 | char *, path, char *, list, vki_size_t, size); |
| 1792 | PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 ); |
| 1793 | PRE_MEM_WRITE( "listxattr(list)", ARG2, ARG3 ); |
| 1794 | } |
| 1795 | POST(sys_listxattr) |
| 1796 | { |
| 1797 | if (RES > 0 && ARG2 != (Addr)NULL) |
| 1798 | POST_MEM_WRITE( ARG2, RES ); |
| 1799 | } |
| 1800 | |
| 1801 | PRE(sys_llistxattr) |
| 1802 | { |
| 1803 | *flags |= SfMayBlock; |
| 1804 | PRINT("sys_llistxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); |
| 1805 | PRE_REG_READ3(ssize_t, "llistxattr", |
| 1806 | char *, path, char *, list, vki_size_t, size); |
| 1807 | PRE_MEM_RASCIIZ( "llistxattr(path)", ARG1 ); |
| 1808 | PRE_MEM_WRITE( "llistxattr(list)", ARG2, ARG3 ); |
| 1809 | } |
| 1810 | POST(sys_llistxattr) |
| 1811 | { |
| 1812 | if (RES > 0 && ARG2 != (Addr)NULL) |
| 1813 | POST_MEM_WRITE( ARG2, RES ); |
| 1814 | } |
| 1815 | |
| 1816 | PRE(sys_flistxattr) |
| 1817 | { |
| 1818 | *flags |= SfMayBlock; |
| 1819 | PRINT("sys_flistxattr ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3); |
| 1820 | PRE_REG_READ3(ssize_t, "flistxattr", |
| 1821 | int, fd, char *, list, vki_size_t, size); |
| 1822 | PRE_MEM_WRITE( "flistxattr(list)", ARG2, ARG3 ); |
| 1823 | } |
| 1824 | POST(sys_flistxattr) |
| 1825 | { |
| 1826 | if (RES > 0 && ARG2 != (Addr)NULL) |
| 1827 | POST_MEM_WRITE( ARG2, RES ); |
| 1828 | } |
| 1829 | |
| 1830 | PRE(sys_removexattr) |
| 1831 | { |
| 1832 | *flags |= SfMayBlock; |
| 1833 | PRINT("sys_removexattr ( %p, %p )", ARG1, ARG2); |
| 1834 | PRE_REG_READ2(long, "removexattr", char *, path, char *, name); |
| 1835 | PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 ); |
| 1836 | PRE_MEM_RASCIIZ( "removexattr(name)", ARG2 ); |
| 1837 | } |
| 1838 | |
| 1839 | PRE(sys_lremovexattr) |
| 1840 | { |
| 1841 | *flags |= SfMayBlock; |
| 1842 | PRINT("sys_lremovexattr ( %p, %p )", ARG1, ARG2); |
| 1843 | PRE_REG_READ2(long, "lremovexattr", char *, path, char *, name); |
| 1844 | PRE_MEM_RASCIIZ( "lremovexattr(path)", ARG1 ); |
| 1845 | PRE_MEM_RASCIIZ( "lremovexattr(name)", ARG2 ); |
| 1846 | } |
| 1847 | |
| 1848 | PRE(sys_fremovexattr) |
| 1849 | { |
| 1850 | *flags |= SfMayBlock; |
| 1851 | PRINT("sys_fremovexattr ( %d, %p )", ARG1, ARG2); |
| 1852 | PRE_REG_READ2(long, "fremovexattr", int, fd, char *, name); |
| 1853 | PRE_MEM_RASCIIZ( "fremovexattr(name)", ARG2 ); |
| 1854 | } |
| 1855 | |
njn | 7397548 | 2005-08-30 02:45:44 +0000 | [diff] [blame] | 1856 | /* --------------------------------------------------------------------- |
| 1857 | sched_* wrappers |
| 1858 | ------------------------------------------------------------------ */ |
| 1859 | |
njn | b2480c9 | 2005-08-30 02:17:23 +0000 | [diff] [blame] | 1860 | PRE(sys_sched_setparam) |
| 1861 | { |
| 1862 | PRINT("sched_setparam ( %d, %p )", ARG1, ARG2 ); |
| 1863 | PRE_REG_READ2(long, "sched_setparam", |
| 1864 | vki_pid_t, pid, struct sched_param *, p); |
| 1865 | PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) ); |
| 1866 | } |
| 1867 | POST(sys_sched_setparam) |
| 1868 | { |
| 1869 | POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); |
| 1870 | } |
| 1871 | |
| 1872 | PRE(sys_sched_getparam) |
| 1873 | { |
| 1874 | PRINT("sched_getparam ( %d, %p )", ARG1, ARG2 ); |
| 1875 | PRE_REG_READ2(long, "sched_getparam", |
| 1876 | vki_pid_t, pid, struct sched_param *, p); |
| 1877 | PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) ); |
| 1878 | } |
| 1879 | POST(sys_sched_getparam) |
| 1880 | { |
| 1881 | POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); |
| 1882 | } |
| 1883 | |
| 1884 | PRE(sys_sched_getscheduler) |
| 1885 | { |
| 1886 | PRINT("sys_sched_getscheduler ( %d )", ARG1); |
| 1887 | PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid); |
| 1888 | } |
| 1889 | |
| 1890 | PRE(sys_sched_setscheduler) |
| 1891 | { |
| 1892 | PRINT("sys_sched_setscheduler ( %d, %d, %p )", ARG1,ARG2,ARG3); |
| 1893 | PRE_REG_READ3(long, "sched_setscheduler", |
| 1894 | vki_pid_t, pid, int, policy, struct sched_param *, p); |
| 1895 | if (ARG3 != 0) |
| 1896 | PRE_MEM_READ( "sched_setscheduler(p)", |
| 1897 | ARG3, sizeof(struct vki_sched_param)); |
| 1898 | } |
| 1899 | |
| 1900 | PRE(sys_sched_yield) |
| 1901 | { |
| 1902 | *flags |= SfMayBlock; |
| 1903 | PRINT("sched_yield()"); |
| 1904 | PRE_REG_READ0(long, "sys_sched_yield"); |
| 1905 | } |
| 1906 | |
| 1907 | PRE(sys_sched_get_priority_max) |
| 1908 | { |
| 1909 | PRINT("sched_get_priority_max ( %d )", ARG1); |
| 1910 | PRE_REG_READ1(long, "sched_get_priority_max", int, policy); |
| 1911 | } |
| 1912 | |
| 1913 | PRE(sys_sched_get_priority_min) |
| 1914 | { |
| 1915 | PRINT("sched_get_priority_min ( %d )", ARG1); |
| 1916 | PRE_REG_READ1(long, "sched_get_priority_min", int, policy); |
| 1917 | } |
| 1918 | |
| 1919 | PRE(sys_sched_setaffinity) |
| 1920 | { |
| 1921 | PRINT("sched_setaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); |
| 1922 | PRE_REG_READ3(long, "sched_setaffinity", |
| 1923 | vki_pid_t, pid, unsigned int, len, unsigned long *, mask); |
| 1924 | PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2); |
| 1925 | } |
| 1926 | |
| 1927 | PRE(sys_sched_getaffinity) |
| 1928 | { |
| 1929 | PRINT("sched_getaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); |
| 1930 | PRE_REG_READ3(long, "sched_getaffinity", |
| 1931 | vki_pid_t, pid, unsigned int, len, unsigned long *, mask); |
| 1932 | PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2); |
| 1933 | } |
| 1934 | POST(sys_sched_getaffinity) |
| 1935 | { |
| 1936 | POST_MEM_WRITE(ARG3, ARG2); |
| 1937 | } |
| 1938 | |
njn | cd405ea | 2005-08-31 02:44:31 +0000 | [diff] [blame] | 1939 | /* --------------------------------------------------------------------- |
| 1940 | miscellaneous wrappers |
| 1941 | ------------------------------------------------------------------ */ |
| 1942 | |
| 1943 | PRE(sys_munlockall) |
| 1944 | { |
| 1945 | *flags |= SfMayBlock; |
| 1946 | PRINT("sys_munlockall ( )"); |
| 1947 | PRE_REG_READ0(long, "munlockall"); |
| 1948 | } |
| 1949 | |
njn | f4ef182 | 2005-09-24 19:42:41 +0000 | [diff] [blame] | 1950 | // This has different signatures for different platforms. |
| 1951 | // |
| 1952 | // x86: int sys_pipe(unsigned long __user *fildes); |
| 1953 | // AMD64: long sys_pipe(int *fildes); |
| 1954 | // ppc32: int sys_pipe(int __user *fildes); |
| 1955 | // ppc64: int sys_pipe(int __user *fildes); |
| 1956 | // |
| 1957 | // The type of the argument is most important, and it is an array of 32 bit |
| 1958 | // values in all cases. (The return type differs across platforms, but it |
| 1959 | // is not used.) So we use 'int' as its type. This fixed bug #113230 which |
| 1960 | // was caused by using an array of 'unsigned long's, which didn't work on |
| 1961 | // AMD64. |
njn | cd405ea | 2005-08-31 02:44:31 +0000 | [diff] [blame] | 1962 | PRE(sys_pipe) |
| 1963 | { |
| 1964 | PRINT("sys_pipe ( %p )", ARG1); |
njn | f4ef182 | 2005-09-24 19:42:41 +0000 | [diff] [blame] | 1965 | PRE_REG_READ1(int, "pipe", int *, filedes); |
| 1966 | PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) ); |
njn | cd405ea | 2005-08-31 02:44:31 +0000 | [diff] [blame] | 1967 | } |
| 1968 | POST(sys_pipe) |
| 1969 | { |
| 1970 | Int *p = (Int *)ARG1; |
| 1971 | |
| 1972 | if (!ML_(fd_allowed)(p[0], "pipe", tid, True) || |
| 1973 | !ML_(fd_allowed)(p[1], "pipe", tid, True)) { |
| 1974 | VG_(close)(p[0]); |
| 1975 | VG_(close)(p[1]); |
| 1976 | SET_STATUS_Failure( VKI_EMFILE ); |
| 1977 | } else { |
| 1978 | POST_MEM_WRITE( ARG1, 2*sizeof(int) ); |
| 1979 | if (VG_(clo_track_fds)) { |
| 1980 | ML_(record_fd_open_nameless)(tid, p[0]); |
| 1981 | ML_(record_fd_open_nameless)(tid, p[1]); |
| 1982 | } |
| 1983 | } |
| 1984 | } |
| 1985 | |
| 1986 | PRE(sys_quotactl) |
| 1987 | { |
| 1988 | PRINT("sys_quotactl (0x%x, %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3, ARG4); |
| 1989 | PRE_REG_READ4(long, "quotactl", |
| 1990 | unsigned int, cmd, const char *, special, vki_qid_t, id, |
| 1991 | void *, addr); |
| 1992 | PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 ); |
| 1993 | } |
| 1994 | |
| 1995 | PRE(sys_waitid) |
| 1996 | { |
| 1997 | *flags |= SfMayBlock; |
| 1998 | PRINT("sys_waitid( %d, %d, %p, %d, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); |
| 1999 | PRE_REG_READ5(int32_t, "sys_waitid", |
| 2000 | int, which, vki_pid_t, pid, struct vki_siginfo *, infop, |
| 2001 | int, options, struct vki_rusage *, ru); |
| 2002 | PRE_MEM_WRITE( "waitid(infop)", ARG3, sizeof(struct vki_siginfo) ); |
| 2003 | if (ARG5 != 0) |
| 2004 | PRE_MEM_WRITE( "waitid(ru)", ARG5, sizeof(struct vki_rusage) ); |
| 2005 | } |
| 2006 | POST(sys_waitid) |
| 2007 | { |
| 2008 | POST_MEM_WRITE( ARG3, sizeof(struct vki_siginfo) ); |
| 2009 | if (ARG5 != 0) |
| 2010 | POST_MEM_WRITE( ARG5, sizeof(struct vki_rusage) ); |
| 2011 | } |
| 2012 | |
| 2013 | /* --------------------------------------------------------------------- |
| 2014 | utime wrapper |
| 2015 | ------------------------------------------------------------------ */ |
| 2016 | |
| 2017 | PRE(sys_utime) |
| 2018 | { |
| 2019 | *flags |= SfMayBlock; |
| 2020 | PRINT("sys_utime ( %p, %p )", ARG1,ARG2); |
| 2021 | PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf); |
| 2022 | PRE_MEM_RASCIIZ( "utime(filename)", ARG1 ); |
| 2023 | if (ARG2 != 0) |
| 2024 | PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) ); |
| 2025 | } |
| 2026 | |
| 2027 | /* --------------------------------------------------------------------- |
| 2028 | lseek wrapper |
| 2029 | ------------------------------------------------------------------ */ |
| 2030 | |
| 2031 | PRE(sys_lseek) |
| 2032 | { |
| 2033 | PRINT("sys_lseek ( %d, %d, %d )", ARG1,ARG2,ARG3); |
| 2034 | PRE_REG_READ3(vki_off_t, "lseek", |
| 2035 | unsigned int, fd, vki_off_t, offset, unsigned int, whence); |
| 2036 | } |
| 2037 | |
| 2038 | /* --------------------------------------------------------------------- |
| 2039 | sig* wrappers |
| 2040 | ------------------------------------------------------------------ */ |
| 2041 | |
| 2042 | PRE(sys_sigpending) |
| 2043 | { |
| 2044 | PRINT( "sys_sigpending ( %p )", ARG1 ); |
| 2045 | PRE_REG_READ1(long, "sigpending", vki_old_sigset_t *, set); |
| 2046 | PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_old_sigset_t)); |
| 2047 | } |
| 2048 | POST(sys_sigpending) |
| 2049 | { |
| 2050 | POST_MEM_WRITE( ARG1, sizeof(vki_old_sigset_t) ) ; |
| 2051 | } |
| 2052 | |
| 2053 | // This syscall is not used on amd64/Linux -- it only provides |
| 2054 | // sys_rt_sigprocmask, which uses sigset_t rather than old_sigset_t. |
| 2055 | // This wrapper is only suitable for 32-bit architectures. |
| 2056 | // (XXX: so how is it that PRE(sys_sigpending) above doesn't need |
| 2057 | // conditional compilation like this?) |
| 2058 | #if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) |
| 2059 | PRE(sys_sigprocmask) |
| 2060 | { |
| 2061 | vki_old_sigset_t* set; |
| 2062 | vki_old_sigset_t* oldset; |
| 2063 | vki_sigset_t bigger_set; |
| 2064 | vki_sigset_t bigger_oldset; |
| 2065 | |
| 2066 | PRINT("sys_sigprocmask ( %d, %p, %p )",ARG1,ARG2,ARG3); |
| 2067 | PRE_REG_READ3(long, "sigprocmask", |
| 2068 | int, how, vki_old_sigset_t *, set, vki_old_sigset_t *, oldset); |
| 2069 | if (ARG2 != 0) |
| 2070 | PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_old_sigset_t)); |
| 2071 | if (ARG3 != 0) |
| 2072 | PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_old_sigset_t)); |
| 2073 | |
| 2074 | // Nb: We must convert the smaller vki_old_sigset_t params into bigger |
| 2075 | // vki_sigset_t params. |
| 2076 | set = (vki_old_sigset_t*)ARG2; |
| 2077 | oldset = (vki_old_sigset_t*)ARG3; |
| 2078 | |
| 2079 | VG_(memset)(&bigger_set, 0, sizeof(vki_sigset_t)); |
| 2080 | VG_(memset)(&bigger_oldset, 0, sizeof(vki_sigset_t)); |
| 2081 | if (set) |
| 2082 | bigger_set.sig[0] = *(vki_old_sigset_t*)set; |
| 2083 | |
| 2084 | SET_STATUS_from_SysRes( |
| 2085 | VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, |
| 2086 | set ? &bigger_set : NULL, |
| 2087 | oldset ? &bigger_oldset : NULL) |
| 2088 | ); |
| 2089 | |
| 2090 | if (oldset) |
| 2091 | *oldset = bigger_oldset.sig[0]; |
| 2092 | |
| 2093 | if (SUCCESS) |
| 2094 | *flags |= SfPollAfter; |
| 2095 | } |
| 2096 | POST(sys_sigprocmask) |
| 2097 | { |
| 2098 | vg_assert(SUCCESS); |
| 2099 | if (RES == 0 && ARG3 != 0) |
| 2100 | POST_MEM_WRITE( ARG3, sizeof(vki_old_sigset_t)); |
| 2101 | } |
| 2102 | #endif |
| 2103 | |
| 2104 | /* --------------------------------------------------------------------- |
| 2105 | rt_sig* wrappers |
| 2106 | ------------------------------------------------------------------ */ |
| 2107 | |
| 2108 | PRE(sys_rt_sigaction) |
| 2109 | { |
| 2110 | PRINT("sys_rt_sigaction ( %d, %p, %p, %d )", ARG1,ARG2,ARG3,ARG4); |
| 2111 | PRE_REG_READ4(long, "rt_sigaction", |
| 2112 | int, signum, const struct sigaction *, act, |
| 2113 | struct sigaction *, oldact, vki_size_t, sigsetsize); |
| 2114 | |
| 2115 | if (ARG2 != 0) { |
| 2116 | struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; |
| 2117 | PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); |
| 2118 | PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); |
| 2119 | PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); |
| 2120 | if (sa->sa_flags & VKI_SA_RESTORER) |
| 2121 | PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer)); |
| 2122 | } |
| 2123 | if (ARG3 != 0) |
| 2124 | PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(struct vki_sigaction)); |
| 2125 | |
| 2126 | // XXX: doesn't seem right to be calling do_sys_sigaction for |
| 2127 | // sys_rt_sigaction... perhaps this function should be renamed |
| 2128 | // VG_(do_sys_rt_sigaction)() --njn |
| 2129 | |
| 2130 | SET_STATUS_from_SysRes( |
| 2131 | VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2, |
| 2132 | (struct vki_sigaction *)ARG3) |
| 2133 | ); |
| 2134 | } |
| 2135 | POST(sys_rt_sigaction) |
| 2136 | { |
| 2137 | vg_assert(SUCCESS); |
| 2138 | if (RES == 0 && ARG3 != 0) |
| 2139 | POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); |
| 2140 | } |
| 2141 | |
| 2142 | PRE(sys_rt_sigprocmask) |
| 2143 | { |
| 2144 | PRINT("sys_rt_sigprocmask ( %d, %p, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4); |
| 2145 | PRE_REG_READ4(long, "rt_sigprocmask", |
| 2146 | int, how, vki_sigset_t *, set, vki_sigset_t *, oldset, |
| 2147 | vki_size_t, sigsetsize); |
| 2148 | if (ARG2 != 0) |
| 2149 | PRE_MEM_READ( "rt_sigprocmask(set)", ARG2, sizeof(vki_sigset_t)); |
| 2150 | if (ARG3 != 0) |
| 2151 | PRE_MEM_WRITE( "rt_sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t)); |
| 2152 | |
| 2153 | // Like the kernel, we fail if the sigsetsize is not exactly what we expect. |
| 2154 | if (sizeof(vki_sigset_t) != ARG4) |
| 2155 | SET_STATUS_Failure( VKI_EMFILE ); |
| 2156 | else { |
| 2157 | SET_STATUS_from_SysRes( |
| 2158 | VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, |
| 2159 | (vki_sigset_t*) ARG2, |
| 2160 | (vki_sigset_t*) ARG3 ) |
| 2161 | ); |
| 2162 | } |
| 2163 | |
| 2164 | if (SUCCESS) |
| 2165 | *flags |= SfPollAfter; |
| 2166 | } |
| 2167 | POST(sys_rt_sigprocmask) |
| 2168 | { |
| 2169 | vg_assert(SUCCESS); |
| 2170 | if (RES == 0 && ARG3 != 0) |
| 2171 | POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t)); |
| 2172 | } |
| 2173 | |
| 2174 | PRE(sys_rt_sigpending) |
| 2175 | { |
| 2176 | PRINT( "sys_rt_sigpending ( %p )", ARG1 ); |
| 2177 | PRE_REG_READ2(long, "rt_sigpending", |
| 2178 | vki_sigset_t *, set, vki_size_t, sigsetsize); |
| 2179 | PRE_MEM_WRITE( "rt_sigpending(set)", ARG1, sizeof(vki_sigset_t)); |
| 2180 | } |
| 2181 | POST(sys_rt_sigpending) |
| 2182 | { |
| 2183 | POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ; |
| 2184 | } |
| 2185 | |
| 2186 | PRE(sys_rt_sigtimedwait) |
| 2187 | { |
| 2188 | *flags |= SfMayBlock; |
| 2189 | PRINT("sys_rt_sigtimedwait ( %p, %p, %p, %lld )", |
| 2190 | ARG1,ARG2,ARG3,(ULong)ARG4); |
| 2191 | PRE_REG_READ4(long, "rt_sigtimedwait", |
| 2192 | const vki_sigset_t *, set, vki_siginfo_t *, info, |
| 2193 | const struct timespec *, timeout, vki_size_t, sigsetsize); |
| 2194 | if (ARG1 != 0) |
| 2195 | PRE_MEM_READ( "rt_sigtimedwait(set)", ARG1, sizeof(vki_sigset_t)); |
| 2196 | if (ARG2 != 0) |
| 2197 | PRE_MEM_WRITE( "rt_sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t) ); |
| 2198 | if (ARG3 != 0) |
| 2199 | PRE_MEM_READ( "rt_sigtimedwait(timeout)", |
| 2200 | ARG3, sizeof(struct vki_timespec) ); |
| 2201 | } |
| 2202 | POST(sys_rt_sigtimedwait) |
| 2203 | { |
| 2204 | if (ARG2 != 0) |
| 2205 | POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); |
| 2206 | } |
| 2207 | |
| 2208 | PRE(sys_rt_sigqueueinfo) |
| 2209 | { |
| 2210 | PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3); |
| 2211 | PRE_REG_READ3(long, "rt_sigqueueinfo", |
| 2212 | int, pid, int, sig, vki_siginfo_t *, uinfo); |
| 2213 | if (ARG2 != 0) |
| 2214 | PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); |
| 2215 | } |
| 2216 | POST(sys_rt_sigqueueinfo) |
| 2217 | { |
| 2218 | if (!ML_(client_signal_OK)(ARG2)) |
| 2219 | SET_STATUS_Failure( VKI_EINVAL ); |
| 2220 | } |
| 2221 | |
| 2222 | // XXX: x86-specific? The kernel prototypes for the different archs are |
| 2223 | // hard to decipher. |
| 2224 | PRE(sys_rt_sigsuspend) |
| 2225 | { |
| 2226 | /* The C library interface to sigsuspend just takes a pointer to |
| 2227 | a signal mask but this system call has two arguments - a pointer |
| 2228 | to the mask and the number of bytes used by it. The kernel insists |
| 2229 | on the size being equal to sizeof(sigset_t) however and will just |
| 2230 | return EINVAL if it isn't. |
| 2231 | */ |
| 2232 | *flags |= SfMayBlock; |
| 2233 | PRINT("sys_rt_sigsuspend ( %p, %d )", ARG1,ARG2 ); |
| 2234 | PRE_REG_READ2(int, "rt_sigsuspend", vki_sigset_t *, mask, vki_size_t, size) |
| 2235 | if (ARG1 != (Addr)NULL) { |
| 2236 | PRE_MEM_READ( "rt_sigsuspend(mask)", ARG1, sizeof(vki_sigset_t) ); |
| 2237 | } |
| 2238 | } |
| 2239 | |
| 2240 | /* --------------------------------------------------------------------- |
| 2241 | linux msg* wrapper helpers |
| 2242 | ------------------------------------------------------------------ */ |
| 2243 | |
| 2244 | void |
| 2245 | ML_(linux_PRE_sys_msgsnd) ( ThreadId tid, |
| 2246 | UWord arg0, UWord arg1, UWord arg2, UWord arg3 ) |
| 2247 | { |
| 2248 | /* int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); */ |
| 2249 | struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; |
| 2250 | PRE_MEM_READ( "msgsnd(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); |
| 2251 | PRE_MEM_READ( "msgsnd(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); |
| 2252 | } |
| 2253 | |
| 2254 | void |
| 2255 | ML_(linux_PRE_sys_msgrcv) ( ThreadId tid, |
| 2256 | UWord arg0, UWord arg1, UWord arg2, |
| 2257 | UWord arg3, UWord arg4 ) |
| 2258 | { |
| 2259 | /* ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, |
| 2260 | long msgtyp, int msgflg); */ |
| 2261 | struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; |
| 2262 | PRE_MEM_WRITE( "msgrcv(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) ); |
| 2263 | PRE_MEM_WRITE( "msgrcv(msgp->mtext)", (Addr)&msgp->mtext, arg2 ); |
| 2264 | } |
| 2265 | void |
| 2266 | ML_(linux_POST_sys_msgrcv) ( ThreadId tid, |
| 2267 | UWord res, |
| 2268 | UWord arg0, UWord arg1, UWord arg2, |
| 2269 | UWord arg3, UWord arg4 ) |
| 2270 | { |
| 2271 | struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1; |
| 2272 | POST_MEM_WRITE( (Addr)&msgp->mtype, sizeof(msgp->mtype) ); |
| 2273 | POST_MEM_WRITE( (Addr)&msgp->mtext, res ); |
| 2274 | } |
| 2275 | |
| 2276 | void |
| 2277 | ML_(linux_PRE_sys_msgctl) ( ThreadId tid, |
| 2278 | UWord arg0, UWord arg1, UWord arg2 ) |
| 2279 | { |
| 2280 | /* int msgctl(int msqid, int cmd, struct msqid_ds *buf); */ |
| 2281 | switch (arg1 /* cmd */) { |
| 2282 | case VKI_IPC_INFO: |
| 2283 | case VKI_MSG_INFO: |
| 2284 | case VKI_IPC_INFO|VKI_IPC_64: |
| 2285 | case VKI_MSG_INFO|VKI_IPC_64: |
| 2286 | PRE_MEM_WRITE( "msgctl(IPC_INFO, buf)", |
| 2287 | arg2, sizeof(struct vki_msginfo) ); |
| 2288 | break; |
| 2289 | case VKI_IPC_STAT: |
| 2290 | case VKI_MSG_STAT: |
| 2291 | PRE_MEM_WRITE( "msgctl(IPC_STAT, buf)", |
| 2292 | arg2, sizeof(struct vki_msqid_ds) ); |
| 2293 | break; |
| 2294 | case VKI_IPC_STAT|VKI_IPC_64: |
| 2295 | case VKI_MSG_STAT|VKI_IPC_64: |
| 2296 | PRE_MEM_WRITE( "msgctl(IPC_STAT, arg.buf)", |
| 2297 | arg2, sizeof(struct vki_msqid64_ds) ); |
| 2298 | break; |
| 2299 | case VKI_IPC_SET: |
| 2300 | PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", |
| 2301 | arg2, sizeof(struct vki_msqid_ds) ); |
| 2302 | break; |
| 2303 | case VKI_IPC_SET|VKI_IPC_64: |
| 2304 | PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)", |
| 2305 | arg2, sizeof(struct vki_msqid64_ds) ); |
| 2306 | break; |
| 2307 | } |
| 2308 | } |
| 2309 | void |
| 2310 | ML_(linux_POST_sys_msgctl) ( ThreadId tid, |
| 2311 | UWord res, |
| 2312 | UWord arg0, UWord arg1, UWord arg2 ) |
| 2313 | { |
| 2314 | switch (arg1 /* cmd */) { |
| 2315 | case VKI_IPC_INFO: |
| 2316 | case VKI_MSG_INFO: |
| 2317 | case VKI_IPC_INFO|VKI_IPC_64: |
| 2318 | case VKI_MSG_INFO|VKI_IPC_64: |
| 2319 | POST_MEM_WRITE( arg2, sizeof(struct vki_msginfo) ); |
| 2320 | break; |
| 2321 | case VKI_IPC_STAT: |
| 2322 | case VKI_MSG_STAT: |
| 2323 | POST_MEM_WRITE( arg2, sizeof(struct vki_msqid_ds) ); |
| 2324 | break; |
| 2325 | case VKI_IPC_STAT|VKI_IPC_64: |
| 2326 | case VKI_MSG_STAT|VKI_IPC_64: |
| 2327 | POST_MEM_WRITE( arg2, sizeof(struct vki_msqid64_ds) ); |
| 2328 | break; |
| 2329 | } |
| 2330 | } |
| 2331 | |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2332 | /* --------------------------------------------------------------------- |
| 2333 | *at wrappers |
| 2334 | ------------------------------------------------------------------ */ |
| 2335 | |
| 2336 | PRE(sys_openat) |
| 2337 | { |
| 2338 | HChar name[30]; |
| 2339 | SysRes sres; |
| 2340 | |
| 2341 | if (ARG3 & VKI_O_CREAT) { |
| 2342 | // 4-arg version |
| 2343 | PRINT("sys_openat ( %d, %p(%s), %d, %d )",ARG1,ARG2,ARG2,ARG3,ARG4); |
| 2344 | PRE_REG_READ4(long, "openat", |
| 2345 | int, dfd, const char *, filename, int, flags, int, mode); |
| 2346 | } else { |
| 2347 | // 3-arg version |
| 2348 | PRINT("sys_openat ( %d, %p(%s), %d )",ARG1,ARG2,ARG2,ARG3); |
| 2349 | PRE_REG_READ3(long, "openat", |
| 2350 | int, dfd, const char *, filename, int, flags); |
| 2351 | } |
| 2352 | |
| 2353 | if (!ML_(fd_allowed)(ARG1, "openat", tid, False)) |
| 2354 | SET_STATUS_Failure( VKI_EBADF ); |
| 2355 | else |
| 2356 | PRE_MEM_RASCIIZ( "openat(filename)", ARG2 ); |
| 2357 | |
| 2358 | /* Handle the case where the open is of /proc/self/cmdline or |
| 2359 | /proc/<pid>/cmdline, and just give it a copy of the fd for the |
| 2360 | fake file we cooked up at startup (in m_main). Also, seek the |
| 2361 | cloned fd back to the start. */ |
| 2362 | |
| 2363 | VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); |
| 2364 | if (ML_(safe_to_deref)( (void*)ARG2, 1 ) |
| 2365 | && (VG_(strcmp)((Char *)ARG2, name) == 0 |
| 2366 | || VG_(strcmp)((Char *)ARG2, "/proc/self/cmdline") == 0)) { |
| 2367 | sres = VG_(dup)( VG_(cl_cmdline_fd) ); |
| 2368 | SET_STATUS_from_SysRes( sres ); |
| 2369 | if (!sres.isError) { |
| 2370 | OffT off = VG_(lseek)( sres.val, 0, VKI_SEEK_SET ); |
| 2371 | if (off < 0) |
| 2372 | SET_STATUS_Failure( VKI_EMFILE ); |
| 2373 | } |
| 2374 | return; |
| 2375 | } |
| 2376 | |
| 2377 | /* Otherwise handle normally */ |
| 2378 | *flags |= SfMayBlock; |
| 2379 | } |
| 2380 | |
| 2381 | POST(sys_openat) |
| 2382 | { |
| 2383 | vg_assert(SUCCESS); |
| 2384 | if (!ML_(fd_allowed)(RES, "openat", tid, True)) { |
| 2385 | VG_(close)(RES); |
| 2386 | SET_STATUS_Failure( VKI_EMFILE ); |
| 2387 | } else { |
| 2388 | if (VG_(clo_track_fds)) |
| 2389 | ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG2); |
| 2390 | } |
| 2391 | } |
| 2392 | |
| 2393 | PRE(sys_mkdirat) |
| 2394 | { |
| 2395 | *flags |= SfMayBlock; |
| 2396 | PRINT("sys_mkdirat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3); |
| 2397 | PRE_REG_READ3(long, "mkdirat", |
| 2398 | int, dfd, const char *, pathname, int, mode); |
| 2399 | PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 ); |
| 2400 | } |
| 2401 | |
| 2402 | PRE(sys_mknodat) |
| 2403 | { |
| 2404 | PRINT("sys_mknodat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4 ); |
| 2405 | PRE_REG_READ4(long, "mknodat", |
| 2406 | int, dfd, const char *, pathname, int, mode, unsigned, dev); |
| 2407 | PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 ); |
| 2408 | } |
| 2409 | |
| 2410 | PRE(sys_fchownat) |
| 2411 | { |
| 2412 | PRINT("sys_fchownat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4); |
| 2413 | PRE_REG_READ4(long, "fchownat", |
| 2414 | int, dfd, const char *, path, |
| 2415 | vki_uid_t, owner, vki_gid_t, group); |
| 2416 | PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 ); |
| 2417 | } |
| 2418 | |
| 2419 | PRE(sys_futimesat) |
| 2420 | { |
| 2421 | PRINT("sys_futimesat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3); |
| 2422 | PRE_REG_READ3(long, "futimesat", |
| 2423 | int, dfd, char *, filename, struct timeval *, tvp); |
| 2424 | PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 ); |
| 2425 | if (ARG3 != 0) |
| 2426 | PRE_MEM_READ( "futimesat(tvp)", ARG3, sizeof(struct vki_timeval) ); |
| 2427 | } |
| 2428 | |
| 2429 | PRE(sys_newfstatat) |
| 2430 | { |
| 2431 | PRINT("sys_newfstatat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3); |
| 2432 | PRE_REG_READ3(long, "fstatat", |
| 2433 | int, dfd, char *, file_name, struct stat *, buf); |
| 2434 | PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 ); |
| 2435 | PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) ); |
| 2436 | } |
| 2437 | |
| 2438 | POST(sys_newfstatat) |
| 2439 | { |
| 2440 | POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) ); |
| 2441 | } |
| 2442 | |
| 2443 | PRE(sys_unlinkat) |
| 2444 | { |
| 2445 | *flags |= SfMayBlock; |
| 2446 | PRINT("sys_unlinkat ( %d, %p(%s) )", ARG1,ARG2,ARG2); |
| 2447 | PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname); |
| 2448 | PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 ); |
| 2449 | } |
| 2450 | |
| 2451 | PRE(sys_renameat) |
| 2452 | { |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2453 | PRINT("sys_renameat ( %d, %p(%s), %d, %p(%s) )", ARG1,ARG2,ARG2,ARG3,ARG4,ARG4); |
| 2454 | PRE_REG_READ4(long, "renameat", |
| 2455 | int, olddfd, const char *, oldpath, |
| 2456 | int, newdfd, const char *, newpath); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2457 | PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 ); |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2458 | PRE_MEM_RASCIIZ( "renameat(newpath)", ARG4 ); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2459 | } |
| 2460 | |
| 2461 | PRE(sys_linkat) |
| 2462 | { |
| 2463 | *flags |= SfMayBlock; |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2464 | PRINT("sys_linkat ( %d, %p(%s), %d, %p(%s), %d )",ARG1,ARG2,ARG2,ARG3,ARG4,ARG4,ARG5); |
| 2465 | PRE_REG_READ5(long, "linkat", |
| 2466 | int, olddfd, const char *, oldpath, |
| 2467 | int, newdfd, const char *, newpath, |
| 2468 | int, flags); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2469 | PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2); |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2470 | PRE_MEM_RASCIIZ( "linkat(newpath)", ARG4); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2471 | } |
| 2472 | |
| 2473 | PRE(sys_symlinkat) |
| 2474 | { |
| 2475 | *flags |= SfMayBlock; |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2476 | PRINT("sys_symlinkat ( %p(%s), %d, %p(%s) )",ARG1,ARG1,ARG2,ARG3,ARG3); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2477 | PRE_REG_READ3(long, "symlinkat", |
tom | a43717f | 2006-05-08 11:19:47 +0000 | [diff] [blame] | 2478 | const char *, oldpath, int, newdfd, const char *, newpath); |
| 2479 | PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG1 ); |
tom | 363ec76 | 2006-03-21 10:58:35 +0000 | [diff] [blame] | 2480 | PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 ); |
| 2481 | } |
| 2482 | |
| 2483 | PRE(sys_readlinkat) |
| 2484 | { |
| 2485 | HChar name[25]; |
| 2486 | Word saved = SYSNO; |
| 2487 | |
| 2488 | PRINT("sys_readlinkat ( %d, %p(%s), %p, %llu )", ARG1,ARG2,ARG2,ARG3,(ULong)ARG4); |
| 2489 | PRE_REG_READ4(long, "readlinkat", |
| 2490 | int, dfd, const char *, path, char *, buf, int, bufsiz); |
| 2491 | PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 ); |
| 2492 | PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 ); |
| 2493 | |
| 2494 | /* |
| 2495 | * Handle the case where readlinkat is looking at /proc/self/exe or |
| 2496 | * /proc/<pid>/exe. |
| 2497 | */ |
| 2498 | VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)()); |
| 2499 | if (ML_(safe_to_deref)((void*)ARG2, 1) |
| 2500 | && (VG_(strcmp)((Char *)ARG2, name) == 0 |
| 2501 | || VG_(strcmp)((Char *)ARG2, "/proc/self/exe") == 0)) { |
| 2502 | VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd)); |
| 2503 | SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name, |
| 2504 | ARG3, ARG4)); |
| 2505 | } else { |
| 2506 | /* Normal case */ |
| 2507 | SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4)); |
| 2508 | } |
| 2509 | |
| 2510 | if (SUCCESS && RES > 0) |
| 2511 | POST_MEM_WRITE( ARG3, RES ); |
| 2512 | } |
| 2513 | |
| 2514 | PRE(sys_fchmodat) |
| 2515 | { |
| 2516 | PRINT("sys_fchmodat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3); |
| 2517 | PRE_REG_READ3(long, "fchmodat", |
| 2518 | int, dfd, const char *, path, vki_mode_t, mode); |
| 2519 | PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 ); |
| 2520 | } |
| 2521 | |
| 2522 | PRE(sys_faccessat) |
| 2523 | { |
| 2524 | PRINT("sys_faccessat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3); |
| 2525 | PRE_REG_READ3(long, "faccessat", |
| 2526 | int, dfd, const char *, pathname, int, mode); |
| 2527 | PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 ); |
| 2528 | } |
| 2529 | |
sewardj | e6d5e72 | 2005-06-10 10:27:55 +0000 | [diff] [blame] | 2530 | #undef PRE |
| 2531 | #undef POST |
nethercote | fd45353 | 2004-11-17 17:21:12 +0000 | [diff] [blame] | 2532 | |
| 2533 | /*--------------------------------------------------------------------*/ |
| 2534 | /*--- end ---*/ |
| 2535 | /*--------------------------------------------------------------------*/ |