From: Dmitry V. Levin Date: Fri, 27 Nov 2015 01:51:22 +0000 (+0000) Subject: x32: fix struct dirent decoding X-Git-Tag: v4.11~94 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bdb07e38ddb0fe630fde681549e74497adc1cd41;p=strace x32: fix struct dirent decoding * 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 . * dirent.c: Stop including . (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. --- diff --git a/Makefile.am b/Makefile.am index 81f0b6d8..0052d0e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -86,6 +86,7 @@ strace_SOURCES = \ ipc_shm.c \ ipc_shmctl.c \ kcmp.c \ + kernel_types.h \ kexec.c \ keyctl.c \ ldt.c \ diff --git a/configure.ac b/configure.ac index 29ea904f..0933733e 100644 --- a/configure.ac +++ b/configure.ac @@ -343,6 +343,8 @@ AC_CHECK_TYPES([struct flock, struct __kernel_flock, struct __kernel_flock64],,, [#include ]) +AC_CHECK_TYPES([__kernel_long_t, __kernel_ulong_t],,, [#include ]) + AC_CHECK_MEMBERS([struct timex.tai],,, [#include ]) AC_CHECK_HEADERS([linux/input.h], [ diff --git a/dirent.c b/dirent.c index cd50968d..bad9bcde 100644 --- a/dirent.c +++ b/dirent.c @@ -33,14 +33,7 @@ #include DEF_MPERS_TYPE(kernel_dirent) -#include - -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 index 00000000..08d33264 --- /dev/null +++ b/kernel_types.h @@ -0,0 +1,25 @@ +#if defined HAVE___KERNEL_LONG_T && defined HAVE___KERNEL_ULONG_T + +#include + +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; diff --git a/syscall.c b/syscall.c index bff00c91..d603c5cc 100644 --- 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 . - */ -#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 diff --git a/tests/getdents.c b/tests/getdents.c index f0aea23d..cfa69c23 100644 --- a/tests/getdents.c +++ b/tests/getdents.c @@ -41,6 +41,8 @@ #include #include +#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);