Arch-abstraction:

- Started overhauling the syscalls to account for different architectures;
  in particular, accounts for the fact that the __NR_foo syscall number
  often doesn't directly match with the sys_foo() function that implements the
  function in the Linux kernel.  So started introducing this indirection as
  needed.  Currently, only read() and write() have been done;  the transition
  will be staged, since doing all syscalls in one hit is a total pain.

  This will also pave the way for scalar syscall arg checking with Memcheck,
  now that it is clear what the prototypes of the relevant syscalls are.

- Removed support for 2.2 kernels in the configure test, after discussion with
  Julian.  If it causes major problems, we can consider reverting.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2948
This commit is contained in:
Nicholas Nethercote 2004-11-08 17:51:39 +00:00
parent 6c2d25aae6
commit d67d99a446
2 changed files with 57 additions and 15 deletions

View File

@ -123,14 +123,9 @@ case "${host_os}" in
AC_DEFINE([KERNEL_2_4], 1, [Define to 1 if you're using Linux 2.4.x])
;;
2.2.*)
AC_MSG_RESULT([2.2 family (${kernel})])
AC_DEFINE([KERNEL_2_2], 1, [Define to 1 if you're using Linux 2.2.x])
;;
*)
AC_MSG_RESULT([unsupported (${kernel})])
AC_MSG_ERROR([Valgrind works on kernels 2.2, 2.4, 2.6])
AC_MSG_ERROR([Valgrind works on kernels 2.4, 2.6])
;;
esac

View File

@ -32,7 +32,7 @@
/* All system calls are channelled through here, doing two things:
* notify the tool of the memory events (reads, writes) happening
* notify the tool of the events (mem/reg reads, writes) happening
* perform the syscall, usually by passing it along to the kernel
unmodified.
@ -42,6 +42,8 @@
having the simulator retain control.
*/
#define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) /*nothing, so far*/
#define PRE_MEM_READ(zzname, zzaddr, zzlen) \
VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
@ -991,9 +993,18 @@ static Bool fd_allowed(Int fd, const Char *syscallname, ThreadId tid, Bool soft)
/* ---------------------------------------------------------------------
The Main Entertainment ...
The Main Entertainment ... syscall wrappers
------------------------------------------------------------------ */
/* Note: the PRE() and POST() wrappers are for the actual functions
implementing the system calls in the Linux kernel. These mostly have
names like sys_write(); a few have names like old_mmap(). See the
comment for sys_info[] and related arrays for important info about the
__NR_foo constants and their relationship to the sys_foo() functions.
XXX: some of these are arch-specific, and should be factored out.
*/
#define MayBlock (1 << 0)
#define PostOnFail (1 << 1)
@ -4084,10 +4095,11 @@ POST(open)
}
}
PRE(read)
PRE(sys_read)
{
/* size_t read(int fd, void *buf, size_t count); */
PRINT("read ( %d, %p, %llu )", arg1, arg2, (ULong)arg3);
PRE_REG_READ3(ssize_t, sys_read,
unsigned int, fd, char __user *, buf, size_t, count);
if (!fd_allowed(arg1, "read", tid, False))
set_result( -VKI_EBADF );
@ -4095,15 +4107,16 @@ PRE(read)
PRE_MEM_WRITE( "read(buf)", arg2, arg3 );
}
POST(read)
POST(sys_read)
{
POST_MEM_WRITE( arg2, res );
}
PRE(write)
PRE(sys_write)
{
/* size_t write(int fd, const void *buf, size_t count); */
PRINT("write ( %d, %p, %llu )", arg1, arg2, (ULong)arg3);
PRE_REG_READ3(ssize_t, sys_write,
unsigned int, fd, const char __user *, buf, size_t, count);
if (!fd_allowed(arg1, "write", tid, False))
set_result( -VKI_EBADF );
else
@ -5625,6 +5638,30 @@ POST(clock_getres)
POST_MEM_WRITE( arg2, sizeof(struct vki_timespec) );
}
/* ---------------------------------------------------------------------
Summary info about syscalls
------------------------------------------------------------------ */
/* Important point: for each arch/Linux platform, the name of the constant
for a syscall (eg. __NR_write) usually matches the name of the function
in the Linux kernel that implements it (eg. sys_write()). However, this
is not always the case. For example:
__NR_lchown --> sys_lchown16()
__NR_lchown32 --> sys_lchown()
__NR_select --> old_select()
__NR__newselect --> sys_select()
Therefore part of the role of the arrays below is to provide a mapping
from the __NR_foo constants to the sys_foo() PRE/POST wrappers above.
XXX: doing this in stages, so we're in transition between the old
SYSB_/SYSBA macros to the new SYSX_/SYS_XY macros.
XXX: some of these are arch-specific, and should be factored out.
*/
struct sys_info {
UInt flags;
void (*before)(ThreadId tid, ThreadState *tst);
@ -5633,6 +5670,9 @@ struct sys_info {
#define SYSB_(name, flags) [__NR_##name] = { flags, before_##name, NULL }
#define SYSBA(name, flags) [__NR_##name] = { flags, before_##name, after_##name }
#define SYSX_(const, name, flags) [const] = { flags, before_##name, NULL }
#define SYSXY(const, name, flags) [const] = { flags, before_##name, after_##name }
static void bad_before(ThreadId tid, ThreadState *tst)
{
VG_(message)
@ -5818,8 +5858,10 @@ static const struct sys_info sys_info[] = {
SYSBA(nanosleep, MayBlock|PostOnFail),
SYSB_(_newselect, MayBlock),
SYSBA(open, MayBlock),
SYSBA(read, MayBlock),
SYSB_(write, MayBlock),
// SYSBA(read, MayBlock),
// SYSB_(write, MayBlock),
SYSXY(__NR_read, sys_read, MayBlock),
SYSX_(__NR_write, sys_write, MayBlock),
SYSBA(creat, MayBlock),
SYSBA(pipe, 0),
SYSBA(poll, MayBlock),
@ -5923,6 +5965,11 @@ static const struct sys_info sys_info[] = {
#undef SYSB_
#undef SYSBA
/* ---------------------------------------------------------------------
Executing the syscalls
------------------------------------------------------------------ */
Bool VG_(pre_syscall) ( ThreadId tid )
{
ThreadState* tst;