summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2012-04-17 11:05:04 -0700
committerDmitry V. Levin <ldv@altlinux.org>2012-04-18 15:02:40 +0000
commit085e42886052190d3e515ca865546b527f59cdd1 (patch)
treef09fae3b106d16477db384dccf3b0e430e7dd52e
parent2bb4581ee501f6803df258ebb74c63a18a48422b (diff)
downloadstrace-085e42886052190d3e515ca865546b527f59cdd1.tar.gz
x32: add ia32 support
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent1.h, linux/x32/ioctlent1.h, linux/x32/signalent1.h and linux/x32/syscallent1.h. * configure.ac: Remove AC_GNU_SOURCE, obsoleted by AC_USE_SYSTEM_EXTENSIONS. * defs.h (SUPPORTED_PERSONALITIES): Set to 2 for X32. (PERSONALITY1_WORDSIZE): Set to 4 for X32. * file.c (stat64): New struct for X32. (sys_lseek32): New function for X32. (stat64): Undef. (sys_fstat64): Likewise. (sys_stat64): Likewise. (realprintstat64): New function for X32. (sys_fstat64): Likewise. (sys_stat64): Likewise. * mem.c (sys_old_mmap): New function for X32. * pathtrace.c (pathtrace_match): Also check sys_old_mmap for X32. * syscall.c (update_personality): Add X32 support. (get_scno): Support currpers == 1 for X32. * linux/syscall.h (sys_lseek32): New function prototype for X32. * linux/x32/errnoent1.h: New file. * linux/x32/ioctlent1.h: Likewise. * linux/x32/signalent1.h: Likewise. * linux/x32/syscallent1.h: Likewise.
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac2
-rw-r--r--defs.h7
-rw-r--r--file.c129
-rw-r--r--linux/syscall.h4
-rw-r--r--linux/x32/errnoent1.h2
-rw-r--r--linux/x32/ioctlent1.h2
-rw-r--r--linux/x32/signalent1.h2
-rw-r--r--linux/x32/syscallent1.h11
-rw-r--r--mem.c34
-rw-r--r--pathtrace.c2
-rw-r--r--syscall.c30
12 files changed, 216 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am
index 7398b7939..e9393d8f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -80,6 +80,8 @@ EXTRA_DIST = $(man_MANS) errnoent.sh signalent.sh syscallent.sh ioctlsort.c \
linux/tile/ioctlent.h.in linux/tile/syscallent.h \
linux/x32/errnoent.h linux/x32/ioctlent.h.in \
linux/x32/signalent.h linux/x32/syscallent.h \
+ linux/x32/errnoent1.h linux/x32/ioctlent1.h \
+ linux/x32/signalent1.h linux/x32/syscallent1.h \
linux/x86_64/ioctlent.h.in linux/x86_64/syscallent.h \
linux/x86_64/gentab.pl \
linux/x86_64/errnoent1.h linux/x86_64/ioctlent1.h \
diff --git a/configure.ac b/configure.ac
index f55b8a204..879ad9a97 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,8 +9,6 @@ AM_MAINTAINER_MODE
AC_CANONICAL_HOST
AC_PROG_CC
-AC_GNU_SOURCE
-
AC_USE_SYSTEM_EXTENSIONS
AC_MSG_CHECKING([for supported architecture])
diff --git a/defs.h b/defs.h
index ddde27151..ed095346b 100644
--- a/defs.h
+++ b/defs.h
@@ -227,6 +227,13 @@ extern long ptrace(int, int, char *, long);
# define PERSONALITY2_WORDSIZE 4
#endif
+#ifdef X32
+# undef SUPPORTED_PERSONALITIES
+# define SUPPORTED_PERSONALITIES 2
+# define PERSONALITY0_WORDSIZE 4
+# define PERSONALITY1_WORDSIZE 4
+#endif
+
#ifdef ARM
# undef SUPPORTED_PERSONALITIES
# define SUPPORTED_PERSONALITIES 2
diff --git a/file.c b/file.c
index 5f3b506aa..0cda7e127 100644
--- a/file.c
+++ b/file.c
@@ -96,6 +96,28 @@ struct stat {
unsigned long long st_ctime_nsec;
long long __unused[3];
};
+
+struct stat64 {
+ unsigned long long st_dev;
+ unsigned char __pad0[4];
+ unsigned long __st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned long st_uid;
+ unsigned long st_gid;
+ unsigned long long st_rdev;
+ unsigned char __pad3[4];
+ long long st_size;
+ unsigned long st_blksize;
+ unsigned long long st_blocks;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned int st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long long st_ino;
+};
#else
# undef dev_t
# undef ino_t
@@ -521,6 +543,28 @@ sys_lseek(struct tcb *tcp)
}
return RVAL_LUDECIMAL;
}
+
+# if defined(X32)
+int
+sys_lseek32(struct tcb *tcp)
+{
+ long offset;
+ int _whence;
+
+ if (entering(tcp)) {
+ printfd(tcp, tcp->u_arg[0]);
+ tprints(", ");
+ offset = tcp->u_arg[1];
+ _whence = tcp->u_arg[2];
+ if (_whence == SEEK_SET)
+ tprintf("%lu, ", offset);
+ else
+ tprintf("%ld, ", offset);
+ printxval(whence, _whence, "SEEK_???");
+ }
+ return RVAL_UDECIMAL;
+}
+# endif
#else
int
sys_lseek(struct tcb *tcp)
@@ -2722,3 +2766,88 @@ sys_swapon(struct tcb *tcp)
}
return 0;
}
+
+#ifdef X32
+# undef stat64
+# undef sys_fstat64
+# undef sys_stat64
+
+static void
+realprintstat64(struct tcb *tcp, long addr)
+{
+ struct stat64 statbuf;
+
+ if (!addr) {
+ tprints("NULL");
+ return;
+ }
+ if (syserror(tcp) || !verbose(tcp)) {
+ tprintf("%#lx", addr);
+ return;
+ }
+
+ if (umove(tcp, addr, &statbuf) < 0) {
+ tprints("{...}");
+ return;
+ }
+
+ if (!abbrev(tcp)) {
+ tprintf("{st_dev=makedev(%lu, %lu), st_ino=%llu, st_mode=%s, ",
+ (unsigned long) major(statbuf.st_dev),
+ (unsigned long) minor(statbuf.st_dev),
+ (unsigned long long) statbuf.st_ino,
+ sprintmode(statbuf.st_mode));
+ tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ",
+ (unsigned long) statbuf.st_nlink,
+ (unsigned long) statbuf.st_uid,
+ (unsigned long) statbuf.st_gid);
+ tprintf("st_blksize=%lu, ",
+ (unsigned long) statbuf.st_blksize);
+ tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks);
+ }
+ else
+ tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
+ switch (statbuf.st_mode & S_IFMT) {
+ case S_IFCHR: case S_IFBLK:
+ tprintf("st_rdev=makedev(%lu, %lu), ",
+ (unsigned long) major(statbuf.st_rdev),
+ (unsigned long) minor(statbuf.st_rdev));
+ break;
+ default:
+ tprintf("st_size=%llu, ", (unsigned long long) statbuf.st_size);
+ break;
+ }
+ if (!abbrev(tcp)) {
+ tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
+ tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
+ tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
+ tprints("}");
+ }
+ else
+ tprints("...}");
+}
+
+int
+sys_fstat64(struct tcb *tcp)
+{
+ if (entering(tcp)) {
+ printfd(tcp, tcp->u_arg[0]);
+ tprints(", ");
+ } else {
+ realprintstat64(tcp, tcp->u_arg[1]);
+ }
+ return 0;
+}
+
+int
+sys_stat64(struct tcb *tcp)
+{
+ if (entering(tcp)) {
+ printpath(tcp, tcp->u_arg[0]);
+ tprints(", ");
+ } else {
+ realprintstat64(tcp, tcp->u_arg[1]);
+ }
+ return 0;
+}
+#endif
diff --git a/linux/syscall.h b/linux/syscall.h
index e56697db4..7e0155ec5 100644
--- a/linux/syscall.h
+++ b/linux/syscall.h
@@ -371,3 +371,7 @@ int sys_shmsys();
#define SYS_shmsys_subcall 207
#define SYS_shmsys_nsubcalls 4
#endif
+
+#ifdef X32
+int sys_lseek32();
+#endif
diff --git a/linux/x32/errnoent1.h b/linux/x32/errnoent1.h
new file mode 100644
index 000000000..a89482760
--- /dev/null
+++ b/linux/x32/errnoent1.h
@@ -0,0 +1,2 @@
+/* Our second set comes from the i386 files. */
+#include "../errnoent.h"
diff --git a/linux/x32/ioctlent1.h b/linux/x32/ioctlent1.h
new file mode 100644
index 000000000..1f92feb74
--- /dev/null
+++ b/linux/x32/ioctlent1.h
@@ -0,0 +1,2 @@
+/* Our second set comes from the i386 files. */
+#include "linux/ioctlent.h"
diff --git a/linux/x32/signalent1.h b/linux/x32/signalent1.h
new file mode 100644
index 000000000..5c18d98b4
--- /dev/null
+++ b/linux/x32/signalent1.h
@@ -0,0 +1,2 @@
+/* Our second set comes from the i386 files. */
+#include "../signalent.h"
diff --git a/linux/x32/syscallent1.h b/linux/x32/syscallent1.h
new file mode 100644
index 000000000..20c65292c
--- /dev/null
+++ b/linux/x32/syscallent1.h
@@ -0,0 +1,11 @@
+/* Our second set comes from the i386 files.
+ Only a couple of calls we cannot support without the i386 headers. */
+
+#define sys_oldstat printargs
+#define sys_oldfstat printargs
+#define sys_oldlstat printargs
+#define sys_lseek sys_lseek32
+#define sys_lstat64 sys_stat64
+#define sys_truncate64 sys_truncate
+#define sys_ftruncate64 sys_ftruncate
+#include "i386/syscallent.h"
diff --git a/mem.c b/mem.c
index 8e34f966e..027903051 100644
--- a/mem.c
+++ b/mem.c
@@ -311,6 +311,40 @@ sys_mmap(struct tcb *tcp)
#endif /* !HAVE_LONG_LONG_OFF_T */
#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
+# if defined(X32)
+int sys_old_mmap(struct tcb *tcp)
+{
+ long u_arg[6];
+ if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1)
+ return 0;
+ if (entering(tcp)) {
+ /* addr */
+ if (!u_arg[0])
+ tprints("NULL, ");
+ else
+ tprintf("%#lx, ", u_arg[0]);
+ /* len */
+ tprintf("%lu, ", u_arg[1]);
+ /* prot */
+ printflags(mmap_prot, u_arg[2], "PROT_???");
+ tprints(", ");
+ /* flags */
+# ifdef MAP_TYPE
+ printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
+ addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
+# else
+ printflags(mmap_flags, u_arg[3], "MAP_???");
+# endif
+ /* fd */
+ tprints(", ");
+ printfd(tcp, u_arg[4]);
+ /* offset */
+ tprintf(", %#lx", u_arg[5]);
+ }
+ return RVAL_HEX;
+}
+# endif
+
/* TODO: comment which arches use this routine.
* For one, does ALPHA on Linux use this??
* From code it seems that it might use 7 or 8 registers,
diff --git a/pathtrace.c b/pathtrace.c
index 886932c87..c000c835f 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -224,9 +224,7 @@ pathtrace_match(struct tcb *tcp)
}
if (
-#if !defined X32
s->sys_func == sys_old_mmap ||
-#endif
s->sys_func == sys_mmap) {
/* x, x, x, x, fd */
return fdmatch(tcp, tcp->u_arg[4]);
diff --git a/syscall.c b/syscall.c
index 44964bccb..52d742f7e 100644
--- a/syscall.c
+++ b/syscall.c
@@ -273,6 +273,12 @@ update_personality(struct tcb *tcp, int personality)
fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
tcp->pid, names[personality]);
}
+# elif defined(X32)
+ if (!qflag) {
+ static const char *const names[] = {"x32", "32 bit"};
+ fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
+ tcp->pid, names[personality]);
+ }
# endif
}
#endif
@@ -868,15 +874,25 @@ get_scno(struct tcb *tcp)
}
# endif
# ifdef X32
- if (currpers == 0 || currpers == 1) {
- fprintf(stderr, "syscall_%lu (...) in unsupported %s "
- "mode of process PID=%d\n", scno,
- currpers == 0 ? "64-bit" : "32-bit", tcp->pid);
- return 0;
+ /* Value of currpers:
+ * 0: 64 bit
+ * 1: 32 bit
+ * 2: X32
+ * Value of current_personality:
+ * 0: X32
+ * 1: 32 bit
+ */
+ switch (currpers) {
+ case 0:
+ fprintf(stderr, "syscall_%lu (...) in unsupported "
+ "64-bit mode of process PID=%d\n",
+ scno, tcp->pid);
+ return 0;
+ case 2:
+ currpers = 0;
}
-# else
- update_personality(tcp, currpers);
# endif
+ update_personality(tcp, currpers);
#elif defined(IA64)
# define IA64_PSR_IS ((long)1 << 34)
if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)