]> granicus.if.org Git - strace/commitdiff
semctl: fix indirect syscall decoding
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 11 Mar 2015 14:57:57 +0000 (14:57 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 16 Mar 2015 14:23:09 +0000 (14:23 +0000)
On architectures where the semctl call is implemented by the ipc syscall
the 4th argument is passed by reference.

* ipc.c (sys_semctl): Handle the indirect ipc subcall case.
* tests/ipc_sem.c (main): Optionally match indirection
in the 4th argument of semctl calls.

Reported-by: Andreas Schwab <schwab@suse.de>
ipc.c
tests/ipc_sem.c

diff --git a/ipc.c b/ipc.c
index 4387772a3b223f60da14306a8db966ed3d461bb5..a94f572c9f393e1165f0bc800baeea2c1fe92721 100644 (file)
--- a/ipc.c
+++ b/ipc.c
@@ -281,7 +281,16 @@ int sys_semctl(struct tcb *tcp)
        if (entering(tcp)) {
                tprintf("%lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
                PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
-               tprintf(", %#lx", tcp->u_arg[3]);
+               tprints(", ");
+               if (indirect_ipccall(tcp)) {
+                       if (current_wordsize == sizeof(int)) {
+                               printnum_int(tcp, tcp->u_arg[3], "%#x");
+                       } else {
+                               printnum_long(tcp, tcp->u_arg[3], "%#lx");
+                       }
+               } else {
+                       tprintf("%#lx", tcp->u_arg[3]);
+               }
        }
        return 0;
 }
index d92ec60dbbfe5b9ddbacb50d3c76ad8629bb1e8c..64450b89aecede521449177ad0aced6264041d41 100644 (file)
@@ -26,13 +26,15 @@ main(void)
        un.buf = &ds;
        if (semctl(id, 0, IPC_STAT, un))
                goto fail;
-       printf("semctl\\(%d, 0, (IPC_64\\|)?IPC_STAT, %p\\) += 0\n", id, &ds);
+       printf("semctl\\(%d, 0, (IPC_64\\|)?IPC_STAT, \\[?%p\\]?\\) += 0\n",
+              id, &ds);
 
        un.__buf = &info;
        int max = semctl(0, 0, SEM_INFO, un);
        if (max < 0)
                goto fail;
-       printf("semctl\\(0, 0, (IPC_64\\|)?SEM_INFO, %p\\) += %d\n", &info, max);
+       printf("semctl\\(0, 0, (IPC_64\\|)?SEM_INFO, \\[?%p\\]?\\) += %d\n",
+              &info, max);
 
        un.buf = &ds;
        rc = semctl(id, 0, SEM_STAT, un);
@@ -43,16 +45,18 @@ main(void)
                 */
                if (-1 != rc || EINVAL != errno)
                        goto fail;
-               printf("semctl\\(%d, 0, (IPC_64\\|)?SEM_STAT, %p\\) += -1 EINVAL \\(Invalid argument\\)\n", id, &ds);
+               printf("semctl\\(%d, 0, (IPC_64\\|)?SEM_STAT, \\[?%p\\]?\\)"
+                      " += -1 EINVAL \\(Invalid argument\\)\n", id, &ds);
        } else {
-               printf("semctl\\(%d, 0, (IPC_64\\|)?SEM_STAT, %p\\) += %d\n", id, &ds, id);
+               printf("semctl\\(%d, 0, (IPC_64\\|)?SEM_STAT, \\[?%p\\]?\\)"
+                      " += %d\n", id, &ds, id);
        }
 
        rc = 0;
 done:
        if (semctl(id, 0, IPC_RMID, 0) < 0)
                return 1;
-       printf("semctl\\(%d, 0, (IPC_64\\|)?IPC_RMID, 0\\) += 0\n", id);
+       printf("semctl\\(%d, 0, (IPC_64\\|)?IPC_RMID, \\[?0\\]?\\) += 0\n", id);
        return rc;
 
 fail: