summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2011-12-23 00:50:49 +0000
committerDmitry V. Levin <ldv@altlinux.org>2011-12-23 00:50:49 +0000
commita5a839a920da9d54c4174ebc82b29d7718839029 (patch)
treee44bcac06e54707d90a4c62989b63b537dd7f554
parentb05fc5463be8df587b4acc8f522f51e21bc22be8 (diff)
downloadstrace-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.h3
-rw-r--r--strace.c3
-rw-r--r--syscall.c50
3 files changed, 38 insertions, 18 deletions
diff --git a/defs.h b/defs.h
index 98c6a0b3e..2f4c98ba0 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 8f8c74c63..2e963059d 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 77df17452..ec3eaab77 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;