diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2011-12-23 00:50:49 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2011-12-23 00:50:49 +0000 |
commit | a5a839a920da9d54c4174ebc82b29d7718839029 (patch) | |
tree | e44bcac06e54707d90a4c62989b63b537dd7f554 | |
parent | b05fc5463be8df587b4acc8f522f51e21bc22be8 (diff) | |
download | strace-a5a839a920da9d54c4174ebc82b29d7718839029.tar.gz |
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 <mafetter@nvidia.com>
-rw-r--r-- | defs.h | 3 | ||||
-rw-r--r-- | strace.c | 3 | ||||
-rw-r--r-- | syscall.c | 50 |
3 files changed, 38 insertions, 18 deletions
@@ -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) */ @@ -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 @@ -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; |