[patch] Add stat() support for biarch i386 on x86_64

Jan Kratochvil jan.kratochvil at redhat.com
Sun Aug 5 22:04:01 UTC 2007


Hi,

currently the stat64() syscall is not printed for i386 tracees on x86_64.

While I would expect it should affect even i386-on-ia64 it works there for me
without any patch.

/*
 * Linux x86_64 has unified `struct stat' but its i386 biarch needs
 * `struct stat64'.  Its <asm-i386/stat.h> definition expects 32-bit `long'.
 * <linux/include/asm-x86_64/ia32.h> is not in the public includes set.
...

Testcase:
	echo -e '#include <sys/stat.h>\nint main (void) { struct stat statbuf; stat ("/proc/self/exe", &statbuf); return 0; }' >/tmp/statself.c;gcc -m32 -o /tmp/statself32 /tmp/statself.c -ggdb2 -Wall;strace -v /tmp/statself32 2>&1|tail|grep ^stat
reports
	stat64(0x80484f0, 0xffb990b8)           = 0
while it should report
	stat64("/proc/self/exe", {st_dev=makedev(8, 1), st_ino=4910638, st_mode=S_IFREG|0755, st_nlink=1, st_uid=502, st_gid=502, st_blksize=4096, st_blocks=16, st_size=6825, st_atime=2007/08/05-23:56:21, st_mtime=2007/08/05-23:56:21, st_ctime=2007/08/05-23:56:21}) = 0


Regards,
Jan
-------------- next part --------------
2007-08-05  Jan Kratochvil  <jan.kratochvil at redhat.com>

	* file.c: New #include <assert.h>.
	(HAVE_STAT64, stat64) [LINUX && X86_64 && __GNUC__]: New definitions.
	(printstat64) [HAVE_STAT64]: Assert the I386 `struct stat64' size.
	(printstat64) [!HAVE_LONG_LONG]: Support the ST_SIZE printing.
	Fixes RH#222275.

--- file.c	24 Jul 2007 01:57:11 -0000	1.84
+++ file.c	5 Aug 2007 21:41:33 -0000
@@ -34,6 +34,7 @@
 #include "defs.h"
 
 #include <dirent.h>
+#include <assert.h>
 #ifdef LINUX
 #define dirent kernel_dirent
 #define dirent64 kernel_dirent64
@@ -193,6 +194,47 @@ struct stat_sparc64 {
 #define sys_ftruncate64	sys_ftruncate
 #endif
 
+/*
+ * Linux x86_64 has unified `struct stat' but its i386 biarch needs
+ * `struct stat64'.  Its <asm-i386/stat.h> definition expects 32-bit `long'.
+ * <linux/include/asm-x86_64/ia32.h> is not in the public includes set.
+ * __GNUC__ is needed for the required __attribute__ below.
+ */
+#if defined LINUX && defined X86_64 && defined __GNUC__
+#define HAVE_STAT64 1	/* Ugly hack */
+struct stat64 {
+	unsigned long	st_dev;
+	unsigned char	__pad0[4];
+
+	unsigned int	__st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+
+	unsigned long	st_rdev;
+	unsigned char	__pad3[4];
+
+	long 		st_size;
+	unsigned int	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+
+	unsigned int	st_atime;
+	unsigned int	st_atime_nsec;
+
+	unsigned int	st_mtime;
+	unsigned int	st_mtime_nsec;
+
+	unsigned int	st_ctime;
+	unsigned int	st_ctime_nsec;
+
+	unsigned long	st_ino;
+} __attribute__((__packed__));
+#endif
+
 #ifdef MAJOR_IN_SYSMACROS
 #include <sys/sysmacros.h>
 #endif
@@ -990,6 +1032,10 @@ struct tcb *tcp;
 long addr;
 {
 	struct stat64 statbuf;
+ 
+#if defined LINUX && (defined X86_64 || defined I386)
+	assert (sizeof (statbuf) == 96);
+#endif
 
 #ifdef LINUXSPARC
  	if (current_personality == 1) {
@@ -1058,7 +1104,11 @@ long addr;
 #endif /* !HAVE_STRUCT_STAT_ST_RDEV */
 		break;
 	default:
-		tprintf("st_size=%llu, ", statbuf.st_size);
+#ifdef HAVE_LONG_LONG
+		tprintf("st_size=%llu, ", (unsigned long long) statbuf.st_size);
+#else
+		tprintf("st_size=%lu, ", (unsigned long) statbuf.st_size);
+#endif
 		break;
 	}
 	if (!abbrev(tcp)) {


More information about the Strace-devel mailing list