From: Dmitry V. Levin Date: Fri, 23 Dec 2011 00:50:49 +0000 (+0000) Subject: Enhance personality switching X-Git-Tag: v4.7~221 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a5a839a920da9d54c4174ebc82b29d7718839029;p=strace Enhance personality switching On syscall entry, save current personality in the tcb structure along with scno. On syscall exit, restore current personality from the tcb structure. * defs.h (struct tcb) [SUPPORTED_PERSONALITIES > 1]: Add currpers field. * strace.c (alloc_tcb) [SUPPORTED_PERSONALITIES > 1]: Initialize tcp->currpers. * syscall.c (update_personality) [SUPPORTED_PERSONALITIES > 1]: New function. (get_scno, trace_syscall_exiting): Use it. Reported-by: Michael A Fetterman --- diff --git a/defs.h b/defs.h index 98c6a0b3..2f4c98ba 100644 --- a/defs.h +++ b/defs.h @@ -407,6 +407,9 @@ struct tcb { long long u_lrval; /* long long return value */ #endif int ptrace_errno; +#if SUPPORTED_PERSONALITIES > 1 + int currpers; /* Personality at the time of scno update */ +#endif int curcol; /* Output column for this process */ FILE *outf; /* Output file for this process */ const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */ diff --git a/strace.c b/strace.c index 8f8c74c6..2e963059 100644 --- a/strace.c +++ b/strace.c @@ -1276,6 +1276,9 @@ alloc_tcb(int pid, int command_options_parsed) tcp->pid = pid; tcp->flags = TCB_INUSE; tcp->outf = outf; /* Initialise to current out file */ +#if SUPPORTED_PERSONALITIES > 1 + tcp->currpers = current_personality; +#endif #ifdef USE_PROCFS tcp->pfd = -1; #endif diff --git a/syscall.c b/syscall.c index 77df1745..ec3eaab7 100644 --- a/syscall.c +++ b/syscall.c @@ -273,6 +273,27 @@ set_personality(int personality) current_personality = personality; } +#if SUPPORTED_PERSONALITIES > 1 +static void +update_personality(struct tcb *tcp, int personality) +{ + if (personality == current_personality) + return; + set_personality(personality); + + if (personality == tcp->currpers) + return; + tcp->currpers = personality; + +#if defined(POWERPC64) || defined(X86_64) + if (!qflag) { + static const char *const names[] = {"64 bit", "32 bit"}; + fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n", + tcp->pid, names[personality]); + } +#endif +} +#endif static int qual_syscall(), qual_signal(), qual_fault(), qual_desc(); @@ -877,12 +898,7 @@ get_scno(struct tcb *tcp) currpers = 0; else currpers = 1; - if (currpers != current_personality) { - static const char *const names[] = {"64 bit", "32 bit"}; - set_personality(currpers); - fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n", - pid, names[current_personality]); - } + update_personality(tcp, currpers); # endif # elif defined(AVR32) /* Read complete register set in one go. */ @@ -947,12 +963,7 @@ get_scno(struct tcb *tcp) break; } # endif - if (currpers != current_personality) { - static const char *const names[] = {"64 bit", "32 bit"}; - set_personality(currpers); - fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n", - tcp->pid, names[current_personality]); - } + update_personality(tcp, currpers); # elif defined(IA64) # define IA64_PSR_IS ((long)1 << 34) if (upeek(tcp, PT_CR_IPSR, &psr) >= 0) @@ -1014,10 +1025,10 @@ get_scno(struct tcb *tcp) /* * Handle ARM specific syscall */ - set_personality(1); + update_personality(tcp, 1); scno &= 0x0000ffff; } else - set_personality(0); + update_personality(tcp, 0); } else { fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid); @@ -1093,11 +1104,11 @@ get_scno(struct tcb *tcp) switch (trap) { case 0x91d02010: /* Linux/SPARC syscall trap. */ - set_personality(0); + update_personality(tcp, 0); break; case 0x91d0206d: /* Linux/SPARC64 syscall trap. */ - set_personality(2); + update_personality(tcp, 2); break; case 0x91d02000: /* SunOS syscall trap. (pers 1) */ @@ -1105,7 +1116,7 @@ get_scno(struct tcb *tcp) return -1; case 0x91d02008: /* Solaris 2.x syscall trap. (per 2) */ - set_personality(1); + update_personality(tcp, 1); break; case 0x91d02009: /* NetBSD/FreeBSD syscall trap. */ @@ -1113,7 +1124,7 @@ get_scno(struct tcb *tcp) return -1; case 0x91d02027: /* Solaris 2.x gettimeofday */ - set_personality(1); + update_personality(tcp, 1); break; default: # if defined (SPARC64) @@ -2325,6 +2336,9 @@ trace_syscall_exiting(struct tcb *tcp) if (dtime || cflag) gettimeofday(&tv, NULL); +#if SUPPORTED_PERSONALITIES > 1 + update_personality(tcp, tcp->currpers); +#endif res = get_syscall_result(tcp); if (res == 0) return res;