]> granicus.if.org Git - strace/commitdiff
2003-12-31 David Mosberger <davidm@hpl.hp.com>
authorRoland McGrath <roland@redhat.com>
Fri, 20 Feb 2004 22:56:43 +0000 (22:56 +0000)
committerRoland McGrath <roland@redhat.com>
Fri, 20 Feb 2004 22:56:43 +0000 (22:56 +0000)
* process.c (internal_exit): For ia64, also recognize IA-32 252
as exit_group().
(change_syscall): For IA64, also support changing IA-32 syscalls.
* syscall.c (internal_syscall): For IA64, also recognize IA-32
        syscall 252 (exit_group) as an internal_exit() syscall.
* util.c (SYS_fork): For IA64, define them to the IA-32 syscall
number.
(SYS_vfork): Likewise.
(arg_setup): For IA64 version, also support IA-32 syscalls.
(get_arg0): Likewise.
(get_arg1): Likewise.
(set_arg0): Likewise.
(set_arg1): Likewise.

process.c
syscall.c
util.c

index de7833f6d8e27e60dce26d670898210d83baf59c..1839463c69035840d14ffffe2ec2daed1b36af42 100644 (file)
--- a/process.c
+++ b/process.c
@@ -373,6 +373,12 @@ struct tcb *tcp;
        if (entering(tcp)) {
                tcp->flags |= TCB_EXITING;
 #ifdef __NR_exit_group
+# ifdef IA64
+               if (ia32) {
+                       if (tcp->scno == 252)
+                               tcp->flags |= TCB_GROUP_EXITING;
+               } else
+# endif
                if (tcp->scno == __NR_exit_group)
                        tcp->flags |= TCB_GROUP_EXITING;
 #endif
@@ -657,7 +663,18 @@ int new;
                return -1;
        return 0;
 #elif defined(IA64)
-       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0)
+       if (ia32) {
+               switch (new) {
+                     case 2: break;    /* x86 SYS_fork */
+                     case SYS_clone:   new = 120; break;
+                     default:
+                       fprintf(stderr, "%s: unexpected syscall %d\n",
+                               __FUNCTION__, new);
+                       return -1;
+               }
+               if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new)<0)
+                       return -1;
+       } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0)
                return -1;
        return 0;
 #elif defined(HPPA)
index 2a04c2a47a60bab42f9b9e017f537402094094ad..d2981b7ba8a20fcce1282f11c562a74e65c400a8 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -679,6 +679,9 @@ struct tcb *tcp;
 #endif
 #ifdef __NR_exit_group
        case __NR_exit_group:
+#endif
+#ifdef IA64
+       case 252: /* IA-32 __NR_exit_group */
 #endif
                internal_exit(tcp);
                break;
diff --git a/util.c b/util.c
index 7dcc5b3b134e4d00b0ee17957ef3a3633d849913..4663bc9c8435d3fc6aa7a40a49afc57a9f81fa37 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1154,6 +1154,11 @@ struct tcb *tcp;
 
 #ifdef IA64
 
+/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
+   subsystem has them for x86... */
+#define SYS_fork       2
+#define SYS_vfork      190
+
 typedef unsigned long *arg_setup_state;
 
 static int
@@ -1161,6 +1166,9 @@ arg_setup(struct tcb *tcp, arg_setup_state *state)
 {
        unsigned long *bsp, cfm, sof, sol;
 
+       if (ia32)
+               return 0;
+
        if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
                return -1;
        if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
@@ -1180,35 +1188,61 @@ arg_setup(struct tcb *tcp, arg_setup_state *state)
 static int
 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
 {
-       return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
-                      sizeof(long), (void *) valp);
+       int ret;
+
+       if (ia32)
+               ret = upeek (tcp->pid, PT_R11, valp);
+       else
+               ret = umoven (tcp,
+                             (unsigned long) ia64_rse_skip_regs(*state, 0),
+                             sizeof(long), (void *) valp);
+       return ret;
 }
 
 static int
 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
 {
-       return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
-                      sizeof(long), (void *) valp);
+       int ret;
+
+       if (ia32)
+               ret = upeek (tcp->pid, PT_R9, valp);
+       else
+               ret = umoven (tcp,
+                             (unsigned long) ia64_rse_skip_regs(*state, 1),
+                             sizeof(long), (void *) valp);
+       return ret;
 }
 #endif
 
 static int
 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
 {
-       unsigned long *ap;
-       ap = ia64_rse_skip_regs(*state, 0);
+       int req = PTRACE_POKEDATA;
+       void *ap;
+
+       if (ia32) {
+               ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
+               req = PTRACE_POKEUSER;
+       } else
+               ap = ia64_rse_skip_regs(*state, 0);
        errno = 0;
-       ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
+       ptrace(req, tcp->pid, ap, val);
        return errno ? -1 : 0;
 }
 
 static int
 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
 {
-       unsigned long *ap;
-       ap = ia64_rse_skip_regs(*state, 1);
+       int req = PTRACE_POKEDATA;
+       void *ap;
+
+       if (ia32) {
+               ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
+               req = PTRACE_POKEUSER;
+       } else
+               ap = ia64_rse_skip_regs(*state, 1);
        errno = 0;
-       ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
+       ptrace(req, tcp->pid, ap, val);
        return errno ? -1 : 0;
 }