1 2/*--------------------------------------------------------------------*/ 3/*--- AIX5-specific syscalls. syswrap-aix5.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2006-2010 OpenWorks LLP 11 info@open-works.co.uk 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 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34*/ 35 36#if defined(VGO_aix5) 37 38#include "pub_core_basics.h" 39#include "pub_core_vki.h" 40#include "pub_core_vkiscnums.h" 41#include "pub_core_threadstate.h" 42#include "pub_core_aspacemgr.h" 43#include "pub_core_debuginfo.h" // VG_(di_notify_*) 44#include "pub_core_transtab.h" // VG_(discard_translations) 45#include "pub_core_xarray.h" 46#include "pub_core_clientstate.h" 47#include "pub_core_debuglog.h" 48#include "pub_core_libcbase.h" 49#include "pub_core_libcassert.h" 50#include "pub_core_libcfile.h" 51#include "pub_core_libcprint.h" 52#include "pub_core_libcproc.h" 53#include "pub_core_libcsignal.h" 54#include "pub_core_mallocfree.h" 55#include "pub_core_tooliface.h" 56#include "pub_core_options.h" 57#include "pub_core_scheduler.h" 58#include "pub_core_signals.h" 59#include "pub_core_syscall.h" 60#include "pub_core_sigframe.h" // VG_(sigframe_destroy) 61#include "pub_core_syswrap.h" 62#include "pub_core_stacktrace.h" 63 64#include "priv_types_n_macros.h" 65#include "priv_syswrap-aix5.h" 66 67 68 69/* --------------------------------------------------------------------- 70 Misc helpers 71 ------------------------------------------------------------------ */ 72 73/* Allocate a stack for this thread, if it doesn't already have one. 74 They're allocated lazily, and never freed. Returns the initial stack 75 pointer value to use, or 0 if allocation failed. */ 76Addr ML_(allocstack)(ThreadId tid) 77{ 78 ThreadState* tst = VG_(get_ThreadState)(tid); 79 VgStack* stack; 80 Addr initial_SP; 81 82 /* Either the stack_base and stack_init_SP are both zero (in which 83 case a stack hasn't been allocated) or they are both non-zero, 84 in which case it has. */ 85 86 if (tst->os_state.valgrind_stack_base == 0) 87 vg_assert(tst->os_state.valgrind_stack_init_SP == 0); 88 89 if (tst->os_state.valgrind_stack_base != 0) 90 vg_assert(tst->os_state.valgrind_stack_init_SP != 0); 91 92 /* If no stack is present, allocate one. */ 93 if (tst->os_state.valgrind_stack_base == 0) { 94 stack = VG_(am_alloc_VgStack)( &initial_SP ); 95 if (stack) { 96 /* Leave some space above SP because AIX's ABI stores 97 stuff there. */ 98 initial_SP -= 256; 99 vg_assert(initial_SP > (Addr)stack); 100 tst->os_state.valgrind_stack_base = (Addr)stack; 101 tst->os_state.valgrind_stack_init_SP = initial_SP; 102 } else { 103 return 0; /* allocation of stack failed */ 104 } 105 } 106 107 if (0) 108 VG_(printf)( "stack for tid %d at %p; init_SP=%p\n", 109 tid, 110 (void*)tst->os_state.valgrind_stack_base, 111 (void*)tst->os_state.valgrind_stack_init_SP ); 112 113 return tst->os_state.valgrind_stack_init_SP; 114} 115 116 117/* If we know or believe a module load/unload event has happened, get 118 aspacem to re-read /proc/../map to update its picture of what text 119 and data segments are present. This also notifies all the usual 120 parties that need to know about address space changes. */ 121 122void ML_(aix5_rescan_procmap_after_load_or_unload) ( void ) 123{ 124 AixCodeSegChange* changes; 125 Int changes_size, changes_used, i; 126 127 /* Find out how many AixCodeSegChange records we will need, and 128 acquire them. */ 129 changes_size = VG_(am_aix5_reread_procmap_howmany_directives)(); 130 changes = VG_(arena_malloc)(VG_AR_CORE, "syswrap-aix5.arpalou.1", 131 changes_size * sizeof(AixCodeSegChange)); 132 vg_assert(changes); 133 134 /* Now re-read /proc/<pid>/map and acquire a change set */ 135 VG_(am_aix5_reread_procmap)( changes, &changes_used ); 136 vg_assert(changes_used >= 0 && changes_used <= changes_size); 137 138 /* And notify all parties of the changes. */ 139 for (i = 0; i < changes_used; i++) { 140 ULong di_handle = VG_(di_aix5_notify_segchange)( 141 changes[i].code_start, 142 changes[i].code_len, 143 changes[i].data_start, 144 changes[i].data_len, 145 changes[i].file_name, 146 changes[i].mem_name, 147 changes[i].is_mainexe, 148 changes[i].acquire 149 ); 150 151 if (changes[i].acquire) { 152 VG_TRACK( new_mem_mmap, 153 changes[i].code_start, changes[i].code_len, 154 /*r*/True, /*w*/False, /*x*/True, di_handle ); 155 VG_TRACK( new_mem_mmap, 156 changes[i].data_start, changes[i].data_len, 157 /*r*/True, /*w*/True, /*x*/False, 0/*or di_handle?*/ ); 158 } else { 159 VG_TRACK( die_mem_munmap, 160 changes[i].code_start, changes[i].code_len ); 161 VG_TRACK( die_mem_munmap, 162 changes[i].data_start, changes[i].data_len ); 163 VG_(discard_translations)( 164 changes[i].code_start, changes[i].code_len, 165 "POST(sys___loadx/sys__kload)(code)" ); 166 VG_(discard_translations)( 167 changes[i].data_start, changes[i].data_len, 168 "POST(sys___loadx/sys__kload)(data)" ); 169 } 170 } 171 172 VG_(arena_free)(VG_AR_CORE, changes); 173} 174 175 176/* Mess with the given thread's pc/toc so that it is entering 177 pthread_exit() with argument PTHREAD_CANCELED. Returns True if ok, 178 False if it failed to do so, due to not being able to find 179 pthread_exit() by searching symbol tables. */ 180Bool ML_(aix5_force_thread_into_pthread_exit)( ThreadId tid ) 181{ 182 Addr ent = 0, toc = 0; 183 Bool found; 184 ThreadState* tst = VG_(get_ThreadState)(tid); 185 found = VG_(lookup_symbol_SLOW)("libpthread*.a(*.o)", "pthread_exit", 186 &ent, &toc); 187 if (found) { 188 if (0) 189 VG_(printf)("THREAD CANCELED, new cia,toc = %#lx,%#lx\n", ent, toc); 190 tst->arch.vex.guest_CIA = ent; 191 tst->arch.vex.guest_GPR2 = toc; 192 tst->arch.vex.guest_GPR3 = (Word)(-1); /* == PTHREAD_CANCELED */ 193 /* If the thread is blocked in a syscall, we better bop it on 194 the head with SIGVGKILL in order to get it out of said 195 syscall. */ 196 if (tst->status == VgTs_WaitSys) { 197 if (VG_(clo_trace_syscalls)) 198 VG_(printf)("(sending SIGVGKILL to tid %d)", (Int)tid); 199 VG_(get_thread_out_of_syscall)( tid ); 200 } 201 return True; /* ok */ 202 } else { 203 // urk. Now we're hosed. Let the caller figure out what to do. 204 return False; /* failed */ 205 } 206} 207 208 209/* For various reasons, on AIX we may have to just give up if 210 continuing is too difficult (eg, risk of future deadlock). This 211 sets up the process state to exit straight away, but does not 212 actually itself exit. */ 213void ML_(aix5_set_threadstate_for_emergency_exit)(ThreadId tid, HChar* why) 214{ 215 ThreadState* tst = VG_(get_ThreadState)(tid); 216 /* Set the thread's status to be exiting and taking out the 217 entire process, then claim that the syscall succeeded. */ 218 tst->exitreason = VgSrc_ExitProcess; 219 tst->os_state.exitcode = 1; 220 if (!VG_(clo_xml)) { 221 VG_(message)(Vg_UserMsg, 222 "WARNING: AIX: %s\n", why); 223 VG_(message)(Vg_UserMsg, 224 "WARNING: (too difficult to continue past this point).\n"); 225 VG_(get_and_pp_StackTrace)(tid, 10); 226 } 227} 228 229 230/* Update aspacem etc on conclusion of a successful sbrk/__libc_sbrk 231 call. 2006-08-24: this was not completed because I don't 232 understand what sbrk/__libc_sbrk are doing. */ 233 234static void handle_sbrk ( Word delta ) 235{ 236 return; 237 /*NOTREACHED*/ 238 if (delta > 0) { 239 /* Map in VG_(brk_limit) for delta */ 240 /* using notify_mmap ? */ 241 VG_(brk_limit) += delta; 242 } 243 if (delta < 0) { 244 Addr tmp = VG_(brk_limit); 245 VG_(brk_limit) += delta; 246 /* Can't move below original starting point */ 247 if (VG_(brk_limit) < VG_(brk_base)) 248 VG_(brk_limit) = VG_(brk_base); 249 if (VG_(brk_limit) < tmp) 250 /* Unmap VG_(brk_limit) for tmp - VG_(brk_limit) */ 251 /* using notify_munmap ? */ 252 ; 253 } 254 if (VG_(clo_trace_syscalls)) 255 VG_(printf)("new brk: 0x%010llx-0x%010llx (size %lld)\n", 256 (ULong)VG_(brk_base), 257 (ULong)VG_(brk_limit), 258 (ULong)VG_(brk_limit) - (ULong)VG_(brk_base)); 259} 260 261 262/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 263#include <sys/thread.h> 264#include <sys/poll.h> 265#include <sys/times.h> 266#include <sys/shm.h> 267#include <semaphore.h> 268#include <sys/statfs.h> 269#include <sys/utsname.h> 270/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 271 272HChar* ML_(aix5debugstuff_pc_to_fnname) ( Addr pc ) 273{ 274 Bool ok; 275 static HChar name[100]; 276 ok = VG_(get_fnname_w_offset)(pc, name, 100); 277 if (!ok) VG_(strcpy)(name, "???"); 278 return &name[0]; 279} 280 281static void aix5debugstuff_show_sigset ( vki_sigset_t* set ) 282{ 283 Int i; 284 UChar* p = (UChar*)set; 285 for (i = 0; i < sizeof(vki_sigset_t); i++) 286 VG_(printf)("%02x", (Int)p[i]); 287} 288 289static HChar* aix5debugstuff_name_of_tstate_flag ( UWord flag ) 290{ 291 Int i, nset; 292 nset = 0; 293 for (i = 0; i < 8*sizeof(UWord); i++) 294 if (flag & (1U << i)) 295 nset++; 296 vg_assert(nset == 1); 297 switch (flag) { 298 case TSTATE_LOCAL: return "LOCAL"; 299 case TSTATE_CANCEL_DEFER: return "CANCEL_DEFER"; 300 case TSTATE_CANCEL_DISABLE: return "CANCEL_DISABLE"; 301 case TSTATE_CANCEL_PENDING: return "CANCEL_PENDING"; 302 case TSTATE_CANCEL_CHKPT: return "CANCEL_CHKPT"; 303 case TSTATE_INTR: return "INTR"; 304 case TSTATE_EXEMPT: return "EXEMPT"; 305#ifdef TSTATE_PROFILING_OFF 306 case TSTATE_PROFILING_OFF: return "PROFILING_OFF"; 307#endif 308 case TSTATE_SUSPEND: return "SUSPEND"; 309 case TSTATE_CONT: return "CONT"; 310#ifdef TSTATE_CREDS 311 case TSTATE_CREDS: return "CREDS"; 312#endif 313#ifdef TSTATE_PROCHANDLERS 314 case TSTATE_PROCHANDLERS: return "PROCHANDLERS"; 315#endif 316 case TSTATE_ADVH: return "ADVH"; 317 case TSTATE_SYNCH: return "SYNCH"; 318 case TSTATE_USCHED: return "USCHED"; 319 case TSTATE_DEFAULT_SCHED: return "DEFAULT_SCHED"; 320#ifdef TSTATE_INHERIT_SCHED 321 case TSTATE_INHERIT_SCHED: return "INHERIT_SCHED"; 322#endif 323#ifdef TSTATE_LOCAL_INIT 324 case TSTATE_LOCAL_INIT: return "LOCAL_INIT"; 325#endif 326#ifdef TSTATE_LOCAL_TERM 327 case TSTATE_LOCAL_TERM: return "LOCAL_TERM"; 328#endif 329#ifdef TSTATE_LOCAL_MCHANGE 330 case TSTATE_LOCAL_MCHANGE: return "LOCAL_MCHANGE"; 331#endif 332 case TSTATE_CHANGE_ALL: return "CHANGE_ALL"; 333#ifdef TSTATE_CHANGE_PTID 334 case TSTATE_CHANGE_PTID: return "CHANGE_PTID"; 335#endif 336#ifdef TSTATE_CHANGE_PROFILE 337 case TSTATE_CHANGE_PROFILE: return "CHANGE_PROFILE"; 338#endif 339#ifdef TSTATE_CHANGE_SSTACK 340 case TSTATE_CHANGE_SSTACK: return "CHANGE_SSTACK"; 341#endif 342 case TSTATE_CHANGE_ERRNOP: return "CHANGE_ERRNOP"; 343 case TSTATE_CHANGE_SIGMASK: return "CHANGE_SIGMASK"; 344 case TSTATE_CHANGE_PSIG: return "CHANGE_PSIG"; 345 case TSTATE_CHANGE_SCHED: return "CHANGE_SCHED"; 346 case TSTATE_CHANGE_FLAGS: return "CHANGE_FLAGS"; 347 case TSTATE_CHANGE_USERDATA: return "CHANGE_USERDATA"; 348 default: return "???"; 349 } 350} 351 352void ML_(aix5debugstuff_show_tstate_flags) ( UWord w ) 353{ 354 const Int step = 5; 355 Int i, j; 356 UWord m; 357 j = 0; 358 for (i = 0; i < 8*sizeof(UWord); i++) { 359 m = 1U << i; 360 if ((w & m) == 0) 361 continue; 362 if ((j % step) == 0) 363 VG_(printf)(" "); 364 VG_(printf)("%s ", aix5debugstuff_name_of_tstate_flag(w & m)); 365 if ((j % step) == step-1 && j > 0) 366 VG_(printf)("\n"); 367 j++; 368 } 369 if (((j-1) % step) != step-1 && j > 0) 370 VG_(printf)("\n"); 371} 372 373void ML_(aix5debugstuff_show_tstate) ( Addr tsA, HChar* who ) 374{ 375 Int i; 376 const Int step = sizeof(void*)==8 ? 3 : 5; 377 struct tstate* ts = (struct tstate*)tsA; 378 VG_(printf)("\n{ ========= %s =========\n", who); 379 for (i = 0; i < _NGPRS; i++) { 380 if ((i % step) == 0) 381 VG_(printf)(" [%2d] ", i); 382 if (sizeof(void*)==8) 383 VG_(printf)("%016llx ", (ULong)ts->mst.gpr[i]); 384 else 385 VG_(printf)("%08llx ", (ULong)ts->mst.gpr[i]); 386 if ((i == _NGPRS-1) || ((i % step) == step-1 && i > 0)) 387 VG_(printf)("\n"); 388 } 389 VG_(printf)(" [iar] %#llx %s\n", (ULong)ts->mst.iar, 390 ML_(aix5debugstuff_pc_to_fnname)(ts->mst.iar)); 391 392 VG_(printf)(" errnop_addr %p\n", ts->errnop_addr); 393 394 VG_(printf)(" sigmask "); 395 aix5debugstuff_show_sigset( (vki_sigset_t*)&ts->sigmask ); 396 VG_(printf)("\n"); 397 398 VG_(printf)(" psig "); 399 aix5debugstuff_show_sigset( (vki_sigset_t*)&ts->psig ); 400 VG_(printf)("\n"); 401 402 VG_(printf)(" policy %d\n", ts->policy); 403 VG_(printf)(" priority %d\n", ts->priority); 404 VG_(printf)(" flags 0x%x\n", ts->flags); 405 ML_(aix5debugstuff_show_tstate_flags)( (UWord)ts->flags ); 406 VG_(printf)(" flagmask 0x%x\n", ts->flagmask); 407 VG_(printf)(" userdata %p\n", (void*)ts->userdata); 408 VG_(printf)(" fpinfo %d\n", ts->fpinfo); 409 VG_(printf)(" fpscrx %d\n", ts->fpscrx); 410 VG_(printf)(" sigaltstack ??\n"); 411 VG_(printf)(" thread_control_p 0x%llx\n", (ULong)ts->thread_control_p); 412// AIX 5.1 does not seem to have these members 413// VG_(printf)(" prbase %p\n", (void*)ts->prbase); 414// VG_(printf)(" credp %p\n", (void*)ts->credp); 415// VG_(printf)(" ptid %d\n", (int)ts->ptid); 416// VG_(printf)(" tct_clock %d\n", (int)ts->tct_clock); 417 UInt* p = (UInt*)tsA; 418 for (i = 0; i < sizeof(struct tstate)/sizeof(UInt); i++) { 419 HChar* s = ML_(aix5debugstuff_pc_to_fnname)( (Addr)p[i] ); 420 if (0==VG_(strcmp)(s,"???")) 421 continue; 422 VG_(printf)(" [%d] %x %s\n", i, p[i], s); 423 } 424 VG_(printf)("}\n"); 425} 426 427/* --------------------------------------------------------------------- 428 PRE/POST wrappers for arch-generic, AIX5-specific syscalls. Note: 429 in fact AIX5 doesn't share any wrappers with Linux since it's 430 difficult to get syswrap-generic.c to compile on AIX. Hence in 431 fact this file also serves the role of syswrap-generic.c for AIX. 432 This could probably be improved at the cost of some extra effort. 433 ------------------------------------------------------------------ */ 434 435// Nb: See the comment above the generic PRE/POST wrappers in 436// m_syswrap/syswrap-generic.c for notes about how they work. 437 438#define PRE(name) DEFN_PRE_TEMPLATE(aix5, name) 439#define POST(name) DEFN_POST_TEMPLATE(aix5, name) 440 441 442// How to make __libc_sbrk appear to fail, from libc's point of view: 443// SysRes r; 444// r.res = -1; /* significant to libc */ 445// r.err = VKI_ENOMEM; /* not significant to libc */ 446// SET_STATUS_from_SysRes( r ); 447// return; 448 449PRE(sys___libc_sbrk) 450{ 451 PRINT("__libc_sbrk (BOGUS HANDLER)( %#lx )",ARG1); 452 PRE_REG_READ1(long, "__libc_sbrk", long, arg1); 453 /* After a zero sbrk, disallow aspacem from doing sbrk, since libc 454 might rely on the value returned by this syscall. */ 455 /* 1 Oct 06: not currently used (aspacemgr-aix5.c ignores it) */ 456 VG_(am_aix5_sbrk_allowed) = toBool(ARG1 != 0); 457 /* Disallow libc from moving the brk backwards as that might trash 458 SkPreAlloc sections acquired by aspacem from previous uses of 459 sbrk. */ 460 if (ARG1 < 0) 461 ARG1 = 0; 462 /* Do this as a sync syscall, so the sbrk_allowed flag gets turned 463 back on ASAP. Typically libc does sbrk(0) and then sbrk(x > 0) 464 in quick succession. Although surely it should hold some kind 465 of lock at that point, else it cannot safely use the result from 466 the first sbrk call to influence the second one? */ 467 *flags &= ~SfMayBlock; 468} 469POST(sys___libc_sbrk) 470{ 471 vg_assert(SUCCESS); 472 handle_sbrk(ARG1); 473} 474 475/* __loadx is handled in the platform-specific files. */ 476 477PRE(sys___msleep) 478{ 479 PRINT("__msleep (BOGUS HANDLER) ( %#lx )", ARG1); 480 PRE_REG_READ1(long, "msleep", void*, arg1); 481} 482 483/* __unload is handled in the platform-specific files. */ 484 485PRE(sys__clock_settime) 486{ 487 PRINT("_clock_settime (UNDOCUMENTED) ( %ld, %#lx )", ARG1, ARG2); 488 PRE_REG_READ2(int, "_clock_settime", int, arg1, int, arg2); 489} 490 491PRE(sys__exit) 492{ 493 ThreadState* tst; 494 /* simple; just make this thread exit */ 495 PRINT("_exit( %ld )", ARG1); 496 PRE_REG_READ1(void, "exit", int, exitcode); 497 498 tst = VG_(get_ThreadState)(tid); 499 /* Set the thread's status to be exiting and taking out the entire 500 process, then claim that the syscall succeeded. */ 501 tst->exitreason = VgSrc_ExitProcess; 502 tst->os_state.exitcode = ARG1; 503 SET_STATUS_Success(0); 504} 505 506PRE(sys__fp_fpscrx_sc) 507{ 508 PRINT("_fp_fpscrx_sc (BOGUS HANDLER)"); 509} 510 511PRE(sys__getpgrp) 512{ 513 PRINT("_getpgrp (BOGUS HANDLER)"); 514} 515 516PRE(sys__getpid) 517{ 518 PRINT("_getpid ( )"); 519} 520 521PRE(sys__getppid) 522{ 523 PRINT("_getppid ( )"); 524} 525 526PRE(sys__getpriority) 527{ 528 PRINT("_getpriority (BOGUS HANDLER)"); 529} 530 531PRE(sys__nsleep) 532{ 533 *flags |= SfMayBlock; 534 PRINT("_nsleep( %#lx, %#lx )", ARG1, ARG2); 535 PRE_REG_READ2(void, "_nsleep", struct timestruc_t*, arg1, 536 struct timestruc_t*, arg2); 537 /* In 64-bit mode, struct ends in 4 padding bytes. Hence: */ 538 if (ARG1) 539 PRE_MEM_READ("_nsleep(arg1)", 540 ARG1, 541 sizeof(void*)==4 ? sizeof(struct timestruc_t) 542 : sizeof(struct timestruc_t)-4 ); 543 if (ARG2) 544 PRE_MEM_WRITE("_nsleep(arg2)", ARG2, sizeof(struct timestruc_t)); 545} 546POST(sys__nsleep) 547{ 548 if (ARG2) 549 POST_MEM_WRITE(ARG2, sizeof(struct timestruc_t)); 550} 551 552PRE(sys__pause) 553{ 554 *flags |= SfMayBlock; 555 PRINT("_pause ( )"); 556 PRE_REG_READ0(long, "pause"); 557} 558 559PRE(sys__poll) 560{ 561 UInt i; 562 struct pollfd* ufds = (struct pollfd *)ARG1; 563 *flags |= SfMayBlock; 564 PRINT("_poll ( %#lx, %ld, %ld )\n", ARG1,ARG2,ARG3); 565 PRE_REG_READ3(long, "_poll", 566 struct pollfd *, ufds, unsigned int, nfds, long, timeout); 567 568 for (i = 0; i < ARG2; i++) { 569 PRE_MEM_READ( "poll(ufds.fd)", 570 (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) ); 571 PRE_MEM_READ( "poll(ufds.events)", 572 (Addr)(&ufds[i].events), sizeof(ufds[i].events) ); 573 PRE_MEM_WRITE( "poll(ufds.reventss)", 574 (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); 575 } 576} 577POST(sys__poll) 578{ 579 if (RES > 0) { 580 UInt i; 581 struct pollfd* ufds = (struct pollfd *)ARG1; 582 for (i = 0; i < ARG2; i++) 583 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) ); 584 } 585} 586 587PRE(sys__select) 588{ 589 UInt nfds, nmqids; 590 *flags |= SfMayBlock; 591 /* XXX: copy of generic; I don't know if this is right or not. */ 592 PRINT("_select ( %ld, %#lx, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); 593 PRE_REG_READ5(long, "_select", 594 int, n, struct sellist *, readfds, 595 struct sellist *, writefds, 596 struct sellist *, exceptfds, 597 struct timeval *, timeout); 598 nfds = ((UInt)ARG1) & 0xFFFF; 599 nmqids = (((UInt)ARG1) >> 16) & 0xFFFF; 600 601 // XXX: this possibly understates how much memory is read. 602 if (ARG2 != 0) 603 PRE_MEM_READ( "select(readfds)", 604 ARG2, nfds/8 /* __FD_SETSIZE/8 */ ); 605 if (ARG3 != 0) 606 PRE_MEM_READ( "select(writefds)", 607 ARG3, nfds/8 /* __FD_SETSIZE/8 */ ); 608 if (ARG4 != 0) 609 PRE_MEM_READ( "select(exceptfds)", 610 ARG4, nfds/8 /* __FD_SETSIZE/8 */ ); 611 if (ARG5 != 0) 612 PRE_MEM_READ( "select(timeout)", ARG5, 613 /* in 64-bit mode, struct timeval has 4 bytes of 614 padding at the end, which tend to not be 615 initialised. */ 616 sizeof(void*)==4 ? sizeof(struct timeval) 617 : sizeof(struct timeval)-4 618 ); 619} 620 621PRE(sys__sem_wait) 622{ 623 *flags |= SfMayBlock; 624 PRINT("_sem_wait (BOGUS HANDLER) ( %#lx, %#lx, %ld )", ARG1, ARG2, ARG3); 625 PRE_REG_READ3(long, "_sem_wait", void*, arg1, void*, arg2, long, arg3 ); 626 /* Not sure what the two pointer args are. Hence no proper handler.*/ 627} 628 629PRE(sys__setpgid) 630{ 631 PRINT("setpgid ( %ld, %ld )", ARG1, ARG2); 632 PRE_REG_READ2(int, "setpgid", int, pid, int, pgid); 633} 634 635PRE(sys__setsid) 636{ 637 PRINT("setsid ( )"); 638} 639 640PRE(sys__sigaction) /* COL, more or less */ 641{ 642 PRINT("_sigaction ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 643 PRE_REG_READ3(long, "_sigaction", 644 int, signum, const struct sigaction *, act, 645 struct sigaction *, oldact); 646 647 if (ARG2 != 0) { 648 struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; 649 PRE_MEM_READ( "_sigaction(act->sa_handler)", 650 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); 651 PRE_MEM_READ( "_sigaction(act->sa_mask)", 652 (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); 653 PRE_MEM_READ( "rt_sigaction(act->sa_flags)", 654 (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); 655 } 656 if (ARG3 != 0) 657 PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(struct vki_sigaction)); 658 659 SET_STATUS_from_SysRes( 660 VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2, 661 (struct vki_sigaction *)ARG3) 662 ); 663} 664POST(sys__sigaction) 665{ 666 vg_assert(SUCCESS); 667 if (RES == 0 && ARG3 != 0) 668 POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); 669} 670 671PRE(sys__thread_self) 672{ 673 PRINT("_thread_self ( )"); 674} 675 676PRE(sys__thread_setsched) 677{ 678 PRINT("_thread_setsched ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); 679 PRE_REG_READ3(long, "_thread_setsched", long, arg1, long, arg2, long, arg3); 680} 681 682PRE(sys_access) 683{ 684 PRINT("access ( %#lx(%s), %ld )", ARG1,(Char*)ARG1, ARG2); 685 PRE_REG_READ2(int, "access", char*, pathname, int, mode); 686 PRE_MEM_RASCIIZ( "access(pathname)", ARG1 ); 687} 688 689PRE(sys_accessx) 690{ 691 PRINT("accessx ( %#lx(%s), %ld, %ld )", ARG1,(Char*)ARG1, ARG2, ARG3); 692 PRE_REG_READ3(int, "accessx", char*, pathname, int, mode, int, who); 693 PRE_MEM_RASCIIZ( "accessx(pathname)", ARG1 ); 694} 695 696PRE(sys_appgetrlimit) 697{ 698 /* Note: assumes kernel struct == libc struct */ 699 PRINT("appgetrlimit ( %ld, %#lx )", ARG1, ARG2); 700 PRE_REG_READ2(int, "appgetrlimit", int, arg1, struct rlimit*, arg2); 701 PRE_MEM_WRITE( "appgetrlimit(buf)", ARG2, sizeof(struct rlimit) ); 702} 703POST(sys_appgetrlimit) 704{ 705 POST_MEM_WRITE( ARG2, sizeof(struct rlimit) ); 706} 707 708PRE(sys_appgetrusage) 709{ 710 /* Note: assumes kernel struct == libc struct */ 711 PRINT("appgetrusage ( %ld, %#lx )", ARG1, ARG2); 712 PRE_REG_READ2(int, "appgetrusage", int, arg1, struct rusage*, arg2); 713 PRE_MEM_WRITE( "appgetrusage(buf)", ARG2, sizeof(struct rusage) ); 714} 715POST(sys_appgetrusage) 716{ 717 POST_MEM_WRITE( ARG2, sizeof(struct rusage) ); 718} 719 720PRE(sys_apprestimer) 721{ 722 PRINT("apprestimer (BOGUS HANDLER)"); 723} 724 725PRE(sys_appsetrlimit) 726{ 727 PRINT("appsetrlimit (BOGUS HANDLER)"); 728} 729 730PRE(sys_appulimit) 731{ 732 PRINT("appulimit ( %ld, %ld )", ARG1, ARG2); 733 PRE_REG_READ2(long, "appulimit", long, arg1, long, arg2); 734} 735 736PRE(sys_bind) 737{ 738 PRINT("bind ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 739 PRE_REG_READ3(int, "bind", int, socket, 740 void*, address, int, addresslen); 741 /* Hmm. This isn't really right - see pre_mem_read_sockaddr. */ 742 PRE_MEM_READ( "bind(address)", ARG2, ARG3 ); 743} 744 745PRE(sys_chdir) 746{ 747 PRINT("chdir ( %#lx(%s) )", ARG1,(Char*)ARG1); 748 PRE_REG_READ1(long, "chdir", const char *, path); 749 PRE_MEM_RASCIIZ( "chdir(path)", ARG1 ); 750} 751 752PRE(sys_chmod) 753{ 754 PRINT("chmod ( %#lx(%s), 0x%lx )", ARG1,(Char*)ARG1, ARG2 ); 755 PRE_REG_READ2(int, "chmod", char*, path, int, mode); 756 PRE_MEM_RASCIIZ( "chmod(path)", ARG1 ); 757} 758 759PRE(sys_chown) 760{ 761 PRINT("chown ( %#lx(%s), %ld, %ld )", ARG1,(Char*)ARG1, ARG2, ARG3 ); 762 PRE_REG_READ3(int, "chown", char*, path, int, owner, int, group); 763 PRE_MEM_RASCIIZ( "chown(path)", ARG1 ); 764} 765 766PRE(sys_close) 767{ 768 PRINT("close ( %ld )", ARG1); 769 PRE_REG_READ1(void, "close", UInt, fd); 770 /* If doing -d style logging (which is to fd=2), don't allow that 771 to be closed. */ 772 if (ARG1 == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0) 773 SET_STATUS_Failure( VKI_EBADF ); 774} 775 776PRE(sys_connext) 777{ 778 /* apparently undocumented. I don't know what it does. */ 779 /* Although /usr/include/net/proto_uipc.h does mention it. 780 Args are apparently (int, caddr_t, int). I suspect the 781 first arg is a fd and the third a flags value. */ 782 PRINT("connext (UNDOCUMENTED)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 783 PRE_REG_READ3(int, "connext", int, arg1, caddr_t*, arg2, int, arg3); 784} 785 786//--- PRE(sys_execve) ---// 787// Pre_read a char** argument. 788static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2) 789{ 790 while (True) { 791 Addr a_deref; 792 Addr* a_p = (Addr*)a; 793 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) ); 794 a_deref = *a_p; 795 if (0 == a_deref) 796 break; 797 PRE_MEM_RASCIIZ( s2, a_deref ); 798 a += sizeof(char*); 799 } 800} 801static SysRes simple_pre_exec_check ( const HChar* exe_name, 802 Bool trace_this_child ) 803{ 804 Int fd, ret; 805 SysRes res; 806 Bool setuid_allowed; 807 808 // Check it's readable 809 res = VG_(open)(exe_name, VKI_O_RDONLY, 0); 810 if (res.isError) { 811 return res; 812 } 813 fd = res.res; 814 VG_(close)(fd); 815 816 // Check we have execute permissions. We allow setuid executables 817 // to be run only in the case when we are not simulating them, that 818 // is, they to be run natively. 819 setuid_allowed = trace_this_child ? False : True; 820 ret = VG_(check_executable)(NULL/*&is_setuid*/, 821 (HChar*)exe_name, setuid_allowed); 822 if (0 != ret) { 823 return VG_(mk_SysRes_Error)(ret); 824 } 825 return VG_(mk_SysRes_Success)(0); 826} 827PRE(sys_execve) 828{ 829 Char* path = NULL; /* path to executable */ 830 Char** envp = NULL; 831 Char** argv = NULL; 832 Char** arg2copy; 833 Char* launcher_basename = NULL; 834 ThreadState* tst; 835 Int i, j, tot_args; 836 SysRes res; 837 Bool trace_this_child; 838 839 PRINT("sys_execve ( %#lx(%s), %#lx, %#lx )", ARG1, (Char*)ARG1, ARG2, ARG3); 840 PRE_REG_READ3(vki_off_t, "execve", 841 char *, filename, char **, argv, char **, envp); 842 PRE_MEM_RASCIIZ( "execve(filename)", ARG1 ); 843 if (ARG2 != 0) 844 pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" ); 845 if (ARG3 != 0) 846 pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" ); 847 848 vg_assert(VG_(is_valid_tid)(tid)); 849 tst = VG_(get_ThreadState)(tid); 850 851 /* Erk. If the exec fails, then the following will have made a 852 mess of things which makes it hard for us to continue. The 853 right thing to do is piece everything together again in 854 POST(execve), but that's close to impossible. Instead, we make 855 an effort to check that the execve will work before actually 856 doing it. */ 857 858 /* Check that the name at least begins in client-accessible storage. */ 859 /* XXX: causes execve to fail for non-memcheck tools, presumably 860 because ARG1 is thought to not to being in client-accessible 861 storage due to inadequate address space tracking. May or may 862 not be due to non-tracking of brk. */ 863 //if (!VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) { 864 // SET_STATUS_Failure( VKI_EFAULT ); 865 // return; 866 //} 867 if (ARG1 == 0 /* obviously bogus */) { 868 SET_STATUS_Failure( VKI_EFAULT ); 869 } 870 871 // Decide whether or not we want to follow along 872 trace_this_child = VG_(should_we_trace_this_child)( (HChar**)ARG2 ); 873 874 // Do the important checks: it is a file, is executable, permissions are 875 // ok, etc. 876 res = simple_pre_exec_check( (const HChar*)ARG1, trace_this_child ); 877 if (res.isError) { 878 SET_STATUS_Failure( res.err ); 879 return; 880 } 881 882 /* If we're tracing the child, and the launcher name looks bogus 883 (possibly because launcher.c couldn't figure it out, see 884 comments therein) then we have no option but to fail. */ 885 if (trace_this_child 886 && (VG_(name_of_launcher) == NULL 887 || VG_(name_of_launcher)[0] != '/')) { 888 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */ 889 return; 890 } 891 892 /* After this point, we can't recover if the execve fails. */ 893 VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1); 894 895 /* Resistance is futile. Nuke all other threads. POSIX mandates 896 this. (Really, nuke them all, since the new process will make 897 its own new thread.) */ 898 VG_(nuke_all_threads_except)( tid, VgSrc_ExitThread ); 899 VG_(reap_threads)(tid); 900 901 // Set up the child's exe path. 902 // 903 if (trace_this_child) { 904 905 // We want to exec the launcher. Get its pre-remembered path. 906 path = VG_(name_of_launcher); 907 // VG_(name_of_launcher) should have been acquired by m_main at 908 // startup. 909 vg_assert(path); 910 911 launcher_basename = VG_(strrchr)(path, '/'); 912 if (launcher_basename == NULL || launcher_basename[1] == 0) { 913 launcher_basename = path; // hmm, tres dubious 914 } else { 915 launcher_basename++; 916 } 917 918 } else { 919 path = (Char*)ARG1; 920 } 921 922 // Set up the child's environment. 923 // 924 // Remove the valgrind-specific stuff from the environment so the 925 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. 926 // This is done unconditionally, since if we are tracing the child, 927 // the child valgrind will set up the appropriate client environment. 928 // Nb: we make a copy of the environment before trying to mangle it 929 // as it might be in read-only memory (this was bug #101881). 930 // 931 // Then, if tracing the child, set VALGRIND_LIB for it. 932 // 933 if (ARG3 == 0) { 934 envp = NULL; 935 } else { 936 envp = VG_(env_clone)( (Char**)ARG3 ); 937 if (envp == NULL) goto hosed; 938 VG_(env_remove_valgrind_env_stuff)( envp ); 939 } 940 941 if (trace_this_child) { 942 // Set VALGRIND_LIB in ARG3 (the environment) 943 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir)); 944 } 945 946 // Set up the child's args. If not tracing it, they are 947 // simply ARG2. Otherwise, they are 948 // 949 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..] 950 // 951 // except that the first VG_(args_for_valgrind_noexecpass) args 952 // are omitted. 953 // 954 if (!trace_this_child) { 955 argv = (Char**)ARG2; 956 } else { 957 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 ); 958 vg_assert( VG_(args_for_valgrind_noexecpass) 959 <= VG_(sizeXA)( VG_(args_for_valgrind) ) ); 960 /* how many args in total will there be? */ 961 // launcher basename 962 tot_args = 1; 963 // V's args 964 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) ); 965 tot_args -= VG_(args_for_valgrind_noexecpass); 966 // name of client exe 967 tot_args++; 968 // args for client exe, skipping [0] 969 arg2copy = (Char**)ARG2; 970 if (arg2copy && arg2copy[0]) { 971 for (i = 1; arg2copy[i]; i++) 972 tot_args++; 973 } 974 // allocate 975 argv = VG_(malloc)( "syswrap-aix5.pre_sys_execve.1", 976 (tot_args+1) * sizeof(HChar*) ); 977 if (argv == 0) goto hosed; 978 // copy 979 j = 0; 980 argv[j++] = launcher_basename; 981 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) { 982 if (i < VG_(args_for_valgrind_noexecpass)) 983 continue; 984 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ); 985 } 986 argv[j++] = (Char*)ARG1; 987 if (arg2copy && arg2copy[0]) 988 for (i = 1; arg2copy[i]; i++) 989 argv[j++] = arg2copy[i]; 990 argv[j++] = NULL; 991 // check 992 vg_assert(j == tot_args+1); 993 } 994 995 /* restore the DATA rlimit for the child */ 996 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data)); 997 998 /* 999 Set the signal state up for exec. 1000 1001 We need to set the real signal state to make sure the exec'd 1002 process gets SIG_IGN properly. 1003 1004 Also set our real sigmask to match the client's sigmask so that 1005 the exec'd child will get the right mask. First we need to 1006 clear out any pending signals so they they don't get delivered, 1007 which would confuse things. 1008 1009 XXX This is a bug - the signals should remain pending, and be 1010 delivered to the new process after exec. There's also a 1011 race-condition, since if someone delivers us a signal between 1012 the sigprocmask and the execve, we'll still get the signal. Oh 1013 well. 1014 */ 1015 { 1016 vki_sigset_t allsigs; 1017 vki_siginfo_t info; 1018 1019 for (i = 1; i < VG_(max_signal); i++) { 1020 struct vki_sigaction sa; 1021 VG_(do_sys_sigaction)(i, NULL, &sa); 1022 if (sa.ksa_handler == VKI_SIG_IGN) 1023 VG_(sigaction)(i, &sa, NULL); 1024 else { 1025 sa.ksa_handler = VKI_SIG_DFL; 1026 VG_(sigaction)(i, &sa, NULL); 1027 } 1028 } 1029 1030 VG_(sigfillset)(&allsigs); 1031 while(VG_(sigtimedwait_zero)(&allsigs, &info) > 0) 1032 ; 1033 1034 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL); 1035 } 1036 1037 if (0) { 1038 Char **cpp; 1039 VG_(printf)("exec: %s\n", path); 1040 for (cpp = argv; cpp && *cpp; cpp++) 1041 VG_(printf)("argv: %s\n", *cpp); 1042 if (0) 1043 for (cpp = envp; cpp && *cpp; cpp++) 1044 VG_(printf)("env: %s\n", *cpp); 1045 } 1046 1047 SET_STATUS_from_SysRes( 1048 VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp) 1049 ); 1050 1051 /* If we got here, then the execve failed. We've already made way 1052 too much of a mess to continue, so we have to abort. */ 1053 hosed: 1054 vg_assert(FAILURE); 1055 VG_(message)(Vg_UserMsg, "execve(%#lx(%s), %#lx, %#lx) failed, errno %ld\n", 1056 ARG1, (Char*)ARG1, ARG2, ARG3, ERR); 1057 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from " 1058 "execve() failing, so I'm dying.\n"); 1059 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), " 1060 "or work out how to recover.\n"); 1061 VG_(exit)(101); 1062} 1063 1064PRE(sys_finfo) 1065{ 1066 PRINT("finfo ( %#lx(%s), %ld, %#lx, %ld )", 1067 ARG1,(Char*)ARG1, ARG2, ARG3, ARG4); 1068 PRE_REG_READ4(int, "finfo", 1069 char*, Path1, int, cmd, void*, buffer, int, length); 1070 PRE_MEM_RASCIIZ( "finfo(Path1)", ARG1 ); 1071 PRE_MEM_WRITE( "finfo(buffer)", ARG3, ARG4 ); 1072} 1073POST(sys_finfo) 1074{ 1075 POST_MEM_WRITE( ARG3, ARG4 ); 1076} 1077 1078PRE(sys_fstatfs) 1079{ 1080 PRINT("sys_fstatfs ( %ld, %#lx )", ARG1, ARG2); 1081 PRE_REG_READ2(UWord, "fstatfs", UWord, fd, struct statfs *, buf); 1082 PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct statfs) ); 1083} 1084POST(sys_fstatfs) 1085{ 1086 POST_MEM_WRITE( ARG2, sizeof(struct statfs) ); 1087} 1088 1089PRE(sys_fstatx) 1090{ 1091 PRINT("fstatx ( %ld, %#lx, %ld, %ld )", ARG1, ARG2, ARG3, ARG4 ); 1092 PRE_REG_READ4(Word, "fstatx", UWord, fd, void*, buf, 1093 UWord, len, UWord, cmd); 1094 PRE_MEM_WRITE( "fstatx(buf)", ARG2, ARG3 ); 1095} 1096POST(sys_fstatx) 1097{ 1098 POST_MEM_WRITE( ARG2, ARG3 ); 1099} 1100 1101PRE(sys_fsync) 1102{ 1103 PRINT("fsync ( %ld )", ARG1); 1104 PRE_REG_READ1(int, "fsync", int, fd); 1105} 1106 1107PRE(sys_getdirent) 1108{ 1109 *flags |= SfMayBlock; 1110 /* this is pretty much like 'read': 1111 getdirent(fd, buffer, nbytes) -> # actually read */ 1112 PRINT("getdirent ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 1113 PRE_REG_READ3(Word, "getdirent", UWord, fd, UChar*, buf, UWord, count); 1114 PRE_MEM_WRITE( "getdirent(buf)", ARG2, ARG3 ); 1115} 1116POST(sys_getdirent) 1117{ 1118 vg_assert(SUCCESS); 1119 POST_MEM_WRITE( ARG2, RES ); 1120} 1121 1122PRE(sys_getdirent64) 1123{ 1124 /* same as getdirent, from our point of view? */ 1125 *flags |= SfMayBlock; 1126 /* this is pretty much like 'read': 1127 getdirent(fd, buffer, nbytes) -> # actually read */ 1128 PRINT("getdirent64 ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 1129 PRE_REG_READ3(Word, "getdirent64", UWord, fd, UChar*, buf, UWord, count); 1130 PRE_MEM_WRITE( "getdirent64(buf)", ARG2, ARG3 ); 1131} 1132POST(sys_getdirent64) 1133{ 1134 vg_assert(SUCCESS); 1135 POST_MEM_WRITE( ARG2, RES ); 1136} 1137 1138PRE(sys_getdomainname) 1139{ 1140 PRINT("getdomainname ( %#lx, %ld )", ARG1, ARG2 ); 1141 PRE_MEM_WRITE( "getdomainname(buf)", ARG1, ARG2 ); 1142} 1143POST(sys_getdomainname) 1144{ 1145 POST_MEM_WRITE( ARG1, ARG2 ); 1146} 1147 1148PRE(sys_getgidx) 1149{ 1150 PRINT("getgidx ( %ld )", ARG1); 1151 PRE_REG_READ1(UInt, "getgidx", long, arg1); 1152} 1153 1154PRE(sys_getgroups) 1155{ 1156 PRINT("getgroups ( %ld, %#lx )", ARG1, ARG2); 1157 PRE_REG_READ2(long, "getgroups", int, size, gid_t *, list); 1158 if (ARG1 > 0) 1159 PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(gid_t) ); 1160} 1161POST(sys_getgroups) 1162{ 1163 vg_assert(SUCCESS); 1164 if (ARG1 > 0 && RES > 0) 1165 POST_MEM_WRITE( ARG2, RES * sizeof(gid_t) ); 1166} 1167 1168PRE(sys_gethostname) 1169{ 1170 PRINT("gethostname ( %#lx, %ld )", ARG1, ARG2); 1171 PRE_MEM_WRITE( "gethostname(buf)", ARG1, ARG2 ); 1172} 1173POST(sys_gethostname) 1174{ 1175 POST_MEM_WRITE( ARG1, ARG2 ); 1176} 1177 1178PRE(sys_getpriv) 1179{ 1180 PRINT("getpriv (UNDOCUMENTED)(%ld, %#lx, %ld)", ARG1, ARG2, ARG3); 1181 PRE_REG_READ3(int, "getpriv", int, arg1, void*, arg2, int, arg3); 1182 PRE_MEM_WRITE( "getpriv(arg2)", ARG2, 8 ); 1183} 1184POST(sys_getpriv) 1185{ 1186 if (ARG2) 1187 POST_MEM_WRITE(ARG2, 8); 1188} 1189 1190/* Note that this is used for both sys_getprocs and sys_getprocs64. I 1191 think that's correct - from the man page, the calling conventions 1192 look identical. */ 1193PRE(sys_getprocs) 1194{ 1195 PRINT("getprocs ( %#lx, %ld, %#lx, %ld, %#lx, %ld )", 1196 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); 1197 PRE_REG_READ6(int, "getprocs", 1198 void*, processbuffer, long, processize, 1199 void*, filebuffer, long, filesize, 1200 void*, indexpointer, long, count); 1201 1202 /* (processbuffer, processsize, filebuffer, filesize, 1203 indexpointer, count) */ 1204 PRE_MEM_READ( "getprocs(IndexPointer)", ARG5, sizeof(UInt) ); 1205 if (ARG1) 1206 PRE_MEM_WRITE( "getprocs(ProcessBuffer)", ARG1, ARG2 * ARG6 ); 1207 if (ARG3) 1208 PRE_MEM_WRITE( "getprocs(FileBuffer)", ARG3, ARG4 * ARG6 ); 1209} 1210POST(sys_getprocs) 1211{ 1212 vg_assert(SUCCESS); 1213 if (ARG1) 1214 POST_MEM_WRITE( ARG1, ARG2 * ARG6 ); 1215 if (ARG3) 1216 POST_MEM_WRITE( ARG3, ARG4 * ARG6 ); 1217} 1218 1219PRE(sys_getrpid) 1220{ 1221 PRINT("getrpid ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); 1222 PRE_REG_READ3(long, "getrpid", long, arg1, long, arg2, long, arg3); 1223} 1224 1225PRE(sys_getsockopt) 1226{ 1227 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )", 1228 ARG1, ARG2, ARG3, ARG4, ARG5); 1229 PRE_REG_READ5(int, "getsockopt", int, socket, int, level, 1230 int, optionname, 1231 void*, optionval, int*, optionlen); 1232 if (ARG5) { 1233 PRE_MEM_READ( "getsockopt(optionlen)", ARG5, sizeof(UInt) ); 1234 PRE_MEM_WRITE( "getsockopt(optionval)", ARG4, *(UInt*)ARG5 ); 1235 } 1236} 1237POST(sys_getsockopt) 1238{ 1239 if (ARG5) { 1240 POST_MEM_WRITE( ARG5, sizeof(UInt) ); 1241 POST_MEM_WRITE( ARG4, *(UInt*)ARG5 ); 1242 } 1243} 1244 1245PRE(sys_gettimerid) 1246{ 1247 PRINT("gettimerid ( %ld, %ld )", ARG1, ARG2); 1248 PRE_REG_READ2(int, "gettimerid", int, timertype, int, notifytype); 1249} 1250 1251PRE(sys_getuidx) 1252{ 1253 PRINT("getuidx ( %ld )", ARG1); 1254 PRE_REG_READ1(UInt, "getuidx", UInt, arg1); 1255} 1256 1257PRE(sys_incinterval) 1258{ 1259 PRINT("incinterval ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 1260 PRE_REG_READ3(int, "incinterval", int, timerid, 1261 struct itimerstruc_t*, value, 1262 struct itimerstruc_t*, ovalue); 1263 if (ARG2) 1264 PRE_MEM_READ( "incinterval(value)", 1265 ARG2, sizeof(struct itimerstruc_t)); 1266 if (ARG3) 1267 PRE_MEM_WRITE( "incinterval(value)", 1268 ARG3, sizeof(struct itimerstruc_t)); 1269} 1270POST(sys_incinterval) 1271{ 1272 if (ARG3) 1273 POST_MEM_WRITE( ARG3, sizeof(struct itimerstruc_t)); 1274} 1275 1276PRE(sys_kfcntl) 1277{ 1278 *flags |= SfMayBlock; 1279 switch (ARG2) { 1280 // These ones ignore ARG3. 1281 case F_GETFD: 1282 case F_GETFL: 1283 case F_GETOWN: 1284 PRINT("kfcntl ( %ld, %ld )", ARG1,ARG2); 1285 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); 1286 break; 1287 1288 // These ones use ARG3 as "arg". 1289 case F_DUPFD: 1290 case F_SETFD: 1291 case F_SETFL: 1292 case F_SETOWN: 1293 PRINT("kfcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); 1294 PRE_REG_READ3(long, "fcntl", 1295 unsigned int, fd, unsigned int, cmd, unsigned long, arg); 1296 break; 1297 1298 // These ones use ARG3 as "lock". 1299# if !defined(VGP_ppc64_aix5) 1300 case F_GETLK: 1301 case F_SETLK: 1302 case F_SETLKW: 1303# endif 1304 case F_GETLK64: 1305 case F_SETLK64: 1306 case F_SETLKW64: 1307 PRINT("kfcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); 1308 PRE_REG_READ3(long, "fcntl", 1309 unsigned int, fd, unsigned int, cmd, 1310 struct flock64 *, lock); 1311 if (ARG3 && (ARG2 == F_GETLK || ARG2 == F_GETLK64)) 1312 PRE_MEM_READ( "kfcntl(F_GETLK)", ARG3, sizeof(struct flock64) ); 1313 break; 1314 } 1315} 1316POST(sys_kfcntl) 1317{ 1318 // if (ARG2 == VKI_F_DUPFD) { 1319 // if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { 1320 // VG_(close)(RES); 1321 // SET_STATUS_Failure( VKI_EMFILE ); 1322 // } else { 1323 // if (VG_(clo_track_fds)) 1324 // record_fd_open_named(tid, RES); 1325 // } 1326 // } 1327 if (ARG3 && (ARG2 == F_GETLK || ARG2 == F_GETLK64)) 1328 POST_MEM_WRITE( ARG3, sizeof(struct flock64) ); 1329} 1330 1331/* COG; can this be moved inside the pre-handler? */ 1332static vki_sigset_t fork_saved_mask; 1333PRE(sys_kfork) /* COPY OF GENERIC */ 1334{ 1335 vki_sigset_t mask; 1336 1337 PRINT("kfork ( )"); 1338 PRE_REG_READ0(long, "fork"); 1339 1340 /* Block all signals during fork, so that we can fix things up in 1341 the child without being interrupted. */ 1342 VG_(sigfillset)(&mask); 1343 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask); 1344 1345 VG_(do_atfork_pre)(tid); 1346 1347 SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) ); 1348 1349 if (SUCCESS && RES == 0) { 1350 /* child */ 1351 VG_(do_atfork_child)(tid); 1352 1353 /* restore signal mask */ 1354 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); 1355 1356 /* If --child-silent-after-fork=yes was specified, set the 1357 logging file descriptor to an 'impossible' value. This is 1358 noticed by send_bytes_to_logging_sink in m_libcprint.c, which 1359 duly stops writing any further logging output. */ 1360 if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork)) 1361 VG_(clo_log_fd) = -1; 1362 } 1363 else 1364 if (SUCCESS && RES > 0) { 1365 /* parent */ 1366 VG_(do_atfork_parent)(tid); 1367 1368 PRINT(" fork: process %d created child %lu\n", VG_(getpid)(), RES); 1369 1370 /* restore signal mask */ 1371 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); 1372 } 1373} 1374 1375PRE(sys_kftruncate) 1376{ 1377 PRINT("kftruncate (BOGUS HANDLER)"); 1378} 1379 1380PRE(sys_kgetsidx) 1381{ 1382 PRINT("kgetsidx ( %ld )", ARG1); 1383 PRE_REG_READ1(Word, "kgetsidx", Word, arg1); 1384} 1385 1386PRE(sys_kill) 1387{ 1388 PRINT("kill ( %ld, %ld )", ARG1, ARG2); 1389 PRE_REG_READ2(int, "kill", int, pid, int, signal); 1390} 1391 1392PRE(sys_kioctl) 1393{ 1394 *flags |= SfMayBlock; 1395 PRINT("kioctl ( %ld, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3, ARG4); 1396 PRE_REG_READ4(Word, "ioctl", Word, fd, 1397 Word, command, Word, arg, Word, ext); 1398 switch (ARG2 /* request */) { 1399 case 0x5800/*TXISATTY*/: 1400 case 0x5801/*TXTTYNAME*/: 1401 break; 1402 case 0x412:/*no idea what any of these are*/ 1403 case 0x430: 1404 case 0x431: 1405 case 0x432: 1406 case 0x441: 1407 case 0x442: 1408 case 0x462: 1409 case 0x480: 1410 case 0x482: 1411 case 0x738: 1412 case 0x736: 1413 case 0x73B: 1414 case 0x73C: 1415 case 0x73D: 1416 case 0x73E: 1417 case 0x5401: 1418 case 0x5403: 1419 case 0xFF01/*no_idea_at_all_what_this_is*/: 1420 break; 1421 /* We don't have any specific information on it, so 1422 try to do something reasonable based on direction and 1423 size bits. 1424 1425 According to Simon Hausmann, _IOC_READ means the kernel 1426 writes a value to the ioctl value passed from the user 1427 space and the other way around with _IOC_WRITE. */ 1428 default: { 1429 UInt dir = _VKI_IOC_DIR(ARG2); 1430 UInt size = _VKI_IOC_SIZE(ARG2); 1431 if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) { 1432 /* 1433 * Be very lax about ioctl handling; the only 1434 * assumption is that the size is correct. Doesn't 1435 * require the full buffer to be initialized when 1436 * writing. Without this, using some device 1437 * drivers with a large number of strange ioctl 1438 * commands becomes very tiresome. 1439 */ 1440 } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) { 1441 static Int moans = 5; 1442 if (moans > 0 && !VG_(clo_xml)) { 1443 moans--; 1444 VG_(message)(Vg_UserMsg, 1445 "Warning: noted but unhandled ioctl 0x%lx" 1446 " with no size/direction hints\n", 1447 ARG2); 1448 VG_(message)(Vg_UserMsg, 1449 " This could cause spurious value errors" 1450 " to appear.\n"); 1451 VG_(message)(Vg_UserMsg, 1452 " See README_MISSING_SYSCALL_OR_IOCTL for " 1453 "guidance on writing a proper wrapper.\n" ); 1454 } 1455 } else { 1456 if ((dir & _VKI_IOC_WRITE) && size > 0) 1457 PRE_MEM_READ( "ioctl(generic)", ARG3, size); 1458 if ((dir & _VKI_IOC_READ) && size > 0) 1459 PRE_MEM_WRITE( "ioctl(generic)", ARG3, size); 1460 } 1461 break; 1462 } 1463 } /* switch */ 1464} 1465POST(sys_kioctl) 1466{ 1467 switch (ARG2 /*request*/) { 1468 case 0xFF01: 1469 /* 100% kludge. I have no idea what this ioctl is. IOCINFO 1470 ? But at a guess I'd say it returns some kind of info 1471 from the kernel. */ 1472 if (ARG3) POST_MEM_WRITE(ARG3, 16); 1473 break; 1474 case 0x738: /* Shows up in MPI applications. */ 1475 if (ARG3) POST_MEM_WRITE(ARG3, 4*sizeof(Word)); 1476 break; 1477 case 0x736: /* Shows up in MPI applications. */ 1478 case 0x73B: /* Shows up in MPI applications. */ 1479 case 0x73C: /* Shows up in MPI applications. */ 1480 if (ARG3) POST_MEM_WRITE(ARG3, 16); 1481 /* in fact only 4 needed, but being conservative */ 1482 break; 1483 1484 case 0x5401: 1485 /* some kind of tty thing */ 1486 if (ARG3) POST_MEM_WRITE(ARG3, 32); 1487 break; 1488 1489 case 0x5801/*TXTTYNAME*/: 1490 /* who knows if this is right. Presumably an ascii string is 1491 written into the buffer specified by ARG3, but how long is 1492 that buffer? */ 1493 if (ARG3) POST_MEM_WRITE(ARG3, 16); 1494 break; 1495 1496 case 0x412: 1497 case 0x430: 1498 case 0x431: 1499 case 0x432: 1500 case 0x441: 1501 case 0x442: 1502 case 0x462: 1503 case 0x480: 1504 case 0x482: 1505 case 0x73D: 1506 case 0x73E: 1507 case 0x5800/*TXISATTY*/: 1508 case 0x5403: 1509 break; 1510 /* We don't have any specific information on it, so 1511 try to do something reasonable based on direction and 1512 size bits. 1513 1514 According to Simon Hausmann, _IOC_READ means the kernel 1515 writes a value to the ioctl value passed from the user 1516 space and the other way around with _IOC_WRITE. */ 1517 default: { 1518 UInt dir = _VKI_IOC_DIR(ARG2); 1519 UInt size = _VKI_IOC_SIZE(ARG2); 1520 if (size > 0 && (dir & _VKI_IOC_READ) 1521 && RES == 0 1522 && ARG3 != (Addr)NULL) 1523 POST_MEM_WRITE(ARG3, size); 1524 break; 1525 } 1526 } 1527} 1528 1529PRE(sys_klseek) 1530{ 1531 PRINT("klseek ( %ld, %ld, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); 1532 PRE_REG_READ4(long, "klseek", 1533 long, fd, long, offset, long, whence, void*, arg4); 1534 /* XXX: looks like 4th arg is a pointer to something. Is it 1535 read or written by the kernel? */ 1536} 1537 1538PRE(sys_knlist) 1539{ 1540 PRINT("knlist (BOGUS HANDLER)"); 1541} 1542 1543PRE(sys_kpread) 1544{ 1545 *flags |= SfMayBlock; 1546 PRINT("sys_kpread ( %ld, %#lx, %llu, %lld )", 1547 ARG1, ARG2, (ULong)ARG3, (ULong)ARG4); 1548 PRE_REG_READ4(ssize_t, "kpread", 1549 unsigned int, fd, char *, buf, 1550 vki_size_t, count, long, offset); 1551 PRE_MEM_WRITE( "kpread(buf)", ARG2, ARG3 ); 1552} 1553POST(sys_kpread) 1554{ 1555 vg_assert(SUCCESS); 1556 if (RES > 0) { 1557 POST_MEM_WRITE( ARG2, RES ); 1558 } 1559} 1560 1561PRE(sys_kread) 1562{ 1563 *flags |= SfMayBlock; 1564 PRINT("sys_read ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3); 1565 PRE_REG_READ3(ssize_t, "read", 1566 unsigned int, fd, char *, buf, vki_size_t, count); 1567 //zz if (!ML_(fd_allowed)(ARG1, "read", tid, False)) 1568 //zz SET_STATUS_Failure( VKI_EBADF ); 1569 //zz else 1570 PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); 1571} 1572POST(sys_kread) 1573{ 1574 vg_assert(SUCCESS); 1575 POST_MEM_WRITE( ARG2, RES ); 1576} 1577 1578PRE(sys_kreadv) 1579{ 1580 Int i; 1581 struct vki_iovec * vec; 1582 *flags |= SfMayBlock; 1583 /* ssize_t readvx ( int fd, struct iovec*, int iovCount, int extension ) */ 1584 PRINT("kreadv ( %ld, %#lx, %ld, %#lx )", ARG1, ARG2, ARG3, ARG4); 1585 PRE_REG_READ4(ssize_t, "kreadv", 1586 unsigned long, fd, const struct iovec *, vector, 1587 unsigned long, iovCount, unsigned long, extension); 1588 //zz if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) { 1589 //zz SET_STATUS_Failure( VKI_EBADF ); 1590 //zz } else { 1591 PRE_MEM_READ( "kreadv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) ); 1592 if (ARG2 != 0) { 1593 /* ToDo: don't do any of the following if the vector is invalid */ 1594 vec = (struct vki_iovec *)ARG2; 1595 for (i = 0; i < (Int)ARG3; i++) 1596 PRE_MEM_WRITE( "kreadv(vector[...])", 1597 (Addr)vec[i].iov_base, vec[i].iov_len ); 1598 } 1599 //zz } 1600} 1601POST(sys_kreadv) 1602{ 1603 vg_assert(SUCCESS); 1604 if (RES > 0) { 1605 Int i; 1606 struct vki_iovec * vec = (struct vki_iovec *)ARG2; 1607 Int remains = RES; 1608 1609 /* RES holds the number of bytes read. */ 1610 for (i = 0; i < (Int)ARG3; i++) { 1611 Int nReadThisBuf = vec[i].iov_len; 1612 if (nReadThisBuf > remains) nReadThisBuf = remains; 1613 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf ); 1614 remains -= nReadThisBuf; 1615 if (remains < 0) VG_(core_panic)("readv: remains < 0"); 1616 } 1617 } 1618} 1619 1620PRE(sys_kthread_ctl) 1621{ 1622 *flags |= SfMayBlock; 1623 PRINT("kthread_ctl (BOGUS HANDLER)"); 1624} 1625 1626PRE(sys_ktruncate) 1627{ 1628 PRINT("ktruncate( %#lx(%s), %lx, %lx )", ARG1,(Char*)ARG1, ARG2, ARG3 ); 1629 PRE_REG_READ3(int, "ktruncate", char*, path, long, arg2, long, arg3 ); 1630 PRE_MEM_RASCIIZ( "ktruncate(path)", ARG1 ); 1631} 1632 1633PRE(sys_kwaitpid) 1634{ 1635 /* Note: args 1 and 2 (status, pid) opposite way round 1636 from generic handler */ 1637 *flags |= SfMayBlock; 1638 PRINT("kwaitpid ( %#lx, %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); 1639 PRE_REG_READ3(long, "waitpid", 1640 unsigned int *, status, int, pid, int, options); 1641 1642 if (ARG1 != (Addr)NULL) 1643 PRE_MEM_WRITE( "kwaitpid(status)", ARG1, sizeof(int) ); 1644} 1645POST(sys_kwaitpid) 1646{ 1647 if (ARG1 != (Addr)NULL) 1648 POST_MEM_WRITE( ARG1, sizeof(int) ); 1649} 1650 1651PRE(sys_kwrite) 1652{ 1653 //zz Bool ok; 1654 *flags |= SfMayBlock; 1655 PRINT("sys_kwrite ( %ld, %#lx, %llu )", ARG1, ARG2, (ULong)ARG3); 1656 PRE_REG_READ3(ssize_t, "kwrite", 1657 unsigned int, fd, const char *, buf, vki_size_t, count); 1658 /* check to see if it is allowed. If not, try for an exemption from 1659 --sim-hints=enable-outer (used for self hosting). */ 1660 //zz ok = ML_(fd_allowed)(ARG1, "write", tid, False); 1661 //zz if (!ok && ARG1 == 2/*stderr*/ 1662 //zz && VG_(strstr)(VG_(clo_sim_hints),"enable-outer")) 1663 //zz ok = True; 1664 //zz if (!ok) 1665 //zz SET_STATUS_Failure( VKI_EBADF ); 1666 //zz else 1667 PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); 1668} 1669 1670PRE(sys_kwritev) 1671{ 1672 PRINT("kwritev (BOGUS HANDLER)"); 1673} 1674 1675PRE(sys_listen) 1676{ 1677 PRINT("listen (BOGUS HANDLER)"); 1678} 1679 1680PRE(sys_loadbind) 1681{ 1682 PRINT("loadbind( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 1683 PRE_REG_READ3(int, "loadbind", int, flag, 1684 void*, ExportPointer, void*, ImportPointer); 1685} 1686 1687PRE(sys_loadquery) 1688{ 1689 /* loadquery ( int flags, void* buffer, unsigned int bufferlength ) */ 1690 PRINT("loadquery ( %#lx, %#lx, %ld )", ARG1, ARG2, ARG3); 1691 PRE_MEM_WRITE( "loadquery(buf)", ARG2, ARG3 ); 1692} 1693POST(sys_loadquery) 1694{ 1695 vg_assert(SUCCESS); 1696 POST_MEM_WRITE( ARG2, ARG3 ); 1697} 1698 1699PRE(sys_lseek) 1700{ 1701 PRINT("lseek (%ld, %ld, %ld)", ARG1, ARG2, ARG3); 1702 PRE_REG_READ3(long, "lseek", long, fd, long, offset, long, whence); 1703} 1704 1705PRE(sys_mkdir) 1706{ 1707 PRINT("mkdir (%#lx(%s), %#lx)", ARG1,(Char*)ARG1, ARG2); 1708 PRE_REG_READ2(int, "mkdir", char*, path, int, mode); 1709 PRE_MEM_RASCIIZ( "mkdir(path)", ARG1 ); 1710} 1711 1712PRE(sys_mmap) 1713{ 1714 PRINT("mmap ( %#lx, %ld, %#lx, %#lx, %ld, %ld )", 1715 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); 1716 PRE_REG_READ6(void*, "mmap", void*, addr, int, len, 1717 int, prot, int, flags, int, fd, int, off); 1718} 1719POST(sys_mmap) 1720{ 1721 vg_assert(SUCCESS); 1722 Addr addr = (Addr)RES; 1723 UWord len = (UWord)ARG2; 1724 UWord prot = (UWord)ARG3; 1725 UWord flags = (UWord)ARG4; 1726 Bool r = (prot & VKI_PROT_READ) > 0; 1727 Bool w = (prot & VKI_PROT_WRITE) > 0; 1728 Bool x = (prot & VKI_PROT_EXEC) > 0; 1729 VG_TRACK( new_mem_mmap, addr, len, r,w,x, 0/*di_handle*/ ); 1730 Bool d = VG_(am_notify_client_mmap)( addr, len, prot, flags, 1731 0/*fake fd*/, 0/*fake offset*/); 1732 if (d) 1733 VG_(discard_translations)( addr, len, "POST(sys_mmap)" ); 1734} 1735 1736PRE(sys_mntctl) 1737{ 1738 PRINT("mntctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 ); 1739 PRE_REG_READ3(long, "mntctl", long, command, long, size, char*, buffer); 1740 PRE_MEM_WRITE( "mntctl(buffer)", ARG3, ARG2 ); 1741} 1742POST(sys_mntctl) 1743{ 1744 vg_assert(SUCCESS); 1745 if (RES == 0) { 1746 /* Buffer too small. First word is the real required size. */ 1747 POST_MEM_WRITE( ARG3, sizeof(Word) ); 1748 } else { 1749 /* RES is the number of struct vmount's written to the buf. But 1750 these are variable length and to find the end would require 1751 inspecting each in turn. So be simple and just mark the 1752 entire buffer as defined. */ 1753 POST_MEM_WRITE( ARG3, ARG2 ); 1754 } 1755} 1756 1757PRE(sys_mprotect) 1758{ 1759 PRINT("mprotect (BOGUS HANDLER)( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3); 1760 PRE_REG_READ3(int, "mprotect", void*, addr, long, len, long, prot); 1761} 1762POST(sys_mprotect) 1763{ 1764 Bool d; 1765 vg_assert(SUCCESS); 1766 Addr addr = ARG1; 1767 UWord len = ARG2; 1768 UWord prot = ARG3; 1769 d = VG_(am_notify_mprotect)( addr, len, prot ); 1770 if (d) 1771 VG_(discard_translations)( addr, len, "POST(sys_mprotect)" ); 1772} 1773 1774PRE(sys_munmap) 1775{ 1776 PRINT("munmap ( %#lx, %ld )", ARG1, ARG2); 1777 PRE_REG_READ2(int, "munmap", void*, addr, long, len); 1778} 1779POST(sys_munmap) 1780{ 1781 Bool d; 1782 vg_assert(SUCCESS); 1783 Addr addr = ARG1; 1784 UWord len = ARG2; 1785 VG_TRACK( die_mem_munmap, addr, len ); 1786 d = VG_(am_notify_munmap)( addr, len ); 1787 if (d) 1788 VG_(discard_translations)( addr, len, "POST(sys_munmap)" ); 1789} 1790 1791PRE(sys_naccept) 1792{ 1793 PRINT("naccept (%ld, %#lx, %#lx)", ARG1, ARG2, ARG3); 1794 PRE_REG_READ3(int, "naccept", int, socket, char*, addr, int*, addrlen); 1795 PRE_MEM_READ( "naccept(addrlen)", ARG3, sizeof(UInt) ); 1796 PRE_MEM_WRITE( "naccept(addr)", ARG2, *(UInt*)ARG3 ); 1797} 1798POST(sys_naccept) 1799{ 1800 POST_MEM_WRITE( ARG3, sizeof(UInt) ); 1801 POST_MEM_WRITE( ARG2, *(UInt*)ARG3 ); 1802} 1803 1804PRE(sys_ngetpeername) 1805{ 1806 PRINT("ngetpeername ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 1807 PRE_REG_READ3(int, "ngetpeername", int, fd, char*, name, int*, namelen); 1808 PRE_MEM_READ( "ngetpeername(namelen)", ARG3, sizeof(UInt) ); 1809 PRE_MEM_WRITE( "ngetpeername(name)", ARG2, *(UInt*)ARG3 ); 1810} 1811POST(sys_ngetpeername) 1812{ 1813 POST_MEM_WRITE( ARG3, sizeof(UInt) ); 1814 POST_MEM_WRITE( ARG2, *(UInt*)ARG3 ); 1815} 1816 1817PRE(sys_ngetsockname) 1818{ 1819 PRINT("ngetsockname ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 1820 PRE_REG_READ3(int, "ngetsockname", int, fd, char*, name, int*, namelen); 1821 PRE_MEM_READ( "ngetsockname(namelen)", ARG3, sizeof(UInt) ); 1822 PRE_MEM_WRITE( "ngetsockname(name)", ARG2, *(UInt*)ARG3 ); 1823} 1824POST(sys_ngetsockname) 1825{ 1826 POST_MEM_WRITE( ARG3, sizeof(UInt) ); 1827 POST_MEM_WRITE( ARG2, *(UInt*)ARG3 ); 1828} 1829 1830PRE(sys_nrecvfrom) 1831{ 1832 *flags |= SfMayBlock; 1833 PRINT("nrecvfrom ( %ld, %#lx, %ld, %ld, %#lx, %#lx )", 1834 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); 1835 PRE_REG_READ6(ssize_t, "nrecvfrom", 1836 int, s, void*, buf, size_t, len, int, flags, 1837 void*, from, UInt*, fromlen); 1838 PRE_MEM_WRITE( "nrecvfrom(buf)", ARG2, ARG3 ); 1839 if (ARG5) { 1840 PRE_MEM_READ( "nrecvfrom(fromlen)", ARG6, sizeof(UInt) ); 1841 PRE_MEM_WRITE( "nrecvfrom(from)", ARG5, *(UInt*)ARG6 ); 1842 } 1843} 1844POST(sys_nrecvfrom) 1845{ 1846 POST_MEM_WRITE( ARG2, RES ); 1847 if (ARG5) { 1848 POST_MEM_WRITE(ARG6, sizeof(UInt)); 1849 POST_MEM_WRITE(ARG5, *(UInt*)ARG6); 1850 } 1851} 1852 1853PRE(sys_nrecvmsg) 1854{ 1855 *flags |= SfMayBlock; 1856 PRINT("nrecvmsg(BOGUS HANDLER)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 1857 PRE_REG_READ3(long, "nrecvmsg", long, arg1, void*, arg2, long, arg3); 1858} 1859 1860PRE(sys_nsendmsg) 1861{ 1862 *flags |= SfMayBlock; 1863 PRINT("nsendmsg(BOGUS HANDLER)( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 1864} 1865 1866PRE(sys_open) /* XXX CoG */ 1867{ 1868 //zz HChar name[30]; 1869 //zz SysRes sres; 1870 1871 if (ARG2 & VKI_O_CREAT) { 1872 // 3-arg version 1873 PRINT("sys_open ( %#lx(%s), %#lx, %ld )",ARG1,(Char*)ARG1,ARG2,ARG3); 1874 PRE_REG_READ3(long, "open", 1875 const char *, filename, int, flags, int, mode); 1876 } else { 1877 // 2-arg version 1878 PRINT("sys_open ( %#lx(%s), %#lx )",ARG1,(Char*)ARG1,ARG2); 1879 PRE_REG_READ2(long, "open", 1880 const char *, filename, int, flags); 1881 } 1882 PRE_MEM_RASCIIZ( "open(filename)", ARG1 ); 1883 1884 //zz /* Handle the case where the open is of /proc/self/cmdline or 1885 //zz /proc/<pid>/cmdline, and just give it a copy of the fd for the 1886 //zz fake file we cooked up at startup (in m_main). Also, seek the 1887 //zz cloned fd back to the start. */ 1888 //zz 1889 //zz VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); 1890 //zz if (ML_(safe_to_deref)( (void*)ARG1, 1 ) 1891 //zz && (VG_(strcmp)((Char *)ARG1, name) == 0 1892 //zz || VG_(strcmp)((Char *)ARG1, "/proc/self/cmdline") == 0)) { 1893 //zz sres = VG_(dup)( VG_(cl_cmdline_fd) ); 1894 //zz SET_STATUS_from_SysRes( sres ); 1895 //zz if (!sres.isError) { 1896 //zz OffT off = VG_(lseek)( sres.res, 0, VKI_SEEK_SET ); 1897 //zz if (off < 0) 1898 //zz SET_STATUS_Failure( VKI_EMFILE ); 1899 //zz } 1900 //zz return; 1901 //zz } 1902 1903 /* Otherwise handle normally */ 1904 *flags |= SfMayBlock; 1905} 1906POST(sys_open) 1907{ 1908 vg_assert(SUCCESS); 1909 //zz if (!ML_(fd_allowed)(RES, "open", tid, True)) { 1910 //zz VG_(close)(RES); 1911 //zz SET_STATUS_Failure( VKI_EMFILE ); 1912 //zz } else { 1913 //zz if (VG_(clo_track_fds)) 1914 //zz ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); 1915 //zz } 1916} 1917 1918PRE(sys_pipe) 1919{ 1920 PRINT("sys_pipe ( %#lx )", ARG1); 1921 PRE_REG_READ1(int, "pipe", int *, filedes); 1922 PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) ); 1923} 1924POST(sys_pipe) 1925{ 1926 //zz Int *p = (Int *)ARG1; 1927 1928 //zz if (!ML_(fd_allowed)(p[0], "pipe", tid, True) || 1929 //zz !ML_(fd_allowed)(p[1], "pipe", tid, True)) { 1930 //zz VG_(close)(p[0]); 1931 //zz VG_(close)(p[1]); 1932 //zz SET_STATUS_Failure( VKI_EMFILE ); 1933 //zz } else { 1934 POST_MEM_WRITE( ARG1, 2*sizeof(int) ); 1935 //zz if (VG_(clo_track_fds)) { 1936 //zz ML_(record_fd_open_nameless)(tid, p[0]); 1937 //zz ML_(record_fd_open_nameless)(tid, p[1]); 1938 //zz } 1939 //zz } 1940} 1941 1942PRE(sys_privcheck) 1943{ 1944 PRINT("privcheck ( %ld )", ARG1); 1945 PRE_REG_READ1(int, "privcheck", int, arg1); 1946} 1947 1948PRE(sys_readlink) 1949{ 1950 PRINT("readlink ( 0x%lx(%s),0x%lx,%ld )", ARG1,(Char*)ARG1, ARG2, ARG3); 1951 PRE_REG_READ3(long, "readlink", 1952 const char *, path, char *, buf, int, bufsiz); 1953 PRE_MEM_RASCIIZ( "readlink(path)", ARG1 ); 1954 PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 ); 1955} 1956POST(sys_readlink) 1957{ 1958 POST_MEM_WRITE( ARG2, RES + 1 ); 1959} 1960 1961PRE(sys_recv) 1962{ 1963 *flags |= SfMayBlock; 1964 PRINT("recv ( %ld, %#lx, %ld, %ld )", 1965 ARG1, ARG2, ARG3, ARG4); 1966 PRE_REG_READ4(int, "recv", int, fd, void*, buf, int, len, int, flags); 1967 PRE_MEM_WRITE( "recv(buf)", ARG2, ARG3); 1968} 1969POST(sys_recv) 1970{ 1971 if (RES > 0) 1972 POST_MEM_WRITE(ARG2, RES); 1973} 1974 1975PRE(sys_rename) 1976{ 1977 *flags |= SfMayBlock; 1978 PRINT( "rename ( %#lx(%s), %#lx(%s) )", ARG1,(Char*)ARG1, ARG2,(Char*)ARG2 ); 1979 PRE_REG_READ2(int, "rename", char*, frompath, char*, topath); 1980 PRE_MEM_RASCIIZ( "rename(frompath)", ARG1 ); 1981 PRE_MEM_RASCIIZ( "rename(topath)", ARG2 ); 1982} 1983 1984PRE(sys_sbrk) 1985{ 1986 PRINT("sbrk (BOGUS HANDLER)( %#lx )", ARG1); 1987 PRE_REG_READ1(long, "sbrk", long, arg1); 1988 /* After a zero sbrk, disallow aspacem from doing sbrk, since libc 1989 might rely on the value returned by this syscall. */ 1990 /* 1 Oct 06: not currently used (aspacemgr-aix5.c ignores it) */ 1991 VG_(am_aix5_sbrk_allowed) = toBool(ARG1 != 0); 1992 /* Disallow libc from moving the brk backwards as that might trash 1993 SkPreAlloc sections acquired by aspacem from previous uses of 1994 sbrk. */ 1995 if (ARG1 < 0) 1996 ARG1 = 0; 1997 /* Do this as a sync syscall, so the sbrk_allowed flag gets turned 1998 back on ASAP. Typically libc does sbrk(0) and then sbrk(x > 0) 1999 in quick succession. Although surely it should hold some kind 2000 of lock at that point, else it cannot safely use the result from 2001 the first sbrk call to influence the second one? */ 2002 *flags &= ~SfMayBlock; 2003} 2004POST(sys_sbrk) 2005{ 2006 vg_assert(SUCCESS); 2007 handle_sbrk(ARG1); 2008} 2009 2010PRE(sys_sched_get_priority_max) 2011{ 2012 PRINT("sched_get_priority_max ( %ld )", ARG1); 2013 PRE_REG_READ1(int, "sched_get_priority_max", int, arg1); 2014} 2015 2016PRE(sys_sem_destroy) 2017{ 2018 PRINT("sem_destroy ( %#lx )", ARG1); 2019 PRE_REG_READ1(int, "sem_destroy", sem_t*, sem); 2020 PRE_MEM_READ( "sem_destroy(sem)", ARG1, sizeof(sem_t) ); 2021} 2022 2023PRE(sys_sem_init) 2024{ 2025 PRINT("sem_init ( %#lx, %ld, %ld )", ARG1, ARG2, ARG3); 2026 PRE_REG_READ3(int, "sem_init", sem_t*, sem, int, pshared, int, value); 2027 PRE_MEM_WRITE( "sem_init(sem)", ARG1, sizeof(sem_t) ); 2028} 2029POST(sys_sem_init) 2030{ 2031 POST_MEM_WRITE( ARG1, sizeof(sem_t) ); 2032} 2033 2034PRE(sys_sem_post) 2035{ 2036 PRINT("sem_post ( %#lx )", ARG1); 2037 PRE_REG_READ1(int, "sem_post", sem_t*, sem); 2038 PRE_MEM_READ("sem_post(sem)", ARG1, sizeof(sem_t)); 2039} 2040POST(sys_sem_post) 2041{ 2042 POST_MEM_WRITE(ARG1, sizeof(sem_t)); 2043} 2044 2045PRE(sys_send) 2046{ 2047 *flags |= SfMayBlock; 2048 PRINT("send (BOGUS HANDLER)( %ld, %#lx, %ld, %ld )", 2049 ARG1, ARG2, ARG3, ARG4); 2050} 2051 2052PRE(sys_setgid) 2053{ 2054 PRINT("setgid ( %ld )", ARG1); 2055 PRE_REG_READ1(void, "setgid", int, uid); 2056} 2057 2058PRE(sys_setsockopt) 2059{ 2060 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )", 2061 ARG1,ARG2,ARG3,ARG4,ARG5 ); 2062 PRE_REG_READ5(long, "setsockopt", 2063 long, socket, long, level, long, optionname, 2064 void*, optionvalue, long, optlen); 2065 if (ARG4) 2066 PRE_MEM_READ( "setsockopt(optionvalue)", ARG4, ARG5 ); 2067} 2068 2069PRE(sys_setuid) 2070{ 2071 PRINT("setuid ( %ld )", ARG1); 2072 PRE_REG_READ1(void, "setuid", int, uid); 2073} 2074 2075static UWord get_shm_size ( Word shmid ) 2076{ 2077 SysRes res; 2078 struct shmid_ds buf; 2079 vg_assert(__NR_AIX5_shmctl != __NR_AIX5_UNKNOWN); 2080 res = VG_(do_syscall3)(__NR_AIX5_shmctl, shmid, IPC_STAT, (UWord)&buf); 2081 if (0) 2082 VG_(printf)("XXX: shm_size(%ld) = %ld %ld\n", shmid, res.res, res.err); 2083 if (res.isError) { 2084 if (0) 2085 VG_(printf)("XXX: shm_size(shmid = %ld): FAILED\n", shmid); 2086 return 0* 4096; 2087 } else { 2088 return buf.shm_segsz; 2089 } 2090 /* fails with 22 and 13 (22 = EINVAL, Invalid argument, 2091 13 = EACCES, Permission denied) */ 2092 /* shmat (4, 0x0, 0x1800) --> Success(0x40000000) 2093 XXX: shm_size(4) = -1 22 2094 shmat: seg size = 0 2095 XXX: shm_size(4) = -1 22 2096 2097 shmat (5, 0x0, 0x1800) --> Success(0x50000000) 2098 XXX: shm_size(5) = -1 13 2099 shmat: seg size = 0 2100 XXX: shm_size(5) = -1 13 2101 2102 shmat (4, 0x0, 0x1800) --> Success(0x40000000) 2103 XXX: shm_size(4) = -1 22 2104 shmat: seg size = 0 2105 XXX: shm_size(4) = -1 22 2106 */ 2107} 2108PRE(sys_shmat) 2109{ 2110 UWord segmentSize; 2111 /* void* shmat ( int shmid, const void* shmaddr, int flags ) */ 2112 PRINT("shmat (%ld, %#lx, %#lx)", ARG1, ARG2, ARG3); 2113 PRE_REG_READ3(void*, "shmat", int, shmid, void*, shmaddr, int, flags); 2114 segmentSize = get_shm_size( ARG1 ); 2115 if (0) VG_(printf)("shmat: seg size = %lu\n", segmentSize); 2116} 2117POST(sys_shmat) 2118{ 2119 UInt segmentSize; 2120 vg_assert(SUCCESS); 2121 vg_assert(RES != -1L); 2122 segmentSize = get_shm_size ( ARG1 ); 2123 if ( segmentSize > 0 ) { 2124 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE; 2125 Bool d; 2126 2127 if (ARG2 & SHM_RDONLY) 2128 prot &= ~VKI_PROT_WRITE; 2129 2130 d = VG_(am_notify_client_shmat)( RES, VG_PGROUNDUP(segmentSize), prot ); 2131 2132 /* we don't distinguish whether it's read-only or 2133 * read-write -- it doesn't matter really. */ 2134 VG_TRACK( new_mem_mmap, RES, segmentSize, True, True, False, 0/*di_handle*/ ); 2135 if (d) 2136 VG_(discard_translations)( (Addr64)RES, 2137 (ULong)VG_PGROUNDUP(segmentSize), 2138 "ML_(generic_POST_sys_shmat)" ); 2139 } 2140} 2141 2142PRE(sys_shmctl) 2143{ 2144 PRINT("shmctl ( %ld, %ld, %#lx )", ARG1, ARG2, ARG3 ); 2145 PRE_REG_READ3(int, "shmctl", int, shmid, int, command, void*, buffer); 2146 if (ARG3) 2147 PRE_MEM_WRITE( "shmctl(buffer)", ARG3, sizeof(struct shmid_ds) ); 2148} 2149POST(sys_shmctl) 2150{ 2151 if ((ARG3) && ARG2 == IPC_STAT) 2152 POST_MEM_WRITE( ARG3, sizeof(struct shmid_ds) ); 2153} 2154 2155PRE(sys_shmdt) 2156{ 2157 PRINT("shmdt ( %#lx )", ARG1); 2158 PRE_REG_READ1(long, "shmdt", void*, address); 2159} 2160POST(sys_shmdt) 2161{ 2162 NSegment const*const s = VG_(am_find_nsegment)(ARG1); 2163 2164 if (s != NULL) { 2165 Addr s_start = s->start; 2166 SizeT s_len = s->end+1 - s->start; 2167 Bool d; 2168 2169 vg_assert(s->kind == SkShmC && s->start == ARG1); 2170 2171 d = VG_(am_notify_munmap)(s_start, s_len); 2172 /* s is now invalid; do not use after here */ 2173 VG_TRACK( die_mem_munmap, s_start, s_len ); 2174 if (d) 2175 VG_(discard_translations)( (Addr64)s_start, 2176 (ULong)s_len, 2177 "ML_(generic_POST_sys_shmdt)" ); 2178 } 2179} 2180 2181PRE(sys_shmget) 2182{ 2183 PRINT("shmget ( %ld, %ld, %ld )", ARG1, ARG2, ARG3 ); 2184 PRE_REG_READ3(int, "shmget", key_t, key, size_t, size, int, shmFlag); 2185} 2186 2187PRE(sys_shutdown) 2188{ 2189 PRINT("shutdown (BOGUS HANDLER)"); 2190} 2191 2192PRE(sys_sigcleanup) 2193{ 2194 PRINT("sigcleanup (UNDOCUMENTED)"); 2195} 2196 2197PRE(sys_sigprocmask) 2198{ 2199 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 2200 PRE_REG_READ3(long, "sigprocmask", 2201 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset); 2202 if (ARG2 != 0) 2203 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t)); 2204 if (ARG3 != 0) 2205 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t)); 2206 2207 SET_STATUS_from_SysRes( 2208 VG_(do_sys_sigprocmask) ( tid, ARG1, (vki_sigset_t*)ARG2, 2209 (vki_sigset_t*)ARG3 ) 2210 ); 2211 2212 if (SUCCESS) 2213 *flags |= SfPollAfter; 2214} 2215POST(sys_sigprocmask) 2216{ 2217 vg_assert(SUCCESS); 2218 if (RES == 0 && ARG3 != 0) 2219 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t)); 2220} 2221 2222PRE(sys_socket) 2223{ 2224 PRINT("socket ( %ld, %ld, %ld )", ARG1, ARG2, ARG3); 2225 PRE_REG_READ3(int, "socket", int, domain, int, type, int, protocol); 2226} 2227 2228PRE(sys_statfs) 2229{ 2230 PRINT("sys_statfs ( %#lx(%s), %#lx )",ARG1,(Char*)ARG1,ARG2); 2231 PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf); 2232 PRE_MEM_RASCIIZ( "statfs(path)", ARG1 ); 2233 PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct statfs) ); 2234} 2235POST(sys_statfs) 2236{ 2237 POST_MEM_WRITE( ARG2, sizeof(struct statfs) ); 2238} 2239 2240PRE(sys_statx) 2241{ 2242 PRINT("statx ( %#lx(%s), %#lx, %ld, %ld )", ARG1,(Char*)ARG1,ARG2,ARG3,ARG4); 2243 PRE_MEM_RASCIIZ( "statx(file_name)", ARG1 ); 2244 PRE_REG_READ4(Word, "statx", UWord, fd, void*, buf, 2245 UWord, len, UWord, cmd); 2246 PRE_MEM_WRITE( "statx(buf)", ARG2, ARG3 ); 2247} 2248POST(sys_statx) 2249{ 2250 POST_MEM_WRITE( ARG2, ARG3 ); 2251} 2252 2253PRE(sys_symlink) 2254{ 2255 PRINT("symlink (BOGUS HANDLER)"); 2256} 2257 2258PRE(sys_sys_parm) 2259{ 2260 PRINT("sys_parm (%ld, %ld, %#lx)", ARG1, ARG2, ARG3); 2261 PRE_REG_READ3(int, "sys_parm", int, cmd, int, cmdflag, 2262 struct vario*, parmp); 2263 /* this is a bit of a kludge, but if parmp has uninitialised areas 2264 and we're doing SYSP_SET, lots of errors will be tiresomely 2265 reported. Hence just ignore the definedness of the area and 2266 only check addressability. */ 2267 PRE_MEM_WRITE( "sys_parm(parmp)", ARG3, sizeof(struct vario)); 2268} 2269POST(sys_sys_parm) 2270{ 2271 if (ARG1 == SYSP_GET) 2272 POST_MEM_WRITE( ARG3, sizeof(struct vario) ); 2273} 2274 2275PRE(sys_sysconfig) 2276{ 2277 PRINT("sysconfig ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 2278 PRE_REG_READ3(int, "sysconfig", int, cmd, void*, parmp, int, parmlen); 2279 /* It may be that the area is read sometimes as well as written, 2280 but for the same reasons as sys_parm, just check addressibility, 2281 not definedness. */ 2282 PRE_MEM_WRITE( "sysconfig(parmp)", ARG2, ARG3 ); 2283} 2284POST(sys_sysconfig) 2285{ 2286 POST_MEM_WRITE( ARG2, ARG3 ); 2287} 2288 2289PRE(sys_thread_create) 2290{ 2291 *flags |= SfMayBlock; 2292 PRINT("thread_create ( )"); 2293} 2294POST(sys_thread_create) 2295{ 2296 vg_assert(SUCCESS); 2297 if (0) VG_(printf)("new lwpid is %ld\n", RES); 2298 2299 /* Allocate a new thread slot (which sets it to VgTs_Init), and 2300 record the lwpid in it, so can later find it again when handling 2301 sys_thread_setstate for that lwpid. */ 2302 2303 ThreadId ctid = VG_(alloc_ThreadState)(); 2304 ThreadState* ctst = VG_(get_ThreadState)(ctid); 2305 2306 vg_assert(ctst->status == VgTs_Init); 2307 2308 { /* Clear all os_state fields except for the vg stack ones, so any 2309 existing stack gets reused. */ 2310 Addr v_s_b = ctst->os_state.valgrind_stack_base; 2311 Addr v_s_i_SP = ctst->os_state.valgrind_stack_init_SP; 2312 VG_(memset)(&ctst->os_state, 0, sizeof(ThreadOSstate)); 2313 ctst->os_state.valgrind_stack_base = v_s_b; 2314 ctst->os_state.valgrind_stack_init_SP = v_s_i_SP; 2315 } 2316 ctst->os_state.lwpid = RES; 2317} 2318 2319PRE(sys_thread_init) 2320{ 2321 *flags |= SfMayBlock; 2322 PRE_REG_READ2(long, "thread_init", long, arg1, long, arg2); 2323 PRINT("thread_init (BOGUS HANDLER) ( %#lx, %#lx )", ARG1, ARG2); 2324} 2325 2326PRE(sys_thread_kill) 2327{ 2328 Int target_lwpid, my_lwpid; 2329 PRINT("thread_kill ( %ld, %ld )", ARG1, ARG2); 2330 2331 if ( ((Word)ARG1) == (Word)(-1) 2332 && ARG2 == VKI_SIGSEGV ) { 2333 /* too difficult to continue; give up. */ 2334 ML_(aix5_set_threadstate_for_emergency_exit) 2335 (tid, "exiting due to thread_kill(..,SIGSEGV) to process"); 2336 SET_STATUS_Success(0); 2337 return; 2338 } 2339 2340 /* Check to see if this kill gave us a pending signal */ 2341 *flags |= SfPollAfter; 2342 2343 target_lwpid = (Int)ARG1; 2344 my_lwpid = VG_(gettid)(); 2345 /* we still hold the lock. Do deadlock-avoidance stuff. */ 2346 if (target_lwpid == my_lwpid) { 2347 /* sending a signal to myself, which may be fatal. Therefore 2348 drop the lock so that if the signal kills me, some other 2349 thread can pick it up. */ 2350 *flags |= SfMayBlock; 2351 } else { 2352 /* sending a signal to some other thread, which may kill it; 2353 therefore I'd better hold on to the lock to ensure that the 2354 target doesn't get killed whilst holding it. */ 2355 } 2356} 2357 2358/* thread_setmymask_fast is handled on a per platform basis */ 2359 2360PRE(sys_thread_setmystate) 2361{ 2362 *flags |= SfMayBlock; 2363 /* args: struct tstate *, struct tstate * 2364 I assume: first is new state, if not NULL. 2365 Second is place to write the previous state, if not NULL. 2366 (in the style of sigaction) */ 2367 PRINT("thread_setmystate (BOGUS HANDLER) ( %#lx, %#lx )", 2368 ARG1, ARG2 ); 2369 PRE_REG_READ2(long, "thread_setmystate", 2370 struct tstate *, newstate, 2371 struct tstate *, oldstate ); 2372 if (ARG1) 2373 PRE_MEM_READ( "thread_setmystate(arg1)", ARG1, sizeof(struct tstate) ); 2374 if (ARG2) 2375 PRE_MEM_WRITE( "thread_setmystate(arg2)", ARG2, sizeof(struct tstate) ); 2376 if (1 && VG_(clo_trace_syscalls) && ARG1) 2377 ML_(aix5debugstuff_show_tstate)(ARG1, "thread_setmystate (NEW)"); 2378 2379 struct tstate* newts = (struct tstate*)ARG1; 2380 struct tstate* oldts = (struct tstate*)ARG2; 2381 2382 /* Are we just messing with the signal mask? If so intercept it 2383 and do it ourselves. Same idea as handling for 2384 thread_setmymask_fast in 32-bit mode. */ 2385 if (newts && newts->flags == TSTATE_CHANGE_SIGMASK) { 2386 vki_sigset_t* newset = newts ? (vki_sigset_t*)&newts->sigmask : NULL; 2387 vki_sigset_t* oldset = oldts ? (vki_sigset_t*)&oldts->sigmask : NULL; 2388 SET_STATUS_from_SysRes( 2389 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_SETMASK, newset, oldset ) 2390 ); 2391 *flags &= ~SfMayBlock; 2392 return; 2393 } 2394} 2395POST(sys_thread_setmystate) 2396{ 2397 if (ARG2) 2398 POST_MEM_WRITE( ARG2, sizeof(struct tstate) ); 2399 if (0 && VG_(clo_trace_syscalls) && ARG2) 2400 ML_(aix5debugstuff_show_tstate)(ARG2, "thread_setmystate (OLD)"); 2401} 2402 2403PRE(sys_thread_setmystate_fast) 2404{ 2405 UWord how = ARG1; 2406 /* args: ?? */ 2407 PRINT("thread_setmystate_fast (BOGUS HANDLER)" 2408 "(%#lx,%#lx(%s),%#lx(%s))", 2409 ARG1, 2410 ARG2, ML_(aix5debugstuff_pc_to_fnname)(ARG2), 2411 ARG3, ML_(aix5debugstuff_pc_to_fnname)(ARG3) 2412 ); 2413 PRE_REG_READ3(long, "thread_setmystate_fast", 2414 long, arg1, long, arg2, long, arg3); 2415 if (1 && VG_(clo_trace_syscalls)) 2416 ML_(aix5debugstuff_show_tstate_flags)( how ); 2417 2418 if (how & TSTATE_CHANGE_FLAGS) { 2419 /* Messing with cancellation type/state. Pay attention. */ 2420 Bool async = (how & TSTATE_CANCEL_DEFER) == 0; 2421 Bool disabled = (how & TSTATE_CANCEL_DISABLE) > 0; 2422 ThreadState* tst = VG_(get_ThreadState)(tid); 2423 if (VG_(clo_trace_syscalls)) 2424 VG_(printf)("(cancellation state -> %s %s)", 2425 async ? "ASYNC" : "DEFER", 2426 disabled ? "DISABLED" : " ENABLED"); 2427 tst->os_state.cancel_async = async; 2428 tst->os_state.cancel_disabled = disabled; 2429 /* If cancellation has been enabled for this thread and there is 2430 a request outstanding, honour it now. */ 2431 if ((!disabled) 2432 && tst->os_state.cancel_progress == Canc_Requested) { 2433 if (VG_(clo_trace_syscalls)) 2434 VG_(printf)("(honouring previous cancellation request)"); 2435 tst->os_state.cancel_progress = Canc_Actioned; 2436 Bool ok = ML_(aix5_force_thread_into_pthread_exit)(tid); 2437 if (!ok) { 2438 /* now at serious risk of deadlock/livelock. Give up 2439 rather than continue. */ 2440 ML_(aix5_set_threadstate_for_emergency_exit) 2441 (tid, "pthread_cancel(case1): " 2442 "cannot find pthread_exit; aborting"); 2443 SET_STATUS_Success(0); 2444 return; 2445 } 2446 } 2447 SET_STATUS_Success(0); 2448 return; 2449 } 2450 2451 /* In all other cases, hand to kernel. */ 2452 *flags |= SfMayBlock; 2453} 2454 2455/* thread_setstate is handled in syswrap-ppc{32,64}-aix5.c. */ 2456 2457PRE(sys_thread_terminate_unlock) 2458{ 2459 ThreadState* tst; 2460 /* simple; just make this thread exit */ 2461 PRINT("thread_terminate_unlock( %#lx )", ARG1); 2462 PRE_REG_READ1(void, "thread_terminate_unlock", void*, exitcode); 2463 tst = VG_(get_ThreadState)(tid); 2464 /* Drop the lock we were holding, since we're not really going to 2465 exit the host thread with thread_terminate_unlock. */ 2466 if (0) VG_(printf)("XXXXX dropping lock\n"); 2467 if (1) VG_(do_syscall1)(__NR_AIX5_thread_unlock, ARG1); 2468 /* Set the thread's status to be exiting, then claim that the 2469 syscall succeeded. */ 2470 tst->exitreason = VgSrc_ExitThread; 2471 tst->os_state.exitcode = 0; 2472 SET_STATUS_Success(0); 2473} 2474 2475PRE(sys_thread_tsleep) 2476{ 2477 *flags |= SfMayBlock; 2478 PRINT("thread_tsleep (BOGUS HANDLER)( %ld, %#lx, %#lx, %#lx )", 2479 ARG1, ARG2, ARG3, ARG4 ); 2480} 2481 2482PRE(sys_thread_tsleep_event) 2483{ 2484 *flags |= SfMayBlock; 2485 PRINT("thread_tsleep_event (UNDOCUMENTED)( %#lx, %#lx, %ld, %#lx )", 2486 ARG1, ARG2, ARG3, ARG4 ); 2487} 2488 2489PRE(sys_thread_twakeup) 2490{ 2491 *flags |= SfMayBlock; 2492 PRINT("thread_twakeup (BOGUS HANDLER)( tid=%ld, val=%#lx )", ARG1, ARG2 ); 2493} 2494 2495PRE(sys_thread_twakeup_event) 2496{ 2497 *flags |= SfMayBlock; 2498 PRINT("thread_twakeup_event (BOGUS HANDLER)( %#lx, %ld, %ld )", 2499 ARG1, ARG2, ARG3 ); 2500} 2501 2502PRE(sys_thread_unlock) 2503{ 2504 *flags |= SfMayBlock; 2505 PRINT("thread_unlock (BOGUS HANDLER)" ); 2506} 2507 2508PRE(sys_thread_waitlock) 2509{ 2510 *flags |= SfMayBlock; 2511 PRINT("thread_waitlock (BOGUS HANDLER)" ); 2512} 2513 2514PRE(sys_thread_waitlock_) 2515{ 2516 *flags |= SfMayBlock; 2517 PRINT("thread_waitlock_ (BOGUS HANDLER)" ); 2518} 2519 2520PRE(sys_times) 2521{ 2522 PRINT("times ( %#lx )", ARG1); 2523 PRE_REG_READ1(long, "times", struct tms *, buffer); 2524 PRE_MEM_WRITE("times(buf)", ARG1, sizeof(struct tms) ); 2525} 2526POST(sys_times) 2527{ 2528 POST_MEM_WRITE( ARG1, sizeof(struct tms) ); 2529} 2530 2531PRE(sys_umask) 2532{ 2533 PRINT("umask (BOGUS HANDLER)"); 2534} 2535 2536PRE(sys_uname) 2537{ 2538 PRINT("uname ( %#lx )", ARG1); 2539 PRE_MEM_WRITE( "uname(Name)", ARG1, sizeof(struct utsname)); 2540} 2541POST(sys_uname) 2542{ 2543 vg_assert(SUCCESS); 2544 POST_MEM_WRITE( ARG1, sizeof(struct utsname)); 2545} 2546 2547PRE(sys_unlink) 2548{ 2549 PRINT("unlink ( %#lx(%s) )", ARG1, (Char*)ARG1 ); 2550 PRE_REG_READ1(int, "unlink", char*, path); 2551 PRE_MEM_RASCIIZ( "unlink(path)", ARG1 ); 2552} 2553 2554PRE(sys_utimes) 2555{ 2556 PRINT("utimes ( %#lx(%s), %#lx )", ARG1,(Char*)ARG1, ARG2); 2557 PRE_REG_READ2(int, "utimes", char*, path, struct timeval*, times); 2558 PRE_MEM_RASCIIZ( "utimes(path)", ARG1 ); 2559 PRE_MEM_READ( "utimes(times)", ARG2, 2 * sizeof(struct vki_timeval) ); 2560} 2561 2562PRE(sys_vmgetinfo) 2563{ 2564 PRINT("vmgetinfo ( %#lx, %ld, %ld )", ARG1, ARG2, ARG3 ); 2565 PRE_REG_READ3(int, "vmgetinfo", void*, out, int, command, int, arg); 2566 /* It looks like libc's vmgetinfo just hands stuff through to the 2567 syscall. The man page says that the interpretation of ARG3(arg) 2568 depends on ARG2(cmd); nevertheless in all cases basically this 2569 writes the buffer (ARG1, ARG3). */ 2570 PRE_MEM_WRITE("vmgetinfo(buf)", ARG1, ARG3); 2571} 2572POST(sys_vmgetinfo) 2573{ 2574 vg_assert(SUCCESS); 2575 POST_MEM_WRITE(ARG1, ARG3); 2576} 2577 2578PRE(sys_yield) 2579{ 2580 *flags |= SfMayBlock; 2581 PRINT("yield ( )"); 2582} 2583 2584#undef PRE 2585#undef POST 2586 2587#endif // defined(VGO_aix5) 2588 2589/*--------------------------------------------------------------------*/ 2590/*--- end ---*/ 2591/*--------------------------------------------------------------------*/ 2592