1
2 /*--------------------------------------------------------------------*/
3 /*--- Platform-specific syscalls stuff. syswrap-ppc32-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(VGP_ppc32_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_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"
53
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"
57
58
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. */
VG_(show_open_fds)64 void VG_(show_open_fds) ( void )
65 {
66 I_die_here;
67 }
i_am_the_only_thread(void)68 static Bool i_am_the_only_thread ( void )
69 {
70 Int c = VG_(count_living_threads)();
71 vg_assert(c >= 1); /* stay sane */
72 return c == 1;
73 }
VG_(reap_threads)74 void VG_(reap_threads)(ThreadId self)
75 {
76 while (!i_am_the_only_thread()) {
77 /* Let other thread(s) run */
78 VG_(vg_yield)();
79 VG_(poll_signals)(self);
80 }
81 vg_assert(i_am_the_only_thread());
82 }
VG_(init_preopened_fds)83 void VG_(init_preopened_fds) ( void )
84 {
85 I_die_here;
86 }
87
88
89 // Run a thread from beginning to end and return the thread's
90 // scheduler-return-code.
thread_wrapper(Word tidW)91 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
92 {
93 VgSchedReturnCode ret;
94 ThreadId tid = (ThreadId)tidW;
95 ThreadState* tst = VG_(get_ThreadState)(tid);
96
97 VG_(debugLog)(1, "syswrap-aix32",
98 "thread_wrapper(tid=%lld): entry\n",
99 (ULong)tidW);
100
101 vg_assert(tst->status == VgTs_Init);
102
103 /* make sure we get the CPU lock before doing anything significant */
104 VG_(acquire_BigLock)(tid, "thread_wrapper(starting new thread)");
105
106 if (0)
107 VG_(printf)("thread tid %d started: stack = %p\n",
108 tid, &tid);
109
110 VG_TRACK( pre_thread_first_insn, tid );
111
112 tst->os_state.lwpid = VG_(gettid)();
113 tst->os_state.threadgroup = VG_(getpid)();
114
115 /* Thread created with all signals blocked; scheduler will set the
116 appropriate mask */
117 ret = VG_(scheduler)(tid);
118
119 vg_assert(VG_(is_exiting)(tid));
120
121 vg_assert(tst->status == VgTs_Runnable);
122 vg_assert(VG_(is_running_thread)(tid));
123
124 VG_(debugLog)(1, "syswrap-aix32",
125 "thread_wrapper(tid=%lld): exit\n",
126 (ULong)tidW);
127
128 /* Return to caller, still holding the lock. */
129 return ret;
130 }
131
132
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). */
run_a_thread_NORETURN(Word tidW)135 static void run_a_thread_NORETURN ( Word tidW )
136 {
137 ThreadId tid = (ThreadId)tidW;
138 VgSchedReturnCode src;
139 Int c;
140
141 VG_(debugLog)(1, "syswrap-aix32",
142 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
143 (ULong)tidW);
144
145 /* Run the thread all the way through. */
146 src = thread_wrapper(tid);
147
148 VG_(debugLog)(1, "syswrap-aix32",
149 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
150 (ULong)tidW);
151
152 c = VG_(count_living_threads)();
153 vg_assert(c >= 1); /* stay sane */
154
155 vg_assert(src == VgSrc_ExitThread
156 || src == VgSrc_ExitProcess
157 || src == VgSrc_FatalSig);
158
159 if (c == 1 || src == VgSrc_ExitProcess) {
160
161 VG_(debugLog)(1, "syswrap-aix32",
162 "run_a_thread_NORETURN(tid=%lld): "
163 "exit process (%d threads remaining)\n",
164 (ULong)tidW, c);
165
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);
170
171 } else {
172
173 ThreadState *tst;
174
175 VG_(debugLog)(1, "syswrap-aix32",
176 "run_a_thread_NORETURN(tid=%lld): "
177 "not last one standing\n",
178 (ULong)tidW);
179
180 /* OK, thread is dead, but others still exist. Just exit. */
181 vg_assert(c >= 2);
182 tst = VG_(get_ThreadState)(tid);
183
184 /* This releases the run lock */
185 VG_(exit_thread)(tid);
186 vg_assert(tst->status == VgTs_Zombie);
187
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
195 assembler. */
196 { UInt block[4];
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;
204 asm volatile (
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 */
215 "crorc 6,6,6\n\t"
216 ".long 0x48000005\n\t" /* "bl here+4" */
217 "mflr 29\n\t"
218 "addi 29,29,16\n\t"
219 "mtlr 29\n\t"
220 "sc\n\t" /* exit(tst->os_state.exitcode) */
221 :
222 : "b" (&block[0])
223 : "lr", "memory", "r2", "r3", "r20", "r21", "r22", "r23", "r29"
224 );
225 }
226
227 VG_(core_panic)("Thread exit failed?\n");
228 }
229
230 /*NOTREACHED*/
231 vg_assert(0);
232 }
233
234
start_thread_NORETURN(void * arg)235 static Word start_thread_NORETURN ( void* arg )
236 {
237 ThreadState* tst = (ThreadState*)arg;
238 ThreadId tid = tst->tid;
239
240 run_a_thread_NORETURN ( (Word)tid );
241 /*NOTREACHED*/
242 vg_assert(0);
243 }
244
245
246 /* Call f(arg1), but first switch stacks, using 'stack' as the new
247 stack. f itself needs to never return. */
248 __attribute__((noreturn))
249 static
call_on_new_stack_0_1_NORETURN(Addr stack,void (* f_NORETURN)(Word),Word arg1)250 void call_on_new_stack_0_1_NORETURN ( Addr stack,
251 void (*f_NORETURN)(Word),
252 Word arg1 )
253 {
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 */
263 "lwz 1,4(4)\n\t"
264 "lwz 2,8(4)\n\t"
265 "lwz 3,12(4)\n\t"
266 "lwz 11,16(4)\n\t"
267 "lwz 4,0(4)\n\t"
268 "mtctr 4\n\t"
269 "bctr\n"
270 : /*out*/ : /*in*/ "b"(&block[0])
271 );
272 /*NOTREACHED*/
273 __asm__ __volatile__("trap");
274 while (1) {} /* convince gcc that this really doesn't return */
275 }
276
277
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.
282 */
VG_(main_thread_wrapper_NORETURN)283 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
284 {
285 Addr sp;
286 VG_(debugLog)(1, "syswrap-aix32",
287 "entering VG_(main_thread_wrapper_NORETURN)\n");
288
289 sp = ML_(allocstack)(tid);
290
291 /* make a stack frame */
292 sp -= 16;
293 sp &= ~0xF;
294 *(UWord *)sp = 0;
295
296 /* If we can't even allocate the first thread's stack, we're hosed.
297 Give up. */
298 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
299
300 /* shouldn't be any other threads around yet */
301 vg_assert( VG_(count_living_threads)() == 1 );
302
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 */
307 );
308
309 /*NOTREACHED*/
310 vg_assert(0);
311 }
312
313 /* --------- end HACKS --------- */
314
315
316 /* ---------------------------------------------------------------------
317 More thread stuff
318 ------------------------------------------------------------------ */
319
VG_(cleanup_thread)320 void VG_(cleanup_thread) ( ThreadArchState* arch )
321 {
322 }
323
324
325 /* ---------------------------------------------------------------------
326 PRE/POST wrappers for ppc32/AIX5-specific syscalls
327 ------------------------------------------------------------------ */
328
329 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
330 #include <sys/thread.h>
331 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
332
333
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
338 magic. */
339
340 #define PRE(name) DEFN_PRE_TEMPLATE(ppc32_aix5, name)
341 #define POST(name) DEFN_POST_TEMPLATE(ppc32_aix5, name)
342
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);
349
350
PRE(sys___loadx)351 PRE(sys___loadx)
352 {
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))",
356 ARG1,ARG2,ARG3,
357 ARG4,(HChar*)ARG4,
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);
362 }
363 else
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);
370 }
371 else
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,
375 ARG3, ARG4, ARG5);
376 }
377 else
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);
381 }
382 else
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);
386 }
387 else
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);
391 }
392 else
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);
397 }
398 else
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
403 seen. */
404 }
405 else {
406 PRINT("__loadx (BOGUS HANDLER) (0x%lx, ..)", ARG1);
407 }
408 }
POST(sys___loadx)409 POST(sys___loadx)
410 {
411 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_PREUNLOADQ
412 && SUCCESS) {
413 POST_MEM_WRITE(ARG2, ARG3);
414 }
415 else
416
417 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_POSTLOADQ
418 && SUCCESS) {
419 POST_MEM_WRITE(ARG2, ARG3);
420 }
421 else
422
423 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXITQ
424 && SUCCESS) {
425 POST_MEM_WRITE(ARG2, ARG3);
426 }
427 else
428
429 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_EXECQ
430 && SUCCESS) {
431 POST_MEM_WRITE(ARG2, ARG3);
432 }
433 else
434
435 if ((ARG1 & VKI_DL_FUNCTION_MASK) == VKI_DL_LOAD
436 && SUCCESS) {
437
438 /* See comment in pre-handler */
439 POST_MEM_WRITE(ARG2, ARG3);
440
441 /* A module load succeeded. Tell m_debuginfo, m_transtab, and
442 the tool. */
443 ML_(aix5_rescan_procmap_after_load_or_unload)();
444 }
445 }
446
PRE(sys___unload)447 PRE(sys___unload)
448 {
449 PRINT("__unload (UNDOCUMENTED) ( %#lx )", ARG1);
450 }
POST(sys___unload)451 POST(sys___unload)
452 {
453 /* A module unload succeeded. Tell m_debuginfo, m_transtab, and the
454 tool. */
455 ML_(aix5_rescan_procmap_after_load_or_unload)();
456 }
457
PRE(sys__clock_gettime)458 PRE(sys__clock_gettime)
459 {
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) );
465 }
POST(sys__clock_gettime)466 POST(sys__clock_gettime)
467 {
468 vg_assert(SUCCESS);
469 POST_MEM_WRITE( ARG3, sizeof(struct timespec) );
470 }
471
PRE(sys_thread_setmymask_fast)472 PRE(sys_thread_setmymask_fast)
473 {
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. */
478 vki_sigset_t set;
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 )
485 );
486 }
487
PRE(sys_thread_setstate)488 PRE(sys_thread_setstate)
489 {
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;
495 Int i;
496
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
503 deadlocks. */
504
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.
517
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.
522
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. */
526
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
530 control. */
531
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)");
537
538 /* Intercept and handle ourselves any attempts to cancel
539 another thread (including this one). */
540
541 if (ats_new && (!ats_old) && ats_new->flags == TSTATE_INTR) {
542 dst_ts = NULL;
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) {
552 dst_tid = i;
553 break;
554 }
555 }
556 if (VG_(clo_trace_syscalls)) {
557 if (dst_tid == VG_INVALID_THREADID)
558 VG_(printf)("(== unknown tid)");
559 else
560 VG_(printf)("(== tid %d)", (Int)dst_tid);
561 }
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. */
568 vg_assert(dst_ts);
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;
575 } else {
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);
580 if (!ok) {
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);
587 return;
588 }
589 }
590 }
591 SET_STATUS_Success(0);
592 return;
593 }
594 }
595
596 /* Well, it's not a cancellation request. Maybe it is the
597 initialisation of a previously created thread? */
598
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) {
605 dst_tid = i;
606 break;
607 }
608 }
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 */
616
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
621 kernel instead. */
622
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 );
662
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
666 supplied here. */
667 dst_ts->client_stack_highest_word = dst_ts->arch.vex.guest_GPR1;
668
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;
676
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;
681 }
682 }
683 }
POST(sys_thread_setstate)684 POST(sys_thread_setstate)
685 {
686 if (ARG3)
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)");
690 }
691
PRE(sys_FAKE_SIGRETURN)692 PRE(sys_FAKE_SIGRETURN)
693 {
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. */
698
699 PRINT("FAKE_SIGRETURN ( )");
700
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));
704
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);
708
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);
713
714 /* Check to see if any signals arose as a result of this. */
715 *flags |= SfPollAfter;
716 }
717
718
719 /* ---------------------------------------------------------------------
720 The ppc32/AIX5 syscall table
721 ------------------------------------------------------------------ */
722
723 typedef
724 struct {
725 UInt* pSysNo;
726 SyscallTableEntry wrappers;
727 }
728 AIX5SCTabEntry;
729
730 #undef PLAXY
731 #undef PLAX_
732
733 #define PLAXY(sysno, name) \
734 { & sysno, \
735 { & WRAPPER_PRE_NAME(ppc32_aix5, name), \
736 & WRAPPER_POST_NAME(ppc32_aix5, name) }}
737
738 #define PLAX_(sysno, name) \
739 { & sysno, \
740 { & WRAPPER_PRE_NAME(ppc32_aix5, name), \
741 NULL }}
742
743 static /* but not const */
744 AIX5SCTabEntry aix5_ppc32_syscall_table[]
745 = {
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)
882 };
883
ML_(get_ppc32_aix5_syscall_entry)884 SyscallTableEntry* ML_(get_ppc32_aix5_syscall_entry) ( UInt sysno )
885 {
886 Int i;
887 AIX5SCTabEntry tmp;
888
889 const Int tab_size = sizeof(aix5_ppc32_syscall_table)
890 / sizeof(aix5_ppc32_syscall_table[0]);
891
892 for (i = 0; i < tab_size; i++)
893 if (sysno == *(aix5_ppc32_syscall_table[i].pSysNo))
894 break;
895
896 vg_assert(i >= 0 && i <= tab_size);
897 if (i == tab_size)
898 return NULL; /* can't find a wrapper */
899
900 /* Move found one a bit closer to the front, so as to
901 make future searches cheaper. */
902 if (i > 0) {
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;
906 i--;
907 }
908
909 vg_assert(i >= 0 && i < tab_size);
910 return &aix5_ppc32_syscall_table[i].wrappers;
911 }
912
913 #endif // defined(VGP_ppc32_aix5)
914
915 /*--------------------------------------------------------------------*/
916 /*--- end ---*/
917 /*--------------------------------------------------------------------*/
918