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