2 /*--------------------------------------------------------------------*/
3 /*--- Platform-specific syscalls stuff. syswrap-ppc32-aix5.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2006-2010 OpenWorks LLP
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
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.
36 #if defined(VGP_ppc32_aix5)
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_debuglog.h"
43 #include "pub_core_libcassert.h"
44 #include "pub_core_libcprint.h"
45 #include "pub_core_libcproc.h"
46 #include "pub_core_options.h"
47 #include "pub_core_scheduler.h"
48 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
49 #include "pub_core_signals.h"
50 #include "pub_core_syscall.h"
51 #include "pub_core_syswrap.h"
52 #include "pub_core_tooliface.h"
54 #include "priv_types_n_macros.h"
55 #include "priv_syswrap-aix5.h" /* for decls of aix5-common wrappers */
56 #include "priv_syswrap-main.h"
59 /* --------- HACKS --------- */
60 /* XXXXXXXXXXXX these HACKS are copies of stuff in syswrap-linux.c;
61 check for duplication. */
62 /* HACK: is in syswrap-generic.c, but that doesn't get built on AIX. */
63 /* Dump out a summary, and a more detailed list, of open file descriptors. */
64 void VG_(show_open_fds) ( void )
68 static Bool i_am_the_only_thread ( void )
70 Int c = VG_(count_living_threads)();
71 vg_assert(c >= 1); /* stay sane */
74 void VG_(reap_threads)(ThreadId self)
76 while (!i_am_the_only_thread()) {
77 /* Let other thread(s) run */
79 VG_(poll_signals)(self);
81 vg_assert(i_am_the_only_thread());
83 void VG_(init_preopened_fds) ( void )
89 // Run a thread from beginning to end and return the thread's
90 // scheduler-return-code.
91 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
93 VgSchedReturnCode ret;
94 ThreadId tid = (ThreadId)tidW;
95 ThreadState* tst = VG_(get_ThreadState)(tid);
97 VG_(debugLog)(1, "syswrap-aix32",
98 "thread_wrapper(tid=%lld): entry\n",
101 vg_assert(tst->status == VgTs_Init);
103 /* make sure we get the CPU lock before doing anything significant */
104 VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)");
107 VG_(printf)("thread tid %d started: stack = %p\n",
110 VG_TRACK( pre_thread_first_insn, tid );
112 tst->os_state.lwpid = VG_(gettid)();
113 tst->os_state.threadgroup = VG_(getpid)();
115 /* Thread created with all signals blocked; scheduler will set the
117 ret = VG_(scheduler)(tid);
119 vg_assert(VG_(is_exiting)(tid));
121 vg_assert(tst->status == VgTs_Runnable);
122 vg_assert(VG_(is_running_thread)(tid));
124 VG_(debugLog)(1, "syswrap-aix32",
125 "thread_wrapper(tid=%lld): exit\n",
128 /* Return to caller, still holding the lock. */
133 /* Run a thread all the way to the end, then do appropriate exit actions
134 (this is the last-one-out-turn-off-the-lights bit). */
135 static void run_a_thread_NORETURN ( Word tidW )
137 ThreadId tid = (ThreadId)tidW;
138 VgSchedReturnCode src;
141 VG_(debugLog)(1, "syswrap-aix32",
142 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
145 /* Run the thread all the way through. */
146 src = thread_wrapper(tid);
148 VG_(debugLog)(1, "syswrap-aix32",
149 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
152 c = VG_(count_living_threads)();
153 vg_assert(c >= 1); /* stay sane */
155 vg_assert(src == VgSrc_ExitThread
156 || src == VgSrc_ExitProcess
157 || src == VgSrc_FatalSig);
159 if (c == 1 || src == VgSrc_ExitProcess) {
161 VG_(debugLog)(1, "syswrap-aix32",
162 "run_a_thread_NORETURN(tid=%lld): "
163 "exit process (%d threads remaining)\n",
166 /* We are the last one standing. Keep hold of the lock and
167 carry on to show final tool results, then exit the entire system.
168 Use the continuation pointer set at startup in m_main. */
169 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
175 VG_(debugLog)(1, "syswrap-aix32",
176 "run_a_thread_NORETURN(tid=%lld): "
177 "not last one standing\n",
180 /* OK, thread is dead, but others still exist. Just exit. */
182 tst = VG_(get_ThreadState)(tid);
184 /* This releases the run lock */
185 VG_(exit_thread)(tid);
186 vg_assert(tst->status == VgTs_Zombie);
188 /* We have to use this sequence to terminate the thread to
189 prevent a subtle race. If VG_(exit_thread)() had left the
190 ThreadState as Empty, then it could have been reallocated,
191 reusing the stack while we're doing these last cleanups.
192 Instead, VG_(exit_thread) leaves it as Zombie to prevent
193 reallocation. We need to make sure we don't touch the stack
194 between marking it Empty and exiting. Hence the
197 vg_assert(sizeof(tst->status == 4));
198 vg_assert(__NR_AIX5_thread_terminate
199 != __NR_AIX5_UNKNOWN);
200 block[0] = (UInt)VgTs_Empty;
201 block[1] = (UInt) & (tst->status);
202 block[2] = (UInt) tst->os_state.exitcode;
203 block[3] = __NR_AIX5_thread_terminate;
205 "mr 29,%0\n\t" /* r29 = &block[0] */
206 "lwz 20, 0(29)\n\t" /* r20 = VgTs_Empty */
207 "lwz 21, 4(29)\n\t" /* r21 = & (tst->status) */
208 "lwz 22, 8(29)\n\t" /* r22 = tst->os_state.exitcode */
209 "lwz 23, 12(29)\n\t" /* r23 = __NR_exit */
210 /* after this point we can't safely use the stack. */
211 "stw 20, 0(21)\n\t" /* tst->status = VgTs_Empty */
212 "mr 2,23\n\t" /* r2 = __NR_exit */
213 "mr 3,22\n\t" /* set r3 = tst->os_state.exitcode */
214 /* set up for syscall */
216 ".long 0x48000005\n\t" /* "bl here+4" */
220 "sc\n\t" /* exit(tst->os_state.exitcode) */
223 : "lr", "memory", "r2", "r3", "r20", "r21", "r22", "r23", "r29"
227 VG_(core_panic)("Thread exit failed?\n");
235 static Word start_thread_NORETURN ( void* arg )
237 ThreadState* tst = (ThreadState*)arg;
238 ThreadId tid = tst->tid;
240 run_a_thread_NORETURN ( (Word)tid );
246 /* Call f(arg1), but first switch stacks, using 'stack' as the new
247 stack. f itself needs to never return. */
248 __attribute__((noreturn))
250 void call_on_new_stack_0_1_NORETURN ( Addr stack,
251 void (*f_NORETURN)(Word),
254 UWord* fdescr = (UWord*)f_NORETURN;
255 volatile UWord block[5];
256 block[0] = fdescr[0]; /* nia */
257 block[1] = stack; /* r1 */
258 block[2] = fdescr[1]; /* r2 */
259 block[3] = arg1; /* r3 */
260 block[4] = fdescr[2]; /* r11 */
261 __asm__ __volatile__(
262 "mr 4,%0\n\t" /* r4 = block */
270 : /*out*/ : /*in*/ "b"(&block[0])
273 __asm__ __volatile__("trap");
274 while (1) {} /* convince gcc that this really doesn't return */
278 /* Allocate a stack for the main thread, and run it all the way to the
279 end. Although we already have a working VgStack
280 (VG_(interim_stack)) it's better to allocate a new one, so that
281 overflow detection works uniformly for all threads.
283 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
286 VG_(debugLog)(1, "syswrap-aix32",
287 "entering VG_(main_thread_wrapper_NORETURN)\n");
289 sp = ML_(allocstack)(tid);
291 /* make a stack frame */
296 /* If we can't even allocate the first thread's stack, we're hosed.
298 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
300 /* shouldn't be any other threads around yet */
301 vg_assert( VG_(count_living_threads)() == 1 );
303 call_on_new_stack_0_1_NORETURN(
304 (Addr)sp, /* stack */
305 run_a_thread_NORETURN, /* fn to call */
306 (Word)tid /* arg to give it */
313 /* --------- end HACKS --------- */
316 /* ---------------------------------------------------------------------
318 ------------------------------------------------------------------ */
320 void VG_(cleanup_thread) ( ThreadArchState* arch )
325 /* ---------------------------------------------------------------------
326 PRE/POST wrappers for ppc32/AIX5-specific syscalls
327 ------------------------------------------------------------------ */
329 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
330 #include <sys/thread.h>
331 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
334 /* Add prototypes for the wrappers declared here, so that gcc doesn't
335 harass us for not having prototypes. Really this is a kludge --
336 the right thing to do is to make these wrappers 'static' since they
337 aren't visible outside this file, but that requires even more macro
340 #define PRE(name) DEFN_PRE_TEMPLATE(ppc32_aix5, name)
341 #define POST(name) DEFN_POST_TEMPLATE(ppc32_aix5, name)
343 DECL_TEMPLATE(ppc32_aix5, sys___loadx);
344 DECL_TEMPLATE(ppc32_aix5, sys___unload);
345 DECL_TEMPLATE(ppc32_aix5, sys__clock_gettime);
346 DECL_TEMPLATE(ppc32_aix5, sys_thread_setmymask_fast);
347 DECL_TEMPLATE(ppc32_aix5, sys_thread_setstate);
348 DECL_TEMPLATE(ppc32_aix5, sys_FAKE_SIGRETURN);
353 *flags |= SfMayBlock;
354 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_LOAD) {
355 PRINT("__loadx(0x%lx(DL_LOAD),0x%lx,%ld,0x%lx(%s),0x%lx(%s))",
358 ARG5, (ARG5 ? (HChar*)ARG5 : "nil") );
359 /* It would appear that (ARG2, ARG3) describe a buffer
360 which is written into by the kernel on success. */
361 PRE_MEM_WRITE("__loadx(DL_LOAD)(ARG2,ARG3)", ARG2, ARG3);
364 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_POSTLOADQ) {
365 PRINT("__loadx(0x%lx(DL_POSTLOADQ),0x%lx,%ld,0x%lx)",
366 ARG1,ARG2,ARG3,ARG4);
367 /* It would appear that (ARG2, ARG3) describe a buffer
368 which is written into by the kernel on success. */
369 PRE_MEM_WRITE("__loadx(DL_POSTLOADQ)(ARG2,ARG3)", ARG2, ARG3);
372 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_GLOBALSYM) {
373 PRINT("__loadx(0x%lx(DL_GLOBALSYM),0x%lx(%s),0x%lx,0x%lx,0x%lx)",
374 ARG1, ARG2,(Char*)ARG2,
378 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXITQ) {
379 PRINT("__loadx(0x%lx(DL_EXITQ),0x%lx,%ld)", ARG1, ARG2, ARG3);
380 PRE_MEM_WRITE("__loadx(DL_EXITQ)(ARG2,ARG3)", ARG2, ARG3);
383 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXECQ) {
384 PRINT("__loadx(0x%lx(DL_EXECQ),0x%lx,%ld)", ARG1, ARG2, ARG3);
385 PRE_MEM_WRITE("__loadx(DL_EXECQ)(ARG2,ARG3)", ARG2, ARG3);
388 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_GETSYM) {
389 PRINT("__loadx(0x%lx(DL_GETSYM),0x%lx(%s),%ld,0x%lx)",
390 ARG1, ARG2,(Char*)ARG2, ARG3, ARG4);
393 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_PREUNLOADQ) {
394 PRINT("__loadx(0x%lx(DL_PREUNLOADQ),0x%lx,%ld,0x%lx)",
395 ARG1,ARG2,ARG3,ARG4);
396 PRE_MEM_WRITE("__loadx(DL_PREUNLOADQ)(ARG2,ARG3)", ARG2, ARG3);
399 if ((ARG1 & VKI_DL_FUNCTION_MASK) == 0x0D000000) {
400 PRINT("__loadx(0x%lx(UNDOCUMENTED),0x%lx,0x%lx,0x%lx)",
401 ARG1,ARG2,ARG3,ARG4);
402 /* This doesn't appear to have any args, from the examples I've
406 PRINT("__loadx (BOGUS HANDLER) (0x%lx, ..)", ARG1);
411 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_PREUNLOADQ
413 POST_MEM_WRITE(ARG2, ARG3);
417 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_POSTLOADQ
419 POST_MEM_WRITE(ARG2, ARG3);
423 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXITQ
425 POST_MEM_WRITE(ARG2, ARG3);
429 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXECQ
431 POST_MEM_WRITE(ARG2, ARG3);
435 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_LOAD
438 /* See comment in pre-handler */
439 POST_MEM_WRITE(ARG2, ARG3);
441 /* A module load succeeded. Tell m_debuginfo, m_transtab, and
443 ML_(aix5_rescan_procmap_after_load_or_unload)();
449 PRINT("__unload (UNDOCUMENTED) ( %#lx )", ARG1);
453 /* A module unload succeeded. Tell m_debuginfo, m_transtab, and the
455 ML_(aix5_rescan_procmap_after_load_or_unload)();
458 PRE(sys__clock_gettime)
460 /* Seems like ARG3 points at a destination buffer? */
461 /* _clock_gettime (UNDOCUMENTED) ( 0, 0xA, 0x2FF21808 ) */
462 PRINT("_clock_gettime (UNDOCUMENTED) ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3 );
463 PRE_REG_READ3(int, "_clock_gettime", int, arg1, int, arg2, void*, arg3);
464 PRE_MEM_WRITE( "_clock_gettime(dst)", ARG3, sizeof(struct timespec) );
466 POST(sys__clock_gettime)
469 POST_MEM_WRITE( ARG3, sizeof(struct timespec) );
472 PRE(sys_thread_setmymask_fast)
474 /* args: a 64-bit signal mask in ARG1/2.*/
475 /* On the assumption that this simply sets the thread's signal
476 mask, we act like sigprocmask(SIG_SETMASK, set, NULL) and don't
477 hand this to the kernel. Layout verified 30 July 06. */
479 PRINT("thread_setmymask_fast (BOGUS HANDLER)( %08lx %08lx )", ARG1,ARG2 );
480 vg_assert(sizeof(vki_sigset_t) == 8);
481 set.sig[0] = ARG1; /* sigs 1-32 */
482 set.sig[1] = ARG2; /* sigs 32-64 */
483 SET_STATUS_from_SysRes(
484 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_SETMASK, &set, NULL )
488 PRE(sys_thread_setstate)
490 UWord dst_lwpid = (UWord)ARG1;
491 struct tstate* ats_new = (struct tstate*)ARG2;
492 struct tstate* ats_old = (struct tstate*)ARG3;
493 ThreadId dst_tid = VG_INVALID_THREADID;
494 ThreadState* dst_ts = NULL;
497 /* Arrgh. We MUST retain the lock during this syscall. Reason is
498 that this is sometimes used for asynchronous thread cancellation
499 (nuking other threads). If we don't have the lock during the
500 syscall, then it's possible that the thread we're nuking might
501 get the lock before it gets killed off, and so we can never
502 re-acquire the lock after this syscall, and the system
505 /* 10 July 06: above comment is a misdiagnosis. It appears that
506 for thread cancellation (that is, with ->flags == TSTATE_INTR)
507 the target thread is has its PC changed by the the kernel to
508 something else, possibly to pthread_exit(), so that it can run
509 its cancellation handlers and exit. Currently is unknown how
510 the kernel knows what to set the target thread's PC to. I did
511 establish that all the other data passed in the struct is not
512 relevant: when ->flags == TSTATE_INTR, all the other words can
513 be set to 0x0 or 0xFFFFFFFF and the syscall still works. So the
514 address is not passed like that. Also I looked at args to
515 thread_setmystate_fast, which is used when a thread sets its
516 cancellation state, but none of those are code addresses.
518 Also, it's ok for the kernel to simply change the target
519 thread's PC to something else for async thread cancellation, but
520 for deferred cancellation something else is needed, and I can't
521 see how that would work either.
523 Anyway, net result is, target thread ends up not running on the
524 simulator (not dead), which is why it's necessary to hold onto
525 the lock at this point. */
527 /* 30 July 06: added kludge to intercept attempts to cancel another
528 thread and instead just force that thread to run
529 pthread_exit(PTHREAD_CANCELED). This allows V to keep
532 PRINT("thread_setstate (BOGUS HANDLER) "
533 "( %ld, %p,%p )", dst_lwpid, ats_new, ats_old);
534 if (1 && VG_(clo_trace_syscalls) && ats_new)
535 ML_(aix5debugstuff_show_tstate)((Addr)ats_new,
536 "thread_setstate (NEW)");
538 /* Intercept and handle ourselves any attempts to cancel
539 another thread (including this one). */
541 if (ats_new && (!ats_old) && ats_new->flags == TSTATE_INTR) {
543 if (VG_(clo_trace_syscalls))
544 VG_(printf)("(INTR for lwpid %ld)", dst_lwpid);
545 dst_tid = VG_INVALID_THREADID;
546 for (i = 0; i < VG_N_THREADS; i++) {
547 dst_ts = VG_(get_ThreadState)(i);
548 if ((dst_ts->status == VgTs_Runnable
549 || dst_ts->status == VgTs_Yielding
550 || dst_ts->status == VgTs_WaitSys)
551 && dst_ts->os_state.lwpid == dst_lwpid) {
556 if (VG_(clo_trace_syscalls)) {
557 if (dst_tid == VG_INVALID_THREADID)
558 VG_(printf)("(== unknown tid)");
560 VG_(printf)("(== tid %d)", (Int)dst_tid);
562 if (dst_tid != VG_INVALID_THREADID) {
563 /* A cancel has been requested for ctid. If the target
564 thread has cancellation enabled, honour it right now. If
565 not, mark the thread as having a cancellation request, so
566 that if it later enables cancellation then the
567 cancellation will take effect. */
569 if (dst_ts->os_state.cancel_progress == Canc_NoRequest) {
570 if (dst_ts->os_state.cancel_disabled) {
571 if (VG_(clo_trace_syscalls))
572 VG_(printf)("(target has cancel disabled"
573 "; request lodged)");
574 dst_ts->os_state.cancel_progress = Canc_Requested;
576 if (VG_(clo_trace_syscalls))
577 VG_(printf)("(forcing target into pthread_exit)");
578 dst_ts->os_state.cancel_progress = Canc_Actioned;
579 Bool ok = ML_(aix5_force_thread_into_pthread_exit)(dst_tid);
581 /* now at serious risk of deadlock/livelock. Give up
582 rather than continue. */
583 ML_(aix5_set_threadstate_for_emergency_exit)
584 (tid, "pthread_cancel(case2-32): "
585 "cannot find pthread_exit; aborting");
586 SET_STATUS_Success(0);
591 SET_STATUS_Success(0);
596 /* Well, it's not a cancellation request. Maybe it is the
597 initialisation of a previously created thread? */
599 if (ats_new && !ats_old) {
600 dst_tid = VG_INVALID_THREADID;
601 for (i = 0; i < VG_N_THREADS; i++) {
602 dst_ts = VG_(get_ThreadState)(i);
603 if (dst_ts->status == VgTs_Init
604 && dst_ts->os_state.lwpid == dst_lwpid) {
609 if (dst_tid != VG_INVALID_THREADID) {
610 /* Found the associated child */
611 if (VG_(clo_trace_syscalls))
612 VG_(printf)("(initialised child tid %d)", (Int)dst_tid);
613 dst_ts = VG_(get_ThreadState)(dst_tid);
614 UWord* stack = (UWord*)ML_(allocstack)(dst_tid);
615 /* XXX TODO: check allocstack failure */
617 /* copy the specified child register state into the guest
618 slot (we need that context to run on the simulated CPU,
619 not the real one) and put pointers to our own
620 run-the-simulator function into what we'll hand off to the
623 /* The guest thread is to start running whatever context
624 this syscall showed up with. */
625 dst_ts->arch.vex.guest_GPR0 = ats_new->mst.gpr[0];
626 dst_ts->arch.vex.guest_GPR1 = ats_new->mst.gpr[1]; /* sp */
627 dst_ts->arch.vex.guest_GPR2 = ats_new->mst.gpr[2]; /* toc */
628 dst_ts->arch.vex.guest_GPR3 = ats_new->mst.gpr[3]; /* initarg */
629 dst_ts->arch.vex.guest_GPR4 = ats_new->mst.gpr[4];
630 dst_ts->arch.vex.guest_GPR5 = ats_new->mst.gpr[5];
631 dst_ts->arch.vex.guest_GPR6 = ats_new->mst.gpr[6];
632 dst_ts->arch.vex.guest_GPR7 = ats_new->mst.gpr[7];
633 dst_ts->arch.vex.guest_GPR8 = ats_new->mst.gpr[8];
634 dst_ts->arch.vex.guest_GPR9 = ats_new->mst.gpr[9];
635 dst_ts->arch.vex.guest_GPR10 = ats_new->mst.gpr[10];
636 dst_ts->arch.vex.guest_GPR11 = ats_new->mst.gpr[11]; /* ?? */
637 dst_ts->arch.vex.guest_GPR12 = ats_new->mst.gpr[12];
638 dst_ts->arch.vex.guest_GPR13 = ats_new->mst.gpr[13];
639 dst_ts->arch.vex.guest_GPR14 = ats_new->mst.gpr[14];
640 dst_ts->arch.vex.guest_GPR15 = ats_new->mst.gpr[15];
641 dst_ts->arch.vex.guest_GPR16 = ats_new->mst.gpr[16];
642 dst_ts->arch.vex.guest_GPR17 = ats_new->mst.gpr[17];
643 dst_ts->arch.vex.guest_GPR18 = ats_new->mst.gpr[18];
644 dst_ts->arch.vex.guest_GPR19 = ats_new->mst.gpr[19];
645 dst_ts->arch.vex.guest_GPR20 = ats_new->mst.gpr[20];
646 dst_ts->arch.vex.guest_GPR21 = ats_new->mst.gpr[21];
647 dst_ts->arch.vex.guest_GPR22 = ats_new->mst.gpr[22];
648 dst_ts->arch.vex.guest_GPR23 = ats_new->mst.gpr[23];
649 dst_ts->arch.vex.guest_GPR24 = ats_new->mst.gpr[24];
650 dst_ts->arch.vex.guest_GPR25 = ats_new->mst.gpr[25];
651 dst_ts->arch.vex.guest_GPR26 = ats_new->mst.gpr[26];
652 dst_ts->arch.vex.guest_GPR27 = ats_new->mst.gpr[27];
653 dst_ts->arch.vex.guest_GPR28 = ats_new->mst.gpr[28];
654 dst_ts->arch.vex.guest_GPR29 = ats_new->mst.gpr[29];
655 dst_ts->arch.vex.guest_GPR30 = ats_new->mst.gpr[30];
656 dst_ts->arch.vex.guest_GPR31 = ats_new->mst.gpr[31];
657 dst_ts->arch.vex.guest_CIA = ats_new->mst.iar; /* pc */
658 dst_ts->arch.vex.guest_LR = ats_new->mst.lr;
659 dst_ts->arch.vex.guest_CTR = ats_new->mst.ctr;
660 LibVEX_GuestPPC32_put_CR( ats_new->mst.cr, &dst_ts->arch.vex );
661 LibVEX_GuestPPC32_put_XER( ats_new->mst.xer, &dst_ts->arch.vex );
663 /* Record what seems like the highest legitimate stack
664 address for this thread, so that the stack unwinder works
665 properly. It seems reasonable to use the R1 value
667 dst_ts->client_stack_highest_word = dst_ts->arch.vex.guest_GPR1;
669 /* The host thread is to start running
670 start_thread_NORETURN */
671 UWord* wrapper_fdescr = (UWord*) & start_thread_NORETURN;
672 ats_new->mst.gpr[1] = (UWord)stack;
673 ats_new->mst.gpr[2] = wrapper_fdescr[1];
674 ats_new->mst.iar = wrapper_fdescr[0];
675 ats_new->mst.gpr[3] = (UWord)dst_ts;
677 /* Set initial cancellation status for the thread. */
678 dst_ts->os_state.cancel_async = False;
679 dst_ts->os_state.cancel_disabled = False;
680 dst_ts->os_state.cancel_progress = Canc_NoRequest;
684 POST(sys_thread_setstate)
687 POST_MEM_WRITE( ARG3, sizeof(struct tstate) );
688 if (0 && VG_(clo_trace_syscalls) && ARG3)
689 ML_(aix5debugstuff_show_tstate)(ARG3, "thread_setstate (OLD)");
692 PRE(sys_FAKE_SIGRETURN)
694 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
695 an explanation of what follows. */
696 /* This handles the fake signal-return system call created by
697 sigframe-ppc32-aix5.c. */
699 PRINT("FAKE_SIGRETURN ( )");
701 vg_assert(VG_(is_valid_tid)(tid));
702 vg_assert(tid >= 1 && tid < VG_N_THREADS);
703 vg_assert(VG_(is_running_thread)(tid));
705 /* Remove the signal frame from this thread's (guest) stack,
706 in the process restoring the pre-signal guest state. */
707 VG_(sigframe_destroy)(tid, True);
709 /* Tell the driver not to update the guest state with the "result",
710 and set a bogus result to keep it happy. */
711 *flags |= SfNoWriteResult;
712 SET_STATUS_Success(0);
714 /* Check to see if any signals arose as a result of this. */
715 *flags |= SfPollAfter;
719 /* ---------------------------------------------------------------------
720 The ppc32/AIX5 syscall table
721 ------------------------------------------------------------------ */
726 SyscallTableEntry wrappers;
733 #define PLAXY(sysno, name) \
735 { & WRAPPER_PRE_NAME(ppc32_aix5, name), \
736 & WRAPPER_POST_NAME(ppc32_aix5, name) }}
738 #define PLAX_(sysno, name) \
740 { & WRAPPER_PRE_NAME(ppc32_aix5, name), \
743 static /* but not const */
744 AIX5SCTabEntry aix5_ppc32_syscall_table[]
746 AIXXY(__NR_AIX5___libc_sbrk, sys___libc_sbrk),
747 PLAXY(__NR_AIX5___loadx, sys___loadx),
748 AIXX_(__NR_AIX5___msleep, sys___msleep),
749 PLAXY(__NR_AIX5___unload, sys___unload),
750 PLAXY(__NR_AIX5__clock_gettime, sys__clock_gettime),
751 AIXX_(__NR_AIX5__clock_settime, sys__clock_settime),
752 AIXX_(__NR_AIX5__exit, sys__exit),
753 AIXX_(__NR_AIX5__fp_fpscrx_sc, sys__fp_fpscrx_sc),
754 AIXX_(__NR_AIX5__getpgrp, sys__getpgrp),
755 AIXX_(__NR_AIX5__getpid, sys__getpid),
756 AIXX_(__NR_AIX5__getppid, sys__getppid),
757 AIXX_(__NR_AIX5__getpriority, sys__getpriority),
758 AIXXY(__NR_AIX5__nsleep, sys__nsleep),
759 AIXX_(__NR_AIX5__pause, sys__pause),
760 AIXXY(__NR_AIX5__poll, sys__poll),
761 AIXX_(__NR_AIX5__select, sys__select),
762 AIXX_(__NR_AIX5__sem_wait, sys__sem_wait),
763 AIXX_(__NR_AIX5__setpgid, sys__setpgid),
764 AIXX_(__NR_AIX5__setsid, sys__setsid),
765 AIXXY(__NR_AIX5__sigaction, sys__sigaction),
766 AIXX_(__NR_AIX5__thread_self, sys__thread_self),
767 AIXX_(__NR_AIX5__thread_setsched, sys__thread_setsched),
768 AIXX_(__NR_AIX5_access, sys_access),
769 AIXX_(__NR_AIX5_accessx, sys_accessx),
770 AIXXY(__NR_AIX5_appgetrlimit, sys_appgetrlimit),
771 AIXXY(__NR_AIX5_appgetrusage, sys_appgetrusage),
772 AIXX_(__NR_AIX5_apprestimer, sys_apprestimer),
773 AIXX_(__NR_AIX5_appsetrlimit, sys_appsetrlimit),
774 AIXX_(__NR_AIX5_appulimit, sys_appulimit),
775 AIXX_(__NR_AIX5_bind, sys_bind),
776 AIXX_(__NR_AIX5_chdir, sys_chdir),
777 AIXX_(__NR_AIX5_chmod, sys_chmod),
778 AIXX_(__NR_AIX5_chown, sys_chown),
779 AIXX_(__NR_AIX5_close, sys_close),
780 AIXX_(__NR_AIX5_connext, sys_connext),
781 AIXX_(__NR_AIX5_execve, sys_execve),
782 AIXXY(__NR_AIX5_finfo, sys_finfo),
783 AIXXY(__NR_AIX5_fstatfs, sys_fstatfs),
784 AIXXY(__NR_AIX5_fstatx, sys_fstatx),
785 AIXX_(__NR_AIX5_fsync, sys_fsync),
786 AIXXY(__NR_AIX5_getdirent, sys_getdirent),
787 AIXXY(__NR_AIX5_getdirent64, sys_getdirent64),
788 AIXXY(__NR_AIX5_getdomainname, sys_getdomainname),
789 AIXX_(__NR_AIX5_getgidx, sys_getgidx),
790 AIXXY(__NR_AIX5_getgroups, sys_getgroups),
791 AIXXY(__NR_AIX5_gethostname, sys_gethostname),
792 AIXXY(__NR_AIX5_getpriv, sys_getpriv),
793 AIXXY(__NR_AIX5_getprocs, sys_getprocs),
794 AIXXY(__NR_AIX5_getprocs64, sys_getprocs), /* XXX: correct? */
795 AIXX_(__NR_AIX5_getrpid, sys_getrpid),
796 AIXXY(__NR_AIX5_getsockopt, sys_getsockopt),
797 AIXX_(__NR_AIX5_gettimerid, sys_gettimerid),
798 AIXX_(__NR_AIX5_getuidx, sys_getuidx),
799 AIXXY(__NR_AIX5_incinterval, sys_incinterval),
800 AIXXY(__NR_AIX5_kfcntl, sys_kfcntl),
801 AIXX_(__NR_AIX5_kfork, sys_kfork),
802 AIXX_(__NR_AIX5_kftruncate, sys_kftruncate),
803 AIXX_(__NR_AIX5_kgetsidx, sys_kgetsidx),
804 AIXX_(__NR_AIX5_kill, sys_kill),
805 AIXXY(__NR_AIX5_kioctl, sys_kioctl),
806 AIXX_(__NR_AIX5_klseek, sys_klseek),
807 AIXX_(__NR_AIX5_knlist, sys_knlist),
808 AIXXY(__NR_AIX5_kpread, sys_kpread),
809 AIXXY(__NR_AIX5_kread, sys_kread),
810 AIXXY(__NR_AIX5_kreadv, sys_kreadv),
811 AIXX_(__NR_AIX5_kthread_ctl, sys_kthread_ctl),
812 AIXX_(__NR_AIX5_ktruncate, sys_ktruncate),
813 AIXXY(__NR_AIX5_kwaitpid, sys_kwaitpid),
814 AIXX_(__NR_AIX5_kwrite, sys_kwrite),
815 AIXX_(__NR_AIX5_kwritev, sys_kwritev),
816 AIXX_(__NR_AIX5_listen, sys_listen),
817 AIXX_(__NR_AIX5_loadbind, sys_loadbind),
818 AIXXY(__NR_AIX5_loadquery, sys_loadquery),
819 AIXX_(__NR_AIX5_lseek, sys_lseek),
820 AIXX_(__NR_AIX5_mkdir, sys_mkdir),
821 AIXXY(__NR_AIX5_mmap, sys_mmap),
822 AIXXY(__NR_AIX5_mntctl, sys_mntctl),
823 AIXXY(__NR_AIX5_mprotect, sys_mprotect),
824 AIXXY(__NR_AIX5_munmap, sys_munmap),
825 AIXXY(__NR_AIX5_naccept, sys_naccept),
826 AIXXY(__NR_AIX5_ngetpeername, sys_ngetpeername),
827 AIXXY(__NR_AIX5_ngetsockname, sys_ngetsockname),
828 AIXXY(__NR_AIX5_nrecvfrom, sys_nrecvfrom),
829 AIXX_(__NR_AIX5_nrecvmsg, sys_nrecvmsg),
830 AIXX_(__NR_AIX5_nsendmsg, sys_nsendmsg),
831 AIXX_(__NR_AIX5_open, sys_open),
832 AIXXY(__NR_AIX5_pipe, sys_pipe),
833 AIXX_(__NR_AIX5_privcheck, sys_privcheck),
834 AIXXY(__NR_AIX5_readlink, sys_readlink),
835 AIXXY(__NR_AIX5_recv, sys_recv),
836 AIXX_(__NR_AIX5_rename, sys_rename),
837 AIXXY(__NR_AIX5_sbrk, sys_sbrk),
838 AIXX_(__NR_AIX5_sched_get_priority_max, sys_sched_get_priority_max),
839 AIXX_(__NR_AIX5_sem_destroy, sys_sem_destroy),
840 AIXXY(__NR_AIX5_sem_init, sys_sem_init),
841 AIXXY(__NR_AIX5_sem_post, sys_sem_post),
842 AIXX_(__NR_AIX5_send, sys_send),
843 AIXX_(__NR_AIX5_setgid, sys_setgid),
844 AIXX_(__NR_AIX5_setsockopt, sys_setsockopt),
845 AIXX_(__NR_AIX5_setuid, sys_setuid),
846 AIXXY(__NR_AIX5_shmat, sys_shmat),
847 AIXXY(__NR_AIX5_shmctl, sys_shmctl),
848 AIXXY(__NR_AIX5_shmdt, sys_shmdt),
849 AIXX_(__NR_AIX5_shmget, sys_shmget),
850 AIXX_(__NR_AIX5_shutdown, sys_shutdown),
851 AIXX_(__NR_AIX5_sigcleanup, sys_sigcleanup),
852 AIXXY(__NR_AIX5_sigprocmask, sys_sigprocmask),
853 AIXX_(__NR_AIX5_socket, sys_socket),
854 AIXXY(__NR_AIX5_statx, sys_statx),
855 AIXXY(__NR_AIX5_statfs, sys_statfs),
856 AIXX_(__NR_AIX5_symlink, sys_symlink),
857 AIXXY(__NR_AIX5_sys_parm, sys_sys_parm),
858 AIXXY(__NR_AIX5_sysconfig, sys_sysconfig),
859 AIXXY(__NR_AIX5_thread_create, sys_thread_create),
860 AIXX_(__NR_AIX5_thread_init, sys_thread_init),
861 AIXX_(__NR_AIX5_thread_kill, sys_thread_kill),
862 PLAX_(__NR_AIX5_thread_setmymask_fast, sys_thread_setmymask_fast),
863 AIXXY(__NR_AIX5_thread_setmystate, sys_thread_setmystate),
864 AIXX_(__NR_AIX5_thread_setmystate_fast, sys_thread_setmystate_fast),
865 PLAXY(__NR_AIX5_thread_setstate, sys_thread_setstate),
866 AIXX_(__NR_AIX5_thread_terminate_unlock, sys_thread_terminate_unlock),
867 AIXX_(__NR_AIX5_thread_tsleep, sys_thread_tsleep),
868 AIXX_(__NR_AIX5_thread_tsleep_event, sys_thread_tsleep_event),
869 AIXX_(__NR_AIX5_thread_twakeup, sys_thread_twakeup),
870 AIXX_(__NR_AIX5_thread_twakeup_event, sys_thread_twakeup_event),
871 AIXX_(__NR_AIX5_thread_unlock, sys_thread_unlock),
872 AIXX_(__NR_AIX5_thread_waitlock, sys_thread_waitlock),
873 AIXX_(__NR_AIX5_thread_waitlock_, sys_thread_waitlock_),
874 AIXXY(__NR_AIX5_times, sys_times),
875 AIXX_(__NR_AIX5_umask, sys_umask),
876 AIXXY(__NR_AIX5_uname, sys_uname),
877 AIXX_(__NR_AIX5_unlink, sys_unlink),
878 AIXX_(__NR_AIX5_utimes, sys_utimes),
879 AIXXY(__NR_AIX5_vmgetinfo, sys_vmgetinfo),
880 AIXX_(__NR_AIX5_yield, sys_yield),
881 PLAX_(__NR_AIX5_FAKE_SIGRETURN, sys_FAKE_SIGRETURN)
884 SyscallTableEntry* ML_(get_ppc32_aix5_syscall_entry) ( UInt sysno )
889 const Int tab_size = sizeof(aix5_ppc32_syscall_table)
890 / sizeof(aix5_ppc32_syscall_table[0]);
892 for (i = 0; i < tab_size; i++)
893 if (sysno == *(aix5_ppc32_syscall_table[i].pSysNo))
896 vg_assert(i >= 0 && i <= tab_size);
898 return NULL; /* can't find a wrapper */
900 /* Move found one a bit closer to the front, so as to
901 make future searches cheaper. */
903 tmp = aix5_ppc32_syscall_table[i-1];
904 aix5_ppc32_syscall_table[i-1] = aix5_ppc32_syscall_table[i];
905 aix5_ppc32_syscall_table[i] = tmp;
909 vg_assert(i >= 0 && i < tab_size);
910 return &aix5_ppc32_syscall_table[i].wrappers;
913 #endif // defined(VGP_ppc32_aix5)
915 /*--------------------------------------------------------------------*/
917 /*--------------------------------------------------------------------*/