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.
This commit is contained in:
H.J. Lu 2012-04-17 11:05:04 -07:00 committed by Dmitry V. Levin
parent 2bb4581ee5
commit 085e428860
12 changed files with 216 additions and 11 deletions

View File

@ -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 \

View File

@ -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])

7
defs.h
View File

@ -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

129
file.c
View File

@ -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

View File

@ -371,3 +371,7 @@ int sys_shmsys();
#define SYS_shmsys_subcall 207
#define SYS_shmsys_nsubcalls 4
#endif
#ifdef X32
int sys_lseek32();
#endif

2
linux/x32/errnoent1.h Normal file
View File

@ -0,0 +1,2 @@
/* Our second set comes from the i386 files. */
#include "../errnoent.h"

2
linux/x32/ioctlent1.h Normal file
View File

@ -0,0 +1,2 @@
/* Our second set comes from the i386 files. */
#include "linux/ioctlent.h"

2
linux/x32/signalent1.h Normal file
View File

@ -0,0 +1,2 @@
/* Our second set comes from the i386 files. */
#include "../signalent.h"

11
linux/x32/syscallent1.h Normal file
View File

@ -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"

34
mem.c
View File

@ -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,

View File

@ -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]);

View File

@ -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)