blob: 37643be96c31bbd633f62ca8264123750275419e [file] [log] [blame]
preludedrewbac65502010-12-30 20:27:30 -07001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH
10 * port by Greg Banks <gbanks@pocketpenguins.com>
11
12 *
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * $Id: process.c,v 1.97 2005/06/08 20:45:28 roland Exp $
38 */
39
40#include "defs.h"
41
42#include <fcntl.h>
43#include <sys/stat.h>
44#include <sys/time.h>
45#include <sys/wait.h>
46#include <sys/resource.h>
47#include <sys/utsname.h>
48#ifdef HAVE_ANDROID_OS
49#include <asm/user.h>
50#else
51#include <sys/user.h>
52#endif
53#include <sys/syscall.h>
54#include <signal.h>
55#ifdef SUNOS4
56#include <machine/reg.h>
57#endif /* SUNOS4 */
58
59#ifdef FREEBSD
60#include <sys/ptrace.h>
61#endif
62
63#ifdef HAVE_ANDROID_OS
64/* for struct sched_param */
65#define sched_priority __sched_priority
66#endif
67
68#if HAVE_ASM_REG_H
69#if defined (SPARC) || defined (SPARC64)
70# define fpq kernel_fpq
71# define fq kernel_fq
72# define fpu kernel_fpu
73#endif /* SPARC || SPARC64 */
74#include <asm/reg.h>
75#if defined (SPARC) || defined (SPARC64)
76# undef fpq
77# undef fq
78# undef fpu
79#endif /* SPARC || SPARC64 */
80#endif /* HAVE_ASM_REG_H */
81
82#ifdef HAVE_SYS_REG_H
83# include <sys/reg.h>
84#ifndef PTRACE_PEEKUSR
85# define PTRACE_PEEKUSR PTRACE_PEEKUSER
86#endif
87#ifndef PTRACE_POKEUSR
88# define PTRACE_POKEUSR PTRACE_POKEUSER
89#endif
90#endif
91
92#ifdef HAVE_LINUX_PTRACE_H
93#undef PTRACE_SYSCALL
94# ifdef HAVE_STRUCT_IA64_FPREG
95# define ia64_fpreg XXX_ia64_fpreg
96# endif
97# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
98# define pt_all_user_regs XXX_pt_all_user_regs
99# endif
100#include <linux/ptrace.h>
101# undef ia64_fpreg
102# undef pt_all_user_regs
103#endif
104
105#if defined (LINUX) && defined (SPARC64)
106# define r_pc r_tpc
107# undef PTRACE_GETREGS
108# define PTRACE_GETREGS PTRACE_GETREGS64
109# undef PTRACE_SETREGS
110# define PTRACE_SETREGS PTRACE_SETREGS64
111#endif /* LINUX && SPARC64 */
112
113#ifdef HAVE_LINUX_FUTEX_H
114#include <linux/futex.h>
115#endif
116#if defined LINUX
117# ifndef FUTEX_WAIT
118# define FUTEX_WAIT 0
119# endif
120# ifndef FUTEX_WAKE
121# define FUTEX_WAKE 1
122# endif
123# ifndef FUTEX_FD
124# define FUTEX_FD 2
125# endif
126# ifndef FUTEX_REQUEUE
127# define FUTEX_REQUEUE 3
128# endif
129#endif
130
131#ifdef LINUX
132#include <sched.h>
133#include <asm/posix_types.h>
134#undef GETGROUPS_T
135#define GETGROUPS_T __kernel_gid_t
136#undef GETGROUPS32_T
137#define GETGROUPS32_T __kernel_gid32_t
138#endif /* LINUX */
139
140#if defined(LINUX) && defined(IA64)
141# include <asm/ptrace_offsets.h>
142# include <asm/rse.h>
143#endif
144
145#ifdef HAVE_PRCTL
146#include <sys/prctl.h>
147#endif
148
149#ifndef WCOREDUMP
150#define WCOREDUMP(status) ((status) & 0200)
151#endif
152
153/* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */
154#if defined(HAVE_PRCTL)
155static const struct xlat prctl_options[] = {
156#ifdef PR_MAXPROCS
157 { PR_MAXPROCS, "PR_MAXPROCS" },
158#endif
159#ifdef PR_ISBLOCKED
160 { PR_ISBLOCKED, "PR_ISBLOCKED" },
161#endif
162#ifdef PR_SETSTACKSIZE
163 { PR_SETSTACKSIZE, "PR_SETSTACKSIZE" },
164#endif
165#ifdef PR_GETSTACKSIZE
166 { PR_GETSTACKSIZE, "PR_GETSTACKSIZE" },
167#endif
168#ifdef PR_MAXPPROCS
169 { PR_MAXPPROCS, "PR_MAXPPROCS" },
170#endif
171#ifdef PR_UNBLKONEXEC
172 { PR_UNBLKONEXEC, "PR_UNBLKONEXEC" },
173#endif
174#ifdef PR_ATOMICSIM
175 { PR_ATOMICSIM, "PR_ATOMICSIM" },
176#endif
177#ifdef PR_SETEXITSIG
178 { PR_SETEXITSIG, "PR_SETEXITSIG" },
179#endif
180#ifdef PR_RESIDENT
181 { PR_RESIDENT, "PR_RESIDENT" },
182#endif
183#ifdef PR_ATTACHADDR
184 { PR_ATTACHADDR, "PR_ATTACHADDR" },
185#endif
186#ifdef PR_DETACHADDR
187 { PR_DETACHADDR, "PR_DETACHADDR" },
188#endif
189#ifdef PR_TERMCHILD
190 { PR_TERMCHILD, "PR_TERMCHILD" },
191#endif
192#ifdef PR_GETSHMASK
193 { PR_GETSHMASK, "PR_GETSHMASK" },
194#endif
195#ifdef PR_GETNSHARE
196 { PR_GETNSHARE, "PR_GETNSHARE" },
197#endif
198#if defined(PR_SET_PDEATHSIG)
199 { PR_SET_PDEATHSIG, "PR_SET_PDEATHSIG" },
200#endif
201#ifdef PR_COREPID
202 { PR_COREPID, "PR_COREPID" },
203#endif
204#ifdef PR_ATTACHADDRPERM
205 { PR_ATTACHADDRPERM, "PR_ATTACHADDRPERM" },
206#endif
207#ifdef PR_PTHREADEXIT
208 { PR_PTHREADEXIT, "PR_PTHREADEXIT" },
209#endif
210#ifdef PR_SET_PDEATHSIG
211 { PR_SET_PDEATHSIG, "PR_SET_PDEATHSIG" },
212#endif
213#ifdef PR_GET_PDEATHSIG
214 { PR_GET_PDEATHSIG, "PR_GET_PDEATHSIG" },
215#endif
216#ifdef PR_GET_UNALIGN
217 { PR_GET_UNALIGN, "PR_GET_UNALIGN" },
218#endif
219#ifdef PR_SET_UNALIGN
220 { PR_SET_UNALIGN, "PR_SET_UNALIGN" },
221#endif
222#ifdef PR_GET_KEEPCAPS
223 { PR_GET_KEEPCAPS, "PR_GET_KEEP_CAPS" },
224#endif
225#ifdef PR_SET_KEEPCAPS
226 { PR_SET_KEEPCAPS, "PR_SET_KEEP_CAPS" },
227#endif
228 { 0, NULL },
229};
230
231
232static const char *
233unalignctl_string (unsigned int ctl)
234{
235 static char buf[16];
236
237 switch (ctl) {
238#ifdef PR_UNALIGN_NOPRINT
239 case PR_UNALIGN_NOPRINT:
240 return "NOPRINT";
241#endif
242#ifdef PR_UNALIGN_SIGBUS
243 case PR_UNALIGN_SIGBUS:
244 return "SIGBUS";
245#endif
246 default:
247 break;
248 }
249 sprintf(buf, "%x", ctl);
250 return buf;
251}
252
253
254int
255sys_prctl(tcp)
256struct tcb *tcp;
257{
258 int i;
259
260 if (entering(tcp)) {
261 printxval(prctl_options, tcp->u_arg[0], "PR_???");
262 switch (tcp->u_arg[0]) {
263#ifdef PR_GETNSHARE
264 case PR_GETNSHARE:
265 break;
266#endif
267#ifdef PR_SET_DEATHSIG
268 case PR_GET_PDEATHSIG:
269 break;
270#endif
271#ifdef PR_SET_UNALIGN
272 case PR_SET_UNALIGN:
273 tprintf(", %s", unalignctl_string(tcp->u_arg[1]));
274 break;
275#endif
276#ifdef PR_GET_UNALIGN
277 case PR_GET_UNALIGN:
278 tprintf(", %#lx", tcp->u_arg[1]);
279 break;
280#endif
281 default:
282 for (i = 1; i < tcp->u_nargs; i++)
283 tprintf(", %#lx", tcp->u_arg[i]);
284 break;
285 }
286 } else {
287 switch (tcp->u_arg[0]) {
288#ifdef PR_GET_PDEATHSIG
289 case PR_GET_PDEATHSIG:
290 for (i=1; i<tcp->u_nargs; i++)
291 tprintf(", %#lx", tcp->u_arg[i]);
292 break;
293#endif
294#ifdef PR_SET_UNALIGN
295 case PR_SET_UNALIGN:
296 break;
297#endif
298#ifdef PR_GET_UNALIGN
299 case PR_GET_UNALIGN:
300 {
301 int ctl;
302
303 umove(tcp, tcp->u_arg[1], &ctl);
304 tcp->auxstr = unalignctl_string(ctl);
305 return RVAL_STR;
306 }
307#endif
308 default:
309 break;
310 }
311 }
312 return 0;
313}
314
315#endif /* HAVE_PRCTL */
316
317int
318sys_gethostid(tcp)
319struct tcb *tcp;
320{
321 if (exiting(tcp))
322 return RVAL_HEX;
323 return 0;
324}
325
326int
327sys_sethostname(tcp)
328struct tcb *tcp;
329{
330 if (entering(tcp)) {
331 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
332 tprintf(", %lu", tcp->u_arg[1]);
333 }
334 return 0;
335}
336
337int
338sys_gethostname(tcp)
339struct tcb *tcp;
340{
341 if (exiting(tcp)) {
342 if (syserror(tcp))
343 tprintf("%#lx", tcp->u_arg[0]);
344 else
345 printpath(tcp, tcp->u_arg[0]);
346 tprintf(", %lu", tcp->u_arg[1]);
347 }
348 return 0;
349}
350
351int
352sys_setdomainname(tcp)
353struct tcb *tcp;
354{
355 if (entering(tcp)) {
356 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
357 tprintf(", %lu", tcp->u_arg[1]);
358 }
359 return 0;
360}
361
362#if !defined(LINUX)
363
364int
365sys_getdomainname(tcp)
366struct tcb *tcp;
367{
368 if (exiting(tcp)) {
369 if (syserror(tcp))
370 tprintf("%#lx", tcp->u_arg[0]);
371 else
372 printpath(tcp, tcp->u_arg[0]);
373 tprintf(", %lu", tcp->u_arg[1]);
374 }
375 return 0;
376}
377#endif /* !LINUX */
378
379int
380sys_exit(tcp)
381struct tcb *tcp;
382{
383 if (exiting(tcp)) {
384 fprintf(stderr, "_exit returned!\n");
385 return -1;
386 }
387 /* special case: we stop tracing this process, finish line now */
388 tprintf("%ld) ", tcp->u_arg[0]);
389 tabto(acolumn);
390 tprintf("= ?");
391 printtrailer(tcp);
392 return 0;
393}
394
395int
396internal_exit(tcp)
397struct tcb *tcp;
398{
399 if (entering(tcp)) {
400 tcp->flags |= TCB_EXITING;
401#ifdef __NR_exit_group
402# ifdef IA64
403 if (ia32) {
404 if (tcp->scno == 252)
405 tcp->flags |= TCB_GROUP_EXITING;
406 } else
407# endif
408 if (known_scno(tcp) == __NR_exit_group)
409 tcp->flags |= TCB_GROUP_EXITING;
410#endif
411 }
412 return 0;
413}
414
415/* TCP is creating a child we want to follow.
416 If there will be space in tcbtab for it, set TCB_FOLLOWFORK and return 0.
417 If not, clear TCB_FOLLOWFORK, print an error, and return 1. */
418static int
419fork_tcb(struct tcb *tcp)
420{
421 if (nprocs == tcbtabsize) {
422 if (expand_tcbtab()) {
423 tcp->flags &= ~TCB_FOLLOWFORK;
424 return 1;
425 }
426 }
427
428 tcp->flags |= TCB_FOLLOWFORK;
429 return 0;
430}
431
432#ifdef USE_PROCFS
433
434int
435sys_fork(tcp)
436struct tcb *tcp;
437{
438 if (exiting(tcp)) {
439 if (getrval2(tcp)) {
440 tcp->auxstr = "child process";
441 return RVAL_UDECIMAL | RVAL_STR;
442 }
443 }
444 return 0;
445}
446
447#if UNIXWARE > 2
448
449int
450sys_rfork(tcp)
451struct tcb *tcp;
452{
453 if (entering(tcp)) {
454 tprintf ("%ld", tcp->u_arg[0]);
455 }
456 else {
457 if (getrval2(tcp)) {
458 tcp->auxstr = "child process";
459 return RVAL_UDECIMAL | RVAL_STR;
460 }
461 }
462 return 0;
463}
464
465#endif
466
467int
468internal_fork(tcp)
469struct tcb *tcp;
470{
471 struct tcb *tcpchild;
472
473 if (exiting(tcp)) {
474#ifdef SYS_rfork
475 if (known_scno(tcp) == SYS_rfork && !(tcp->u_arg[0]&RFPROC))
476 return 0;
477#endif
478 if (getrval2(tcp))
479 return 0;
480 if (!followfork)
481 return 0;
482 if (fork_tcb(tcp))
483 return 0;
484 if (syserror(tcp))
485 return 0;
486 if ((tcpchild = alloctcb(tcp->u_rval)) == NULL)
487 return 0;
488 if (proc_open(tcpchild, 2) < 0)
489 droptcb(tcpchild);
490 }
491 return 0;
492}
493
494#else /* !USE_PROCFS */
495
496#ifdef LINUX
497
498/* defines copied from linux/sched.h since we can't include that
499 * ourselves (it conflicts with *lots* of libc includes)
500 */
501#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
502#define CLONE_VM 0x00000100 /* set if VM shared between processes */
503#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
504#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
505#define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */
506#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
507#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
508#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
509#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
510#define CLONE_THREAD 0x00010000 /* Same thread group? */
511#define CLONE_NEWNS 0x00020000 /* New namespace group? */
512#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
513#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
514#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
515#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
516#define CLONE_DETACHED 0x00400000 /* parent wants no child-exit signal */
517#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
518#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
519
520static const struct xlat clone_flags[] = {
521 { CLONE_VM, "CLONE_VM" },
522 { CLONE_FS, "CLONE_FS" },
523 { CLONE_FILES, "CLONE_FILES" },
524 { CLONE_SIGHAND, "CLONE_SIGHAND" },
525 { CLONE_IDLETASK, "CLONE_IDLETASK"},
526 { CLONE_PTRACE, "CLONE_PTRACE" },
527 { CLONE_VFORK, "CLONE_VFORK" },
528 { CLONE_PARENT, "CLONE_PARENT" },
529 { CLONE_THREAD, "CLONE_THREAD" },
530 { CLONE_NEWNS, "CLONE_NEWNS" },
531 { CLONE_SYSVSEM, "CLONE_SYSVSEM" },
532 { CLONE_SETTLS, "CLONE_SETTLS" },
533 { CLONE_PARENT_SETTID,"CLONE_PARENT_SETTID" },
534 { CLONE_CHILD_CLEARTID,"CLONE_CHILD_CLEARTID" },
535 { CLONE_DETACHED, "CLONE_DETACHED" },
536 { CLONE_UNTRACED, "CLONE_UNTRACED" },
537 { CLONE_CHILD_SETTID,"CLONE_CHILD_SETTID" },
538 { 0, NULL },
539};
540
541# ifdef I386
542# include <asm/ldt.h>
543# ifdef HAVE_STRUCT_USER_DESC
544# define modify_ldt_ldt_s user_desc
545# endif
546extern void print_ldt_entry();
547# endif
548
549# if defined IA64
550# define ARG_FLAGS 0
551# define ARG_STACK 1
552# define ARG_STACKSIZE (known_scno(tcp) == SYS_clone2 ? 2 : -1)
553# define ARG_PTID (known_scno(tcp) == SYS_clone2 ? 3 : 2)
554# define ARG_CTID (known_scno(tcp) == SYS_clone2 ? 4 : 3)
555# define ARG_TLS (known_scno(tcp) == SYS_clone2 ? 5 : 4)
556# elif defined S390 || defined S390X
557# define ARG_STACK 0
558# define ARG_FLAGS 1
559# define ARG_PTID 2
560# define ARG_CTID 3
561# define ARG_TLS 4
562# elif defined X86_64 || defined ALPHA
563# define ARG_FLAGS 0
564# define ARG_STACK 1
565# define ARG_PTID 2
566# define ARG_CTID 3
567# define ARG_TLS 4
568# else
569# define ARG_FLAGS 0
570# define ARG_STACK 1
571# define ARG_PTID 2
572# define ARG_TLS 3
573# define ARG_CTID 4
574# endif
575
576int
577sys_clone(tcp)
578struct tcb *tcp;
579{
580 if (exiting(tcp)) {
581 unsigned long flags = tcp->u_arg[ARG_FLAGS];
582 tprintf("child_stack=%#lx, ", tcp->u_arg[ARG_STACK]);
583# ifdef ARG_STACKSIZE
584 if (ARG_STACKSIZE != -1)
585 tprintf("stack_size=%#lx, ",
586 tcp->u_arg[ARG_STACKSIZE]);
587# endif
588 tprintf("flags=");
589 printflags(clone_flags, flags &~ CSIGNAL, NULL);
590 if ((flags & CSIGNAL) != 0)
591 tprintf("|%s", signame(flags & CSIGNAL));
592 if ((flags & (CLONE_PARENT_SETTID|CLONE_CHILD_SETTID
593 |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
594 return 0;
595 if (flags & CLONE_PARENT_SETTID)
596 tprintf(", parent_tidptr=%#lx", tcp->u_arg[ARG_PTID]);
597 if (flags & CLONE_SETTLS) {
598# ifdef I386
599 struct modify_ldt_ldt_s copy;
600 if (umove(tcp, tcp->u_arg[ARG_TLS], &copy) != -1) {
601 tprintf(", {entry_number:%d, ",
602 copy.entry_number);
603 if (!verbose(tcp))
604 tprintf("...}");
605 else
606 print_ldt_entry(&copy);
607 }
608 else
609# endif
610 tprintf(", tls=%#lx", tcp->u_arg[ARG_TLS]);
611 }
612 if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID))
613 tprintf(", child_tidptr=%#lx", tcp->u_arg[ARG_CTID]);
614 }
615 return 0;
616}
617
618int
619sys_unshare(struct tcb *tcp)
620{
621 if (entering(tcp))
622 printflags(clone_flags, tcp->u_arg[0], "CLONE_???");
623 return 0;
624}
625#endif
626
627int
628sys_fork(tcp)
629struct tcb *tcp;
630{
631 if (exiting(tcp))
632 return RVAL_UDECIMAL;
633 return 0;
634}
635
636int
637change_syscall(tcp, new)
638struct tcb *tcp;
639int new;
640{
641#if defined(LINUX)
642#if defined(I386)
643 /* Attempt to make vfork into fork, which we can follow. */
644 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
645 return -1;
646 return 0;
647#elif defined(X86_64)
648 /* Attempt to make vfork into fork, which we can follow. */
649 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
650 return -1;
651 return 0;
652#elif defined(POWERPC)
653 if (ptrace(PTRACE_POKEUSER, tcp->pid,
654 (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
655 return -1;
656 return 0;
657#elif defined(S390) || defined(S390X)
658 /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
659 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new)<0)
660 return -1;
661 return 0;
662#elif defined(M68K)
663 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new)<0)
664 return -1;
665 return 0;
666#elif defined(SPARC) || defined(SPARC64)
667 struct regs regs;
668 if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0)<0)
669 return -1;
670 regs.r_g1=new;
671 if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0)<0)
672 return -1;
673 return 0;
674#elif defined(MIPS)
675 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new)<0)
676 return -1;
677 return 0;
678#elif defined(ALPHA)
679 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new)<0)
680 return -1;
681 return 0;
682#elif defined(IA64)
683 if (ia32) {
684 switch (new) {
685 case 2: break; /* x86 SYS_fork */
686 case SYS_clone: new = 120; break;
687 default:
688 fprintf(stderr, "%s: unexpected syscall %d\n",
689 __FUNCTION__, new);
690 return -1;
691 }
692 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new)<0)
693 return -1;
694 } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0)
695 return -1;
696 return 0;
697#elif defined(HPPA)
698 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new)<0)
699 return -1;
700 return 0;
701#elif defined(SH)
702 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new)<0)
703 return -1;
704 return 0;
705#elif defined(SH64)
706 /* Top half of reg encodes the no. of args n as 0x1n.
707 Assume 0 args as kernel never actually checks... */
708 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
709 0x100000 | new) < 0)
710 return -1;
711 return 0;
712#elif defined(ARM)
713 /* Some kernels support this, some (pre-2.6.16 or so) don't. */
714# ifndef PTRACE_SET_SYSCALL
715# define PTRACE_SET_SYSCALL 23
716# endif
717
718 if (ptrace (PTRACE_SET_SYSCALL, tcp->pid, 0, new) != 0)
719 return -1;
720
721 return 0;
722#else
723#warning Do not know how to handle change_syscall for this architecture
724#endif /* architecture */
725#endif /* LINUX */
726 return -1;
727}
728
729#if 0
730int
731setarg(tcp, argnum)
732 struct tcb *tcp;
733 int argnum;
734{
735#if defined (IA64)
736 {
737 unsigned long *bsp, *ap;
738
739 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) , 0)
740 return -1;
741
742 ap = ia64_rse_skip_regs(bsp, argnum);
743 errno = 0;
744 ptrace(PTRACE_POKEDATA, tcp->pid, (char *) ap, tcp->u_arg[argnum]);
745 if (errno)
746 return -1;
747
748 }
749#elif defined(I386)
750 {
751 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*argnum), tcp->u_arg[argnum]);
752 if (errno)
753 return -1;
754 }
755#elif defined(X86_64)
756 {
757 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(8*(long)argnum), tcp->u_arg[argnum]);
758 if (errno)
759 return -1;
760 }
761#elif defined(POWERPC)
762#ifndef PT_ORIG_R3
763#define PT_ORIG_R3 34
764#endif
765 {
766 ptrace(PTRACE_POKEUSER, tcp->pid,
767 (char*)((argnum==0 ? PT_ORIG_R3 : argnum+PT_R3)*sizeof(unsigned long)),
768 tcp->u_arg[argnum]);
769 if (errno)
770 return -1;
771 }
772#elif defined(MIPS)
773 {
774 errno = 0;
775 if (argnum < 4)
776 ptrace(PTRACE_POKEUSER, tcp->pid,
777 (char*)(REG_A0 + argnum), tcp->u_arg[argnum]);
778 else {
779 unsigned long *sp;
780
781 if (upeek(tcp->pid, REG_SP, (long *) &sp) , 0)
782 return -1;
783
784 ptrace(PTRACE_POKEDATA, tcp->pid,
785 (char*)(sp + argnum - 4), tcp->u_arg[argnum]);
786 }
787 if (errno)
788 return -1;
789 }
790#elif defined(S390) || defined(S390X)
791 {
792 if(argnum <= 5)
793 ptrace(PTRACE_POKEUSER, tcp->pid,
794 (char *) (argnum==0 ? PT_ORIGGPR2 :
795 PT_GPR2 + argnum*sizeof(long)),
796 tcp->u_arg[argnum]);
797 else
798 return -E2BIG;
799 if (errno)
800 return -1;
801 }
802#else
803# warning Sorry, setargs not implemented for this architecture.
804#endif
805 return 0;
806}
807#endif
808
809#if defined SYS_clone || defined SYS_clone2 || defined __NR_clone
810int
811internal_clone(tcp)
812struct tcb *tcp;
813{
814 struct tcb *tcpchild;
815 int pid;
816 if (entering(tcp)) {
817 if (!followfork)
818 return 0;
819 if (fork_tcb(tcp))
820 return 0;
821 if (setbpt(tcp) < 0)
822 return 0;
823 } else {
824 int bpt = tcp->flags & TCB_BPTSET;
825
826 if (!(tcp->flags & TCB_FOLLOWFORK))
827 return 0;
828
829 if (syserror(tcp)) {
830 if (bpt)
831 clearbpt(tcp);
832 return 0;
833 }
834
835 pid = tcp->u_rval;
836
837#ifdef CLONE_PTRACE /* See new setbpt code. */
838 tcpchild = pid2tcb(pid);
839 if (tcpchild != NULL) {
840 /* The child already reported its startup trap
841 before the parent reported its syscall return. */
842 if ((tcpchild->flags
843 & (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
844 != (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
845 fprintf(stderr, "\
846[preattached child %d of %d in weird state!]\n",
847 pid, tcp->pid);
848 }
849 else
850#endif
851 if (fork_tcb(tcp) || (tcpchild = alloctcb(pid)) == NULL) {
852 if (bpt)
853 clearbpt(tcp);
854 kill(pid, SIGKILL); /* XXX */
855 return 0;
856 }
857
858#ifndef CLONE_PTRACE
859 /* Attach to the new child */
860 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
861 if (bpt)
862 clearbpt(tcp);
863 perror("PTRACE_ATTACH");
864 fprintf(stderr, "Too late?\n");
865 droptcb(tcpchild);
866 return 0;
867 }
868#endif
869
870 if (bpt)
871 clearbpt(tcp);
872
873 tcpchild->flags |= TCB_ATTACHED;
874 /* Child has BPT too, must be removed on first occasion. */
875 if (bpt) {
876 tcpchild->flags |= TCB_BPTSET;
877 tcpchild->baddr = tcp->baddr;
878 memcpy(tcpchild->inst, tcp->inst,
879 sizeof tcpchild->inst);
880 }
881 tcpchild->parent = tcp;
882 tcp->nchildren++;
883 if (tcpchild->flags & TCB_SUSPENDED) {
884 /* The child was born suspended, due to our having
885 forced CLONE_PTRACE. */
886 if (bpt)
887 clearbpt(tcpchild);
888
889 tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
890 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
891 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
892 return -1;
893 }
894
895 if (!qflag)
896 fprintf(stderr, "\
897Process %u resumed (parent %d ready)\n",
898 pid, tcp->pid);
899 }
900 else {
901 newoutf(tcpchild);
902 if (!qflag)
903 fprintf(stderr, "Process %d attached\n", pid);
904 }
905
906#ifdef TCB_CLONE_THREAD
907 {
908 /*
909 * Save the flags used in this call,
910 * in case we point TCP to our parent below.
911 */
912 int call_flags = tcp->u_arg[ARG_FLAGS];
913 if ((tcp->flags & TCB_CLONE_THREAD) &&
914 tcp->parent != NULL) {
915 /* The parent in this clone is itself a
916 thread belonging to another process.
917 There is no meaning to the parentage
918 relationship of the new child with the
919 thread, only with the process. We
920 associate the new thread with our
921 parent. Since this is done for every
922 new thread, there will never be a
923 TCB_CLONE_THREAD process that has
924 children. */
925 --tcp->nchildren;
926 tcp = tcp->parent;
927 tcpchild->parent = tcp;
928 ++tcp->nchildren;
929 }
930 if (call_flags & CLONE_THREAD) {
931 tcpchild->flags |= TCB_CLONE_THREAD;
932 ++tcp->nclone_threads;
933 }
934 if (call_flags & CLONE_DETACHED) {
935 tcpchild->flags |= TCB_CLONE_DETACHED;
936 ++tcp->nclone_detached;
937 }
938 }
939#endif
940
941 }
942 return 0;
943}
944#endif
945
946int
947internal_fork(tcp)
948struct tcb *tcp;
949{
950#ifdef LINUX
951 /* We do special magic with clone for any clone or fork. */
952 return internal_clone(tcp);
953#else
954
955 struct tcb *tcpchild;
956 int pid;
957 int dont_follow = 0;
958
959#ifdef SYS_vfork
960 if (known_scno(tcp) == SYS_vfork) {
961 /* Attempt to make vfork into fork, which we can follow. */
962 if (!followvfork ||
963 change_syscall(tcp, SYS_fork) < 0)
964 dont_follow = 1;
965 }
966#endif
967 if (entering(tcp)) {
968 if (!followfork || dont_follow)
969 return 0;
970 if (fork_tcb(tcp))
971 return 0;
972 if (setbpt(tcp) < 0)
973 return 0;
974 }
975 else {
976 int bpt = tcp->flags & TCB_BPTSET;
977
978 if (!(tcp->flags & TCB_FOLLOWFORK))
979 return 0;
980 if (bpt)
981 clearbpt(tcp);
982
983 if (syserror(tcp))
984 return 0;
985
986 pid = tcp->u_rval;
987 if (fork_tcb(tcp) || (tcpchild = alloctcb(pid)) == NULL) {
988 kill(pid, SIGKILL); /* XXX */
989 return 0;
990 }
991#ifdef LINUX
992#ifdef HPPA
993 /* The child must have run before it can be attached. */
994 /* This must be a bug in the parisc kernel, but I havn't
995 * identified it yet. Seems to be an issue associated
996 * with attaching to a process (which sends it a signal)
997 * before that process has ever been scheduled. When
998 * debugging, I started seeing crashes in
999 * arch/parisc/kernel/signal.c:do_signal(), apparently
1000 * caused by r8 getting corrupt over the dequeue_signal()
1001 * call. Didn't make much sense though...
1002 */
1003 {
1004 struct timeval tv;
1005 tv.tv_sec = 0;
1006 tv.tv_usec = 10000;
1007 select(0, NULL, NULL, NULL, &tv);
1008 }
1009#endif
1010 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
1011 perror("PTRACE_ATTACH");
1012 fprintf(stderr, "Too late?\n");
1013 droptcb(tcpchild);
1014 return 0;
1015 }
1016#endif /* LINUX */
1017#ifdef SUNOS4
1018#ifdef oldway
1019 /* The child must have run before it can be attached. */
1020 {
1021 struct timeval tv;
1022 tv.tv_sec = 0;
1023 tv.tv_usec = 10000;
1024 select(0, NULL, NULL, NULL, &tv);
1025 }
1026 if (ptrace(PTRACE_ATTACH, pid, (char *)1, 0) < 0) {
1027 perror("PTRACE_ATTACH");
1028 fprintf(stderr, "Too late?\n");
1029 droptcb(tcpchild);
1030 return 0;
1031 }
1032#else /* !oldway */
1033 /* Try to catch the new process as soon as possible. */
1034 {
1035 int i;
1036 for (i = 0; i < 1024; i++)
1037 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) >= 0)
1038 break;
1039 if (i == 1024) {
1040 perror("PTRACE_ATTACH");
1041 fprintf(stderr, "Too late?\n");
1042 droptcb(tcpchild);
1043 return 0;
1044 }
1045 }
1046#endif /* !oldway */
1047#endif /* SUNOS4 */
1048 tcpchild->flags |= TCB_ATTACHED;
1049 /* Child has BPT too, must be removed on first occasion */
1050 if (bpt) {
1051 tcpchild->flags |= TCB_BPTSET;
1052 tcpchild->baddr = tcp->baddr;
1053 memcpy(tcpchild->inst, tcp->inst,
1054 sizeof tcpchild->inst);
1055 }
1056 newoutf(tcpchild);
1057 tcpchild->parent = tcp;
1058 tcp->nchildren++;
1059 if (!qflag)
1060 fprintf(stderr, "Process %d attached\n", pid);
1061 }
1062 return 0;
1063#endif
1064}
1065
1066#endif /* !USE_PROCFS */
1067
1068#if defined(SUNOS4) || defined(LINUX) || defined(FREEBSD)
1069
1070int
1071sys_vfork(tcp)
1072struct tcb *tcp;
1073{
1074 if (exiting(tcp))
1075 return RVAL_UDECIMAL;
1076 return 0;
1077}
1078
1079#endif /* SUNOS4 || LINUX || FREEBSD */
1080
1081#ifndef LINUX
1082
1083static char idstr[16];
1084
1085int
1086sys_getpid(tcp)
1087struct tcb *tcp;
1088{
1089 if (exiting(tcp)) {
1090 sprintf(idstr, "ppid %lu", getrval2(tcp));
1091 tcp->auxstr = idstr;
1092 return RVAL_STR;
1093 }
1094 return 0;
1095}
1096
1097int
1098sys_getuid(tcp)
1099struct tcb *tcp;
1100{
1101 if (exiting(tcp)) {
1102 sprintf(idstr, "euid %lu", getrval2(tcp));
1103 tcp->auxstr = idstr;
1104 return RVAL_STR;
1105 }
1106 return 0;
1107}
1108
1109int
1110sys_getgid(tcp)
1111struct tcb *tcp;
1112{
1113 if (exiting(tcp)) {
1114 sprintf(idstr, "egid %lu", getrval2(tcp));
1115 tcp->auxstr = idstr;
1116 return RVAL_STR;
1117 }
1118 return 0;
1119}
1120
1121#endif /* !LINUX */
1122
1123#ifdef LINUX
1124
1125int
1126sys_setuid(tcp)
1127struct tcb *tcp;
1128{
1129 if (entering(tcp)) {
1130 tprintf("%u", (uid_t) tcp->u_arg[0]);
1131 }
1132 return 0;
1133}
1134
1135int
1136sys_setgid(tcp)
1137struct tcb *tcp;
1138{
1139 if (entering(tcp)) {
1140 tprintf("%u", (gid_t) tcp->u_arg[0]);
1141 }
1142 return 0;
1143}
1144
1145int
1146sys_getresuid(tcp)
1147 struct tcb *tcp;
1148{
1149 if (exiting(tcp)) {
1150 __kernel_uid_t uid;
1151 if (syserror(tcp))
1152 tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
1153 tcp->u_arg[1], tcp->u_arg[2]);
1154 else {
1155 if (umove(tcp, tcp->u_arg[0], &uid) < 0)
1156 tprintf("%#lx, ", tcp->u_arg[0]);
1157 else
1158 tprintf("[%lu], ", (unsigned long) uid);
1159 if (umove(tcp, tcp->u_arg[1], &uid) < 0)
1160 tprintf("%#lx, ", tcp->u_arg[1]);
1161 else
1162 tprintf("[%lu], ", (unsigned long) uid);
1163 if (umove(tcp, tcp->u_arg[2], &uid) < 0)
1164 tprintf("%#lx", tcp->u_arg[2]);
1165 else
1166 tprintf("[%lu]", (unsigned long) uid);
1167 }
1168 }
1169 return 0;
1170}
1171
1172int
1173sys_getresgid(tcp)
1174struct tcb *tcp;
1175{
1176 if (exiting(tcp)) {
1177 __kernel_gid_t gid;
1178 if (syserror(tcp))
1179 tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
1180 tcp->u_arg[1], tcp->u_arg[2]);
1181 else {
1182 if (umove(tcp, tcp->u_arg[0], &gid) < 0)
1183 tprintf("%#lx, ", tcp->u_arg[0]);
1184 else
1185 tprintf("[%lu], ", (unsigned long) gid);
1186 if (umove(tcp, tcp->u_arg[1], &gid) < 0)
1187 tprintf("%#lx, ", tcp->u_arg[1]);
1188 else
1189 tprintf("[%lu], ", (unsigned long) gid);
1190 if (umove(tcp, tcp->u_arg[2], &gid) < 0)
1191 tprintf("%#lx", tcp->u_arg[2]);
1192 else
1193 tprintf("[%lu]", (unsigned long) gid);
1194 }
1195 }
1196 return 0;
1197}
1198
1199#endif /* LINUX */
1200
1201int
1202sys_setreuid(tcp)
1203struct tcb *tcp;
1204{
1205 if (entering(tcp)) {
1206 printuid("", tcp->u_arg[0]);
1207 printuid(", ", tcp->u_arg[1]);
1208 }
1209 return 0;
1210}
1211
1212int
1213sys_setregid(tcp)
1214struct tcb *tcp;
1215{
1216 if (entering(tcp)) {
1217 printuid("", tcp->u_arg[0]);
1218 printuid(", ", tcp->u_arg[1]);
1219 }
1220 return 0;
1221}
1222
1223#if defined(LINUX) || defined(FREEBSD)
1224int
1225sys_setresuid(tcp)
1226 struct tcb *tcp;
1227{
1228 if (entering(tcp)) {
1229 printuid("", tcp->u_arg[0]);
1230 printuid(", ", tcp->u_arg[1]);
1231 printuid(", ", tcp->u_arg[2]);
1232 }
1233 return 0;
1234}
1235int
1236sys_setresgid(tcp)
1237 struct tcb *tcp;
1238{
1239 if (entering(tcp)) {
1240 printuid("", tcp->u_arg[0]);
1241 printuid(", ", tcp->u_arg[1]);
1242 printuid(", ", tcp->u_arg[2]);
1243 }
1244 return 0;
1245}
1246
1247#endif /* LINUX || FREEBSD */
1248
1249int
1250sys_setgroups(tcp)
1251struct tcb *tcp;
1252{
1253 if (entering(tcp)) {
1254 unsigned long len, size, start, cur, end, abbrev_end;
1255 GETGROUPS_T gid;
1256 int failed = 0;
1257
1258 len = tcp->u_arg[0];
1259 tprintf("%lu, ", len);
1260 if (len == 0) {
1261 tprintf("[]");
1262 return 0;
1263 }
1264 start = tcp->u_arg[1];
1265 if (start == 0) {
1266 tprintf("NULL");
1267 return 0;
1268 }
1269 size = len * sizeof(gid);
1270 end = start + size;
1271 if (!verbose(tcp) || size / sizeof(gid) != len || end < start) {
1272 tprintf("%#lx", start);
1273 return 0;
1274 }
1275 if (abbrev(tcp)) {
1276 abbrev_end = start + max_strlen * sizeof(gid);
1277 if (abbrev_end < start)
1278 abbrev_end = end;
1279 } else {
1280 abbrev_end = end;
1281 }
1282 tprintf("[");
1283 for (cur = start; cur < end; cur += sizeof(gid)) {
1284 if (cur > start)
1285 tprintf(", ");
1286 if (cur >= abbrev_end) {
1287 tprintf("...");
1288 break;
1289 }
1290 if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
1291 tprintf("?");
1292 failed = 1;
1293 break;
1294 }
1295 tprintf("%lu", (unsigned long) gid);
1296 }
1297 tprintf("]");
1298 if (failed)
1299 tprintf(" %#lx", tcp->u_arg[1]);
1300 }
1301 return 0;
1302}
1303
1304int
1305sys_getgroups(tcp)
1306struct tcb *tcp;
1307{
1308 unsigned long len;
1309
1310 if (entering(tcp)) {
1311 len = tcp->u_arg[0];
1312 tprintf("%lu, ", len);
1313 } else {
1314 unsigned long size, start, cur, end, abbrev_end;
1315 GETGROUPS_T gid;
1316 int failed = 0;
1317
1318 len = tcp->u_rval;
1319 if (len == 0) {
1320 tprintf("[]");
1321 return 0;
1322 }
1323 start = tcp->u_arg[1];
1324 if (start == 0) {
1325 tprintf("NULL");
1326 return 0;
1327 }
1328 if (tcp->u_arg[0] == 0) {
1329 tprintf("%#lx", start);
1330 return 0;
1331 }
1332 size = len * sizeof(gid);
1333 end = start + size;
1334 if (!verbose(tcp) || tcp->u_arg[0] == 0 ||
1335 size / sizeof(gid) != len || end < start) {
1336 tprintf("%#lx", start);
1337 return 0;
1338 }
1339 if (abbrev(tcp)) {
1340 abbrev_end = start + max_strlen * sizeof(gid);
1341 if (abbrev_end < start)
1342 abbrev_end = end;
1343 } else {
1344 abbrev_end = end;
1345 }
1346 tprintf("[");
1347 for (cur = start; cur < end; cur += sizeof(gid)) {
1348 if (cur > start)
1349 tprintf(", ");
1350 if (cur >= abbrev_end) {
1351 tprintf("...");
1352 break;
1353 }
1354 if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
1355 tprintf("?");
1356 failed = 1;
1357 break;
1358 }
1359 tprintf("%lu", (unsigned long) gid);
1360 }
1361 tprintf("]");
1362 if (failed)
1363 tprintf(" %#lx", tcp->u_arg[1]);
1364 }
1365 return 0;
1366}
1367
1368#ifdef LINUX
1369int
1370sys_setgroups32(tcp)
1371struct tcb *tcp;
1372{
1373 if (entering(tcp)) {
1374 unsigned long len, size, start, cur, end, abbrev_end;
1375 GETGROUPS32_T gid;
1376 int failed = 0;
1377
1378 len = tcp->u_arg[0];
1379 tprintf("%lu, ", len);
1380 if (len == 0) {
1381 tprintf("[]");
1382 return 0;
1383 }
1384 start = tcp->u_arg[1];
1385 if (start == 0) {
1386 tprintf("NULL");
1387 return 0;
1388 }
1389 size = len * sizeof(gid);
1390 end = start + size;
1391 if (!verbose(tcp) || size / sizeof(gid) != len || end < start) {
1392 tprintf("%#lx", start);
1393 return 0;
1394 }
1395 if (abbrev(tcp)) {
1396 abbrev_end = start + max_strlen * sizeof(gid);
1397 if (abbrev_end < start)
1398 abbrev_end = end;
1399 } else {
1400 abbrev_end = end;
1401 }
1402 tprintf("[");
1403 for (cur = start; cur < end; cur += sizeof(gid)) {
1404 if (cur > start)
1405 tprintf(", ");
1406 if (cur >= abbrev_end) {
1407 tprintf("...");
1408 break;
1409 }
1410 if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
1411 tprintf("?");
1412 failed = 1;
1413 break;
1414 }
1415 tprintf("%lu", (unsigned long) gid);
1416 }
1417 tprintf("]");
1418 if (failed)
1419 tprintf(" %#lx", tcp->u_arg[1]);
1420 }
1421 return 0;
1422}
1423
1424int
1425sys_getgroups32(tcp)
1426struct tcb *tcp;
1427{
1428 unsigned long len;
1429
1430 if (entering(tcp)) {
1431 len = tcp->u_arg[0];
1432 tprintf("%lu, ", len);
1433 } else {
1434 unsigned long size, start, cur, end, abbrev_end;
1435 GETGROUPS32_T gid;
1436 int failed = 0;
1437
1438 len = tcp->u_rval;
1439 if (len == 0) {
1440 tprintf("[]");
1441 return 0;
1442 }
1443 start = tcp->u_arg[1];
1444 if (start == 0) {
1445 tprintf("NULL");
1446 return 0;
1447 }
1448 size = len * sizeof(gid);
1449 end = start + size;
1450 if (!verbose(tcp) || tcp->u_arg[0] == 0 ||
1451 size / sizeof(gid) != len || end < start) {
1452 tprintf("%#lx", start);
1453 return 0;
1454 }
1455 if (abbrev(tcp)) {
1456 abbrev_end = start + max_strlen * sizeof(gid);
1457 if (abbrev_end < start)
1458 abbrev_end = end;
1459 } else {
1460 abbrev_end = end;
1461 }
1462 tprintf("[");
1463 for (cur = start; cur < end; cur += sizeof(gid)) {
1464 if (cur > start)
1465 tprintf(", ");
1466 if (cur >= abbrev_end) {
1467 tprintf("...");
1468 break;
1469 }
1470 if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
1471 tprintf("?");
1472 failed = 1;
1473 break;
1474 }
1475 tprintf("%lu", (unsigned long) gid);
1476 }
1477 tprintf("]");
1478 if (failed)
1479 tprintf(" %#lx", tcp->u_arg[1]);
1480 }
1481 return 0;
1482}
1483#endif /* LINUX */
1484
1485int
1486sys_setpgrp(tcp)
1487struct tcb *tcp;
1488{
1489 if (entering(tcp)) {
1490#ifndef SVR4
1491 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
1492#endif /* !SVR4 */
1493 }
1494 return 0;
1495}
1496
1497int
1498sys_getpgrp(tcp)
1499struct tcb *tcp;
1500{
1501 if (entering(tcp)) {
1502#ifndef SVR4
1503 tprintf("%lu", tcp->u_arg[0]);
1504#endif /* !SVR4 */
1505 }
1506 return 0;
1507}
1508
1509int
1510sys_getsid(tcp)
1511struct tcb *tcp;
1512{
1513 if (entering(tcp)) {
1514 tprintf("%lu", tcp->u_arg[0]);
1515 }
1516 return 0;
1517}
1518
1519int
1520sys_setsid(tcp)
1521struct tcb *tcp;
1522{
1523 return 0;
1524}
1525
1526int
1527sys_getpgid(tcp)
1528struct tcb *tcp;
1529{
1530 if (entering(tcp)) {
1531 tprintf("%lu", tcp->u_arg[0]);
1532 }
1533 return 0;
1534}
1535
1536int
1537sys_setpgid(tcp)
1538struct tcb *tcp;
1539{
1540 if (entering(tcp)) {
1541 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
1542 }
1543 return 0;
1544}
1545
1546#if UNIXWARE >= 2
1547
1548#include <sys/privilege.h>
1549
1550
1551static const struct xlat procpriv_cmds [] = {
1552 { SETPRV, "SETPRV" },
1553 { CLRPRV, "CLRPRV" },
1554 { PUTPRV, "PUTPRV" },
1555 { GETPRV, "GETPRV" },
1556 { CNTPRV, "CNTPRV" },
1557 { 0, NULL },
1558};
1559
1560
1561static const struct xlat procpriv_priv [] = {
1562 { P_OWNER, "P_OWNER" },
1563 { P_AUDIT, "P_AUDIT" },
1564 { P_COMPAT, "P_COMPAT" },
1565 { P_DACREAD, "P_DACREAD" },
1566 { P_DACWRITE, "P_DACWRITE" },
1567 { P_DEV, "P_DEV" },
1568 { P_FILESYS, "P_FILESYS" },
1569 { P_MACREAD, "P_MACREAD" },
1570 { P_MACWRITE, "P_MACWRITE" },
1571 { P_MOUNT, "P_MOUNT" },
1572 { P_MULTIDIR, "P_MULTIDIR" },
1573 { P_SETPLEVEL, "P_SETPLEVEL" },
1574 { P_SETSPRIV, "P_SETSPRIV" },
1575 { P_SETUID, "P_SETUID" },
1576 { P_SYSOPS, "P_SYSOPS" },
1577 { P_SETUPRIV, "P_SETUPRIV" },
1578 { P_DRIVER, "P_DRIVER" },
1579 { P_RTIME, "P_RTIME" },
1580 { P_MACUPGRADE, "P_MACUPGRADE" },
1581 { P_FSYSRANGE, "P_FSYSRANGE" },
1582 { P_SETFLEVEL, "P_SETFLEVEL" },
1583 { P_AUDITWR, "P_AUDITWR" },
1584 { P_TSHAR, "P_TSHAR" },
1585 { P_PLOCK, "P_PLOCK" },
1586 { P_CORE, "P_CORE" },
1587 { P_LOADMOD, "P_LOADMOD" },
1588 { P_BIND, "P_BIND" },
1589 { P_ALLPRIVS, "P_ALLPRIVS" },
1590 { 0, NULL },
1591};
1592
1593
1594static const struct xlat procpriv_type [] = {
1595 { PS_FIX, "PS_FIX" },
1596 { PS_INH, "PS_INH" },
1597 { PS_MAX, "PS_MAX" },
1598 { PS_WKG, "PS_WKG" },
1599 { 0, NULL },
1600};
1601
1602
1603static void
1604printpriv(tcp, addr, len, opt)
1605struct tcb *tcp;
1606long addr;
1607int len;
1608const struct xlat *opt;
1609{
1610 priv_t buf [128];
1611 int max = verbose (tcp) ? sizeof buf / sizeof buf [0] : 10;
1612 int dots = len > max;
1613 int i;
1614
1615 if (len > max) len = max;
1616
1617 if (len <= 0 ||
1618 umoven (tcp, addr, len * sizeof buf[0], (char *) buf) < 0)
1619 {
1620 tprintf ("%#lx", addr);
1621 return;
1622 }
1623
1624 tprintf ("[");
1625
1626 for (i = 0; i < len; ++i) {
1627 char *t, *p;
1628
1629 if (i) tprintf (", ");
1630
1631 if ((t = xlookup (procpriv_type, buf [i] & PS_TYPE)) &&
1632 (p = xlookup (procpriv_priv, buf [i] & ~PS_TYPE)))
1633 {
1634 tprintf ("%s|%s", t, p);
1635 }
1636 else {
1637 tprintf ("%#lx", buf [i]);
1638 }
1639 }
1640
1641 if (dots) tprintf (" ...");
1642
1643 tprintf ("]");
1644}
1645
1646
1647int
1648sys_procpriv(tcp)
1649struct tcb *tcp;
1650{
1651 if (entering(tcp)) {
1652 printxval(procpriv_cmds, tcp->u_arg[0], "???PRV");
1653 switch (tcp->u_arg[0]) {
1654 case CNTPRV:
1655 tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
1656 break;
1657
1658 case GETPRV:
1659 break;
1660
1661 default:
1662 tprintf (", ");
1663 printpriv (tcp, tcp->u_arg[1], tcp->u_arg[2]);
1664 tprintf (", %ld", tcp->u_arg[2]);
1665 }
1666 }
1667 else if (tcp->u_arg[0] == GETPRV) {
1668 if (syserror (tcp)) {
1669 tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
1670 }
1671 else {
1672 tprintf (", ");
1673 printpriv (tcp, tcp->u_arg[1], tcp->u_rval);
1674 tprintf (", %ld", tcp->u_arg[2]);
1675 }
1676 }
1677
1678 return 0;
1679}
1680
1681#endif
1682
1683
1684static void
1685printargv(tcp, addr)
1686struct tcb *tcp;
1687long addr;
1688{
1689 union {
1690 int p32;
1691 long p64;
1692 char data[sizeof(long)];
1693 } cp;
1694 char *sep;
1695 int n = 0;
1696
1697 cp.p64 = 1;
1698 for (sep = ""; !abbrev(tcp) || n < max_strlen / 2; sep = ", ", ++n) {
1699 if (umoven(tcp, addr, personality_wordsize[current_personality],
1700 cp.data) < 0) {
1701 tprintf("%#lx", addr);
1702 return;
1703 }
1704 if (personality_wordsize[current_personality] == 4)
1705 cp.p64 = cp.p32;
1706 if (cp.p64 == 0)
1707 break;
1708 tprintf("%s", sep);
1709 printstr(tcp, cp.p64, -1);
1710 addr += personality_wordsize[current_personality];
1711 }
1712 if (cp.p64)
1713 tprintf("%s...", sep);
1714}
1715
1716static void
1717printargc(fmt, tcp, addr)
1718char *fmt;
1719struct tcb *tcp;
1720long addr;
1721{
1722 int count;
1723 char *cp;
1724
1725 for (count = 0; umove(tcp, addr, &cp) >= 0 && cp != NULL; count++) {
1726 addr += sizeof(char *);
1727 }
1728 tprintf(fmt, count, count == 1 ? "" : "s");
1729}
1730
1731int
1732sys_execv(tcp)
1733struct tcb *tcp;
1734{
1735 if (entering(tcp)) {
1736 printpath(tcp, tcp->u_arg[0]);
1737 if (!verbose(tcp))
1738 tprintf(", %#lx", tcp->u_arg[1]);
1739#if 0
1740 else if (abbrev(tcp))
1741 printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
1742#endif
1743 else {
1744 tprintf(", [");
1745 printargv(tcp, tcp->u_arg[1]);
1746 tprintf("]");
1747 }
1748 }
1749 return 0;
1750}
1751
1752int
1753sys_execve(tcp)
1754struct tcb *tcp;
1755{
1756 if (entering(tcp)) {
1757 printpath(tcp, tcp->u_arg[0]);
1758 if (!verbose(tcp))
1759 tprintf(", %#lx", tcp->u_arg[1]);
1760#if 0
1761 else if (abbrev(tcp))
1762 printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
1763#endif
1764 else {
1765 tprintf(", [");
1766 printargv(tcp, tcp->u_arg[1]);
1767 tprintf("]");
1768 }
1769 if (!verbose(tcp))
1770 tprintf(", %#lx", tcp->u_arg[2]);
1771 else if (abbrev(tcp))
1772 printargc(", [/* %d var%s */]", tcp, tcp->u_arg[2]);
1773 else {
1774 tprintf(", [");
1775 printargv(tcp, tcp->u_arg[2]);
1776 tprintf("]");
1777 }
1778 }
1779 return 0;
1780}
1781
1782#if UNIXWARE > 2
1783
1784int sys_rexecve(tcp)
1785struct tcb *tcp;
1786{
1787 if (entering (tcp)) {
1788 sys_execve (tcp);
1789 tprintf (", %ld", tcp->u_arg[3]);
1790 }
1791 return 0;
1792}
1793
1794#endif
1795
1796int
1797internal_exec(tcp)
1798struct tcb *tcp;
1799{
1800#ifdef SUNOS4
1801 if (exiting(tcp) && !syserror(tcp) && followfork)
1802 fixvfork(tcp);
1803#endif /* SUNOS4 */
1804#if defined LINUX && defined TCB_WAITEXECVE
1805 if (exiting(tcp) && syserror(tcp))
1806 tcp->flags &= ~TCB_WAITEXECVE;
1807 else
1808 tcp->flags |= TCB_WAITEXECVE;
1809#endif /* LINUX && TCB_WAITEXECVE */
1810 return 0;
1811}
1812
1813#ifdef LINUX
1814#ifndef __WNOTHREAD
1815#define __WNOTHREAD 0x20000000
1816#endif
1817#ifndef __WALL
1818#define __WALL 0x40000000
1819#endif
1820#ifndef __WCLONE
1821#define __WCLONE 0x80000000
1822#endif
1823#endif /* LINUX */
1824
1825static const struct xlat wait4_options[] = {
1826 { WNOHANG, "WNOHANG" },
1827#ifndef WSTOPPED
1828 { WUNTRACED, "WUNTRACED" },
1829#endif
1830#ifdef WEXITED
1831 { WEXITED, "WEXITED" },
1832#endif
1833#ifdef WTRAPPED
1834 { WTRAPPED, "WTRAPPED" },
1835#endif
1836#ifdef WSTOPPED
1837 { WSTOPPED, "WSTOPPED" },
1838#endif
1839#ifdef WCONTINUED
1840 { WCONTINUED, "WCONTINUED" },
1841#endif
1842#ifdef WNOWAIT
1843 { WNOWAIT, "WNOWAIT" },
1844#endif
1845#ifdef __WCLONE
1846 { __WCLONE, "__WCLONE" },
1847#endif
1848#ifdef __WALL
1849 { __WALL, "__WALL" },
1850#endif
1851#ifdef __WNOTHREAD
1852 { __WNOTHREAD, "__WNOTHREAD" },
1853#endif
1854 { 0, NULL },
1855};
1856
1857#if !defined WCOREFLAG && defined WCOREFLG
1858# define WCOREFLAG WCOREFLG
1859#endif
1860#ifndef WCOREFLAG
1861#define WCOREFLAG 0x80
1862#endif
1863
1864#ifndef W_STOPCODE
1865#define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
1866#endif
1867#ifndef W_EXITCODE
1868#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
1869#endif
1870
1871static int
1872printstatus(status)
1873int status;
1874{
1875 int exited = 0;
1876
1877 /*
1878 * Here is a tricky presentation problem. This solution
1879 * is still not entirely satisfactory but since there
1880 * are no wait status constructors it will have to do.
1881 */
1882 if (WIFSTOPPED(status)) {
1883 tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s}",
1884 signame(WSTOPSIG(status)));
1885 status &= ~W_STOPCODE(WSTOPSIG(status));
1886 }
1887 else if (WIFSIGNALED(status)) {
1888 tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
1889 signame(WTERMSIG(status)),
1890 WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
1891 status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
1892 }
1893 else if (WIFEXITED(status)) {
1894 tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
1895 WEXITSTATUS(status));
1896 exited = 1;
1897 status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
1898 }
1899 else {
1900 tprintf("[%#x]", status);
1901 return 0;
1902 }
1903
1904 if (status == 0)
1905 tprintf("]");
1906 else
1907 tprintf(" | %#x]", status);
1908
1909 return exited;
1910}
1911
1912static int
1913printwaitn(tcp, n, bitness)
1914struct tcb *tcp;
1915int n;
1916int bitness;
1917{
1918 int status;
1919 int exited = 0;
1920
1921 if (entering(tcp)) {
1922 tprintf("%ld, ", tcp->u_arg[0]);
1923 } else {
1924 /* status */
1925 if (!tcp->u_arg[1])
1926 tprintf("NULL");
1927 else if (syserror(tcp) || tcp->u_rval == 0)
1928 tprintf("%#lx", tcp->u_arg[1]);
1929 else if (umove(tcp, tcp->u_arg[1], &status) < 0)
1930 tprintf("[?]");
1931 else
1932 exited = printstatus(status);
1933 /* options */
1934 tprintf(", ");
1935 printflags(wait4_options, tcp->u_arg[2], "W???");
1936 if (n == 4) {
1937 tprintf(", ");
1938 /* usage */
1939 if (!tcp->u_arg[3])
1940 tprintf("NULL");
1941#ifdef LINUX
1942 else if (tcp->u_rval > 0) {
1943#ifdef LINUX_64BIT
1944 if (bitness)
1945 printrusage32(tcp, tcp->u_arg[3]);
1946 else
1947#endif
1948 printrusage(tcp, tcp->u_arg[3]);
1949 }
1950#endif /* LINUX */
1951#ifdef SUNOS4
1952 else if (tcp->u_rval > 0 && exited)
1953 printrusage(tcp, tcp->u_arg[3]);
1954#endif /* SUNOS4 */
1955 else
1956 tprintf("%#lx", tcp->u_arg[3]);
1957 }
1958 }
1959 return 0;
1960}
1961
1962int
1963internal_wait(tcp, flagarg)
1964struct tcb *tcp;
1965int flagarg;
1966{
1967 int got_kids;
1968
1969#ifdef TCB_CLONE_THREAD
1970 if (tcp->flags & TCB_CLONE_THREAD)
1971 /* The children we wait for are our parent's children. */
1972 got_kids = (tcp->parent->nchildren
1973 > tcp->parent->nclone_detached);
1974 else
1975 got_kids = (tcp->nchildren > tcp->nclone_detached);
1976#else
1977 got_kids = tcp->nchildren > 0;
1978#endif
1979
1980 if (entering(tcp) && got_kids) {
1981 /* There are children that this parent should block for.
1982 But ptrace made us the parent of the traced children
1983 and the real parent will get ECHILD from the wait call.
1984
1985 XXX If we attached with strace -f -p PID, then there
1986 may be untraced dead children the parent could be reaping
1987 now, but we make him block. */
1988
1989 /* ??? WTA: fix bug with hanging children */
1990
1991 if (!(tcp->u_arg[flagarg] & WNOHANG)) {
1992 /*
1993 * There are traced children. We'll make the parent
1994 * block to avoid a false ECHILD error due to our
1995 * ptrace having stolen the children. However,
1996 * we shouldn't block if there are zombies to reap.
1997 * XXX doesn't handle pgrp matches (u_arg[0]==0,<-1)
1998 */
1999 struct tcb *child = NULL;
2000 if (tcp->nzombies > 0 &&
2001 (tcp->u_arg[0] == -1 ||
2002 (child = pid2tcb(tcp->u_arg[0])) == NULL))
2003 return 0;
2004 if (tcp->u_arg[0] > 0) {
2005 /*
2006 * If the parent waits for a specified child
2007 * PID, then it must get ECHILD right away
2008 * if that PID is not one of its children.
2009 * Make sure that the requested PID matches
2010 * one of the parent's children that we are
2011 * tracing, and don't suspend it otherwise.
2012 */
2013 if (child == NULL)
2014 child = pid2tcb(tcp->u_arg[0]);
2015 if (child == NULL || child->parent != (
2016#ifdef TCB_CLONE_THREAD
2017 (tcp->flags & TCB_CLONE_THREAD)
2018 ? tcp->parent :
2019#endif
2020 tcp) ||
2021 (child->flags & TCB_EXITING))
2022 return 0;
2023 }
2024 tcp->flags |= TCB_SUSPENDED;
2025 tcp->waitpid = tcp->u_arg[0];
2026#ifdef TCB_CLONE_THREAD
2027 if (tcp->flags & TCB_CLONE_THREAD)
2028 tcp->parent->nclone_waiting++;
2029#endif
2030 }
2031 }
2032 if (exiting(tcp) && tcp->u_error == ECHILD && got_kids) {
2033 if (tcp->u_arg[flagarg] & WNOHANG) {
2034 /* We must force a fake result of 0 instead of
2035 the ECHILD error. */
2036 extern int force_result();
2037 return force_result(tcp, 0, 0);
2038 }
2039 }
2040 else if (exiting(tcp) && tcp->u_error == 0 && tcp->u_rval > 0 &&
2041 tcp->nzombies > 0 && pid2tcb(tcp->u_rval) == NULL) {
2042 /*
2043 * We just reaped a child we don't know about,
2044 * presumably a zombie we already droptcb'd.
2045 */
2046 tcp->nzombies--;
2047 }
2048 return 0;
2049}
2050
2051#ifdef SVR4
2052
2053int
2054sys_wait(tcp)
2055struct tcb *tcp;
2056{
2057 if (exiting(tcp)) {
2058 /* The library wrapper stuffs this into the user variable. */
2059 if (!syserror(tcp))
2060 printstatus(getrval2(tcp));
2061 }
2062 return 0;
2063}
2064
2065#endif /* SVR4 */
2066
2067#ifdef FREEBSD
2068int
2069sys_wait(tcp)
2070struct tcb *tcp;
2071{
2072 int status;
2073
2074 if (exiting(tcp)) {
2075 if (!syserror(tcp)) {
2076 if (umove(tcp, tcp->u_arg[0], &status) < 0)
2077 tprintf("%#lx", tcp->u_arg[0]);
2078 else
2079 printstatus(status);
2080 }
2081 }
2082 return 0;
2083}
2084#endif
2085
2086int
2087sys_waitpid(tcp)
2088struct tcb *tcp;
2089{
2090 return printwaitn(tcp, 3, 0);
2091}
2092
2093int
2094sys_wait4(tcp)
2095struct tcb *tcp;
2096{
2097 return printwaitn(tcp, 4, 0);
2098}
2099
2100#ifdef ALPHA
2101int
2102sys_osf_wait4(tcp)
2103struct tcb *tcp;
2104{
2105 return printwaitn(tcp, 4, 1);
2106}
2107#endif
2108
2109#if defined SVR4 || defined LINUX
2110
2111static const struct xlat waitid_types[] = {
2112 { P_PID, "P_PID" },
2113#ifdef P_PPID
2114 { P_PPID, "P_PPID" },
2115#endif
2116 { P_PGID, "P_PGID" },
2117#ifdef P_SID
2118 { P_SID, "P_SID" },
2119#endif
2120#ifdef P_CID
2121 { P_CID, "P_CID" },
2122#endif
2123#ifdef P_UID
2124 { P_UID, "P_UID" },
2125#endif
2126#ifdef P_GID
2127 { P_GID, "P_GID" },
2128#endif
2129 { P_ALL, "P_ALL" },
2130#ifdef P_LWPID
2131 { P_LWPID, "P_LWPID" },
2132#endif
2133 { 0, NULL },
2134};
2135
2136int
2137sys_waitid(tcp)
2138struct tcb *tcp;
2139{
2140 siginfo_t si;
2141 int exited;
2142
2143 if (entering(tcp)) {
2144 printxval(waitid_types, tcp->u_arg[0], "P_???");
2145 tprintf(", %ld, ", tcp->u_arg[1]);
2146 }
2147 else {
2148 /* siginfo */
2149 exited = 0;
2150 if (!tcp->u_arg[2])
2151 tprintf("NULL");
2152 else if (syserror(tcp))
2153 tprintf("%#lx", tcp->u_arg[2]);
2154 else if (umove(tcp, tcp->u_arg[2], &si) < 0)
2155 tprintf("{???}");
2156 else
2157 printsiginfo(&si, verbose (tcp));
2158 /* options */
2159 tprintf(", ");
2160 printflags(wait4_options, tcp->u_arg[3], "W???");
2161 if (tcp->u_nargs > 4) {
2162 /* usage */
2163 tprintf(", ");
2164 if (!tcp->u_arg[4])
2165 tprintf("NULL");
2166 else if (tcp->u_error)
2167 tprintf("%#lx", tcp->u_arg[4]);
2168 else
2169 printrusage(tcp, tcp->u_arg[4]);
2170 }
2171 }
2172 return 0;
2173}
2174
2175#endif /* SVR4 or LINUX */
2176
2177int
2178sys_alarm(tcp)
2179struct tcb *tcp;
2180{
2181 if (entering(tcp))
2182 tprintf("%lu", tcp->u_arg[0]);
2183 return 0;
2184}
2185
2186int
2187sys_uname(tcp)
2188struct tcb *tcp;
2189{
2190 struct utsname uname;
2191
2192 if (exiting(tcp)) {
2193 if (syserror(tcp) || !verbose(tcp))
2194 tprintf("%#lx", tcp->u_arg[0]);
2195 else if (umove(tcp, tcp->u_arg[0], &uname) < 0)
2196 tprintf("{...}");
2197 else if (!abbrev(tcp)) {
2198
2199 tprintf("{sysname=\"%s\", nodename=\"%s\", ",
2200 uname.sysname, uname.nodename);
2201 tprintf("release=\"%s\", version=\"%s\", ",
2202 uname.release, uname.version);
2203 tprintf("machine=\"%s\"", uname.machine);
2204#ifdef LINUX
2205#ifndef __GLIBC__
2206 tprintf(", domainname=\"%s\"", uname.domainname);
2207#endif /* __GLIBC__ */
2208#endif /* LINUX */
2209 tprintf("}");
2210 }
2211 else
2212 tprintf("{sys=\"%s\", node=\"%s\", ...}",
2213 uname.sysname, uname.nodename);
2214 }
2215 return 0;
2216}
2217
2218#ifndef SVR4
2219
2220static const struct xlat ptrace_cmds[] = {
2221#ifndef FREEBSD
2222 { PTRACE_TRACEME, "PTRACE_TRACEME" },
2223 { PTRACE_PEEKTEXT, "PTRACE_PEEKTEXT", },
2224 { PTRACE_PEEKDATA, "PTRACE_PEEKDATA", },
2225 { PTRACE_PEEKUSER, "PTRACE_PEEKUSER", },
2226 { PTRACE_POKETEXT, "PTRACE_POKETEXT", },
2227 { PTRACE_POKEDATA, "PTRACE_POKEDATA", },
2228 { PTRACE_POKEUSER, "PTRACE_POKEUSER", },
2229 { PTRACE_CONT, "PTRACE_CONT" },
2230 { PTRACE_KILL, "PTRACE_KILL" },
2231 { PTRACE_SINGLESTEP, "PTRACE_SINGLESTEP" },
2232 { PTRACE_ATTACH, "PTRACE_ATTACH" },
2233 { PTRACE_DETACH, "PTRACE_DETACH" },
2234#ifdef PTRACE_GETREGS
2235 { PTRACE_GETREGS, "PTRACE_GETREGS" },
2236#endif
2237#ifdef PTRACE_SETREGS
2238 { PTRACE_SETREGS, "PTRACE_SETREGS" },
2239#endif
2240#ifdef PTRACE_GETFPREGS
2241 { PTRACE_GETFPREGS, "PTRACE_GETFPREGS", },
2242#endif
2243#ifdef PTRACE_SETFPREGS
2244 { PTRACE_SETFPREGS, "PTRACE_SETFPREGS", },
2245#endif
2246#ifdef PTRACE_GETFPXREGS
2247 { PTRACE_GETFPXREGS, "PTRACE_GETFPXREGS", },
2248#endif
2249#ifdef PTRACE_SETFPXREGS
2250 { PTRACE_SETFPXREGS, "PTRACE_SETFPXREGS", },
2251#endif
2252#ifdef PTRACE_GETVRREGS
2253 { PTRACE_GETVRREGS, "PTRACE_GETVRREGS", },
2254#endif
2255#ifdef PTRACE_SETVRREGS
2256 { PTRACE_SETVRREGS, "PTRACE_SETVRREGS", },
2257#endif
2258#ifdef SUNOS4
2259 { PTRACE_READDATA, "PTRACE_READDATA" },
2260 { PTRACE_WRITEDATA, "PTRACE_WRITEDATA" },
2261 { PTRACE_READTEXT, "PTRACE_READTEXT" },
2262 { PTRACE_WRITETEXT, "PTRACE_WRITETEXT" },
2263 { PTRACE_GETFPAREGS, "PTRACE_GETFPAREGS" },
2264 { PTRACE_SETFPAREGS, "PTRACE_SETFPAREGS" },
2265#ifdef SPARC
2266 { PTRACE_GETWINDOW, "PTRACE_GETWINDOW" },
2267 { PTRACE_SETWINDOW, "PTRACE_SETWINDOW" },
2268#else /* !SPARC */
2269 { PTRACE_22, "PTRACE_PTRACE_22" },
2270 { PTRACE_23, "PTRACE_PTRACE_23" },
2271#endif /* !SPARC */
2272#endif /* SUNOS4 */
2273 { PTRACE_SYSCALL, "PTRACE_SYSCALL" },
2274#ifdef SUNOS4
2275 { PTRACE_DUMPCORE, "PTRACE_DUMPCORE" },
2276#ifdef I386
2277 { PTRACE_SETWRBKPT, "PTRACE_SETWRBKPT" },
2278 { PTRACE_SETACBKPT, "PTRACE_SETACBKPT" },
2279 { PTRACE_CLRDR7, "PTRACE_CLRDR7" },
2280#else /* !I386 */
2281 { PTRACE_26, "PTRACE_26" },
2282 { PTRACE_27, "PTRACE_27" },
2283 { PTRACE_28, "PTRACE_28" },
2284#endif /* !I386 */
2285 { PTRACE_GETUCODE, "PTRACE_GETUCODE" },
2286#endif /* SUNOS4 */
2287#else /* FREEBSD */
2288 { PT_TRACE_ME, "PT_TRACE_ME" },
2289 { PT_READ_I, "PT_READ_I" },
2290 { PT_READ_D, "PT_READ_D" },
2291 { PT_WRITE_I, "PT_WRITE_I" },
2292 { PT_WRITE_D, "PT_WRITE_D" },
2293#ifdef PT_READ_U
2294 { PT_READ_U, "PT_READ_U" },
2295#endif
2296 { PT_CONTINUE, "PT_CONTINUE" },
2297 { PT_KILL, "PT_KILL" },
2298 { PT_STEP, "PT_STEP" },
2299 { PT_ATTACH, "PT_ATTACH" },
2300 { PT_DETACH, "PT_DETACH" },
2301 { PT_GETREGS, "PT_GETREGS" },
2302 { PT_SETREGS, "PT_SETREGS" },
2303 { PT_GETFPREGS, "PT_GETFPREGS" },
2304 { PT_SETFPREGS, "PT_SETFPREGS" },
2305 { PT_GETDBREGS, "PT_GETDBREGS" },
2306 { PT_SETDBREGS, "PT_SETDBREGS" },
2307#endif /* FREEBSD */
2308 { 0, NULL },
2309};
2310
2311#ifndef FREEBSD
2312#ifndef SUNOS4_KERNEL_ARCH_KLUDGE
2313static
2314#endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
2315const struct xlat struct_user_offsets[] = {
2316#ifdef LINUX
2317#if defined(S390) || defined(S390X)
2318 { PT_PSWMASK, "psw_mask" },
2319 { PT_PSWADDR, "psw_addr" },
2320 { PT_GPR0, "gpr0" },
2321 { PT_GPR1, "gpr1" },
2322 { PT_GPR2, "gpr2" },
2323 { PT_GPR3, "gpr3" },
2324 { PT_GPR4, "gpr4" },
2325 { PT_GPR5, "gpr5" },
2326 { PT_GPR6, "gpr6" },
2327 { PT_GPR7, "gpr7" },
2328 { PT_GPR8, "gpr8" },
2329 { PT_GPR9, "gpr9" },
2330 { PT_GPR10, "gpr10" },
2331 { PT_GPR11, "gpr11" },
2332 { PT_GPR12, "gpr12" },
2333 { PT_GPR13, "gpr13" },
2334 { PT_GPR14, "gpr14" },
2335 { PT_GPR15, "gpr15" },
2336 { PT_ACR0, "acr0" },
2337 { PT_ACR1, "acr1" },
2338 { PT_ACR2, "acr2" },
2339 { PT_ACR3, "acr3" },
2340 { PT_ACR4, "acr4" },
2341 { PT_ACR5, "acr5" },
2342 { PT_ACR6, "acr6" },
2343 { PT_ACR7, "acr7" },
2344 { PT_ACR8, "acr8" },
2345 { PT_ACR9, "acr9" },
2346 { PT_ACR10, "acr10" },
2347 { PT_ACR11, "acr11" },
2348 { PT_ACR12, "acr12" },
2349 { PT_ACR13, "acr13" },
2350 { PT_ACR14, "acr14" },
2351 { PT_ACR15, "acr15" },
2352 { PT_ORIGGPR2, "orig_gpr2" },
2353 { PT_FPC, "fpc" },
2354#if defined(S390)
2355 { PT_FPR0_HI, "fpr0.hi" },
2356 { PT_FPR0_LO, "fpr0.lo" },
2357 { PT_FPR1_HI, "fpr1.hi" },
2358 { PT_FPR1_LO, "fpr1.lo" },
2359 { PT_FPR2_HI, "fpr2.hi" },
2360 { PT_FPR2_LO, "fpr2.lo" },
2361 { PT_FPR3_HI, "fpr3.hi" },
2362 { PT_FPR3_LO, "fpr3.lo" },
2363 { PT_FPR4_HI, "fpr4.hi" },
2364 { PT_FPR4_LO, "fpr4.lo" },
2365 { PT_FPR5_HI, "fpr5.hi" },
2366 { PT_FPR5_LO, "fpr5.lo" },
2367 { PT_FPR6_HI, "fpr6.hi" },
2368 { PT_FPR6_LO, "fpr6.lo" },
2369 { PT_FPR7_HI, "fpr7.hi" },
2370 { PT_FPR7_LO, "fpr7.lo" },
2371 { PT_FPR8_HI, "fpr8.hi" },
2372 { PT_FPR8_LO, "fpr8.lo" },
2373 { PT_FPR9_HI, "fpr9.hi" },
2374 { PT_FPR9_LO, "fpr9.lo" },
2375 { PT_FPR10_HI, "fpr10.hi" },
2376 { PT_FPR10_LO, "fpr10.lo" },
2377 { PT_FPR11_HI, "fpr11.hi" },
2378 { PT_FPR11_LO, "fpr11.lo" },
2379 { PT_FPR12_HI, "fpr12.hi" },
2380 { PT_FPR12_LO, "fpr12.lo" },
2381 { PT_FPR13_HI, "fpr13.hi" },
2382 { PT_FPR13_LO, "fpr13.lo" },
2383 { PT_FPR14_HI, "fpr14.hi" },
2384 { PT_FPR14_LO, "fpr14.lo" },
2385 { PT_FPR15_HI, "fpr15.hi" },
2386 { PT_FPR15_LO, "fpr15.lo" },
2387#endif
2388#if defined(S390X)
2389 { PT_FPR0, "fpr0" },
2390 { PT_FPR1, "fpr1" },
2391 { PT_FPR2, "fpr2" },
2392 { PT_FPR3, "fpr3" },
2393 { PT_FPR4, "fpr4" },
2394 { PT_FPR5, "fpr5" },
2395 { PT_FPR6, "fpr6" },
2396 { PT_FPR7, "fpr7" },
2397 { PT_FPR8, "fpr8" },
2398 { PT_FPR9, "fpr9" },
2399 { PT_FPR10, "fpr10" },
2400 { PT_FPR11, "fpr11" },
2401 { PT_FPR12, "fpr12" },
2402 { PT_FPR13, "fpr13" },
2403 { PT_FPR14, "fpr14" },
2404 { PT_FPR15, "fpr15" },
2405#endif
2406 { PT_CR_9, "cr9" },
2407 { PT_CR_10, "cr10" },
2408 { PT_CR_11, "cr11" },
2409 { PT_IEEE_IP, "ieee_exception_ip" },
2410#endif
2411#if defined(SPARC)
2412 /* XXX No support for these offsets yet. */
2413#elif defined(HPPA)
2414 /* XXX No support for these offsets yet. */
2415#elif defined(POWERPC)
2416#ifndef PT_ORIG_R3
2417#define PT_ORIG_R3 34
2418#endif
2419#define REGSIZE (sizeof(unsigned long))
2420 { REGSIZE*PT_R0, "r0" },
2421 { REGSIZE*PT_R1, "r1" },
2422 { REGSIZE*PT_R2, "r2" },
2423 { REGSIZE*PT_R3, "r3" },
2424 { REGSIZE*PT_R4, "r4" },
2425 { REGSIZE*PT_R5, "r5" },
2426 { REGSIZE*PT_R6, "r6" },
2427 { REGSIZE*PT_R7, "r7" },
2428 { REGSIZE*PT_R8, "r8" },
2429 { REGSIZE*PT_R9, "r9" },
2430 { REGSIZE*PT_R10, "r10" },
2431 { REGSIZE*PT_R11, "r11" },
2432 { REGSIZE*PT_R12, "r12" },
2433 { REGSIZE*PT_R13, "r13" },
2434 { REGSIZE*PT_R14, "r14" },
2435 { REGSIZE*PT_R15, "r15" },
2436 { REGSIZE*PT_R16, "r16" },
2437 { REGSIZE*PT_R17, "r17" },
2438 { REGSIZE*PT_R18, "r18" },
2439 { REGSIZE*PT_R19, "r19" },
2440 { REGSIZE*PT_R20, "r20" },
2441 { REGSIZE*PT_R21, "r21" },
2442 { REGSIZE*PT_R22, "r22" },
2443 { REGSIZE*PT_R23, "r23" },
2444 { REGSIZE*PT_R24, "r24" },
2445 { REGSIZE*PT_R25, "r25" },
2446 { REGSIZE*PT_R26, "r26" },
2447 { REGSIZE*PT_R27, "r27" },
2448 { REGSIZE*PT_R28, "r28" },
2449 { REGSIZE*PT_R29, "r29" },
2450 { REGSIZE*PT_R30, "r30" },
2451 { REGSIZE*PT_R31, "r31" },
2452 { REGSIZE*PT_NIP, "NIP" },
2453 { REGSIZE*PT_MSR, "MSR" },
2454 { REGSIZE*PT_ORIG_R3, "ORIG_R3" },
2455 { REGSIZE*PT_CTR, "CTR" },
2456 { REGSIZE*PT_LNK, "LNK" },
2457 { REGSIZE*PT_XER, "XER" },
2458 { REGSIZE*PT_CCR, "CCR" },
2459 { REGSIZE*PT_FPR0, "FPR0" },
2460#undef REGSIZE
2461#else
2462#ifdef ALPHA
2463 { 0, "r0" },
2464 { 1, "r1" },
2465 { 2, "r2" },
2466 { 3, "r3" },
2467 { 4, "r4" },
2468 { 5, "r5" },
2469 { 6, "r6" },
2470 { 7, "r7" },
2471 { 8, "r8" },
2472 { 9, "r9" },
2473 { 10, "r10" },
2474 { 11, "r11" },
2475 { 12, "r12" },
2476 { 13, "r13" },
2477 { 14, "r14" },
2478 { 15, "r15" },
2479 { 16, "r16" },
2480 { 17, "r17" },
2481 { 18, "r18" },
2482 { 19, "r19" },
2483 { 20, "r20" },
2484 { 21, "r21" },
2485 { 22, "r22" },
2486 { 23, "r23" },
2487 { 24, "r24" },
2488 { 25, "r25" },
2489 { 26, "r26" },
2490 { 27, "r27" },
2491 { 28, "r28" },
2492 { 29, "gp" },
2493 { 30, "fp" },
2494 { 31, "zero" },
2495 { 32, "fp0" },
2496 { 33, "fp" },
2497 { 34, "fp2" },
2498 { 35, "fp3" },
2499 { 36, "fp4" },
2500 { 37, "fp5" },
2501 { 38, "fp6" },
2502 { 39, "fp7" },
2503 { 40, "fp8" },
2504 { 41, "fp9" },
2505 { 42, "fp10" },
2506 { 43, "fp11" },
2507 { 44, "fp12" },
2508 { 45, "fp13" },
2509 { 46, "fp14" },
2510 { 47, "fp15" },
2511 { 48, "fp16" },
2512 { 49, "fp17" },
2513 { 50, "fp18" },
2514 { 51, "fp19" },
2515 { 52, "fp20" },
2516 { 53, "fp21" },
2517 { 54, "fp22" },
2518 { 55, "fp23" },
2519 { 56, "fp24" },
2520 { 57, "fp25" },
2521 { 58, "fp26" },
2522 { 59, "fp27" },
2523 { 60, "fp28" },
2524 { 61, "fp29" },
2525 { 62, "fp30" },
2526 { 63, "fp31" },
2527 { 64, "pc" },
2528#else /* !ALPHA */
2529#ifdef IA64
2530 { PT_F32, "f32" }, { PT_F33, "f33" }, { PT_F34, "f34" },
2531 { PT_F35, "f35" }, { PT_F36, "f36" }, { PT_F37, "f37" },
2532 { PT_F38, "f38" }, { PT_F39, "f39" }, { PT_F40, "f40" },
2533 { PT_F41, "f41" }, { PT_F42, "f42" }, { PT_F43, "f43" },
2534 { PT_F44, "f44" }, { PT_F45, "f45" }, { PT_F46, "f46" },
2535 { PT_F47, "f47" }, { PT_F48, "f48" }, { PT_F49, "f49" },
2536 { PT_F50, "f50" }, { PT_F51, "f51" }, { PT_F52, "f52" },
2537 { PT_F53, "f53" }, { PT_F54, "f54" }, { PT_F55, "f55" },
2538 { PT_F56, "f56" }, { PT_F57, "f57" }, { PT_F58, "f58" },
2539 { PT_F59, "f59" }, { PT_F60, "f60" }, { PT_F61, "f61" },
2540 { PT_F62, "f62" }, { PT_F63, "f63" }, { PT_F64, "f64" },
2541 { PT_F65, "f65" }, { PT_F66, "f66" }, { PT_F67, "f67" },
2542 { PT_F68, "f68" }, { PT_F69, "f69" }, { PT_F70, "f70" },
2543 { PT_F71, "f71" }, { PT_F72, "f72" }, { PT_F73, "f73" },
2544 { PT_F74, "f74" }, { PT_F75, "f75" }, { PT_F76, "f76" },
2545 { PT_F77, "f77" }, { PT_F78, "f78" }, { PT_F79, "f79" },
2546 { PT_F80, "f80" }, { PT_F81, "f81" }, { PT_F82, "f82" },
2547 { PT_F83, "f83" }, { PT_F84, "f84" }, { PT_F85, "f85" },
2548 { PT_F86, "f86" }, { PT_F87, "f87" }, { PT_F88, "f88" },
2549 { PT_F89, "f89" }, { PT_F90, "f90" }, { PT_F91, "f91" },
2550 { PT_F92, "f92" }, { PT_F93, "f93" }, { PT_F94, "f94" },
2551 { PT_F95, "f95" }, { PT_F96, "f96" }, { PT_F97, "f97" },
2552 { PT_F98, "f98" }, { PT_F99, "f99" }, { PT_F100, "f100" },
2553 { PT_F101, "f101" }, { PT_F102, "f102" }, { PT_F103, "f103" },
2554 { PT_F104, "f104" }, { PT_F105, "f105" }, { PT_F106, "f106" },
2555 { PT_F107, "f107" }, { PT_F108, "f108" }, { PT_F109, "f109" },
2556 { PT_F110, "f110" }, { PT_F111, "f111" }, { PT_F112, "f112" },
2557 { PT_F113, "f113" }, { PT_F114, "f114" }, { PT_F115, "f115" },
2558 { PT_F116, "f116" }, { PT_F117, "f117" }, { PT_F118, "f118" },
2559 { PT_F119, "f119" }, { PT_F120, "f120" }, { PT_F121, "f121" },
2560 { PT_F122, "f122" }, { PT_F123, "f123" }, { PT_F124, "f124" },
2561 { PT_F125, "f125" }, { PT_F126, "f126" }, { PT_F127, "f127" },
2562 /* switch stack: */
2563 { PT_F2, "f2" }, { PT_F3, "f3" }, { PT_F4, "f4" },
2564 { PT_F5, "f5" }, { PT_F10, "f10" }, { PT_F11, "f11" },
2565 { PT_F12, "f12" }, { PT_F13, "f13" }, { PT_F14, "f14" },
2566 { PT_F15, "f15" }, { PT_F16, "f16" }, { PT_F17, "f17" },
2567 { PT_F18, "f18" }, { PT_F19, "f19" }, { PT_F20, "f20" },
2568 { PT_F21, "f21" }, { PT_F22, "f22" }, { PT_F23, "f23" },
2569 { PT_F24, "f24" }, { PT_F25, "f25" }, { PT_F26, "f26" },
2570 { PT_F27, "f27" }, { PT_F28, "f28" }, { PT_F29, "f29" },
2571 { PT_F30, "f30" }, { PT_F31, "f31" }, { PT_R4, "r4" },
2572 { PT_R5, "r5" }, { PT_R6, "r6" }, { PT_R7, "r7" },
2573 { PT_B1, "b1" }, { PT_B2, "b2" }, { PT_B3, "b3" },
2574 { PT_B4, "b4" }, { PT_B5, "b5" },
2575 { PT_AR_EC, "ar.ec" }, { PT_AR_LC, "ar.lc" },
2576 /* pt_regs */
2577 { PT_CR_IPSR, "psr" }, { PT_CR_IIP, "ip" },
2578 { PT_CFM, "cfm" }, { PT_AR_UNAT, "ar.unat" },
2579 { PT_AR_PFS, "ar.pfs" }, { PT_AR_RSC, "ar.rsc" },
2580 { PT_AR_RNAT, "ar.rnat" }, { PT_AR_BSPSTORE, "ar.bspstore" },
2581 { PT_PR, "pr" }, { PT_B6, "b6" }, { PT_AR_BSP, "ar.bsp" },
2582 { PT_R1, "r1" }, { PT_R2, "r2" }, { PT_R3, "r3" },
2583 { PT_R12, "r12" }, { PT_R13, "r13" }, { PT_R14, "r14" },
2584 { PT_R15, "r15" }, { PT_R8, "r8" }, { PT_R9, "r9" },
2585 { PT_R10, "r10" }, { PT_R11, "r11" }, { PT_R16, "r16" },
2586 { PT_R17, "r17" }, { PT_R18, "r18" }, { PT_R19, "r19" },
2587 { PT_R20, "r20" }, { PT_R21, "r21" }, { PT_R22, "r22" },
2588 { PT_R23, "r23" }, { PT_R24, "r24" }, { PT_R25, "r25" },
2589 { PT_R26, "r26" }, { PT_R27, "r27" }, { PT_R28, "r28" },
2590 { PT_R29, "r29" }, { PT_R30, "r30" }, { PT_R31, "r31" },
2591 { PT_AR_CCV, "ar.ccv" }, { PT_AR_FPSR, "ar.fpsr" },
2592 { PT_B0, "b0" }, { PT_B7, "b7" }, { PT_F6, "f6" },
2593 { PT_F7, "f7" }, { PT_F8, "f8" }, { PT_F9, "f9" },
2594# ifdef PT_AR_CSD
2595 { PT_AR_CSD, "ar.csd" },
2596# endif
2597# ifdef PT_AR_SSD
2598 { PT_AR_SSD, "ar.ssd" },
2599# endif
2600 { PT_DBR, "dbr" }, { PT_IBR, "ibr" }, { PT_PMD, "pmd" },
2601#else /* !IA64 */
2602#ifdef I386
2603 { 4*EBX, "4*EBX" },
2604 { 4*ECX, "4*ECX" },
2605 { 4*EDX, "4*EDX" },
2606 { 4*ESI, "4*ESI" },
2607 { 4*EDI, "4*EDI" },
2608 { 4*EBP, "4*EBP" },
2609 { 4*EAX, "4*EAX" },
2610 { 4*DS, "4*DS" },
2611 { 4*ES, "4*ES" },
2612 { 4*FS, "4*FS" },
2613 { 4*GS, "4*GS" },
2614 { 4*ORIG_EAX, "4*ORIG_EAX" },
2615 { 4*EIP, "4*EIP" },
2616 { 4*CS, "4*CS" },
2617 { 4*EFL, "4*EFL" },
2618 { 4*UESP, "4*UESP" },
2619 { 4*SS, "4*SS" },
2620#else /* !I386 */
2621#ifdef X86_64
2622 { 8*R15, "8*R15" },
2623 { 8*R14, "8*R14" },
2624 { 8*R13, "8*R13" },
2625 { 8*R12, "8*R12" },
2626 { 8*RBP, "8*RBP" },
2627 { 8*RBX, "8*RBX" },
2628 { 8*R11, "8*R11" },
2629 { 8*R10, "8*R10" },
2630 { 8*R9, "8*R9" },
2631 { 8*R8, "8*R8" },
2632 { 8*RAX, "8*RAX" },
2633 { 8*RCX, "8*RCX" },
2634 { 8*RDX, "8*RDX" },
2635 { 8*RSI, "8*RSI" },
2636 { 8*RDI, "8*RDI" },
2637#if 0
2638 { DS, "DS" },
2639 { ES, "ES" },
2640 { FS, "FS" },
2641 { GS, "GS" },
2642#endif
2643 { 8*ORIG_RAX, "8*ORIG_RAX" },
2644 { 8*RIP, "8*RIP" },
2645 { 8*CS, "8*CS" },
2646 { 8*EFLAGS, "8*EFL" },
2647 { 8*RSP, "8*RSP" },
2648 { 8*SS, "8*SS" },
2649#endif
2650#ifdef M68K
2651 { 4*PT_D1, "4*PT_D1" },
2652 { 4*PT_D2, "4*PT_D2" },
2653 { 4*PT_D3, "4*PT_D3" },
2654 { 4*PT_D4, "4*PT_D4" },
2655 { 4*PT_D5, "4*PT_D5" },
2656 { 4*PT_D6, "4*PT_D6" },
2657 { 4*PT_D7, "4*PT_D7" },
2658 { 4*PT_A0, "4*PT_A0" },
2659 { 4*PT_A1, "4*PT_A1" },
2660 { 4*PT_A2, "4*PT_A2" },
2661 { 4*PT_A3, "4*PT_A3" },
2662 { 4*PT_A4, "4*PT_A4" },
2663 { 4*PT_A5, "4*PT_A5" },
2664 { 4*PT_A6, "4*PT_A6" },
2665 { 4*PT_D0, "4*PT_D0" },
2666 { 4*PT_USP, "4*PT_USP" },
2667 { 4*PT_ORIG_D0, "4*PT_ORIG_D0" },
2668 { 4*PT_SR, "4*PT_SR" },
2669 { 4*PT_PC, "4*PT_PC" },
2670#endif /* M68K */
2671#endif /* !I386 */
2672#ifdef SH
2673 { 4*REG_REG0, "4*REG_REG0" },
2674 { 4*(REG_REG0+1), "4*REG_REG1" },
2675 { 4*(REG_REG0+2), "4*REG_REG2" },
2676 { 4*(REG_REG0+3), "4*REG_REG3" },
2677 { 4*(REG_REG0+4), "4*REG_REG4" },
2678 { 4*(REG_REG0+5), "4*REG_REG5" },
2679 { 4*(REG_REG0+6), "4*REG_REG6" },
2680 { 4*(REG_REG0+7), "4*REG_REG7" },
2681 { 4*(REG_REG0+8), "4*REG_REG8" },
2682 { 4*(REG_REG0+9), "4*REG_REG9" },
2683 { 4*(REG_REG0+10), "4*REG_REG10" },
2684 { 4*(REG_REG0+11), "4*REG_REG11" },
2685 { 4*(REG_REG0+12), "4*REG_REG12" },
2686 { 4*(REG_REG0+13), "4*REG_REG13" },
2687 { 4*(REG_REG0+14), "4*REG_REG14" },
2688 { 4*REG_REG15, "4*REG_REG15" },
2689 { 4*REG_PC, "4*REG_PC" },
2690 { 4*REG_PR, "4*REG_PR" },
2691 { 4*REG_SR, "4*REG_SR" },
2692 { 4*REG_GBR, "4*REG_GBR" },
2693 { 4*REG_MACH, "4*REG_MACH" },
2694 { 4*REG_MACL, "4*REG_MACL" },
2695 { 4*REG_SYSCALL, "4*REG_SYSCALL" },
2696 { 4*REG_FPUL, "4*REG_FPUL" },
2697 { 4*REG_FPREG0, "4*REG_FPREG0" },
2698 { 4*(REG_FPREG0+1), "4*REG_FPREG1" },
2699 { 4*(REG_FPREG0+2), "4*REG_FPREG2" },
2700 { 4*(REG_FPREG0+3), "4*REG_FPREG3" },
2701 { 4*(REG_FPREG0+4), "4*REG_FPREG4" },
2702 { 4*(REG_FPREG0+5), "4*REG_FPREG5" },
2703 { 4*(REG_FPREG0+6), "4*REG_FPREG6" },
2704 { 4*(REG_FPREG0+7), "4*REG_FPREG7" },
2705 { 4*(REG_FPREG0+8), "4*REG_FPREG8" },
2706 { 4*(REG_FPREG0+9), "4*REG_FPREG9" },
2707 { 4*(REG_FPREG0+10), "4*REG_FPREG10" },
2708 { 4*(REG_FPREG0+11), "4*REG_FPREG11" },
2709 { 4*(REG_FPREG0+12), "4*REG_FPREG12" },
2710 { 4*(REG_FPREG0+13), "4*REG_FPREG13" },
2711 { 4*(REG_FPREG0+14), "4*REG_FPREG14" },
2712 { 4*REG_FPREG15, "4*REG_FPREG15" },
2713#ifdef REG_XDREG0
2714 { 4*REG_XDREG0, "4*REG_XDREG0" },
2715 { 4*(REG_XDREG0+2), "4*REG_XDREG2" },
2716 { 4*(REG_XDREG0+4), "4*REG_XDREG4" },
2717 { 4*(REG_XDREG0+6), "4*REG_XDREG6" },
2718 { 4*(REG_XDREG0+8), "4*REG_XDREG8" },
2719 { 4*(REG_XDREG0+10), "4*REG_XDREG10" },
2720 { 4*(REG_XDREG0+12), "4*REG_XDREG12" },
2721 { 4*REG_XDREG14, "4*REG_XDREG14" },
2722#endif
2723 { 4*REG_FPSCR, "4*REG_FPSCR" },
2724#endif /* SH */
2725#ifdef SH64
2726 { 0, "PC(L)" },
2727 { 4, "PC(U)" },
2728 { 8, "SR(L)" },
2729 { 12, "SR(U)" },
2730 { 16, "syscall no.(L)" },
2731 { 20, "syscall_no.(U)" },
2732 { 24, "R0(L)" },
2733 { 28, "R0(U)" },
2734 { 32, "R1(L)" },
2735 { 36, "R1(U)" },
2736 { 40, "R2(L)" },
2737 { 44, "R2(U)" },
2738 { 48, "R3(L)" },
2739 { 52, "R3(U)" },
2740 { 56, "R4(L)" },
2741 { 60, "R4(U)" },
2742 { 64, "R5(L)" },
2743 { 68, "R5(U)" },
2744 { 72, "R6(L)" },
2745 { 76, "R6(U)" },
2746 { 80, "R7(L)" },
2747 { 84, "R7(U)" },
2748 { 88, "R8(L)" },
2749 { 92, "R8(U)" },
2750 { 96, "R9(L)" },
2751 { 100, "R9(U)" },
2752 { 104, "R10(L)" },
2753 { 108, "R10(U)" },
2754 { 112, "R11(L)" },
2755 { 116, "R11(U)" },
2756 { 120, "R12(L)" },
2757 { 124, "R12(U)" },
2758 { 128, "R13(L)" },
2759 { 132, "R13(U)" },
2760 { 136, "R14(L)" },
2761 { 140, "R14(U)" },
2762 { 144, "R15(L)" },
2763 { 148, "R15(U)" },
2764 { 152, "R16(L)" },
2765 { 156, "R16(U)" },
2766 { 160, "R17(L)" },
2767 { 164, "R17(U)" },
2768 { 168, "R18(L)" },
2769 { 172, "R18(U)" },
2770 { 176, "R19(L)" },
2771 { 180, "R19(U)" },
2772 { 184, "R20(L)" },
2773 { 188, "R20(U)" },
2774 { 192, "R21(L)" },
2775 { 196, "R21(U)" },
2776 { 200, "R22(L)" },
2777 { 204, "R22(U)" },
2778 { 208, "R23(L)" },
2779 { 212, "R23(U)" },
2780 { 216, "R24(L)" },
2781 { 220, "R24(U)" },
2782 { 224, "R25(L)" },
2783 { 228, "R25(U)" },
2784 { 232, "R26(L)" },
2785 { 236, "R26(U)" },
2786 { 240, "R27(L)" },
2787 { 244, "R27(U)" },
2788 { 248, "R28(L)" },
2789 { 252, "R28(U)" },
2790 { 256, "R29(L)" },
2791 { 260, "R29(U)" },
2792 { 264, "R30(L)" },
2793 { 268, "R30(U)" },
2794 { 272, "R31(L)" },
2795 { 276, "R31(U)" },
2796 { 280, "R32(L)" },
2797 { 284, "R32(U)" },
2798 { 288, "R33(L)" },
2799 { 292, "R33(U)" },
2800 { 296, "R34(L)" },
2801 { 300, "R34(U)" },
2802 { 304, "R35(L)" },
2803 { 308, "R35(U)" },
2804 { 312, "R36(L)" },
2805 { 316, "R36(U)" },
2806 { 320, "R37(L)" },
2807 { 324, "R37(U)" },
2808 { 328, "R38(L)" },
2809 { 332, "R38(U)" },
2810 { 336, "R39(L)" },
2811 { 340, "R39(U)" },
2812 { 344, "R40(L)" },
2813 { 348, "R40(U)" },
2814 { 352, "R41(L)" },
2815 { 356, "R41(U)" },
2816 { 360, "R42(L)" },
2817 { 364, "R42(U)" },
2818 { 368, "R43(L)" },
2819 { 372, "R43(U)" },
2820 { 376, "R44(L)" },
2821 { 380, "R44(U)" },
2822 { 384, "R45(L)" },
2823 { 388, "R45(U)" },
2824 { 392, "R46(L)" },
2825 { 396, "R46(U)" },
2826 { 400, "R47(L)" },
2827 { 404, "R47(U)" },
2828 { 408, "R48(L)" },
2829 { 412, "R48(U)" },
2830 { 416, "R49(L)" },
2831 { 420, "R49(U)" },
2832 { 424, "R50(L)" },
2833 { 428, "R50(U)" },
2834 { 432, "R51(L)" },
2835 { 436, "R51(U)" },
2836 { 440, "R52(L)" },
2837 { 444, "R52(U)" },
2838 { 448, "R53(L)" },
2839 { 452, "R53(U)" },
2840 { 456, "R54(L)" },
2841 { 460, "R54(U)" },
2842 { 464, "R55(L)" },
2843 { 468, "R55(U)" },
2844 { 472, "R56(L)" },
2845 { 476, "R56(U)" },
2846 { 480, "R57(L)" },
2847 { 484, "R57(U)" },
2848 { 488, "R58(L)" },
2849 { 492, "R58(U)" },
2850 { 496, "R59(L)" },
2851 { 500, "R59(U)" },
2852 { 504, "R60(L)" },
2853 { 508, "R60(U)" },
2854 { 512, "R61(L)" },
2855 { 516, "R61(U)" },
2856 { 520, "R62(L)" },
2857 { 524, "R62(U)" },
2858 { 528, "TR0(L)" },
2859 { 532, "TR0(U)" },
2860 { 536, "TR1(L)" },
2861 { 540, "TR1(U)" },
2862 { 544, "TR2(L)" },
2863 { 548, "TR2(U)" },
2864 { 552, "TR3(L)" },
2865 { 556, "TR3(U)" },
2866 { 560, "TR4(L)" },
2867 { 564, "TR4(U)" },
2868 { 568, "TR5(L)" },
2869 { 572, "TR5(U)" },
2870 { 576, "TR6(L)" },
2871 { 580, "TR6(U)" },
2872 { 584, "TR7(L)" },
2873 { 588, "TR7(U)" },
2874 /* This entry is in case pt_regs contains dregs (depends on
2875 the kernel build options). */
2876 { uoff(regs), "offsetof(struct user, regs)" },
2877 { uoff(fpu), "offsetof(struct user, fpu)" },
2878#endif
2879#ifdef ARM
2880 { uoff(regs.ARM_r0), "r0" },
2881 { uoff(regs.ARM_r1), "r1" },
2882 { uoff(regs.ARM_r2), "r2" },
2883 { uoff(regs.ARM_r3), "r3" },
2884 { uoff(regs.ARM_r4), "r4" },
2885 { uoff(regs.ARM_r5), "r5" },
2886 { uoff(regs.ARM_r6), "r6" },
2887 { uoff(regs.ARM_r7), "r7" },
2888 { uoff(regs.ARM_r8), "r8" },
2889 { uoff(regs.ARM_r9), "r9" },
2890 { uoff(regs.ARM_r10), "r10" },
2891 { uoff(regs.ARM_fp), "fp" },
2892 { uoff(regs.ARM_ip), "ip" },
2893 { uoff(regs.ARM_sp), "sp" },
2894 { uoff(regs.ARM_lr), "lr" },
2895 { uoff(regs.ARM_pc), "pc" },
2896 { uoff(regs.ARM_cpsr), "cpsr" },
2897#endif
2898
2899#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SPARC64)
2900 { uoff(u_fpvalid), "offsetof(struct user, u_fpvalid)" },
2901#endif
2902#if defined(I386) || defined(X86_64)
2903 { uoff(i387), "offsetof(struct user, i387)" },
2904#else /* !I386 */
2905#ifdef M68K
2906 { uoff(m68kfp), "offsetof(struct user, m68kfp)" },
2907#endif /* M68K */
2908#endif /* !I386 */
2909 { uoff(u_tsize), "offsetof(struct user, u_tsize)" },
2910 { uoff(u_dsize), "offsetof(struct user, u_dsize)" },
2911 { uoff(u_ssize), "offsetof(struct user, u_ssize)" },
2912#if !defined(SPARC64)
2913 { uoff(start_code), "offsetof(struct user, start_code)" },
2914#endif
2915#ifdef SH64
2916 { uoff(start_data), "offsetof(struct user, start_data)" },
2917#endif
2918#if !defined(SPARC64)
2919 { uoff(start_stack), "offsetof(struct user, start_stack)" },
2920#endif
2921 { uoff(signal), "offsetof(struct user, signal)" },
2922#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SH) && !defined(SH64) && !defined(SPARC64)
2923 { uoff(reserved), "offsetof(struct user, reserved)" },
2924#endif
2925#if !defined(SPARC64)
2926 { uoff(u_ar0), "offsetof(struct user, u_ar0)" },
2927#endif
2928#if !defined(ARM) && !defined(MIPS) && !defined(S390) && !defined(S390X) && !defined(SPARC64)
2929 { uoff(u_fpstate), "offsetof(struct user, u_fpstate)" },
2930#endif
2931 { uoff(magic), "offsetof(struct user, magic)" },
2932 { uoff(u_comm), "offsetof(struct user, u_comm)" },
2933#if defined(I386) || defined(X86_64)
2934 { uoff(u_debugreg), "offsetof(struct user, u_debugreg)" },
2935#endif /* I386 */
2936#endif /* !IA64 */
2937#endif /* !ALPHA */
2938#endif /* !POWERPC/!SPARC */
2939#endif /* LINUX */
2940#ifdef SUNOS4
2941 { uoff(u_pcb), "offsetof(struct user, u_pcb)" },
2942 { uoff(u_procp), "offsetof(struct user, u_procp)" },
2943 { uoff(u_ar0), "offsetof(struct user, u_ar0)" },
2944 { uoff(u_comm[0]), "offsetof(struct user, u_comm[0])" },
2945 { uoff(u_arg[0]), "offsetof(struct user, u_arg[0])" },
2946 { uoff(u_ap), "offsetof(struct user, u_ap)" },
2947 { uoff(u_qsave), "offsetof(struct user, u_qsave)" },
2948 { uoff(u_rval1), "offsetof(struct user, u_rval1)" },
2949 { uoff(u_rval2), "offsetof(struct user, u_rval2)" },
2950 { uoff(u_error), "offsetof(struct user, u_error)" },
2951 { uoff(u_eosys), "offsetof(struct user, u_eosys)" },
2952 { uoff(u_ssave), "offsetof(struct user, u_ssave)" },
2953 { uoff(u_signal[0]), "offsetof(struct user, u_signal)" },
2954 { uoff(u_sigmask[0]), "offsetof(struct user, u_sigmask)" },
2955 { uoff(u_sigonstack), "offsetof(struct user, u_sigonstack)" },
2956 { uoff(u_sigintr), "offsetof(struct user, u_sigintr)" },
2957 { uoff(u_sigreset), "offsetof(struct user, u_sigreset)" },
2958 { uoff(u_oldmask), "offsetof(struct user, u_oldmask)" },
2959 { uoff(u_code), "offsetof(struct user, u_code)" },
2960 { uoff(u_addr), "offsetof(struct user, u_addr)" },
2961 { uoff(u_sigstack), "offsetof(struct user, u_sigstack)" },
2962 { uoff(u_ofile), "offsetof(struct user, u_ofile)" },
2963 { uoff(u_pofile), "offsetof(struct user, u_pofile)" },
2964 { uoff(u_ofile_arr[0]), "offsetof(struct user, u_ofile_arr[0])" },
2965 { uoff(u_pofile_arr[0]),"offsetof(struct user, u_pofile_arr[0])"},
2966 { uoff(u_lastfile), "offsetof(struct user, u_lastfile)" },
2967 { uoff(u_cwd), "offsetof(struct user, u_cwd)" },
2968 { uoff(u_cdir), "offsetof(struct user, u_cdir)" },
2969 { uoff(u_rdir), "offsetof(struct user, u_rdir)" },
2970 { uoff(u_cmask), "offsetof(struct user, u_cmask)" },
2971 { uoff(u_ru), "offsetof(struct user, u_ru)" },
2972 { uoff(u_cru), "offsetof(struct user, u_cru)" },
2973 { uoff(u_timer[0]), "offsetof(struct user, u_timer[0])" },
2974 { uoff(u_XXX[0]), "offsetof(struct user, u_XXX[0])" },
2975 { uoff(u_ioch), "offsetof(struct user, u_ioch)" },
2976 { uoff(u_start), "offsetof(struct user, u_start)" },
2977 { uoff(u_acflag), "offsetof(struct user, u_acflag)" },
2978 { uoff(u_prof.pr_base), "offsetof(struct user, u_prof.pr_base)" },
2979 { uoff(u_prof.pr_size), "offsetof(struct user, u_prof.pr_size)" },
2980 { uoff(u_prof.pr_off), "offsetof(struct user, u_prof.pr_off)" },
2981 { uoff(u_prof.pr_scale),"offsetof(struct user, u_prof.pr_scale)"},
2982 { uoff(u_rlimit[0]), "offsetof(struct user, u_rlimit)" },
2983 { uoff(u_exdata.Ux_A), "offsetof(struct user, u_exdata.Ux_A)" },
2984 { uoff(u_exdata.ux_shell[0]),"offsetof(struct user, u_exdata.ux_shell[0])"},
2985 { uoff(u_lofault), "offsetof(struct user, u_lofault)" },
2986#endif /* SUNOS4 */
2987#ifndef HPPA
2988 { sizeof(struct user), "sizeof(struct user)" },
2989#endif
2990 { 0, NULL },
2991};
2992#endif
2993
2994int
2995sys_ptrace(tcp)
2996struct tcb *tcp;
2997{
2998 const struct xlat *x;
2999 long addr;
3000
3001 if (entering(tcp)) {
3002 printxval(ptrace_cmds, tcp->u_arg[0],
3003#ifndef FREEBSD
3004 "PTRACE_???"
3005#else
3006 "PT_???"
3007#endif
3008 );
3009 tprintf(", %lu, ", tcp->u_arg[1]);
3010 addr = tcp->u_arg[2];
3011#ifndef FREEBSD
3012 if (tcp->u_arg[0] == PTRACE_PEEKUSER
3013 || tcp->u_arg[0] == PTRACE_POKEUSER) {
3014 for (x = struct_user_offsets; x->str; x++) {
3015 if (x->val >= addr)
3016 break;
3017 }
3018 if (!x->str)
3019 tprintf("%#lx, ", addr);
3020 else if (x->val > addr && x != struct_user_offsets) {
3021 x--;
3022 tprintf("%s + %ld, ", x->str, addr - x->val);
3023 }
3024 else
3025 tprintf("%s, ", x->str);
3026 }
3027 else
3028#endif
3029 tprintf("%#lx, ", tcp->u_arg[2]);
3030#ifdef LINUX
3031 switch (tcp->u_arg[0]) {
3032 case PTRACE_PEEKDATA:
3033 case PTRACE_PEEKTEXT:
3034 case PTRACE_PEEKUSER:
3035 break;
3036 case PTRACE_CONT:
3037 case PTRACE_SINGLESTEP:
3038 case PTRACE_SYSCALL:
3039 case PTRACE_DETACH:
3040 printsignal(tcp->u_arg[3]);
3041 break;
3042 default:
3043 tprintf("%#lx", tcp->u_arg[3]);
3044 break;
3045 }
3046 } else {
3047 switch (tcp->u_arg[0]) {
3048 case PTRACE_PEEKDATA:
3049 case PTRACE_PEEKTEXT:
3050 case PTRACE_PEEKUSER:
3051 printnum(tcp, tcp->u_arg[3], "%#lx");
3052 break;
3053 }
3054 }
3055#endif /* LINUX */
3056#ifdef SUNOS4
3057 if (tcp->u_arg[0] == PTRACE_WRITEDATA ||
3058 tcp->u_arg[0] == PTRACE_WRITETEXT) {
3059 tprintf("%lu, ", tcp->u_arg[3]);
3060 printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
3061 } else if (tcp->u_arg[0] != PTRACE_READDATA &&
3062 tcp->u_arg[0] != PTRACE_READTEXT) {
3063 tprintf("%#lx", tcp->u_arg[3]);
3064 }
3065 } else {
3066 if (tcp->u_arg[0] == PTRACE_READDATA ||
3067 tcp->u_arg[0] == PTRACE_READTEXT) {
3068 tprintf("%lu, ", tcp->u_arg[3]);
3069 printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
3070 }
3071 }
3072#endif /* SUNOS4 */
3073#ifdef FREEBSD
3074 tprintf("%lu", tcp->u_arg[3]);
3075 }
3076#endif /* FREEBSD */
3077 return 0;
3078}
3079
3080#endif /* !SVR4 */
3081
3082#ifdef LINUX
3083# ifndef FUTEX_CMP_REQUEUE
3084# define FUTEX_CMP_REQUEUE 4
3085# endif
3086# ifndef FUTEX_WAKE_OP
3087# define FUTEX_WAKE_OP 5
3088# endif
3089# ifndef FUTEX_LOCK_PI
3090# define FUTEX_LOCK_PI 6
3091# define FUTEX_UNLOCK_PI 7
3092# define FUTEX_TRYLOCK_PI 8
3093# endif
3094# ifndef FUTEX_CMP_REQUEUE_PI
3095# define FUTEX_CMP_REQUEUE_PI 9
3096# endif
3097# ifndef FUTEX_PRIVATE_FLAG
3098# define FUTEX_PRIVATE_FLAG 128
3099# endif
3100static const struct xlat futexops[] = {
3101 { FUTEX_WAIT, "FUTEX_WAIT" },
3102 { FUTEX_WAKE, "FUTEX_WAKE" },
3103 { FUTEX_FD, "FUTEX_FD" },
3104 { FUTEX_REQUEUE, "FUTEX_REQUEUE" },
3105 { FUTEX_CMP_REQUEUE, "FUTEX_CMP_REQUEUE" },
3106 { FUTEX_WAKE_OP, "FUTEX_WAKE_OP" },
3107 { FUTEX_LOCK_PI, "FUTEX_LOCK_PI" },
3108 { FUTEX_UNLOCK_PI, "FUTEX_UNLOCK_PI" },
3109 { FUTEX_TRYLOCK_PI, "FUTEX_TRYLOCK_PI" },
3110 { FUTEX_CMP_REQUEUE_PI, "FUTEX_CMP_REQUEUE_PI" },
3111 { FUTEX_WAIT|FUTEX_PRIVATE_FLAG, "FUTEX_WAIT_PRIVATE" },
3112 { FUTEX_WAKE|FUTEX_PRIVATE_FLAG, "FUTEX_WAKE_PRIVATE" },
3113 { FUTEX_FD|FUTEX_PRIVATE_FLAG, "FUTEX_FD_PRIVATE" },
3114 { FUTEX_REQUEUE|FUTEX_PRIVATE_FLAG, "FUTEX_REQUEUE_PRIVATE" },
3115 { FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG, "FUTEX_CMP_REQUEUE_PRIVATE" },
3116 { FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG, "FUTEX_WAKE_OP_PRIVATE" },
3117 { FUTEX_LOCK_PI|FUTEX_PRIVATE_FLAG, "FUTEX_LOCK_PI_PRIVATE" },
3118 { FUTEX_UNLOCK_PI|FUTEX_PRIVATE_FLAG, "FUTEX_UNLOCK_PI_PRIVATE" },
3119 { FUTEX_TRYLOCK_PI|FUTEX_PRIVATE_FLAG, "FUTEX_TRYLOCK_PI_PRIVATE" },
3120 { FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG, "FUTEX_CMP_REQUEUE_PI_PRIVATE" },
3121 { 0, NULL }
3122};
3123#ifndef FUTEX_OP_SET
3124# define FUTEX_OP_SET 0
3125# define FUTEX_OP_ADD 1
3126# define FUTEX_OP_OR 2
3127# define FUTEX_OP_ANDN 3
3128# define FUTEX_OP_XOR 4
3129# define FUTEX_OP_CMP_EQ 0
3130# define FUTEX_OP_CMP_NE 1
3131# define FUTEX_OP_CMP_LT 2
3132# define FUTEX_OP_CMP_LE 3
3133# define FUTEX_OP_CMP_GT 4
3134# define FUTEX_OP_CMP_GE 5
3135#endif
3136static const struct xlat futexwakeops[] = {
3137 { FUTEX_OP_SET, "FUTEX_OP_SET" },
3138 { FUTEX_OP_ADD, "FUTEX_OP_ADD" },
3139 { FUTEX_OP_OR, "FUTEX_OP_OR" },
3140 { FUTEX_OP_ANDN, "FUTEX_OP_ANDN" },
3141 { FUTEX_OP_XOR, "FUTEX_OP_XOR" },
3142 { 0, NULL }
3143};
3144static const struct xlat futexwakecmps[] = {
3145 { FUTEX_OP_CMP_EQ, "FUTEX_OP_CMP_EQ" },
3146 { FUTEX_OP_CMP_NE, "FUTEX_OP_CMP_NE" },
3147 { FUTEX_OP_CMP_LT, "FUTEX_OP_CMP_LT" },
3148 { FUTEX_OP_CMP_LE, "FUTEX_OP_CMP_LE" },
3149 { FUTEX_OP_CMP_GT, "FUTEX_OP_CMP_GT" },
3150 { FUTEX_OP_CMP_GE, "FUTEX_OP_CMP_GE" },
3151 { 0, NULL }
3152};
3153
3154int
3155sys_futex(tcp)
3156struct tcb *tcp;
3157{
3158 if (entering(tcp)) {
3159 long int cmd = tcp->u_arg[1] & ~FUTEX_PRIVATE_FLAG;
3160 tprintf("%p, ", (void *) tcp->u_arg[0]);
3161 printxval(futexops, tcp->u_arg[1], "FUTEX_???");
3162 tprintf(", %ld", tcp->u_arg[2]);
3163 if (cmd == FUTEX_WAIT) {
3164 tprintf(", ");
3165 printtv(tcp, tcp->u_arg[3]);
3166 } else if (cmd == FUTEX_REQUEUE)
3167 tprintf(", %ld, %p", tcp->u_arg[3], (void *) tcp->u_arg[4]);
3168 else if (cmd == FUTEX_CMP_REQUEUE)
3169 tprintf(", %ld, %p, %ld", tcp->u_arg[3], (void *) tcp->u_arg[4], tcp->u_arg[5]);
3170 else if (cmd == FUTEX_WAKE_OP) {
3171 tprintf(", %ld, %p, {", tcp->u_arg[3], (void *) tcp->u_arg[4]);
3172 if ((tcp->u_arg[5] >> 28) & 8)
3173 tprintf("FUTEX_OP_OPARG_SHIFT|");
3174 printxval(futexwakeops, (tcp->u_arg[5] >> 28) & 0x7, "FUTEX_OP_???");
3175 tprintf(", %ld, ", (tcp->u_arg[5] >> 12) & 0xfff);
3176 if ((tcp->u_arg[5] >> 24) & 8)
3177 tprintf("FUTEX_OP_OPARG_SHIFT|");
3178 printxval(futexwakecmps, (tcp->u_arg[5] >> 24) & 0x7, "FUTEX_OP_CMP_???");
3179 tprintf(", %ld}", tcp->u_arg[5] & 0xfff);
3180 }
3181 }
3182 return 0;
3183}
3184
3185static void
3186print_affinitylist(tcp, list, len)
3187struct tcb *tcp;
3188long list;
3189unsigned int len;
3190{
3191 int first = 1;
3192 tprintf(" {");
3193 while (len >= sizeof (unsigned long)) {
3194 unsigned long w;
3195 umove(tcp, list, &w);
3196 tprintf("%s %lx", first ? "" : ",", w);
3197 first = 0;
3198 len -= sizeof (unsigned long);
3199 list += sizeof(unsigned long);
3200 }
3201 tprintf(" }");
3202}
3203
3204int
3205sys_sched_setaffinity(tcp)
3206struct tcb *tcp;
3207{
3208 if (entering(tcp)) {
3209 tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
3210 print_affinitylist(tcp, tcp->u_arg[2], tcp->u_arg[1]);
3211 }
3212 return 0;
3213}
3214
3215int
3216sys_sched_getaffinity(tcp)
3217struct tcb *tcp;
3218{
3219 if (entering(tcp)) {
3220 tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
3221 } else {
3222 if (tcp->u_rval == -1)
3223 tprintf("%#lx", tcp->u_arg[2]);
3224 else
3225 print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval);
3226 }
3227 return 0;
3228}
3229
3230static const struct xlat schedulers[] = {
3231 { SCHED_OTHER, "SCHED_OTHER" },
3232 { SCHED_RR, "SCHED_RR" },
3233 { SCHED_FIFO, "SCHED_FIFO" },
3234 { 0, NULL }
3235};
3236
3237int
3238sys_sched_getscheduler(tcp)
3239struct tcb *tcp;
3240{
3241 if (entering(tcp)) {
3242 tprintf("%d", (int) tcp->u_arg[0]);
3243 } else if (! syserror(tcp)) {
3244 tcp->auxstr = xlookup (schedulers, tcp->u_rval);
3245 if (tcp->auxstr != NULL)
3246 return RVAL_STR;
3247 }
3248 return 0;
3249}
3250
3251int
3252sys_sched_setscheduler(tcp)
3253struct tcb *tcp;
3254{
3255 if (entering(tcp)) {
3256 struct sched_param p;
3257 tprintf("%d, ", (int) tcp->u_arg[0]);
3258 printxval(schedulers, tcp->u_arg[1], "SCHED_???");
3259 if (umove(tcp, tcp->u_arg[2], &p) < 0)
3260 tprintf(", %#lx", tcp->u_arg[2]);
3261 else
3262 tprintf(", { %d }", p.__sched_priority);
3263 }
3264 return 0;
3265}
3266
3267int
3268sys_sched_getparam(tcp)
3269struct tcb *tcp;
3270{
3271 if (entering(tcp)) {
3272 tprintf("%d, ", (int) tcp->u_arg[0]);
3273 } else {
3274 struct sched_param p;
3275 if (umove(tcp, tcp->u_arg[1], &p) < 0)
3276 tprintf("%#lx", tcp->u_arg[1]);
3277 else
3278 tprintf("{ %d }", p.__sched_priority);
3279 }
3280 return 0;
3281}
3282
3283int
3284sys_sched_setparam(tcp)
3285struct tcb *tcp;
3286{
3287 if (entering(tcp)) {
3288 struct sched_param p;
3289 if (umove(tcp, tcp->u_arg[1], &p) < 0)
3290 tprintf("%d, %#lx", (int) tcp->u_arg[0], tcp->u_arg[1]);
3291 else
3292 tprintf("%d, { %d }", (int) tcp->u_arg[0], p.__sched_priority);
3293 }
3294 return 0;
3295}
3296
3297int
3298sys_sched_get_priority_min(tcp)
3299struct tcb *tcp;
3300{
3301 if (entering(tcp)) {
3302 printxval(schedulers, tcp->u_arg[0], "SCHED_???");
3303 }
3304 return 0;
3305}
3306
3307#ifdef X86_64
3308#include <asm/prctl.h>
3309
3310static const struct xlat archvals[] = {
3311 { ARCH_SET_GS, "ARCH_SET_GS" },
3312 { ARCH_SET_FS, "ARCH_SET_FS" },
3313 { ARCH_GET_FS, "ARCH_GET_FS" },
3314 { ARCH_GET_GS, "ARCH_GET_GS" },
3315 { 0, NULL },
3316};
3317
3318int
3319sys_arch_prctl(tcp)
3320struct tcb *tcp;
3321{
3322 if (entering(tcp)) {
3323 printxval(archvals, tcp->u_arg[0], "ARCH_???");
3324 if (tcp->u_arg[0] == ARCH_SET_GS
3325 || tcp->u_arg[0] == ARCH_SET_FS)
3326 tprintf(", %#lx", tcp->u_arg[1]);
3327 } else {
3328 if (tcp->u_arg[0] == ARCH_GET_GS
3329 || tcp->u_arg[0] == ARCH_GET_FS) {
3330 long int v;
3331 if (!syserror(tcp) && umove(tcp, tcp->u_arg[1], &v) != -1)
3332 tprintf(", [%#lx]", v);
3333 else
3334 tprintf(", %#lx", tcp->u_arg[1]);
3335 }
3336 }
3337 return 0;
3338}
3339#endif
3340
3341#endif