]> granicus.if.org Git - strace/commitdiff
Add biarch support for powerpc64
authorAndreas Schwab <schwab@linux-m68k.org>
Mon, 12 Jul 2010 19:39:57 +0000 (21:39 +0200)
committerAndreas Schwab <schwab@linux-m68k.org>
Tue, 13 Jul 2010 17:13:03 +0000 (19:13 +0200)
* acinclude.m4 (AC_LITTLE_ENDIAN_LONG_LONG): Use int instead of
long.
* configure.ac [$host_cpu = powerpc*]: Also define POWERPC64 if
$host_cpu = powerpc64.
* defs.h (SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE)
(PERSONALITY1_WORDSIZE) [POWERPC64]: Define.
* file.c: (struct stat_powerpc32, printstat_powerpc32) [POWERPC64]:
Define.
(printstat) [LINUX && POWERPC64]: Use printstat_powerpc32 in
32-bit personality.
(sys_newfstatat) [POWERPC64]: Handle personalities.
* signal.c (sys_sigreturn) [POWERPC64]: Likewise.
* util.c (printllval) [POWERPC64]: Likewise.
(printcall) [POWERPC64]: Use wider format for IP prefix.
* syscall.c (get_scno) [POWERPC64]: Check for 64/32 bit mode.
* linux/powerpc/errnoent1.h: New file.
* linux/powerpc/ioctlent1.h: New file.
* linux/powerpc/signalent1.h: New file.
* linux/powerpc/syscallent1.h: New file.

acinclude.m4
configure.ac
defs.h
file.c
linux/powerpc/errnoent1.h [new file with mode: 0644]
linux/powerpc/ioctlent1.h [new file with mode: 0644]
linux/powerpc/signalent1.h [new file with mode: 0644]
linux/powerpc/syscallent1.h [new file with mode: 0644]
signal.c
syscall.c
util.c

index da66c646a6cfb526550ba953f225b20148ecc857..1741ab99b765f82679f60fafcc9bb94da146cee5 100644 (file)
@@ -280,7 +280,7 @@ AC_CACHE_VAL(ac_cv_have_little_endian_long_long,
 int main () {
        union {
                long long ll;
-               long l [2];
+               int l [2];
        } u;
        u.ll = 0x12345678;
        if (u.l[0] == 0x12345678)
index 76f55d290f3928b4a2fe4ea70aa3150e14e5ce77..40fa15b97da1e3d8363530fbeb81b054841cf1f2 100644 (file)
@@ -79,6 +79,9 @@ alpha*)
 powerpc*)
        arch=powerpc
        AC_DEFINE([POWERPC], 1, [Define for the PowerPC architecture.])
+       if test $host_cpu = powerpc64; then
+               AC_DEFINE([POWERPC64], 1, [Define for the PowerPC64 architecture.])
+       fi
        ;;
 arm*)
        arch=arm
diff --git a/defs.h b/defs.h
index a7e8793319c8670383771237197a2a4f07e76372..419b12e58a50d4c8547e43cd6bafe7c3fc1ba857 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -246,6 +246,13 @@ extern int ptrace(int, int, char *, int, ...);
 #define PERSONALITY1_WORDSIZE 4
 #endif
 
+#ifdef POWERPC64
+#undef SUPPORTED_PERSONALITIES
+#define SUPPORTED_PERSONALITIES 2
+#define PERSONALITY0_WORDSIZE 8
+#define PERSONALITY1_WORDSIZE 4
+#endif
+
 #ifdef SVR4
 #ifdef HAVE_MP_PROCFS
 extern int mp_ioctl (int f, int c, void *a, int s);
diff --git a/file.c b/file.c
index 854548f7a0987aef65af84ce5c110c3e123bc0b9..afdbf328da1747d488f2dcd56c441093cb1b3cd5 100644 (file)
--- a/file.c
+++ b/file.c
@@ -859,6 +859,71 @@ printstat_sparc64(struct tcb *tcp, long addr)
 #endif /* SPARC64 */
 #endif /* LINUXSPARC */
 
