diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2012-04-17 11:05:04 -0700 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2012-04-18 15:02:40 +0000 |
commit | 085e42886052190d3e515ca865546b527f59cdd1 (patch) | |
tree | f09fae3b106d16477db384dccf3b0e430e7dd52e | |
parent | 2bb4581ee501f6803df258ebb74c63a18a48422b (diff) | |
download | strace-085e42886052190d3e515ca865546b527f59cdd1.tar.gz |
x32: add ia32 support
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent1.h,
linux/x32/ioctlent1.h, linux/x32/signalent1.h and
linux/x32/syscallent1.h.
* configure.ac: Remove AC_GNU_SOURCE, obsoleted by
AC_USE_SYSTEM_EXTENSIONS.
* defs.h (SUPPORTED_PERSONALITIES): Set to 2 for X32.
(PERSONALITY1_WORDSIZE): Set to 4 for X32.
* file.c (stat64): New struct for X32.
(sys_lseek32): New function for X32.
(stat64): Undef.
(sys_fstat64): Likewise.
(sys_stat64): Likewise.
(realprintstat64): New function for X32.
(sys_fstat64): Likewise.
(sys_stat64): Likewise.
* mem.c (sys_old_mmap): New function for X32.
* pathtrace.c (pathtrace_match): Also check sys_old_mmap for X32.
* syscall.c (update_personality): Add X32 support.
(get_scno): Support currpers == 1 for X32.
* linux/syscall.h (sys_lseek32): New function prototype for X32.
* linux/x32/errnoent1.h: New file.
* linux/x32/ioctlent1.h: Likewise.
* linux/x32/signalent1.h: Likewise.
* linux/x32/syscallent1.h: Likewise.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | defs.h | 7 | ||||
-rw-r--r-- | file.c | 129 | ||||
-rw-r--r-- | linux/syscall.h | 4 | ||||
-rw-r--r-- | linux/x32/errnoent1.h | 2 | ||||
-rw-r--r-- | linux/x32/ioctlent1.h | 2 | ||||
-rw-r--r-- | linux/x32/signalent1.h | 2 | ||||
-rw-r--r-- | linux/x32/syscallent1.h | 11 | ||||
-rw-r--r-- | mem.c | 34 | ||||
-rw-r--r-- | pathtrace.c | 2 | ||||
-rw-r--r-- | syscall.c | 30 |
12 files changed, 216 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am index 7398b7939..e9393d8f7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -80,6 +80,8 @@ EXTRA_DIST = $(man_MANS) errnoent.sh signalent.sh syscallent.sh ioctlsort.c \ linux/tile/ioctlent.h.in linux/tile/syscallent.h \ linux/x32/errnoent.h linux/x32/ioctlent.h.in \ linux/x32/signalent.h linux/x32/syscallent.h \ + linux/x32/errnoent1.h linux/x32/ioctlent1.h \ + linux/x32/signalent1.h linux/x32/syscallent1.h \ linux/x86_64/ioctlent.h.in linux/x86_64/syscallent.h \ linux/x86_64/gentab.pl \ linux/x86_64/errnoent1.h linux/x86_64/ioctlent1.h \ diff --git a/configure.ac b/configure.ac index f55b8a204..879ad9a97 100644 --- a/configure.ac +++ b/configure.ac @@ -9,8 +9,6 @@ AM_MAINTAINER_MODE AC_CANONICAL_HOST AC_PROG_CC -AC_GNU_SOURCE - AC_USE_SYSTEM_EXTENSIONS AC_MSG_CHECKING([for supported architecture]) @@ -227,6 +227,13 @@ extern long ptrace(int, int, char *, long); # define PERSONALITY2_WORDSIZE 4 #endif +#ifdef X32 +# undef SUPPORTED_PERSONALITIES +# define SUPPORTED_PERSONALITIES 2 +# define PERSONALITY0_WORDSIZE 4 +# define PERSONALITY1_WORDSIZE 4 +#endif + #ifdef ARM # undef SUPPORTED_PERSONALITIES # define SUPPORTED_PERSONALITIES 2 @@ -96,6 +96,28 @@ struct stat { unsigned long long st_ctime_nsec; long long __unused[3]; }; + +struct stat64 { + unsigned long long st_dev; + unsigned char __pad0[4]; + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned long long st_rdev; + unsigned char __pad3[4]; + long long st_size; + unsigned long st_blksize; + unsigned long long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned int st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long long st_ino; +}; #else # undef dev_t # undef ino_t @@ -521,6 +543,28 @@ sys_lseek(struct tcb *tcp) } return RVAL_LUDECIMAL; } + +# if defined(X32) +int +sys_lseek32(struct tcb *tcp) +{ + long offset; + int _whence; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + offset = tcp->u_arg[1]; + _whence = tcp->u_arg[2]; + if (_whence == SEEK_SET) + tprintf("%lu, ", offset); + else + tprintf("%ld, ", offset); + printxval(whence, _whence, "SEEK_???"); + } + return RVAL_UDECIMAL; +} +# endif #else int sys_lseek(struct tcb *tcp) @@ -2722,3 +2766,88 @@ sys_swapon(struct tcb *tcp) } return 0; } + +#ifdef X32 +# undef stat64 +# undef sys_fstat64 +# undef sys_stat64 + +static void +realprintstat64(struct tcb *tcp, long addr) +{ + struct stat64 statbuf; + + if (!addr) { + tprints("NULL"); + return; + } + if (syserror(tcp) || !verbose(tcp)) { + tprintf("%#lx", addr); + return; + } + + if (umove(tcp, addr, &statbuf) < 0) { + tprints("{...}"); + return; + } + + if (!abbrev(tcp)) { + tprintf("{st_dev=makedev(%lu, %lu), st_ino=%llu, st_mode=%s, ", + (unsigned long) major(statbuf.st_dev), + (unsigned long) minor(statbuf.st_dev), + (unsigned long long) statbuf.st_ino, + sprintmode(statbuf.st_mode)); + tprintf("st_nlink=%lu, st_uid=%lu, st_gid=%lu, ", + (unsigned long) statbuf.st_nlink, + (unsigned long) statbuf.st_uid, + (unsigned long) statbuf.st_gid); + tprintf("st_blksize=%lu, ", + (unsigned long) statbuf.st_blksize); + tprintf("st_blocks=%lu, ", (unsigned long) statbuf.st_blocks); + } + else + tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode)); + switch (statbuf.st_mode & S_IFMT) { + case S_IFCHR: case S_IFBLK: + tprintf("st_rdev=makedev(%lu, %lu), ", + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + default: + tprintf("st_size=%llu, ", (unsigned long long) statbuf.st_size); + break; + } + if (!abbrev(tcp)) { + tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime)); + tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime)); + tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime)); + tprints("}"); + } + else + tprints("...}"); +} + +int +sys_fstat64(struct tcb *tcp) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + realprintstat64(tcp, tcp->u_arg[1]); + } + return 0; +} + +int +sys_stat64(struct tcb *tcp) +{ + if (entering(tcp)) { + printpath(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + realprintstat64(tcp, tcp->u_arg[1]); + } + return 0; +} +#endif diff --git a/linux/syscall.h b/linux/syscall.h index e56697db4..7e0155ec5 100644 --- a/linux/syscall.h +++ b/linux/syscall.h @@ -371,3 +371,7 @@ int sys_shmsys(); #define SYS_shmsys_subcall 207 #define SYS_shmsys_nsubcalls 4 #endif + +#ifdef X32 +int sys_lseek32(); +#endif diff --git a/linux/x32/errnoent1.h b/linux/x32/errnoent1.h new file mode 100644 index 000000000..a89482760 --- /dev/null +++ b/linux/x32/errnoent1.h @@ -0,0 +1,2 @@ +/* Our second set comes from the i386 files. */ +#include "../errnoent.h" diff --git a/linux/x32/ioctlent1.h b/linux/x32/ioctlent1.h new file mode 100644 index 000000000..1f92feb74 --- /dev/null +++ b/linux/x32/ioctlent1.h @@ -0,0 +1,2 @@ +/* Our second set comes from the i386 files. */ +#include "linux/ioctlent.h" diff --git a/linux/x32/signalent1.h b/linux/x32/signalent1.h new file mode 100644 index 000000000..5c18d98b4 --- /dev/null +++ b/linux/x32/signalent1.h @@ -0,0 +1,2 @@ +/* Our second set comes from the i386 files. */ +#include "../signalent.h" diff --git a/linux/x32/syscallent1.h b/linux/x32/syscallent1.h new file mode 100644 index 000000000..20c65292c --- /dev/null +++ b/linux/x32/syscallent1.h @@ -0,0 +1,11 @@ +/* Our second set comes from the i386 files. + Only a couple of calls we cannot support without the i386 headers. */ + +#define sys_oldstat printargs +#define sys_oldfstat printargs +#define sys_oldlstat printargs +#define sys_lseek sys_lseek32 +#define sys_lstat64 sys_stat64 +#define sys_truncate64 sys_truncate +#define sys_ftruncate64 sys_ftruncate +#include "i386/syscallent.h" @@ -311,6 +311,40 @@ sys_mmap(struct tcb *tcp) #endif /* !HAVE_LONG_LONG_OFF_T */ #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T +# if defined(X32) +int sys_old_mmap(struct tcb *tcp) +{ + long u_arg[6]; + if (umoven(tcp, tcp->u_arg[0], sizeof(u_arg), (char *) u_arg) == -1) + return 0; + if (entering(tcp)) { + /* addr */ + if (!u_arg[0]) + tprints("NULL, "); + else + tprintf("%#lx, ", u_arg[0]); + /* len */ + tprintf("%lu, ", u_arg[1]); + /* prot */ + printflags(mmap_prot, u_arg[2], "PROT_???"); + tprints(", "); + /* flags */ +# ifdef MAP_TYPE + printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???"); + addflags(mmap_flags, u_arg[3] & ~MAP_TYPE); +# else + printflags(mmap_flags, u_arg[3], "MAP_???"); +# endif + /* fd */ + tprints(", "); + printfd(tcp, u_arg[4]); + /* offset */ + tprintf(", %#lx", u_arg[5]); + } + return RVAL_HEX; +} +# endif + /* TODO: comment which arches use this routine. * For one, does ALPHA on Linux use this?? * From code it seems that it might use 7 or 8 registers, diff --git a/pathtrace.c b/pathtrace.c index 886932c87..c000c835f 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -224,9 +224,7 @@ pathtrace_match(struct tcb *tcp) } if ( -#if !defined X32 s->sys_func == sys_old_mmap || -#endif s->sys_func == sys_mmap) { /* x, x, x, x, fd */ return fdmatch(tcp, tcp->u_arg[4]); @@ -273,6 +273,12 @@ update_personality(struct tcb *tcp, int personality) fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n", tcp->pid, names[personality]); } +# elif defined(X32) + if (!qflag) { + static const char *const names[] = {"x32", "32 bit"}; + fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n", + tcp->pid, names[personality]); + } # endif } #endif @@ -868,15 +874,25 @@ get_scno(struct tcb *tcp) } # endif # ifdef X32 - if (currpers == 0 || currpers == 1) { - fprintf(stderr, "syscall_%lu (...) in unsupported %s " - "mode of process PID=%d\n", scno, - currpers == 0 ? "64-bit" : "32-bit", tcp->pid); - return 0; + /* Value of currpers: + * 0: 64 bit + * 1: 32 bit + * 2: X32 + * Value of current_personality: + * 0: X32 + * 1: 32 bit + */ + switch (currpers) { + case 0: + fprintf(stderr, "syscall_%lu (...) in unsupported " + "64-bit mode of process PID=%d\n", + scno, tcp->pid); + return 0; + case 2: + currpers = 0; } -# else - update_personality(tcp, currpers); # endif + update_personality(tcp, currpers); #elif defined(IA64) # define IA64_PSR_IS ((long)1 << 34) if (upeek(tcp, PT_CR_IPSR, &psr) >= 0) |