]> granicus.if.org Git - strace/commitdiff
x32: add ia32 support
authorH.J. Lu <hongjiu.lu@intel.com>
Tue, 17 Apr 2012 18:05:04 +0000 (11:05 -0700)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 18 Apr 2012 15:02:40 +0000 (15:02 +0000)
* 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.

12 files changed:
Makefile.am
configure.ac
defs.h
file.c
linux/syscall.h
linux/x32/errnoent1.h [new file with mode: 0644]
linux/x32/ioctlent1.h [new file with mode: 0644]
linux/x32/signalent1.h [new file with mode: 0644]
linux/x32/syscallent1.h [new file with mode: 0644]
mem.c
pathtrace.c
syscall.c

index 7398b79394c8a21cf8a1679994d890ab6ed30fad..e9393d8f75006bde6a39a351e67c538be968f181 100644 (file)
@@ -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 \
index f55b8a204a85511782c433d76eda87d638478268..879ad9a9765ba6e5d35298a095a00172777c4583 100644 (file)
@@ -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 ddde2715198e5a99cdf13cc99b845cb64f6e76a9..ed095346bde6577f202984e9ab7ef2ef40a71185 100644 (file)
--- 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 5f3b506aacd6f4b119c7ffb80fea97a2e7793c49..0cda7e127b71342674c316d23c93eefd5437febb 100644 (file)
--- 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
index e56697db4c5f18ac0a3552f5be16a076305cf5f1..7e0155ec50e512dd22e2ebe7a5f15b715fb52555 100644 (file)
@@ -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 (file)
index 0000000..a894827
--- /dev/null
@@ -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 (file)
index 0000000..1f92feb
--- /dev/null
@@ -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 (file)
index 0000000..5c18d98
--- /dev/null
@@ -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 (file)
index 0000000..20c6529
--- /dev/null
@@ -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 8e34f966eee3aad937783a432a5816679daa241d..027903051a1d3a35a1b06fdd418b6f2c7491e572 100644 (file)
--- 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,
index 886932c87392ccceb930629bc996bffcf2c9d5ab..c000c835f9077d7e4e7c290245d5c7bd74c4ec5b 100644 (file)
@@ -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]);
index 44964bccb6aec995f8e8c50759ffe898cedad965..52d742f7e324f20bf82ee288a8c7fd13c0a5ebbf 100644 (file)
--- 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)