+#if defined LINUX && defined POWERPC64
+struct stat_powerpc32 {
+       unsigned int    st_dev;
+       unsigned int    st_ino;
+       unsigned int    st_mode;
+       unsigned short  st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_rdev;
+       unsigned int    st_size;
+       unsigned int    st_blksize;
+       unsigned int    st_blocks;
+       unsigned int    st_atime;
+       unsigned int    st_atime_nsec;
+       unsigned int    st_mtime;
+       unsigned int    st_mtime_nsec;
+       unsigned int    st_ctime;
+       unsigned int    st_ctime_nsec;
+       unsigned int    __unused4;
+       unsigned int    __unused5;
+};
+
+static void
+printstat_powerpc32(struct tcb *tcp, long addr)
+{
+       struct stat_powerpc32 statbuf;
+
+       if (umove(tcp, addr, &statbuf) < 0) {
+               tprintf("{...}");
+               return;
+       }
+
+       if (!abbrev(tcp)) {
+               tprintf("{st_dev=makedev(%u, %u), st_ino=%u, st_mode=%s, ",
+                       major(statbuf.st_dev), minor(statbuf.st_dev),
+                       statbuf.st_ino,
+                       sprintmode(statbuf.st_mode));
+               tprintf("st_nlink=%u, st_uid=%u, st_gid=%u, ",
+                       statbuf.st_nlink, statbuf.st_uid, statbuf.st_gid);
+               tprintf("st_blksize=%u, ", statbuf.st_blksize);
+               tprintf("st_blocks=%u, ", 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=%u, ", 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));
+               tprintf("}");
+       }
+       else
+               tprintf("...}");
+}
+#endif /* LINUX && POWERPC64 */
+
 static const struct xlat fileflags[] = {
 #ifdef FREEBSD
        { UF_NODUMP,    "UF_NODUMP"     },
@@ -998,6 +1063,13 @@ printstat(struct tcb *tcp, long addr)
 #endif
 #endif /* LINUXSPARC */
 
+#if defined LINUX && defined POWERPC64
+       if (current_personality == 1) {
+               printstat_powerpc32(tcp, addr);
+               return;
+       }
+#endif
+
        if (umove(tcp, addr, &statbuf) < 0) {
                tprintf("{...}");
                return;
@@ -1259,7 +1331,12 @@ sys_newfstatat(struct tcb *tcp)
                printpath(tcp, tcp->u_arg[1]);
                tprintf(", ");
        } else {
-#if defined HAVE_STAT64 && !(defined POWERPC && defined __powerpc64__)
+#ifdef POWERPC64
+               if (current_personality == 0)
+                       printstat(tcp, tcp->u_arg[2]);
+               else
+                       printstat64(tcp, tcp->u_arg[2]);
+#elif defined HAVE_STAT64
                printstat64(tcp, tcp->u_arg[2]);
 #else
                printstat(tcp, tcp->u_arg[2]);
diff --git a/linux/powerpc/errnoent1.h b/linux/powerpc/errnoent1.h
new file mode 100644 (file)
index 0000000..441c66b
--- /dev/null
@@ -0,0 +1 @@
+#include "../errnoent.h"
diff --git a/linux/powerpc/ioctlent1.h b/linux/powerpc/ioctlent1.h
new file mode 100644 (file)
index 0000000..72eeaf1
--- /dev/null
@@ -0,0 +1 @@
+#include "ioctlent.h"
diff --git a/linux/powerpc/signalent1.h b/linux/powerpc/signalent1.h
new file mode 100644 (file)
index 0000000..d31e6a4
--- /dev/null
@@ -0,0 +1 @@
+#include "../signalent.h"
diff --git a/linux/powerpc/syscallent1.h b/linux/powerpc/syscallent1.h
new file mode 100644 (file)
index 0000000..49ccb8a
--- /dev/null
@@ -0,0 +1 @@
+#include "syscallent.h"
index bf97e900e0b4c099ddab7f307fe5a890ce966568..337dd6abb0952774c097b0fbba8539f645b98216 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1330,8 +1330,11 @@ sys_sigreturn(struct tcb *tcp)
                if (upeek(tcp, sizeof(unsigned long)*PT_R1, &esp) < 0)
                        return 0;
                /* Skip dummy stack frame. */
-#ifdef __powerpc64__
-               esp += 128;
+#ifdef POWERPC64
+               if (current_personality == 0)
+                       esp += 128;
+               else
+                       esp += 64;
 #else
                esp += 64;
 #endif
index ba2185c804bfb96095d8389e36d6d79c87b805c7..f33ae4ce3ef393007944485505755eaf583d29d4 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -883,6 +883,29 @@ get_scno(struct tcb *tcp)
                        return 0;
                }
        }
+
+#  ifdef POWERPC64
+       if (!(tcp->flags & TCB_INSYSCALL)) {
+               static int currpers = -1;
+               long val;
+               int pid = tcp->pid;
+
+               /* Check for 64/32 bit mode. */
+               if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
+                       return -1;
+               /* SF is bit 0 of MSR */
+               if (val < 0)
+                       currpers = 0;
+               else
+                       currpers = 1;
+               if (currpers != current_personality) {
+                       static const char *const names[] = {"64 bit", "32 bit"};
+                       set_personality(currpers);
+                       printf("[ Process PID=%d runs in %s mode. ]\n",
+                                       pid, names[current_personality]);
+               }
+       }
+#  endif
 # elif defined(AVR32)
        /*
         * Read complete register set in one go.
diff --git a/util.c b/util.c
index bd12c0f7b1480a404e26e82bf0a2e81a041cbba4..07cbfdeda40b308843318581a9beea61af7c2ee6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -251,20 +251,24 @@ int
 printllval(struct tcb *tcp, const char *format, int llarg)
 {
 # if defined(FREEBSD) \
-     || (defined(LINUX) && defined(POWERPC) && !defined(__powerpc64__)) \
+     || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
      || defined (LINUX_MIPSO32)
        /* Align 64bit argument to 64bit boundary.  */
        if (llarg % 2) llarg++;
 # endif
-# if defined LINUX && defined X86_64
+# if defined LINUX && (defined X86_64 || defined POWERPC64)
        if (current_personality == 0) {
                tprintf(format, tcp->u_arg[llarg]);
                llarg++;
        } else {
+#  ifdef POWERPC64
+               /* Align 64bit argument to 64bit boundary.  */
+               if (llarg % 2) llarg++;
+#  endif
                tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
                llarg += 2;
        }
-# elif defined IA64 || defined ALPHA || (defined POWERPC && defined __powerpc64__)
+# elif defined IA64 || defined ALPHA
        tprintf(format, tcp->u_arg[llarg]);
        llarg++;
 # elif defined LINUX_MIPSN32
@@ -1110,10 +1114,14 @@ printcall(struct tcb *tcp)
        long pc;
 
        if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
-               tprintf ("[????????] ");
+               PRINTBADPC;
                return;
        }
+#  ifdef POWERPC64
+       tprintf("[%016lx] ", pc);
+#  else
        tprintf("[%08lx] ", pc);
+#  endif
 # elif defined(M68K)
        long pc;