]> granicus.if.org Git - strace/commitdiff
x32: fix struct dirent decoding
authorDmitry V. Levin <ldv@altlinux.org>
Fri, 27 Nov 2015 01:51:22 +0000 (01:51 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 27 Nov 2015 01:51:22 +0000 (01:51 +0000)
* kernel_types.h: New file.
* Makefile.am (strace_SOURCES): Add it.
* configure.ac (AC_CHECK_TYPES): Check for __kernel_long_t
and __kernel_ulong_t in <asm/posix_types.h>.
* dirent.c: Stop including <dirent.h>.
(kernel_dirent): Remove.
Include "kernel_types.h".
(print_old_dirent, SYS_FUNC(getdents)): Print variables
of kernel_ulong_t type using %Lu format.
* syscall.c (kernel_long_t, kernel_ulong_t): Remove.
Include "kernel_types.h".
* tests/getdents.c (kernel_dirent): Remove.
Include "kernel_types.h".
(print_dirent): Print variables of kernel_ulong_t type using %Lu format.

Makefile.am
configure.ac
dirent.c
kernel_types.h [new file with mode: 0644]
syscall.c
tests/getdents.c

index 81f0b6d80016ea1b1055b355ff7859d0221fcb35..0052d0e1f4384abb7558421c01f819de0cdc6784 100644 (file)
@@ -86,6 +86,7 @@ strace_SOURCES =      \
        ipc_shm.c       \
        ipc_shmctl.c    \
        kcmp.c          \
+       kernel_types.h  \
        kexec.c         \
        keyctl.c        \
        ldt.c           \
index 29ea904f9fe4c089ff1cd7610e897137ab545127..0933733e4e09091cdd1ed6aca1ac589dfa5a2ac1 100644 (file)
@@ -343,6 +343,8 @@ AC_CHECK_TYPES([struct flock,
                struct __kernel_flock,
                struct __kernel_flock64],,, [#include <linux/fcntl.h>])
 
+AC_CHECK_TYPES([__kernel_long_t, __kernel_ulong_t],,, [#include <asm/posix_types.h>])
+
 AC_CHECK_MEMBERS([struct timex.tai],,, [#include <sys/timex.h>])
 
 AC_CHECK_HEADERS([linux/input.h], [
index cd50968d78cca779b09cbaae96962ab8f6623898..bad9bcdea1d9bbeae1828e6031e47bce10182b7b 100644 (file)
--- a/dirent.c
+++ b/dirent.c
 
 #include DEF_MPERS_TYPE(kernel_dirent)
 
-#include <dirent.h>
-
-typedef struct {
-       unsigned long   d_ino;
-       unsigned long   d_off;
-       unsigned short  d_reclen;
-       char            d_name[1];
-} kernel_dirent;
+#include "kernel_types.h"
 
 #include MPERS_DEFS
 
@@ -54,8 +47,9 @@ print_old_dirent(struct tcb *tcp, long addr)
        if (umove_or_printaddr(tcp, addr, &d))
                return;
 
-       tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
-               (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
+       tprintf("{d_ino=%Lu, d_off=%Lu, d_reclen=%u, d_name=",
+               (unsigned long long) d.d_ino,
+               (unsigned long long) d.d_off, d.d_reclen);
        if (d.d_reclen > D_NAME_LEN_MAX)
                d.d_reclen = D_NAME_LEN_MAX;
        printpathn(tcp, addr + offsetof(kernel_dirent, d_name), d.d_reclen);
@@ -128,9 +122,10 @@ SYS_FUNC(getdents)
                        if (d_name_len > D_NAME_LEN_MAX)
                                d_name_len = D_NAME_LEN_MAX;
 
-                       tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
-                               i ? ", " : "", (unsigned long) d->d_ino,
-                               (unsigned long) d->d_off, d->d_reclen);
+                       tprintf("%s{d_ino=%Lu, d_off=%Lu, d_reclen=%u"
+                               ", d_name=", i ? ", " : "",
+                               (unsigned long long) d->d_ino,
+                               (unsigned long long) d->d_off, d->d_reclen);
 
                        if (print_quoted_string(d->d_name, d_name_len,
                                                QUOTE_0_TERMINATED) > 0) {
@@ -146,7 +141,7 @@ SYS_FUNC(getdents)
                }
                dents++;
                if (d->d_reclen < sizeof(kernel_dirent)) {
-                       tprints("/* d_reclen < sizeof(kernel_dirent) */");
+                       tprints("/* d_reclen < sizeof(struct dirent) */");
                        break;
                }
                i += d->d_reclen;
diff --git a/kernel_types.h b/kernel_types.h
new file mode 100644 (file)
index 0000000..08d3326
--- /dev/null
@@ -0,0 +1,25 @@
+#if defined HAVE___KERNEL_LONG_T && defined HAVE___KERNEL_ULONG_T
+
+#include <asm/posix_types.h>
+
+typedef __kernel_long_t kernel_long_t;
+typedef __kernel_ulong_t kernel_ulong_t;
+
+#elif defined __x86_64__ && defined __ILP32__
+
+typedef long long kernel_long_t;
+typedef unsigned long long kernel_ulong_t;
+
+#else
+
+typedef long kernel_long_t;
+typedef unsigned long kernel_ulong_t;
+
+#endif
+
+typedef struct {
+       kernel_ulong_t  d_ino;
+       kernel_ulong_t  d_off;
+       unsigned short  d_reclen;
+       char            d_name[1];
+} kernel_dirent;
index bff00c918c63412cd7b953f35d8336a06f1dde69..d603c5cc1b101f1c25a0eda679494266e104d0b8 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -1156,22 +1156,7 @@ restore_cleared_syserror(struct tcb *tcp)
        tcp->u_error = saved_u_error;
 }
 
-/*
- * Cannot rely on __kernel_[u]long_t being defined,
- * it is quite a recent feature of <asm/posix_types.h>.
- */
-#ifdef __kernel_long_t
-typedef __kernel_long_t kernel_long_t;
-typedef __kernel_ulong_t kernel_ulong_t;
-#else
-# ifdef X32
-typedef long long kernel_long_t;
-typedef unsigned long long kernel_ulong_t;
-# else
-typedef long kernel_long_t;
-typedef unsigned long kernel_ulong_t;
-# endif
-#endif
+#include "kernel_types.h"
 
 /*
  * Check the syscall return value register value for whether it is
index f0aea23da10652a2fb9e582c32eb93d856443ed8..cfa69c2330b64a60c08d9f82bf7940de7f123130 100644 (file)
@@ -41,6 +41,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "kernel_types.h"
+
 static const char fname[] =
        "A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
        "A\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\nA\n"
@@ -60,13 +62,6 @@ static const char qname[] =
        "A\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\n"
        "A\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nA\\nZ";
 
-typedef struct {
-               unsigned long d_ino;
-               unsigned long d_off;
-               unsigned short d_reclen;
-               char d_name[256];
-} kernel_dirent;
-
 static char buf[8192];
 
 static const char *
@@ -88,8 +83,9 @@ print_dirent(const kernel_dirent *d)
        int d_name_len = d->d_reclen - d_name_offset - 1;
        assert(d_name_len > 0);
 
-       printf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
-              d->d_ino, d->d_off, d->d_reclen);
+       printf("{d_ino=%Lu, d_off=%Lu, d_reclen=%u, d_name=",
+              (unsigned long long) d->d_ino,
+              (unsigned long long) d->d_off, d->d_reclen);
 
        if (d->d_name[0] == '.')
                printf("\"%.*s\"", d_name_len, d->d_name);