Package: strace
Version: 4.5.12-1

  strace does not correctly report the parameters for ipc syscalls
on architectures other than i386.  It shuffles the order of parameters
on several calls.  That should only be done on i386 systems.  The use
of incorrect parameters also results in bad addresses and errors such as-
    ptrace: umoven: Input/output error
    umovestr: Input/output error

  I have created a patch for this.  It is attached as strace.patch.
I tested it on x86_64, ia64, and hppa systems with the attached ipc_test.c
program.  It can be run with
    trace -f -e trace=ipc -o ipc_test.strace ./ipc_test
    cat ipc_test.strace
to show the interesting msg*, sem*, and shm* parameters.

  There may be more changes appropriate for the syscallent.h files for other
non-i386 architectures.  They may need changes to use sys_* functions and
get the right number of parameters.  I don't have those at hand to test.

-- 
Mike Stroyan, [EMAIL PROTECTED]
diff -u -r strace-4.5.12/debian/changelog strace-4.5.12.1/debian/changelog
--- strace-4.5.12/debian/changelog      2005-11-21 15:25:13.000000000 -0700
+++ strace-4.5.12.1/debian/changelog    2005-11-21 15:26:10.000000000 -0700
@@ -1,3 +1,9 @@
+strace (4.5.12-1.1) unstable; urgency=low
+  * Handle non-i386 architectures in ipc.c, no parameter shuffling
+  * Fix number of arguments to msgrcv on hppa and x86_64
+
+ -- Mike Stroyan <[EMAIL PROTECTED]>  Mon, 21 Nov 2005 14:38:39 -0700
+
 strace (4.5.12-1) unstable; urgency=low
 
   * New upstream version.
diff -u -r strace-4.5.12/ipc.c strace-4.5.12.1/ipc.c
--- strace-4.5.12/ipc.c 2005-11-21 15:25:13.000000000 -0700
+++ strace-4.5.12.1/ipc.c       2005-11-21 15:25:10.000000000 -0700
@@ -183,11 +183,11 @@
        if (entering(tcp)) {
                tprintf("%lu, ", tcp->u_arg[0]);
                PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
-#ifdef LINUX
+#if defined LINUX && defined I386
                tprintf(", %#lx", tcp->u_arg[3]);
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                tprintf(", %#lx", tcp->u_arg[2]);
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        }
        return 0;
 }
