Arch-abstraction:
- Moved the system call table into x86-linux, since it's platform specific.
- Started moving the non-generic syscall wrappers into linux/syscalls.c and
x86-linux/syscalls.c as appropriate.
- Added new coregrind/linux/ directory and some files in it.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3034 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/core.h b/coregrind/core.h
index a550d94..1a6d7f1 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -86,6 +86,11 @@
#include "core_asm.h" // asm stuff
#include "tool.h" // tool stuff
#include "core_arch.h" // arch-specific stuff, eg. x86/core_arch.h
+
+// Ugly: this is needed by linux/core_os.h
+typedef struct _ThreadState ThreadState;
+
+#include "core_os.h" // OS-specific stuff, eg. linux/core_os.h
#include "core_platform.h" // platform-specific stuff,
// eg. x86-linux/core_platform.h
@@ -703,7 +708,7 @@
typedef struct ProxyLWP ProxyLWP;
-typedef
+//typedef
struct _ThreadState {
/* ThreadId == 0 (and hence vg_threads[0]) is NEVER USED.
The thread identity is simply the index in vg_threads[].
@@ -849,8 +854,8 @@
/* Architecture-specific thread state */
arch_thread_t arch;
-}
-ThreadState;
+};
+//ThreadState;
/* The thread table. */
@@ -1397,6 +1402,336 @@
extern void VG_(init_preopened_fds) ( void );
extern void VG_(show_open_fds) ( void );
+// Return true if address range entirely contained within client
+// address space.
+Bool VG_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
+ const Char *syscallname);
+
+// Flags describing syscall wrappers
+#define Special (1 << 0)
+#define MayBlock (1 << 1)
+#define NBRunInLWP (1 << 2) // non-blocking, but must run in LWP context
+#define PostOnFail (1 << 3)
+
+// For each generic ("gen") wrapper, we declare the pre-wrapper, the
+// post-wrapper (which is actually not always needed), and the associated
+// flags.
+#define GEN_SYSCALL_WRAPPER(x) \
+ extern UInt VGA_(gen_##x##_flags); \
+ extern void VGA_(gen_##x##_before)(ThreadId tid, ThreadState *tst); \
+ extern void VGA_(gen_##x##_after) (ThreadId tid, ThreadState *tst)
+
+// Generic (platform-independent) syscall wrappers. These are generally
+// POSIX or something like that; those that are not POSIX are annotated
+// with what standards they are part of, as stated in the Linux man pages.
+// Unless otherwise indicated, all those here are generic across all
+// architectures at least for Linux.
+//
+// Nb: This list may change over time... ones thought at first to be generic
+// may turn out not to be, and so be moved into OS-specific or
+// platform-specific files. If there's any doubt, I'm leaving them in here.
+//
+// Nb 2: if porting to a new OS, you should really check all these generic
+// wrappers to make sure they match your OS, painful as it might be.
+
+GEN_SYSCALL_WRAPPER(sys_ni_syscall); // * P -- unimplemented
+GEN_SYSCALL_WRAPPER(sys_exit);
+GEN_SYSCALL_WRAPPER(sys_fork);
+GEN_SYSCALL_WRAPPER(sys_read);
+GEN_SYSCALL_WRAPPER(sys_write);
+GEN_SYSCALL_WRAPPER(sys_open);
+GEN_SYSCALL_WRAPPER(sys_close);
+GEN_SYSCALL_WRAPPER(sys_waitpid);
+GEN_SYSCALL_WRAPPER(sys_creat);
+GEN_SYSCALL_WRAPPER(sys_link);
+GEN_SYSCALL_WRAPPER(sys_unlink);
+GEN_SYSCALL_WRAPPER(sys_execve); // 11 (*??) P
+GEN_SYSCALL_WRAPPER(sys_chdir);
+GEN_SYSCALL_WRAPPER(sys_time);
+GEN_SYSCALL_WRAPPER(sys_mknod);
+GEN_SYSCALL_WRAPPER(sys_chmod);
+GEN_SYSCALL_WRAPPER(sys_lseek);
+GEN_SYSCALL_WRAPPER(sys_getpid);
+GEN_SYSCALL_WRAPPER(sys_alarm);
+GEN_SYSCALL_WRAPPER(sys_pause);
+GEN_SYSCALL_WRAPPER(sys_utime);
+GEN_SYSCALL_WRAPPER(sys_access);
+GEN_SYSCALL_WRAPPER(sys_kill);
+GEN_SYSCALL_WRAPPER(sys_rename);
+GEN_SYSCALL_WRAPPER(sys_mkdir);
+GEN_SYSCALL_WRAPPER(sys_rmdir);
+GEN_SYSCALL_WRAPPER(sys_dup);
+GEN_SYSCALL_WRAPPER(sys_times);
+GEN_SYSCALL_WRAPPER(sys_fcntl); // POSIX (but complicated)
+GEN_SYSCALL_WRAPPER(sys_setpgid);
+GEN_SYSCALL_WRAPPER(sys_umask);
+GEN_SYSCALL_WRAPPER(sys_dup2);
+GEN_SYSCALL_WRAPPER(sys_getppid);
+GEN_SYSCALL_WRAPPER(sys_getpgrp);
+GEN_SYSCALL_WRAPPER(sys_setsid);
+GEN_SYSCALL_WRAPPER(sys_munmap);
+GEN_SYSCALL_WRAPPER(sys_truncate);
+GEN_SYSCALL_WRAPPER(sys_ftruncate);
+GEN_SYSCALL_WRAPPER(sys_fchmod);
+GEN_SYSCALL_WRAPPER(sys_msync);
+GEN_SYSCALL_WRAPPER(sys_readv);
+GEN_SYSCALL_WRAPPER(sys_writev);
+GEN_SYSCALL_WRAPPER(sys_getsid);
+GEN_SYSCALL_WRAPPER(sys_fdatasync);
+GEN_SYSCALL_WRAPPER(sys_mlock);
+GEN_SYSCALL_WRAPPER(sys_munlock);
+GEN_SYSCALL_WRAPPER(sys_mlockall);
+GEN_SYSCALL_WRAPPER(sys_munlockall);
+GEN_SYSCALL_WRAPPER(sys_sched_setparam);
+GEN_SYSCALL_WRAPPER(sys_sched_getparam);
+GEN_SYSCALL_WRAPPER(sys_sched_setscheduler);
+GEN_SYSCALL_WRAPPER(sys_sched_getscheduler);
+GEN_SYSCALL_WRAPPER(sys_sched_yield);
+GEN_SYSCALL_WRAPPER(sys_sched_get_priority_max);
+GEN_SYSCALL_WRAPPER(sys_sched_get_priority_min);
+GEN_SYSCALL_WRAPPER(sys_nanosleep);
+GEN_SYSCALL_WRAPPER(sys_mremap); // POSIX, but Linux arg order may be odd
+GEN_SYSCALL_WRAPPER(sys_getuid);
+GEN_SYSCALL_WRAPPER(sys_getgid);
+GEN_SYSCALL_WRAPPER(sys_geteuid);
+GEN_SYSCALL_WRAPPER(sys_getegid);
+GEN_SYSCALL_WRAPPER(sys_fsync);
+GEN_SYSCALL_WRAPPER(sys_wait4);
+GEN_SYSCALL_WRAPPER(sys_mprotect);
+GEN_SYSCALL_WRAPPER(sys_sigprocmask);
+GEN_SYSCALL_WRAPPER(sys_timer_create); // Linux: varies across archs?
+GEN_SYSCALL_WRAPPER(sys_timer_settime);
+GEN_SYSCALL_WRAPPER(sys_timer_gettime);
+GEN_SYSCALL_WRAPPER(sys_timer_getoverrun);
+GEN_SYSCALL_WRAPPER(sys_timer_delete);
+GEN_SYSCALL_WRAPPER(sys_clock_settime);
+GEN_SYSCALL_WRAPPER(sys_clock_gettime);
+GEN_SYSCALL_WRAPPER(sys_clock_getres);
+GEN_SYSCALL_WRAPPER(sys_getcwd);
+
+// These ones aren't POSIX, but are in some standard and look reasonably
+// generic, and are the same for all architectures under Linux.
+GEN_SYSCALL_WRAPPER(sys_nice); // SVr4, SVID EXT, AT&T, X/OPEN, BSD 4.3
+GEN_SYSCALL_WRAPPER(sys_sync); // SVr4, SVID, X/OPEN, BSD 4.3
+GEN_SYSCALL_WRAPPER(sys_brk); // 4.3BSD
+GEN_SYSCALL_WRAPPER(sys_acct); // SVR4, non-POSIX
+GEN_SYSCALL_WRAPPER(sys_chroot); // SVr4, SVID, 4.4BSD, X/OPEN
+
+
+// These ones may be Linux specific... not sure. They use 16-bit gid_t and
+// uid_t types. The similarly named (minus the "16" suffix) ones below use
+// 32-bit versions of these types.
+GEN_SYSCALL_WRAPPER(sys_setuid16); // ## P
+GEN_SYSCALL_WRAPPER(sys_getuid16); // ## P
+GEN_SYSCALL_WRAPPER(sys_setgid16); // ## SVr4,SVID
+GEN_SYSCALL_WRAPPER(sys_getgid16); // ## P
+GEN_SYSCALL_WRAPPER(sys_geteuid16); // ## P
+GEN_SYSCALL_WRAPPER(sys_getegid16); // ## P
+GEN_SYSCALL_WRAPPER(sys_setreuid16); // ## BSD4.3
+GEN_SYSCALL_WRAPPER(sys_setregid16); // ## BSD4.3
+GEN_SYSCALL_WRAPPER(sys_getgroups16); // ## P
+GEN_SYSCALL_WRAPPER(sys_setgroups16); // ## SVr4, SVID, X/OPEN, 4.3BSD
+GEN_SYSCALL_WRAPPER(sys_fchown16); // ## SVr4,BSD4.3
+GEN_SYSCALL_WRAPPER(sys_chown16); // ## P
+
+GEN_SYSCALL_WRAPPER(sys_setresuid16); // ## (non-standard)
+GEN_SYSCALL_WRAPPER(sys_getresuid16); // ## L
+GEN_SYSCALL_WRAPPER(sys_setresgid16); // ## (non-standard)
+GEN_SYSCALL_WRAPPER(sys_getresgid16); // ## L
+GEN_SYSCALL_WRAPPER(sys_setresuid); // * (non-standard)
+GEN_SYSCALL_WRAPPER(sys_getresuid); // * L
+GEN_SYSCALL_WRAPPER(sys_setresgid); // * (non-standard)
+GEN_SYSCALL_WRAPPER(sys_getresgid); // * L
+
+GEN_SYSCALL_WRAPPER(sys_ptrace); // (x86?) (almost-P)
+
+
+// Some archs on Linux do not match the generic wrapper for sys_pipe().
+GEN_SYSCALL_WRAPPER(sys_pipe);
+
+GEN_SYSCALL_WRAPPER(sys_ioctl); // */x86 (various)
+
+
+// May not be generic for every architecture under Linux.
+GEN_SYSCALL_WRAPPER(sys_sigaction); // (x86) P
+
+GEN_SYSCALL_WRAPPER(sys_sigsuspend); // POSIX, but LLL (proto varies across archs)
+GEN_SYSCALL_WRAPPER(sys_sigpending);
+GEN_SYSCALL_WRAPPER(sys_setrlimit); // SVr4, 4.3BSD
+
+GEN_SYSCALL_WRAPPER(sys_old_getrlimit); // SVr4, 4.3BSD LLL?
+
+GEN_SYSCALL_WRAPPER(sys_getrusage); // SVr4, 4.3BSD
+GEN_SYSCALL_WRAPPER(sys_gettimeofday);
+GEN_SYSCALL_WRAPPER(sys_settimeofday); // SVr4, 4.3BSD (non-POSIX)
+
+GEN_SYSCALL_WRAPPER(old_select); // (x86) (4.4BSD) LLL
+
+GEN_SYSCALL_WRAPPER(sys_symlink);
+GEN_SYSCALL_WRAPPER(sys_readlink); // * (X/OPEN,4.4BSD)
+GEN_SYSCALL_WRAPPER(old_mmap); // (x86) (P but not...)
+GEN_SYSCALL_WRAPPER(sys_getpriority); // SVr4,4.4BSD
+GEN_SYSCALL_WRAPPER(sys_setpriority); // SVr4,4.4BSD
+GEN_SYSCALL_WRAPPER(sys_statfs); // * L?
+GEN_SYSCALL_WRAPPER(sys_fstatfs); // * L?
+
+// Linux's funny many-in-one socketcall is certainly not generic, but I
+// didn't want to move it until necessary because it's big and has a lot of
+// associated junk.
+GEN_SYSCALL_WRAPPER(sys_socketcall);
+
+GEN_SYSCALL_WRAPPER(sys_setitimer); // * (SVr4,4.4BSD)
+GEN_SYSCALL_WRAPPER(sys_getitimer); // * (SVr4,4.4BSD)
+
+// XXX: funny names...
+GEN_SYSCALL_WRAPPER(sys_newstat); // * P
+GEN_SYSCALL_WRAPPER(sys_newlstat); // *
+GEN_SYSCALL_WRAPPER(sys_newfstat); // * P (SVr4,BSD4.3)
+
+GEN_SYSCALL_WRAPPER(sys_iopl); // (x86/amd64) L
+GEN_SYSCALL_WRAPPER(sys_ipc); // (x86) L
+GEN_SYSCALL_WRAPPER(sys_clone); // (x86/Linux) TTT
+GEN_SYSCALL_WRAPPER(sys_newuname); // * P
+GEN_SYSCALL_WRAPPER(sys_init_module); // * L?
+GEN_SYSCALL_WRAPPER(sys_quotactl); // * (?)
+GEN_SYSCALL_WRAPPER(sys_getpgid);
+GEN_SYSCALL_WRAPPER(sys_fchdir); // * (almost-P)
+GEN_SYSCALL_WRAPPER(sys_getdents); // * (SVr4,SVID)
+GEN_SYSCALL_WRAPPER(sys_select); // * (4.4BSD...)
+GEN_SYSCALL_WRAPPER(sys_flock); // * (4.4BSD...)
+GEN_SYSCALL_WRAPPER(sys_poll); // * (XPG4-UNIX)
+GEN_SYSCALL_WRAPPER(sys_rt_sigaction); // (x86) ()
+GEN_SYSCALL_WRAPPER(sys_rt_sigprocmask); // * ?
+GEN_SYSCALL_WRAPPER(sys_rt_sigpending); // * ?
+GEN_SYSCALL_WRAPPER(sys_rt_sigtimedwait); // * ?
+GEN_SYSCALL_WRAPPER(sys_rt_sigqueueinfo); // * ?
+GEN_SYSCALL_WRAPPER(sys_rt_sigsuspend); // () ()
+GEN_SYSCALL_WRAPPER(sys_pread64); // * (Unix98?)
+GEN_SYSCALL_WRAPPER(sys_pwrite64); // * (Unix98?)
+GEN_SYSCALL_WRAPPER(sys_capget); // * L?
+GEN_SYSCALL_WRAPPER(sys_capset); // * L?
+GEN_SYSCALL_WRAPPER(sys_sigaltstack); // (x86) (XPG4-UNIX)
+GEN_SYSCALL_WRAPPER(sys_sendfile); // * L
+GEN_SYSCALL_WRAPPER(sys_getpmsg); // (?) (?)
+GEN_SYSCALL_WRAPPER(sys_putpmsg); // (?) (?)
+GEN_SYSCALL_WRAPPER(sys_getrlimit); // * (?)
+GEN_SYSCALL_WRAPPER(sys_mmap2); // (x86?) P?
+GEN_SYSCALL_WRAPPER(sys_truncate64); // %% (P?)
+GEN_SYSCALL_WRAPPER(sys_ftruncate64); // %% (P?)
+GEN_SYSCALL_WRAPPER(sys_stat64); // %% (?)
+GEN_SYSCALL_WRAPPER(sys_lstat64); // %% (?)
+GEN_SYSCALL_WRAPPER(sys_fstat64); // %% (?)
+GEN_SYSCALL_WRAPPER(sys_lchown); // * (L?)
+GEN_SYSCALL_WRAPPER(sys_setreuid); // * (BSD4.3)
+GEN_SYSCALL_WRAPPER(sys_setregid); // * (BSD4.3)
+GEN_SYSCALL_WRAPPER(sys_getgroups); // * P
+GEN_SYSCALL_WRAPPER(sys_setgroups); // * almost-P
+GEN_SYSCALL_WRAPPER(sys_fchown); // * (SVr4,BSD4.3)
+GEN_SYSCALL_WRAPPER(sys_chown); // * P
+GEN_SYSCALL_WRAPPER(sys_setuid); // *
+GEN_SYSCALL_WRAPPER(sys_setgid); // * (SVr4,SVID)
+GEN_SYSCALL_WRAPPER(sys_mincore); // * non-P?
+GEN_SYSCALL_WRAPPER(sys_madvise); // * P
+GEN_SYSCALL_WRAPPER(sys_getdents64); // * (SVr4,SVID?)
+GEN_SYSCALL_WRAPPER(sys_fcntl64); // * P?
+GEN_SYSCALL_WRAPPER(sys_setxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_lsetxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_fsetxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_getxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_lgetxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_fgetxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_listxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_llistxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_flistxattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_removexattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_lremovexattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_fremovexattr); // * L?
+GEN_SYSCALL_WRAPPER(sys_sendfile64); // * L
+GEN_SYSCALL_WRAPPER(sys_futex); // * L
+GEN_SYSCALL_WRAPPER(sys_sched_setaffinity); // * L?
+GEN_SYSCALL_WRAPPER(sys_sched_getaffinity); // * L?
+GEN_SYSCALL_WRAPPER(sys_exit_group); // *
+GEN_SYSCALL_WRAPPER(sys_lookup_dcookie); // (*/32/64) L
+GEN_SYSCALL_WRAPPER(sys_epoll_create); // * L
+GEN_SYSCALL_WRAPPER(sys_epoll_ctl); // * L
+GEN_SYSCALL_WRAPPER(sys_epoll_wait); // * L
+GEN_SYSCALL_WRAPPER(sys_set_tid_address); // * ?
+GEN_SYSCALL_WRAPPER(sys_statfs64); // * (?)
+GEN_SYSCALL_WRAPPER(sys_fstatfs64); // * (?)
+GEN_SYSCALL_WRAPPER(sys_utimes); // * (4.3BSD)
+GEN_SYSCALL_WRAPPER(sys_mq_open); // * P?
+GEN_SYSCALL_WRAPPER(sys_mq_unlink); // * P?
+GEN_SYSCALL_WRAPPER(sys_mq_timedsend); // * P?
+GEN_SYSCALL_WRAPPER(sys_mq_timedreceive); // * P?
+GEN_SYSCALL_WRAPPER(sys_mq_notify); // * P?
+GEN_SYSCALL_WRAPPER(sys_mq_getsetattr); // * P?
+
+#undef GEN_SYSCALL_WRAPPER
+
+// Macros used in syscall wrappers
+
+#define PRRSN \
+ SK_(pre_reg_read)(Vg_CoreSysCall, tid, "(syscallno)", \
+ R_SYSCALL_NUM, sizeof(UWord));
+#define PRRAn(n,s,t,a) \
+ SK_(pre_reg_read)(Vg_CoreSysCall, tid, s"("#a")", \
+ R_SYSCALL_ARG##n, sizeof(t));
+#define PRE_REG_READ0(tr, s) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ }
+#define PRE_REG_READ1(tr, s, t1, a1) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); \
+ }
+#define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); \
+ }
+#define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
+ }
+#define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
+ PRRAn(4,s,t4,a4); \
+ }
+#define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
+ PRRAn(4,s,t4,a4); PRRAn(5,s,t5,a5); \
+ }
+#define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
+ if (VG_(defined_pre_reg_read)()) { \
+ PRRSN; \
+ PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
+ PRRAn(4,s,t4,a4); PRRAn(5,s,t5,a5); PRRAn(6,s,t6,a6); \
+ }
+
+#define PRE_MEM_READ(zzname, zzaddr, zzlen) \
+ VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
+
+#define PRE_MEM_RASCIIZ(zzname, zzaddr) \
+ VG_TRACK( pre_mem_read_asciiz, Vg_CoreSysCall, tid, zzname, zzaddr)
+
+#define PRE_MEM_WRITE(zzname, zzaddr, zzlen) \
+ VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
+
+#define POST_MEM_WRITE(zzaddr, zzlen) \
+ VG_TRACK( post_mem_write, zzaddr, zzlen)
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end vg_syscalls.c ---*/
+/*--------------------------------------------------------------------*/
+
/* ---------------------------------------------------------------------
Exports of vg_transtab.c
------------------------------------------------------------------ */
@@ -1558,8 +1893,29 @@
// Platform-specific things defined in eg. x86/*.c
// ---------------------------------------------------------------------
+struct SyscallTableEntry {
+ UInt *flags_ptr;
+ void (*before)(ThreadId tid, ThreadState *tst);
+ void (*after) (ThreadId tid, ThreadState *tst);
+};
+
+/* This table is the mapping from __NR_xxx syscall numbers to the PRE/POST
+ wrappers for the relevant syscalls used in the OS kernel for that number.
+ Note that the constant names don't always match the wrapper names in a
+ straightforward way. For example, on x86/Linux:
+
+ __NR_lchown --> sys_lchown16()
+ __NR_lchown32 --> sys_lchown()
+ __NR_select --> old_select()
+ __NR__newselect --> sys_select()
+*/
+extern const struct SyscallTableEntry VGA_(syscall_table)[];
+
+extern const UInt VGA_(syscall_table_size);
+
+
extern const Addr vga_sys_before, vga_sys_restarted,
- vga_sys_after, vga_sys_done;
+ vga_sys_after, vga_sys_done;
extern void VGA_(restart_syscall)(arch_thread_t* arch);