X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=process.c;h=bc116a4778077e8f0d70fbad517cb6d0ea5d6d7a;hb=aa524c88c49814863cb7f19e5c8a8eeca6ce22fe;hp=c24bfc665d1013b8c9e09583278805c22fbdff58;hpb=5bd7cf8545631b1e249b6a0ec80e7a5925a3c584;p=strace diff --git a/process.c b/process.c index c24bfc66..bc116a47 100644 --- a/process.c +++ b/process.c @@ -57,17 +57,17 @@ #endif #if HAVE_ASM_REG_H -#ifdef SPARC +#if defined (SPARC) || defined (SPARC64) # define fpq kernel_fpq # define fq kernel_fq # define fpu kernel_fpu -#endif +#endif /* SPARC || SPARC64 */ #include -#ifdef SPARC +#if defined (SPARC) || defined (SPARC64) # undef fpq # undef fq # undef fpu -#endif +#endif /* SPARC || SPARC64 */ #endif /* HAVE_ASM_REG_H */ #ifdef HAVE_SYS_REG_H @@ -82,9 +82,25 @@ #ifdef HAVE_LINUX_PTRACE_H #undef PTRACE_SYSCALL +# ifdef HAVE_STRUCT_IA64_FPREG +# define ia64_fpreg XXX_ia64_fpreg +# endif +# ifdef HAVE_STRUCT_PT_ALL_USER_REGS +# define pt_all_user_regs XXX_pt_all_user_regs +# endif #include +# undef ia64_fpreg +# undef pt_all_user_regs #endif +#if defined (LINUX) && defined (SPARC64) +# define r_pc r_tpc +# undef PTRACE_GETREGS +# define PTRACE_GETREGS PTRACE_GETREGS64 +# undef PTRACE_SETREGS +# define PTRACE_SETREGS PTRACE_SETREGS64 +#endif /* LINUX && SPARC64 */ + #ifdef HAVE_LINUX_FUTEX_H #include #endif @@ -98,12 +114,18 @@ # ifndef FUTEX_FD # define FUTEX_FD 2 # endif +# ifndef FUTEX_REQUEUE +# define FUTEX_REQUEUE 3 +# endif #endif #ifdef LINUX +#include #include #undef GETGROUPS_T #define GETGROUPS_T __kernel_gid_t +#undef GETGROUPS32_T +#define GETGROUPS32_T __kernel_gid32_t #endif /* LINUX */ #if defined(LINUX) && defined(IA64) @@ -121,7 +143,7 @@ /* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */ #if defined(HAVE_PRCTL) -static struct xlat prctl_options[] = { +static const struct xlat prctl_options[] = { #ifdef PR_MAXPROCS { PR_MAXPROCS, "PR_MAXPROCS" }, #endif @@ -368,6 +390,12 @@ struct tcb *tcp; if (entering(tcp)) { tcp->flags |= TCB_EXITING; #ifdef __NR_exit_group +# ifdef IA64 + if (ia32) { + if (tcp->scno == 252) + tcp->flags |= TCB_GROUP_EXITING; + } else +# endif if (tcp->scno == __NR_exit_group) tcp->flags |= TCB_GROUP_EXITING; #endif @@ -382,27 +410,10 @@ static int fork_tcb(struct tcb *tcp) { if (nprocs == tcbtabsize) { - /* Allocate some more TCBs and expand the table. - We don't want to relocate the TCBs because our - callers have pointers and it would be a pain. - So tcbtab is a table of pointers. Since we never - free the TCBs, we allocate a single chunk of many. */ - struct tcb **newtab = (struct tcb **) - realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]); - struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize, - sizeof *newtcbs); - int i; - if (newtab == NULL || newtcbs == NULL) { - if (newtab != NULL) - free(newtab); + if (expand_tcbtab()) { tcp->flags &= ~TCB_FOLLOWFORK; fprintf(stderr, "sys_fork: tcb table full\n"); - return 1; } - for (i = tcbtabsize; i < 2 * tcbtabsize; ++i) - newtab[i] = &newtcbs[i - tcbtabsize]; - tcbtabsize *= 2; - tcbtab = newtab; } tcp->flags |= TCB_FOLLOWFORK; @@ -451,6 +462,10 @@ struct tcb *tcp; struct tcb *tcpchild; if (exiting(tcp)) { +#ifdef SYS_rfork + if (tcp->scno == SYS_rfork && !(tcp->u_arg[0]&RFPROC)) + return 0; +#endif if (getrval2(tcp)) return 0; if (!followfork) @@ -495,7 +510,7 @@ struct tcb *tcp; #define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */ #define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */ -static struct xlat clone_flags[] = { +static const struct xlat clone_flags[] = { { CLONE_VM, "CLONE_VM" }, { CLONE_FS, "CLONE_FS" }, { CLONE_FILES, "CLONE_FILES" }, @@ -518,42 +533,64 @@ static struct xlat clone_flags[] = { # ifdef I386 # include +# ifdef HAVE_STRUCT_USER_DESC +# define modify_ldt_ldt_s user_desc +# endif extern void print_ldt_entry(); # endif +# if defined IA64 +# define ARG_FLAGS 0 +# define ARG_STACK 1 +# define ARG_STACKSIZE (tcp->scno == SYS_clone2 ? 2 : -1) +# define ARG_PTID (tcp->scno == SYS_clone2 ? 3 : 2) +# define ARG_CTID (tcp->scno == SYS_clone2 ? 4 : 3) +# define ARG_TLS (tcp->scno == SYS_clone2 ? 5 : 4) +# elif defined S390 || defined S390X +# define ARG_STACK 0 +# define ARG_FLAGS 1 +# define ARG_PTID 2 +# define ARG_CTID 3 +# define ARG_TLS 4 +# elif defined X86_64 || defined ALPHA +# define ARG_FLAGS 0 +# define ARG_STACK 1 +# define ARG_PTID 2 +# define ARG_CTID 3 +# define ARG_TLS 4 +# else +# define ARG_FLAGS 0 +# define ARG_STACK 1 +# define ARG_PTID 2 +# define ARG_TLS 3 +# define ARG_CTID 4 +# endif + int sys_clone(tcp) struct tcb *tcp; { if (exiting(tcp)) { - long flags, stack; -# if defined S390 || defined S390X - /* For some reason, S390 has the stack argument first. */ - stack = tcp->u_arg[0]; - flags = tcp->u_arg[1]; -# else - flags = tcp->u_arg[0]; - stack = tcp->u_arg[1]; + unsigned long flags = tcp->u_arg[ARG_FLAGS]; + tprintf("child_stack=%#lx, ", tcp->u_arg[ARG_STACK]); +# ifdef ARG_STACKSIZE + if (ARG_STACKSIZE != -1) + tprintf("stack_size=%#lx, ", + tcp->u_arg[ARG_STACKSIZE]); # endif - tprintf("child_stack=%#lx, flags=", stack); - if (printflags(clone_flags, flags) == 0) - tprintf("0"); + tprintf("flags="); + printflags(clone_flags, flags &~ CSIGNAL, NULL); + if ((flags & CSIGNAL) != 0) + tprintf("|%s", signame(flags & CSIGNAL)); if ((flags & (CLONE_PARENT_SETTID|CLONE_CHILD_SETTID - |CLONE_SETTLS)) == 0) + |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0) return 0; - if (flags & CLONE_PARENT_SETTID) { - int pid; - if (umove(tcp, tcp->u_arg[2], &pid) == 0) - tprintf(", [%d]", pid); - else - tprintf(", %#lx", tcp->u_arg[2]); - } - else - tprintf(", "); -#ifdef I386 + if (flags & CLONE_PARENT_SETTID) + tprintf(", parent_tidptr=%#lx", tcp->u_arg[ARG_PTID]); if (flags & CLONE_SETTLS) { +# ifdef I386 struct modify_ldt_ldt_s copy; - if (umove(tcp, tcp->u_arg[3], ©) != -1) { + if (umove(tcp, tcp->u_arg[ARG_TLS], ©) != -1) { tprintf(", {entry_number:%d, ", copy.entry_number); if (!verbose(tcp)) @@ -562,34 +599,14 @@ struct tcb *tcp; print_ldt_entry(©); } else - tprintf(", %#lx", tcp->u_arg[3]); +# endif + tprintf(", tls=%#lx", tcp->u_arg[ARG_TLS]); } - else - tprintf(", "); -# define TIDARG 4 -#else -# define TIDARG 3 -#endif - if (flags & CLONE_CHILD_SETTID) - tprintf(", %#lx", tcp->u_arg[TIDARG]); -#undef TIDARG + if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID)) + tprintf(", child_tidptr=%#lx", tcp->u_arg[ARG_CTID]); } return 0; } - -int -sys_clone2(tcp) -struct tcb *tcp; -{ - if (exiting(tcp)) { - tprintf("child_stack=%#lx, stack_size=%#lx, flags=", - tcp->u_arg[1], tcp->u_arg[2]); - if (printflags(clone_flags, tcp->u_arg[0]) == 0) - tprintf("0"); - } - return 0; -} - #endif int @@ -631,7 +648,7 @@ int new; if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new)<0) return -1; return 0; -#elif defined(SPARC) +#elif defined(SPARC) || defined(SPARC64) struct regs regs; if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)®s, 0)<0) return -1; @@ -648,7 +665,18 @@ int new; return -1; return 0; #elif defined(IA64) - if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0) + if (ia32) { + switch (new) { + case 2: break; /* x86 SYS_fork */ + case SYS_clone: new = 120; break; + default: + fprintf(stderr, "%s: unexpected syscall %d\n", + __FUNCTION__, new); + return -1; + } + if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new)<0) + return -1; + } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0) return -1; return 0; #elif defined(HPPA) @@ -656,9 +684,16 @@ int new; return -1; return 0; #elif defined(SH) - if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL), new)<0) + if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new)<0) return -1; return 0; +#elif defined(SH64) + /* Top half of reg encodes the no. of args n as 0x1n. + Assume 0 args as kernel never actually checks... */ + if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL), + 0x100000 | new) < 0) + return -1; + return 0; #else #warning Do not know how to handle change_syscall for this architecture #endif /* architecture */ @@ -843,29 +878,37 @@ Process %u resumed (parent %d ready)\n", } #ifdef TCB_CLONE_THREAD - if ((tcp->flags & TCB_CLONE_THREAD) && tcp->parent != NULL) { - /* The parent in this clone is itself a thread - belonging to another process. There is no - meaning to the parentage relationship of the new - child with the thread, only with the process. - We associate the new thread with our parent. - Since this is done for every new thread, there - will never be a TCB_CLONE_THREAD process that - has children. */ - --tcp->nchildren; - tcp->u_arg[0] = tcp->parent->u_arg[0]; - tcp = tcp->parent; - tcpchild->parent = tcp; - ++tcp->nchildren; - } - - if (tcp->u_arg[0] & CLONE_THREAD) { - tcpchild->flags |= TCB_CLONE_THREAD; - ++tcp->nclone_threads; - } - if (tcp->u_arg[0] & CLONE_DETACHED) { - tcpchild->flags |= TCB_CLONE_DETACHED; - ++tcp->nclone_detached; + { + /* + * Save the flags used in this call, + * in case we point TCP to our parent below. + */ + int call_flags = tcp->u_arg[ARG_FLAGS]; + if ((tcp->flags & TCB_CLONE_THREAD) && + tcp->parent != NULL) { + /* The parent in this clone is itself a + thread belonging to another process. + There is no meaning to the parentage + relationship of the new child with the + thread, only with the process. We + associate the new thread with our + parent. Since this is done for every + new thread, there will never be a + TCB_CLONE_THREAD process that has + children. */ + --tcp->nchildren; + tcp = tcp->parent; + tcpchild->parent = tcp; + ++tcp->nchildren; + } + if (call_flags & CLONE_THREAD) { + tcpchild->flags |= TCB_CLONE_THREAD; + ++tcp->nclone_threads; + } + if (call_flags & CLONE_DETACHED) { + tcpchild->flags |= TCB_CLONE_DETACHED; + ++tcp->nclone_detached; + } } #endif @@ -1087,15 +1130,15 @@ sys_getresuid(tcp) if (umove(tcp, tcp->u_arg[0], &uid) < 0) tprintf("%#lx, ", tcp->u_arg[0]); else - tprintf("ruid %lu, ", (unsigned long) uid); - if (umove(tcp, tcp->u_arg[0], &uid) < 0) - tprintf("%#lx, ", tcp->u_arg[0]); + tprintf("[%lu], ", (unsigned long) uid); + if (umove(tcp, tcp->u_arg[1], &uid) < 0) + tprintf("%#lx, ", tcp->u_arg[1]); else - tprintf("euid %lu, ", (unsigned long) uid); - if (umove(tcp, tcp->u_arg[0], &uid) < 0) - tprintf("%#lx", tcp->u_arg[0]); + tprintf("[%lu], ", (unsigned long) uid); + if (umove(tcp, tcp->u_arg[2], &uid) < 0) + tprintf("%#lx", tcp->u_arg[2]); else - tprintf("suid %lu", (unsigned long) uid); + tprintf("[%lu]", (unsigned long) uid); } } return 0; @@ -1114,15 +1157,15 @@ struct tcb *tcp; if (umove(tcp, tcp->u_arg[0], &gid) < 0) tprintf("%#lx, ", tcp->u_arg[0]); else - tprintf("rgid %lu, ", (unsigned long) gid); - if (umove(tcp, tcp->u_arg[0], &gid) < 0) - tprintf("%#lx, ", tcp->u_arg[0]); + tprintf("[%lu], ", (unsigned long) gid); + if (umove(tcp, tcp->u_arg[1], &gid) < 0) + tprintf("%#lx, ", tcp->u_arg[1]); else - tprintf("egid %lu, ", (unsigned long) gid); - if (umove(tcp, tcp->u_arg[0], &gid) < 0) - tprintf("%#lx", tcp->u_arg[0]); + tprintf("[%lu], ", (unsigned long) gid); + if (umove(tcp, tcp->u_arg[2], &gid) < 0) + tprintf("%#lx", tcp->u_arg[2]); else - tprintf("sgid %lu", (unsigned long) gid); + tprintf("[%lu]", (unsigned long) gid); } } return 0; @@ -1135,9 +1178,8 @@ sys_setreuid(tcp) struct tcb *tcp; { if (entering(tcp)) { - tprintf("%lu, %lu", - (unsigned long) (uid_t) tcp->u_arg[0], - (unsigned long) (uid_t) tcp->u_arg[1]); + printuid("", tcp->u_arg[0]); + printuid(", ", tcp->u_arg[1]); } return 0; } @@ -1147,9 +1189,8 @@ sys_setregid(tcp) struct tcb *tcp; { if (entering(tcp)) { - tprintf("%lu, %lu", - (unsigned long) (gid_t) tcp->u_arg[0], - (unsigned long) (gid_t) tcp->u_arg[1]); + printuid("", tcp->u_arg[0]); + printuid(", ", tcp->u_arg[1]); } return 0; } @@ -1160,10 +1201,9 @@ sys_setresuid(tcp) struct tcb *tcp; { if (entering(tcp)) { - tprintf("ruid %u, euid %u, suid %u", - (uid_t) tcp->u_arg[0], - (uid_t) tcp->u_arg[1], - (uid_t) tcp->u_arg[2]); + printuid("", tcp->u_arg[0]); + printuid(", ", tcp->u_arg[1]); + printuid(", ", tcp->u_arg[2]); } return 0; } @@ -1172,10 +1212,9 @@ sys_setresgid(tcp) struct tcb *tcp; { if (entering(tcp)) { - tprintf("rgid %u, egid %u, sgid %u", - (uid_t) tcp->u_arg[0], - (uid_t) tcp->u_arg[1], - (uid_t) tcp->u_arg[2]); + printuid("", tcp->u_arg[0]); + printuid(", ", tcp->u_arg[1]); + printuid(", ", tcp->u_arg[2]); } return 0; } @@ -1186,34 +1225,53 @@ int sys_setgroups(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS_T *gidset; - if (entering(tcp)) { + unsigned long len, size, start, cur, end, abbrev_end; + GETGROUPS_T gid; + int failed = 0; + len = tcp->u_arg[0]; - tprintf("%u, ", len); - if (len <= 0) { + tprintf("%lu, ", len); + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_setgroups: out of memory\n"); - return -1; + start = tcp->u_arg[1]; + if (start == 0) { + tprintf("NULL"); + return 0; } - if (!verbose(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || size / sizeof(gid) != len || end < start) { + tprintf("%#lx", start); + return 0; + } + if (abbrev(tcp)) { + abbrev_end = start + max_strlen * sizeof(gid); + if (abbrev_end < start) + abbrev_end = end; + } else { + abbrev_end = end; } - free((char *) gidset); + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } @@ -1222,42 +1280,183 @@ int sys_getgroups(tcp) struct tcb *tcp; { - int i, len; - GETGROUPS_T *gidset; + unsigned long len; if (entering(tcp)) { len = tcp->u_arg[0]; - tprintf("%u, ", len); + tprintf("%lu, ", len); } else { + unsigned long size, start, cur, end, abbrev_end; + GETGROUPS_T gid; + int failed = 0; + len = tcp->u_rval; - if (len <= 0) { + if (len == 0) { tprintf("[]"); return 0; } - gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T)); - if (gidset == NULL) { - fprintf(stderr, "sys_getgroups: out of memory\n"); - return -1; + start = tcp->u_arg[1]; + if (start == 0) { + tprintf("NULL"); + return 0; } - if (!tcp->u_arg[1]) + if (tcp->u_arg[0] == 0) { + tprintf("%#lx", start); + return 0; + } + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || tcp->u_arg[0] == 0 || + size / sizeof(gid) != len || end < start) { + tprintf("%#lx", start); + return 0; + } + if (abbrev(tcp)) { + abbrev_end = start + max_strlen * sizeof(gid); + if (abbrev_end < start) + abbrev_end = end; + } else { + abbrev_end = end; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); + } + return 0; +} + +#ifdef LINUX +int +sys_setgroups32(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + unsigned long len, size, start, cur, end, abbrev_end; + GETGROUPS32_T gid; + int failed = 0; + + len = tcp->u_arg[0]; + tprintf("%lu, ", len); + if (len == 0) { + tprintf("[]"); + return 0; + } + start = tcp->u_arg[1]; + if (start == 0) { tprintf("NULL"); - else if (!verbose(tcp) || tcp->u_arg[0] == 0) - tprintf("%#lx", tcp->u_arg[1]); - else if (umoven(tcp, tcp->u_arg[1], - len * sizeof(GETGROUPS_T), (char *) gidset) < 0) - tprintf("[?]"); - else { - tprintf("["); - for (i = 0; i < len; i++) - tprintf("%s%lu", i ? ", " : "", - (unsigned long) gidset[i]); - tprintf("]"); + return 0; + } + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || size / sizeof(gid) != len || end < start) { + tprintf("%#lx", start); + return 0; } - free((char *)gidset); + if (abbrev(tcp)) { + abbrev_end = start + max_strlen * sizeof(gid); + if (abbrev_end < start) + abbrev_end = end; + } else { + abbrev_end = end; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); } return 0; } +int +sys_getgroups32(tcp) +struct tcb *tcp; +{ + unsigned long len; + + if (entering(tcp)) { + len = tcp->u_arg[0]; + tprintf("%lu, ", len); + } else { + unsigned long size, start, cur, end, abbrev_end; + GETGROUPS32_T gid; + int failed = 0; + + len = tcp->u_rval; + if (len == 0) { + tprintf("[]"); + return 0; + } + start = tcp->u_arg[1]; + if (start == 0) { + tprintf("NULL"); + return 0; + } + size = len * sizeof(gid); + end = start + size; + if (!verbose(tcp) || tcp->u_arg[0] == 0 || + size / sizeof(gid) != len || end < start) { + tprintf("%#lx", start); + return 0; + } + if (abbrev(tcp)) { + abbrev_end = start + max_strlen * sizeof(gid); + if (abbrev_end < start) + abbrev_end = end; + } else { + abbrev_end = end; + } + tprintf("["); + for (cur = start; cur < end; cur += sizeof(gid)) { + if (cur > start) + tprintf(", "); + if (cur >= abbrev_end) { + tprintf("..."); + break; + } + if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) { + tprintf("?"); + failed = 1; + break; + } + tprintf("%lu", (unsigned long) gid); + } + tprintf("]"); + if (failed) + tprintf(" %#lx", tcp->u_arg[1]); + } + return 0; +} +#endif /* LINUX */ + int sys_setpgrp(tcp) struct tcb *tcp; @@ -1324,7 +1523,7 @@ struct tcb *tcp; #include -static struct xlat procpriv_cmds [] = { +static const struct xlat procpriv_cmds [] = { { SETPRV, "SETPRV" }, { CLRPRV, "CLRPRV" }, { PUTPRV, "PUTPRV" }, @@ -1334,7 +1533,7 @@ static struct xlat procpriv_cmds [] = { }; -static struct xlat procpriv_priv [] = { +static const struct xlat procpriv_priv [] = { { P_OWNER, "P_OWNER" }, { P_AUDIT, "P_AUDIT" }, { P_COMPAT, "P_COMPAT" }, @@ -1367,7 +1566,7 @@ static struct xlat procpriv_priv [] = { }; -static struct xlat procpriv_type [] = { +static const struct xlat procpriv_type [] = { { PS_FIX, "PS_FIX" }, { PS_INH, "PS_INH" }, { PS_MAX, "PS_MAX" }, @@ -1381,7 +1580,7 @@ printpriv(tcp, addr, len, opt) struct tcb *tcp; long addr; int len; -struct xlat *opt; +const struct xlat *opt; { priv_t buf [128]; int max = verbose (tcp) ? sizeof buf / sizeof buf [0] : 10; @@ -1457,39 +1656,6 @@ struct tcb *tcp; #endif -void -fake_execve(tcp, program, argv, envp) -struct tcb *tcp; -char *program; -char *argv[]; -char *envp[]; -{ - int i; - -#ifdef ARM - if (!(qual_flags[SYS_execve - __NR_SYSCALL_BASE] & QUAL_TRACE)) - return; -#else - if (!(qual_flags[SYS_execve] & QUAL_TRACE)) - return; -#endif /* !ARM */ - printleader(tcp); - tprintf("execve("); - string_quote(program); - tprintf(", ["); - for (i = 0; argv[i] != NULL; i++) { - if (i != 0) - tprintf(", "); - string_quote(argv[i]); - } - for (i = 0; envp[i] != NULL; i++) - ; - tprintf("], [/* %d var%s */]) ", i, (i != 1) ? "s" : ""); - tabto(acolumn); - tprintf("= 0"); - printtrailer(tcp); -} - static void printargv(tcp, addr) struct tcb *tcp; @@ -1579,9 +1745,6 @@ struct tcb *tcp; tprintf("]"); } } -#if defined LINUX && defined TCB_WAITEXECVE - tcp->flags |= TCB_WAITEXECVE; -#endif /* LINUX && TCB_WAITEXECVE */ return 0; } @@ -1607,6 +1770,12 @@ struct tcb *tcp; if (exiting(tcp) && !syserror(tcp) && followfork) fixvfork(tcp); #endif /* SUNOS4 */ +#if defined LINUX && defined TCB_WAITEXECVE + if (exiting(tcp) && syserror(tcp)) + tcp->flags &= ~TCB_WAITEXECVE; + else + tcp->flags |= TCB_WAITEXECVE; +#endif /* LINUX && TCB_WAITEXECVE */ return 0; } @@ -1622,7 +1791,7 @@ struct tcb *tcp; #endif #endif /* LINUX */ -static struct xlat wait4_options[] = { +static const struct xlat wait4_options[] = { { WNOHANG, "WNOHANG" }, #ifndef WSTOPPED { WUNTRACED, "WUNTRACED" }, @@ -1654,6 +1823,20 @@ static struct xlat wait4_options[] = { { 0, NULL }, }; +#if !defined WCOREFLAG && defined WCOREFLG +# define WCOREFLAG WCOREFLG +#endif +#ifndef WCOREFLAG +#define WCOREFLAG 0x80 +#endif + +#ifndef W_STOPCODE +#define W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#endif +#ifndef W_EXITCODE +#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +#endif + static int printstatus(status) int status; @@ -1665,20 +1848,33 @@ int status; * is still not entirely satisfactory but since there * are no wait status constructors it will have to do. */ - if (WIFSTOPPED(status)) - tprintf("[WIFSTOPPED(s) && WSTOPSIG(s) == %s]", + if (WIFSTOPPED(status)) { + tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s}", signame(WSTOPSIG(status))); - else if WIFSIGNALED(status) - tprintf("[WIFSIGNALED(s) && WTERMSIG(s) == %s%s]", + status &= ~W_STOPCODE(WSTOPSIG(status)); + } + else if (WIFSIGNALED(status)) { + tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}", signame(WTERMSIG(status)), WCOREDUMP(status) ? " && WCOREDUMP(s)" : ""); - else if WIFEXITED(status) { - tprintf("[WIFEXITED(s) && WEXITSTATUS(s) == %d]", + status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG); + } + else if (WIFEXITED(status)) { + tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}", WEXITSTATUS(status)); exited = 1; + status &= ~W_EXITCODE(WEXITSTATUS(status), 0); } - else + else { tprintf("[%#x]", status); + return 0; + } + + if (status == 0) + tprintf("]"); + else + tprintf(" | %#x]", status); + return exited; } @@ -1705,8 +1901,7 @@ int bitness; exited = printstatus(status); /* options */ tprintf(", "); - if (!printflags(wait4_options, tcp->u_arg[2])) - tprintf("0"); + printflags(wait4_options, tcp->u_arg[2], "W???"); if (n == 4) { tprintf(", "); /* usage */ @@ -1734,8 +1929,9 @@ int bitness; } int -internal_wait(tcp) +internal_wait(tcp, flagarg) struct tcb *tcp; +int flagarg; { int got_kids; @@ -1761,8 +1957,38 @@ struct tcb *tcp; /* ??? WTA: fix bug with hanging children */ - if (!(tcp->u_arg[2] & WNOHANG)) { - /* There are traced children */ + if (!(tcp->u_arg[flagarg] & WNOHANG)) { + /* + * There are traced children. We'll make the parent + * block to avoid a false ECHILD error due to our + * ptrace having stolen the children. However, + * we shouldn't block if there are zombies to reap. + * XXX doesn't handle pgrp matches (u_arg[0]==0,<-1) + */ + struct tcb *child = NULL; + if (tcp->nzombies > 0 && + (tcp->u_arg[0] == -1 || + (child = pid2tcb(tcp->u_arg[0])) == NULL)) + return 0; + if (tcp->u_arg[0] > 0) { + /* + * If the parent waits for a specified child + * PID, then it must get ECHILD right away + * if that PID is not one of its children. + * Make sure that the requested PID matches + * one of the parent's children that we are + * tracing, and don't suspend it otherwise. + */ + if (child == NULL) + child = pid2tcb(tcp->u_arg[0]); + if (child == NULL || child->parent != ( +#ifdef TCB_CLONE_THREAD + (tcp->flags & TCB_CLONE_THREAD) + ? tcp->parent : +#endif + tcp)) + return 0; + } tcp->flags |= TCB_SUSPENDED; tcp->waitpid = tcp->u_arg[0]; #ifdef TCB_CLONE_THREAD @@ -1772,16 +1998,20 @@ struct tcb *tcp; } } if (exiting(tcp) && tcp->u_error == ECHILD && got_kids) { - if (tcp->u_arg[2] & WNOHANG) { + if (tcp->u_arg[flagarg] & WNOHANG) { /* We must force a fake result of 0 instead of the ECHILD error. */ extern int force_result(); return force_result(tcp, 0, 0); } - else - fprintf(stderr, - "internal_wait: should not have resumed %d\n", - tcp->pid); + } + else if (exiting(tcp) && tcp->u_error == 0 && tcp->u_rval > 0 && + tcp->nzombies > 0 && pid2tcb(tcp->u_rval) == NULL) { + /* + * We just reaped a child we don't know about, + * presumably a zombie we already droptcb'd. + */ + tcp->nzombies--; } return 0; } @@ -1844,16 +2074,26 @@ struct tcb *tcp; } #endif -#ifdef SVR4 +#if defined SVR4 || defined LINUX -static struct xlat waitid_types[] = { +static const struct xlat waitid_types[] = { { P_PID, "P_PID" }, +#ifdef P_PPID { P_PPID, "P_PPID" }, +#endif { P_PGID, "P_PGID" }, +#ifdef P_SID { P_SID, "P_SID" }, +#endif +#ifdef P_CID { P_CID, "P_CID" }, +#endif +#ifdef P_UID { P_UID, "P_UID" }, +#endif +#ifdef P_GID { P_GID, "P_GID" }, +#endif { P_ALL, "P_ALL" }, #ifdef P_LWPID { P_LWPID, "P_LWPID" }, @@ -1871,11 +2111,6 @@ struct tcb *tcp; if (entering(tcp)) { printxval(waitid_types, tcp->u_arg[0], "P_???"); tprintf(", %ld, ", tcp->u_arg[1]); - if (tcp->nchildren > 0) { - /* There are traced children */ - tcp->flags |= TCB_SUSPENDED; - tcp->waitpid = tcp->u_arg[0]; - } } else { /* siginfo */ @@ -1890,13 +2125,22 @@ struct tcb *tcp; printsiginfo(&si, verbose (tcp)); /* options */ tprintf(", "); - if (!printflags(wait4_options, tcp->u_arg[3])) - tprintf("0"); + printflags(wait4_options, tcp->u_arg[3], "W???"); + if (tcp->u_nargs > 4) { + /* usage */ + tprintf(", "); + if (!tcp->u_arg[4]) + tprintf("NULL"); + else if (tcp->u_error) + tprintf("%#lx", tcp->u_arg[4]); + else + printrusage(tcp, tcp->u_arg[4]); + } } return 0; } -#endif /* SVR4 */ +#endif /* SVR4 or LINUX */ int sys_alarm(tcp) @@ -1941,7 +2185,7 @@ struct tcb *tcp; #ifndef SVR4 -static struct xlat ptrace_cmds[] = { +static const struct xlat ptrace_cmds[] = { #ifndef FREEBSD { PTRACE_TRACEME, "PTRACE_TRACEME" }, { PTRACE_PEEKTEXT, "PTRACE_PEEKTEXT", }, @@ -1973,6 +2217,12 @@ static struct xlat ptrace_cmds[] = { #ifdef PTRACE_SETFPXREGS { PTRACE_SETFPXREGS, "PTRACE_SETFPXREGS", }, #endif +#ifdef PTRACE_GETVRREGS + { PTRACE_GETVRREGS, "PTRACE_GETVRREGS", }, +#endif +#ifdef PTRACE_SETVRREGS + { PTRACE_SETVRREGS, "PTRACE_SETVRREGS", }, +#endif #ifdef SUNOS4 { PTRACE_READDATA, "PTRACE_READDATA" }, { PTRACE_WRITEDATA, "PTRACE_WRITEDATA" }, @@ -2030,7 +2280,7 @@ static struct xlat ptrace_cmds[] = { #ifndef SUNOS4_KERNEL_ARCH_KLUDGE static #endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */ -struct xlat struct_user_offsets[] = { +const struct xlat struct_user_offsets[] = { #ifdef LINUX #if defined(S390) || defined(S390X) { PT_PSWMASK, "psw_mask" }, @@ -2288,16 +2538,12 @@ struct xlat struct_user_offsets[] = { { PT_F27, "f27" }, { PT_F28, "f28" }, { PT_F29, "f29" }, { PT_F30, "f30" }, { PT_F31, "f31" }, { PT_R4, "r4" }, { PT_R5, "r5" }, { PT_R6, "r6" }, { PT_R7, "r7" }, - { PT_B0, "kb0" }, { PT_B1, "b1" }, { PT_B2, "b2" }, { PT_B3, "b3" }, { PT_B4, "b4" }, { PT_B5, "b5" }, - { PT_AR_PFS, "kar.pfs" }, - { PT_AR_LC, "ar.lc" }, { PT_AR_UNAT, "kar.unat" }, - { PT_AR_RNAT, "kar.rnat" }, { PT_AR_BSPSTORE, "kar.bspstore" }, - { PT_PR, "k.pr" }, + { PT_AR_EC, "ar.ec" }, { PT_AR_LC, "ar.lc" }, /* pt_regs */ - { PT_CR_IPSR, "cr.ipsr" }, { PT_CR_IIP, "cr.iip" }, - /*{ PT_CR_IFS, "cr.ifs" },*/ { PT_AR_UNAT, "ar.unat" }, + { PT_CR_IPSR, "psr" }, { PT_CR_IIP, "ip" }, + { PT_CFM, "cfm" }, { PT_AR_UNAT, "ar.unat" }, { PT_AR_PFS, "ar.pfs" }, { PT_AR_RSC, "ar.rsc" }, { PT_AR_RNAT, "ar.rnat" }, { PT_AR_BSPSTORE, "ar.bspstore" }, { PT_PR, "pr" }, { PT_B6, "b6" }, { PT_AR_BSP, "ar.bsp" }, @@ -2313,6 +2559,13 @@ struct xlat struct_user_offsets[] = { { PT_AR_CCV, "ar.ccv" }, { PT_AR_FPSR, "ar.fpsr" }, { PT_B0, "b0" }, { PT_B7, "b7" }, { PT_F6, "f6" }, { PT_F7, "f7" }, { PT_F8, "f8" }, { PT_F9, "f9" }, +# ifdef PT_AR_CSD + { PT_AR_CSD, "ar.csd" }, +# endif +# ifdef PT_AR_SSD + { PT_AR_SSD, "ar.ssd" }, +# endif + { PT_DBR, "dbr" }, { PT_IBR, "ibr" }, { PT_PMD, "pmd" }, #else /* !IA64 */ #ifdef I386 { 4*EBX, "4*EBX" }, @@ -2425,6 +2678,7 @@ struct xlat struct_user_offsets[] = { { 4*(REG_FPREG0+13), "4*REG_FPREG13" }, { 4*(REG_FPREG0+14), "4*REG_FPREG14" }, { 4*REG_FPREG15, "4*REG_FPREG15" }, +#ifdef REG_XDREG0 { 4*REG_XDREG0, "4*REG_XDREG0" }, { 4*(REG_XDREG0+2), "4*REG_XDREG2" }, { 4*(REG_XDREG0+4), "4*REG_XDREG4" }, @@ -2433,10 +2687,184 @@ struct xlat struct_user_offsets[] = { { 4*(REG_XDREG0+10), "4*REG_XDREG10" }, { 4*(REG_XDREG0+12), "4*REG_XDREG12" }, { 4*REG_XDREG14, "4*REG_XDREG14" }, +#endif { 4*REG_FPSCR, "4*REG_FPSCR" }, #endif /* SH */ - -#if !defined(S390) && !defined(S390X) && !defined(MIPS) +#ifdef SH64 + { 0, "PC(L)" }, + { 4, "PC(U)" }, + { 8, "SR(L)" }, + { 12, "SR(U)" }, + { 16, "syscall no.(L)" }, + { 20, "syscall_no.(U)" }, + { 24, "R0(L)" }, + { 28, "R0(U)" }, + { 32, "R1(L)" }, + { 36, "R1(U)" }, + { 40, "R2(L)" }, + { 44, "R2(U)" }, + { 48, "R3(L)" }, + { 52, "R3(U)" }, + { 56, "R4(L)" }, + { 60, "R4(U)" }, + { 64, "R5(L)" }, + { 68, "R5(U)" }, + { 72, "R6(L)" }, + { 76, "R6(U)" }, + { 80, "R7(L)" }, + { 84, "R7(U)" }, + { 88, "R8(L)" }, + { 92, "R8(U)" }, + { 96, "R9(L)" }, + { 100, "R9(U)" }, + { 104, "R10(L)" }, + { 108, "R10(U)" }, + { 112, "R11(L)" }, + { 116, "R11(U)" }, + { 120, "R12(L)" }, + { 124, "R12(U)" }, + { 128, "R13(L)" }, + { 132, "R13(U)" }, + { 136, "R14(L)" }, + { 140, "R14(U)" }, + { 144, "R15(L)" }, + { 148, "R15(U)" }, + { 152, "R16(L)" }, + { 156, "R16(U)" }, + { 160, "R17(L)" }, + { 164, "R17(U)" }, + { 168, "R18(L)" }, + { 172, "R18(U)" }, + { 176, "R19(L)" }, + { 180, "R19(U)" }, + { 184, "R20(L)" }, + { 188, "R20(U)" }, + { 192, "R21(L)" }, + { 196, "R21(U)" }, + { 200, "R22(L)" }, + { 204, "R22(U)" }, + { 208, "R23(L)" }, + { 212, "R23(U)" }, + { 216, "R24(L)" }, + { 220, "R24(U)" }, + { 224, "R25(L)" }, + { 228, "R25(U)" }, + { 232, "R26(L)" }, + { 236, "R26(U)" }, + { 240, "R27(L)" }, + { 244, "R27(U)" }, + { 248, "R28(L)" }, + { 252, "R28(U)" }, + { 256, "R29(L)" }, + { 260, "R29(U)" }, + { 264, "R30(L)" }, + { 268, "R30(U)" }, + { 272, "R31(L)" }, + { 276, "R31(U)" }, + { 280, "R32(L)" }, + { 284, "R32(U)" }, + { 288, "R33(L)" }, + { 292, "R33(U)" }, + { 296, "R34(L)" }, + { 300, "R34(U)" }, + { 304, "R35(L)" }, + { 308, "R35(U)" }, + { 312, "R36(L)" }, + { 316, "R36(U)" }, + { 320, "R37(L)" }, + { 324, "R37(U)" }, + { 328, "R38(L)" }, + { 332, "R38(U)" }, + { 336, "R39(L)" }, + { 340, "R39(U)" }, + { 344, "R40(L)" }, + { 348, "R40(U)" }, + { 352, "R41(L)" }, + { 356, "R41(U)" }, + { 360, "R42(L)" }, + { 364, "R42(U)" }, + { 368, "R43(L)" }, + { 372, "R43(U)" }, + { 376, "R44(L)" }, + { 380, "R44(U)" }, + { 384, "R45(L)" }, + { 388, "R45(U)" }, + { 392, "R46(L)" }, + { 396, "R46(U)" }, + { 400, "R47(L)" }, + { 404, "R47(U)" }, + { 408, "R48(L)" }, + { 412, "R48(U)" }, + { 416, "R49(L)" }, + { 420, "R49(U)" }, + { 424, "R50(L)" }, + { 428, "R50(U)" }, + { 432, "R51(L)" }, + { 436, "R51(U)" }, + { 440, "R52(L)" }, + { 444, "R52(U)" }, + { 448, "R53(L)" }, + { 452, "R53(U)" }, + { 456, "R54(L)" }, + { 460, "R54(U)" }, + { 464, "R55(L)" }, + { 468, "R55(U)" }, + { 472, "R56(L)" }, + { 476, "R56(U)" }, + { 480, "R57(L)" }, + { 484, "R57(U)" }, + { 488, "R58(L)" }, + { 492, "R58(U)" }, + { 496, "R59(L)" }, + { 500, "R59(U)" }, + { 504, "R60(L)" }, + { 508, "R60(U)" }, + { 512, "R61(L)" }, + { 516, "R61(U)" }, + { 520, "R62(L)" }, + { 524, "R62(U)" }, + { 528, "TR0(L)" }, + { 532, "TR0(U)" }, + { 536, "TR1(L)" }, + { 540, "TR1(U)" }, + { 544, "TR2(L)" }, + { 548, "TR2(U)" }, + { 552, "TR3(L)" }, + { 556, "TR3(U)" }, + { 560, "TR4(L)" }, + { 564, "TR4(U)" }, + { 568, "TR5(L)" }, + { 572, "TR5(U)" }, + { 576, "TR6(L)" }, + { 580, "TR6(U)" }, + { 584, "TR7(L)" }, + { 588, "TR7(U)" }, + /* This entry is in case pt_regs contains dregs (depends on + the kernel build options). */ + { uoff(regs), "offsetof(struct user, regs)" }, + { uoff(fpu), "offsetof(struct user, fpu)" }, +#endif +#ifdef ARM + { uoff(regs.ARM_r0), "r0" }, + { uoff(regs.ARM_r1), "r1" }, + { uoff(regs.ARM_r2), "r2" }, + { uoff(regs.ARM_r3), "r3" }, + { uoff(regs.ARM_r4), "r4" }, + { uoff(regs.ARM_r5), "r5" }, + { uoff(regs.ARM_r6), "r6" }, + { uoff(regs.ARM_r7), "r7" }, + { uoff(regs.ARM_r8), "r8" }, + { uoff(regs.ARM_r9), "r9" }, + { uoff(regs.ARM_r10), "r10" }, + { uoff(regs.ARM_fp), "fp" }, + { uoff(regs.ARM_ip), "ip" }, + { uoff(regs.ARM_sp), "sp" }, + { uoff(regs.ARM_lr), "lr" }, + { uoff(regs.ARM_pc), "pc" }, + { uoff(regs.ARM_cpsr), "cpsr" }, +#endif + +#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SPARC64) { uoff(u_fpvalid), "offsetof(struct user, u_fpvalid)" }, #endif #if defined(I386) || defined(X86_64) @@ -2449,14 +2877,23 @@ struct xlat struct_user_offsets[] = { { uoff(u_tsize), "offsetof(struct user, u_tsize)" }, { uoff(u_dsize), "offsetof(struct user, u_dsize)" }, { uoff(u_ssize), "offsetof(struct user, u_ssize)" }, +#if !defined(SPARC64) { uoff(start_code), "offsetof(struct user, start_code)" }, +#endif +#ifdef SH64 + { uoff(start_data), "offsetof(struct user, start_data)" }, +#endif +#if !defined(SPARC64) { uoff(start_stack), "offsetof(struct user, start_stack)" }, +#endif { uoff(signal), "offsetof(struct user, signal)" }, -#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SH) +#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SH) && !defined(SH64) && !defined(SPARC64) { uoff(reserved), "offsetof(struct user, reserved)" }, #endif +#if !defined(SPARC64) { uoff(u_ar0), "offsetof(struct user, u_ar0)" }, -#if !defined(ARM) && !defined(MIPS) && !defined(S390) && !defined(S390X) +#endif +#if !defined(ARM) && !defined(MIPS) && !defined(S390) && !defined(S390X) && !defined(SPARC64) { uoff(u_fpstate), "offsetof(struct user, u_fpstate)" }, #endif { uoff(magic), "offsetof(struct user, magic)" }, @@ -2526,7 +2963,7 @@ int sys_ptrace(tcp) struct tcb *tcp; { - struct xlat *x; + const struct xlat *x; long addr; if (entering(tcp)) { @@ -2611,10 +3048,11 @@ struct tcb *tcp; #endif /* !SVR4 */ #ifdef LINUX -static struct xlat futexops[] = { +static const struct xlat futexops[] = { { FUTEX_WAIT, "FUTEX_WAIT" }, { FUTEX_WAKE, "FUTEX_WAKE" }, { FUTEX_FD, "FUTEX_FD" }, + { FUTEX_REQUEUE,"FUTEX_REQUEUE" }, { 0, NULL } }; @@ -2624,24 +3062,32 @@ struct tcb *tcp; { if (entering(tcp)) { tprintf("%p, ", (void *) tcp->u_arg[0]); - printflags(futexops, tcp->u_arg[1]); - tprintf(", %ld, ", tcp->u_arg[2]); - printtv(tcp, tcp->u_arg[3]); + printxval(futexops, tcp->u_arg[1], "FUTEX_???"); + tprintf(", %ld", tcp->u_arg[2]); + if (tcp->u_arg[1] == FUTEX_WAIT) { + tprintf(", "); + printtv(tcp, tcp->u_arg[3]); + } else if (tcp->u_arg[1] == FUTEX_REQUEUE) + tprintf(", %ld, %p", tcp->u_arg[3], (void *) tcp->u_arg[4]); } return 0; } static void -print_affinitylist(list, len) -unsigned long *list; +print_affinitylist(tcp, list, len) +struct tcb *tcp; +long list; unsigned int len; { int first = 1; tprintf(" {"); - while (len > sizeof (unsigned long)) { - tprintf("%s %lx", first ? "" : ",", *list++); + while (len >= sizeof (unsigned long)) { + unsigned long w; + umove(tcp, list, &w); + tprintf("%s %lx", first ? "" : ",", w); first = 0; len -= sizeof (unsigned long); + list += sizeof(unsigned long); } tprintf(" }"); } @@ -2652,7 +3098,7 @@ struct tcb *tcp; { if (entering(tcp)) { tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); - print_affinitylist((unsigned long *) tcp->u_arg[2], tcp->u_arg[1]); + print_affinitylist(tcp, tcp->u_arg[2], tcp->u_arg[1]); } return 0; } @@ -2664,8 +3110,123 @@ struct tcb *tcp; if (entering(tcp)) { tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]); } else { - print_affinitylist((unsigned long *) tcp->u_arg[2], tcp->u_rval); + if (tcp->u_rval == -1) + tprintf("%#lx", tcp->u_arg[2]); + else + print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval); } return 0; } + +static const struct xlat schedulers[] = { + { SCHED_OTHER, "SCHED_OTHER" }, + { SCHED_RR, "SCHED_RR" }, + { SCHED_FIFO, "SCHED_FIFO" }, + { 0, NULL } +}; + +int +sys_sched_getscheduler(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + tprintf("%d", (int) tcp->u_arg[0]); + } else if (! syserror(tcp)) { + tcp->auxstr = xlookup (schedulers, tcp->u_rval); + if (tcp->auxstr != NULL) + return RVAL_STR; + } + return 0; +} + +int +sys_sched_setscheduler(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + struct sched_param p; + tprintf("%d, ", (int) tcp->u_arg[0]); + printxval(schedulers, tcp->u_arg[1], "SCHED_???"); + if (umove(tcp, tcp->u_arg[2], &p) < 0) + tprintf(", %#lx", tcp->u_arg[2]); + else + tprintf(", { %d }", p.__sched_priority); + } + return 0; +} + +int +sys_sched_getparam(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + tprintf("%d, ", (int) tcp->u_arg[0]); + } else { + struct sched_param p; + if (umove(tcp, tcp->u_arg[1], &p) < 0) + tprintf("%#lx", tcp->u_arg[1]); + else + tprintf("{ %d }", p.__sched_priority); + } + return 0; +} + +int +sys_sched_setparam(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + struct sched_param p; + if (umove(tcp, tcp->u_arg[1], &p) < 0) + tprintf("%d, %#lx", (int) tcp->u_arg[0], tcp->u_arg[1]); + else + tprintf("%d, { %d }", (int) tcp->u_arg[0], p.__sched_priority); + } + return 0; +} + +int +sys_sched_get_priority_min(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + printxval(schedulers, tcp->u_arg[0], "SCHED_???"); + } + return 0; +} + +#ifdef X86_64 +#include + +static const struct xlat archvals[] = { + { ARCH_SET_GS, "ARCH_SET_GS" }, + { ARCH_SET_FS, "ARCH_SET_FS" }, + { ARCH_GET_FS, "ARCH_GET_FS" }, + { ARCH_GET_GS, "ARCH_GET_GS" }, + { 0, NULL }, +}; + +int +sys_arch_prctl(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + printxval(archvals, tcp->u_arg[0], "ARCH_???"); + if (tcp->u_arg[0] == ARCH_SET_GS + || tcp->u_arg[0] == ARCH_SET_FS) + tprintf(", %#lx", tcp->u_arg[1]); + } else { + if (tcp->u_arg[0] == ARCH_GET_GS + || tcp->u_arg[0] == ARCH_GET_FS) { + long int v; + if (!syserror(tcp) && umove(tcp, tcp->u_arg[1], &v) != -1) + tprintf(", [%#lx]", v); + else + tprintf(", %#lx", tcp->u_arg[1]); + } + } + return 0; +} +#endif + #endif