@@ -199,7 +199,7 @@
 
        if (entering(tcp)) {
                tprintf("%lu", tcp->u_arg[0]);
-#ifdef LINUX
+#if defined LINUX && defined I386
                umove(tcp, tcp->u_arg[3], &mtype);
                tprintf(", {%lu, ", mtype);
                printstr(tcp, tcp->u_arg[3] + sizeof(long),
@@ -207,7 +207,7 @@
                tprintf("}, %lu", tcp->u_arg[1]);
                tprintf(", ");
                printflags(msg_flags, tcp->u_arg[2], "MSG_???");
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                umove(tcp, tcp->u_arg[1], &mtype);
                tprintf(", {%lu, ", mtype);
                printstr(tcp, tcp->u_arg[1] + sizeof(long),
@@ -215,7 +215,7 @@
                tprintf("}, %lu", tcp->u_arg[2]);
                tprintf(", ");
                printflags(msg_flags, tcp->u_arg[3], "MSG_???");
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        }
        return 0;
 }
@@ -224,7 +224,7 @@
 struct tcb *tcp;
 {
        long mtype;
-#ifdef LINUX
+#if defined LINUX && defined I386
        struct ipc_wrapper {
                struct msgbuf *msgp;
                long msgtyp;
@@ -234,7 +234,7 @@
 
        if (exiting(tcp)) {
                tprintf("%lu", tcp->u_arg[0]);
-#ifdef LINUX
+#if defined LINUX && defined I386
                umove(tcp, tcp->u_arg[3], &tmp);
                umove(tcp, (long) tmp.msgp, &mtype);
                tprintf(", {%lu, ", mtype);
@@ -244,7 +244,7 @@
                tprintf(", %ld", tmp.msgtyp);
                tprintf(", ");
                printflags(msg_flags, tcp->u_arg[2], "MSG_???");
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                umove(tcp, tcp->u_arg[1], &mtype);
                tprintf(", {%lu, ", mtype);
                printstr(tcp, tcp->u_arg[1] + sizeof(long),
@@ -253,7 +253,7 @@
                tprintf(", %ld", tcp->u_arg[3]);
                tprintf(", ");
                printflags(msg_flags, tcp->u_arg[4], "MSG_???");
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        }
        return 0;
 }
@@ -263,13 +263,13 @@
 {
        if (entering(tcp)) {
                tprintf("%lu", tcp->u_arg[0]);
-#ifdef LINUX
+#if defined LINUX && defined I386
                tprintf(", %#lx", tcp->u_arg[3]);
                tprintf(", %lu", tcp->u_arg[1]);
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                tprintf(", %#lx", tcp->u_arg[1]);
                tprintf(", %lu", tcp->u_arg[2]);
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        }
        return 0;
 }
@@ -279,10 +279,17 @@
 struct tcb *tcp;
 {
        if (entering(tcp)) {
+#if defined I386
                tprintf("%lu", tcp->u_arg[0]);
                tprintf(", %#lx", tcp->u_arg[3]);
                tprintf(", %lu, ", tcp->u_arg[1]);
                printtv(tcp, tcp->u_arg[5]);
+#else
+               tprintf("%lu", tcp->u_arg[0]);
+               tprintf(", %#lx", tcp->u_arg[1]);
+               tprintf(", %lu, ", tcp->u_arg[2]);
+               printtv(tcp, tcp->u_arg[3]);
+#endif
        }
        return 0;
 }
@@ -340,11 +347,11 @@
        if (entering(tcp)) {
                tprintf("%lu, ", tcp->u_arg[0]);
                PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
-#ifdef LINUX
+#if defined LINUX && defined I386
                tprintf(", %#lx", tcp->u_arg[3]);
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                tprintf(", %#lx", tcp->u_arg[2]);
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        }
        return 0;
 }
@@ -352,28 +359,28 @@
 int sys_shmat(tcp)
 struct tcb *tcp;
 {
-#ifdef LINUX
+#if defined LINUX && defined I386
        unsigned long raddr;
-#endif /* LINUX */
+#endif /* !(LINUX I386)*/
 
        if (exiting(tcp)) {
                tprintf("%lu", tcp->u_arg[0]);
-#ifdef LINUX
+#if defined LINUX && defined I386
                tprintf(", %#lx", tcp->u_arg[3]);
                tprintf(", ");
                printflags(shm_flags, tcp->u_arg[1], "SHM_???");
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                tprintf(", %#lx", tcp->u_arg[1]);
                tprintf(", ");
                printflags(shm_flags, tcp->u_arg[2], "SHM_???");
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
                if (syserror(tcp))
                        return 0;
-#ifdef LINUX
+#if defined LINUX && defined I386
                if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
                        return RVAL_NONE;
                tcp->u_rval = raddr;
-#endif /* LINUX */
+#endif /* !(LINUX I386)*/
                return RVAL_HEX;
        }
        return 0;
@@ -383,11 +390,11 @@
 struct tcb *tcp;
 {
        if (entering(tcp))
-#ifdef LINUX
+#if defined LINUX && defined I386
                tprintf("%#lx", tcp->u_arg[3]);
-#else /* !LINUX */
+#else /* !(LINUX I386)*/
                tprintf("%#lx", tcp->u_arg[0]);
-#endif /* !LINUX */
+#endif /* !(LINUX I386)*/
        return 0;
 }
 
Only in strace-4.5.12.1: ipc_test.strace
diff -u -r strace-4.5.12/linux/hppa/syscallent.h 
strace-4.5.12.1/linux/hppa/syscallent.h
--- strace-4.5.12/linux/hppa/syscallent.h       2005-11-21 15:25:13.000000000 
-0700
+++ strace-4.5.12.1/linux/hppa/syscallent.h     2005-11-21 15:25:10.000000000 
-0700
@@ -194,7 +194,7 @@
        { 4,    TI,     sys_semget,             "semget"                }, /* 
186 */
        { 4,    TI,     sys_semctl,             "semctl"                }, /* 
187 */
        { 4,    TI,     sys_msgsnd,             "msgsnd"                }, /* 
188 */
-       { 4,    TI,     sys_msgrcv,             "msgrcv"                }, /* 
189 */
+       { 5,    TI,     sys_msgrcv,             "msgrcv"                }, /* 
189 */
        { 4,    TI,     sys_msgget,             "msgget"                }, /* 
190 */
        { 4,    TI,     sys_msgctl,             "msgctl"                }, /* 
191 */
        { 4,    TI,     sys_shmat,              "shmat"                 }, /* 
192 */
diff -u -r strace-4.5.12/linux/x86_64/syscallent.h 
strace-4.5.12.1/linux/x86_64/syscallent.h
--- strace-4.5.12/linux/x86_64/syscallent.h     2005-11-21 15:25:13.000000000 
-0700
+++ strace-4.5.12.1/linux/x86_64/syscallent.h   2005-11-21 15:25:10.000000000 
-0700
@@ -68,7 +68,7 @@
        { 4,    TI,     sys_shmdt,              "shmdt"         },  /* 67 */
        { 4,    TI,     sys_msgget,             "msgget"        },  /* 68 */
        { 4,    TI,     sys_msgsnd,             "msgsnd"        },  /* 69 */
-       { 4,    TI,     sys_msgrcv,             "msgrcv"        },  /* 70 */
+       { 5,    TI,     sys_msgrcv,             "msgrcv"        },  /* 70 */
        { 4,    TI,     sys_msgctl,             "msgctl"        },  /* 71 */
        { 3,    0,      sys_fcntl,              "fcntl"         },  /* 72 */
        { 2,    0,      sys_flock,              "flock"         },  /* 73 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/wait.h>

struct mybuf {
    long mtype;
    char mtext[10];
};

void parent(int queue)
{
    int result;
    struct mybuf buf;
    struct msqid_ds statbuf;

    printf("parent &buf is 0x%p\n", &buf);
    buf.mtype = 1;
    buf.mtext[0] = 'A';
    result = msgsnd(queue, (struct msgbuf *)&buf, 1, 0);
    if (result == -1) {
	perror("parent msgsnd failed");
	return;
    }
    printf("parent sent %c\n", buf.mtext[0]);
    result = msgrcv(queue, (struct msgbuf *)&buf, 1, 2, MSG_NOERROR);
    if (result == -1) {
	perror("parent msgrcv failed");
	return;
    }
    printf("parent received %c\n", buf.mtext[0]);
    result = msgctl(queue, IPC_STAT, &statbuf); 
    printf("max queue length = %lu\n", statbuf.msg_qbytes);
    result = msgctl(queue, IPC_RMID, NULL); 
}

void child(int queue)
{
    int result;
    struct mybuf buf;

    printf("child &buf is 0x%p\n", &buf);
    result = msgrcv(queue, (struct msgbuf *)&buf, 1, 1, 0);
    if (result == -1) {
	perror("child msgrcv failed");
	return;
    }
    printf("child received %c\n", buf.mtext[0]);
    buf.mtype = 2;
    buf.mtext[0] = 'B';
    result = msgsnd(queue, (struct msgbuf *)&buf, 1, 0);
    if (result == -1) {
	perror("child msgsnd failed");
	return;
    }
    printf("child sent %c\n", buf.mtext[0]);
}

int main(int argc, char *argv[])
{
    int queue;
    pid_t pid;

    queue = msgget(IPC_PRIVATE , IPC_CREAT | 0600);
    if (queue == -1) {
	perror("msgget failed");
	return 1;
    }
    switch(pid = fork()) {
	case -1:
	    perror("fork failed");
	    return 1;
	case 0:
	    child(queue);
	    break;
	default:
	    parent(queue);
	    waitpid(pid, NULL, 0);
	    break;
    }

    {
        register int semid;
        struct sembuf P_op, V_op;
        union semun {
            int val;
            struct semid_ds *buf;
            unsigned short *array;
        } arg;
	struct timespec timespec;

        semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
        arg.val = 1;
        semctl(semid, 0, SETVAL, arg);

        P_op.sem_num = 0;
        P_op.sem_op = -1;  /* Down the semaphore */
        P_op.sem_flg = SEM_UNDO;        /* Recover if process dies */

        V_op.sem_num = 0;
        V_op.sem_op = 1;   /* Raise the semaphore */
        V_op.sem_flg = SEM_UNDO;        /* Recover if process dies */

	timespec.tv_sec=1; /* seconds */
	timespec.tv_nsec=2; /* nanoseconds */

        semop(semid, &P_op, 1);
	semtimedop(semid, &V_op, 1, &timespec);

        semctl(semid, 0, IPC_RMID, 0);
    }
    {
        int shmid;
        void *addr;
	struct shmid_ds statbuf;

        shmid = shmget(IPC_PRIVATE, 16384, IPC_CREAT | 0777);
        if (shmid == -1) {
	    perror("shmget failed");
	    return 1;
	}
        addr = shmat(shmid, NULL, 0);
        if (addr == (caddr_t) -1) {
	    perror("shmat failed");
	    return 1;
	}
	printf("shm addr = 0x%p\n", addr);
	shmctl(shmid, IPC_STAT, &statbuf);
	printf("shm size = 0x%zu\n", (long) statbuf.shm_segsz);
	shmctl(shmid, IPC_RMID, NULL);
	shmdt(addr);
    }

    return 0;
}

Reply via email to