diff options
30 files changed, 5578 insertions, 4550 deletions
diff --git a/coregrind/core.h b/coregrind/core.h index a371342df..6b668209f 100644 --- a/coregrind/core.h +++ b/coregrind/core.h @@ -105,7 +105,7 @@ extern Int VG_(poll)( struct vki_pollfd *, UInt nfds, Int timeout); /* system/mman.h */ extern void* VG_(mmap) ( void* start, SizeT length, UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset ); -extern void* VG_(mmap_native)( void* start, SizeT length, UInt prot, UInt flags, +extern SysRes VG_(mmap_native)( void* start, SizeT length, UInt prot, UInt flags, UInt fd, OffT offset ); extern Int VG_(munmap) ( void* start, SizeT length ); extern Int VG_(mprotect) ( void *start, SizeT length, UInt prot ); @@ -120,6 +120,16 @@ extern void VG_(env_remove_valgrind_env_stuff) ( Char** env ); extern void VG_(nanosleep)(struct vki_timespec *); +/* Simple Valgrind-internal atfork mechanism */ +/* Internal atfork handlers */ +typedef void (*vg_atfork_t)(ThreadId); +extern void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, + vg_atfork_t child); +extern void VG_(do_atfork_pre) (ThreadId tid); +extern void VG_(do_atfork_parent)(ThreadId tid); +extern void VG_(do_atfork_child) (ThreadId tid); + + /* --------------------------------------------------------------------- Exports of vg_syscall.S ------------------------------------------------------------------ */ @@ -129,16 +139,6 @@ extern void VG_(nanosleep)(struct vki_timespec *); // cause problems when passing 32-bit integers on 64-bit platforms, because // the top 32-bits might not be zeroed appropriately, eg. as would happen // with the 6th arg on AMD64 which is passed on the stack. -extern Word VG_(do_syscall) ( UInt, UWord, UWord, UWord, UWord, UWord, UWord ); - -// Macros make life easier. -#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0) -#define vgPlain_do_syscall1(s,a) VG_(do_syscall)((s),(a),0,0,0,0,0) -#define vgPlain_do_syscall2(s,a,b) VG_(do_syscall)((s),(a),(b),0,0,0,0) -#define vgPlain_do_syscall3(s,a,b,c) VG_(do_syscall)((s),(a),(b),(c),0,0,0) -#define vgPlain_do_syscall4(s,a,b,c,d) VG_(do_syscall)((s),(a),(b),(c),(d),0,0) -#define vgPlain_do_syscall5(s,a,b,c,d,e) VG_(do_syscall)((s),(a),(b),(c),(d),(e),0) -#define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),(c),(d),(e),(f)) extern void VG_(sigreturn)(void); diff --git a/coregrind/linux/core_os.c b/coregrind/linux/core_os.c index dc1241033..18bf8c2bb 100644 --- a/coregrind/linux/core_os.c +++ b/coregrind/linux/core_os.c @@ -29,6 +29,7 @@ */ #include "core.h" +#include "pub_core_libcbase.h" #include "pub_core_debuglog.h" #include "pub_core_libcassert.h" #include "pub_core_libcprint.h" @@ -140,6 +141,7 @@ void VGA_(reap_threads)(ThreadId self) while (!i_am_the_only_thread()) { /* Let other thread(s) run */ VG_(vg_yield)(); + VG_(poll_signals)(self); } vg_assert(i_am_the_only_thread()); } diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c index 4eb20e242..343a4cb91 100644 --- a/coregrind/m_aspacemgr/aspacemgr.c +++ b/coregrind/m_aspacemgr/aspacemgr.c @@ -590,7 +590,7 @@ void VG_(unmap_range)(Addr addr, SizeT len) len = VG_PGROUNDUP(len); if (debug) - VG_(printf)("unmap_range(%p, %lu)\n", addr, len); + VG_(printf)("unmap_range(%p, %llu)\n", addr, (ULong)len); if (0) show_segments("unmap_range(BEFORE)"); end = addr+len; @@ -698,6 +698,8 @@ VG_(map_file_segment)( Addr addr, SizeT len, static const Bool debug = False || mem_debug; Segment* s; Int idx; + HChar* stage2_suffix = "lib/valgrind/stage2"; + Bool is_stage2 = VG_(strstr)(filename, stage2_suffix) != NULL; if (debug) VG_(printf)( @@ -707,6 +709,8 @@ VG_(map_file_segment)( Addr addr, SizeT len, " filename='%s')\n", addr, (ULong)len, prot, flags, dev, ino, off, filename); + if (0) show_segments("before map_file_segment"); + /* Everything must be page-aligned */ vg_assert(VG_IS_PAGE_ALIGNED(addr)); len = VG_PGROUNDUP(len); @@ -741,7 +745,9 @@ VG_(map_file_segment)( Addr addr, SizeT len, file, then try reading symbols from it. */ if (s->seginfo == NULL - && (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last)) + && ( (addr+len < VG_(valgrind_base) || addr > VG_(valgrind_last)) + || is_stage2 + ) && (flags & (SF_MMAP|SF_NOSYMS)) == SF_MMAP) { if (off == 0 && s->fnIdx != -1 @@ -855,8 +861,8 @@ Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client) if (debug) { VG_(printf)("\n\n"); - VG_(printf)("find_map_space(%p, %lu, %d) ...\n", - addr, len, for_client); + VG_(printf)("find_map_space(%p, %llu, %d) ...\n", + addr, (ULong)len, for_client); } if (0) show_segments("find_map_space: start"); @@ -957,8 +963,8 @@ Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client) ret = 0; /* not found */ if (debug) - VG_(printf)("find_map_space(%p, %lu, %d) -> %p\n\n", - addr, len, for_client, ret); + VG_(printf)("find_map_space(%p, %llu, %d) -> %p\n\n", + addr, (ULong)len, for_client, ret); if (fixed) { vg_assert(ret == 0 || ret == addrOrig); @@ -982,7 +988,7 @@ Addr VG_(find_map_space)(Addr addr, SizeT len, Bool for_client) void VG_(pad_address_space)(Addr start) { Addr addr = (start == 0) ? VG_(client_base) : start; - void* ret; + SysRes ret; Int i = 0; Segment* s = i >= segments_used ? NULL : &segments[i]; @@ -1010,7 +1016,7 @@ void VG_(pad_address_space)(Addr start) void VG_(unpad_address_space)(Addr start) { Addr addr = (start == 0) ? VG_(client_base) : start; - Int ret; + SysRes ret; Int i = 0; Segment* s = i >= segments_used ? NULL : &segments[i]; @@ -1539,11 +1545,11 @@ Bool VGA_(setup_pointercheck)(Addr client_base, Addr client_end) 0, // ! seg not present 1, // useable }; - int ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt)); - if (ret < 0) { + SysRes ret = VG_(do_syscall3)(__NR_modify_ldt, 1, (UWord)&ldt, sizeof(ldt)); + if (ret.isError) { VG_(message)(Vg_UserMsg, "Warning: ignoring --pointercheck=yes, " - "because modify_ldt failed (errno=%d)", -ret); + "because modify_ldt failed (errno=%d)", ret.val); return False; } else { return True; diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c index 1ab10d37d..2ed7f8216 100644 --- a/coregrind/m_libcbase.c +++ b/coregrind/m_libcbase.c @@ -471,6 +471,56 @@ void VG_(ssort)( void* base, SizeT nmemb, SizeT size, #undef SORT } +/* --------------------------------------------------------------------- + A function for doing syscalls. + ------------------------------------------------------------------ */ + +#if defined(VGP_x86_linux) +extern UInt do_syscall_x86_linux_WRK ( + UInt syscall_no, + UInt a1, UInt a2, UInt a3, + UInt a4, UInt a5, UInt a6 + ); +asm( +"do_syscall_x86_linux_WRK:\n" +" push %esi\n" +" push %edi\n" +" push %ebx\n" +" push %ebp\n" +" movl 16+ 4(%esp),%eax\n" +" movl 16+ 8(%esp),%ebx\n" +" movl 16+12(%esp),%ecx\n" +" movl 16+16(%esp),%edx\n" +" movl 16+20(%esp),%esi\n" +" movl 16+24(%esp),%edi\n" +" movl 16+28(%esp),%ebp\n" +" int $0x80\n" +" popl %ebp\n" +" popl %ebx\n" +" popl %edi\n" +" popl %esi\n" +" ret\n" +); +#endif + + +SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, + UWord a4, UWord a5, UWord a6 ) +{ + SysRes res; + +# if defined(VGP_x86_linux) + UInt eax = do_syscall_x86_linux_WRK(sysno,a1,a2,a3,a4,a5,a6); + res = VG_(mk_SysRes_x86_linux)( eax ); +# else + +# error VG_(do_syscall): unimplemented on this platform + +# endif + + return res; +} + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 974dcdbdb..34ca5798d 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -33,7 +33,6 @@ #include "pub_core_libcassert.h" #include "pub_core_libcfile.h" #include "pub_core_options.h" -#include "pub_core_syscalls.h" // For VG_(is_kerror)() #include "vki_unistd.h" /* --------------------------------------------------------------------- @@ -67,86 +66,77 @@ Int VG_(safe_fd)(Int oldfd) /* Returns -1 on failure. */ Int VG_(open) ( const Char* pathname, Int flags, Int mode ) { - Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); - return fd; + SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode); + return res.isError ? -1 : res.val; } void VG_(close) ( Int fd ) { - VG_(do_syscall1)(__NR_close, fd); + (void)VG_(do_syscall1)(__NR_close, fd); } Int VG_(read) ( Int fd, void* buf, Int count) { - Int res; - res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); - return res; + SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); + return res.isError ? -1 : res.val; } Int VG_(write) ( Int fd, const void* buf, Int count) { - Int res; - res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); - return res; + SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); + return res.isError ? -1 : res.val; } Int VG_(pipe) ( Int fd[2] ) { - Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd); - return VG_(is_kerror)(ret) ? -1 : 0; + SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); + return res.isError ? -1 : 0; } OffT VG_(lseek) ( Int fd, OffT offset, Int whence) { - Int res; - res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); - if (VG_(is_kerror)(res)) res = -1; - return res; + SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); + return res.isError ? (-1) : 0; } Int VG_(stat) ( Char* file_name, struct vki_stat* buf ) { - Int res; - res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf); - return res; /* return -ve error */ + SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf); + return res.isError ? (-1) : 0; } Int VG_(fstat) ( Int fd, struct vki_stat* buf ) { - Int res; - res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf); - return VG_(is_kerror)(res) ? (-1) : 0; + SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf); + return res.isError ? (-1) : 0; } Int VG_(dup2) ( Int oldfd, Int newfd ) { - Int res; - res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd); - return VG_(is_kerror)(res) ? (-1) : res; + SysRes res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd); + return res.isError ? (-1) : res.val; } Int VG_(rename) ( Char* old_name, Char* new_name ) { - Int res; - res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); - return VG_(is_kerror)(res) ? (-1) : 0; + SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); + return res.isError ? (-1) : 0; } Int VG_(unlink) ( Char* file_name ) { - Int res; - res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); - return VG_(is_kerror)(res) ? (-1) : 0; + SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); + return res.isError ? (-1) : 0; } /* Nb: we do not allow the Linux extension which malloc()s memory for the buffer if buf==NULL, because we don't want Linux calling malloc() */ Char* VG_(getcwd) ( Char* buf, SizeT size ) { - Word res; + SysRes res; vg_assert(buf != NULL); res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size); - return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res; + return res.isError ? ((Char*)NULL) : (Char*)res.val; } /* Alternative version that does allocate the memory. Easier to use. */ @@ -170,20 +160,18 @@ Bool VG_(getcwd_alloc) ( Char** out ) Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz) { - Int res; + SysRes res; /* res = readlink( path, buf, bufsiz ); */ res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); - if (VG_(is_kerror)(res)) res = -1; - return res; + return res.isError ? -1 : res.val; } Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count) { - Int res; + SysRes res; /* res = getdents( fd, dirp, count ); */ res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); - if (VG_(is_kerror)(res)) res = -1; - return res; + return res.isError ? -1 : res.val; } /* --------------------------------------------------------------------- @@ -309,133 +297,119 @@ Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) # undef GET_CH } - static Int my_socket ( Int domain, Int type, Int protocol ) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[3]; args[0] = domain; args[1] = type; args[2] = protocol; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. + I_die_here; +# endif } static Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[3]; args[0] = sockfd; args[1] = (UWord)serv_addr; args[2] = addrlen; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. + I_die_here; +# endif } Int VG_(write_socket)( Int sd, void *msg, Int count ) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else /* This is actually send(). */ - /* Requests not to send SIGPIPE on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned. */ Int flags = VKI_MSG_NOSIGNAL; - Int res; - UWord args[4]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[4]; args[0] = sd; args[1] = (UWord)msg; args[2] = count; args[3] = flags; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); - if (VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. + I_die_here; +# endif } Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[3]; args[0] = sd; args[1] = (UWord)name; args[2] = (UWord)namelen; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. + I_die_here; +# endif } Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[3]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[3]; args[0] = sd; args[1] = (UWord)name; args[2] = (UWord)namelen; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. + I_die_here; +# endif } Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, Int *optlen) { -// AMD64/Linux doesn't define __NR_socketcall... see comment above -// VG_(sigpending)() for more details. -#ifdef __amd64__ - I_die_here; -#else - Int res; - UWord args[5]; +# if defined(VGP_x86_linux) + SysRes res; + UWord args[5]; args[0] = sd; args[1] = level; args[2] = optname; args[3] = (UWord)optval; args[4] = (UWord)optlen; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); - if(VG_(is_kerror)(res)) - res = -1; - return res; -#endif + return res.isError ? -1 : res.val; +# else + I_die_here; + // AMD64/Linux doesn't define __NR_socketcall... see comment above + // VG_(sigpending)() for more details. +# endif } diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 9be79d5aa..64e297c09 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -338,7 +338,8 @@ void VG_(set_sleeping)(ThreadId tid, ThreadStatus sleepstate) if (VG_(clo_trace_sched)) { Char buf[50]; - VG_(sprintf)(buf, "now sleeping in state %s", name_of_thread_state(sleepstate)); + VG_(sprintf)(buf, "now sleeping in state %s", + name_of_thread_state(sleepstate)); print_sched_event(tid, buf); } } @@ -410,8 +411,6 @@ void VG_(vg_yield)(void) VG_(nanosleep)(&ts); VG_(set_running)(tid); - - VG_(poll_signals)(tid); /* something might have happened */ } @@ -566,8 +565,6 @@ void mostly_clear_thread_record ( ThreadId tid ) until the caller is finally done with the thread stack. */ VG_(threads)[tid].status = VgTs_Zombie; - VG_(threads)[tid].syscallno = -1; - VG_(sigemptyset)(&VG_(threads)[tid].sig_mask); VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask); @@ -613,6 +610,7 @@ static void sched_fork_cleanup(ThreadId me) if (tid != me) { mostly_clear_thread_record(tid); VG_(threads)[tid].status = VgTs_Empty; + VG_(clear_syscallInfo)(tid); } } @@ -908,6 +906,8 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src ) "VG_(nuke_all_threads_except): nuking tid %d\n", tid); VG_(threads)[tid].exitreason = src; + if (src == VgSrc_FatalSig) + VG_(threads)[tid].os_state.fatalsig = VKI_SIGKILL; VG_(kill_thread)(tid); } } diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index e126ec920..5f3adc5b4 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -124,7 +124,9 @@ typedef struct SigQueue { # define VGP_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.esp) # define VGP_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.ebp) # define VGP_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.eax) -# define VGP_UCONTEXT_SYSCALL_RET(uc) ((uc)->uc_mcontext.eax) +# define VGP_UCONTEXT_SYSCALL_SYSRES(uc) \ + /* Convert the value in uc_mcontext.eax into a SysRes. */ \ + VG_(mk_SysRes_x86_linux)( (uc)->uc_mcontext.eax ) #elif defined(VGP_amd64_linux) # define VGP_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.rip) # define VGP_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.rsp) @@ -327,10 +329,11 @@ void calculate_SKSS_from_SCSS ( SKSS* dst ) /* SA_ONESHOT: ignore client setting */ - /* SA_RESTART: ignore client setting and always set it for us - (even though we never rely on the kernel to restart a + /* SA_RESTART: ignore client setting and always set it for us. + Though we never rely on the kernel to restart a syscall, we observe whether it wanted to restart the syscall - or not, which helps VGA_(interrupted_syscall)()) */ + or not, which is needed by + VG_(fixup_guest_state_after_syscall_interrupted) */ skss_flags |= VKI_SA_RESTART; /* SA_NOMASK: ignore it */ @@ -458,7 +461,7 @@ static Int sas_ss_flags ( ThreadId tid, Addr m_SP ) } -Int VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) +SysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) { Addr m_SP; @@ -479,18 +482,18 @@ Int VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) if (ss != NULL) { if (on_sig_stack(tid, STACK_PTR(VG_(threads)[tid].arch))) { - return -VKI_EPERM; + return VG_(mk_SysRes_Error)( VKI_EPERM ); } if (ss->ss_flags != VKI_SS_DISABLE && ss->ss_flags != VKI_SS_ONSTACK && ss->ss_flags != 0) { - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } if (ss->ss_flags == VKI_SS_DISABLE) { VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE; } else { if (ss->ss_size < VKI_MINSIGSTKSZ) { - return -VKI_ENOMEM; + return VG_(mk_SysRes_Error)( VKI_ENOMEM ); } VG_(threads)[tid].altstack.ss_sp = ss->ss_sp; @@ -498,13 +501,13 @@ Int VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss ) VG_(threads)[tid].altstack.ss_flags = 0; } } - return 0; + return VG_(mk_SysRes_Success)( 0 ); } -Int VG_(do_sys_sigaction) ( Int signo, - const struct vki_sigaction *new_act, - struct vki_sigaction *old_act ) +SysRes VG_(do_sys_sigaction) ( Int signo, + const struct vki_sigaction *new_act, + struct vki_sigaction *old_act ) { if (VG_(clo_trace_signals)) VG_(message)(Vg_DebugExtraMsg, @@ -523,7 +526,8 @@ Int VG_(do_sys_sigaction) ( Int signo, /* don't let them use our signals */ if ( (signo > VKI_SIGVGRTUSERMAX) && new_act - && !(new_act->ksa_handler == VKI_SIG_DFL || new_act->ksa_handler == VKI_SIG_IGN) ) + && !(new_act->ksa_handler == VKI_SIG_DFL + || new_act->ksa_handler == VKI_SIG_IGN) ) goto bad_signo_reserved; /* Reject attempts to set a handler (or set ignore) for SIGKILL. */ @@ -556,7 +560,7 @@ Int VG_(do_sys_sigaction) ( Int signo, if (new_act) { handle_SCSS_change( False /* lazy update */ ); } - return 0; + return VG_(mk_SysRes_Success)( 0 ); bad_signo: if (VG_(needs).core_errors && VG_(clo_verbosity) >= 1 @@ -565,7 +569,7 @@ Int VG_(do_sys_sigaction) ( Int signo, "Warning: bad signal number %d in sigaction()", signo); } - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); bad_signo_reserved: if (VG_(needs).core_errors && VG_(clo_verbosity) >= 1 @@ -577,7 +581,7 @@ Int VG_(do_sys_sigaction) ( Int signo, " the %s signal is used internally by Valgrind", signame(signo)); } - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); bad_sigkill_or_sigstop: if (VG_(needs).core_errors && VG_(clo_verbosity) >= 1 @@ -589,7 +593,7 @@ Int VG_(do_sys_sigaction) ( Int signo, " the %s signal is uncatchable", signame(signo)); } - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } @@ -655,10 +659,10 @@ void do_setmask ( ThreadId tid, } -int VG_(do_sys_sigprocmask) ( ThreadId tid, - Int how, - vki_sigset_t* set, - vki_sigset_t* oldset ) +SysRes VG_(do_sys_sigprocmask) ( ThreadId tid, + Int how, + vki_sigset_t* set, + vki_sigset_t* oldset ) { switch(how) { case VKI_SIG_BLOCK: @@ -666,13 +670,12 @@ int VG_(do_sys_sigprocmask) ( ThreadId tid, case VKI_SIG_SETMASK: vg_assert(VG_(is_valid_tid)(tid)); do_setmask ( tid, how, set, oldset ); - VG_(poll_signals)(tid); /* look for any newly deliverable signals */ - return 0; + return VG_(mk_SysRes_Success)( 0 ); default: VG_(message)(Vg_DebugMsg, "sigprocmask: unknown 'how' field %d", how); - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } } @@ -1611,11 +1614,13 @@ void async_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext * sigNo, tid, info->si_code); /* Update thread state properly */ - VGP_(interrupted_syscall)(tid, - VGP_UCONTEXT_INSTR_PTR(uc), - VGP_UCONTEXT_SYSCALL_NUM(uc), - VGP_UCONTEXT_SYSCALL_RET(uc), - !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART)); + VG_(fixup_guest_state_after_syscall_interrupted)( + tid, + VGP_UCONTEXT_INSTR_PTR(uc), + VGP_UCONTEXT_SYSCALL_NUM(uc), + VGP_UCONTEXT_SYSCALL_SYSRES(uc), + !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART) + ); /* Set up the thread's state to deliver a signal */ if (!is_sig_ign(info->si_signo)) @@ -1985,7 +1990,8 @@ void VG_(poll_signals)(ThreadId tid) /* If there was nothing queued, ask the kernel for a pending signal */ if (sip == NULL && VG_(sigtimedwait)(&pollset, &si, &zero) > 0) { if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "poll_signals: got signal %d for thread %d", si.si_signo, tid); + VG_(message)(Vg_DebugMsg, "poll_signals: got signal %d " + "for thread %d", si.si_signo, tid); sip = &si; } diff --git a/coregrind/m_syscalls/Makefile.am b/coregrind/m_syscalls/Makefile.am index 796a08223..51c7db17d 100644 --- a/coregrind/m_syscalls/Makefile.am +++ b/coregrind/m_syscalls/Makefile.am @@ -5,7 +5,8 @@ EXTRA_DIST = \ README_SYSCALLS.txt noinst_HEADERS = \ - priv_syscalls.h \ + priv_types_n_macros.h \ + priv_syscalls-generic.h \ priv_syscalls-linux.h \ priv_syscalls-amd64-linux.h \ priv_syscalls-arm-linux.h \ @@ -15,6 +16,7 @@ noinst_LIBRARIES = libsyscalls.a libsyscalls_a_SOURCES = \ syscall-@VG_PLATFORM@.S \ - syscalls.c \ + syscalls-generic.c \ syscalls-@VG_OS@.c \ - syscalls-@VG_PLATFORM@.c + syscalls-@VG_PLATFORM@.c \ + syscalls-main.c diff --git a/coregrind/m_syscalls/README_SYSCALLS.txt b/coregrind/m_syscalls/README_SYSCALLS.txt index 5c12cf776..060069305 100644 --- a/coregrind/m_syscalls/README_SYSCALLS.txt +++ b/coregrind/m_syscalls/README_SYSCALLS.txt @@ -1 +1,14 @@ -(put useful notes about this module in here) + +This module handles the complex business of handing system calls off +to the host and then fixing up the guest state accordingly. It +interacts complicatedly with signals and to a less extent threads. + +There are some important caveats regarding how to write the PRE and +POST wrappers for syscalls. It is important to observe these, else +you will have to track down almost impossibly obscure bugs. These +caveats are described in comments at the top of syscalls-main.c. + +The main file is syscalls-main.c. It contains all the driver logic +and a great deal of commentary. The wrappers themselves live in +syscalls-generic.c, syscalls-${OS}.c and syscalls-${PLATFORM}.c. + diff --git a/coregrind/m_syscalls/priv_syscalls-generic.h b/coregrind/m_syscalls/priv_syscalls-generic.h new file mode 100644 index 000000000..e695cf481 --- /dev/null +++ b/coregrind/m_syscalls/priv_syscalls-generic.h @@ -0,0 +1,324 @@ + +/*--------------------------------------------------------------------*/ +/*--- Private syscalls header. priv_syscalls.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PRIV_SYSCALLS_GENERIC_H +#define __PRIV_SYSCALLS_GENERIC_H + +/* requires #include "priv_types_n_macros.h" */ + + +// Return true if address range entirely contained within client +// address space. +extern +Bool VG_(valid_client_addr)(Addr start, SizeT size, ThreadId tid, + const Char *syscallname); + +// Return true if we're allowed to use or create this fd. +extern +Bool VG_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool soft); + +extern +void VG_(record_fd_open)(ThreadId tid, Int fd, char *pathname); + +// Used when killing threads -- we must not kill a thread if it's the thread +// that would do Valgrind's final cleanup and output. +extern +Bool VG_(do_sigkill)(Int pid, Int tgid); + +/* So that it can be seen from syscalls-x86-linux.c. */ +extern +void VG_(mmap_segment) ( Addr a, SizeT len, UInt prot, + UInt mm_flags, Int fd, ULong offset ); + + +DECL_TEMPLATE(generic,sys_ni_syscall); // * P -- unimplemented +DECL_TEMPLATE(generic,sys_exit); +DECL_TEMPLATE(generic,sys_fork); +DECL_TEMPLATE(generic,sys_read); +DECL_TEMPLATE(generic,sys_write); +DECL_TEMPLATE(generic,sys_open); +DECL_TEMPLATE(generic,sys_close); +DECL_TEMPLATE(generic,sys_waitpid); +DECL_TEMPLATE(generic,sys_creat); +DECL_TEMPLATE(generic,sys_link); +DECL_TEMPLATE(generic,sys_unlink); +DECL_TEMPLATE(generic,sys_execve); // (*??) P +DECL_TEMPLATE(generic,sys_chdir); +DECL_TEMPLATE(generic,sys_time); +DECL_TEMPLATE(generic,sys_mknod); +DECL_TEMPLATE(generic,sys_chmod); +DECL_TEMPLATE(generic,sys_lseek); +DECL_TEMPLATE(generic,sys_getpid); +DECL_TEMPLATE(generic,sys_alarm); +DECL_TEMPLATE(generic,sys_pause); +DECL_TEMPLATE(generic,sys_utime); +DECL_TEMPLATE(generic,sys_access); +DECL_TEMPLATE(generic,sys_kill); +DECL_TEMPLATE(generic,sys_rename); +DECL_TEMPLATE(generic,sys_mkdir); +DECL_TEMPLATE(generic,sys_rmdir); +DECL_TEMPLATE(generic,sys_dup); +DECL_TEMPLATE(generic,sys_times); +DECL_TEMPLATE(generic,sys_fcntl); // POSIX (but complicated) +DECL_TEMPLATE(generic,sys_setpgid); +DECL_TEMPLATE(generic,sys_umask); +DECL_TEMPLATE(generic,sys_dup2); +DECL_TEMPLATE(generic,sys_getppid); +DECL_TEMPLATE(generic,sys_getpgrp); +DECL_TEMPLATE(generic,sys_setsid); +DECL_TEMPLATE(generic,sys_munmap); +DECL_TEMPLATE(generic,sys_truncate); +DECL_TEMPLATE(generic,sys_ftruncate); +DECL_TEMPLATE(generic,sys_fchmod); +DECL_TEMPLATE(generic,sys_msync); +DECL_TEMPLATE(generic,sys_readv); +DECL_TEMPLATE(generic,sys_writev); +DECL_TEMPLATE(generic,sys_getsid); +DECL_TEMPLATE(generic,sys_fdatasync); +DECL_TEMPLATE(generic,sys_mlock); +DECL_TEMPLATE(generic,sys_munlock); +DECL_TEMPLATE(generic,sys_mlockall); +DECL_TEMPLATE(generic,sys_munlockall); +DECL_TEMPLATE(generic,sys_sched_setparam); +DECL_TEMPLATE(generic,sys_sched_getparam); +DECL_TEMPLATE(generic,sys_sched_rr_get_interval); +DECL_TEMPLATE(generic,sys_sched_setscheduler); +DECL_TEMPLATE(generic,sys_sched_getscheduler); +DECL_TEMPLATE(generic,sys_sched_yield); +DECL_TEMPLATE(generic,sys_sched_get_priority_max); +DECL_TEMPLATE(generic,sys_sched_get_priority_min); +DECL_TEMPLATE(generic,sys_nanosleep); +DECL_TEMPLATE(generic,sys_mremap); // POSIX, but Linux arg order may be odd +DECL_TEMPLATE(generic,sys_getuid); +DECL_TEMPLATE(generic,sys_getgid); +DECL_TEMPLATE(generic,sys_geteuid); +DECL_TEMPLATE(generic,sys_getegid); +DECL_TEMPLATE(generic,sys_getpgid); +DECL_TEMPLATE(generic,sys_fsync); +DECL_TEMPLATE(generic,sys_wait4); +DECL_TEMPLATE(generic,sys_mprotect); +DECL_TEMPLATE(generic,sys_sigprocmask); +DECL_TEMPLATE(generic,sys_timer_create); // Linux: varies across archs? +DECL_TEMPLATE(generic,sys_timer_settime); +DECL_TEMPLATE(generic,sys_timer_gettime); +DECL_TEMPLATE(generic,sys_timer_getoverrun); +DECL_TEMPLATE(generic,sys_timer_delete); +DECL_TEMPLATE(generic,sys_clock_settime); +DECL_TEMPLATE(generic,sys_clock_gettime); +DECL_TEMPLATE(generic,sys_clock_getres); +DECL_TEMPLATE(generic,sys_clock_nanosleep); +DECL_TEMPLATE(generic,sys_getcwd); +DECL_TEMPLATE(generic,sys_symlink); +DECL_TEMPLATE(generic,sys_getgroups); +DECL_TEMPLATE(generic,sys_setgroups); // SVr4, SVID, X/OPEN, 4.3BSD +DECL_TEMPLATE(generic,sys_chown); +DECL_TEMPLATE(generic,sys_setuid); +DECL_TEMPLATE(generic,sys_gettimeofday); +DECL_TEMPLATE(generic,sys_madvise); +DECL_TEMPLATE(generic,sys_sigpending); + +// These ones aren't POSIX, but are in some standard and look reasonably +// generic, and are the same for all architectures under Linux. +DECL_TEMPLATE(generic,sys_nice); // SVr4, SVID EXT, AT&T, X/OPEN, BSD 4.3 +DECL_TEMPLATE(generic,sys_sync); // SVr4, SVID, X/OPEN, BSD 4.3 +DECL_TEMPLATE(generic,sys_brk); // 4.3BSD +DECL_TEMPLATE(generic,sys_acct); // SVR4, non-POSIX +DECL_TEMPLATE(generic,sys_chroot); // SVr4, SVID, 4.4BSD, X/OPEN +DECL_TEMPLATE(generic,sys_readlink); // X/OPEN, 4.4BSD +DECL_TEMPLATE(generic,sys_fchdir); // SVr4, SVID, POSIX, X/OPEN, 4.4BSD +DECL_TEMPLATE(generic,sys_getdents); // SVr4,SVID +DECL_TEMPLATE(generic,sys_select); // 4.4BSD +DECL_TEMPLATE(generic,sys_flock); // 4.4BSD +DECL_TEMPLATE(generic,sys_poll); // XPG4-UNIX +DECL_TEMPLATE(generic,sys_getrusage); // SVr4, 4.3BSD +DECL_TEMPLATE(generic,sys_stime); // SVr4, SVID, X/OPEN +DECL_TEMPLATE(generic,sys_settimeofday); // SVr4, 4.3BSD (non-POSIX) +DECL_TEMPLATE(generic,sys_getpriority); // SVr4, 4.4BSD +DECL_TEMPLATE(generic,sys_setpriority); // SVr4, 4.4BSD +DECL_TEMPLATE(generic,sys_setitimer); // SVr4, 4.4BSD +DECL_TEMPLATE(generic,sys_getitimer); // SVr4, 4.4BSD +DECL_TEMPLATE(generic,sys_setreuid); // 4.3BSD +DECL_TEMPLATE(generic,sys_setregid); // 4.3BSD +DECL_TEMPLATE(generic,sys_fchown); // SVr4,4.3BSD +DECL_TEMPLATE(generic,sys_setgid); // SVr4,SVID +DECL_TEMPLATE(generic,sys_utimes); // 4.3BSD + +// 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. +DECL_TEMPLATE(generic,sys_setuid16); // ## P +DECL_TEMPLATE(generic,sys_getuid16); // ## P +DECL_TEMPLATE(generic,sys_setgid16); // ## SVr4,SVID +DECL_TEMPLATE(generic,sys_getgid16); // ## P +DECL_TEMPLATE(generic,sys_geteuid16); // ## P +DECL_TEMPLATE(generic,sys_getegid16); // ## P +DECL_TEMPLATE(generic,sys_setreuid16); // ## BSD4.3 +DECL_TEMPLATE(generic,sys_setregid16); // ## BSD4.3 +DECL_TEMPLATE(generic,sys_getgroups16); // ## P +DECL_TEMPLATE(generic,sys_setgroups16); // ## SVr4, SVID, X/OPEN, 4.3BSD +DECL_TEMPLATE(generic,sys_fchown16); // ## SVr4,BSD4.3 +DECL_TEMPLATE(generic,sys_chown16); // ## P + +// Some archs on Linux do not match the generic wrapper for sys_pipe(). +DECL_TEMPLATE(generic,sys_pipe); + +// May not be generic for every architecture under Linux. +DECL_TEMPLATE(generic,sys_sigaction); // (x86) P + +// Funny names, not sure... +DECL_TEMPLATE(generic,sys_newstat); // * P +DECL_TEMPLATE(generic,sys_newlstat); // * +DECL_TEMPLATE(generic,sys_newfstat); // * P (SVr4,BSD4.3) + +// For the remainder, not really sure yet +DECL_TEMPLATE(generic,sys_ptrace); // (x86?) (almost-P) +DECL_TEMPLATE(generic,sys_sigsuspend); // POSIX, but L (proto varies across archs) +DECL_TEMPLATE(generic,sys_setrlimit); // SVr4, 4.3BSD +DECL_TEMPLATE(generic,sys_ioctl); // x86? (various) +DECL_TEMPLATE(generic,sys_old_getrlimit); // SVr4, 4.3BSD L? +DECL_TEMPLATE(generic,sys_statfs); // * L? +DECL_TEMPLATE(generic,sys_fstatfs); // * L? +DECL_TEMPLATE(generic,sys_iopl); // (x86/amd64) L +DECL_TEMPLATE(generic,sys_ipc); // (x86) L +DECL_TEMPLATE(generic,sys_newuname); // * P +DECL_TEMPLATE(generic,sys_init_module); // * L? +DECL_TEMPLATE(generic,sys_quotactl); // * (?) +DECL_TEMPLATE(generic,sys_rt_sigaction); // (x86) () +DECL_TEMPLATE(generic,sys_rt_sigprocmask); // * ? +DECL_TEMPLATE(generic,sys_rt_sigpending); // * ? +DECL_TEMPLATE(generic,sys_rt_sigtimedwait); // * ? +DECL_TEMPLATE(generic,sys_rt_sigqueueinfo); // * ? +DECL_TEMPLATE(generic,sys_rt_sigsuspend); // () () +DECL_TEMPLATE(generic,sys_pread64); // * (Unix98?) +DECL_TEMPLATE(generic,sys_pwrite64); // * (Unix98?) +DECL_TEMPLATE(generic,sys_capget); // * L? +DECL_TEMPLATE(generic,sys_capset); // * L? +DECL_TEMPLATE(generic,sys_sigaltstack); // (x86) (XPG4-UNIX) +DECL_TEMPLATE(generic,sys_getpmsg); // (?) (?) +DECL_TEMPLATE(generic,sys_putpmsg); // (?) (?) +DECL_TEMPLATE(generic,sys_getrlimit); // * (?) +DECL_TEMPLATE(generic,sys_mmap2); // (x86?) P? +DECL_TEMPLATE(generic,sys_truncate64); // %% (P?) +DECL_TEMPLATE(generic,sys_ftruncate64); // %% (P?) +DECL_TEMPLATE(generic,sys_lchown); // * (L?) +DECL_TEMPLATE(generic,sys_mincore); // * L? +DECL_TEMPLATE(generic,sys_getdents64); // * (SVr4,SVID?) +DECL_TEMPLATE(generic,sys_fcntl64); // * P? +DECL_TEMPLATE(generic,sys_setxattr); // * L? +DECL_TEMPLATE(generic,sys_lsetxattr); // * L? +DECL_TEMPLATE(generic,sys_fsetxattr); // * L? +DECL_TEMPLATE(generic,sys_getxattr); // * L? +DECL_TEMPLATE(generic,sys_lgetxattr); // * L? +DECL_TEMPLATE(generic,sys_fgetxattr); // * L? +DECL_TEMPLATE(generic,sys_listxattr); // * L? +DECL_TEMPLATE(generic,sys_llistxattr); // * L? +DECL_TEMPLATE(generic,sys_flistxattr); // * L? +DECL_TEMPLATE(generic,sys_removexattr); // * L? +DECL_TEMPLATE(generic,sys_lremovexattr); // * L? +DECL_TEMPLATE(generic,sys_fremovexattr); // * L? +DECL_TEMPLATE(generic,sys_sched_setaffinity); // * L? +DECL_TEMPLATE(generic,sys_sched_getaffinity); // * L? +DECL_TEMPLATE(generic,sys_lookup_dcookie); // (*/32/64) L +DECL_TEMPLATE(generic,sys_set_tid_address); // * ? +DECL_TEMPLATE(generic,sys_statfs64); // * (?) +DECL_TEMPLATE(generic,sys_fstatfs64); // * (?) +DECL_TEMPLATE(generic,sys_mq_open); // * P? +DECL_TEMPLATE(generic,sys_mq_unlink); // * P? +DECL_TEMPLATE(generic,sys_mq_timedsend); // * P? +DECL_TEMPLATE(generic,sys_mq_timedreceive); // * P? +DECL_TEMPLATE(generic,sys_mq_notify); // * P? +DECL_TEMPLATE(generic,sys_mq_getsetattr); // * P? + + + +/* --------------------------------------------------------------------- + Wrappers for sockets and ipc-ery. These are split into standalone + procedures because x86-linux hides them inside multiplexors + (sys_socketcall and sys_ipc). + ------------------------------------------------------------------ */ + +#define TId ThreadId +#define UW UWord +#define SR SysRes + +extern void VG_(generic_PRE_sys_socketpair) ( TId, UW, UW, UW, UW ); +extern SysRes VG_(generic_POST_sys_socketpair) ( TId, SR, UW, UW, UW, UW ); +extern SysRes VG_(generic_POST_sys_socket) ( TId, SR ); +extern void VG_(generic_PRE_sys_bind) ( TId, UW, UW, UW ); +extern void VG_(generic_PRE_sys_accept) ( TId, UW, UW, UW ); +extern SysRes VG_(generic_POST_sys_accept) ( TId, SR, UW, UW, UW ); +extern void VG_(generic_PRE_sys_sendto) ( TId, UW, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_send) ( TId, UW, UW, UW ); +extern void VG_(generic_PRE_sys_recvfrom) ( TId, UW, UW, UW, UW, UW, UW ); +extern void VG_(generic_POST_sys_recvfrom) ( TId, SR, UW, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_recv) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_recv) ( TId, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_connect) ( TId, UW, UW, UW ); +extern void VG_(generic_PRE_sys_setsockopt) ( TId, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_getsockopt) ( TId, UW, UW, UW, UW, UW ); +extern void VG_(generic_POST_sys_getsockopt) ( TId, SR, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_getsockname) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_getsockname) ( TId, SR, UW, UW, UW ); +extern void VG_(generic_PRE_sys_getpeername) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_getpeername) ( TId, SR, UW, UW, UW ); +extern void VG_(generic_PRE_sys_sendmsg) ( TId, UW, UW ); +extern void VG_(generic_PRE_sys_recvmsg) ( TId, UW, UW ); +extern void VG_(generic_POST_sys_recvmsg) ( TId, UW, UW ); + +extern void VG_(generic_PRE_sys_semop) ( TId, UW, UW, UW ); +extern void VG_(generic_PRE_sys_semtimedop) ( TId, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_semctl) ( TId, UW, UW, UW, UW ); +extern void VG_(generic_POST_sys_semctl) ( TId, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_msgsnd) ( TId, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_msgrcv) ( TId, UW, UW, UW, UW, UW ); +extern void VG_(generic_POST_sys_msgrcv) ( TId, UW, UW, UW, UW, UW, UW ); +extern void VG_(generic_PRE_sys_msgctl) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_msgctl) ( TId, UW, UW, UW, UW ); +extern UWord VG_(generic_PRE_sys_shmat) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_shmat) ( TId, UW, UW, UW, UW ); +extern Bool VG_(generic_PRE_sys_shmdt) ( TId, UW ); +extern void VG_(generic_POST_sys_shmdt) ( TId, UW, UW ); +extern void VG_(generic_PRE_sys_shmctl) ( TId, UW, UW, UW ); +extern void VG_(generic_POST_sys_shmctl) ( TId, UW, UW, UW, UW ); + +#undef TId +#undef UW +#undef SR + + +///////////////////////////////////////////////////////////////// + + +#endif // __PRIV_SYSCALLS_GENERIC_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ + diff --git a/coregrind/m_syscalls/priv_syscalls-linux.h b/coregrind/m_syscalls/priv_syscalls-linux.h index 86223cf60..7747196b3 100644 --- a/coregrind/m_syscalls/priv_syscalls-linux.h +++ b/coregrind/m_syscalls/priv_syscalls-linux.h @@ -31,68 +31,60 @@ #ifndef __PRIV_SYSCALLS_LINUX_H #define __PRIV_SYSCALLS_LINUX_H -// Macros for adding Linux-specific, arch-independent wrappers to a syscall -// table. -#define LINX_(const, name) SYS_WRAPPER_ENTRY_X_(vgOS_linux, const, name) -#define LINXY(const, name) SYS_WRAPPER_ENTRY_XY(vgOS_linux, const, name) - -// The following syscall wrappers are Linux-specific, but arch-independent. -#define LINUX_SYSCALL_WRAPPER(x) \ - extern UInt VGO_(linux_##x##_flags); \ - extern void VGO_(linux_##x##_before)(ThreadId tid, ThreadState *tst); \ - extern void VGO_(linux_##x##_after) (ThreadId tid, ThreadState *tst) - -LINUX_SYSCALL_WRAPPER(sys_exit_group); - -LINUX_SYSCALL_WRAPPER(sys_mount); -LINUX_SYSCALL_WRAPPER(sys_oldumount); -LINUX_SYSCALL_WRAPPER(sys_umount); - -LINUX_SYSCALL_WRAPPER(sys_llseek); -LINUX_SYSCALL_WRAPPER(sys_adjtimex); - -LINUX_SYSCALL_WRAPPER(sys_setfsuid16); -LINUX_SYSCALL_WRAPPER(sys_setfsgid16); -LINUX_SYSCALL_WRAPPER(sys_setresuid16); // man page says "non-standard"; -LINUX_SYSCALL_WRAPPER(sys_getresuid16); -LINUX_SYSCALL_WRAPPER(sys_setresgid16); // man page says "non-standard" -LINUX_SYSCALL_WRAPPER(sys_getresgid16); - -LINUX_SYSCALL_WRAPPER(sys_setfsuid); -LINUX_SYSCALL_WRAPPER(sys_setfsgid); -LINUX_SYSCALL_WRAPPER(sys_setresuid); // man page says "non-standard" -LINUX_SYSCALL_WRAPPER(sys_getresuid); -LINUX_SYSCALL_WRAPPER(sys_setresgid); // man page says "non-standard" -LINUX_SYSCALL_WRAPPER(sys_getresgid); - -LINUX_SYSCALL_WRAPPER(sys_ioperm); -LINUX_SYSCALL_WRAPPER(sys_syslog); -LINUX_SYSCALL_WRAPPER(sys_vhangup); -LINUX_SYSCALL_WRAPPER(sys_sysinfo); -LINUX_SYSCALL_WRAPPER(sys_personality); -LINUX_SYSCALL_WRAPPER(sys_sysctl); -LINUX_SYSCALL_WRAPPER(sys_prctl); - -LINUX_SYSCALL_WRAPPER(sys_sendfile); -LINUX_SYSCALL_WRAPPER(sys_sendfile64); -LINUX_SYSCALL_WRAPPER(sys_futex); - -LINUX_SYSCALL_WRAPPER(sys_epoll_create); -LINUX_SYSCALL_WRAPPER(sys_epoll_ctl); -LINUX_SYSCALL_WRAPPER(sys_epoll_wait); - -LINUX_SYSCALL_WRAPPER(sys_gettid); -LINUX_SYSCALL_WRAPPER(sys_tkill); -LINUX_SYSCALL_WRAPPER(sys_tgkill); - -LINUX_SYSCALL_WRAPPER(sys_fadvise64); -LINUX_SYSCALL_WRAPPER(sys_fadvise64_64); - -LINUX_SYSCALL_WRAPPER(sys_io_setup); -LINUX_SYSCALL_WRAPPER(sys_io_destroy); -LINUX_SYSCALL_WRAPPER(sys_io_getevents); -LINUX_SYSCALL_WRAPPER(sys_io_submit); -LINUX_SYSCALL_WRAPPER(sys_io_cancel); +/* requires #include "priv_types_n_macros.h" */ + + +DECL_TEMPLATE(linux,sys_exit_group); + +DECL_TEMPLATE(linux,sys_mount); +DECL_TEMPLATE(linux,sys_oldumount); +DECL_TEMPLATE(linux,sys_umount); + +DECL_TEMPLATE(linux,sys_llseek); +DECL_TEMPLATE(linux,sys_adjtimex); + +DECL_TEMPLATE(linux,sys_setfsuid16); +DECL_TEMPLATE(linux,sys_setfsgid16); +DECL_TEMPLATE(linux,sys_setresuid16); // man page says "non-standard"; +DECL_TEMPLATE(linux,sys_getresuid16); +DECL_TEMPLATE(linux,sys_setresgid16); // man page says "non-standard" +DECL_TEMPLATE(linux,sys_getresgid16); + +DECL_TEMPLATE(linux,sys_setfsuid); +DECL_TEMPLATE(linux,sys_setfsgid); +DECL_TEMPLATE(linux,sys_setresuid); // man page says "non-standard" +DECL_TEMPLATE(linux,sys_getresuid); +DECL_TEMPLATE(linux,sys_setresgid); // man page says "non-standard" +DECL_TEMPLATE(linux,sys_getresgid); + +DECL_TEMPLATE(linux,sys_ioperm); +DECL_TEMPLATE(linux,sys_syslog); +DECL_TEMPLATE(linux,sys_vhangup); +DECL_TEMPLATE(linux,sys_sysinfo); +DECL_TEMPLATE(linux,sys_personality); +DECL_TEMPLATE(linux,sys_sysctl); +DECL_TEMPLATE(linux,sys_prctl); + +DECL_TEMPLATE(linux,sys_sendfile); +DECL_TEMPLATE(linux,sys_sendfile64); +DECL_TEMPLATE(linux,sys_futex); + +DECL_TEMPLATE(linux,sys_epoll_create); +DECL_TEMPLATE(linux,sys_epoll_ctl); +DECL_TEMPLATE(linux,sys_epoll_wait); + +DECL_TEMPLATE(linux,sys_gettid); +DECL_TEMPLATE(linux,sys_tkill); +DECL_TEMPLATE(linux,sys_tgkill); + +DECL_TEMPLATE(linux,sys_fadvise64); +DECL_TEMPLATE(linux,sys_fadvise64_64); + +DECL_TEMPLATE(linux,sys_io_setup); +DECL_TEMPLATE(linux,sys_io_destroy); +DECL_TEMPLATE(linux,sys_io_getevents); +DECL_TEMPLATE(linux,sys_io_submit); +DECL_TEMPLATE(linux,sys_io_cancel); #endif // __PRIV_SYSCALLS_LINUX_H diff --git a/coregrind/m_syscalls/priv_syscalls-main.h b/coregrind/m_syscalls/priv_syscalls-main.h new file mode 100644 index 000000000..80823fdd0 --- /dev/null +++ b/coregrind/m_syscalls/priv_syscalls-main.h @@ -0,0 +1,43 @@ + +/*--------------------------------------------------------------------*/ +/*--- Private exports of syscalls-main.c. priv_syscalls-main.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Nicholas Nethercote + njn@valgrind.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PRIV_SYSCALLS_MAIN_H +#define __PRIV_SYSCALLS_MAIN_H + +/* Back up a thread so as to restart a system call. */ +extern +void VG_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ); + +#endif // __PRIV_SYSCALLS_MAIN_H + +/*--------------------------------------------------------------------*/ +/*--- end priv_syscalls-main.h ---*/ +/*--------------------------------------------------------------------*/ + diff --git a/coregrind/m_syscalls/priv_syscalls-x86-linux.h b/coregrind/m_syscalls/priv_syscalls-x86-linux.h index 69218cecb..1c6fc97f2 100644 --- a/coregrind/m_syscalls/priv_syscalls-x86-linux.h +++ b/coregrind/m_syscalls/priv_syscalls-x86-linux.h @@ -31,23 +31,6 @@ #ifndef __PRIV_SYSCALLS_X86_LINUX_H #define __PRIV_SYSCALLS_X86_LINUX_H -// Accessors for the ThreadArchState -#define VGP_SYSCALL_NUM guest_EAX -#define VGP_SYSCALL_ARG1 guest_EBX -#define VGP_SYSCALL_ARG2 guest_ECX -#define VGP_SYSCALL_ARG3 guest_EDX -#define VGP_SYSCALL_ARG4 guest_ESI -#define VGP_SYSCALL_ARG5 guest_EDI -#define VGP_SYSCALL_ARG6 guest_EBP -#define VGP_SYSCALL_RET guest_EAX - -// Setting a syscall result -#define VGP_SET_SYSCALL_RESULT(regs, val) ((regs).vex.guest_EAX = (val)) - -// For informing tools that a syscall result has been set. -#define VGP_TRACK_SYSCALL_RETVAL(zztid) \ - VG_TRACK( post_reg_write, Vg_CoreSysCall, zztid, O_SYSCALL_RET, sizeof(UWord) ); - #endif // __PRIV_SYSCALLS_X86_LINUX_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syscalls/priv_syscalls.h b/coregrind/m_syscalls/priv_syscalls.h deleted file mode 100644 index c60b57933..000000000 --- a/coregrind/m_syscalls/priv_syscalls.h +++ /dev/null @@ -1,515 +0,0 @@ -/*--------------------------------------------------------------------*/ -/*--- Private syscalls header. priv_syscalls.h ---*/ -/*--------------------------------------------------------------------*/ - -/* - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2005 Julian Seward - jseward@acm.org - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - -#ifndef __PRIV_SYSCALLS_H -#define __PRIV_SYSCALLS_H - -#include "pub_core_options.h" -#include "pub_core_signals.h" - -#if defined(VGO_linux) -# include "priv_syscalls-linux.h" -#else -# error Unknown OS -#endif - -#if defined(VGP_amd64_linux) -# include "priv_syscalls-amd64-linux.h" -#elif defined(VGP_arm_linux) -# include "priv_syscalls-arm-linux.h" -#elif defined(VGP_x86_linux) -# include "priv_syscalls-x86-linux.h" -#else -# error Unknown platform -#endif - -#include "vki_unistd.h" - -// Offsets for the shadow state -#define O_SYSCALL_NUM (offsetof(VexGuestArchState, VGP_SYSCALL_NUM)) -#define O_SYSCALL_ARG1 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG1)) -#define O_SYSCALL_ARG2 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG2)) -#define O_SYSCALL_ARG3 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG3)) -#define O_SYSCALL_ARG4 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG4)) -#define O_SYSCALL_ARG5 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG5)) -#define O_SYSCALL_ARG6 (offsetof(VexGuestArchState, VGP_SYSCALL_ARG6)) -#define O_SYSCALL_RET (offsetof(VexGuestArchState, VGP_SYSCALL_RET)) - -// The syscall table -struct SyscallTableEntry { - UInt *flags_ptr; - void (*before)(ThreadId tid, ThreadState *tst /*, UInt *flags*/); - 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 Int VG_(clone) ( Int (*fn)(void *), void *stack, Int flags, void *arg, - Int *child_tid, Int *parent_tid, vki_modify_ldt_t * ); - -/* - Perform a syscall on behalf of a client thread, using a specific - signal mask. On completion, the signal mask is set to restore_mask - (which presumably blocks almost everything). If a signal happens - during the syscall, the handler should call - VGA_(interrupted_syscall)() to adjust the thread's context to do the - right thing. -*/ -extern void VGA_(client_syscall)(Int syscallno, ThreadState *tst, - const vki_sigset_t *syscall_mask); - -/* Simple Valgrind-internal atfork mechanism */ -extern void VG_(do_atfork_pre) (ThreadId tid); -extern void VG_(do_atfork_parent)(ThreadId tid); -extern void VG_(do_atfork_child) (ThreadId tid); - -// 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); - -// Return true if we're allowed to use or create this fd. -Bool VG_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool soft); - -void VG_(record_fd_open)(ThreadId tid, Int fd, char *pathname); - -// Used when killing threads -- we must not kill a thread if it's the thread -// that would do Valgrind's final cleanup and output. -Bool VG_(do_sigkill)(Int pid, Int tgid); - -// Flags describing syscall wrappers -#define Special (1 << 0) /* handled specially */ -#define MayBlock (1 << 1) /* may block */ -#define PostOnFail (1 << 2) /* call POST() function on failure */ -#define PadAddr (1 << 3) /* pad+unpad address space around syscall */ -#define Done (1 << 4) /* used if a PRE() did the syscall */ - -// Templates for generating the PRE and POST macros. For ones that must be -// publically visible, use an empty 'qual', 'prefix' should start with -// "vgArch_" or similar, and there should be corresponding global -// declarations (like the GEN_SYSCALL_WRAPPER ones below). Otherwise, use -// "static" for 'qual', and "vgArch_" should not be in the 'prefix'. -#define PRE_TEMPLATE(qual, prefix, name, f) \ - qual UInt prefix##_##name##_flags = f; \ - qual void prefix##_##name##_before(ThreadId tid, ThreadState *tst) -#define POST_TEMPLATE(qual, prefix, name) \ - qual void prefix##_##name##_after (ThreadId tid, ThreadState *tst) - -// This macro is used to write other macros which making writing syscall -// tables easier. -#define SYS_WRAPPER_ENTRY_X_(prefix, const, name) \ - [const] = { &prefix##_##name##_flags, \ - prefix##_##name##_before, NULL } -#define SYS_WRAPPER_ENTRY_XY(prefix, const, name) \ - [const] = { &prefix##_##name##_flags, \ - prefix##_##name##_before, \ - prefix##_##name##_after } - -// Macros for adding generic wrappers to a syscall table. -#define GENX_(const, name) SYS_WRAPPER_ENTRY_X_(vgArch_gen, const, name) -#define GENXY(const, name) SYS_WRAPPER_ENTRY_XY(vgArch_gen, const, name) - -// Space-saving macros for syscall PRE() and POST() wrappers -#define RES ((tst->arch).vex.VGP_SYSCALL_RET) -#define SYSNO ((tst->arch).vex.VGP_SYSCALL_NUM) -#define ARG1 ((tst->arch).vex.VGP_SYSCALL_ARG1) -#define ARG2 ((tst->arch).vex.VGP_SYSCALL_ARG2) -#define ARG3 ((tst->arch).vex.VGP_SYSCALL_ARG3) -#define ARG4 ((tst->arch).vex.VGP_SYSCALL_ARG4) -#define ARG5 ((tst->arch).vex.VGP_SYSCALL_ARG5) -#define ARG6 ((tst->arch).vex.VGP_SYSCALL_ARG6) - -// For setting the result of a syscall in a wrapper -#define SET_RESULT(val) \ - do { VGP_SET_SYSCALL_RESULT(tst->arch, (val)); \ - tst->syscall_result_set = True; \ - } while (0) - -#define PRINT(format, args...) \ - if (VG_(clo_trace_syscalls)) \ - VG_(printf)(format, ## args) - -// 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. -// For many of them, it's unclear if they are generic, or Linux-specific, or -// x86/Linux-specific, or something else again. -// -// 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. -// -// 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) - -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); // (*??) 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_rr_get_interval); -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_getpgid); -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_clock_nanosleep); -GEN_SYSCALL_WRAPPER(sys_getcwd); -GEN_SYSCALL_WRAPPER(sys_symlink); -GEN_SYSCALL_WRAPPER(sys_getgroups); -GEN_SYSCALL_WRAPPER(sys_setgroups); // SVr4, SVID, X/OPEN, 4.3BSD -GEN_SYSCALL_WRAPPER(sys_chown); -GEN_SYSCALL_WRAPPER(sys_setuid); -GEN_SYSCALL_WRAPPER(sys_gettimeofday); -GEN_SYSCALL_WRAPPER(sys_madvise); -GEN_SYSCALL_WRAPPER(sys_sigpending); - -// 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 -GEN_SYSCALL_WRAPPER(sys_readlink); // X/OPEN, 4.4BSD -GEN_SYSCALL_WRAPPER(sys_fchdir); // SVr4, SVID, POSIX, X/OPEN, 4.4BSD -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_getrusage); // SVr4, 4.3BSD -GEN_SYSCALL_WRAPPER(sys_stime); // SVr4, SVID, X/OPEN -GEN_SYSCALL_WRAPPER(sys_settimeofday); // SVr4, 4.3BSD (non-POSIX) -GEN_SYSCALL_WRAPPER(sys_getpriority); // SVr4, 4.4BSD -GEN_SYSCALL_WRAPPER(sys_setpriority); // SVr4, 4.4BSD -GEN_SYSCALL_WRAPPER(sys_setitimer); // SVr4, 4.4BSD -GEN_SYSCALL_WRAPPER(sys_getitimer); // SVr4, 4.4BSD -GEN_SYSCALL_WRAPPER(sys_setreuid); // 4.3BSD -GEN_SYSCALL_WRAPPER(sys_setregid); // 4.3BSD -GEN_SYSCALL_WRAPPER(sys_fchown); // SVr4,4.3BSD -GEN_SYSCALL_WRAPPER(sys_setgid); // SVr4,SVID -GEN_SYSCALL_WRAPPER(sys_utimes); // 4.3BSD - -// 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 - -// 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); - -// Some archs on Linux do not match the generic wrapper for sys_pipe(). -GEN_SYSCALL_WRAPPER(sys_pipe); - -// May not be generic for every architecture under Linux. -GEN_SYSCALL_WRAPPER(sys_sigaction); // (x86) P - -// Funny names, not sure... -GEN_SYSCALL_WRAPPER(sys_newstat); // * P -GEN_SYSCALL_WRAPPER(sys_newlstat); // * -GEN_SYSCALL_WRAPPER(sys_newfstat); // * P (SVr4,BSD4.3) - -// For the remainder, not really sure yet -GEN_SYSCALL_WRAPPER(old_mmap); // x86, weird arg passing -GEN_SYSCALL_WRAPPER(sys_ptrace); // (x86?) (almost-P) -GEN_SYSCALL_WRAPPER(sys_sigsuspend); // POSIX, but L (proto varies across archs) -GEN_SYSCALL_WRAPPER(sys_setrlimit); // SVr4, 4.3BSD -GEN_SYSCALL_WRAPPER(sys_ioctl); // x86? (various) -GEN_SYSCALL_WRAPPER(sys_old_getrlimit); // SVr4, 4.3BSD L? -GEN_SYSCALL_WRAPPER(sys_statfs); // * L? -GEN_SYSCALL_WRAPPER(sys_fstatfs); // * L? -GEN_SYSCALL_WRAPPER(sys_iopl); // (x86/amd64) L -GEN_SYSCALL_WRAPPER(sys_ipc); // (x86) L -GEN_SYSCALL_WRAPPER(sys_newuname); // * P -GEN_SYSCALL_WRAPPER(sys_init_module); // * L? -GEN_SYSCALL_WRAPPER(sys_quotactl); // * (?) -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_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_mincore); // * L? -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_sched_setaffinity); // * L? -GEN_SYSCALL_WRAPPER(sys_sched_getaffinity); // * L? -GEN_SYSCALL_WRAPPER(sys_lookup_dcookie); // (*/32/64) L -GEN_SYSCALL_WRAPPER(sys_set_tid_address); // * ? -GEN_SYSCALL_WRAPPER(sys_statfs64); // * (?) -GEN_SYSCALL_WRAPPER(sys_fstatfs64); // * (?) -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 -/* PRRAn == "pre-register-read-argument" - PRRSN == "pre-register-read-syscall" -*/ - -#define PRRSN \ - VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \ - O_SYSCALL_NUM, sizeof(UWord)); -#define PRRAn(n,s,t,a) \ - VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, s"("#a")", \ - O_SYSCALL_ARG##n, sizeof(t)); -#define PRE_REG_READ0(tr, s) \ - if (VG_(tdict).track_pre_reg_read) { \ - PRRSN; \ - } -#define PRE_REG_READ1(tr, s, t1, a1) \ - if (VG_(tdict).track_pre_reg_read) { \ - PRRSN; \ - PRRAn(1,s,t1,a1); \ - } -#define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \ - if (VG_(tdict).track_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_(tdict).track_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_(tdict).track_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_(tdict).track_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_(tdict).track_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, Vg_CoreSysCall, tid, zzaddr, zzlen) - - -////////////////////////////////////////////////////////// - -#define TId ThreadId -#define UW UWord - -extern void VG_(generic_PRE_sys_socketpair) ( TId, UW, UW, UW, UW ); -extern UWord VG_(generic_POST_sys_socketpair) ( TId, UW, UW, UW, UW, UW ); -extern UWord VG_(generic_POST_sys_socket) ( TId, UW ); -extern void VG_(generic_PRE_sys_bind) ( TId, UW, UW, UW ); -extern void VG_(generic_PRE_sys_accept) ( TId, UW, UW, UW ); -extern UWord VG_(generic_POST_sys_accept) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_sendto) ( TId, UW, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_send) ( TId, UW, UW, UW ); -extern void VG_(generic_PRE_sys_recvfrom) ( TId, UW, UW, UW, UW, UW, UW ); -extern void VG_(generic_POST_sys_recvfrom) ( TId, UW, UW, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_recv) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_recv) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_connect) ( TId, UW, UW, UW ); -extern void VG_(generic_PRE_sys_setsockopt) ( TId, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_getsockopt) ( TId, UW, UW, UW, UW, UW ); -extern void VG_(generic_POST_sys_getsockopt) ( TId, UW, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_getsockname) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_getsockname) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_getpeername) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_getpeername) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_sendmsg) ( TId, UW, UW ); -extern void VG_(generic_PRE_sys_recvmsg) ( TId, UW, UW ); -extern void VG_(generic_POST_sys_recvmsg) ( TId, UW, UW, UW ); - -extern void VG_(generic_PRE_sys_semop) ( TId, UW, UW, UW ); -extern void VG_(generic_PRE_sys_semtimedop) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_semctl) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_POST_sys_semctl) ( TId, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_msgsnd) ( TId, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_msgrcv) ( TId, UW, UW, UW, UW, UW ); -extern void VG_(generic_POST_sys_msgrcv) ( TId, UW, UW, UW, UW, UW, UW ); -extern void VG_(generic_PRE_sys_msgctl) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_msgctl) ( TId, UW, UW, UW, UW ); -extern UWord VG_(generic_PRE_sys_shmat) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_shmat) ( TId, UW, UW, UW, UW ); -extern Bool VG_(generic_PRE_sys_shmdt) ( TId, UW ); -extern void VG_(generic_POST_sys_shmdt) ( TId, UW, UW ); -extern void VG_(generic_PRE_sys_shmctl) ( TId, UW, UW, UW ); -extern void VG_(generic_POST_sys_shmctl) ( TId, UW, UW, UW, UW ); - -#undef TId -#undef UW - -#endif // __PRIV_SYSCALLS_H - -/*--------------------------------------------------------------------*/ -/*--- end ---*/ -/*--------------------------------------------------------------------*/ - diff --git a/coregrind/m_syscalls/priv_types_n_macros.h b/coregrind/m_syscalls/priv_types_n_macros.h new file mode 100644 index 000000000..711f06164 --- /dev/null +++ b/coregrind/m_syscalls/priv_types_n_macros.h @@ -0,0 +1,348 @@ + +/*--------------------------------------------------------------------*/ +/*--- Types and macros for writing syscall wrappers. ---*/ +/*--- priv_syscalls.h ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#ifndef __PRIV_TYPES_N_MACROS_H +#define __PRIV_TYPES_N_MACROS_H + +/* requires #include "pub_core_options.h" */ +/* requires #include "pub_core_signals.h" */ + +/* This header defines types and macros which are useful for writing + syscall wrappers. It does not give prototypes for any such + headers, though: that is the job of the priv_syscalls-*.h headers. + This header gets included in any file which defines or declares + wrappers, and as such should only contain stuff which is relevant + to all such files. +*/ + +/* --------------------------------------------------------------------- + Types that are used in syscall wrappers. + ------------------------------------------------------------------ */ + +/* Arguments for a syscall. */ +typedef + struct { + UWord sysno; + UWord arg1; + UWord arg2; + UWord arg3; + UWord arg4; + UWord arg5; + UWord arg6; + } + SyscallArgs; + +/* Current status of a syscall being done on behalf of the client. */ +typedef + struct { + enum { SsSuccess=1, SsFailure, SsHandToKernel, SsIdle } what; + UWord val; /* only meaningful for .what == Success or Failure */ + } + SyscallStatus; + +/* Guest state layout info for syscall args. */ +typedef + struct { + Int o_sysno; + Int o_arg1; + Int o_arg2; + Int o_arg3; + Int o_arg4; + Int o_arg5; + Int o_arg6; + Int o_retval; + } + SyscallArgLayout; + +/* Flags describing syscall wrappers */ +#define SfMayBlock (1 << 1) /* may block */ +#define SfPostOnFail (1 << 2) /* call POST() function on failure */ +/* #define SfPadAddr (1 << 3) */ /* pad+unpad address space around syscall */ +#define SfPollAfter (1 << 4) /* poll for signals on completion */ +#define SfYieldAfter (1 << 5) /* yield on completion */ + + +/* --------------------------------------------------------------------- + The syscall table. + ------------------------------------------------------------------ */ + +typedef + struct { + void (*before) ( ThreadId, + SyscallArgLayout*, + /*MOD*/SyscallArgs*, + /*OUT*/SyscallStatus*, + /*OUT*/UWord* + ); + + void (*after) ( ThreadId, + SyscallArgs*, + SyscallStatus* + ); + } + SyscallTableEntry; + +/* Syscall table entries bind __NR_xxx syscall numbers to the PRE/POST + wrappers for the relevant syscall 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() +*/ + + +/* These are defined in the relevant platform-specific files -- + syscalls-arch-os.c */ + +extern const SyscallTableEntry VGP_(syscall_table)[]; + +extern const UInt VGP_(syscall_table_size); + + +/* --------------------------------------------------------------------- + Declaring and defining wrappers. + ------------------------------------------------------------------ */ + +/* Templates for generating the PRE and POST macros -- that is, the + formal parameter lists for the definitions of wrapper functions. + + Since these names exist in the global namespace, 'auxstr' should + give an auxiliary string, eg, "generic", "x86_linux", "linux", etc, + that ensures the names won't clash with other wrappers. + + You should create corresponding global declarations using + DECL_TEMPLATE (indirectly) below. +*/ + +#define DEFN_PRE_TEMPLATE(auxstr, name) \ + void vgSysWrap_##auxstr##_##name##_before \ + ( ThreadId tid, \ + SyscallArgLayout* layout, \ + /*MOD*/SyscallArgs* args, \ + /*OUT*/SyscallStatus* status, \ + /*OUT*/UWord* flags \ + ) + +#define DEFN_POST_TEMPLATE(auxstr, name) \ + void vgSysWrap_##auxstr##_##name##_after \ + ( ThreadId tid, \ + SyscallArgs* args, \ + SyscallStatus* status \ + ) + + +/* This macro generates declarations (prototypes) for wrappers. It + declares both the pre-wrapper and the post-wrapper, even though the + post-wrapper may not actually exist. +*/ +#define DECL_TEMPLATE(auxstr, name) \ + extern \ + void vgSysWrap_##auxstr##_##name##_before \ + ( ThreadId tid, \ + SyscallArgLayout* layout, \ + /*MOD*/SyscallArgs* args, \ + /*OUT*/SyscallStatus* status, \ + /*OUT*/UWord* flags \ + ); \ + extern \ + void vgSysWrap_##auxstr##_##name##_after \ + ( ThreadId tid, \ + SyscallArgs* args, \ + SyscallStatus* status \ + ); + + + +/* Macros for conveniently generating entries in the syscall + tables. This first pair are not used directly. */ + +#define WRAPPER_ENTRY_X_(auxstr, sysno, name) \ + [sysno] = { vgSysWrap_##auxstr##_##name##_before, NULL } +#define WRAPPER_ENTRY_XY(auxstr, sysno, name) \ + [sysno] = { vgSysWrap_##auxstr##_##name##_before, \ + vgSysWrap_##auxstr##_##name##_after } + +/* Add a generic wrapper to a syscall table. */ +#define GENX_(sysno, name) WRAPPER_ENTRY_X_(generic, sysno, name) +#define GENXY(sysno, name) WRAPPER_ENTRY_XY(generic, sysno, name) + +/* Add a Linux-specific, arch-independent wrapper to a syscall + table. */ +#define LINX_(sysno, name) WRAPPER_ENTRY_X_(linux, sysno, name) +#define LINXY(sysno, name) WRAPPER_ENTRY_XY(linux, sysno, name) + + + +/* --------------------------------------------------------------------- + Macros useful for writing wrappers concisely. These refer to the + parameters declared by DEFN_{PRE,POST}_TEMPLATE and so in a way do + not help clarity of understanding. But they are just too useful to + omit. + ------------------------------------------------------------------ */ + +/* Reference to the syscall's arguments -- the ones which the + pre-wrapper may have modified, not the original copy. */ +#define SYSNO (args->sysno) +#define ARG1 (args->arg1) +#define ARG2 (args->arg2) +#define ARG3 (args->arg3) +#define ARG4 (args->arg4) +#define ARG5 (args->arg5) +#define ARG6 (args->arg6) + +/* Reference to the syscall's current result status/value. Note that + + (1) status->val by itself is meaningless -- you have to consider it + together with status->what, which is why RES uses a helper + function (this also has the desirable effect of turning RES + into a non-lvalue). + + (2) post-wrappers will not get called in case of failure (unless + PostOnFail is set, which is rare). This is why the assertion + in getRES is viable. + + If you really really want to just get hold of status->val without + inspecting status->what, use RES_unchecked. This is dangerous and + therefore discouraged. +*/ +#define SUCCESS (status->what == SsSuccess) +#define FAILURE (status->what == SsFailure) +#define SWHAT (status->what) +#define RES_unchecked (status->val) /* do not use! */ +#define RES (getRES(status)) /* use this instead, if possible */ + +static inline UWord getRES ( SyscallStatus* st ) { + vg_assert(st->what == SsSuccess); + return st->val; +} + + +/* Set the current result status/value in various ways. */ +#define SET_STATUS_Success(zzz) \ + do { status->what = SsSuccess; \ + status->val = (zzz); \ + } while (0) + +#define SET_STATUS_Failure(zzz) \ + do { Word wzz = (Word)(zzz); \ + /* Catch out wildly bogus error values. */ \ + vg_assert(wzz >= 0 && wzz < 10000); \ + status->what = SsFailure; \ + status->val = wzz; \ + } while (0) + +#define SET_STATUS_from_SysRes(zzz) \ + do { \ + SysRes zres = (zzz); \ + if (zres.isError) { \ + SET_STATUS_Failure(zres.val); \ + } else { \ + SET_STATUS_Success(zres.val); \ + } \ + } while (0) + +#define PRINT(format, args...) \ + if (VG_(clo_trace_syscalls)) \ + VG_(printf)(format, ## args) + + +/* Macros used to tell tools about uses of scalar arguments. Note, + these assume little-endianness. These can only be used in + pre-wrappers, and they refer to the layout parameter passed in. */ +/* PRRAn == "pre-register-read-argument" + PRRSN == "pre-register-read-syscall" +*/ + +#define PRRSN \ + VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \ + layout->o_sysno, sizeof(UWord)); +#define PRRAn(n,s,t,a) \ + VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, s"("#a")", \ + layout->o_arg##n, sizeof(t)); +#define PRE_REG_READ0(tr, s) \ + if (VG_(tdict).track_pre_reg_read) { \ + PRRSN; \ + } +#define PRE_REG_READ1(tr, s, t1, a1) \ + if (VG_(tdict).track_pre_reg_read) { \ + PRRSN; \ + PRRAn(1,s,t1,a1); \ + } +#define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \ + if (VG_(tdict).track_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_(tdict).track_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_(tdict).track_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_(tdict).track_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_(tdict).track_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, Vg_CoreSysCall, tid, zzaddr, zzlen) + + +#endif // __PRIV_TYPES_N_MACROS_H + +/*--------------------------------------------------------------------*/ +/*--- end priv_types_n_macros.h ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syscalls/syscall-x86-linux.S b/coregrind/m_syscalls/syscall-x86-linux.S index ea4547223..5e403b0a3 100644 --- a/coregrind/m_syscalls/syscall-x86-linux.S +++ b/coregrind/m_syscalls/syscall-x86-linux.S @@ -32,104 +32,6 @@ #include "vki_unistd.h" #include "libvex_guest_offsets.h" -.globl VG_(do_syscall) - -/* - Perform a Linux syscall with int 0x80 - - Syscall args are passed on the stack - Int VG_(do_syscall)(Int syscall_no, UWord a1, UWord a2, UWord a3, - UWord a4, UWord a5, UWord a6) - - This has no effect on the virtual machine; the assumption is - that the syscall mechanism makes no useful changes to any - register except %eax, which is returned. (Some kernels will - change other registers randomly, but they're just compiler - spill values.) - */ -VG_(do_syscall): - push %esi - push %edi - push %ebx - push %ebp - movl 16+ 4(%esp),%eax - movl 16+ 8(%esp),%ebx - movl 16+12(%esp),%ecx - movl 16+16(%esp),%edx - movl 16+20(%esp),%esi - movl 16+24(%esp),%edi - movl 16+28(%esp),%ebp - int $0x80 - popl %ebp - popl %ebx - popl %edi - popl %esi - ret - -/* - Perform a clone system call. clone is strange because it has - fork()-like return-twice semantics, so it needs special - handling here. - - Upon entry, we have: - - int (fn)(void*) in 0+FSZ(%esp) - void* child_stack in 4+FSZ(%esp) - int flags in 8+FSZ(%esp) - void* arg in 12+FSZ(%esp) - pid_t* child_tid in 16+FSZ(%esp) - pid_t* parent_tid in 20+FSZ(%esp) - void* tls_ptr in 24+FSZ(%esp) - - System call requires: - - int $__NR_clone in %eax - int flags in %ebx - void* child_stack in %ecx - pid_t* parent_tid in %edx - pid_t* child_tid in %edi - void* tls_ptr in %esi - */ -.globl VG_(clone) -VG_(clone): -#define FSZ (4+4+4) /* frame size = retaddr+ebx+edi */ - push %ebx - push %edi - /* set up child stack with function and arg */ - movl 4+FSZ(%esp), %ecx /* syscall arg2: child stack */ - movl 12+FSZ(%esp), %ebx /* fn arg */ - movl 0+FSZ(%esp), %eax /* fn */ - lea -8(%ecx), %ecx /* make space on stack */ - movl %ebx, 4(%ecx) /* fn arg */ - movl %eax, 0(%ecx) /* fn */ - - /* get other args to clone */ - movl 8+FSZ(%esp), %ebx /* syscall arg1: flags */ - movl 20+FSZ(%esp), %edx /* syscall arg3: parent tid * */ - movl 16+FSZ(%esp), %edi /* syscall arg4: child tid * */ - movl 24+FSZ(%esp), %esi /* syscall arg5: tls_ptr * */ - movl $__NR_clone, %eax - int $0x80 /* clone() */ - testl %eax, %eax /* child if retval == 0 */ - jnz 1f - - /* CHILD - call thread function */ - popl %eax - call *%eax /* call fn */ - - /* exit with result */ - movl %eax, %ebx /* arg1: return value from fn */ - movl $__NR_exit, %eax - int $0x80 - - /* Hm, exit returned */ - ud2 - -1: /* PARENT or ERROR */ - pop %edi - pop %ebx - ret -#undef FSZ .globl VG_(sigreturn) VG_(sigreturn): @@ -163,7 +65,8 @@ VG_(sigreturn): Prototype: - Int VGA_(_client_syscall)(Int syscallno, // 0 + Int VGA_(do_syscall_for_client_WRK)( + Int syscallno, // 0 void* guest_state, // 4 const vki_sigset_t *sysmask, // 8 const vki_sigset_t *postmask, // 12 @@ -174,8 +77,8 @@ VG_(sigreturn): /* from vki_arch.h */ #define VKI_SIG_SETMASK 2 -.globl VGA_(_client_syscall) -VGA_(_client_syscall): +.globl VGA_(do_syscall_for_client_WRK) +VGA_(do_syscall_for_client_WRK): /* save callee-saved regs */ push %esi push %edi @@ -234,8 +137,9 @@ VGA_(_client_syscall): ret .section .rodata -/* export the ranges so that VGA_(interrupted_syscall) can do the - right thing */ +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ .globl VGA_(blksys_setup) .globl VGA_(blksys_restart) diff --git a/coregrind/m_syscalls/syscalls-amd64-linux.c b/coregrind/m_syscalls/syscalls-amd64-linux.c index 355034b5f..62b15dcdd 100644 --- a/coregrind/m_syscalls/syscalls-amd64-linux.c +++ b/coregrind/m_syscalls/syscalls-amd64-linux.c @@ -609,7 +609,7 @@ PRE(sys_clone, Special) /* Thread creation was successful; let the child have the chance to run */ - VG_(vg_yield)(); + XXX FIXME VG_(vg_yield)(); } } @@ -628,7 +628,7 @@ PRE(sys_rt_sigreturn, Special) VG_(sigframe_destroy)(tid, True); /* Keep looking for signals until there are none */ - VG_(poll_signals)(tid); + XXX FIXME VG_(poll_signals)(tid); /* placate return-must-be-set assertion */ SET_RESULT(RES); diff --git a/coregrind/m_syscalls/syscalls.c b/coregrind/m_syscalls/syscalls-generic.c index faa6514a0..e473ed94b 100644 --- a/coregrind/m_syscalls/syscalls.c +++ b/coregrind/m_syscalls/syscalls-generic.c @@ -1,6 +1,6 @@ /*--------------------------------------------------------------------*/ -/*--- Handle system calls. syscalls.c ---*/ +/*--- Wrappers for generic Unix system calls syscalls-generic.c ---*/ /*--------------------------------------------------------------------*/ /* @@ -32,91 +32,21 @@ #include "pub_core_debuglog.h" #include "pub_core_aspacemgr.h" #include "pub_core_libcbase.h" -#include "pub_core_libcassert.h" -#include "pub_core_libcfile.h" #include "pub_core_libcprint.h" +#include "pub_core_libcfile.h" +#include "pub_core_libcassert.h" #include "pub_core_main.h" -#include "pub_core_profile.h" #include "pub_core_stacktrace.h" -#include "pub_core_syscalls.h" #include "pub_core_tooliface.h" -#include "priv_syscalls.h" - - -/* All system calls are channelled through here, doing two things: - - * notify the tool of the events (mem/reg reads, writes) happening - - * perform the syscall, usually by passing it along to the kernel - unmodified. - - A magical piece of assembly code, VG_(do_syscall)(), in syscall-$PLATFORM.S - does the tricky bit of passing a syscall to the kernel, whilst - having the simulator retain control. -*/ - -/* --------------------------------------------------------------------- - A simple atfork() facility for Valgrind's internal use - ------------------------------------------------------------------ */ - -struct atfork { - vg_atfork_t pre; - vg_atfork_t parent; - vg_atfork_t child; -}; - -#define VG_MAX_ATFORK 10 - -static struct atfork atforks[VG_MAX_ATFORK]; -static Int n_atfork; - -void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child) -{ - Int i; - - for(i = 0; i < n_atfork; i++) { - if (atforks[i].pre == pre && - atforks[i].parent == parent && - atforks[i].child == child) - return; - } - - if (n_atfork >= VG_MAX_ATFORK) - VG_(core_panic)("Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK"); - - atforks[n_atfork].pre = pre; - atforks[n_atfork].parent = parent; - atforks[n_atfork].child = child; - - n_atfork++; -} - -void VG_(do_atfork_pre)(ThreadId tid) -{ - Int i; - - for(i = 0; i < n_atfork; i++) - if (atforks[i].pre != NULL) - (*atforks[i].pre)(tid); -} - -void VG_(do_atfork_parent)(ThreadId tid) -{ - Int i; +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_syscalls.h" - for(i = 0; i < n_atfork; i++) - if (atforks[i].parent != NULL) - (*atforks[i].parent)(tid); -} +#include "priv_types_n_macros.h" +#include "priv_syscalls-generic.h" -void VG_(do_atfork_child)(ThreadId tid) -{ - Int i; +#include "vki_unistd.h" /* for the __NR_* constants */ - for(i = 0; i < n_atfork; i++) - if (atforks[i].child != NULL) - (*atforks[i].child)(tid); -} /* return true if address range entirely contained within client address space */ @@ -143,8 +73,9 @@ Bool VG_(valid_client_addr)(Addr start, SizeT size, ThreadId tid, syscallname, start, end, cl_base, VG_(client_end), ret); if (!ret && syscallname != NULL) { - VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p", - syscallname, start, end); + VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried " + "to modify addresses %p-%p", + syscallname, start, end); if (VG_(clo_verbosity) > 1) { VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); @@ -181,8 +112,8 @@ void mash_addr_and_len( Addr* a, SizeT* len) *a = ra; } -static -void mmap_segment ( Addr a, SizeT len, UInt prot, UInt mm_flags, Int fd, ULong offset ) +void VG_(mmap_segment) ( Addr a, SizeT len, UInt prot, + UInt mm_flags, Int fd, ULong offset ) { Bool rr, ww, xx; UInt flags; @@ -207,21 +138,21 @@ void mmap_segment ( Addr a, SizeT len, UInt prot, UInt mm_flags, Int fd, ULong o } static -Addr mremap_segment ( Addr old_addr, SizeT old_size, - Addr new_addr, SizeT new_size, - UInt flags, ThreadId tid) +SysRes mremap_segment ( Addr old_addr, SizeT old_size, + Addr new_addr, SizeT new_size, + UInt flags, ThreadId tid) { - Addr ret; + SysRes ret; Segment *seg, *next; old_size = VG_PGROUNDUP(old_size); new_size = VG_PGROUNDUP(new_size); if (VG_PGROUNDDN(old_addr) != old_addr) - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); if (!VG_(valid_client_addr)(old_addr, old_size, tid, "mremap(old_addr)")) - return -VKI_EFAULT; + return VG_(mk_SysRes_Error)( VKI_EFAULT ); /* fixed at the current address means we don't move it */ if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr)) @@ -229,28 +160,28 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, if (flags & VKI_MREMAP_FIXED) { if (VG_PGROUNDDN(new_addr) != new_addr) - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); if (!VG_(valid_client_addr)(new_addr, new_size, tid, "mremap(new_addr)")) - return -VKI_ENOMEM; + return VG_(mk_SysRes_Error)( VKI_ENOMEM ); /* check for overlaps */ if ((old_addr < (new_addr+new_size) && (old_addr+old_size) > new_addr) || (new_addr < (old_addr+new_size) && (new_addr+new_size) > old_addr)) - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } /* Do nothing */ if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size) - return old_addr; + return VG_(mk_SysRes_Success)( old_addr ); seg = VG_(find_segment)(old_addr); /* range must be contained within segment */ if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size)) - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); next = VG_(find_segment_above_mapped)(old_addr); @@ -264,7 +195,8 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, Addr a; if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0) - return -VKI_ENOMEM; /* not allowed to move */ + /* not allowed to move */ + return VG_(mk_SysRes_Error)( VKI_ENOMEM ); if ((flags & VKI_MREMAP_FIXED) == 0) new_addr = 0; @@ -272,19 +204,18 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, a = VG_(find_map_space)(new_addr, new_size, True); if ((flags & VKI_MREMAP_FIXED) && a != new_addr) - return -VKI_ENOMEM; /* didn't find the place we wanted */ + /* didn't find the place we wanted */ + return VG_(mk_SysRes_Error)( VKI_ENOMEM ); new_addr = a; - ret = a; /* we've nailed down the location */ - flags |= VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE; + flags |= VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE; ret = VG_(do_syscall5)(__NR_mremap, old_addr, old_size, new_size, flags, new_addr); - if (ret != new_addr) { - vg_assert(VG_(is_kerror)(ret)); + if (ret.isError) { return ret; } @@ -307,7 +238,7 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, VG_(munmap)((void *)old_addr, old_size); } else { /* staying in place */ - ret = old_addr; + ret = VG_(mk_SysRes_Success)( old_addr ); if (new_size < old_size) { VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size); @@ -323,7 +254,7 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, ret = VG_(do_syscall5)(__NR_mremap, old_addr, old_size, new_size, flags, 0); - if (ret != old_addr) + if (ret.isError || (!ret.isError && ret.val != old_addr)) return ret; VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size, @@ -343,34 +274,9 @@ Addr mremap_segment ( Addr old_addr, SizeT old_size, } -/* Is this a Linux kernel error return value? */ -/* From: - http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ - linux/i386/sysdep.h? - rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc - - \begin{quote}: - - Linux uses a negative return value to indicate syscall errors, - unlike most Unices, which use the condition codes' carry flag. - - Since version 2.1 the return value of a system call might be - negative even if the call succeeded. E.g., the 'lseek' system call - might return a large offset. Therefore we must not anymore test - for < 0, but test for a real error by making sure the value in %eax - is a real error number. Linus said he will make sure the no syscall - returns a value in -1 .. -4095 as a valid result so we can safely - test with -4095. - - END QUOTE -*/ -Bool VG_(is_kerror) ( Word res ) -{ - if (res >= -4095 && res <= -1) - return True; - else - return False; -} +/* --------------------------------------------------------------------- + File-descriptor tracking + ------------------------------------------------------------------ */ /* One of these is allocated for each open file descriptor. */ @@ -527,11 +433,9 @@ Char *inet2name(struct vki_sockaddr_in *sa, UInt len, Char *name) return name; } - /* * Try get some details about a socket. */ - static void getsockdetails(int fd) { @@ -773,8 +677,8 @@ static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg) static void pre_mem_read_sockaddr ( ThreadId tid, - Char *description, - struct vki_sockaddr *sa, UInt salen ) + Char *description, + struct vki_sockaddr *sa, UInt salen ) { Char *outmsg; @@ -858,11 +762,10 @@ void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p, } static -void buf_and_len_post_check( ThreadId tid, Int res, +void buf_and_len_post_check( ThreadId tid, SysRes res, Addr buf_p, Addr buflen_p, Char* s ) { - if (!VG_(is_kerror)(res) && VG_(tdict).track_post_mem_write) - { + if (!res.isError && VG_(tdict).track_post_mem_write) { UInt buflen_out = deref_UInt( tid, buflen_p, s); if (buflen_out > 0 && buf_p != (Addr)NULL) { VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out ); @@ -1001,13 +904,14 @@ VG_(generic_PRE_sys_socketpair) ( ThreadId tid, arg3, 2*sizeof(int) ); } -UWord +SysRes VG_(generic_POST_sys_socketpair) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2, UWord arg3 ) { - UWord r = res; + SysRes r = res; + vg_assert(!res.isError); /* guaranteed by caller */ Int fd1 = ((Int*)arg3)[0]; Int fd2 = ((Int*)arg3)[1]; POST_MEM_WRITE( arg3, 2*sizeof(int) ); @@ -1015,7 +919,7 @@ VG_(generic_POST_sys_socketpair) ( ThreadId tid, !VG_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) { VG_(close)(fd1); VG_(close)(fd2); - r = -VKI_EMFILE; + r = VG_(mk_SysRes_Error)( VKI_EMFILE ); } else { POST_MEM_WRITE( arg3, 2*sizeof(int) ); if (VG_(clo_track_fds)) { @@ -1028,16 +932,17 @@ VG_(generic_POST_sys_socketpair) ( ThreadId tid, /* ------ */ -UWord -VG_(generic_POST_sys_socket) ( ThreadId tid, UWord res ) +SysRes +VG_(generic_POST_sys_socket) ( ThreadId tid, SysRes res ) { - UWord r = res; - if (!VG_(fd_allowed)(res, "socket", tid, True)) { - VG_(close)(res); - r = -VKI_EMFILE; + SysRes r = res; + vg_assert(!res.isError); /* guaranteed by caller */ + if (!VG_(fd_allowed)(res.val, "socket", tid, True)) { + VG_(close)(res.val); + r = VG_(mk_SysRes_Error)( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, res, NULL); + VG_(record_fd_open)(tid, res.val, NULL); } return r; } @@ -1071,15 +976,16 @@ VG_(generic_PRE_sys_accept) ( ThreadId tid, "socketcall.accept(addrlen_in)" ); } -UWord +SysRes VG_(generic_POST_sys_accept) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2 ) { - UWord r = res; - if (!VG_(fd_allowed)(res, "accept", tid, True)) { - VG_(close)(res); - r = -VKI_EMFILE; + SysRes r = res; + vg_assert(!res.isError); /* guaranteed by caller */ + if (!VG_(fd_allowed)(res.val, "accept", tid, True)) { + VG_(close)(res.val); + r = VG_(mk_SysRes_Error)( VKI_EMFILE ); } else { Addr addr_p = arg1; Addr addrlen_p = arg2; @@ -1087,7 +993,7 @@ VG_(generic_POST_sys_accept) ( ThreadId tid, buf_and_len_post_check ( tid, res, addr_p, addrlen_p, "socketcall.accept(addrlen_out)" ); if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, res, NULL); + VG_(record_fd_open)(tid, res.val, NULL); } return r; } @@ -1146,7 +1052,7 @@ VG_(generic_PRE_sys_recvfrom) ( ThreadId tid, void VG_(generic_POST_sys_recvfrom) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2, UWord arg3, UWord arg4, UWord arg5 ) { @@ -1155,6 +1061,7 @@ VG_(generic_POST_sys_recvfrom) ( ThreadId tid, Addr from_p = arg4; Addr fromlen_p = arg5; + vg_assert(!res.isError); /* guaranteed by caller */ if (from_p != (Addr)NULL) buf_and_len_post_check ( tid, res, from_p, fromlen_p, "socketcall.recvfrom(fromlen_out)" ); @@ -1239,12 +1146,13 @@ VG_(generic_PRE_sys_getsockopt) ( ThreadId tid, void VG_(generic_POST_sys_getsockopt) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2, UWord arg3, UWord arg4 ) { Addr optval_p = arg3; Addr optlen_p = arg4; + vg_assert(!res.isError); /* guaranteed by caller */ if (optval_p != (Addr)NULL) buf_and_len_post_check ( tid, res, optval_p, optlen_p, "socketcall.getsockopt(optlen_out)" ); @@ -1267,11 +1175,12 @@ VG_(generic_PRE_sys_getsockname) ( ThreadId tid, void VG_(generic_POST_sys_getsockname) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2 ) { Addr name_p = arg1; Addr namelen_p = arg2; + vg_assert(!res.isError); /* guaranteed by caller */ buf_and_len_post_check ( tid, res, name_p, namelen_p, "socketcall.getsockname(namelen_out)" ); } @@ -1293,11 +1202,12 @@ VG_(generic_PRE_sys_getpeername) ( ThreadId tid, void VG_(generic_POST_sys_getpeername) ( ThreadId tid, - UWord res, + SysRes res, UWord arg0, UWord arg1, UWord arg2 ) { Addr name_p = arg1; Addr namelen_p = arg2; + vg_assert(!res.isError); /* guaranteed by caller */ buf_and_len_post_check ( tid, res, name_p, namelen_p, "socketcall.getpeername(namelen_out)" ); } @@ -1326,7 +1236,6 @@ VG_(generic_PRE_sys_recvmsg) ( ThreadId tid, void VG_(generic_POST_sys_recvmsg) ( ThreadId tid, - UWord res, UWord arg0, UWord arg1 ) { struct vki_msghdr *msg = (struct vki_msghdr *)arg1; @@ -1368,22 +1277,22 @@ VG_(generic_PRE_sys_semtimedop) ( ThreadId tid, static UInt get_sem_count( Int semid ) { - struct vki_semid_ds buf; - union vki_semun arg; - long res; + struct vki_semid_ds buf; + union vki_semun arg; + SysRes res; - arg.buf = &buf; + arg.buf = &buf; -#ifdef __NR_semctl - res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); -#else - res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, - VKI_IPC_STAT, (UWord)&arg); -#endif - if ( VG_(is_kerror)(res) ) - return 0; +# ifdef __NR_semctl + res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg); +# else + res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, + VKI_IPC_STAT, (UWord)&arg); +# endif + if (res.isError) + return 0; - return buf.sem_nsems; + return buf.sem_nsems; } void @@ -1568,15 +1477,15 @@ VG_(generic_POST_sys_msgctl) ( ThreadId tid, static UInt get_shm_size ( Int shmid ) { -#ifdef __NR_shmctl +# ifdef __NR_shmctl struct vki_shmid64_ds buf; - long __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf); -#else + SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf); +# else struct vki_shmid_ds buf; - long __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, + SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, VKI_IPC_STAT, 0, (UWord)&buf); -#endif - if ( VG_(is_kerror) ( __res ) ) +# endif + if (__res.isError) return 0; return buf.shm_segsz; @@ -1736,94 +1645,94 @@ VG_(generic_POST_sys_shmctl) ( ThreadId tid, XXX: some of these are arch-specific, and should be factored out. */ -#define PRE(name, f) PRE_TEMPLATE( , vgArch_gen, name, f) -#define POST(name) POST_TEMPLATE( , vgArch_gen, name) - -// Combine two 32-bit values into a 64-bit value -#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) +#define PRE(name) DEFN_PRE_TEMPLATE(generic, name) +#define POST(name) DEFN_POST_TEMPLATE(generic, name) -//PRE(sys_exit_group, Special) -//{ -// VG_(core_panic)("syscall exit_group() not caught by the scheduler?!"); -//} +//zz // Combine two 32-bit values into a 64-bit value +//zz #define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) +//zz +//zz //PRE(sys_exit_group, Special) +//zz //{ +//zz // VG_(core_panic)("syscall exit_group() not caught by the scheduler?!"); +//zz //} -PRE(sys_exit, Special) +PRE(sys_exit) { + ThreadState* tst; /* simple; just make this thread exit */ PRINT("exit( %d )", ARG1); PRE_REG_READ1(void, "exit", int, exitcode); + tst = VG_(get_ThreadState)(tid); + /* Set the thread's status to be exiting, then claim that the + syscall succeeded. */ tst->exitreason = VgSrc_ExitSyscall; tst->os_state.exitcode = ARG1; - /* exit doesn't return anything (it doesn't return.) - Nevertheless, if we don't do this, the result-not-assigned- - yet-you-said-you-were-Special assertion in the main syscall - handling logic will fire. Hence .. - */ - SET_RESULT(0); + SET_STATUS_Success(0); } -PRE(sys_sched_yield, MayBlock) -{ - PRINT("sched_yield()"); - PRE_REG_READ0(long, "sys_sched_yield"); -} +//zz PRE(sys_sched_yield, SfMayBlock) +//zz { +//zz PRINT("sched_yield()"); +//zz PRE_REG_READ0(long, "sys_sched_yield"); +//zz } -PRE(sys_ni_syscall, Special) +PRE(sys_ni_syscall) { PRINT("non-existent syscall! (ni_syscall)"); PRE_REG_READ0(long, "ni_syscall"); - SET_RESULT( -VKI_ENOSYS ); -} - -PRE(sys_set_tid_address, 0) -{ - PRINT("sys_set_tid_address ( %p )", ARG1); - PRE_REG_READ1(long, "set_tid_address", int *, tidptr); -} - -PRE(sys_iopl, 0) -{ - PRINT("sys_iopl ( %d )", ARG1); - PRE_REG_READ1(long, "iopl", unsigned long, level); -} - -PRE(sys_setxattr, MayBlock) -{ - PRINT("sys_setxattr ( %p, %p, %p, %llu, %d )", - ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); - PRE_REG_READ5(long, "setxattr", - char *, path, char *, name, - void *, value, vki_size_t, size, int, flags); - PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 ); - PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 ); - PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 ); -} - -PRE(sys_lsetxattr, MayBlock) -{ - PRINT("sys_lsetxattr ( %p, %p, %p, %llu, %d )", - ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); - PRE_REG_READ5(long, "lsetxattr", - char *, path, char *, name, - void *, value, vki_size_t, size, int, flags); - PRE_MEM_RASCIIZ( "lsetxattr(path)", ARG1 ); - PRE_MEM_RASCIIZ( "lsetxattr(name)", ARG2 ); - PRE_MEM_READ( "lsetxattr(value)", ARG3, ARG4 ); -} - -PRE(sys_fsetxattr, MayBlock) -{ - PRINT("sys_fsetxattr ( %d, %p, %p, %llu, %d )", - ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); - PRE_REG_READ5(long, "fsetxattr", - int, fd, char *, name, void *, value, - vki_size_t, size, int, flags); - PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 ); - PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 ); -} - -PRE(sys_getxattr, MayBlock) -{ + SET_STATUS_Failure( VKI_ENOSYS ); +} + +//zz PRE(sys_set_tid_address, 0) +//zz { +//zz PRINT("sys_set_tid_address ( %p )", ARG1); +//zz PRE_REG_READ1(long, "set_tid_address", int *, tidptr); +//zz } +//zz +//zz PRE(sys_iopl, 0) +//zz { +//zz PRINT("sys_iopl ( %d )", ARG1); +//zz PRE_REG_READ1(long, "iopl", unsigned long, level); +//zz } +//zz +//zz PRE(sys_setxattr, SfMayBlock) +//zz { +//zz PRINT("sys_setxattr ( %p, %p, %p, %llu, %d )", +//zz ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); +//zz PRE_REG_READ5(long, "setxattr", +//zz char *, path, char *, name, +//zz void *, value, vki_size_t, size, int, flags); +//zz PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 ); +//zz PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 ); +//zz } +//zz +//zz PRE(sys_lsetxattr, SfMayBlock) +//zz { +//zz PRINT("sys_lsetxattr ( %p, %p, %p, %llu, %d )", +//zz ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); +//zz PRE_REG_READ5(long, "lsetxattr", +//zz char *, path, char *, name, +//zz void *, value, vki_size_t, size, int, flags); +//zz PRE_MEM_RASCIIZ( "lsetxattr(path)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "lsetxattr(name)", ARG2 ); +//zz PRE_MEM_READ( "lsetxattr(value)", ARG3, ARG4 ); +//zz } +//zz +//zz PRE(sys_fsetxattr, SfMayBlock) +//zz { +//zz PRINT("sys_fsetxattr ( %d, %p, %p, %llu, %d )", +//zz ARG1, ARG2, ARG3, (ULong)ARG4, ARG5); +//zz PRE_REG_READ5(long, "fsetxattr", +//zz int, fd, char *, name, void *, value, +//zz vki_size_t, size, int, flags); +//zz PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 ); +//zz PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 ); +//zz } + +PRE(sys_getxattr) +{ + *flags |= SfMayBlock; PRINT("sys_getxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4); PRE_REG_READ4(ssize_t, "getxattr", char *, path, char *, name, void *, value, vki_size_t, size); @@ -1834,266 +1743,268 @@ PRE(sys_getxattr, MayBlock) POST(sys_getxattr) { + vg_assert(SUCCESS); if (RES > 0 && ARG3 != (Addr)NULL) { POST_MEM_WRITE( ARG3, RES ); } } -PRE(sys_lgetxattr, MayBlock) -{ - PRINT("sys_lgetxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4); - PRE_REG_READ4(ssize_t, "lgetxattr", - char *, path, char *, name, void *, value, vki_size_t, size); - PRE_MEM_RASCIIZ( "lgetxattr(path)", ARG1 ); - PRE_MEM_RASCIIZ( "lgetxattr(name)", ARG2 ); - PRE_MEM_WRITE( "lgetxattr(value)", ARG3, ARG4 ); -} - -POST(sys_lgetxattr) -{ - if (RES > 0 && ARG3 != (Addr)NULL) { - POST_MEM_WRITE( ARG3, RES ); - } -} - -PRE(sys_fgetxattr, MayBlock) -{ - PRINT("sys_fgetxattr ( %d, %p, %p, %llu )", ARG1, ARG2, ARG3, (ULong)ARG4); - PRE_REG_READ4(ssize_t, "fgetxattr", - int, fd, char *, name, void *, value, vki_size_t, size); - PRE_MEM_RASCIIZ( "fgetxattr(name)", ARG2 ); - PRE_MEM_WRITE( "fgetxattr(value)", ARG3, ARG4 ); -} - -POST(sys_fgetxattr) -{ - if (RES > 0 && ARG3 != (Addr)NULL) - POST_MEM_WRITE( ARG3, RES ); -} - -PRE(sys_listxattr, MayBlock) -{ - PRINT("sys_listxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); - PRE_REG_READ3(ssize_t, "listxattr", - char *, path, char *, list, vki_size_t, size); - PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 ); - PRE_MEM_WRITE( "listxattr(list)", ARG2, ARG3 ); -} - -POST(sys_listxattr) -{ - if (RES > 0 && ARG2 != (Addr)NULL) - POST_MEM_WRITE( ARG2, RES ); -} - -PRE(sys_llistxattr, MayBlock) -{ - PRINT("sys_llistxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); - PRE_REG_READ3(ssize_t, "llistxattr", - char *, path, char *, list, vki_size_t, size); - PRE_MEM_RASCIIZ( "llistxattr(path)", ARG1 ); - PRE_MEM_WRITE( "llistxattr(list)", ARG2, ARG3 ); -} - -POST(sys_llistxattr) -{ - if (RES > 0 && ARG2 != (Addr)NULL) - POST_MEM_WRITE( ARG2, RES ); -} - -PRE(sys_flistxattr, MayBlock) -{ - PRINT("sys_flistxattr ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3); - PRE_REG_READ3(ssize_t, "flistxattr", - int, fd, char *, list, vki_size_t, size); - PRE_MEM_WRITE( "flistxattr(list)", ARG2, ARG3 ); -} - -POST(sys_flistxattr) -{ - if (RES > 0 && ARG2 != (Addr)NULL) - POST_MEM_WRITE( ARG2, RES ); -} - -PRE(sys_removexattr, MayBlock) -{ - PRINT("sys_removexattr ( %p, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "removexattr", char *, path, char *, name); - PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 ); - PRE_MEM_RASCIIZ( "removexattr(name)", ARG2 ); -} - -PRE(sys_lremovexattr, MayBlock) -{ - PRINT("sys_lremovexattr ( %p, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "lremovexattr", char *, path, char *, name); - PRE_MEM_RASCIIZ( "lremovexattr(path)", ARG1 ); - PRE_MEM_RASCIIZ( "lremovexattr(name)", ARG2 ); -} - -PRE(sys_fremovexattr, MayBlock) -{ - PRINT("sys_fremovexattr ( %d, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "fremovexattr", int, fd, char *, name); - PRE_MEM_RASCIIZ( "fremovexattr(name)", ARG2 ); -} - -PRE(sys_quotactl, 0) -{ - PRINT("sys_quotactl (0x%x, %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3, ARG4); - PRE_REG_READ4(long, "quotactl", - unsigned int, cmd, const char *, special, vki_qid_t, id, - void *, addr); - PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 ); -} - -// XXX: this wrapper is only suitable for 32-bit platforms -PRE(sys_lookup_dcookie, 0) -{ - PRINT("sys_lookup_dcookie (0x%llx, %p, %d)", LOHI64(ARG1,ARG2), ARG3, ARG4); - PRE_REG_READ4(long, "lookup_dcookie", - vki_u32, cookie_low32, vki_u32, cookie_high32, - char *, buf, vki_size_t, len); - PRE_MEM_WRITE( "lookup_dcookie(buf)", ARG3, ARG4); -} - -POST(sys_lookup_dcookie) -{ - if (ARG3 != (Addr)NULL) - POST_MEM_WRITE( ARG3, RES); -} - -PRE(sys_fsync, MayBlock) -{ - PRINT("sys_fsync ( %d )", ARG1); - PRE_REG_READ1(long, "fsync", unsigned int, fd); -} - -PRE(sys_fdatasync, MayBlock) -{ - PRINT("sys_fdatasync ( %d )", ARG1); - PRE_REG_READ1(long, "fdatasync", unsigned int, fd); -} - -PRE(sys_msync, MayBlock) -{ - PRINT("sys_msync ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3); - PRE_REG_READ3(long, "msync", - unsigned long, start, vki_size_t, length, int, flags); - PRE_MEM_READ( "msync(start)", ARG1, ARG2 ); -} - -// Nb: getpmsg() and putpmsg() are special additional syscalls used in early -// versions of LiS (Linux Streams). They are not part of the kernel. -// Therefore, we have to provide this type ourself, rather than getting it -// from the kernel sources. -struct vki_pmsg_strbuf { - int maxlen; /* no. of bytes in buffer */ - int len; /* no. of bytes returned */ - vki_caddr_t buf; /* pointer to data */ -}; - -PRE(sys_getpmsg, MayBlock) -{ - /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */ - struct vki_pmsg_strbuf *ctrl; - struct vki_pmsg_strbuf *data; - PRINT("sys_getpmsg ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); - PRE_REG_READ5(int, "getpmsg", - int, fd, struct strbuf *, ctrl, struct strbuf *, data, - int *, bandp, int *, flagsp); - ctrl = (struct vki_pmsg_strbuf *)ARG2; - data = (struct vki_pmsg_strbuf *)ARG3; - if (ctrl && ctrl->maxlen > 0) - PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen); - if (data && data->maxlen > 0) - PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen); - if (ARG4) - PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int)); - if (ARG5) - PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int)); -} - -POST(sys_getpmsg) -{ - struct vki_pmsg_strbuf *ctrl; - struct vki_pmsg_strbuf *data; - - ctrl = (struct vki_pmsg_strbuf *)ARG2; - data = (struct vki_pmsg_strbuf *)ARG3; - if (RES == 0 && ctrl && ctrl->len > 0) { - POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len); - } - if (RES == 0 && data && data->len > 0) { - POST_MEM_WRITE( (Addr)data->buf, data->len); - } -} - -PRE(sys_putpmsg, MayBlock) -{ - /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */ - struct vki_pmsg_strbuf *ctrl; - struct vki_pmsg_strbuf *data; - PRINT("sys_putpmsg ( %d, %p, %p, %d, %d )", ARG1,ARG2,ARG3,ARG4,ARG5); - PRE_REG_READ5(int, "putpmsg", - int, fd, struct strbuf *, ctrl, struct strbuf *, data, - int, band, int, flags); - ctrl = (struct vki_pmsg_strbuf *)ARG2; - data = (struct vki_pmsg_strbuf *)ARG3; - if (ctrl && ctrl->len > 0) - PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len); - if (data && data->len > 0) - PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len); -} - -PRE(sys_getitimer, 0) -{ - PRINT("sys_getitimer ( %d, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value); - PRE_MEM_WRITE( "getitimer(value)", ARG2, sizeof(struct vki_itimerval) ); -} - -POST(sys_getitimer) -{ - if (ARG2 != (Addr)NULL) { - POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerval)); - } -} - -PRE(sys_setitimer, 0) -{ - PRINT("sys_setitimer ( %d, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "setitimer", - int, which, - struct itimerval *, value, struct itimerval *, ovalue); - if (ARG2 != (Addr)NULL) - PRE_MEM_READ( "setitimer(value)", ARG2, sizeof(struct vki_itimerval) ); - if (ARG3 != (Addr)NULL) - PRE_MEM_WRITE( "setitimer(ovalue)", ARG3, sizeof(struct vki_itimerval)); -} - -POST(sys_setitimer) -{ - if (ARG3 != (Addr)NULL) { - POST_MEM_WRITE(ARG3, sizeof(struct vki_itimerval)); - } -} - -PRE(sys_chroot, 0) -{ - PRINT("sys_chroot ( %p )", ARG1); - PRE_REG_READ1(long, "chroot", const char *, path); - PRE_MEM_RASCIIZ( "chroot(path)", ARG1 ); -} - -PRE(sys_madvise, MayBlock) -{ +//zz PRE(sys_lgetxattr, SfMayBlock) +//zz { +//zz PRINT("sys_lgetxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4); +//zz PRE_REG_READ4(ssize_t, "lgetxattr", +//zz char *, path, char *, name, void *, value, vki_size_t, size); +//zz PRE_MEM_RASCIIZ( "lgetxattr(path)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "lgetxattr(name)", ARG2 ); +//zz PRE_MEM_WRITE( "lgetxattr(value)", ARG3, ARG4 ); +//zz } +//zz +//zz POST(sys_lgetxattr) +//zz { +//zz if (RES > 0 && ARG3 != (Addr)NULL) { +//zz POST_MEM_WRITE( ARG3, RES ); +//zz } +//zz } +//zz +//zz PRE(sys_fgetxattr, SfMayBlock) +//zz { +//zz PRINT("sys_fgetxattr ( %d, %p, %p, %llu )", ARG1, ARG2, ARG3, (ULong)ARG4); +//zz PRE_REG_READ4(ssize_t, "fgetxattr", +//zz int, fd, char *, name, void *, value, vki_size_t, size); +//zz PRE_MEM_RASCIIZ( "fgetxattr(name)", ARG2 ); +//zz PRE_MEM_WRITE( "fgetxattr(value)", ARG3, ARG4 ); +//zz } +//zz +//zz POST(sys_fgetxattr) +//zz { +//zz if (RES > 0 && ARG3 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG3, RES ); +//zz } +//zz +//zz PRE(sys_listxattr, SfMayBlock) +//zz { +//zz PRINT("sys_listxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); +//zz PRE_REG_READ3(ssize_t, "listxattr", +//zz char *, path, char *, list, vki_size_t, size); +//zz PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 ); +//zz PRE_MEM_WRITE( "listxattr(list)", ARG2, ARG3 ); +//zz } +//zz +//zz POST(sys_listxattr) +//zz { +//zz if (RES > 0 && ARG2 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG2, RES ); +//zz } +//zz +//zz PRE(sys_llistxattr, SfMayBlock) +//zz { +//zz PRINT("sys_llistxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3); +//zz PRE_REG_READ3(ssize_t, "llistxattr", +//zz char *, path, char *, list, vki_size_t, size); +//zz PRE_MEM_RASCIIZ( "llistxattr(path)", ARG1 ); +//zz PRE_MEM_WRITE( "llistxattr(list)", ARG2, ARG3 ); +//zz } +//zz +//zz POST(sys_llistxattr) +//zz { +//zz if (RES > 0 && ARG2 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG2, RES ); +//zz } +//zz +//zz PRE(sys_flistxattr, SfMayBlock) +//zz { +//zz PRINT("sys_flistxattr ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3); +//zz PRE_REG_READ3(ssize_t, "flistxattr", +//zz int, fd, char *, list, vki_size_t, size); +//zz PRE_MEM_WRITE( "flistxattr(list)", ARG2, ARG3 ); +//zz } +//zz +//zz POST(sys_flistxattr) +//zz { +//zz if (RES > 0 && ARG2 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG2, RES ); +//zz } +//zz +//zz PRE(sys_removexattr, SfMayBlock) +//zz { +//zz PRINT("sys_removexattr ( %p, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "removexattr", char *, path, char *, name); +//zz PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "removexattr(name)", ARG2 ); +//zz } +//zz +//zz PRE(sys_lremovexattr, SfMayBlock) +//zz { +//zz PRINT("sys_lremovexattr ( %p, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "lremovexattr", char *, path, char *, name); +//zz PRE_MEM_RASCIIZ( "lremovexattr(path)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "lremovexattr(name)", ARG2 ); +//zz } +//zz +//zz PRE(sys_fremovexattr, SfMayBlock) +//zz { +//zz PRINT("sys_fremovexattr ( %d, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "fremovexattr", int, fd, char *, name); +//zz PRE_MEM_RASCIIZ( "fremovexattr(name)", ARG2 ); +//zz } +//zz +//zz PRE(sys_quotactl, 0) +//zz { +//zz PRINT("sys_quotactl (0x%x, %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3, ARG4); +//zz PRE_REG_READ4(long, "quotactl", +//zz unsigned int, cmd, const char *, special, vki_qid_t, id, +//zz void *, addr); +//zz PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 ); +//zz } +//zz +//zz // XXX: this wrapper is only suitable for 32-bit platforms +//zz PRE(sys_lookup_dcookie, 0) +//zz { +//zz PRINT("sys_lookup_dcookie (0x%llx, %p, %d)", LOHI64(ARG1,ARG2), ARG3, ARG4); +//zz PRE_REG_READ4(long, "lookup_dcookie", +//zz vki_u32, cookie_low32, vki_u32, cookie_high32, +//zz char *, buf, vki_size_t, len); +//zz PRE_MEM_WRITE( "lookup_dcookie(buf)", ARG3, ARG4); +//zz } +//zz +//zz POST(sys_lookup_dcookie) +//zz { +//zz if (ARG3 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG3, RES); +//zz } +//zz +//zz PRE(sys_fsync, SfMayBlock) +//zz { +//zz PRINT("sys_fsync ( %d )", ARG1); +//zz PRE_REG_READ1(long, "fsync", unsigned int, fd); +//zz } +//zz +//zz PRE(sys_fdatasync, SfMayBlock) +//zz { +//zz PRINT("sys_fdatasync ( %d )", ARG1); +//zz PRE_REG_READ1(long, "fdatasync", unsigned int, fd); +//zz } +//zz +//zz PRE(sys_msync, SfMayBlock) +//zz { +//zz PRINT("sys_msync ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3); +//zz PRE_REG_READ3(long, "msync", +//zz unsigned long, start, vki_size_t, length, int, flags); +//zz PRE_MEM_READ( "msync(start)", ARG1, ARG2 ); +//zz } +//zz +//zz // Nb: getpmsg() and putpmsg() are special additional syscalls used in early +//zz // versions of LiS (Linux Streams). They are not part of the kernel. +//zz // Therefore, we have to provide this type ourself, rather than getting it +//zz // from the kernel sources. +//zz struct vki_pmsg_strbuf { +//zz int maxlen; /* no. of bytes in buffer */ +//zz int len; /* no. of bytes returned */ +//zz vki_caddr_t buf; /* pointer to data */ +//zz }; +//zz +//zz PRE(sys_getpmsg, SfMayBlock) +//zz { +//zz /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */ +//zz struct vki_pmsg_strbuf *ctrl; +//zz struct vki_pmsg_strbuf *data; +//zz PRINT("sys_getpmsg ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); +//zz PRE_REG_READ5(int, "getpmsg", +//zz int, fd, struct strbuf *, ctrl, struct strbuf *, data, +//zz int *, bandp, int *, flagsp); +//zz ctrl = (struct vki_pmsg_strbuf *)ARG2; +//zz data = (struct vki_pmsg_strbuf *)ARG3; +//zz if (ctrl && ctrl->maxlen > 0) +//zz PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen); +//zz if (data && data->maxlen > 0) +//zz PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen); +//zz if (ARG4) +//zz PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int)); +//zz if (ARG5) +//zz PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int)); +//zz } +//zz +//zz POST(sys_getpmsg) +//zz { +//zz struct vki_pmsg_strbuf *ctrl; +//zz struct vki_pmsg_strbuf *data; +//zz +//zz ctrl = (struct vki_pmsg_strbuf *)ARG2; +//zz data = (struct vki_pmsg_strbuf *)ARG3; +//zz if (RES == 0 && ctrl && ctrl->len > 0) { +//zz POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len); +//zz } +//zz if (RES == 0 && data && data->len > 0) { +//zz POST_MEM_WRITE( (Addr)data->buf, data->len); +//zz } +//zz } +//zz +//zz PRE(sys_putpmsg, SfMayBlock) +//zz { +//zz /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */ +//zz struct vki_pmsg_strbuf *ctrl; +//zz struct vki_pmsg_strbuf *data; +//zz PRINT("sys_putpmsg ( %d, %p, %p, %d, %d )", ARG1,ARG2,ARG3,ARG4,ARG5); +//zz PRE_REG_READ5(int, "putpmsg", +//zz int, fd, struct strbuf *, ctrl, struct strbuf *, data, +//zz int, band, int, flags); +//zz ctrl = (struct vki_pmsg_strbuf *)ARG2; +//zz data = (struct vki_pmsg_strbuf *)ARG3; +//zz if (ctrl && ctrl->len > 0) +//zz PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len); +//zz if (data && data->len > 0) +//zz PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len); +//zz } +//zz +//zz PRE(sys_getitimer, 0) +//zz { +//zz PRINT("sys_getitimer ( %d, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value); +//zz PRE_MEM_WRITE( "getitimer(value)", ARG2, sizeof(struct vki_itimerval) ); +//zz } +//zz +//zz POST(sys_getitimer) +//zz { +//zz if (ARG2 != (Addr)NULL) { +//zz POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerval)); +//zz } +//zz } +//zz +//zz PRE(sys_setitimer, 0) +//zz { +//zz PRINT("sys_setitimer ( %d, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "setitimer", +//zz int, which, +//zz struct itimerval *, value, struct itimerval *, ovalue); +//zz if (ARG2 != (Addr)NULL) +//zz PRE_MEM_READ( "setitimer(value)", ARG2, sizeof(struct vki_itimerval) ); +//zz if (ARG3 != (Addr)NULL) +//zz PRE_MEM_WRITE( "setitimer(ovalue)", ARG3, sizeof(struct vki_itimerval)); +//zz } +//zz +//zz POST(sys_setitimer) +//zz { +//zz if (ARG3 != (Addr)NULL) { +//zz POST_MEM_WRITE(ARG3, sizeof(struct vki_itimerval)); +//zz } +//zz } +//zz +//zz PRE(sys_chroot, 0) +//zz { +//zz PRINT("sys_chroot ( %p )", ARG1); +//zz PRE_REG_READ1(long, "chroot", const char *, path); +//zz PRE_MEM_RASCIIZ( "chroot(path)", ARG1 ); +//zz } + +PRE(sys_madvise) +{ + *flags |= SfMayBlock; PRINT("sys_madvise ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3); PRE_REG_READ3(long, "madvise", unsigned long, start, vki_size_t, length, int, advice); } -PRE(sys_mremap, Special) +PRE(sys_mremap) { // Nb: this is different to the glibc version described in the man pages, // which lacks the fifth 'new_address' argument. @@ -2103,153 +2014,155 @@ PRE(sys_mremap, Special) unsigned long, old_addr, unsigned long, old_size, unsigned long, new_size, unsigned long, flags, unsigned long, new_addr); - SET_RESULT( mremap_segment((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid) ); -} - -PRE(sys_nice, 0) -{ - PRINT("sys_nice ( %d )", ARG1); - PRE_REG_READ1(long, "nice", int, inc); -} - -PRE(sys_sched_getscheduler, 0) -{ - PRINT("sys_sched_getscheduler ( %d )", ARG1); - PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid); -} - -PRE(sys_sched_setscheduler, 0) -{ - PRINT("sys_sched_setscheduler ( %d, %d, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "sched_setscheduler", - vki_pid_t, pid, int, policy, struct sched_param *, p); - if (ARG3 != 0) - PRE_MEM_READ( "sched_setscheduler(p)", - ARG3, sizeof(struct vki_sched_param)); -} - -PRE(sys_mlock, MayBlock) -{ - PRINT("sys_mlock ( %p, %llu )", ARG1, (ULong)ARG2); - PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len); -} - -PRE(sys_munlock, MayBlock) -{ - PRINT("sys_munlock ( %p, %llu )", ARG1, (ULong)ARG2); - PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len); -} - -PRE(sys_mlockall, MayBlock) -{ - PRINT("sys_mlockall ( %x )", ARG1); - PRE_REG_READ1(long, "mlockall", int, flags); -} - -PRE(sys_munlockall, MayBlock) -{ - PRINT("sys_munlockall ( )"); - PRE_REG_READ0(long, "munlockall"); -} - -PRE(sys_sched_get_priority_max, 0) -{ - PRINT("sched_get_priority_max ( %d )", ARG1); - PRE_REG_READ1(long, "sched_get_priority_max", int, policy); -} - -PRE(sys_sched_get_priority_min, 0) -{ - PRINT("sched_get_priority_min ( %d )", ARG1); - PRE_REG_READ1(long, "sched_get_priority_min", int, policy); -} - -PRE(sys_setpriority, 0) -{ - PRINT("sys_setpriority ( %d, %d, %d )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio); -} - -PRE(sys_getpriority, 0) -{ - PRINT("sys_getpriority ( %d, %d )", ARG1, ARG2); - PRE_REG_READ2(long, "getpriority", int, which, int, who); -} - -PRE(sys_setregid16, 0) -{ - PRINT("sys_setregid16 ( %d, %d )", ARG1, ARG2); - PRE_REG_READ2(long, "setregid16", vki_old_gid_t, rgid, vki_old_gid_t, egid); -} - -// XXX: only for 32-bit archs -PRE(sys_pwrite64, MayBlock) -{ - PRINT("sys_pwrite64 ( %d, %p, %llu, %lld )", - ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5)); - PRE_REG_READ5(ssize_t, "pwrite64", - unsigned int, fd, const char *, buf, vki_size_t, count, - vki_u32, offset_low32, vki_u32, offset_high32); - PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 ); -} - -PRE(sys_sync, MayBlock) -{ - PRINT("sys_sync ( )"); - PRE_REG_READ0(long, "sync"); -} - -PRE(sys_fstatfs, 0) -{ - PRINT("sys_fstatfs ( %d, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "fstatfs", - unsigned int, fd, struct statfs *, buf); - PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) ); -} - -POST(sys_fstatfs) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); -} - -PRE(sys_fstatfs64, 0) -{ - PRINT("sys_fstatfs64 ( %d, %llu, %p )",ARG1,(ULong)ARG2,ARG3); - PRE_REG_READ3(long, "fstatfs64", - unsigned int, fd, vki_size_t, size, struct statfs64 *, buf); - PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 ); -} - -POST(sys_fstatfs64) -{ - POST_MEM_WRITE( ARG3, ARG2 ); -} - -PRE(sys_getsid, 0) -{ - PRINT("sys_getsid ( %d )", ARG1); - PRE_REG_READ1(long, "getsid", vki_pid_t, pid); -} - -// XXX: only for 32-bit archs -PRE(sys_pread64, MayBlock) -{ - PRINT("sys_pread64 ( %d, %p, %llu, %lld )", - ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5)); - PRE_REG_READ5(ssize_t, "pread64", - unsigned int, fd, char *, buf, vki_size_t, count, - vki_u32, offset_low32, vki_u32, offset_high32); - PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 ); -} - -POST(sys_pread64) -{ - if (RES > 0) { - POST_MEM_WRITE( ARG2, RES ); - } + SET_STATUS_from_SysRes( + mremap_segment((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid) + ); } -PRE(sys_mknod, 0) +//zz PRE(sys_nice, 0) +//zz { +//zz PRINT("sys_nice ( %d )", ARG1); +//zz PRE_REG_READ1(long, "nice", int, inc); +//zz } +//zz +//zz PRE(sys_sched_getscheduler, 0) +//zz { +//zz PRINT("sys_sched_getscheduler ( %d )", ARG1); +//zz PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid); +//zz } +//zz +//zz PRE(sys_sched_setscheduler, 0) +//zz { +//zz PRINT("sys_sched_setscheduler ( %d, %d, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "sched_setscheduler", +//zz vki_pid_t, pid, int, policy, struct sched_param *, p); +//zz if (ARG3 != 0) +//zz PRE_MEM_READ( "sched_setscheduler(p)", +//zz ARG3, sizeof(struct vki_sched_param)); +//zz } +//zz +//zz PRE(sys_mlock, SfMayBlock) +//zz { +//zz PRINT("sys_mlock ( %p, %llu )", ARG1, (ULong)ARG2); +//zz PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len); +//zz } +//zz +//zz PRE(sys_munlock, SfMayBlock) +//zz { +//zz PRINT("sys_munlock ( %p, %llu )", ARG1, (ULong)ARG2); +//zz PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len); +//zz } +//zz +//zz PRE(sys_mlockall, SfMayBlock) +//zz { +//zz PRINT("sys_mlockall ( %x )", ARG1); +//zz PRE_REG_READ1(long, "mlockall", int, flags); +//zz } +//zz +//zz PRE(sys_munlockall, SfMayBlock) +//zz { +//zz PRINT("sys_munlockall ( )"); +//zz PRE_REG_READ0(long, "munlockall"); +//zz } +//zz +//zz PRE(sys_sched_get_priority_max, 0) +//zz { +//zz PRINT("sched_get_priority_max ( %d )", ARG1); +//zz PRE_REG_READ1(long, "sched_get_priority_max", int, policy); +//zz } +//zz +//zz PRE(sys_sched_get_priority_min, 0) +//zz { +//zz PRINT("sched_get_priority_min ( %d )", ARG1); +//zz PRE_REG_READ1(long, "sched_get_priority_min", int, policy); +//zz } +//zz +//zz PRE(sys_setpriority, 0) +//zz { +//zz PRINT("sys_setpriority ( %d, %d, %d )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio); +//zz } +//zz +//zz PRE(sys_getpriority, 0) +//zz { +//zz PRINT("sys_getpriority ( %d, %d )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "getpriority", int, which, int, who); +//zz } +//zz +//zz PRE(sys_setregid16, 0) +//zz { +//zz PRINT("sys_setregid16 ( %d, %d )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "setregid16", vki_old_gid_t, rgid, vki_old_gid_t, egid); +//zz } +//zz +//zz // XXX: only for 32-bit archs +//zz PRE(sys_pwrite64, SfMayBlock) +//zz { +//zz PRINT("sys_pwrite64 ( %d, %p, %llu, %lld )", +//zz ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5)); +//zz PRE_REG_READ5(ssize_t, "pwrite64", +//zz unsigned int, fd, const char *, buf, vki_size_t, count, +//zz vki_u32, offset_low32, vki_u32, offset_high32); +//zz PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 ); +//zz } +//zz +//zz PRE(sys_sync, SfMayBlock) +//zz { +//zz PRINT("sys_sync ( )"); +//zz PRE_REG_READ0(long, "sync"); +//zz } +//zz +//zz PRE(sys_fstatfs, 0) +//zz { +//zz PRINT("sys_fstatfs ( %d, %p )",ARG1,ARG2); +//zz PRE_REG_READ2(long, "fstatfs", +//zz unsigned int, fd, struct statfs *, buf); +//zz PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) ); +//zz } +//zz +//zz POST(sys_fstatfs) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); +//zz } +//zz +//zz PRE(sys_fstatfs64, 0) +//zz { +//zz PRINT("sys_fstatfs64 ( %d, %llu, %p )",ARG1,(ULong)ARG2,ARG3); +//zz PRE_REG_READ3(long, "fstatfs64", +//zz unsigned int, fd, vki_size_t, size, struct statfs64 *, buf); +//zz PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 ); +//zz } +//zz +//zz POST(sys_fstatfs64) +//zz { +//zz POST_MEM_WRITE( ARG3, ARG2 ); +//zz } +//zz +//zz PRE(sys_getsid, 0) +//zz { +//zz PRINT("sys_getsid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "getsid", vki_pid_t, pid); +//zz } +//zz +//zz // XXX: only for 32-bit archs +//zz PRE(sys_pread64, SfMayBlock) +//zz { +//zz PRINT("sys_pread64 ( %d, %p, %llu, %lld )", +//zz ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5)); +//zz PRE_REG_READ5(ssize_t, "pread64", +//zz unsigned int, fd, char *, buf, vki_size_t, count, +//zz vki_u32, offset_low32, vki_u32, offset_high32); +//zz PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 ); +//zz } +//zz +//zz POST(sys_pread64) +//zz { +//zz if (RES > 0) { +//zz POST_MEM_WRITE( ARG2, RES ); +//zz } +//zz } + +PRE(sys_mknod) { PRINT("sys_mknod ( %p, 0x%x, 0x%x )", ARG1, ARG2, ARG3 ); PRE_REG_READ3(long, "mknod", @@ -2257,49 +2170,49 @@ PRE(sys_mknod, 0) PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 ); } -PRE(sys_flock, MayBlock) -{ - PRINT("sys_flock ( %d, %d )", ARG1, ARG2 ); - PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation); -} - -PRE(sys_init_module, MayBlock) -{ - PRINT("sys_init_module ( %p, %llu, %p )", ARG1, (ULong)ARG2, ARG3 ); - PRE_REG_READ3(long, "init_module", - void *, umod, unsigned long, len, const char *, uargs); - PRE_MEM_READ( "init_module(umod)", ARG1, ARG2 ); - PRE_MEM_RASCIIZ( "init_module(uargs)", ARG3 ); -} - -PRE(sys_capget, 0) -{ - PRINT("sys_capget ( %p, %p )", ARG1, ARG2 ); - PRE_REG_READ2(long, "capget", - vki_cap_user_header_t, header, vki_cap_user_data_t, data); - PRE_MEM_READ( "capget(header)", ARG1, - sizeof(struct __vki_user_cap_header_struct) ); - PRE_MEM_WRITE( "capget(data)", ARG2, - sizeof(struct __vki_user_cap_data_struct) ); -} - -POST(sys_capget) -{ - if (ARG2 != (Addr)NULL) - POST_MEM_WRITE( ARG2, sizeof(struct __vki_user_cap_data_struct) ); -} - -PRE(sys_capset, 0) -{ - PRINT("sys_capset ( %p, %p )", ARG1, ARG2 ); - PRE_REG_READ2(long, "capset", - vki_cap_user_header_t, header, - const vki_cap_user_data_t, data); - PRE_MEM_READ( "capset(header)", - ARG1, sizeof(struct __vki_user_cap_header_struct) ); - PRE_MEM_READ( "capset(data)", - ARG2, sizeof(struct __vki_user_cap_data_struct) ); -} +//zz PRE(sys_flock, SfMayBlock) +//zz { +//zz PRINT("sys_flock ( %d, %d )", ARG1, ARG2 ); +//zz PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation); +//zz } +//zz +//zz PRE(sys_init_module, SfMayBlock) +//zz { +//zz PRINT("sys_init_module ( %p, %llu, %p )", ARG1, (ULong)ARG2, ARG3 ); +//zz PRE_REG_READ3(long, "init_module", +//zz void *, umod, unsigned long, len, const char *, uargs); +//zz PRE_MEM_READ( "init_module(umod)", ARG1, ARG2 ); +//zz PRE_MEM_RASCIIZ( "init_module(uargs)", ARG3 ); +//zz } +//zz +//zz PRE(sys_capget, 0) +//zz { +//zz PRINT("sys_capget ( %p, %p )", ARG1, ARG2 ); +//zz PRE_REG_READ2(long, "capget", +//zz vki_cap_user_header_t, header, vki_cap_user_data_t, data); +//zz PRE_MEM_READ( "capget(header)", ARG1, +//zz sizeof(struct __vki_user_cap_header_struct) ); +//zz PRE_MEM_WRITE( "capget(data)", ARG2, +//zz sizeof(struct __vki_user_cap_data_struct) ); +//zz } +//zz +//zz POST(sys_capget) +//zz { +//zz if (ARG2 != (Addr)NULL) +//zz POST_MEM_WRITE( ARG2, sizeof(struct __vki_user_cap_data_struct) ); +//zz } +//zz +//zz PRE(sys_capset, 0) +//zz { +//zz PRINT("sys_capset ( %p, %p )", ARG1, ARG2 ); +//zz PRE_REG_READ2(long, "capset", +//zz vki_cap_user_header_t, header, +//zz const vki_cap_user_data_t, data); +//zz PRE_MEM_READ( "capset(header)", +//zz ARG1, sizeof(struct __vki_user_cap_header_struct) ); +//zz PRE_MEM_READ( "capset(data)", +//zz ARG2, sizeof(struct __vki_user_cap_data_struct) ); +//zz } // Pre_read a char** argument. static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2) @@ -2318,9 +2231,10 @@ static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2) // XXX: prototype here seemingly doesn't match the prototype for i386-linux, // but it seems to work nonetheless... -PRE(sys_execve, Special) +PRE(sys_execve) { - Char *path; /* path to executable */ + Char* path; /* path to executable */ + ThreadState* tst; PRINT("sys_execve ( %p(%s), %p, %p )", ARG1, ARG1, ARG2, ARG3); PRE_REG_READ3(vki_off_t, "execve", @@ -2333,6 +2247,9 @@ PRE(sys_execve, Special) path = (Char *)ARG1; + vg_assert(VG_(is_valid_tid)(tid)); + tst = VG_(get_ThreadState)(tid); + /* Erk. If the exec fails, then the following will have made a mess of things which makes it hard for us to continue. The right thing to do is piece everything together again in @@ -2341,17 +2258,18 @@ PRE(sys_execve, Special) exec. */ { struct vki_stat st; - Int ret = VG_(stat)((Char *)ARG1, &st); + Int i = VG_(stat)((Char *)ARG1, &st); - if (ret < 0) { - SET_RESULT( ret ); + if (i == -1) { + /* stat failed */ + SET_STATUS_Failure( VKI_EACCES/*really, we should copy stat's result*/ ); return; } /* just look for regular file with any X bit set XXX do proper permissions check? */ if ((st.st_mode & 0100111) == 0100000) { - SET_RESULT( -VKI_EACCES ); + SET_STATUS_Failure( VKI_EACCES ); return; } } @@ -2439,7 +2357,9 @@ PRE(sys_execve, Special) VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL); } - SET_RESULT( VG_(do_syscall3)(__NR_execve, (UWord)path, ARG2, ARG3) ); + SET_STATUS_from_SysRes( + VG_(do_syscall3)(__NR_execve, (UWord)path, ARG2, ARG3) + ); /* If we got here, then the execve failed. We've already made too much of a mess of ourselves to continue, so we have to abort. */ @@ -2447,27 +2367,28 @@ PRE(sys_execve, Special) ARG1, ARG1, ARG2, ARG3, -RES); VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from " "execve() failing, so I'm dying."); - VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(execve), " + VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), " "or work out how to recover."); VG_(exit)(101); } -PRE(sys_access, 0) +PRE(sys_access) { PRINT("sys_access ( %p(%s), %d )", ARG1,ARG1,ARG2); PRE_REG_READ2(long, "access", const char *, pathname, int, mode); PRE_MEM_RASCIIZ( "access(pathname)", ARG1 ); } -PRE(sys_alarm, 0) +PRE(sys_alarm) { PRINT("sys_alarm ( %d )", ARG1); PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds); } -PRE(sys_brk, Special) +PRE(sys_brk) { Addr brk_limit = VG_(brk_limit); + Addr brk_new; /* libc says: int brk(void *end_data_segment); kernel says: void* brk(void* end_data_segment); (more or less) @@ -2487,74 +2408,75 @@ PRE(sys_brk, Special) PRINT("sys_brk ( %p )", ARG1); PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment); - SET_RESULT( do_brk(ARG1) ); + brk_new = do_brk(ARG1); + SET_STATUS_Success( brk_new ); - if (RES == ARG1) { + if (brk_new == ARG1) { /* brk() succeeded */ - if (RES < brk_limit) { + if (brk_new < brk_limit) { /* successfully shrunk the data segment. */ VG_TRACK( die_mem_brk, (Addr)ARG1, brk_limit-ARG1 ); } else - if (RES > brk_limit) { + if (brk_new > brk_limit) { /* successfully grew the data segment */ VG_TRACK( new_mem_brk, brk_limit, ARG1-brk_limit ); } } else { /* brk() failed */ - vg_assert(brk_limit == RES); + vg_assert(brk_limit == brk_new); } } -PRE(sys_chdir, 0) +PRE(sys_chdir) { PRINT("sys_chdir ( %p )", ARG1); PRE_REG_READ1(long, "chdir", const char *, path); PRE_MEM_RASCIIZ( "chdir(path)", ARG1 ); } -PRE(sys_chmod, 0) +PRE(sys_chmod) { PRINT("sys_chmod ( %p, %d )", ARG1,ARG2); PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode); PRE_MEM_RASCIIZ( "chmod(path)", ARG1 ); } -PRE(sys_chown16, 0) -{ - PRINT("sys_chown16 ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "chown16", - const char *, path, - vki_old_uid_t, owner, vki_old_gid_t, group); - PRE_MEM_RASCIIZ( "chown16(path)", ARG1 ); -} - -PRE(sys_chown, 0) -{ - /* int chown(const char *path, uid_t owner, gid_t group); */ - PRINT("sys_chown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "chown", - const char *, path, vki_uid_t, owner, vki_gid_t, group); - PRE_MEM_RASCIIZ( "chown(path)", ARG1 ); -} - -PRE(sys_lchown, 0) -{ - PRINT("sys_lchown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "lchown", - const char *, path, vki_uid_t, owner, vki_gid_t, group); - PRE_MEM_RASCIIZ( "lchown(path)", ARG1 ); -} - -PRE(sys_close, 0) +//zz PRE(sys_chown16, 0) +//zz { +//zz PRINT("sys_chown16 ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "chown16", +//zz const char *, path, +//zz vki_old_uid_t, owner, vki_old_gid_t, group); +//zz PRE_MEM_RASCIIZ( "chown16(path)", ARG1 ); +//zz } +//zz +//zz PRE(sys_chown, 0) +//zz { +//zz /* int chown(const char *path, uid_t owner, gid_t group); */ +//zz PRINT("sys_chown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "chown", +//zz const char *, path, vki_uid_t, owner, vki_gid_t, group); +//zz PRE_MEM_RASCIIZ( "chown(path)", ARG1 ); +//zz } +//zz +//zz PRE(sys_lchown, 0) +//zz { +//zz PRINT("sys_lchown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "lchown", +//zz const char *, path, vki_uid_t, owner, vki_gid_t, group); +//zz PRE_MEM_RASCIIZ( "lchown(path)", ARG1 ); +//zz } + +PRE(sys_close) { PRINT("sys_close ( %d )", ARG1); PRE_REG_READ1(long, "close", unsigned int, fd); /* Detect and negate attempts by the client to close Valgrind's log fd */ if (!VG_(fd_allowed)(ARG1, "close", tid, False)) - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); } POST(sys_close) @@ -2562,7 +2484,7 @@ POST(sys_close) if (VG_(clo_track_fds)) record_fd_close(tid, ARG1); } -PRE(sys_dup, 0) +PRE(sys_dup) { PRINT("sys_dup ( %d )", ARG1); PRE_REG_READ1(long, "dup", unsigned int, oldfd); @@ -2570,117 +2492,119 @@ PRE(sys_dup, 0) POST(sys_dup) { + vg_assert(SUCCESS); if (!VG_(fd_allowed)(RES, "dup", tid, True)) { VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) VG_(record_fd_open)(tid, RES, VG_(resolve_filename)(RES)); } } -PRE(sys_dup2, 0) +PRE(sys_dup2) { PRINT("sys_dup2 ( %d, %d )", ARG1,ARG2); PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd); if (!VG_(fd_allowed)(ARG2, "dup2", tid, True)) - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); } POST(sys_dup2) { + vg_assert(SUCCESS); if (VG_(clo_track_fds)) VG_(record_fd_open)(tid, RES, VG_(resolve_filename)(RES)); } -PRE(sys_fchdir, 0) -{ - PRINT("sys_fchdir ( %d )", ARG1); - PRE_REG_READ1(long, "fchdir", unsigned int, fd); -} - -PRE(sys_fchown16, 0) -{ - PRINT("sys_fchown16 ( %d, %d, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "fchown16", - unsigned int, fd, vki_old_uid_t, owner, vki_old_gid_t, group); -} - -PRE(sys_fchown, 0) -{ - PRINT("sys_fchown ( %d, %d, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "fchown", - unsigned int, fd, vki_uid_t, owner, vki_gid_t, group); -} - -PRE(sys_fchmod, 0) -{ - PRINT("sys_fchmod ( %d, %d )", ARG1,ARG2); - PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode); -} - -PRE(sys_fcntl, 0) -{ - switch (ARG2) { - // These ones ignore ARG3. - case VKI_F_GETFD: - case VKI_F_GETFL: - case VKI_F_GETOWN: - case VKI_F_SETOWN: - case VKI_F_GETSIG: - case VKI_F_SETSIG: - case VKI_F_GETLEASE: - PRINT("sys_fcntl ( %d, %d )", ARG1,ARG2); - PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); - break; - - // These ones use ARG3 as "arg". - case VKI_F_DUPFD: - case VKI_F_SETFD: - case VKI_F_SETFL: - case VKI_F_SETLEASE: - case VKI_F_NOTIFY: - PRINT("sys_fcntl[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "fcntl", - unsigned int, fd, unsigned int, cmd, unsigned long, arg); - break; - - // These ones use ARG3 as "lock". - case VKI_F_GETLK: - case VKI_F_SETLK: - case VKI_F_SETLKW: -#ifndef __amd64__ - case VKI_F_GETLK64: - case VKI_F_SETLK64: - case VKI_F_SETLKW64: -#else -#endif - PRINT("sys_fcntl[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "fcntl", - unsigned int, fd, unsigned int, cmd, - struct flock64 *, lock); - break; - } - - //if (ARG2 == VKI_F_SETLKW) - // tst->sys_flags |= MayBlock; -} - -POST(sys_fcntl) -{ - if (ARG2 == VKI_F_DUPFD) { - if (!VG_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { - VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); - } else { - if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, RES, VG_(resolve_filename)(RES)); - } - } -} +//zz PRE(sys_fchdir, 0) +//zz { +//zz PRINT("sys_fchdir ( %d )", ARG1); +//zz PRE_REG_READ1(long, "fchdir", unsigned int, fd); +//zz } +//zz +//zz PRE(sys_fchown16, 0) +//zz { +//zz PRINT("sys_fchown16 ( %d, %d, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "fchown16", +//zz unsigned int, fd, vki_old_uid_t, owner, vki_old_gid_t, group); +//zz } +//zz +//zz PRE(sys_fchown, 0) +//zz { +//zz PRINT("sys_fchown ( %d, %d, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "fchown", +//zz unsigned int, fd, vki_uid_t, owner, vki_gid_t, group); +//zz } +//zz +//zz PRE(sys_fchmod, 0) +//zz { +//zz PRINT("sys_fchmod ( %d, %d )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode); +//zz } +//zz +//zz PRE(sys_fcntl, 0) +//zz { +//zz switch (ARG2) { +//zz // These ones ignore ARG3. +//zz case VKI_F_GETFD: +//zz case VKI_F_GETFL: +//zz case VKI_F_GETOWN: +//zz case VKI_F_SETOWN: +//zz case VKI_F_GETSIG: +//zz case VKI_F_SETSIG: +//zz case VKI_F_GETLEASE: +//zz PRINT("sys_fcntl ( %d, %d )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); +//zz break; +//zz +//zz // These ones use ARG3 as "arg". +//zz case VKI_F_DUPFD: +//zz case VKI_F_SETFD: +//zz case VKI_F_SETFL: +//zz case VKI_F_SETLEASE: +//zz case VKI_F_NOTIFY: +//zz PRINT("sys_fcntl[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "fcntl", +//zz unsigned int, fd, unsigned int, cmd, unsigned long, arg); +//zz break; +//zz +//zz // These ones use ARG3 as "lock". +//zz case VKI_F_GETLK: +//zz case VKI_F_SETLK: +//zz case VKI_F_SETLKW: +//zz #ifndef __amd64__ +//zz case VKI_F_GETLK64: +//zz case VKI_F_SETLK64: +//zz case VKI_F_SETLKW64: +//zz #else +//zz #endif +//zz PRINT("sys_fcntl[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "fcntl", +//zz unsigned int, fd, unsigned int, cmd, +//zz struct flock64 *, lock); +//zz break; +//zz } +//zz +//zz //if (ARG2 == VKI_F_SETLKW) +//zz // tst->sys_flags |= SfMayBlock; +//zz } +//zz +//zz POST(sys_fcntl) +//zz { +//zz if (ARG2 == VKI_F_DUPFD) { +//zz if (!VG_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { +//zz VG_(close)(RES); +//zz SET_STATUS_( -VKI_EMFILE ); +//zz } else { +//zz if (VG_(clo_track_fds)) +//zz VG_(record_fd_open)(tid, RES, VG_(resolve_filename)(RES)); +//zz } +//zz } +//zz } // XXX: wrapper only suitable for 32-bit systems -PRE(sys_fcntl64, 0) +PRE(sys_fcntl64) { switch (ARG2) { // These ones ignore ARG3. @@ -2710,11 +2634,11 @@ PRE(sys_fcntl64, 0) case VKI_F_GETLK: case VKI_F_SETLK: case VKI_F_SETLKW: -#ifndef __amd64__ +# if defined(VGP_amd64_linux) case VKI_F_GETLK64: case VKI_F_SETLK64: case VKI_F_SETLKW64: -#endif +# endif PRINT("sys_fcntl64[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3); PRE_REG_READ3(long, "fcntl64", unsigned int, fd, unsigned int, cmd, @@ -2722,45 +2646,47 @@ PRE(sys_fcntl64, 0) break; } -#ifndef __amd64__ +# if defined(VGP_amd64_linux) //if (ARG2 == VKI_F_SETLKW || ARG2 == VKI_F_SETLKW64) - // tst->sys_flags |= MayBlock; -#else + // tst->sys_flags |= SfMayBlock; +# else //if (ARG2 == VKI_F_SETLKW) - // tst->sys_flags |= MayBlock; -#endif + // tst->sys_flags |= SfMayBlock; +# endif } POST(sys_fcntl64) { + vg_assert(SUCCESS); if (ARG2 == VKI_F_DUPFD) { if (!VG_(fd_allowed)(RES, "fcntl64(DUPFD)", tid, True)) { VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, RES, VG_(resolve_filename)(RES)); + VG_(record_fd_open)(tid, RES, + VG_(resolve_filename)(RES)); } } } -PRE(sys_newfstat, 0) -{ - PRINT("sys_newfstat ( %d, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf); - PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) ); -} - -POST(sys_newfstat) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); -} +//zz PRE(sys_newfstat, 0) +//zz { +//zz PRINT("sys_newfstat ( %d, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf); +//zz PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) ); +//zz } +//zz +//zz POST(sys_newfstat) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +//zz } static vki_sigset_t fork_saved_mask; // In Linux, the sys_fork() function varies across architectures, but we // ignore the various args it gets, and so it looks arch-neutral. Hmm. -PRE(sys_fork, 0) +PRE(sys_fork) { vki_sigset_t mask; @@ -2774,14 +2700,16 @@ PRE(sys_fork, 0) VG_(do_atfork_pre)(tid); - SET_RESULT(VG_(do_syscall0)(__NR_fork)); + SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) ); - if (RES == 0) { + if (SUCCESS && RES == 0) { VG_(do_atfork_child)(tid); /* restore signal mask */ VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); - } else if (RES > 0) { + } + else + if (SUCCESS && RES > 0) { PRINT(" fork: process %d created child %d\n", VG_(getpid)(), RES); VG_(do_atfork_parent)(tid); @@ -2791,57 +2719,58 @@ PRE(sys_fork, 0) } } -PRE(sys_ftruncate, MayBlock) -{ - PRINT("sys_ftruncate ( %d, %lld )", ARG1,(ULong)ARG2); - PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length); -} - -PRE(sys_truncate, MayBlock) -{ - PRINT("sys_truncate ( %p(%s), %d )", ARG1,ARG1,ARG2); - PRE_REG_READ2(long, "truncate", - const char *, path, unsigned long, length); - PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); -} - -// XXX: this wrapper is only suitable for 32-bit platforms -PRE(sys_ftruncate64, MayBlock) -{ - PRINT("sys_ftruncate64 ( %d, %lld )", ARG1, LOHI64(ARG2,ARG3)); - PRE_REG_READ3(long, "ftruncate64", - unsigned int, fd, - vki_u32, length_low32, vki_u32, length_high32); -} - -// XXX: this wrapper is only suitable for 32-bit platforms -PRE(sys_truncate64, MayBlock) -{ - PRINT("sys_truncate64 ( %p, %lld )", ARG1, LOHI64(ARG2, ARG3)); - PRE_REG_READ3(long, "truncate64", - const char *, path, - vki_u32, length_low32, vki_u32, length_high32); - PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 ); -} - - -PRE(sys_getdents, MayBlock) -{ - PRINT("sys_getdents ( %d, %p, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "getdents", - unsigned int, fd, struct linux_dirent *, dirp, - unsigned int, count); - PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 ); -} - -POST(sys_getdents) -{ - if (RES > 0) - POST_MEM_WRITE( ARG2, RES ); -} - -PRE(sys_getdents64, MayBlock) -{ +//zz PRE(sys_ftruncate, SfMayBlock) +//zz { +//zz PRINT("sys_ftruncate ( %d, %lld )", ARG1,(ULong)ARG2); +//zz PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length); +//zz } +//zz +//zz PRE(sys_truncate, SfMayBlock) +//zz { +//zz PRINT("sys_truncate ( %p(%s), %d )", ARG1,ARG1,ARG2); +//zz PRE_REG_READ2(long, "truncate", +//zz const char *, path, unsigned long, length); +//zz PRE_MEM_RASCIIZ( "truncate(path)", ARG1 ); +//zz } +//zz +//zz // XXX: this wrapper is only suitable for 32-bit platforms +//zz PRE(sys_ftruncate64, SfMayBlock) +//zz { +//zz PRINT("sys_ftruncate64 ( %d, %lld )", ARG1, LOHI64(ARG2,ARG3)); +//zz PRE_REG_READ3(long, "ftruncate64", +//zz unsigned int, fd, +//zz vki_u32, length_low32, vki_u32, length_high32); +//zz } +//zz +//zz // XXX: this wrapper is only suitable for 32-bit platforms +//zz PRE(sys_truncate64, SfMayBlock) +//zz { +//zz PRINT("sys_truncate64 ( %p, %lld )", ARG1, LOHI64(ARG2, ARG3)); +//zz PRE_REG_READ3(long, "truncate64", +//zz const char *, path, +//zz vki_u32, length_low32, vki_u32, length_high32); +//zz PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 ); +//zz } +//zz +//zz +//zz PRE(sys_getdents, SfMayBlock) +//zz { +//zz PRINT("sys_getdents ( %d, %p, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "getdents", +//zz unsigned int, fd, struct linux_dirent *, dirp, +//zz unsigned int, count); +//zz PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 ); +//zz } +//zz +//zz POST(sys_getdents) +//zz { +//zz if (RES > 0) +//zz POST_MEM_WRITE( ARG2, RES ); +//zz } + +PRE(sys_getdents64) +{ + *flags |= SfMayBlock; PRINT("sys_getdents64 ( %d, %p, %d )",ARG1,ARG2,ARG3); PRE_REG_READ3(long, "getdents64", unsigned int, fd, struct linux_dirent64 *, dirp, @@ -2851,39 +2780,40 @@ PRE(sys_getdents64, MayBlock) POST(sys_getdents64) { + vg_assert(SUCCESS); if (RES > 0) POST_MEM_WRITE( ARG2, RES ); } -PRE(sys_getgroups16, 0) -{ - PRINT("sys_getgroups16 ( %d, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "getgroups16", int, size, vki_old_gid_t *, list); - if (ARG1 > 0) - PRE_MEM_WRITE( "getgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); -} - -POST(sys_getgroups16) -{ - if (ARG1 > 0 && RES > 0) - POST_MEM_WRITE( ARG2, RES * sizeof(vki_old_gid_t) ); -} - -PRE(sys_getgroups, 0) -{ - PRINT("sys_getgroups ( %d, %p )", ARG1, ARG2); - PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list); - if (ARG1 > 0) - PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); -} - -POST(sys_getgroups) -{ - if (ARG1 > 0 && RES > 0) - POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) ); -} - -PRE(sys_getcwd, 0) +//zz PRE(sys_getgroups16, 0) +//zz { +//zz PRINT("sys_getgroups16 ( %d, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "getgroups16", int, size, vki_old_gid_t *, list); +//zz if (ARG1 > 0) +//zz PRE_MEM_WRITE( "getgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); +//zz } +//zz +//zz POST(sys_getgroups16) +//zz { +//zz if (ARG1 > 0 && RES > 0) +//zz POST_MEM_WRITE( ARG2, RES * sizeof(vki_old_gid_t) ); +//zz } +//zz +//zz PRE(sys_getgroups, 0) +//zz { +//zz PRINT("sys_getgroups ( %d, %p )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list); +//zz if (ARG1 > 0) +//zz PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); +//zz } +//zz +//zz POST(sys_getgroups) +//zz { +//zz if (ARG1 > 0 && RES > 0) +//zz POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) ); +//zz } + +PRE(sys_getcwd) { // Note that the kernel version of getcwd() behaves quite differently to // the glibc one. @@ -2894,65 +2824,66 @@ PRE(sys_getcwd, 0) POST(sys_getcwd) { + vg_assert(SUCCESS); if (RES != (Addr)NULL) POST_MEM_WRITE( ARG1, RES ); } -PRE(sys_geteuid16, 0) +PRE(sys_geteuid16) { PRINT("sys_geteuid16 ( )"); PRE_REG_READ0(long, "geteuid16"); } -PRE(sys_geteuid, 0) +PRE(sys_geteuid) { PRINT("sys_geteuid ( )"); PRE_REG_READ0(long, "geteuid"); } -PRE(sys_getegid16, 0) -{ - PRINT("sys_getegid16 ( )"); - PRE_REG_READ0(long, "getegid16"); -} - -PRE(sys_getegid, 0) -{ - PRINT("sys_getegid ( )"); - PRE_REG_READ0(long, "getegid"); -} - -PRE(sys_getgid16, 0) -{ - PRINT("sys_getgid16 ( )"); - PRE_REG_READ0(long, "getgid16"); -} - -PRE(sys_getgid, 0) -{ - PRINT("sys_getgid ( )"); - PRE_REG_READ0(long, "getgid"); -} - -PRE(sys_getpid, 0) +//zz PRE(sys_getegid16, 0) +//zz { +//zz PRINT("sys_getegid16 ( )"); +//zz PRE_REG_READ0(long, "getegid16"); +//zz } +//zz +//zz PRE(sys_getegid, 0) +//zz { +//zz PRINT("sys_getegid ( )"); +//zz PRE_REG_READ0(long, "getegid"); +//zz } +//zz +//zz PRE(sys_getgid16, 0) +//zz { +//zz PRINT("sys_getgid16 ( )"); +//zz PRE_REG_READ0(long, "getgid16"); +//zz } +//zz +//zz PRE(sys_getgid, 0) +//zz { +//zz PRINT("sys_getgid ( )"); +//zz PRE_REG_READ0(long, "getgid"); +//zz } + +PRE(sys_getpid) { PRINT("sys_getpid ()"); PRE_REG_READ0(long, "getpid"); } -PRE(sys_getpgid, 0) -{ - PRINT("sys_getpgid ( %d )", ARG1); - PRE_REG_READ1(long, "getpgid", vki_pid_t, pid); -} - -PRE(sys_getpgrp, 0) -{ - PRINT("sys_getpgrp ()"); - PRE_REG_READ0(long, "getpgrp"); -} +//zz PRE(sys_getpgid, 0) +//zz { +//zz PRINT("sys_getpgid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "getpgid", vki_pid_t, pid); +//zz } +//zz +//zz PRE(sys_getpgrp, 0) +//zz { +//zz PRINT("sys_getpgrp ()"); +//zz PRE_REG_READ0(long, "getpgrp"); +//zz } -PRE(sys_getppid, 0) +PRE(sys_getppid) { PRINT("sys_getppid ()"); PRE_REG_READ0(long, "getppid"); @@ -2978,20 +2909,20 @@ static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2) } } -PRE(sys_old_getrlimit, 0) -{ - PRINT("sys_old_getrlimit ( %d, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "old_getrlimit", - unsigned int, resource, struct rlimit *, rlim); - PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) ); -} +//zz PRE(sys_old_getrlimit, 0) +//zz { +//zz PRINT("sys_old_getrlimit ( %d, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "old_getrlimit", +//zz unsigned int, resource, struct rlimit *, rlim); +//zz PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) ); +//zz } +//zz +//zz POST(sys_old_getrlimit) +//zz { +//zz common_post_getrlimit(tid, ARG1, ARG2); +//zz } -POST(sys_old_getrlimit) -{ - common_post_getrlimit(tid, ARG1, ARG2); -} - -PRE(sys_getrlimit, 0) +PRE(sys_getrlimit) { PRINT("sys_getrlimit ( %d, %p )", ARG1,ARG2); PRE_REG_READ2(long, "getrlimit", @@ -3004,21 +2935,21 @@ POST(sys_getrlimit) common_post_getrlimit(tid, ARG1, ARG2); } -PRE(sys_getrusage, 0) -{ - /* int getrusage (int who, struct rusage *usage); */ - PRINT("sys_getrusage ( %d, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage); - PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) ); -} - -POST(sys_getrusage) -{ - if (RES == 0) - POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) ); -} +//zz PRE(sys_getrusage, 0) +//zz { +//zz /* int getrusage (int who, struct rusage *usage); */ +//zz PRINT("sys_getrusage ( %d, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage); +//zz PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) ); +//zz } +//zz +//zz POST(sys_getrusage) +//zz { +//zz if (RES == 0) +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) ); +//zz } -PRE(sys_gettimeofday, 0) +PRE(sys_gettimeofday) { PRINT("sys_gettimeofday ( %p, %p )", ARG1,ARG2); PRE_REG_READ2(long, "gettimeofday", @@ -3030,6 +2961,7 @@ PRE(sys_gettimeofday, 0) POST(sys_gettimeofday) { + vg_assert(SUCCESS); if (RES == 0) { POST_MEM_WRITE( ARG1, sizeof(struct vki_timeval) ); if (ARG2 != 0) @@ -3037,33 +2969,34 @@ POST(sys_gettimeofday) } } -PRE(sys_settimeofday, 0) -{ - PRINT("sys_settimeofday ( %p, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "settimeofday", - struct timeval *, tv, struct timezone *, tz); - PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) ); - if (ARG2 != 0) { - PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) ); - /* maybe should warn if tz->tz_dsttime is non-zero? */ - } -} +//zz PRE(sys_settimeofday, 0) +//zz { +//zz PRINT("sys_settimeofday ( %p, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "settimeofday", +//zz struct timeval *, tv, struct timezone *, tz); +//zz PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) ); +//zz if (ARG2 != 0) { +//zz PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) ); +//zz /* maybe should warn if tz->tz_dsttime is non-zero? */ +//zz } +//zz } -PRE(sys_getuid16, 0) +PRE(sys_getuid16) { PRINT("sys_getuid16 ( )"); PRE_REG_READ0(long, "getuid16"); } -PRE(sys_getuid, 0) +PRE(sys_getuid) { PRINT("sys_getuid ( )"); PRE_REG_READ0(long, "getuid"); } // XXX: I reckon some of these cases must be x86-specific -PRE(sys_ioctl, MayBlock) +PRE(sys_ioctl) { + *flags |= SfMayBlock; PRINT("sys_ioctl ( %d, 0x%x, %p )",ARG1,ARG2,ARG3); PRE_REG_READ3(long, "ioctl", unsigned int, fd, unsigned int, request, unsigned long, arg); @@ -3378,7 +3311,7 @@ PRE(sys_ioctl, MayBlock) break; case VKI_SIOCSPGRP: PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) ); - //tst->sys_flags &= ~MayBlock; + //tst->sys_flags &= ~SfMayBlock; break; /* linux/soundcard interface (OSS) */ @@ -3827,6 +3760,7 @@ PRE(sys_ioctl, MayBlock) POST(sys_ioctl) { + vg_assert(SUCCESS); switch (ARG2 /* request */) { case VKI_TCSETS: case VKI_TCSETSW: @@ -4323,7 +4257,7 @@ POST(sys_ioctl) UInt dir = _VKI_IOC_DIR(ARG2); UInt size = _VKI_IOC_SIZE(ARG2); if (size > 0 && (dir & _VKI_IOC_READ) - && RES == 0 + && RES == 0 && ARG3 != (Addr)NULL) POST_MEM_WRITE(ARG3, size); break; @@ -4369,7 +4303,8 @@ Bool VG_(do_sigkill)(Int pid, Int tgid) /* Check to see that the target isn't already exiting. */ if (!VG_(is_exiting)(tid)) { if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "Thread %d being killed with SIGKILL", tst->tid); + VG_(message)(Vg_DebugMsg, "Thread %d being killed with SIGKILL", + tst->tid); tst->exitreason = VgSrc_FatalSig; tst->os_state.fatalsig = VKI_SIGKILL; @@ -4381,167 +4316,74 @@ Bool VG_(do_sigkill)(Int pid, Int tgid) return True; } -PRE(sys_kill, Special) +PRE(sys_kill) { /* int kill(pid_t pid, int sig); */ PRINT("sys_kill ( %d, %d )", ARG1,ARG2); PRE_REG_READ2(long, "kill", int, pid, int, sig); if (!VG_(client_signal_OK)(ARG2)) { - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); return; } /* If we're sending SIGKILL, check to see if the target is one of our threads and handle it specially. */ if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1)) - SET_RESULT(0); + SET_STATUS_Success(0); else - SET_RESULT(VG_(do_syscall2)(SYSNO, ARG1, ARG2)); + SET_STATUS_from_SysRes( VG_(do_syscall2)(SYSNO, ARG1, ARG2) ); if (VG_(clo_trace_signals)) VG_(message)(Vg_DebugMsg, "kill: sent signal %d to pid %d", ARG2, ARG1); - // Check to see if this kill gave us a pending signal - VG_(poll_signals)(tid); + + /* This kill might have given us a pending signal. Ask for a check once + the syscall is done. */ + *flags |= SfPollAfter; } -PRE(sys_link, MayBlock) +PRE(sys_link) { + *flags |= SfMayBlock; PRINT("sys_link ( %p, %p)", ARG1, ARG2); PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath); PRE_MEM_RASCIIZ( "link(oldpath)", ARG1); PRE_MEM_RASCIIZ( "link(newpath)", ARG2); } -PRE(sys_lseek, 0) +PRE(sys_lseek) { PRINT("sys_lseek ( %d, %d, %d )", ARG1,ARG2,ARG3); PRE_REG_READ3(vki_off_t, "lseek", unsigned int, fd, vki_off_t, offset, unsigned int, whence); } -PRE(sys_newlstat, 0) -{ - PRINT("sys_newlstat ( %p(%s), %p )", ARG1,ARG1,ARG2); - PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf); - PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 ); - PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) ); -} - -POST(sys_newlstat) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); - } -} - -// XXX: this syscall is generic, but not necessarily applicable to every -// architecture -- I think only to 32-bit archs. We're going to need -// something like linux/core_os32.h for such things, eventually, I think. -// --njn -#ifndef __amd64__ -PRE(sys_lstat64, 0) -{ - PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2); - PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf); - PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 ); - PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) ); -} - -POST(sys_lstat64) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); - } -} -#endif - -PRE(sys_mkdir, MayBlock) -{ +//zz PRE(sys_newlstat, 0) +//zz { +//zz PRINT("sys_newlstat ( %p(%s), %p )", ARG1,ARG1,ARG2); +//zz PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf); +//zz PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 ); +//zz PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) ); +//zz } +//zz +//zz POST(sys_newlstat) +//zz { +//zz if (RES == 0) { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +//zz } +//zz } + +PRE(sys_mkdir) +{ + *flags |= SfMayBlock; PRINT("sys_mkdir ( %p, %d )", ARG1,ARG2); PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode); PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 ); } -// Nb: this should probably be in m_syscalls/syscalls-x86-linux.c, but it -// might be required for ARM, and I was too lazy to move it (which would -// have required making mmap_segment() public). -PRE(old_mmap, Special) +PRE(sys_mmap2) { - /* struct mmap_arg_struct { - unsigned long addr; - unsigned long len; - unsigned long prot; - unsigned long flags; - unsigned long fd; - unsigned long offset; - }; */ -#if defined(VGP_x86_linux) - // do nothing -#else - vg_assert2(0, "old_mmap should only be called on x86/Linux"); -#endif - - UWord a1, a2, a3, a4, a5, a6; - UWord *arg_block = (UWord*)(tst->arch.vex.VGP_SYSCALL_ARG1); - - PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args); - arg_block = (UWord*)(tst->arch.vex.VGP_SYSCALL_ARG1); - PRE_MEM_READ( "old_mmap(args)", (Addr)arg_block, 6*sizeof(UWord) );\ - a1 = arg_block[0]; - a2 = arg_block[1]; - a3 = arg_block[2]; - a4 = arg_block[3]; - a5 = arg_block[4]; - a6 = arg_block[5]; - - PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )", - a1, (ULong)a2, a3, a4, a5, a6 ); - - if (a2 == 0) { - /* SuSV3 says: If len is zero, mmap() shall fail and no mapping - shall be established. */ - SET_RESULT( -VKI_EINVAL ); - return; - } - - if (/*(a4 & VKI_MAP_FIXED) &&*/ (0 != (a1 & (VKI_PAGE_SIZE-1)))) { - /* zap any misaligned addresses. */ - SET_RESULT( -VKI_EINVAL ); - return; - } - - if (a4 & VKI_MAP_FIXED) { - if (!VG_(valid_client_addr)(a1, a2, tid, "old_mmap")) { - PRINT("old_mmap failing: %p-%p\n", a1, a1+a2); - SET_RESULT( -VKI_ENOMEM ); - } - } else { - Addr a = VG_(find_map_space)(a1, a2, True); - if (a == 0 && a1 != 0) - a1 = VG_(find_map_space)(0, a2, True); - else - a1 = a; - if (a1 == 0) - SET_RESULT( -VKI_ENOMEM ); - else - a4 |= VKI_MAP_FIXED; - } - - if (RES != -VKI_ENOMEM) { - Int res = (Int)VG_(mmap_native)((void*)a1, a2, a3, a4, a5, a6); - SET_RESULT(res); - - if (!VG_(is_kerror)(RES)) { - vg_assert(VG_(valid_client_addr)(RES, a2, tid, "old_mmap")); - mmap_segment( (Addr)RES, a2, a3, a4, a5, a6 ); - } - } -} - -PRE(sys_mmap2, 0) -{ - // Exactly like old_mmap() except: + // Exactly like old_mmap() in x86-linux except: // - all 6 args are passed in regs, rather than in a memory-block. // - the file offset is specified in pagesize units rather than bytes, // so that it can be used for files bigger than 2^32 bytes. @@ -4555,7 +4397,7 @@ PRE(sys_mmap2, 0) if (ARG2 == 0) { /* SuSV3 says: If len is zero, mmap() shall fail and no mapping shall be established. */ - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); return; } @@ -4563,13 +4405,13 @@ PRE(sys_mmap2, 0) /* zap any misaligned addresses. */ /* SuSV3 says misaligned addresses only cause the MAP_FIXED case to fail. Here, we catch them all. */ - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); return; } if (ARG4 & VKI_MAP_FIXED) { if (!VG_(valid_client_addr)(ARG1, ARG2, tid, "mmap2")) - SET_RESULT( -VKI_ENOMEM ); + SET_STATUS_Failure( VKI_ENOMEM ); } else { Addr a = VG_(find_map_space)(ARG1, ARG2, True); if (a == 0 && ARG1 != 0) @@ -4577,7 +4419,7 @@ PRE(sys_mmap2, 0) else ARG1 = a; if (ARG1 == 0) - SET_RESULT( -VKI_ENOMEM ); + SET_STATUS_Failure( VKI_ENOMEM ); else ARG4 |= VKI_MAP_FIXED; } @@ -4585,19 +4427,20 @@ PRE(sys_mmap2, 0) POST(sys_mmap2) { + vg_assert(SUCCESS); vg_assert(VG_(valid_client_addr)(RES, ARG2, tid, "mmap2")); - mmap_segment( (Addr)RES, ARG2, ARG3, ARG4, ARG5, - ARG6 * (ULong)VKI_PAGE_SIZE ); + VG_(mmap_segment)( (Addr)RES, ARG2, ARG3, ARG4, ARG5, + ARG6 * (ULong)VKI_PAGE_SIZE ); } -PRE(sys_mprotect, 0) +PRE(sys_mprotect) { PRINT("sys_mprotect ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3); PRE_REG_READ3(long, "mprotect", unsigned long, addr, vki_size_t, len, unsigned long, prot); if (!VG_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) - SET_RESULT( -VKI_ENOMEM ); + SET_STATUS_Failure( VKI_ENOMEM ); } POST(sys_mprotect) @@ -4614,13 +4457,14 @@ POST(sys_mprotect) VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx ); } -PRE(sys_munmap, 0) +PRE(sys_munmap) { + if (0) VG_(printf)(" munmap( %p )\n", ARG1); PRINT("sys_munmap ( %p, %llu )", ARG1,(ULong)ARG2); PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length); if (!VG_(valid_client_addr)(ARG1, ARG2, tid, "munmap")) - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); } POST(sys_munmap) @@ -4633,22 +4477,23 @@ POST(sys_munmap) VG_TRACK( die_mem_munmap, a, len ); } -PRE(sys_mincore, 0) -{ - PRINT("sys_mincore ( %p, %llu, %p )", ARG1,(ULong)ARG2,ARG3); - PRE_REG_READ3(long, "mincore", - unsigned long, start, vki_size_t, length, - unsigned char *, vec); - PRE_MEM_WRITE( "mincore(vec)", ARG3, (ARG2 + 4096 - 1) / 4096); -} - -POST(sys_mincore) -{ - POST_MEM_WRITE( ARG3, (ARG2 + 4096 - 1) / 4096 ); -} +//zz PRE(sys_mincore, 0) +//zz { +//zz PRINT("sys_mincore ( %p, %llu, %p )", ARG1,(ULong)ARG2,ARG3); +//zz PRE_REG_READ3(long, "mincore", +//zz unsigned long, start, vki_size_t, length, +//zz unsigned char *, vec); +//zz PRE_MEM_WRITE( "mincore(vec)", ARG3, (ARG2 + 4096 - 1) / 4096); +//zz } +//zz +//zz POST(sys_mincore) +//zz { +//zz POST_MEM_WRITE( ARG3, (ARG2 + 4096 - 1) / 4096 ); +//zz } -PRE(sys_nanosleep, MayBlock|PostOnFail) +PRE(sys_nanosleep) { + *flags |= SfMayBlock|SfPostOnFail; PRINT("sys_nanosleep ( %p, %p )", ARG1,ARG2); PRE_REG_READ2(long, "nanosleep", struct timespec *, req, struct timespec *, rem); @@ -4659,12 +4504,14 @@ PRE(sys_nanosleep, MayBlock|PostOnFail) POST(sys_nanosleep) { - if (ARG2 != 0 && RES == -VKI_EINTR) + vg_assert(SUCCESS || FAILURE); + if (ARG2 != 0 && FAILURE && RES_unchecked == VKI_EINTR) POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); } -PRE(sys_open, MayBlock) +PRE(sys_open) { + *flags |= SfMayBlock; if (ARG2 & VKI_O_CREAT) { // 3-arg version PRINT("sys_open ( %p(%s), %d, %d )",ARG1,ARG1,ARG2,ARG3); @@ -4681,45 +4528,51 @@ PRE(sys_open, MayBlock) POST(sys_open) { + vg_assert(SUCCESS); if (!VG_(fd_allowed)(RES, "open", tid, True)) { VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); + VG_(record_fd_open)(tid, RES, + VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); } } -PRE(sys_read, MayBlock) +PRE(sys_read) { + *flags |= SfMayBlock; PRINT("sys_read ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3); PRE_REG_READ3(ssize_t, "read", unsigned int, fd, char *, buf, vki_size_t, count); if (!VG_(fd_allowed)(ARG1, "read", tid, False)) - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); else PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 ); } POST(sys_read) { + vg_assert(SUCCESS); POST_MEM_WRITE( ARG2, RES ); } -PRE(sys_write, MayBlock) +PRE(sys_write) { + *flags |= SfMayBlock; PRINT("sys_write ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3); PRE_REG_READ3(ssize_t, "write", unsigned int, fd, const char *, buf, vki_size_t, count); if (!VG_(fd_allowed)(ARG1, "write", tid, False)) - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); else PRE_MEM_READ( "write(buf)", ARG2, ARG3 ); } -PRE(sys_creat, MayBlock) +PRE(sys_creat) { + *flags |= SfMayBlock; PRINT("sys_creat ( %p(%s), %d )", ARG1,ARG1,ARG2); PRE_REG_READ2(long, "creat", const char *, pathname, int, mode); PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 ); @@ -4727,9 +4580,10 @@ PRE(sys_creat, MayBlock) POST(sys_creat) { + vg_assert(SUCCESS); if (!VG_(fd_allowed)(RES, "creat", tid, True)) { VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); @@ -4737,7 +4591,7 @@ POST(sys_creat) } // XXX: sort of x86-specific -PRE(sys_pipe, 0) +PRE(sys_pipe) { PRINT("sys_pipe ( %p )", ARG1); PRE_REG_READ1(int, "pipe", unsigned long *, filedes); @@ -4752,7 +4606,7 @@ POST(sys_pipe) !VG_(fd_allowed)(p[1], "pipe", tid, True)) { VG_(close)(p[0]); VG_(close)(p[1]); - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); } else { POST_MEM_WRITE( ARG1, 2*sizeof(int) ); if (VG_(clo_track_fds)) { @@ -4763,7 +4617,7 @@ POST(sys_pipe) } // XXX: x86-specific, due to pollfd struct -PRE(sys_poll, MayBlock) +PRE(sys_poll) { /* struct pollfd { int fd; -- file descriptor @@ -4773,6 +4627,7 @@ PRE(sys_poll, MayBlock) int poll(struct pollfd *ufds, unsigned int nfds, int timeout) */ UInt i; + *flags |= SfMayBlock; struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1; PRINT("sys_poll ( %p, %d, %d )\n", ARG1,ARG2,ARG3); PRE_REG_READ3(long, "poll", @@ -4799,9 +4654,9 @@ POST(sys_poll) } } -PRE(sys_readlink, Special) +PRE(sys_readlink) { - int saved = SYSNO; + Word saved = SYSNO; PRINT("sys_readlink ( %p, %p, %llu )", ARG1,ARG2,(ULong)ARG3); PRE_REG_READ3(long, "readlink", const char *, path, char *, buf, int, bufsiz); @@ -4813,33 +4668,36 @@ PRE(sys_readlink, Special) * /proc/<pid>/exe. */ - SET_RESULT( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3)); - if ((Int)RES == -2) { - char name[25]; + SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3)); + /* jrs 20050604: where does the magic value 2 come from? It seems + like it should be a kernel error value, but we don't know of any + such. */ + if (SWHAT == SsFailure && RES_unchecked == 2) { + HChar name[25]; VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)()); - if (VG_(strcmp)((Char *)ARG1, name) == 0 || VG_(strcmp)((Char *)ARG1, "/proc/self/exe") == 0) { VG_(sprintf)(name, "/proc/self/fd/%d", VG_(clexecfd)); - SET_RESULT( VG_(do_syscall3)(saved, (UWord)name, ARG2, ARG3)); + SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name, ARG2, ARG3)); } } - if ((Int)RES > 0) + if (SUCCESS && RES > 0) POST_MEM_WRITE( ARG2, RES ); } -PRE(sys_readv, MayBlock) +PRE(sys_readv) { Int i; struct vki_iovec * vec; + *flags |= SfMayBlock; PRINT("sys_readv ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3); PRE_REG_READ3(ssize_t, "readv", unsigned long, fd, const struct iovec *, vector, unsigned long, count); if (!VG_(fd_allowed)(ARG1, "readv", tid, False)) { - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); } else { PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) ); @@ -4855,6 +4713,7 @@ PRE(sys_readv, MayBlock) POST(sys_readv) { + vg_assert(SUCCESS); if (RES > 0) { Int i; struct vki_iovec * vec = (struct vki_iovec *)ARG2; @@ -4871,7 +4730,7 @@ POST(sys_readv) } } -PRE(sys_rename, 0) +PRE(sys_rename) { PRINT("sys_rename ( %p, %p )", ARG1, ARG2 ); PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath); @@ -4879,41 +4738,42 @@ PRE(sys_rename, 0) PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 ); } -PRE(sys_rmdir, MayBlock) -{ - PRINT("sys_rmdir ( %p )", ARG1); - PRE_REG_READ1(long, "rmdir", const char *, pathname); - PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 ); -} - -PRE(sys_sched_setparam, 0) -{ - PRINT("sched_setparam ( %d, %p )", ARG1, ARG2 ); - PRE_REG_READ2(long, "sched_setparam", - vki_pid_t, pid, struct sched_param *, p); - PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) ); -} - -POST(sys_sched_setparam) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); -} - -PRE(sys_sched_getparam, 0) -{ - PRINT("sched_getparam ( %d, %p )", ARG1, ARG2 ); - PRE_REG_READ2(long, "sched_getparam", - vki_pid_t, pid, struct sched_param *, p); - PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) ); -} - -POST(sys_sched_getparam) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); -} - -PRE(sys_select, MayBlock) -{ +//zz PRE(sys_rmdir, SfMayBlock) +//zz { +//zz PRINT("sys_rmdir ( %p )", ARG1); +//zz PRE_REG_READ1(long, "rmdir", const char *, pathname); +//zz PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 ); +//zz } +//zz +//zz PRE(sys_sched_setparam, 0) +//zz { +//zz PRINT("sched_setparam ( %d, %p )", ARG1, ARG2 ); +//zz PRE_REG_READ2(long, "sched_setparam", +//zz vki_pid_t, pid, struct sched_param *, p); +//zz PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) ); +//zz } +//zz +//zz POST(sys_sched_setparam) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +//zz } +//zz +//zz PRE(sys_sched_getparam, 0) +//zz { +//zz PRINT("sched_getparam ( %d, %p )", ARG1, ARG2 ); +//zz PRE_REG_READ2(long, "sched_getparam", +//zz vki_pid_t, pid, struct sched_param *, p); +//zz PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) ); +//zz } +//zz +//zz POST(sys_sched_getparam) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) ); +//zz } + +PRE(sys_select) +{ + *flags |= SfMayBlock; PRINT("sys_select ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); PRE_REG_READ5(long, "select", int, n, vki_fd_set *, readfds, vki_fd_set *, writefds, @@ -4932,65 +4792,65 @@ PRE(sys_select, MayBlock) PRE_MEM_READ( "select(timeout)", ARG5, sizeof(struct vki_timeval) ); } -PRE(sys_setgid16, 0) -{ - PRINT("sys_setgid16 ( %d )", ARG1); - PRE_REG_READ1(long, "setgid16", vki_old_gid_t, gid); -} - -PRE(sys_setgid, 0) -{ - PRINT("sys_setgid ( %d )", ARG1); - PRE_REG_READ1(long, "setgid", vki_gid_t, gid); -} - -PRE(sys_setsid, 0) -{ - PRINT("sys_setsid ( )"); - PRE_REG_READ0(long, "setsid"); -} - -PRE(sys_setgroups16, 0) -{ - PRINT("sys_setgroups16 ( %llu, %p )", (ULong)ARG1, ARG2); - PRE_REG_READ2(long, "setgroups16", int, size, vki_old_gid_t *, list); - if (ARG1 > 0) - PRE_MEM_READ( "setgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); -} - -PRE(sys_setgroups, 0) -{ - PRINT("setgroups ( %llu, %p )", (ULong)ARG1, ARG2); - PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list); - if (ARG1 > 0) - PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); -} - -PRE(sys_setpgid, 0) -{ - PRINT("setpgid ( %d, %d )", ARG1, ARG2); - PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid); -} - -PRE(sys_setregid, 0) -{ - PRINT("sys_setregid ( %d, %d )", ARG1, ARG2); - PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid); -} - -PRE(sys_setreuid16, 0) -{ - PRINT("setreuid16 ( 0x%x, 0x%x )", ARG1, ARG2); - PRE_REG_READ2(long, "setreuid16", vki_old_uid_t, ruid, vki_old_uid_t, euid); -} - -PRE(sys_setreuid, 0) -{ - PRINT("sys_setreuid ( 0x%x, 0x%x )", ARG1, ARG2); - PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid); -} - -PRE(sys_setrlimit, 0) +//zz PRE(sys_setgid16, 0) +//zz { +//zz PRINT("sys_setgid16 ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setgid16", vki_old_gid_t, gid); +//zz } +//zz +//zz PRE(sys_setgid, 0) +//zz { +//zz PRINT("sys_setgid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setgid", vki_gid_t, gid); +//zz } +//zz +//zz PRE(sys_setsid, 0) +//zz { +//zz PRINT("sys_setsid ( )"); +//zz PRE_REG_READ0(long, "setsid"); +//zz } +//zz +//zz PRE(sys_setgroups16, 0) +//zz { +//zz PRINT("sys_setgroups16 ( %llu, %p )", (ULong)ARG1, ARG2); +//zz PRE_REG_READ2(long, "setgroups16", int, size, vki_old_gid_t *, list); +//zz if (ARG1 > 0) +//zz PRE_MEM_READ( "setgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) ); +//zz } +//zz +//zz PRE(sys_setgroups, 0) +//zz { +//zz PRINT("setgroups ( %llu, %p )", (ULong)ARG1, ARG2); +//zz PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list); +//zz if (ARG1 > 0) +//zz PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) ); +//zz } +//zz +//zz PRE(sys_setpgid, 0) +//zz { +//zz PRINT("setpgid ( %d, %d )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid); +//zz } +//zz +//zz PRE(sys_setregid, 0) +//zz { +//zz PRINT("sys_setregid ( %d, %d )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid); +//zz } +//zz +//zz PRE(sys_setreuid16, 0) +//zz { +//zz PRINT("setreuid16 ( 0x%x, 0x%x )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "setreuid16", vki_old_uid_t, ruid, vki_old_uid_t, euid); +//zz } +//zz +//zz PRE(sys_setreuid, 0) +//zz { +//zz PRINT("sys_setreuid ( 0x%x, 0x%x )", ARG1, ARG2); +//zz PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid); +//zz } + +PRE(sys_setrlimit) { PRINT("sys_setrlimit ( %d, %p )", ARG1,ARG2); PRE_REG_READ2(long, "setrlimit", @@ -5000,372 +4860,97 @@ PRE(sys_setrlimit, 0) if (ARG1 == VKI_RLIMIT_NOFILE) { if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) || ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) { - SET_RESULT( -VKI_EPERM ); + SET_STATUS_Failure( VKI_EPERM ); } else { VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur; - SET_RESULT( 0 ); + SET_STATUS_Success( 0 ); } } else if (ARG1 == VKI_RLIMIT_DATA) { if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max || ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) { - SET_RESULT( -VKI_EPERM ); + SET_STATUS_Failure( VKI_EPERM ); } else { VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2; - SET_RESULT( 0 ); + SET_STATUS_Success( 0 ); } } else if (ARG1 == VKI_RLIMIT_STACK && tid == 1) { if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max || ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) { - SET_RESULT( -VKI_EPERM ); + SET_STATUS_Failure( VKI_EPERM ); } else { - VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur; + VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur; VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2; - SET_RESULT( 0 ); + SET_STATUS_Success( 0 ); } } } -PRE(sys_setuid16, 0) +PRE(sys_setuid16) { PRINT("sys_setuid16 ( %d )", ARG1); PRE_REG_READ1(long, "setuid16", vki_old_uid_t, uid); } -PRE(sys_setuid, 0) -{ - PRINT("sys_setuid ( %d )", ARG1); - PRE_REG_READ1(long, "setuid", vki_uid_t, uid); -} - -PRE(sys_socketcall, MayBlock) -{ -# define ARG2_0 (((UWord*)ARG2)[0]) -# define ARG2_1 (((UWord*)ARG2)[1]) -# define ARG2_2 (((UWord*)ARG2)[2]) -# define ARG2_3 (((UWord*)ARG2)[3]) -# define ARG2_4 (((UWord*)ARG2)[4]) -# define ARG2_5 (((UWord*)ARG2)[5]) - - PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args); - - switch (ARG1 /* request */) { - - case VKI_SYS_SOCKETPAIR: - /* int socketpair(int d, int type, int protocol, int sv[2]); */ - PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) ); - VG_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 ); - break; - - case VKI_SYS_SOCKET: - /* int socket(int domain, int type, int protocol); */ - PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) ); - break; - - case VKI_SYS_BIND: - /* int bind(int sockfd, struct sockaddr *my_addr, - int addrlen); */ - PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) ); - VG_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_LISTEN: - /* int listen(int s, int backlog); */ - PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) ); - break; - - case VKI_SYS_ACCEPT: { - /* int accept(int s, struct sockaddr *addr, int *addrlen); */ - PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) ); - VG_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - } - - case VKI_SYS_SENDTO: - /* int sendto(int s, const void *msg, int len, - unsigned int flags, - const struct sockaddr *to, int tolen); */ - PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) ); - VG_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4, ARG2_5 ); - break; - - case VKI_SYS_SEND: - /* int send(int s, const void *msg, size_t len, int flags); */ - PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) ); - VG_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_RECVFROM: - /* int recvfrom(int s, void *buf, int len, unsigned int flags, - struct sockaddr *from, int *fromlen); */ - PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) ); - VG_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4, ARG2_5 ); - break; - - case VKI_SYS_RECV: - /* int recv(int s, void *buf, int len, unsigned int flags); */ - /* man 2 recv says: - The recv call is normally used only on a connected socket - (see connect(2)) and is identical to recvfrom with a NULL - from parameter. - */ - PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) ); - VG_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_CONNECT: - /* int connect(int sockfd, - struct sockaddr *serv_addr, int addrlen ); */ - PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) ); - VG_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_SETSOCKOPT: - /* int setsockopt(int s, int level, int optname, - const void *optval, int optlen); */ - PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) ); - VG_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4 ); - break; - - case VKI_SYS_GETSOCKOPT: - /* int getsockopt(int s, int level, int optname, - void *optval, socklen_t *optlen); */ - PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) ); - VG_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4 ); - break; - - case VKI_SYS_GETSOCKNAME: - /* int getsockname(int s, struct sockaddr* name, int* namelen) */ - PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) ); - VG_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_GETPEERNAME: - /* int getpeername(int s, struct sockaddr* name, int* namelen) */ - PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) ); - VG_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_SHUTDOWN: - /* int shutdown(int s, int how); */ - PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) ); - break; - - case VKI_SYS_SENDMSG: { - /* int sendmsg(int s, const struct msghdr *msg, int flags); */ - - /* this causes warnings, and I don't get why. glibc bug? - * (after all it's glibc providing the arguments array) - PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) ); - */ - VG_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 ); - break; - } - - case VKI_SYS_RECVMSG: { - /* int recvmsg(int s, struct msghdr *msg, int flags); */ - - /* this causes warnings, and I don't get why. glibc bug? - * (after all it's glibc providing the arguments array) - PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) ); - */ - VG_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 ); - break; - } - - default: - VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1); - SET_RESULT( -VKI_EINVAL ); - break; - } -# undef ARG2_0 -# undef ARG2_1 -# undef ARG2_2 -# undef ARG2_3 -# undef ARG2_4 -# undef ARG2_5 -} - -POST(sys_socketcall) -{ -# define ARG2_0 (((UWord*)ARG2)[0]) -# define ARG2_1 (((UWord*)ARG2)[1]) -# define ARG2_2 (((UWord*)ARG2)[2]) -# define ARG2_3 (((UWord*)ARG2)[3]) -# define ARG2_4 (((UWord*)ARG2)[4]) -# define ARG2_5 (((UWord*)ARG2)[5]) - - UWord r; - switch (ARG1 /* request */) { - - case VKI_SYS_SOCKETPAIR: - VG_(generic_POST_sys_socketpair)( tid, RES, ARG2_0, - ARG2_1, ARG2_2, ARG2_3 ); - break; - - case VKI_SYS_SOCKET: - r = VG_(generic_POST_sys_socket)( tid, RES ); - SET_RESULT(r); - break; - - case VKI_SYS_BIND: - /* int bind(int sockfd, struct sockaddr *my_addr, - int addrlen); */ - break; - - case VKI_SYS_LISTEN: - /* int listen(int s, int backlog); */ - break; - - case VKI_SYS_ACCEPT: - /* int accept(int s, struct sockaddr *addr, int *addrlen); */ - r = VG_(generic_POST_sys_accept)( tid, RES, ARG2_0, ARG2_1, ARG2_2 ); - SET_RESULT(r); - break; - - case VKI_SYS_SENDTO: - break; - - case VKI_SYS_SEND: - break; - - case VKI_SYS_RECVFROM: - VG_(generic_POST_sys_recvfrom)( tid, RES, ARG2_0, ARG2_1, ARG2_2, - ARG2_3, ARG2_4, ARG2_5 ); - break; - - case VKI_SYS_RECV: - VG_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_CONNECT: - break; - - case VKI_SYS_SETSOCKOPT: - break; - - case VKI_SYS_GETSOCKOPT: - VG_(generic_POST_sys_getsockopt)( tid, RES, ARG2_0, ARG2_1, - ARG2_2, ARG2_3, ARG2_4 ); - break; - - case VKI_SYS_GETSOCKNAME: - VG_(generic_POST_sys_getsockname)( tid, RES, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_GETPEERNAME: - VG_(generic_POST_sys_getpeername)( tid, RES, ARG2_0, ARG2_1, ARG2_2 ); - break; - - case VKI_SYS_SHUTDOWN: - break; - - case VKI_SYS_SENDMSG: - break; - - case VKI_SYS_RECVMSG: - VG_(generic_POST_sys_recvmsg)( tid, RES, ARG2_0, ARG2_1 ); - break; - - default: - VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1); - VG_(core_panic)("... bye!\n"); - break; /*NOTREACHED*/ - } -# undef ARG2_0 -# undef ARG2_1 -# undef ARG2_2 -# undef ARG2_3 -# undef ARG2_4 -# undef ARG2_5 -} - -PRE(sys_newstat, 0) -{ - PRINT("sys_newstat ( %p(%s), %p )", ARG1,ARG1,ARG2); - PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf); - PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 ); - PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) ); -} - -POST(sys_newstat) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); -} - -PRE(sys_statfs, 0) -{ - PRINT("sys_statfs ( %p, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf); - PRE_MEM_RASCIIZ( "statfs(path)", ARG1 ); - PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) ); -} - -POST(sys_statfs) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); -} - -PRE(sys_statfs64, 0) -{ - PRINT("sys_statfs64 ( %p, %llu, %p )",ARG1,(ULong)ARG2,ARG3); - PRE_REG_READ3(long, "statfs64", - const char *, path, vki_size_t, size, struct statfs64 *, buf); - PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 ); - PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 ); -} - -POST(sys_statfs64) -{ - POST_MEM_WRITE( ARG3, ARG2 ); -} - -PRE(sys_symlink, MayBlock) -{ - PRINT("sys_symlink ( %p, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath); - PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 ); - PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 ); -} - -// See comment above PRE(sys_lstat64) for an explanation of this #ifdef. -#ifndef __amd64__ -PRE(sys_stat64, 0) -{ - PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf); - PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 ); - PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) ); -} - -POST(sys_stat64) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); -} - -PRE(sys_fstat64, 0) -{ - PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2); - PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf); - PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) ); -} - -POST(sys_fstat64) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); -} -#endif - -PRE(sys_time, 0) +//zz PRE(sys_setuid, 0) +//zz { +//zz PRINT("sys_setuid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setuid", vki_uid_t, uid); +//zz } + +//zz PRE(sys_newstat, 0) +//zz { +//zz PRINT("sys_newstat ( %p(%s), %p )", ARG1,ARG1,ARG2); +//zz PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf); +//zz PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 ); +//zz PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) ); +//zz } +//zz +//zz POST(sys_newstat) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); +//zz } +//zz +//zz PRE(sys_statfs, 0) +//zz { +//zz PRINT("sys_statfs ( %p, %p )",ARG1,ARG2); +//zz PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf); +//zz PRE_MEM_RASCIIZ( "statfs(path)", ARG1 ); +//zz PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) ); +//zz } +//zz +//zz POST(sys_statfs) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) ); +//zz } +//zz +//zz PRE(sys_statfs64, 0) +//zz { +//zz PRINT("sys_statfs64 ( %p, %llu, %p )",ARG1,(ULong)ARG2,ARG3); +//zz PRE_REG_READ3(long, "statfs64", +//zz const char *, path, vki_size_t, size, struct statfs64 *, buf); +//zz PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 ); +//zz PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 ); +//zz } +//zz +//zz POST(sys_statfs64) +//zz { +//zz POST_MEM_WRITE( ARG3, ARG2 ); +//zz } +//zz +//zz PRE(sys_symlink, SfMayBlock) +//zz { +//zz PRINT("sys_symlink ( %p, %p )",ARG1,ARG2); +//zz PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath); +//zz PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 ); +//zz PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 ); +//zz } + +PRE(sys_time) { /* time_t time(time_t *t); */ PRINT("sys_time ( %p )",ARG1); @@ -5382,34 +4967,35 @@ POST(sys_time) } } -PRE(sys_times, 0) -{ - PRINT("sys_times ( %p )", ARG1); - PRE_REG_READ1(long, "times", struct tms *, buf); - PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) ); -} - -POST(sys_times) -{ - if (ARG1 != 0) { - POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) ); - } -} - -PRE(sys_umask, 0) -{ - PRINT("sys_umask ( %d )", ARG1); - PRE_REG_READ1(long, "umask", int, mask); -} - -PRE(sys_unlink, MayBlock) -{ +//zz PRE(sys_times, 0) +//zz { +//zz PRINT("sys_times ( %p )", ARG1); +//zz PRE_REG_READ1(long, "times", struct tms *, buf); +//zz PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) ); +//zz } +//zz +//zz POST(sys_times) +//zz { +//zz if (ARG1 != 0) { +//zz POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) ); +//zz } +//zz } +//zz +//zz PRE(sys_umask, 0) +//zz { +//zz PRINT("sys_umask ( %d )", ARG1); +//zz PRE_REG_READ1(long, "umask", int, mask); +//zz } + +PRE(sys_unlink) +{ + *flags |= SfMayBlock; PRINT("sys_unlink ( %p(%s) )", ARG1,ARG1); PRE_REG_READ1(long, "unlink", const char *, pathname); PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 ); } -PRE(sys_newuname, 0) +PRE(sys_newuname) { PRINT("sys_newuname ( %p )", ARG1); PRE_REG_READ1(long, "uname", struct new_utsname *, buf); @@ -5423,17 +5009,18 @@ POST(sys_newuname) } } -PRE(sys_utime, MayBlock) -{ - PRINT("sys_utime ( %p, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf); - PRE_MEM_RASCIIZ( "utime(filename)", ARG1 ); - if (ARG2 != 0) - PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) ); -} +//zz PRE(sys_utime, SfMayBlock) +//zz { +//zz PRINT("sys_utime ( %p, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf); +//zz PRE_MEM_RASCIIZ( "utime(filename)", ARG1 ); +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) ); +//zz } -PRE(sys_waitpid, MayBlock) +PRE(sys_waitpid) { + *flags |= SfMayBlock; PRINT("sys_waitpid ( %d, %p, %d )", ARG1,ARG2,ARG3); PRE_REG_READ3(long, "waitpid", vki_pid_t, pid, unsigned int *, status, int, options); @@ -5448,8 +5035,9 @@ POST(sys_waitpid) POST_MEM_WRITE( ARG2, sizeof(int) ); } -PRE(sys_wait4, MayBlock) +PRE(sys_wait4) { + *flags |= SfMayBlock; PRINT("sys_wait4 ( %d, %p, %d, %p )", ARG1,ARG2,ARG3,ARG4); PRE_REG_READ4(long, "wait4", @@ -5469,16 +5057,17 @@ POST(sys_wait4) POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) ); } -PRE(sys_writev, MayBlock) +PRE(sys_writev) { Int i; struct vki_iovec * vec; + *flags |= SfMayBlock; PRINT("sys_writev ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3); PRE_REG_READ3(ssize_t, "writev", unsigned long, fd, const struct iovec *, vector, unsigned long, count); if (!VG_(fd_allowed)(ARG1, "writev", tid, False)) { - SET_RESULT( -VKI_EBADF ); + SET_STATUS_Failure( VKI_EBADF ); } else { PRE_MEM_READ( "writev(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) ); @@ -5492,69 +5081,70 @@ PRE(sys_writev, MayBlock) } } -PRE(sys_utimes, 0) -{ - PRINT("sys_utimes ( %p, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp); - PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 ); - if (ARG2 != 0) - PRE_MEM_READ( "utimes(tvp)", ARG2, sizeof(struct vki_timeval) ); -} - -PRE(sys_sched_setaffinity, 0) -{ - PRINT("sched_setaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "sched_setaffinity", - vki_pid_t, pid, unsigned int, len, unsigned long *, mask); - PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2); -} - -PRE(sys_sched_getaffinity, 0) -{ - PRINT("sched_getaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "sched_getaffinity", - vki_pid_t, pid, unsigned int, len, unsigned long *, mask); - PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2); -} - -POST(sys_sched_getaffinity) -{ - POST_MEM_WRITE(ARG3, ARG2); -} - -PRE(sys_acct, 0) -{ - PRINT("sys_acct ( %p )", ARG1); - PRE_REG_READ1(long, "acct", const char *, filename); - PRE_MEM_RASCIIZ( "acct(filename)", ARG1 ); -} - -PRE(sys_pause, MayBlock) -{ +//zz PRE(sys_utimes, 0) +//zz { +//zz PRINT("sys_utimes ( %p, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp); +//zz PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 ); +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "utimes(tvp)", ARG2, sizeof(struct vki_timeval) ); +//zz } +//zz +//zz PRE(sys_sched_setaffinity, 0) +//zz { +//zz PRINT("sched_setaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "sched_setaffinity", +//zz vki_pid_t, pid, unsigned int, len, unsigned long *, mask); +//zz PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2); +//zz } +//zz +//zz PRE(sys_sched_getaffinity, 0) +//zz { +//zz PRINT("sched_getaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "sched_getaffinity", +//zz vki_pid_t, pid, unsigned int, len, unsigned long *, mask); +//zz PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2); +//zz } +//zz +//zz POST(sys_sched_getaffinity) +//zz { +//zz POST_MEM_WRITE(ARG3, ARG2); +//zz } +//zz +//zz PRE(sys_acct, 0) +//zz { +//zz PRINT("sys_acct ( %p )", ARG1); +//zz PRE_REG_READ1(long, "acct", const char *, filename); +//zz PRE_MEM_RASCIIZ( "acct(filename)", ARG1 ); +//zz } + +PRE(sys_pause) +{ + *flags |= SfMayBlock; PRINT("sys_pause ( )"); PRE_REG_READ0(long, "pause"); } -// XXX: x86-specific -PRE(sys_sigsuspend, MayBlock) -{ - /* The C library interface to sigsuspend just takes a pointer to - a signal mask but this system call has three arguments - the first - two don't appear to be used by the kernel and are always passed as - zero by glibc and the third is the first word of the signal mask - so only 32 signals are supported. - - In fact glibc normally uses rt_sigsuspend if it is available as - that takes a pointer to the signal mask so supports more signals. - */ - PRINT("sys_sigsuspend ( %d, %d, %d )", ARG1,ARG2,ARG3 ); - PRE_REG_READ3(int, "sigsuspend", - int, history0, int, history1, - vki_old_sigset_t, mask); -} +//zz // XXX: x86-specific +//zz PRE(sys_sigsuspend, SfMayBlock) +//zz { +//zz /* The C library interface to sigsuspend just takes a pointer to +//zz a signal mask but this system call has three arguments - the first +//zz two don't appear to be used by the kernel and are always passed as +//zz zero by glibc and the third is the first word of the signal mask +//zz so only 32 signals are supported. +//zz +//zz In fact glibc normally uses rt_sigsuspend if it is available as +//zz that takes a pointer to the signal mask so supports more signals. +//zz */ +//zz PRINT("sys_sigsuspend ( %d, %d, %d )", ARG1,ARG2,ARG3 ); +//zz PRE_REG_READ3(int, "sigsuspend", +//zz int, history0, int, history1, +//zz vki_old_sigset_t, mask); +//zz } // XXX: x86-specific -PRE(sys_rt_sigsuspend, MayBlock) +PRE(sys_rt_sigsuspend) { /* The C library interface to sigsuspend just takes a pointer to a signal mask but this system call has two arguments - a pointer @@ -5562,6 +5152,7 @@ PRE(sys_rt_sigsuspend, MayBlock) on the size being equal to sizeof(sigset_t) however and will just return EINVAL if it isn't. */ + *flags |= SfMayBlock; PRINT("sys_rt_sigsuspend ( %p, %d )", ARG1,ARG2 ); PRE_REG_READ2(int, "rt_sigsuspend", vki_sigset_t *, mask, vki_size_t, size) if (ARG1 != (Addr)NULL) { @@ -5569,8 +5160,9 @@ PRE(sys_rt_sigsuspend, MayBlock) } } -PRE(sys_rt_sigtimedwait, MayBlock) +PRE(sys_rt_sigtimedwait) { + *flags |= SfMayBlock; PRINT("sys_rt_sigtimedwait ( %p, %p, %p, %lld )", ARG1,ARG2,ARG3,(ULong)ARG4); PRE_REG_READ4(long, "rt_sigtimedwait", @@ -5590,28 +5182,28 @@ POST(sys_rt_sigtimedwait) POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) ); } -PRE(sys_rt_sigqueueinfo, 0) -{ - PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "rt_sigqueueinfo", - int, pid, int, sig, vki_siginfo_t *, uinfo); - if (ARG2 != 0) - PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); -} - -POST(sys_rt_sigqueueinfo) -{ - PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "rt_sigqueueinfo", - int, pid, int, sig, vki_siginfo_t *, uinfo); - if (ARG2 != 0) - PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); - if (!VG_(client_signal_OK)(ARG2)) - SET_RESULT( -VKI_EINVAL ); -} +//zz PRE(sys_rt_sigqueueinfo, 0) +//zz { +//zz PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "rt_sigqueueinfo", +//zz int, pid, int, sig, vki_siginfo_t *, uinfo); +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); +//zz } +//zz +//zz POST(sys_rt_sigqueueinfo) +//zz { +//zz PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "rt_sigqueueinfo", +//zz int, pid, int, sig, vki_siginfo_t *, uinfo); +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) ); +//zz if (!VG_(client_signal_OK)(ARG2)) +//zz SET_STATUS_( -VKI_EINVAL ); +//zz } // XXX: x86-specific -PRE(sys_sigaltstack, Special) +PRE(sys_sigaltstack) { /* int sigaltstack(const stack_t *ss, stack_t *oss); */ PRINT("sigaltstack ( %p, %p )",ARG1,ARG2); @@ -5624,18 +5216,21 @@ PRE(sys_sigaltstack, Special) PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) ); } - SET_RESULT( VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1, - (vki_stack_t*)ARG2) ); + SET_STATUS_from_SysRes( + VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1, + (vki_stack_t*)ARG2) + ); } POST(sys_sigaltstack) { + vg_assert(SUCCESS); if (RES == 0 && ARG2 != 0) POST_MEM_WRITE( ARG2, sizeof(vki_stack_t)); } // XXX: x86-specific -PRE(sys_rt_sigaction, Special) +PRE(sys_rt_sigaction) { PRINT("sys_rt_sigaction ( %d, %p, %p, %d )", ARG1,ARG2,ARG3,ARG4); PRE_REG_READ4(long, "rt_sigaction", @@ -5651,7 +5246,7 @@ PRE(sys_rt_sigaction, Special) // sys_rt_sigaction... perhaps this function should be renamed // VG_(do_sys_rt_sigaction)() --njn - SET_RESULT( + SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2, (struct vki_sigaction *)ARG3) ); @@ -5659,6 +5254,7 @@ PRE(sys_rt_sigaction, Special) POST(sys_rt_sigaction) { + vg_assert(SUCCESS); if (RES == 0 && ARG3 != 0) POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); } @@ -5666,8 +5262,8 @@ POST(sys_rt_sigaction) // XXX: This syscall is not used on amd64 -- it only provides // sys_rt_sigprocmask, which uses sigset_t rather than old_sigset_t. // This wrapper is only suitable for 32-bit architectures. -#ifndef __amd64__ -PRE(sys_sigprocmask, Special) +#if defined(VGP_x86_linux) +PRE(sys_sigprocmask) { vki_old_sigset_t* set; vki_old_sigset_t* oldset; @@ -5692,7 +5288,7 @@ PRE(sys_sigprocmask, Special) if (set) bigger_set.sig[0] = *(vki_old_sigset_t*)set; - SET_RESULT( + SET_STATUS_from_SysRes( VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, set ? &bigger_set : NULL, oldset ? &bigger_oldset : NULL) @@ -5700,16 +5296,20 @@ PRE(sys_sigprocmask, Special) if (oldset) *oldset = bigger_oldset.sig[0]; + + if (SUCCESS) + *flags |= SfPollAfter; } POST(sys_sigprocmask) { + vg_assert(SUCCESS); if (RES == 0 && ARG3 != 0) POST_MEM_WRITE( ARG3, sizeof(vki_old_sigset_t)); } #endif -PRE(sys_rt_sigprocmask, Special) +PRE(sys_rt_sigprocmask) { PRINT("sys_rt_sigprocmask ( %d, %p, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4); PRE_REG_READ4(long, "rt_sigprocmask", @@ -5722,235 +5322,240 @@ PRE(sys_rt_sigprocmask, Special) // Like the kernel, we fail if the sigsetsize is not exactly what we expect. if (sizeof(vki_sigset_t) != ARG4) - SET_RESULT( -VKI_EMFILE ); + SET_STATUS_Failure( VKI_EMFILE ); else { - SET_RESULT( VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, + SET_STATUS_from_SysRes( + VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/, (vki_sigset_t*) ARG2, (vki_sigset_t*) ARG3 ) ); } + + if (SUCCESS) + *flags |= SfPollAfter; } POST(sys_rt_sigprocmask) { + vg_assert(SUCCESS); if (RES == 0 && ARG3 != 0) POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t)); } -PRE(sys_sigpending, 0) -{ - PRINT( "sys_sigpending ( %p )", ARG1 ); - PRE_REG_READ1(long, "sigpending", vki_old_sigset_t *, set); - PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_old_sigset_t)); -} - -POST(sys_sigpending) -{ - POST_MEM_WRITE( ARG1, sizeof(vki_old_sigset_t) ) ; -} - -PRE(sys_rt_sigpending, 0) -{ - PRINT( "sys_rt_sigpending ( %p )", ARG1 ); - PRE_REG_READ2(long, "rt_sigpending", - vki_sigset_t *, set, vki_size_t, sigsetsize); - PRE_MEM_WRITE( "rt_sigpending(set)", ARG1, sizeof(vki_sigset_t)); -} - -POST(sys_rt_sigpending) -{ - POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ; -} - -PRE(sys_mq_open, 0) -{ - PRINT("sys_mq_open( %p(%s), %d, %lld, %p )", - ARG1,ARG1,ARG2,(ULong)ARG3,ARG4); - PRE_REG_READ4(long, "mq_open", - const char *, name, int, oflag, vki_mode_t, mode, - struct mq_attr *, attr); - PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 ); - if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) { - const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4; - PRE_MEM_READ( "mq_open(attr->mq_maxmsg)", - (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); - PRE_MEM_READ( "mq_open(attr->mq_msgsize)", - (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); - } -} - -POST(sys_mq_open) -{ - if (!VG_(fd_allowed)(RES, "mq_open", tid, True)) { - VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); - } else { - if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); - } -} - -PRE(sys_mq_unlink, 0) -{ - PRINT("sys_mq_unlink ( %p(%s) )", ARG1,ARG1); - PRE_REG_READ1(long, "mq_unlink", const char *, name); - PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 ); -} - -PRE(sys_mq_timedsend, MayBlock) -{ - PRINT("sys_mq_timedsend ( %d, %p, %llu, %d, %p )", - ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); - PRE_REG_READ5(long, "mq_timedsend", - vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len, - unsigned int, msg_prio, const struct timespec *, abs_timeout); - if (!VG_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) { - SET_RESULT( -VKI_EBADF ); - } else { - PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 ); - if (ARG5 != 0) - PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5, - sizeof(struct vki_timespec) ); - } -} - -PRE(sys_mq_timedreceive, MayBlock) -{ - PRINT("sys_mq_timedreceive( %d, %p, %llu, %p, %p )", - ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); - PRE_REG_READ5(ssize_t, "mq_timedreceive", - vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len, - unsigned int *, msg_prio, - const struct timespec *, abs_timeout); - if (!VG_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) { - SET_RESULT( -VKI_EBADF ); - } else { - PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 ); - if (ARG4 != 0) - PRE_MEM_WRITE( "mq_timedreceive(msg_prio)", - ARG4, sizeof(unsigned int) ); - if (ARG5 != 0) - PRE_MEM_READ( "mq_timedreceive(abs_timeout)", - ARG5, sizeof(struct vki_timespec) ); - } -} - -POST(sys_mq_timedreceive) -{ - POST_MEM_WRITE( ARG2, ARG3 ); - if (ARG4 != 0) - POST_MEM_WRITE( ARG4, sizeof(unsigned int) ); -} - -PRE(sys_mq_notify, 0) -{ - PRINT("sys_mq_notify( %d, %p )", ARG1,ARG2 ); - PRE_REG_READ2(long, "mq_notify", - vki_mqd_t, mqdes, const struct sigevent *, notification); - if (!VG_(fd_allowed)(ARG1, "mq_notify", tid, False)) - SET_RESULT( -VKI_EBADF ); - else if (ARG2 != 0) - PRE_MEM_READ( "mq_notify(notification)", - ARG2, sizeof(struct vki_sigevent) ); -} - -PRE(sys_mq_getsetattr, 0) -{ - PRINT("sys_mq_getsetattr( %d, %p, %p )", ARG1,ARG2,ARG3 ); - PRE_REG_READ3(long, "mq_getsetattr", - vki_mqd_t, mqdes, const struct mq_attr *, mqstat, - struct mq_attr *, omqstat); - if (!VG_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) { - SET_RESULT( -VKI_EBADF ); - } else { - if (ARG2 != 0) { - const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2; - PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)", - (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); - } - if (ARG3 != 0) - PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3, - sizeof(struct vki_mq_attr) ); - } -} - -POST(sys_mq_getsetattr) -{ - if (ARG3 != 0) - POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) ); -} - -PRE(sys_timer_create, 0) -{ - PRINT("sys_timer_create( %d, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "timer_create", - vki_clockid_t, clockid, struct sigevent *, evp, - vki_timer_t *, timerid); - if (ARG2 != 0) - PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) ); - PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) ); -} - -POST(sys_timer_create) -{ - POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) ); -} - -PRE(sys_timer_settime, 0) -{ - PRINT("sys_timer_settime( %lld, %d, %p, %p )", (ULong)ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(long, "timer_settime", - vki_timer_t, timerid, int, flags, - const struct itimerspec *, value, - struct itimerspec *, ovalue); - PRE_MEM_READ( "timer_settime(value)", ARG3, - sizeof(struct vki_itimerspec) ); - if (ARG4 != 0) - PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4, - sizeof(struct vki_itimerspec) ); -} - -POST(sys_timer_settime) -{ - if (ARG4 != 0) - POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) ); -} - -PRE(sys_timer_gettime, 0) -{ - PRINT("sys_timer_gettime( %lld, %p )", (ULong)ARG1,ARG2); - PRE_REG_READ2(long, "timer_gettime", - vki_timer_t, timerid, struct itimerspec *, value); - PRE_MEM_WRITE( "timer_gettime(value)", ARG2, - sizeof(struct vki_itimerspec)); -} - -POST(sys_timer_gettime) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) ); -} - -PRE(sys_timer_getoverrun, 0) -{ - PRINT("sys_timer_getoverrun( %p )", ARG1); - PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid); -} - -PRE(sys_timer_delete, 0) -{ - PRINT("sys_timer_delete( %p )", ARG1); - PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); -} - -PRE(sys_clock_settime, 0) -{ - PRINT("sys_clock_settime( %d, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "clock_settime", - vki_clockid_t, clk_id, const struct timespec *, tp); - PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) ); -} - -PRE(sys_clock_gettime, 0) +//zz PRE(sys_sigpending, 0) +//zz { +//zz PRINT( "sys_sigpending ( %p )", ARG1 ); +//zz PRE_REG_READ1(long, "sigpending", vki_old_sigset_t *, set); +//zz PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_old_sigset_t)); +//zz } +//zz +//zz POST(sys_sigpending) +//zz { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_old_sigset_t) ) ; +//zz } +//zz +//zz PRE(sys_rt_sigpending, 0) +//zz { +//zz PRINT( "sys_rt_sigpending ( %p )", ARG1 ); +//zz PRE_REG_READ2(long, "rt_sigpending", +//zz vki_sigset_t *, set, vki_size_t, sigsetsize); +//zz PRE_MEM_WRITE( "rt_sigpending(set)", ARG1, sizeof(vki_sigset_t)); +//zz } +//zz +//zz POST(sys_rt_sigpending) +//zz { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ; +//zz } +//zz +//zz PRE(sys_mq_open, 0) +//zz { +//zz PRINT("sys_mq_open( %p(%s), %d, %lld, %p )", +//zz ARG1,ARG1,ARG2,(ULong)ARG3,ARG4); +//zz PRE_REG_READ4(long, "mq_open", +//zz const char *, name, int, oflag, vki_mode_t, mode, +//zz struct mq_attr *, attr); +//zz PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 ); +//zz if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) { +//zz const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4; +//zz PRE_MEM_READ( "mq_open(attr->mq_maxmsg)", +//zz (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) ); +//zz PRE_MEM_READ( "mq_open(attr->mq_msgsize)", +//zz (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) ); +//zz } +//zz } +//zz +//zz POST(sys_mq_open) +//zz { +//zz if (!VG_(fd_allowed)(RES, "mq_open", tid, True)) { +//zz VG_(close)(RES); +//zz SET_STATUS_( -VKI_EMFILE ); +//zz } else { +//zz if (VG_(clo_track_fds)) +//zz VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); +//zz } +//zz } +//zz +//zz PRE(sys_mq_unlink, 0) +//zz { +//zz PRINT("sys_mq_unlink ( %p(%s) )", ARG1,ARG1); +//zz PRE_REG_READ1(long, "mq_unlink", const char *, name); +//zz PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 ); +//zz } +//zz +//zz PRE(sys_mq_timedsend, SfMayBlock) +//zz { +//zz PRINT("sys_mq_timedsend ( %d, %p, %llu, %d, %p )", +//zz ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); +//zz PRE_REG_READ5(long, "mq_timedsend", +//zz vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len, +//zz unsigned int, msg_prio, const struct timespec *, abs_timeout); +//zz if (!VG_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) { +//zz SET_STATUS_( -VKI_EBADF ); +//zz } else { +//zz PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 ); +//zz if (ARG5 != 0) +//zz PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5, +//zz sizeof(struct vki_timespec) ); +//zz } +//zz } +//zz +//zz PRE(sys_mq_timedreceive, SfMayBlock) +//zz { +//zz PRINT("sys_mq_timedreceive( %d, %p, %llu, %p, %p )", +//zz ARG1,ARG2,(ULong)ARG3,ARG4,ARG5); +//zz PRE_REG_READ5(ssize_t, "mq_timedreceive", +//zz vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len, +//zz unsigned int *, msg_prio, +//zz const struct timespec *, abs_timeout); +//zz if (!VG_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) { +//zz SET_STATUS_( -VKI_EBADF ); +//zz } else { +//zz PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 ); +//zz if (ARG4 != 0) +//zz PRE_MEM_WRITE( "mq_timedreceive(msg_prio)", +//zz ARG4, sizeof(unsigned int) ); +//zz if (ARG5 != 0) +//zz PRE_MEM_READ( "mq_timedreceive(abs_timeout)", +//zz ARG5, sizeof(struct vki_timespec) ); +//zz } +//zz } +//zz +//zz POST(sys_mq_timedreceive) +//zz { +//zz POST_MEM_WRITE( ARG2, ARG3 ); +//zz if (ARG4 != 0) +//zz POST_MEM_WRITE( ARG4, sizeof(unsigned int) ); +//zz } +//zz +//zz PRE(sys_mq_notify, 0) +//zz { +//zz PRINT("sys_mq_notify( %d, %p )", ARG1,ARG2 ); +//zz PRE_REG_READ2(long, "mq_notify", +//zz vki_mqd_t, mqdes, const struct sigevent *, notification); +//zz if (!VG_(fd_allowed)(ARG1, "mq_notify", tid, False)) +//zz SET_STATUS_( -VKI_EBADF ); +//zz else if (ARG2 != 0) +//zz PRE_MEM_READ( "mq_notify(notification)", +//zz ARG2, sizeof(struct vki_sigevent) ); +//zz } +//zz +//zz PRE(sys_mq_getsetattr, 0) +//zz { +//zz PRINT("sys_mq_getsetattr( %d, %p, %p )", ARG1,ARG2,ARG3 ); +//zz PRE_REG_READ3(long, "mq_getsetattr", +//zz vki_mqd_t, mqdes, const struct mq_attr *, mqstat, +//zz struct mq_attr *, omqstat); +//zz if (!VG_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) { +//zz SET_STATUS_( -VKI_EBADF ); +//zz } else { +//zz if (ARG2 != 0) { +//zz const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2; +//zz PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)", +//zz (Addr)&attr->mq_flags, sizeof(attr->mq_flags) ); +//zz } +//zz if (ARG3 != 0) +//zz PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3, +//zz sizeof(struct vki_mq_attr) ); +//zz } +//zz } +//zz +//zz POST(sys_mq_getsetattr) +//zz { +//zz if (ARG3 != 0) +//zz POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) ); +//zz } +//zz +//zz PRE(sys_timer_create, 0) +//zz { +//zz PRINT("sys_timer_create( %d, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "timer_create", +//zz vki_clockid_t, clockid, struct sigevent *, evp, +//zz vki_timer_t *, timerid); +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) ); +//zz PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) ); +//zz } +//zz +//zz POST(sys_timer_create) +//zz { +//zz POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) ); +//zz } +//zz +//zz PRE(sys_timer_settime, 0) +//zz { +//zz PRINT("sys_timer_settime( %lld, %d, %p, %p )", (ULong)ARG1,ARG2,ARG3,ARG4); +//zz PRE_REG_READ4(long, "timer_settime", +//zz vki_timer_t, timerid, int, flags, +//zz const struct itimerspec *, value, +//zz struct itimerspec *, ovalue); +//zz PRE_MEM_READ( "timer_settime(value)", ARG3, +//zz sizeof(struct vki_itimerspec) ); +//zz if (ARG4 != 0) +//zz PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4, +//zz sizeof(struct vki_itimerspec) ); +//zz } +//zz +//zz POST(sys_timer_settime) +//zz { +//zz if (ARG4 != 0) +//zz POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) ); +//zz } +//zz +//zz PRE(sys_timer_gettime, 0) +//zz { +//zz PRINT("sys_timer_gettime( %lld, %p )", (ULong)ARG1,ARG2); +//zz PRE_REG_READ2(long, "timer_gettime", +//zz vki_timer_t, timerid, struct itimerspec *, value); +//zz PRE_MEM_WRITE( "timer_gettime(value)", ARG2, +//zz sizeof(struct vki_itimerspec)); +//zz } +//zz +//zz POST(sys_timer_gettime) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) ); +//zz } +//zz +//zz PRE(sys_timer_getoverrun, 0) +//zz { +//zz PRINT("sys_timer_getoverrun( %p )", ARG1); +//zz PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid); +//zz } +//zz +//zz PRE(sys_timer_delete, 0) +//zz { +//zz PRINT("sys_timer_delete( %p )", ARG1); +//zz PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid); +//zz } +//zz +//zz PRE(sys_clock_settime, 0) +//zz { +//zz PRINT("sys_clock_settime( %d, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "clock_settime", +//zz vki_clockid_t, clk_id, const struct timespec *, tp); +//zz PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) ); +//zz } + +PRE(sys_clock_gettime) { PRINT("sys_clock_gettime( %d, %p )" , ARG1,ARG2); PRE_REG_READ2(long, "clock_gettime", @@ -5963,250 +5568,22 @@ POST(sys_clock_gettime) POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); } -PRE(sys_clock_getres, 0) -{ - PRINT("sys_clock_getres( %d, %p )" , ARG1,ARG2); - // Nb: we can't use "RES" as the param name because that's a macro - // defined above! - PRE_REG_READ2(long, "clock_getres", - vki_clockid_t, clk_id, struct timespec *, res); - PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) ); -} - -POST(sys_clock_getres) -{ - POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); -} - - -/* --------------------------------------------------------------------- - Executing the syscalls - ------------------------------------------------------------------ */ - -static UInt bad_flags = Special; -static void bad_before(ThreadId tid, ThreadState *tst) -{ - VG_(message) - (Vg_DebugMsg,"WARNING: unhandled syscall: %u", (UInt)SYSNO); - if (VG_(clo_verbosity) > 1) { - VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); - } - VG_(message) - (Vg_DebugMsg,"Do not panic. You may be able to fix this easily."); - VG_(message) - (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL."); - - SET_RESULT( -VKI_ENOSYS ); -} - -static const struct SyscallTableEntry bad_sys = - { &bad_flags, bad_before, NULL }; - -static const struct SyscallTableEntry *get_syscall_entry(UInt syscallno) -{ - const struct SyscallTableEntry *sys; +//zz PRE(sys_clock_getres, 0) +//zz { +//zz PRINT("sys_clock_getres( %d, %p )" , ARG1,ARG2); +//zz // Nb: we can't use "RES" as the param name because that's a macro +//zz // defined above! +//zz PRE_REG_READ2(long, "clock_getres", +//zz vki_clockid_t, clk_id, struct timespec *, res); +//zz PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) ); +//zz } +//zz +//zz POST(sys_clock_getres) +//zz { +//zz POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) ); +//zz } - if (syscallno < VGA_(syscall_table_size) && - VGA_(syscall_table)[syscallno].before != NULL) - sys = &VGA_(syscall_table)[syscallno]; - else - sys = &bad_sys; - - return sys; -} - -/* Perform post-syscall actions */ -void VG_(post_syscall) (ThreadId tid) -{ - const struct SyscallTableEntry *sys; - UInt flags; - Bool mayBlock; - ThreadState *tst = VG_(get_ThreadState)(tid); - Int syscallno; - - vg_assert(VG_(is_running_thread)(tid)); - - syscallno = tst->syscallno; - tst->syscallno = -1; - - vg_assert(syscallno != -1); - - sys = get_syscall_entry(syscallno); - flags = *(sys->flags_ptr); - - mayBlock = !!( flags & MayBlock ); - - if (sys->after != NULL && - ((flags & PostOnFail) != 0 || !VG_(is_kerror)(RES))) { - if (0) - VG_(printf)("post_syscall: calling sys_after tid=%d syscallno=%d\n", - tid, syscallno); - (sys->after)(tid, tst); - } - - /* Do any post-syscall actions - - NOTE: this is only called if the syscall completed. If the - syscall was restarted, then it will call the Tool's - pre_syscall again, without calling post_syscall (ie, more - pre's than post's) */ - if (VG_(needs).syscall_wrapper) { - VG_TDICT_CALL(tool_post_syscall, tid, syscallno, RES); - } -} - -/* Add and remove signals from mask so that we end up telling the - kernel the state we actually want rather than what the client - wants. */ -static void sanitize_client_sigmask(ThreadId tid, vki_sigset_t *mask) -{ - VG_(sigdelset)(mask, VKI_SIGKILL); - VG_(sigdelset)(mask, VKI_SIGSTOP); - - VG_(sigdelset)(mask, VKI_SIGVGKILL); /* never block */ -} - -void VG_(client_syscall) ( ThreadId tid ) -{ - ThreadState* tst; - UInt syscallno, flags; - const struct SyscallTableEntry *sys; - Bool isSpecial = False; - Bool mayBlock = False; - Bool runInLWP = False; - Bool syscall_done = False; /* we actually ran the syscall */ - -// VGP_PUSHCC(VgpCoreSysWrap); - - tst = VG_(get_ThreadState)(tid); - - syscallno = (UInt)SYSNO; - - /* the syscall no is in %eax. For syscalls with <= 6 args, - args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp. - For calls with > 6 args, %ebx points to a lump of memory - containing the args. - - The result is returned in %eax. If this value >= 0, the call - succeeded, and this is the return value. If < 0, it failed, and - the negation of this value is errno. To be more specific, - if RES is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1) - (kernel 2.4.9 sources, include/asm-i386/errno.h) - then it indicates an error. Otherwise it doesn't. - - Dirk Mueller (mueller@kde.org) says that values -4095 .. -1 - (inclusive?) indicate error returns. Not sure where the -4095 - comes from. - */ - - vg_assert(VG_(is_running_thread)(tid)); - vg_assert(tst->syscallno == -1); - tst->syscallno = syscallno; - - /* Make sure the tmp signal mask matches the real signal - mask; sigsuspend may change this. */ - vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask)); - - sys = get_syscall_entry(syscallno); - flags = *(sys->flags_ptr); - - /* !! is standard idiom to turn an int->bool */ - isSpecial = !!( flags & Special ); - mayBlock = !!( flags & MayBlock ); - // At most one of these should be true - vg_assert( isSpecial + mayBlock <= 1 ); - - /* Do any pre-syscall actions */ - if (VG_(needs).syscall_wrapper) { - VG_TDICT_CALL(tool_pre_syscall, tid, syscallno); - } - - PRINT("SYSCALL[%d,%d](%3d)%s%s:", - VG_(getpid)(), tid, syscallno, - isSpecial ? " special" : "", - runInLWP ? " runInLWP" : ""); - - tst->syscall_result_set = False; - - if (isSpecial) { - /* "Special" syscalls are implemented by Valgrind internally, - and do not generate real kernel calls. The expectation, - therefore, is that the "before" function not only does the - appropriate tests, but also performs the syscall itself and - sets the result. Special syscalls cannot block. */ - vg_assert(!mayBlock && !runInLWP); - - (sys->before)(tst->tid, tst); - /* This *must* result in tst->syscall_result_set becoming - True. */ - - // vg_assert(tst->sys_flags == flags); - vg_assert(tst->syscall_result_set == True); - - PRINT(" --> %lld (0x%llx)\n", (Long)(Word)RES, (ULong)RES); - syscall_done = True; - } else { - (sys->before)(tst->tid, tst); - /* This *may* result in tst->syscall_result_set becoming - True. */ - - if (tst->syscall_result_set) { - /* "before" decided to provide a syscall result itself, so - don't do anything - just pretend the syscall happened. */ - PRINT(" ==> %lld (0x%llx)\n", (Long)RES, (ULong)RES); - syscall_done = True; - } else if (mayBlock) { - vki_sigset_t mask; - - vg_assert(!(flags & PadAddr)); - - /* Syscall may block, so run it asynchronously */ - PRINT(" --> ...\n"); - - mask = tst->sig_mask; - sanitize_client_sigmask(tid, &mask); - - VG_(set_sleeping)(tid, VgTs_WaitSys); - VGA_(client_syscall)(syscallno, tst, &mask); - /* VGA_(client_syscall) may not return if the syscall was - interrupted by a signal. In that case, flow of control - will end up back in the scheduler via the signal - machinery. */ - VG_(set_running)(tid); - PRINT("SYSCALL[%d,%d](%3d) --> %lld (0x%llx)\n", - VG_(getpid)(), tid, syscallno, (Long)(Word)RES, (ULong)RES); - } else { - /* run the syscall directly */ - if (flags & PadAddr) - VG_(pad_address_space)(VG_(client_end)); - - RES = VG_(do_syscall6)(syscallno, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); - PRINT(" --> %lld (0x%llx)\n", (Long)(Word)RES, (ULong)RES); - syscall_done = True; - } - } - - vg_assert(VG_(is_running_thread)(tid)); - - // Tell the tool that the assignment has occurred, so it can update - // shadow regs as necessary. - VGP_TRACK_SYSCALL_RETVAL(tid); - - VG_(post_syscall)(tid); - - if (flags & PadAddr) { - vg_assert(!mayBlock); - VG_(unpad_address_space)(VG_(client_end)); - //VG_(sanity_check_memory)(); - } - - /* VG_(post_syscall) should set this */ - vg_assert(tst->syscallno == -1); - -// VGP_POPCC(VgpCoreSysWrap); -} /*--------------------------------------------------------------------*/ -/*--- end ---*/ +/*--- end syscalls-generic.c ---*/ /*--------------------------------------------------------------------*/ - diff --git a/coregrind/m_syscalls/syscalls-linux.c b/coregrind/m_syscalls/syscalls-linux.c index 2d801a1a9..c8f3bfcec 100644 --- a/coregrind/m_syscalls/syscalls-linux.c +++ b/coregrind/m_syscalls/syscalls-linux.c @@ -34,7 +34,11 @@ #include "pub_core_libcfile.h" #include "pub_core_libcprint.h" #include "pub_core_tooliface.h" -#include "priv_syscalls.h" +#include "pub_core_options.h" + +#include "priv_types_n_macros.h" +#include "priv_syscalls-linux.h" + /* --------------------------------------------------------------------- PRE/POST wrappers for arch-generic, Linux-specific syscalls @@ -43,22 +47,29 @@ // Nb: See the comment above the generic PRE/POST wrappers in // coregrind/vg_syscalls.c for notes about how they work. -#define PRE(name, f) PRE_TEMPLATE( , vgOS_linux, name, f) -#define POST(name) POST_TEMPLATE( , vgOS_linux, name) +#define PRE(name) DEFN_PRE_TEMPLATE(linux, name) +#define POST(name) DEFN_POST_TEMPLATE(linux, name) -PRE(sys_exit_group, Special) +PRE(sys_exit_group) { - ThreadId t; + ThreadId t; + ThreadState* tst; PRINT("exit_group( %d )", ARG1); PRE_REG_READ1(void, "exit_group", int, exit_code); + tst = VG_(get_ThreadState)(tid); + /* A little complex; find all the threads with the same threadgroup as this one (including this one), and mark them to exit */ for (t = 1; t < VG_N_THREADS; t++) { - if (VG_(threads)[t].status == VgTs_Empty || /* not alive */ - VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup) /* not our group */ - continue; + if ( /* not alive */ + VG_(threads)[t].status == VgTs_Empty + || + /* not our group */ + VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup + ) + continue; VG_(threads)[t].exitreason = VgSrc_ExitSyscall; VG_(threads)[t].os_state.exitcode = ARG1; @@ -67,19 +78,16 @@ PRE(sys_exit_group, Special) VG_(kill_thread)(t); /* unblock it, if blocked */ } - /* exit_group doesn't return anything (perhaps it doesn't return?) - Nevertheless, if we don't do this, the result-not-assigned- - yet-you-said-you-were-Special assertion in the main syscall - handling logic will fire. Hence .. - */ - SET_RESULT(0); + /* We have to claim the syscall already succeeded. */ + SET_STATUS_Success(0); } -PRE(sys_mount, MayBlock) +PRE(sys_mount) { // Nb: depending on 'flags', the 'type' and 'data' args may be ignored. // We are conservative and check everything, except the memory pointed to // by 'data'. + *flags |= SfMayBlock; PRINT( "sys_mount( %p, %p, %p, %p, %p )" ,ARG1,ARG2,ARG3,ARG4,ARG5); PRE_REG_READ5(long, "mount", char *, source, char *, target, char *, type, @@ -89,21 +97,21 @@ PRE(sys_mount, MayBlock) PRE_MEM_RASCIIZ( "mount(type)", ARG3); } -PRE(sys_oldumount, 0) +PRE(sys_oldumount) { PRINT("sys_oldumount( %p )", ARG1); PRE_REG_READ1(long, "umount", char *, path); PRE_MEM_RASCIIZ( "umount(path)", ARG1); } -PRE(sys_umount, 0) +PRE(sys_umount) { PRINT("sys_umount( %p )", ARG1); PRE_REG_READ2(long, "umount2", char *, path, int, flags); PRE_MEM_RASCIIZ( "umount2(path)", ARG1); } -PRE(sys_llseek, 0) +PRE(sys_llseek) { PRINT("sys_llseek ( %d, 0x%x, 0x%x, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5); PRE_REG_READ5(long, "llseek", @@ -115,641 +123,642 @@ PRE(sys_llseek, 0) POST(sys_llseek) { + vg_assert(SUCCESS); if (RES == 0) POST_MEM_WRITE( ARG4, sizeof(vki_loff_t) ); } -PRE(sys_adjtimex, 0) -{ - struct vki_timex *tx = (struct vki_timex *)ARG1; - PRINT("sys_adjtimex ( %p )", ARG1); - PRE_REG_READ1(long, "adjtimex", struct timex *, buf); - PRE_MEM_READ( "adjtimex(timex->modes)", ARG1, sizeof(tx->modes)); - -#define ADJX(bit,field) \ - if (tx->modes & bit) \ - PRE_MEM_READ( "adjtimex(timex->"#field")", \ - (Addr)&tx->field, sizeof(tx->field)) - ADJX(ADJ_FREQUENCY, freq); - ADJX(ADJ_MAXERROR, maxerror); - ADJX(ADJ_ESTERROR, esterror); - ADJX(ADJ_STATUS, status); - ADJX(ADJ_TIMECONST, constant); - ADJX(ADJ_TICK, tick); -#undef ADJX - - PRE_MEM_WRITE( "adjtimex(timex)", ARG1, sizeof(struct vki_timex)); -} - -POST(sys_adjtimex) -{ - POST_MEM_WRITE( ARG1, sizeof(struct vki_timex) ); -} - -PRE(sys_setfsuid16, 0) -{ - PRINT("sys_setfsuid16 ( %d )", ARG1); - PRE_REG_READ1(long, "setfsuid16", vki_old_uid_t, uid); -} - -PRE(sys_setfsuid, 0) -{ - PRINT("sys_setfsuid ( %d )", ARG1); - PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid); -} - -PRE(sys_setfsgid16, 0) -{ - PRINT("sys_setfsgid16 ( %d )", ARG1); - PRE_REG_READ1(long, "setfsgid16", vki_old_gid_t, gid); -} - -PRE(sys_setfsgid, 0) -{ - PRINT("sys_setfsgid ( %d )", ARG1); - PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid); -} - -PRE(sys_setresuid16, 0) -{ - PRINT("sys_setresuid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "setresuid16", - vki_old_uid_t, ruid, vki_old_uid_t, euid, vki_old_uid_t, suid); -} - -PRE(sys_setresuid, 0) -{ - PRINT("sys_setresuid ( %d, %d, %d )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "setresuid", - vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid); -} - -PRE(sys_getresuid16, 0) -{ - PRINT("sys_getresuid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "getresuid16", - vki_old_uid_t *, ruid, vki_old_uid_t *, euid, - vki_old_uid_t *, suid); - PRE_MEM_WRITE( "getresuid16(ruid)", ARG1, sizeof(vki_old_uid_t) ); - PRE_MEM_WRITE( "getresuid16(euid)", ARG2, sizeof(vki_old_uid_t) ); - PRE_MEM_WRITE( "getresuid16(suid)", ARG3, sizeof(vki_old_uid_t) ); -} - -POST(sys_getresuid16) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG1, sizeof(vki_old_uid_t) ); - POST_MEM_WRITE( ARG2, sizeof(vki_old_uid_t) ); - POST_MEM_WRITE( ARG3, sizeof(vki_old_uid_t) ); - } -} - -PRE(sys_getresuid, 0) -{ - PRINT("sys_getresuid ( %p, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "getresuid", - vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid); - PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) ); - PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) ); - PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) ); -} - -POST(sys_getresuid) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) ); - POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) ); - POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) ); - } -} - -PRE(sys_setresgid16, 0) -{ - PRINT("sys_setresgid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "setresgid16", - vki_old_gid_t, rgid, vki_old_gid_t, egid, vki_old_gid_t, sgid); -} - -PRE(sys_setresgid, 0) -{ - PRINT("sys_setresgid ( %d, %d, %d )", ARG1, ARG2, ARG3); - PRE_REG_READ3(long, "setresgid", - vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid); -} - -PRE(sys_getresgid16, 0) -{ - PRINT("sys_getresgid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "getresgid16", - vki_old_gid_t *, rgid, vki_old_gid_t *, egid, - vki_old_gid_t *, sgid); - PRE_MEM_WRITE( "getresgid16(rgid)", ARG1, sizeof(vki_old_gid_t) ); - PRE_MEM_WRITE( "getresgid16(egid)", ARG2, sizeof(vki_old_gid_t) ); - PRE_MEM_WRITE( "getresgid16(sgid)", ARG3, sizeof(vki_old_gid_t) ); -} - -POST(sys_getresgid16) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG1, sizeof(vki_old_gid_t) ); - POST_MEM_WRITE( ARG2, sizeof(vki_old_gid_t) ); - POST_MEM_WRITE( ARG3, sizeof(vki_old_gid_t) ); - } -} - -PRE(sys_getresgid, 0) -{ - PRINT("sys_getresgid ( %p, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "getresgid", - vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid); - PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) ); - PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) ); - PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) ); -} - -POST(sys_getresgid) -{ - if (RES == 0) { - POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) ); - POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) ); - POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) ); - } -} - -PRE(sys_ioperm, 0) -{ - PRINT("sys_ioperm ( %d, %d, %d )", ARG1, ARG2, ARG3 ); - PRE_REG_READ3(long, "ioperm", - unsigned long, from, unsigned long, num, int, turn_on); -} - -PRE(sys_syslog, MayBlock) -{ - PRINT("sys_syslog (%d, %p, %d)", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "syslog", int, type, char *, bufp, int, len); - switch (ARG1) { - // The kernel uses magic numbers here, rather than named constants, - // therefore so do we. - case 2: case 3: case 4: - PRE_MEM_WRITE( "syslog(bufp)", ARG2, ARG3); - break; - default: - break; - } -} - -POST(sys_syslog) -{ - switch (ARG1) { - case 2: case 3: case 4: - POST_MEM_WRITE( ARG2, ARG3 ); - break; - default: - break; - } -} - -PRE(sys_vhangup, 0) -{ - PRINT("sys_vhangup ( )"); - PRE_REG_READ0(long, "vhangup"); -} - -PRE(sys_sysinfo, 0) -{ - PRINT("sys_sysinfo ( %p )",ARG1); - PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info); - PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) ); -} - -POST(sys_sysinfo) -{ - POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) ); -} - -PRE(sys_personality, 0) -{ - PRINT("sys_personality ( %llu )", (ULong)ARG1); - PRE_REG_READ1(long, "personality", vki_u_long, persona); -} - -PRE(sys_sysctl, 0) -{ - struct __vki_sysctl_args *args; +//zz PRE(sys_adjtimex, 0) +//zz { +//zz struct vki_timex *tx = (struct vki_timex *)ARG1; +//zz PRINT("sys_adjtimex ( %p )", ARG1); +//zz PRE_REG_READ1(long, "adjtimex", struct timex *, buf); +//zz PRE_MEM_READ( "adjtimex(timex->modes)", ARG1, sizeof(tx->modes)); +//zz +//zz #define ADJX(bit,field) \ +//zz if (tx->modes & bit) \ +//zz PRE_MEM_READ( "adjtimex(timex->"#field")", \ +//zz (Addr)&tx->field, sizeof(tx->field)) +//zz ADJX(ADJ_FREQUENCY, freq); +//zz ADJX(ADJ_MAXERROR, maxerror); +//zz ADJX(ADJ_ESTERROR, esterror); +//zz ADJX(ADJ_STATUS, status); +//zz ADJX(ADJ_TIMECONST, constant); +//zz ADJX(ADJ_TICK, tick); +//zz #undef ADJX +//zz +//zz PRE_MEM_WRITE( "adjtimex(timex)", ARG1, sizeof(struct vki_timex)); +//zz } +//zz +//zz POST(sys_adjtimex) +//zz { +//zz POST_MEM_WRITE( ARG1, sizeof(struct vki_timex) ); +//zz } +//zz +//zz PRE(sys_setfsuid16, 0) +//zz { +//zz PRINT("sys_setfsuid16 ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setfsuid16", vki_old_uid_t, uid); +//zz } +//zz +//zz PRE(sys_setfsuid, 0) +//zz { +//zz PRINT("sys_setfsuid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid); +//zz } +//zz +//zz PRE(sys_setfsgid16, 0) +//zz { +//zz PRINT("sys_setfsgid16 ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setfsgid16", vki_old_gid_t, gid); +//zz } +//zz +//zz PRE(sys_setfsgid, 0) +//zz { +//zz PRINT("sys_setfsgid ( %d )", ARG1); +//zz PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid); +//zz } +//zz +//zz PRE(sys_setresuid16, 0) +//zz { +//zz PRINT("sys_setresuid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "setresuid16", +//zz vki_old_uid_t, ruid, vki_old_uid_t, euid, vki_old_uid_t, suid); +//zz } +//zz +//zz PRE(sys_setresuid, 0) +//zz { +//zz PRINT("sys_setresuid ( %d, %d, %d )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "setresuid", +//zz vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid); +//zz } +//zz +//zz PRE(sys_getresuid16, 0) +//zz { +//zz PRINT("sys_getresuid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "getresuid16", +//zz vki_old_uid_t *, ruid, vki_old_uid_t *, euid, +//zz vki_old_uid_t *, suid); +//zz PRE_MEM_WRITE( "getresuid16(ruid)", ARG1, sizeof(vki_old_uid_t) ); +//zz PRE_MEM_WRITE( "getresuid16(euid)", ARG2, sizeof(vki_old_uid_t) ); +//zz PRE_MEM_WRITE( "getresuid16(suid)", ARG3, sizeof(vki_old_uid_t) ); +//zz } +//zz +//zz POST(sys_getresuid16) +//zz { +//zz if (RES == 0) { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_old_uid_t) ); +//zz POST_MEM_WRITE( ARG2, sizeof(vki_old_uid_t) ); +//zz POST_MEM_WRITE( ARG3, sizeof(vki_old_uid_t) ); +//zz } +//zz } +//zz +//zz PRE(sys_getresuid, 0) +//zz { +//zz PRINT("sys_getresuid ( %p, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "getresuid", +//zz vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid); +//zz PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) ); +//zz PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) ); +//zz PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) ); +//zz } +//zz +//zz POST(sys_getresuid) +//zz { +//zz if (RES == 0) { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) ); +//zz POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) ); +//zz POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) ); +//zz } +//zz } +//zz +//zz PRE(sys_setresgid16, 0) +//zz { +//zz PRINT("sys_setresgid16 ( %d, %d, %d )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "setresgid16", +//zz vki_old_gid_t, rgid, vki_old_gid_t, egid, vki_old_gid_t, sgid); +//zz } +//zz +//zz PRE(sys_setresgid, 0) +//zz { +//zz PRINT("sys_setresgid ( %d, %d, %d )", ARG1, ARG2, ARG3); +//zz PRE_REG_READ3(long, "setresgid", +//zz vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid); +//zz } +//zz +//zz PRE(sys_getresgid16, 0) +//zz { +//zz PRINT("sys_getresgid16 ( %p, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "getresgid16", +//zz vki_old_gid_t *, rgid, vki_old_gid_t *, egid, +//zz vki_old_gid_t *, sgid); +//zz PRE_MEM_WRITE( "getresgid16(rgid)", ARG1, sizeof(vki_old_gid_t) ); +//zz PRE_MEM_WRITE( "getresgid16(egid)", ARG2, sizeof(vki_old_gid_t) ); +//zz PRE_MEM_WRITE( "getresgid16(sgid)", ARG3, sizeof(vki_old_gid_t) ); +//zz } +//zz +//zz POST(sys_getresgid16) +//zz { +//zz if (RES == 0) { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_old_gid_t) ); +//zz POST_MEM_WRITE( ARG2, sizeof(vki_old_gid_t) ); +//zz POST_MEM_WRITE( ARG3, sizeof(vki_old_gid_t) ); +//zz } +//zz } +//zz +//zz PRE(sys_getresgid, 0) +//zz { +//zz PRINT("sys_getresgid ( %p, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "getresgid", +//zz vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid); +//zz PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) ); +//zz PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) ); +//zz PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) ); +//zz } +//zz +//zz POST(sys_getresgid) +//zz { +//zz if (RES == 0) { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) ); +//zz POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) ); +//zz POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) ); +//zz } +//zz } +//zz +//zz PRE(sys_ioperm, 0) +//zz { +//zz PRINT("sys_ioperm ( %d, %d, %d )", ARG1, ARG2, ARG3 ); +//zz PRE_REG_READ3(long, "ioperm", +//zz unsigned long, from, unsigned long, num, int, turn_on); +//zz } +//zz +//zz PRE(sys_syslog, MayBlock) +//zz { +//zz PRINT("sys_syslog (%d, %p, %d)", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "syslog", int, type, char *, bufp, int, len); +//zz switch (ARG1) { +//zz // The kernel uses magic numbers here, rather than named constants, +//zz // therefore so do we. +//zz case 2: case 3: case 4: +//zz PRE_MEM_WRITE( "syslog(bufp)", ARG2, ARG3); +//zz break; +//zz default: +//zz break; +//zz } +//zz } +//zz +//zz POST(sys_syslog) +//zz { +//zz switch (ARG1) { +//zz case 2: case 3: case 4: +//zz POST_MEM_WRITE( ARG2, ARG3 ); +//zz break; +//zz default: +//zz break; +//zz } +//zz } +//zz +//zz PRE(sys_vhangup, 0) +//zz { +//zz PRINT("sys_vhangup ( )"); +//zz PRE_REG_READ0(long, "vhangup"); +//zz } +//zz +//zz PRE(sys_sysinfo, 0) +//zz { +//zz PRINT("sys_sysinfo ( %p )",ARG1); +//zz PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info); +//zz PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) ); +//zz } +//zz +//zz POST(sys_sysinfo) +//zz { +//zz POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) ); +//zz } +//zz +//zz PRE(sys_personality, 0) +//zz { +//zz PRINT("sys_personality ( %llu )", (ULong)ARG1); +//zz PRE_REG_READ1(long, "personality", vki_u_long, persona); +//zz } + +PRE(sys_sysctl) +{ + struct __vki_sysctl_args *argz; PRINT("sys_sysctl ( %p )", ARG1 ); - args = (struct __vki_sysctl_args *)ARG1; - PRE_REG_READ1(long, "sysctl", struct __sysctl_args *, args); + argz = (struct __vki_sysctl_args *)ARG1; + PRE_REG_READ1(long, "sysctl", struct __sysctl_args *, argz); PRE_MEM_WRITE( "sysctl(args)", ARG1, sizeof(struct __vki_sysctl_args) ); if (!VG_(is_addressable)(ARG1, sizeof(struct __vki_sysctl_args), VKI_PROT_READ)) { - SET_RESULT( -VKI_EFAULT ); + SET_STATUS_Failure( VKI_EFAULT ); return; } - PRE_MEM_READ("sysctl(name)", (Addr)args->name, args->nlen * sizeof(*args->name)); - if (args->newval != NULL) - PRE_MEM_READ("sysctl(newval)", (Addr)args->newval, args->newlen); - if (args->oldlenp != NULL) { - PRE_MEM_READ("sysctl(oldlenp)", (Addr)args->oldlenp, sizeof(*args->oldlenp)); - PRE_MEM_WRITE("sysctl(oldval)", (Addr)args->oldval, *args->oldlenp); + PRE_MEM_READ("sysctl(name)", (Addr)argz->name, argz->nlen * sizeof(*argz->name)); + if (argz->newval != NULL) + PRE_MEM_READ("sysctl(newval)", (Addr)argz->newval, argz->newlen); + if (argz->oldlenp != NULL) { + PRE_MEM_READ("sysctl(oldlenp)", (Addr)argz->oldlenp, sizeof(*argz->oldlenp)); + PRE_MEM_WRITE("sysctl(oldval)", (Addr)argz->oldval, *argz->oldlenp); } } POST(sys_sysctl) { - struct __vki_sysctl_args *args; - args = (struct __vki_sysctl_args *)ARG1; - if (args->oldlenp != NULL) { - POST_MEM_WRITE((Addr)args->oldlenp, sizeof(*args->oldlenp)); - POST_MEM_WRITE((Addr)args->oldval, 1 + *args->oldlenp); - } -} - -PRE(sys_prctl, MayBlock) -{ - PRINT( "prctl ( %d, %d, %d, %d, %d )", ARG1, ARG2, ARG3, ARG4, ARG5 ); - // XXX: too simplistic, often not all args are used - // Nb: can't use "ARG2".."ARG5" here because that's our own macro... - PRE_REG_READ5(long, "prctl", - int, option, unsigned long, arg2, unsigned long, arg3, - unsigned long, arg4, unsigned long, arg5); - // XXX: totally wrong... we need to look at the 'option' arg, and do - // PRE_MEM_READs/PRE_MEM_WRITEs as necessary... -} - -PRE(sys_sendfile, MayBlock) -{ - PRINT("sys_sendfile ( %d, %d, %p, %llu )", ARG1,ARG2,ARG3,(ULong)ARG4); - PRE_REG_READ4(ssize_t, "sendfile", - int, out_fd, int, in_fd, vki_off_t *, offset, - vki_size_t, count); - if (ARG3 != 0) - PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) ); -} - -POST(sys_sendfile) -{ - POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) ); -} - -PRE(sys_sendfile64, MayBlock) -{ - PRINT("sendfile64 ( %d, %d, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4); - PRE_REG_READ4(ssize_t, "sendfile64", - int, out_fd, int, in_fd, vki_loff_t *, offset, - vki_size_t, count); - if (ARG3 != 0) - PRE_MEM_WRITE( "sendfile64(offset)", ARG3, sizeof(vki_loff_t) ); -} - -POST(sys_sendfile64) -{ - if (ARG3 != 0 ) { - POST_MEM_WRITE( ARG3, sizeof(vki_loff_t) ); - } -} - -PRE(sys_futex, MayBlock) -{ - /* - arg param used by ops - - ARG1 - u32 *futex all - ARG2 - int op - ARG3 - int val WAIT,WAKE,FD,REQUEUE,CMP_REQUEUE - ARG4 - struct timespec *utime WAIT:time* REQUEUE,CMP_REQUEUE:val2 - ARG5 - u32 *uaddr2 REQUEUE,CMP_REQUEUE - ARG6 - int val3 CMP_REQUEUE - */ - PRINT("sys_futex ( %p, %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); - PRE_REG_READ6(long, "futex", - vki_u32 *, futex, int, op, int, val, - struct timespec *, utime, vki_u32 *, uaddr2, int, val3); - - PRE_MEM_READ( "futex(futex)", ARG1, sizeof(Int) ); - - switch(ARG2) { - case VKI_FUTEX_WAIT: - if (ARG4 != 0) - PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) ); - break; - - case VKI_FUTEX_REQUEUE: - case VKI_FUTEX_CMP_REQUEUE: - PRE_MEM_READ( "futex(futex2)", ARG5, sizeof(Int) ); - break; - - case VKI_FUTEX_WAKE: - case VKI_FUTEX_FD: - /* no additional pointers */ - break; - - default: - SET_RESULT(-VKI_ENOSYS); // some futex function we don't understand - break; - } -} - -POST(sys_futex) -{ - POST_MEM_WRITE( ARG1, sizeof(int) ); - if (ARG2 == VKI_FUTEX_FD) { - if (!VG_(fd_allowed)(RES, "futex", tid, True)) { - VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); - } else { - if (VG_(clo_track_fds)) - VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); - } - } -} - -PRE(sys_epoll_create, 0) -{ - PRINT("sys_epoll_create ( %d )", ARG1); - PRE_REG_READ1(long, "epoll_create", int, size); -} - -POST(sys_epoll_create) -{ - if (!VG_(fd_allowed)(RES, "epoll_create", tid, True)) { - VG_(close)(RES); - SET_RESULT( -VKI_EMFILE ); - } else { - if (VG_(clo_track_fds)) - VG_(record_fd_open) (tid, RES, NULL); - } -} - -PRE(sys_epoll_ctl, 0) -{ - static const char* epoll_ctl_s[3] = { - "EPOLL_CTL_ADD", - "EPOLL_CTL_DEL", - "EPOLL_CTL_MOD" - }; - PRINT("sys_epoll_ctl ( %d, %s, %d, %p )", - ARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), ARG3, ARG4); - PRE_REG_READ4(long, "epoll_ctl", - int, epfd, int, op, int, fd, struct epoll_event *, event); - PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct epoll_event) ); -} - -PRE(sys_epoll_wait, MayBlock) -{ - PRINT("sys_epoll_wait ( %d, %p, %d, %d )", ARG1, ARG2, ARG3, ARG4); - PRE_REG_READ4(long, "epoll_wait", - int, epfd, struct epoll_event *, events, - int, maxevents, int, timeout); - PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct epoll_event)*ARG3); -} - -POST(sys_epoll_wait) -{ - if (RES > 0) - POST_MEM_WRITE( ARG2, sizeof(struct epoll_event)*RES ) ; -} - -PRE(sys_gettid, 0) -{ - PRINT("sys_gettid ()"); - PRE_REG_READ0(long, "gettid"); -} - -PRE(sys_tkill, Special) -{ - /* int tkill(pid_t tid, int sig); */ - PRINT("sys_tkill ( %d, %d )", ARG1,ARG2); - PRE_REG_READ2(long, "tkill", int, tid, int, sig); - if (!VG_(client_signal_OK)(ARG2)) { - SET_RESULT( -VKI_EINVAL ); - return; - } - - /* If we're sending SIGKILL, check to see if the target is one of - our threads and handle it specially. */ - if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1)) - SET_RESULT(0); - else - SET_RESULT(VG_(do_syscall2)(SYSNO, ARG1, ARG2)); - - if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d", - ARG2, ARG1); - // Check to see if this kill gave us a pending signal - VG_(poll_signals)(tid); -} - -PRE(sys_tgkill, Special) -{ - /* int tgkill(pid_t tgid, pid_t tid, int sig); */ - PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig); - if (!VG_(client_signal_OK)(ARG3)) { - SET_RESULT( -VKI_EINVAL ); - return; - } - - /* If we're sending SIGKILL, check to see if the target is one of - our threads and handle it specially. */ - if (ARG3 == VKI_SIGKILL && VG_(do_sigkill)(ARG2, ARG1)) - SET_RESULT(0); - else - SET_RESULT(VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3)); - - if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d", - ARG3, ARG1, ARG2); - // Check to see if this kill gave us a pending signal - VG_(poll_signals)(tid); -} - -POST(sys_tgkill) -{ - if (VG_(clo_trace_signals)) - VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d", - ARG3, ARG1, ARG2); - // Check to see if this kill gave us a pending signal - VG_(poll_signals)(tid); -} - -PRE(sys_fadvise64, 0) -{ - PRINT("sys_fadvise64 ( %d, %lld, %lu, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ4(long, "fadvise64", - int, fd, vki_loff_t, offset, vki_size_t, len, int, advice) -} - -PRE(sys_fadvise64_64, 0) -{ - PRINT("sys_fadvise64_64 ( %d, %lld, %lld, %d )", ARG1,ARG2,ARG3); - PRE_REG_READ4(long, "fadvise64_64", - int, fd, vki_loff_t, offset, vki_loff_t, len, int, advice) -} - -// Nb: this wrapper is "Special" because we have to pad/unpad memory around -// the syscall itself, and this allows us to control exactly the code that -// gets run while the padding is in place. -PRE(sys_io_setup, Special) -{ - SizeT size; - Addr addr; - - PRINT("sys_io_setup ( %u, %p )", ARG1,ARG2); - PRE_REG_READ2(long, "io_setup", - unsigned, nr_events, vki_aio_context_t *, ctxp); - PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) ); - - size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + - ARG1*sizeof(struct vki_io_event)); - addr = VG_(find_map_space)(0, size, True); - - if (addr == 0) { - SET_RESULT( -VKI_ENOMEM ); - return; - } - - VG_(map_segment)(addr, size, VKI_PROT_READ|VKI_PROT_WRITE, SF_FIXED); - - VG_(pad_address_space)(0); - SET_RESULT( VG_(do_syscall2)(SYSNO, ARG1, ARG2) ); - VG_(unpad_address_space)(0); - - if (RES == 0) { - struct vki_aio_ring *r = *(struct vki_aio_ring **)ARG2; - - vg_assert(addr == (Addr)r); - vg_assert(VG_(valid_client_addr)(addr, size, tid, "io_setup")); - - VG_TRACK( new_mem_mmap, addr, size, True, True, False ); - POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) ); - } - else { - VG_(unmap_range)(addr, size); - } -} - -// Nb: This wrapper is "Special" because we need 'size' to do the unmap -// after the syscall. We must get 'size' from the aio_ring structure, -// before the syscall, while the aio_ring structure still exists. (And we -// know that we must look at the aio_ring structure because Tom inspected the -// kernel and glibc sources to see what they do, yuk.) -// -// XXX This segment can be implicitly unmapped when aio -// file-descriptors are closed... -PRE(sys_io_destroy, Special) -{ - Segment *s = VG_(find_segment)(ARG1); - struct vki_aio_ring *r; - SizeT size; - - PRINT("sys_io_destroy ( %llu )", (ULong)ARG1); - PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx); - - // If we are going to seg fault (due to a bogus ARG1) do it as late as - // possible... - r = *(struct vki_aio_ring **)ARG1; - size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + - r->nr*sizeof(struct vki_io_event)); - - SET_RESULT( VG_(do_syscall1)(SYSNO, ARG1) ); - - if (RES == 0 && s != NULL) { - VG_TRACK( die_mem_munmap, ARG1, size ); - VG_(unmap_range)(ARG1, size); - } -} - -PRE(sys_io_getevents, MayBlock) -{ - PRINT("sys_io_getevents ( %llu, %lld, %lld, %p, %p )", - (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5); - PRE_REG_READ5(long, "io_getevents", - vki_aio_context_t, ctx_id, long, min_nr, long, nr, - struct io_event *, events, - struct timespec *, timeout); - if (ARG3 > 0) - PRE_MEM_WRITE( "io_getevents(events)", - ARG4, sizeof(struct vki_io_event)*ARG3 ); - if (ARG5 != 0) - PRE_MEM_READ( "io_getevents(timeout)", - ARG5, sizeof(struct vki_timespec)); -} - -POST(sys_io_getevents) -{ - int i; - - if (RES > 0) { - POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES ); - for (i = 0; i < RES; i++) { - const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i; - const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj; - - switch (cb->aio_lio_opcode) { - case VKI_IOCB_CMD_PREAD: - if (vev->result > 0) - POST_MEM_WRITE( cb->aio_buf, vev->result ); - break; - - case VKI_IOCB_CMD_PWRITE: - break; - - default: - VG_(message)(Vg_DebugMsg,"Warning: unhandled io_getevents opcode: %u\n",cb->aio_lio_opcode); - break; - } - } + struct __vki_sysctl_args *argz; + argz = (struct __vki_sysctl_args *)ARG1; + if (argz->oldlenp != NULL) { + POST_MEM_WRITE((Addr)argz->oldlenp, sizeof(*argz->oldlenp)); + POST_MEM_WRITE((Addr)argz->oldval, 1 + *argz->oldlenp); } } -PRE(sys_io_submit, 0) -{ - int i; - - PRINT("sys_io_submit( %llu, %lld, %p )", (ULong)ARG1,(Long)ARG2,ARG3); - PRE_REG_READ3(long, "io_submit", - vki_aio_context_t, ctx_id, long, nr, - struct iocb **, iocbpp); - PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) ); - if (ARG3 != 0) { - for (i = 0; i < ARG2; i++) { - struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i]; - PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) ); - switch (cb->aio_lio_opcode) { - case VKI_IOCB_CMD_PREAD: - PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes ); - break; - - case VKI_IOCB_CMD_PWRITE: - PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes ); - break; - - default: - VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n", - cb->aio_lio_opcode); - break; - } - } - } -} - -PRE(sys_io_cancel, 0) -{ - PRINT("sys_io_cancel( %llu, %p, %p )", (ULong)ARG1,ARG2,ARG3); - PRE_REG_READ3(long, "io_cancel", - vki_aio_context_t, ctx_id, struct iocb *, iocb, - struct io_event *, result); - PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) ); - PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) ); -} - -POST(sys_io_cancel) -{ - POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) ); -} - -#undef PRE -#undef POST +//zz PRE(sys_prctl, MayBlock) +//zz { +//zz PRINT( "prctl ( %d, %d, %d, %d, %d )", ARG1, ARG2, ARG3, ARG4, ARG5 ); +//zz // XXX: too simplistic, often not all args are used +//zz // Nb: can't use "ARG2".."ARG5" here because that's our own macro... +//zz PRE_REG_READ5(long, "prctl", +//zz int, option, unsigned long, arg2, unsigned long, arg3, +//zz unsigned long, arg4, unsigned long, arg5); +//zz // XXX: totally wrong... we need to look at the 'option' arg, and do +//zz // PRE_MEM_READs/PRE_MEM_WRITEs as necessary... +//zz } +//zz +//zz PRE(sys_sendfile, MayBlock) +//zz { +//zz PRINT("sys_sendfile ( %d, %d, %p, %llu )", ARG1,ARG2,ARG3,(ULong)ARG4); +//zz PRE_REG_READ4(ssize_t, "sendfile", +//zz int, out_fd, int, in_fd, vki_off_t *, offset, +//zz vki_size_t, count); +//zz if (ARG3 != 0) +//zz PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) ); +//zz } +//zz +//zz POST(sys_sendfile) +//zz { +//zz POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) ); +//zz } +//zz +//zz PRE(sys_sendfile64, MayBlock) +//zz { +//zz PRINT("sendfile64 ( %d, %d, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4); +//zz PRE_REG_READ4(ssize_t, "sendfile64", +//zz int, out_fd, int, in_fd, vki_loff_t *, offset, +//zz vki_size_t, count); +//zz if (ARG3 != 0) +//zz PRE_MEM_WRITE( "sendfile64(offset)", ARG3, sizeof(vki_loff_t) ); +//zz } +//zz +//zz POST(sys_sendfile64) +//zz { +//zz if (ARG3 != 0 ) { +//zz POST_MEM_WRITE( ARG3, sizeof(vki_loff_t) ); +//zz } +//zz } +//zz +//zz PRE(sys_futex, MayBlock) +//zz { +//zz /* +//zz arg param used by ops +//zz +//zz ARG1 - u32 *futex all +//zz ARG2 - int op +//zz ARG3 - int val WAIT,WAKE,FD,REQUEUE,CMP_REQUEUE +//zz ARG4 - struct timespec *utime WAIT:time* REQUEUE,CMP_REQUEUE:val2 +//zz ARG5 - u32 *uaddr2 REQUEUE,CMP_REQUEUE +//zz ARG6 - int val3 CMP_REQUEUE +//zz */ +//zz PRINT("sys_futex ( %p, %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5); +//zz PRE_REG_READ6(long, "futex", +//zz vki_u32 *, futex, int, op, int, val, +//zz struct timespec *, utime, vki_u32 *, uaddr2, int, val3); +//zz +//zz PRE_MEM_READ( "futex(futex)", ARG1, sizeof(Int) ); +//zz +//zz switch(ARG2) { +//zz case VKI_FUTEX_WAIT: +//zz if (ARG4 != 0) +//zz PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) ); +//zz break; +//zz +//zz case VKI_FUTEX_REQUEUE: +//zz case VKI_FUTEX_CMP_REQUEUE: +//zz PRE_MEM_READ( "futex(futex2)", ARG5, sizeof(Int) ); +//zz break; +//zz +//zz case VKI_FUTEX_WAKE: +//zz case VKI_FUTEX_FD: +//zz /* no additional pointers */ +//zz break; +//zz +//zz default: +//zz SET_RESULT(-VKI_ENOSYS); // some futex function we don't understand +//zz break; +//zz } +//zz } +//zz +//zz POST(sys_futex) +//zz { +//zz POST_MEM_WRITE( ARG1, sizeof(int) ); +//zz if (ARG2 == VKI_FUTEX_FD) { +//zz if (!VG_(fd_allowed)(RES, "futex", tid, True)) { +//zz VG_(close)(RES); +//zz SET_RESULT( -VKI_EMFILE ); +//zz } else { +//zz if (VG_(clo_track_fds)) +//zz VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1)); +//zz } +//zz } +//zz } +//zz +//zz PRE(sys_epoll_create, 0) +//zz { +//zz PRINT("sys_epoll_create ( %d )", ARG1); +//zz PRE_REG_READ1(long, "epoll_create", int, size); +//zz } +//zz +//zz POST(sys_epoll_create) +//zz { +//zz if (!VG_(fd_allowed)(RES, "epoll_create", tid, True)) { +//zz VG_(close)(RES); +//zz SET_RESULT( -VKI_EMFILE ); +//zz } else { +//zz if (VG_(clo_track_fds)) +//zz VG_(record_fd_open) (tid, RES, NULL); +//zz } +//zz } +//zz +//zz PRE(sys_epoll_ctl, 0) +//zz { +//zz static const char* epoll_ctl_s[3] = { +//zz "EPOLL_CTL_ADD", +//zz "EPOLL_CTL_DEL", +//zz "EPOLL_CTL_MOD" +//zz }; +//zz PRINT("sys_epoll_ctl ( %d, %s, %d, %p )", +//zz ARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), ARG3, ARG4); +//zz PRE_REG_READ4(long, "epoll_ctl", +//zz int, epfd, int, op, int, fd, struct epoll_event *, event); +//zz PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct epoll_event) ); +//zz } +//zz +//zz PRE(sys_epoll_wait, MayBlock) +//zz { +//zz PRINT("sys_epoll_wait ( %d, %p, %d, %d )", ARG1, ARG2, ARG3, ARG4); +//zz PRE_REG_READ4(long, "epoll_wait", +//zz int, epfd, struct epoll_event *, events, +//zz int, maxevents, int, timeout); +//zz PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct epoll_event)*ARG3); +//zz } +//zz +//zz POST(sys_epoll_wait) +//zz { +//zz if (RES > 0) +//zz POST_MEM_WRITE( ARG2, sizeof(struct epoll_event)*RES ) ; +//zz } +//zz +//zz PRE(sys_gettid, 0) +//zz { +//zz PRINT("sys_gettid ()"); +//zz PRE_REG_READ0(long, "gettid"); +//zz } +//zz +//zz PRE(sys_tkill, Special) +//zz { +//zz /* int tkill(pid_t tid, int sig); */ +//zz PRINT("sys_tkill ( %d, %d )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "tkill", int, tid, int, sig); +//zz if (!VG_(client_signal_OK)(ARG2)) { +//zz SET_RESULT( -VKI_EINVAL ); +//zz return; +//zz } +//zz +//zz /* If we're sending SIGKILL, check to see if the target is one of +//zz our threads and handle it specially. */ +//zz if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1)) +//zz SET_RESULT(0); +//zz else +//zz SET_RESULT(VG_(do_syscall2)(SYSNO, ARG1, ARG2)); +//zz +//zz if (VG_(clo_trace_signals)) +//zz VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d", +//zz ARG2, ARG1); +//zz // Check to see if this kill gave us a pending signal +//zz XXX FIXME VG_(poll_signals)(tid); +//zz } +//zz +//zz PRE(sys_tgkill, Special) +//zz { +//zz /* int tgkill(pid_t tgid, pid_t tid, int sig); */ +//zz PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig); +//zz if (!VG_(client_signal_OK)(ARG3)) { +//zz SET_RESULT( -VKI_EINVAL ); +//zz return; +//zz } +//zz +//zz /* If we're sending SIGKILL, check to see if the target is one of +//zz our threads and handle it specially. */ +//zz if (ARG3 == VKI_SIGKILL && VG_(do_sigkill)(ARG2, ARG1)) +//zz SET_RESULT(0); +//zz else +//zz SET_RESULT(VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3)); +//zz +//zz if (VG_(clo_trace_signals)) +//zz VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d", +//zz ARG3, ARG1, ARG2); +//zz // Check to see if this kill gave us a pending signal +//zz XXX FIXME VG_(poll_signals)(tid); +//zz } +//zz +//zz POST(sys_tgkill) +//zz { +//zz if (VG_(clo_trace_signals)) +//zz VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d", +//zz ARG3, ARG1, ARG2); +//zz // Check to see if this kill gave us a pending signal +//zz XXX FIXME VG_(poll_signals)(tid); +//zz } +//zz +//zz PRE(sys_fadvise64, 0) +//zz { +//zz PRINT("sys_fadvise64 ( %d, %lld, %lu, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ4(long, "fadvise64", +//zz int, fd, vki_loff_t, offset, vki_size_t, len, int, advice) +//zz } +//zz +//zz PRE(sys_fadvise64_64, 0) +//zz { +//zz PRINT("sys_fadvise64_64 ( %d, %lld, %lld, %d )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ4(long, "fadvise64_64", +//zz int, fd, vki_loff_t, offset, vki_loff_t, len, int, advice) +//zz } +//zz +//zz // Nb: this wrapper is "Special" because we have to pad/unpad memory around +//zz // the syscall itself, and this allows us to control exactly the code that +//zz // gets run while the padding is in place. +//zz PRE(sys_io_setup, Special) +//zz { +//zz SizeT size; +//zz Addr addr; +//zz +//zz PRINT("sys_io_setup ( %u, %p )", ARG1,ARG2); +//zz PRE_REG_READ2(long, "io_setup", +//zz unsigned, nr_events, vki_aio_context_t *, ctxp); +//zz PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) ); +//zz +//zz size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + +//zz ARG1*sizeof(struct vki_io_event)); +//zz addr = VG_(find_map_space)(0, size, True); +//zz +//zz if (addr == 0) { +//zz SET_RESULT( -VKI_ENOMEM ); +//zz return; +//zz } +//zz +//zz VG_(map_segment)(addr, size, VKI_PROT_READ|VKI_PROT_WRITE, SF_FIXED); +//zz +//zz VG_(pad_address_space)(0); +//zz SET_RESULT( VG_(do_syscall2)(SYSNO, ARG1, ARG2) ); +//zz VG_(unpad_address_space)(0); +//zz +//zz if (RES == 0) { +//zz struct vki_aio_ring *r = *(struct vki_aio_ring **)ARG2; +//zz +//zz vg_assert(addr == (Addr)r); +//zz vg_assert(VG_(valid_client_addr)(addr, size, tid, "io_setup")); +//zz +//zz VG_TRACK( new_mem_mmap, addr, size, True, True, False ); +//zz POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) ); +//zz } +//zz else { +//zz VG_(unmap_range)(addr, size); +//zz } +//zz } +//zz +//zz // Nb: This wrapper is "Special" because we need 'size' to do the unmap +//zz // after the syscall. We must get 'size' from the aio_ring structure, +//zz // before the syscall, while the aio_ring structure still exists. (And we +//zz // know that we must look at the aio_ring structure because Tom inspected the +//zz // kernel and glibc sources to see what they do, yuk.) +//zz // +//zz // XXX This segment can be implicitly unmapped when aio +//zz // file-descriptors are closed... +//zz PRE(sys_io_destroy, Special) +//zz { +//zz Segment *s = VG_(find_segment)(ARG1); +//zz struct vki_aio_ring *r; +//zz SizeT size; +//zz +//zz PRINT("sys_io_destroy ( %llu )", (ULong)ARG1); +//zz PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx); +//zz +//zz // If we are going to seg fault (due to a bogus ARG1) do it as late as +//zz // possible... +//zz r = *(struct vki_aio_ring **)ARG1; +//zz size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) + +//zz r->nr*sizeof(struct vki_io_event)); +//zz +//zz SET_RESULT( VG_(do_syscall1)(SYSNO, ARG1) ); +//zz +//zz if (RES == 0 && s != NULL) { +//zz VG_TRACK( die_mem_munmap, ARG1, size ); +//zz VG_(unmap_range)(ARG1, size); +//zz } +//zz } +//zz +//zz PRE(sys_io_getevents, MayBlock) +//zz { +//zz PRINT("sys_io_getevents ( %llu, %lld, %lld, %p, %p )", +//zz (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5); +//zz PRE_REG_READ5(long, "io_getevents", +//zz vki_aio_context_t, ctx_id, long, min_nr, long, nr, +//zz struct io_event *, events, +//zz struct timespec *, timeout); +//zz if (ARG3 > 0) +//zz PRE_MEM_WRITE( "io_getevents(events)", +//zz ARG4, sizeof(struct vki_io_event)*ARG3 ); +//zz if (ARG5 != 0) +//zz PRE_MEM_READ( "io_getevents(timeout)", +//zz ARG5, sizeof(struct vki_timespec)); +//zz } +//zz +//zz POST(sys_io_getevents) +//zz { +//zz int i; +//zz +//zz if (RES > 0) { +//zz POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES ); +//zz for (i = 0; i < RES; i++) { +//zz const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i; +//zz const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj; +//zz +//zz switch (cb->aio_lio_opcode) { +//zz case VKI_IOCB_CMD_PREAD: +//zz if (vev->result > 0) +//zz POST_MEM_WRITE( cb->aio_buf, vev->result ); +//zz break; +//zz +//zz case VKI_IOCB_CMD_PWRITE: +//zz break; +//zz +//zz default: +//zz VG_(message)(Vg_DebugMsg,"Warning: unhandled io_getevents opcode: %u\n",cb->aio_lio_opcode); +//zz break; +//zz } +//zz } +//zz } +//zz } +//zz +//zz PRE(sys_io_submit, 0) +//zz { +//zz int i; +//zz +//zz PRINT("sys_io_submit( %llu, %lld, %p )", (ULong)ARG1,(Long)ARG2,ARG3); +//zz PRE_REG_READ3(long, "io_submit", +//zz vki_aio_context_t, ctx_id, long, nr, +//zz struct iocb **, iocbpp); +//zz PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) ); +//zz if (ARG3 != 0) { +//zz for (i = 0; i < ARG2; i++) { +//zz struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i]; +//zz PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) ); +//zz switch (cb->aio_lio_opcode) { +//zz case VKI_IOCB_CMD_PREAD: +//zz PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes ); +//zz break; +//zz +//zz case VKI_IOCB_CMD_PWRITE: +//zz PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes ); +//zz break; +//zz +//zz default: +//zz VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n", +//zz cb->aio_lio_opcode); +//zz break; +//zz } +//zz } +//zz } +//zz } +//zz +//zz PRE(sys_io_cancel, 0) +//zz { +//zz PRINT("sys_io_cancel( %llu, %p, %p )", (ULong)ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(long, "io_cancel", +//zz vki_aio_context_t, ctx_id, struct iocb *, iocb, +//zz struct io_event *, result); +//zz PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) ); +//zz PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) ); +//zz } +//zz +//zz POST(sys_io_cancel) +//zz { +//zz POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) ); +//zz } +//zz +//zz #undef PRE +//zz #undef POST /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_syscalls/syscalls-main.c b/coregrind/m_syscalls/syscalls-main.c new file mode 100644 index 000000000..f2fbb0890 --- /dev/null +++ b/coregrind/m_syscalls/syscalls-main.c @@ -0,0 +1,970 @@ + +/*--------------------------------------------------------------------*/ +/*--- Handle system calls. syscalls-main.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2005 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "libvex_guest_offsets.h" +#include "core.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcassert.h" +#include "pub_core_libcprint.h" +#include "pub_core_stacktrace.h" +#include "pub_core_tooliface.h" +#include "pub_core_options.h" +#include "pub_core_signals.h" +#include "pub_core_syscalls.h" + +#include "priv_types_n_macros.h" +#include "priv_syscalls-main.h" + + +/* This is the top level of the system-call handler module. All + system calls are channelled through here, doing two things: + + * notify the tool of the events (mem/reg reads, writes) happening + + * perform the syscall, usually by passing it along to the kernel + unmodified. + + A magical piece of assembly code, do_syscall_for_client_WRK, in + syscall-$PLATFORM.S does the tricky bit of passing a syscall to the + kernel, whilst having the simulator retain control. +*/ + +/* The main function is VG_(client_syscall). The simulation calls it + whenever a client thread wants to do a syscall. The following is a + sketch of what it does. + + * First, it rounds up the syscall number and args (which is a + platform dependent activity) and puts them in a struct ("args") + and also a copy in "orig_args". + + The pre/post wrappers refer to these structs and so no longer + need magic macros to access any specific registers. This struct + is stored in thread-specific storage. + + + * The pre-wrapper is called, passing it a pointer to struct + "args". + + + * The pre-wrapper examines the args and pokes the tool + appropriately. It may modify the args; this is why "orig_args" + is also stored. + + The pre-wrapper may choose to 'do' the syscall itself, and + concludes one of three outcomes: + + Success(N) -- syscall is already complete, with success; + result is N + + Fail(N) -- syscall is already complete, with failure; + error code is N + + HandToKernel -- (the usual case): this needs to be given to + the kernel to be done, using the values in + the possibly-modified "args" struct. + + In addition, the pre-wrapper may set some flags: + + MayBlock -- only applicable when outcome==HandToKernel + + PostOnFail -- only applicable when outcome==HandToKernel or Fail + + + * If the pre-outcome is HandToKernel, the syscall is duly handed + off to the kernel (perhaps involving some thread switchery, but + that's not important). This reduces the possible set of outcomes + to either Success(N) or Fail(N). + + + * The outcome (Success(N) or Fail(N)) is written back to the guest + register(s). This is platform specific: + + x86: Success(N) ==> eax = N + Fail(N) ==> eax = -N + + ditto amd64 + + ppc32: Success(N) ==> r3 = N, CR0.SO = 0 + Fail(N) ==> r3 = N, CR0.SO = 1 + + * The post wrapper is called if: + + - it exists, and + - outcome==Success or (outcome==Fail and PostOnFail is set) + + The post wrapper is passed the adulterated syscall args (struct + "args"), and the syscall outcome (viz, Success(N) or Fail(N)). + + There are several other complications, primarily to do with + syscalls getting interrupted, explained in comments in the code. +*/ + +/* CAVEATS for writing wrappers. It is important to follow these! + + The macros defined in priv_types_n_macros.h are designed to help + decouple the wrapper logic from the actual representation of + syscall args/results, since these wrappers are designed to work on + multiple platforms. + + Sometimes a PRE wrapper will complete the syscall itself, without + handing it to the kernel. It will use one of SET_STATUS_Success, + SET_STATUS_Failure or SET_STATUS_from_SysRes to set the return + value. It is critical to appreciate that use of the macro does not + immediately cause the underlying guest state to be updated -- that + is done by the driver logic in this file, when the wrapper returns. + + As a result, PRE wrappers of the following form will malfunction: + + PRE(fooble) + { + ... do stuff ... + SET_STATUS_Somehow(...) + + // do something that assumes guest state is up to date + } + + In particular, direct or indirect calls to VG_(poll_signals) after + setting STATUS can cause the guest state to be read (in order to + build signal frames). Do not do this. If you want a signal poll + after the syscall goes through, do "*flags |= SfPollAfter" and the + driver logic will do it for you. +*/ + + +/* --------------------------------------------------------------------- + Do potentially blocking syscall for the client, and mess with + signal masks at the same time. + ------------------------------------------------------------------ */ + +/* Perform a syscall on behalf of a client thread, using a specific + signal mask. On completion, the signal mask is set to restore_mask + (which presumably blocks almost everything). If a signal happens + during the syscall, the handler should call + VG_(fixup_guest_state_after_syscall_interrupted) to adjust the + thread's context to do the right thing. + + The _WRK function is handwritten assembly. It has some very magic + properties. See comments at the top of + VG_(fixup_guest_state_after_syscall_interrupted) below for details. +*/ +extern +void VGA_(do_syscall_for_client_WRK)( Int syscallno, + void* guest_state, + const vki_sigset_t *syscall_mask, + const vki_sigset_t *restore_mask, + Int nsigwords ); + +static +void do_syscall_for_client ( Int syscallno, + ThreadState* tst, + const vki_sigset_t* syscall_mask ) +{ + vki_sigset_t saved; + VGA_(do_syscall_for_client_WRK)( + syscallno, &tst->arch.vex, + syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord) + ); +} + + + +/* --------------------------------------------------------------------- + Impedance matchers and misc helpers + ------------------------------------------------------------------ */ + +static +Bool eq_SyscallArgs ( SyscallArgs* a1, SyscallArgs* a2 ) +{ + return a1->sysno == a2->sysno + && a1->arg1 == a2->arg1 + && a1->arg2 == a2->arg2 + && a1->arg3 == a2->arg3 + && a1->arg4 == a2->arg4 + && a1->arg5 == a2->arg5 + && a1->arg6 == a2->arg6; +} + +static +Bool eq_SyscallStatus ( SyscallStatus* s1, SyscallStatus* s2 ) +{ + return s1->what == s2->what + && s1->val == s2->val; +} + + +/* Convert between SysRet and SyscallStatus, to the extent possible. */ + +/* This is unused. */ +/* +static +SysRes convert_SyscallStatus_to_SysRes ( SyscallStatus status ) +{ + SysRes res; + vg_assert(status.what == SsSuccess || status.what == SsFailure); + res.isError = status.what == SsFailure; + res.val = status.val; + return res; +} +*/ + +static +SyscallStatus convert_SysRes_to_SyscallStatus ( SysRes res ) +{ + SyscallStatus status; + status.what = res.isError ? SsFailure : SsSuccess; + status.val = res.val; + return status; +} + + +/* Impedance matchers. These convert syscall arg or result data from + the platform-specific in-guest-state format to the canonical + formats, and back. */ + +static +void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical, + /*IN*/ VexGuestArchState* gst_vanilla ) +{ +# if defined(VGP_x86_linux) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + canonical->sysno = gst->guest_EAX; + canonical->arg1 = gst->guest_EBX; + canonical->arg2 = gst->guest_ECX; + canonical->arg3 = gst->guest_EDX; + canonical->arg4 = gst->guest_ESI; + canonical->arg5 = gst->guest_EDI; + canonical->arg6 = gst->guest_EBP; +# else +# error "getSyscallArgsFromGuestState: unknown arch" +# endif +} + +static +void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical, + /*OUT*/VexGuestArchState* gst_vanilla ) +{ +# if defined(VGP_x86_linux) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + gst->guest_EAX = canonical->sysno; + gst->guest_EBX = canonical->arg1; + gst->guest_ECX = canonical->arg2; + gst->guest_EDX = canonical->arg3; + gst->guest_ESI = canonical->arg4; + gst->guest_EDI = canonical->arg5; + gst->guest_EBP = canonical->arg6; +# else +# error "putSyscallArgsIntoGuestState: unknown arch" +# endif +} + +static +void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical, + /*IN*/ VexGuestArchState* gst_vanilla ) +{ +# if defined(VGP_x86_linux) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + Int i = (Int)gst->guest_EAX; + canonical->what = i >= -4095 && i <= -1 ? SsFailure : SsSuccess; + canonical->val = (UWord)(canonical->what==SsFailure ? -i : i); +# else +# error "getSyscallStatusFromGuestState: unknown arch" +# endif +} + +static +void putSyscallStatusIntoGuestState ( /*IN*/ SyscallStatus* canonical, + /*OUT*/VexGuestArchState* gst_vanilla ) +{ + vg_assert(canonical->what == SsSuccess + || canonical->what == SsFailure); +# if defined(VGP_x86_linux) + VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; + if (canonical->what == SsFailure) { + /* This isn't exactly right, in that really a Failure with res + not in the range 1 .. 4095 is unrepresentable in the + Linux-x86 scheme. Oh well. */ + gst->guest_EAX = - (Int)canonical->val; + } else { + gst->guest_EAX = canonical->val; + } +# else +# error "putSyscallStatusIntoGuestState: unknown arch" +# endif +} + + +/* Tell me the offsets in the guest state of the syscall params, so + that the scalar argument checkers don't have to have this info + hardwired. */ + +static +void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) +{ +# if defined(VGP_x86_linux) + layout->o_sysno = OFFSET_x86_EAX; + layout->o_arg1 = OFFSET_x86_EBX; + layout->o_arg2 = OFFSET_x86_ECX; + layout->o_arg3 = OFFSET_x86_EDX; + layout->o_arg4 = OFFSET_x86_ESI; + layout->o_arg5 = OFFSET_x86_EDI; + layout->o_arg6 = OFFSET_x86_EBP; + layout->o_retval = OFFSET_x86_EAX; +# else +# error "getSyscallLayout: unknown arch" +# endif +} + + +/* --------------------------------------------------------------------- + The main driver logic + ------------------------------------------------------------------ */ + +/* Finding the handlers for a given syscall, or faking up one + when no handler is found. */ + +static +void bad_before ( ThreadId tid, + SyscallArgLayout* layout, + /*MOD*/SyscallArgs* args, + /*OUT*/SyscallStatus* status, + /*OUT*/UWord* flags ) +{ + VG_(message) + (Vg_DebugMsg,"WARNING: unhandled syscall: %llu", (ULong)args->sysno); + if (VG_(clo_verbosity) > 1) { + VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); + } + VG_(message) + (Vg_DebugMsg,"You may be able to write your own handler."); + VG_(message) + (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL."); + + SET_STATUS_Failure(VKI_ENOSYS); +} + +static SyscallTableEntry bad_sys = + { bad_before, NULL }; + +static const SyscallTableEntry* get_syscall_entry ( UInt syscallno ) +{ + const SyscallTableEntry* sys = &bad_sys; + + if (syscallno < VGP_(syscall_table_size) && + VGP_(syscall_table)[syscallno].before != NULL) + sys = &VGP_(syscall_table)[syscallno]; + + return sys; +} + + +/* Add and remove signals from mask so that we end up telling the + kernel the state we actually want rather than what the client + wants. */ +static void sanitize_client_sigmask(ThreadId tid, vki_sigset_t *mask) +{ + VG_(sigdelset)(mask, VKI_SIGKILL); + VG_(sigdelset)(mask, VKI_SIGSTOP); + VG_(sigdelset)(mask, VKI_SIGVGKILL); /* never block */ +} + +typedef + struct { + SyscallArgs orig_args; + SyscallArgs args; + SyscallStatus status; + UWord flags; + } + SyscallInfo; + +SyscallInfo syscallInfo[VG_N_THREADS]; + + +/* The scheduler needs to be able to zero out these records after a + fork, hence this is exported from m_syscalls. */ +void VG_(clear_syscallInfo) ( Int tid ) +{ + vg_assert(tid >= 0 && tid < VG_N_THREADS); + VG_(memset)( & syscallInfo[tid], 0, sizeof( syscallInfo[tid] )); + syscallInfo[tid].status.what = SsIdle; +} + +static void ensure_initialised ( void ) +{ + Int i; + static Bool init_done = False; + if (init_done) + return; + init_done = True; + for (i = 0; i < VG_N_THREADS; i++) { + VG_(clear_syscallInfo)( i ); + } +} + +/* --- This is the main function of this file. --- */ + +void VG_(client_syscall) ( ThreadId tid ) +{ + UWord sysno; + ThreadState* tst; + const SyscallTableEntry* ent; + SyscallArgLayout layout; + SyscallInfo* sci; + + ensure_initialised(); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + + /* First off, get the syscall args and number. This is a + platform-dependent action. */ + + sci = & syscallInfo[tid]; + vg_assert(sci->status.what == SsIdle); + + getSyscallArgsFromGuestState( &sci->orig_args, &tst->arch.vex ); + + /* Copy .orig_args to .args. The pre-handler may modify .args, but + we want to keep the originals too, just in case. */ + sci->args = sci->orig_args; + + /* Save the syscall number in the thread state in case the syscall + is interrupted by a signal. */ + sysno = sci->orig_args.sysno; + + /* The default what-to-do-next thing is hand the syscall to the + kernel, so we pre-set that here. */ + sci->status.what = SsHandToKernel; + sci->status.val = 0; + sci->flags = 0; + + /* Fetch the syscall's handlers. If no handlers exist for this + syscall, we are given dummy handlers which force an immediate + return with ENOSYS. */ + ent = get_syscall_entry(sysno); + + /* Fetch the layout information, which tells us where in the guest + state the syscall args reside. This is a platform-dependent + action. This info is needed so that the scalar syscall argument + checks (PRE_REG_READ calls) know which bits of the guest state + they need to inspect. */ + getSyscallArgLayout( &layout ); + + /* Make sure the tmp signal mask matches the real signal mask; + sigsuspend may change this. */ + vg_assert(VG_(iseqsigset)(&tst->sig_mask, &tst->tmp_sig_mask)); + + /* Right, we're finally ready to Party. Call the pre-handler and + see what we get back. At this point: + + sci->status.what is Unset (we don't know yet). + sci->orig_args contains the original args. + sci->args is the same as sci->orig_args. + sci->flags is zero. + */ + + PRINT("SYSCALL[%d,%d](%3lld) ", VG_(getpid)(), tid, (ULong)sysno); + + /* Do any pre-syscall actions */ + if (VG_(needs).syscall_wrapper) { + VG_TDICT_CALL(tool_pre_syscall, tid, sysno); + } + + vg_assert(ent); + vg_assert(ent->before); + (ent->before)( tid, + &layout, + &sci->args, &sci->status, &sci->flags ); + + /* The pre-handler may have modified: + sci->args + sci->status + sci->flags + All else remains unchanged. + Although the args may be modified, pre handlers are not allowed + to change the syscall number. + */ + /* Now we proceed according to what the pre-handler decided. */ + vg_assert(sci->status.what == SsHandToKernel + || sci->status.what == SsSuccess + || sci->status.what == SsFailure); + vg_assert(sci->args.sysno == sci->orig_args.sysno); + + if (sci->status.what == SsSuccess) { + /* The pre-handler completed the syscall itself, declaring + success. */ + PRINT(" --> [pre-success] Success(0x%llx)\n", (Long)sci->status.val ); + + /* In this case thes allowable flag are to ask for a signal-poll + and/or a yield after the call. Changing the args isn't + allowed. */ + vg_assert(0 == (sci->flags & ~(SfPollAfter | SfYieldAfter))); + vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); + } + + else + if (sci->status.what == SsFailure) { + /* The pre-handler decided to fail syscall itself. */ + PRINT(" --> [pre-fail] Failure(0x%llx)\n", (Long)sci->status.val ); + /* In this case, the pre-handler is also allowed to ask for the + post-handler to be run anyway. Changing the args is not + allowed. */ + vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail | SfPollAfter))); + vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); + } + + else + if (sci->status.what != SsHandToKernel) { + /* huh?! */ + vg_assert(0); + } + + else /* (sci->status.what == HandToKernel) */ { + /* Ok, this is the usual case -- and the complicated one. There + are two subcases: sync and async. async is the general case + and is to be used when there is any possibility that the + syscall might block [a fact that the pre-handler must tell us + via the sci->flags field.] Because the tidying-away / + context-switch overhead of the async case could be large, if + we are sure that the syscall will not block, we fast-track it + by doing it directly in this thread, which is a lot + simpler. */ + + /* Check that the given flags are allowable: MayBlock and + PostOnFail are ok. */ + vg_assert(0 == (sci->flags & ~(SfMayBlock | SfPostOnFail))); + + if (sci->flags & SfMayBlock) { + + /* Syscall may block, so run it asynchronously */ + vki_sigset_t mask; + +// vg_assert(!(sci->flags & PadAddr)); + PRINT(" --> [async] ... \n"); + + mask = tst->sig_mask; + sanitize_client_sigmask(tid, &mask); + + /* Gack. More impedance matching. Copy the possibly + modified syscall args back into the guest state. */ + vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); + putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex ); + + /* Drop the lock */ + VG_(set_sleeping)(tid, VgTs_WaitSys); + + /* Do the call, which operates directly on the guest state, + not on our abstracted copies of the args/result. */ + do_syscall_for_client(sysno, tst, &mask); + + /* do_syscall_for_client may not return if the syscall was + interrupted by a signal. In that case, flow of control is + first to m_signals.async_sighandler, which calls + VG_(fixup_guest_state_after_syscall_interrupted), which + fixes up the guest state, and possibly calls + VG_(post_syscall). Once that's done, control drops back + to the scheduler. */ + + /* Reacquire the lock */ + VG_(set_running)(tid); + + /* Even more impedance matching. Extract the syscall status + from the guest state. */ + getSyscallStatusFromGuestState( &sci->status, &tst->arch.vex ); + + PRINT("SYSCALL[%d,%d](%3d) ... [async] --> %s(0x%llx)\n", + VG_(getpid)(), tid, sysno, + sci->status.what==SsSuccess ? "Success" : "Failure", + (Long)sci->status.val ); + + } else { + + /* run the syscall directly */ + /* The pre-handler may have modified the syscall args, but + since we're passing values in ->args directly to the + kernel, there's no point in flushing them back to the + guest state. Indeed doing so could be construed as + incorrect. */ + +// if (sci->flags & PadAddr) +// VG_(pad_address_space)(VG_(client_end)); + + SysRes sres + = VG_(do_syscall6)(sysno, sci->args.arg1, sci->args.arg2, + sci->args.arg3, sci->args.arg4, + sci->args.arg5, sci->args.arg6 ); + sci->status = convert_SysRes_to_SyscallStatus(sres); + + PRINT("[sync] --> %s(0x%llx)\n", + sci->status.what==SsSuccess ? "Success" : "Failure", + (Long)sci->status.val ); + } + } + + vg_assert(sci->status.what == SsFailure + || sci->status.what == SsSuccess); + + vg_assert(VG_(is_running_thread)(tid)); + + /* Dump the syscall result back in the guest state. This is + a platform-specific action. */ + putSyscallStatusIntoGuestState( &sci->status, &tst->arch.vex ); + + /* Situation now: + - the guest state is now correctly modified following the syscall + - modified args, original args and syscall status are still + available in the syscallInfo[] entry for this syscall. + + Now go on to do the post-syscall actions (read on down ..) + */ + VG_(post_syscall)(tid); +} + + +/* Perform post syscall actions. The expected state on entry is + precisely as at the end of VG_(client_syscall), that is: + + - guest state up to date following the syscall + - modified args, original args and syscall status are still + available in the syscallInfo[] entry for this syscall. + - syscall status matches what's in the guest state. + + There are two ways to get here: the normal way -- being called by + VG_(client_syscall), and the unusual way, from + VG_(fixup_guest_state_after_syscall_interrupted). +*/ +void VG_(post_syscall) (ThreadId tid) +{ + SyscallArgLayout layout; + SyscallInfo* sci; + const SyscallTableEntry* ent; + SyscallStatus test_status; + ThreadState* tst; + UWord sysno; + + /* Preliminaries */ + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + sci = & syscallInfo[tid]; + + /* m_signals.sigvgkill_handler might call here even when not in + a syscall. */ + if (sci->status.what == SsIdle || sci->status.what == SsHandToKernel) { + sci->status.what = SsIdle; + return; + } + + /* Validate current syscallInfo entry. In particular we require + that the current .status matches what's actually in the guest + state. */ + vg_assert(sci->status.what == SsFailure + || sci->status.what == SsSuccess); + + getSyscallStatusFromGuestState( &test_status, &tst->arch.vex ); + vg_assert(eq_SyscallStatus( &sci->status, &test_status )); + /* Ok, looks sane */ + + /* Get the system call number. Because the pre-handler isn't + allowed to mess with it, it should be the same for both the + original and potentially-modified args. */ + vg_assert(sci->args.sysno == sci->orig_args.sysno); + sysno = sci->args.sysno; + ent = get_syscall_entry(sysno); + + /* We need the arg layout .. sigh */ + getSyscallArgLayout( &layout ); + + /* Tell the tool that the assignment has occurred, so it can update + shadow regs as necessary. */ + VG_TRACK( post_reg_write, Vg_CoreSysCall, tid, layout.o_retval, + sizeof(UWord) ); + + /* Consider, either success or failure. Now run the post handler if: + - it exists, and + - status==Success or (status==Fail and PostOnFail is set) + */ + if (ent->after + && (sci->status.what == SsSuccess + || (sci->status.what == SsFailure + && (sci->flags & SfPostOnFail) ))) { + + (ent->after)( tid, &sci->args, &sci->status ); + } + + /* Because the post handler might have changed the status (eg, the + post-handler for sys_open can change the result from success to + failure if the kernel supplied a fd that it doesn't like), once + again dump the syscall result back in the guest state.*/ + putSyscallStatusIntoGuestState( &sci->status, &tst->arch.vex ); + + /* Do any post-syscall actions required by the tool. */ + if (VG_(needs).syscall_wrapper) { + SysRes res; + res.val = sci->status.val; + res.isError = sci->status.what == SsFailure; + VG_TDICT_CALL(tool_post_syscall, tid, sysno, res); + } + +//zz if (flags & PadAddr) { +//zz vg_assert(!mayBlock); +//zz VG_(unpad_address_space)(VG_(client_end)); +//zz //VG_(sanity_check_memory)(); +//zz } +//zz + + /* The syscall is done. */ + sci->status.what = SsIdle; + + /* The pre/post wrappers may have concluded that pending signals + might have been created, and will have set SfPollAfter to + request a poll for them once the syscall is done. */ + if (sci->flags & SfPollAfter) + VG_(poll_signals)(tid); + + /* Similarly, the wrappers might have asked for a yield + afterwards. */ + if (sci->flags & SfYieldAfter) + VG_(vg_yield)(); +} + + +/* --------------------------------------------------------------------- + Dealing with syscalls which get interrupted by a signal: + VG_(fixup_guest_state_after_syscall_interrupted) + ------------------------------------------------------------------ */ + +/* Syscalls done on behalf of the client are finally handed off to the + kernel in VG_(client_syscall) above, either by calling + do_syscall_for_client (the async case), or by calling + VG_(do_syscall6) (the sync case). + + If the syscall is not interrupted by a signal (it may block and + later unblock, but that's irrelevant here) then those functions + eventually return and so control is passed to VG_(post_syscall). + NB: not sure if the sync case can actually get interrupted, as it + operates with all signals masked. + + However, the syscall may get interrupted by an async-signal. In + that case do_syscall_for_client/VG_(do_syscall6) do not + return. Instead we wind up in m_signals.async_sighandler. We need + to fix up the guest state to make it look like the syscall was + interrupted for guest. So async_sighandler calls here, and this + does the fixup. Note that from here we wind up calling + VG_(post_syscall) too. +*/ + + +/* These are addresses within VGA_(_do_syscall_for_client). See syscall.S for + details. */ +extern const Addr VGA_(blksys_setup); +extern const Addr VGA_(blksys_restart); +extern const Addr VGA_(blksys_complete); +extern const Addr VGA_(blksys_committed); +extern const Addr VGA_(blksys_finished); + + +/* Back up guest state to restart a system call. */ + +void VG_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) +{ +# if defined(VGP_x86_linux) + arch->vex.guest_EIP -= 2; // sizeof(int $0x80) + + /* Make sure our caller is actually sane, and we're really backing + back over a syscall. + + int $0x80 == CD 80 + */ + { + UChar *p = (UChar *)arch->vex.guest_EIP; + + if (p[0] != 0xcd || p[1] != 0x80) + VG_(message)(Vg_DebugMsg, + "?! restarting over syscall at %p %02x %02x\n", + arch->vex.guest_EIP, p[0], p[1]); + + vg_assert(p[0] == 0xcd && p[1] == 0x80); + } +# else + +# error "VG_(fixup_guest_state_to_restart_syscall): unknown plat" +# endif +} + +/* + Fix up the guest state when a syscall is interrupted by a signal + and so has been forced to return 'sysret'. + + To do this, we determine the precise state of the syscall by + looking at the (real) IP at the time the signal happened. The + syscall sequence looks like: + + 1. unblock signals + 2. perform syscall + 3. save result to guest state (EAX, RAX, R3+CR0.SO) + 4. re-block signals + + If a signal + happens at Then Why? + [1-2) restart nothing has happened (restart syscall) + [2] restart syscall hasn't started, or kernel wants to restart + [2-3) save syscall complete, but results not saved + [3-4) syscall complete, results saved + + Sometimes we never want to restart an interrupted syscall (because + sigaction says not to), so we only restart if "restart" is True. + + This will also call VG_(post_syscall) if the syscall has actually + completed (either because it was interrupted, or because it + actually finished). It will not call VG_(post_syscall) if the + syscall is set up for restart, which means that the pre-wrapper may + get called multiple times. +*/ + +void +VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, + Addr ip, + UWord sysnum, + SysRes sysret, + Bool restart) +{ + /* Note that the sysnum arg seems to contain not-dependable-on info + (I think it depends on the state the real syscall was in at + interrupt) and so is ignored, apart from in the following + printf. */ + + static const Bool debug = False; + + ThreadState* tst; + SyscallStatus canonical; + ThreadArchState* th_regs; + SyscallInfo* sci; + + if (debug) + VG_(printf)( "interrupted_syscall %d: tid=%d, IP=0x%llx, " + "restart=%s, sysret.isError=%s, sysret.val=%lld\n", + (Int)sysnum, + (Int)tid, + (ULong)ip, + restart ? "True" : "False", + sysret.isError ? "True" : "False", + (Long)(Word)sysret.val ); + + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + + tst = VG_(get_ThreadState)(tid); + th_regs = &tst->arch; + sci = & syscallInfo[tid]; + + /* Figure out what the state of the syscall was by examining the + (real) IP at the time of the signal, and act accordingly. */ + + if (ip < VGA_(blksys_setup) || ip >= VGA_(blksys_finished)) { + VG_(printf)(" not in syscall (%p - %p)\n", + VGA_(blksys_setup), VGA_(blksys_finished)); + /* Looks like we weren't in a syscall at all. Hmm. */ + vg_assert(sci->status.what != SsIdle); + return; + } + + /* We should not be here unless this thread had first started up + the machinery for a syscall by calling VG_(client_syscall). + Hence: */ + vg_assert(sci->status.what != SsIdle); + + if (ip >= VGA_(blksys_setup) && ip < VGA_(blksys_restart)) { + /* syscall hasn't even started; go around again */ + if (debug) + VG_(printf)(" not started: restart\n"); + vg_assert(sci->status.what == SsHandToKernel); + VG_(fixup_guest_state_to_restart_syscall)(th_regs); + } + + else + if (ip == VGA_(blksys_restart)) { + /* We're either about to run the syscall, or it was interrupted + and the kernel restarted it. Restart if asked, otherwise + EINTR it. */ + if (restart) + VG_(fixup_guest_state_to_restart_syscall)(th_regs); + else { + canonical = convert_SysRes_to_SyscallStatus( + VG_(mk_SysRes_Error)( VKI_EINTR ) + ); + putSyscallStatusIntoGuestState( &canonical, &th_regs->vex ); + sci->status = canonical; + VG_(post_syscall)(tid); + } + } + + else + if (ip >= VGA_(blksys_complete) && ip < VGA_(blksys_committed)) { + /* Syscall complete, but result hasn't been written back yet. + Write the SysRes we were supplied with back to the guest + state. */ + if (debug) + VG_(printf)(" completed\n", sysret); + canonical = convert_SysRes_to_SyscallStatus( sysret ); + putSyscallStatusIntoGuestState( &canonical, &th_regs->vex ); + sci->status = canonical; + VG_(post_syscall)(tid); + } + + else + if (ip >= VGA_(blksys_committed) && ip < VGA_(blksys_finished)) { + /* Result committed, but the signal mask has not been restored; + we expect our caller (the signal handler) will have fixed + this up. */ + if (debug) + VG_(printf)(" all done\n"); + VG_(post_syscall)(tid); + } + + else + VG_(core_panic)("?? strange syscall interrupt state?"); + + /* In all cases, the syscall is now finished (even if we called + VG_(fixup_guest_state_to_restart_syscall), since that just + re-positions the guest's IP for another go at it). So we need + to record that fact. */ + sci->status.what = SsIdle; +} + + +/*--------------------------------------------------------------------*/ +/*--- end syscalls-main.c ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_syscalls/syscalls-x86-linux.c b/coregrind/m_syscalls/syscalls-x86-linux.c index 691be0278..74f9bb135 100644 --- a/coregrind/m_syscalls/syscalls-x86-linux.c +++ b/coregrind/m_syscalls/syscalls-x86-linux.c @@ -37,12 +37,21 @@ #include "ume.h" /* for jmp_with_stack */ #include "pub_core_debuglog.h" #include "pub_core_aspacemgr.h" +#include "pub_core_options.h" +#include "pub_core_libcbase.h" #include "pub_core_libcassert.h" #include "pub_core_libcprint.h" #include "pub_core_sigframe.h" #include "pub_core_syscalls.h" #include "pub_core_tooliface.h" -#include "priv_syscalls.h" +#include "pub_core_signals.h" + +#include "priv_types_n_macros.h" +#include "priv_syscalls-generic.h" /* for decls of generic wrappers */ +#include "priv_syscalls-linux.h" /* for decls of linux-ish wrappers */ +#include "priv_syscalls-main.h" + +#include "vki_unistd.h" /* for the __NR_* constants */ /* --------------------------------------------------------------------- @@ -50,137 +59,6 @@ Note. Why is this stuff here? ------------------------------------------------------------------ */ - -/* These are addresses within VGA_(client_syscall). See syscall.S for details. */ -extern const Addr VGA_(blksys_setup); -extern const Addr VGA_(blksys_restart); -extern const Addr VGA_(blksys_complete); -extern const Addr VGA_(blksys_committed); -extern const Addr VGA_(blksys_finished); - -// Back up to restart a system call. -static void restart_syscall(ThreadArchState *arch) -{ - arch->vex.guest_EIP -= 2; // sizeof(int $0x80) - - /* Make sure our caller is actually sane, and we're really backing - back over a syscall. - - int $0x80 == CD 80 - */ - { - UChar *p = (UChar *)arch->vex.guest_EIP; - - if (p[0] != 0xcd || p[1] != 0x80) - VG_(message)(Vg_DebugMsg, - "?! restarting over syscall at %p %02x %02x\n", - arch->vex.guest_EIP, p[0], p[1]); - - vg_assert(p[0] == 0xcd && p[1] == 0x80); - } -} - -/* - Fix up the VCPU state when a syscall is interrupted by a signal. - - To do this, we determine the precise state of the syscall by - looking at the (real) eip at the time the signal happened. The - syscall sequence looks like: - - 1. unblock signals - 2. perform syscall - 3. save result to EAX - 4. re-block signals - - If a signal - happens at Then Why? - [1-2) restart nothing has happened (restart syscall) - [2] restart syscall hasn't started, or kernel wants to restart - [2-3) save syscall complete, but results not saved - [3-4) syscall complete, results saved - - Sometimes we never want to restart an interrupted syscall (because - sigaction says not to), so we only restart if "restart" is True. - - This will also call VG_(post_syscall)() if the syscall has actually - completed (either because it was interrupted, or because it - actually finished). It will not call VG_(post_syscall)() if the - syscall is set up for restart, which means that the pre-wrapper may - get called multiple times. - */ -/* NB: this is identical to the amd64 version */ -void VGP_(interrupted_syscall)(ThreadId tid, - Word eip, UWord sysnum, UWord sysret, - Bool restart) -{ - static const Bool debug = 0; - - ThreadState *tst = VG_(get_ThreadState)(tid); - ThreadArchState *th_regs = &tst->arch; - - if (debug) - VG_(printf)("interrupted_syscall: eip=%p; restart=%d eax=%d\n", - eip, restart, sysnum); - - if (eip < VGA_(blksys_setup) || eip >= VGA_(blksys_finished)) { - VG_(printf)(" not in syscall (%p - %p)\n", VGA_(blksys_setup), VGA_(blksys_finished)); - vg_assert(tst->syscallno == -1); - return; - } - - vg_assert(tst->syscallno != -1); - - if (eip >= VGA_(blksys_setup) && eip < VGA_(blksys_restart)) { - /* syscall hasn't even started; go around again */ - if (debug) - VG_(printf)(" not started: restart\n"); - restart_syscall(th_regs); - } else if (eip == VGA_(blksys_restart)) { - /* We're either about to run the syscall, or it was interrupted - and the kernel restarted it. Restart if asked, otherwise - EINTR it. */ - if (restart) - restart_syscall(th_regs); - else { - th_regs->vex.VGP_SYSCALL_RET = -VKI_EINTR; - VG_(post_syscall)(tid); - } - } else if (eip >= VGA_(blksys_complete) && eip < VGA_(blksys_committed)) { - /* Syscall complete, but result hasn't been written back yet. - The saved real CPU %eax has the result, which we need to move - to EAX. */ - if (debug) - VG_(printf)(" completed: ret=%d\n", sysret); - th_regs->vex.VGP_SYSCALL_RET = sysret; - VG_(post_syscall)(tid); - } else if (eip >= VGA_(blksys_committed) && eip < VGA_(blksys_finished)) { - /* Result committed, but the signal mask has not been restored; - we expect our caller (the signal handler) will have fixed - this up. */ - if (debug) - VG_(printf)(" all done\n"); - VG_(post_syscall)(tid); - } else - VG_(core_panic)("?? strange syscall interrupt state?"); - - tst->syscallno = -1; -} - -extern void VGA_(_client_syscall)(Int syscallno, - void* guest_state, - const vki_sigset_t *syscall_mask, - const vki_sigset_t *restore_mask, - Int nsigwords); - -void VGA_(client_syscall)(Int syscallno, ThreadState *tst, - const vki_sigset_t *syscall_mask) -{ - vki_sigset_t saved; - VGA_(_client_syscall)(syscallno, &tst->arch.vex, - syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord)); -} - - /* Allocate a stack for this thread. @@ -204,11 +82,11 @@ static UWord* allocstack(ThreadId tid) -1, 0); if (stk != (void *)-1) { - VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page */ - tst->os_state.valgrind_stack_base = ((Addr)stk) + VKI_PAGE_SIZE; - tst->os_state.valgrind_stack_szB = STACK_SIZE_W * sizeof(UWord); + VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page */ + tst->os_state.valgrind_stack_base = ((Addr)stk) + VKI_PAGE_SIZE; + tst->os_state.valgrind_stack_szB = STACK_SIZE_W * sizeof(UWord); } else - return (UWord*)-1; + return (UWord*)-1; } for (esp = (UWord*) tst->os_state.valgrind_stack_base; @@ -361,9 +239,97 @@ static Int start_thread_NORETURN ( void* arg ) clone() handling ------------------------------------------------------------------ */ +/* + Perform a clone system call. clone is strange because it has + fork()-like return-twice semantics, so it needs special + handling here. + + Upon entry, we have: + + int (fn)(void*) in 0+FSZ(%esp) + void* child_stack in 4+FSZ(%esp) + int flags in 8+FSZ(%esp) + void* arg in 12+FSZ(%esp) + pid_t* child_tid in 16+FSZ(%esp) + pid_t* parent_tid in 20+FSZ(%esp) + void* tls_ptr in 24+FSZ(%esp) + + System call requires: + + int $__NR_clone in %eax + int flags in %ebx + void* child_stack in %ecx + pid_t* parent_tid in %edx + pid_t* child_tid in %edi + void* tls_ptr in %esi + + Returns an Int encoded in the linux-x86 way, not a SysRes. + */ +#define STRINGIFZ(__str) #__str +#define STRINGIFY(__str) STRINGIFZ(__str) +#define FSZ "4+4+4" /* frame size = retaddr+ebx+edi */ +#define __NR_CLONE STRINGIFY(__NR_clone) +#define __NR_EXIT STRINGIFY(__NR_exit) + +extern +Int do_syscall_clone_x86_linux ( Int (*fn)(void *), + void* stack, + Int flags, + void* arg, + Int* child_tid, + Int* parent_tid, + vki_modify_ldt_t * ); +asm( +"\n" +"do_syscall_clone_x86_linux:\n" +" push %ebx\n" +" push %edi\n" + + /* set up child stack with function and arg */ +" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */ +" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */ +" movl 0+"FSZ"(%esp), %eax\n" /* fn */ +" lea -8(%ecx), %ecx\n" /* make space on stack */ +" movl %ebx, 4(%ecx)\n" /* fn arg */ +" movl %eax, 0(%ecx)\n" /* fn */ + + /* get other args to clone */ +" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */ +" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */ +" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg4: child tid * */ +" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg5: tls_ptr * */ +" movl $"__NR_CLONE", %eax\n" +" int $0x80\n" /* clone() */ +" testl %eax, %eax\n" /* child if retval == 0 */ +" jnz 1f\n" + + /* CHILD - call thread function */ +" popl %eax\n" +" call *%eax\n" /* call fn */ + + /* exit with result */ +" movl %eax, %ebx\n" /* arg1: return value from fn */ +" movl $"__NR_EXIT", %eax\n" +" int $0x80\n" + + /* Hm, exit returned */ +" ud2\n" + +"1: /* PARENT or ERROR */\n" +" pop %edi\n" +" pop %ebx\n" +" ret\n" +); + +#undef FSZ +#undef __NR_CLONE +#undef __NR_EXIT +#undef STRINGIFY +#undef STRINGIFZ + // forward declarations static void setup_child ( ThreadArchState*, ThreadArchState*, Bool ); -static Int sys_set_thread_area ( ThreadId, vki_modify_ldt_t* ); +static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* ); /* When a client clones, we need to keep track of the new thread. This means: @@ -375,20 +341,21 @@ static Int sys_set_thread_area ( ThreadId, vki_modify_ldt_t* ); but using the scheduler entrypoint for EIP, and a separate stack for ESP. */ -static Int do_clone(ThreadId ptid, - UInt flags, Addr esp, - Int *parent_tidptr, - Int *child_tidptr, - vki_modify_ldt_t *tlsinfo) +static SysRes do_clone ( ThreadId ptid, + UInt flags, Addr esp, + Int *parent_tidptr, + Int *child_tidptr, + vki_modify_ldt_t *tlsinfo) { static const Bool debug = False; - ThreadId ctid = VG_(alloc_ThreadState)(); - ThreadState *ptst = VG_(get_ThreadState)(ptid); - ThreadState *ctst = VG_(get_ThreadState)(ctid); - UWord *stack; - Segment *seg; - Int ret; + ThreadId ctid = VG_(alloc_ThreadState)(); + ThreadState* ptst = VG_(get_ThreadState)(ptid); + ThreadState* ctst = VG_(get_ThreadState)(ctid); + UWord* stack; + Segment* seg; + SysRes res; + Int eax; vki_sigset_t blockall, savedmask; VG_(sigfillset)(&blockall); @@ -416,7 +383,9 @@ static Int do_clone(ThreadId ptid, is passed as an arg to setup_child. */ setup_child( &ctst->arch, &ptst->arch, True /*VG_(clo_support_elan3)*/ ); - VGP_SET_SYSCALL_RESULT(ctst->arch, 0); + /* Make sys_clone appear to have returned zero in the child. */ + ctst->arch.vex.guest_EAX = 0; + if (esp != 0) ctst->arch.vex.guest_ESP = esp; @@ -447,13 +416,14 @@ static Int do_clone(ThreadId ptid, if (flags & VKI_CLONE_SETTLS) { if (debug) - VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d base=%p limit=%x; esp=%p fs=%x gs=%x\n", - tlsinfo, tlsinfo->entry_number, tlsinfo->base_addr, tlsinfo->limit, + VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d " + "base=%p limit=%x; esp=%p fs=%x gs=%x\n", + tlsinfo, tlsinfo->entry_number, + tlsinfo->base_addr, tlsinfo->limit, ptst->arch.vex.guest_ESP, ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS); - ret = sys_set_thread_area(ctid, tlsinfo); - - if (ret != 0) + res = sys_set_thread_area(ctid, tlsinfo); + if (res.isError) goto out; } @@ -463,30 +433,37 @@ static Int do_clone(ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); /* Create the new thread */ - ret = VG_(clone)(start_thread_NORETURN, stack, flags, &VG_(threads)[ctid], - child_tidptr, parent_tidptr, NULL); - + eax = do_syscall_clone_x86_linux( + start_thread_NORETURN, stack, flags, &VG_(threads)[ctid], + child_tidptr, parent_tidptr, NULL + ); + res = VG_(mk_SysRes_x86_linux)( eax ); VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); out: - if (ret < 0) { + if (res.isError) { /* clone failed */ VGP_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; } - return ret; + return res; } + /* Do a clone which is really a fork() */ -static Int do_fork_clone(ThreadId tid, UInt flags, Addr esp, Int *parent_tidptr, Int *child_tidptr) +static SysRes do_fork_clone ( ThreadId tid, + UInt flags, Addr esp, + Int* parent_tidptr, + Int* child_tidptr ) { vki_sigset_t fork_saved_mask; vki_sigset_t mask; - Int ret; + SysRes res; - if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM | VKI_CLONE_FILES | VKI_CLONE_VFORK)) - return -VKI_EINVAL; + if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM + | VKI_CLONE_FILES | VKI_CLONE_VFORK)) + return VG_(mk_SysRes_Error)( VKI_EINVAL ); /* Block all signals during fork, so that we can fix things up in the child without being interrupted. */ @@ -497,19 +474,22 @@ static Int do_fork_clone(ThreadId tid, UInt flags, Addr esp, Int *parent_tidptr, /* Since this is the fork() form of clone, we don't need all that VG_(clone) stuff */ - ret = VG_(do_syscall5)(__NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, + res = VG_(do_syscall5)(__NR_clone, flags, (UWord)NULL, (UWord)parent_tidptr, (UWord)NULL, (UWord)child_tidptr); - if (ret == 0) { + if (!res.isError && res.val == 0) { /* child */ VG_(do_atfork_child)(tid); /* restore signal mask */ VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); - } else if (ret > 0) { + } + else + if (!res.isError && res.val > 0) { /* parent */ if (VG_(clo_trace_syscalls)) - VG_(printf)(" clone(fork): process %d created child %d\n", VG_(getpid)(), ret); + VG_(printf)(" clone(fork): process %d created child %d\n", + VG_(getpid)(), res.val); VG_(do_atfork_parent)(tid); @@ -517,7 +497,7 @@ static Int do_fork_clone(ThreadId tid, UInt flags, Addr esp, Int *parent_tidptr, VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); } - return ret; + return res; } /* --------------------------------------------------------------------- @@ -585,7 +565,7 @@ static Int do_fork_clone(ThreadId tid, UInt flags, Addr esp, Int *parent_tidptr, static void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn, - /* OUT */ VexGuestX86SegDescr* out, + /* OUT */ VexGuestX86SegDescr* out, Int oldmode ) { UInt entry_1, entry_2; @@ -655,22 +635,22 @@ static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt ) static void copy_LDT_from_to ( VexGuestX86SegDescr* src, VexGuestX86SegDescr* dst ) { - Int i; - vg_assert(src); - vg_assert(dst); - for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++) - dst[i] = src[i]; + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++) + dst[i] = src[i]; } /* Copy contents between two existing GDTs. */ static void copy_GDT_from_to ( VexGuestX86SegDescr* src, VexGuestX86SegDescr* dst ) { - Int i; - vg_assert(src); - vg_assert(dst); - for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++) - dst[i] = src[i]; + Int i; + vg_assert(src); + vg_assert(dst); + for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++) + dst[i] = src[i]; } /* Free this thread's DTs, if it has any. */ @@ -709,9 +689,9 @@ static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex ) * the security checks done on new descriptors. */ static -Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount ) +SysRes read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount ) { - Int err; + SysRes res; UInt i, size; UChar* ldt; @@ -723,7 +703,7 @@ Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount ) vg_assert(8 == sizeof(VexGuestX86SegDescr)); ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT); - err = 0; + res = VG_(mk_SysRes_Success)( 0 ); if (ldt == NULL) /* LDT not allocated, meaning all entries are null */ goto out; @@ -732,19 +712,19 @@ Int read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount ) if (size > bytecount) size = bytecount; - err = size; + res = VG_(mk_SysRes_Success)( size ); for (i = 0; i < size; i++) ptr[i] = ldt[i]; out: - return err; + return res; } static -Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode ) +SysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode ) { - Int error; + SysRes res; VexGuestX86SegDescr* ldt; vki_modify_ldt_t* ldt_info; @@ -759,11 +739,11 @@ Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode ) ldt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT; ldt_info = (vki_modify_ldt_t*)ptr; - error = -VKI_EINVAL; + res = VG_(mk_SysRes_Error)( VKI_EINVAL ); if (bytecount != sizeof(vki_modify_ldt_t)) goto out; - error = -VKI_EINVAL; + res = VG_(mk_SysRes_Error)( VKI_EINVAL ); if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT) goto out; if (ldt_info->contents == 3) { @@ -782,17 +762,17 @@ Int write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode ) /* Install the new entry ... */ translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode ); - error = 0; + res = VG_(mk_SysRes_Success)( 0 ); out: - return error; + return res; } -static Int sys_modify_ldt ( ThreadId tid, - Int func, void* ptr, UInt bytecount ) +static SysRes sys_modify_ldt ( ThreadId tid, + Int func, void* ptr, UInt bytecount ) { - Int ret = -VKI_ENOSYS; + SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS ); switch (func) { case 0: @@ -815,16 +795,16 @@ static Int sys_modify_ldt ( ThreadId tid, } -static Int sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) +static SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) { - Int idx; + Int idx; VexGuestX86SegDescr* gdt; vg_assert(8 == sizeof(VexGuestX86SegDescr)); vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); if (info == NULL) - return -VKI_EFAULT; + return VG_(mk_SysRes_Error)( VKI_EFAULT ); gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; @@ -845,9 +825,9 @@ static Int sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) } if (idx == VEX_GUEST_X86_GDT_NENT) - return -VKI_ESRCH; + return VG_(mk_SysRes_Error)( VKI_ESRCH ); } else if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) { - return -VKI_EINVAL; + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } translate_to_hw_format(info, &gdt[idx], 0); @@ -859,49 +839,49 @@ static Int sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, (Addr) & info->entry_number, sizeof(unsigned int) ); - return 0; + return VG_(mk_SysRes_Success)( 0 ); } -static Int sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) -{ - Int idx; - VexGuestX86SegDescr* gdt; - - vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); - vg_assert(8 == sizeof(VexGuestX86SegDescr)); - - if (info == NULL) - return -VKI_EFAULT; - - idx = info->entry_number; - - if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) - return -VKI_EINVAL; - - gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; - - /* If the thread doesn't have a GDT, allocate it now. */ - if (!gdt) { - gdt = alloc_zeroed_x86_GDT(); - VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; - } - - info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) | - ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) | - gdt[idx].LdtEnt.Bits.BaseLow; - info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) | - gdt[idx].LdtEnt.Bits.LimitLow; - info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big; - info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3; - info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1; - info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity; - info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1; - info->useable = gdt[idx].LdtEnt.Bits.Sys; - info->reserved = 0; - - return 0; -} +//zz static Int sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info ) +//zz { +//zz Int idx; +//zz VexGuestX86SegDescr* gdt; +//zz +//zz vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); +//zz vg_assert(8 == sizeof(VexGuestX86SegDescr)); +//zz +//zz if (info == NULL) +//zz return -VKI_EFAULT; +//zz +//zz idx = info->entry_number; +//zz +//zz if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) +//zz return -VKI_EINVAL; +//zz +//zz gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT; +//zz +//zz /* If the thread doesn't have a GDT, allocate it now. */ +//zz if (!gdt) { +//zz gdt = alloc_zeroed_x86_GDT(); +//zz VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; +//zz } +//zz +//zz info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) | +//zz ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) | +//zz gdt[idx].LdtEnt.Bits.BaseLow; +//zz info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) | +//zz gdt[idx].LdtEnt.Bits.LimitLow; +//zz info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big; +//zz info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3; +//zz info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1; +//zz info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity; +//zz info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1; +//zz info->useable = gdt[idx].LdtEnt.Bits.Sys; +//zz info->reserved = 0; +//zz +//zz return 0; +//zz } /* --------------------------------------------------------------------- More thread stuff @@ -946,50 +926,64 @@ static void setup_child ( /*OUT*/ ThreadArchState *child, } } + /* --------------------------------------------------------------------- PRE/POST wrappers for x86/Linux-specific syscalls ------------------------------------------------------------------ */ -// Nb: See the comment above the generic PRE/POST wrappers in -// coregrind/vg_syscalls.c for notes about how they work. - -#define PRE(name, f) PRE_TEMPLATE(static, x86_linux, name, f) -#define POST(name) POST_TEMPLATE(static, x86_linux, name) - -PRE(old_select, MayBlock) -{ - /* struct sel_arg_struct { - unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; - }; - */ - PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args); - PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) ); - - { - UInt* arg_struct = (UInt*)ARG1; - UInt a1, a2, a3, a4, a5; - - a1 = arg_struct[0]; - a2 = arg_struct[1]; - a3 = arg_struct[2]; - a4 = arg_struct[3]; - a5 = arg_struct[4]; - - PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5); - if (a2 != (Addr)NULL) - PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ ); - if (a3 != (Addr)NULL) - PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ ); - if (a4 != (Addr)NULL) - PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ ); - if (a5 != (Addr)NULL) - PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) ); - } -} - -PRE(sys_clone, Special) +#define PRE(name) DEFN_PRE_TEMPLATE(x86_linux, name) +#define POST(name) DEFN_POST_TEMPLATE(x86_linux, name) + +/* Add prototypes for the wrappers declared here, so that gcc doesn't + harass us for not having prototypes. Really this is a kludge -- + the right thing to do is to make these wrappers 'static' since they + aren't visible outside this file, but that requires even more macro + magic. */ +DECL_TEMPLATE(x86_linux, sys_socketcall); +DECL_TEMPLATE(x86_linux, sys_stat64); +DECL_TEMPLATE(x86_linux, sys_fstat64); +DECL_TEMPLATE(x86_linux, sys_lstat64); +DECL_TEMPLATE(x86_linux, sys_clone); +DECL_TEMPLATE(x86_linux, old_mmap); +DECL_TEMPLATE(x86_linux, sys_sigreturn); +DECL_TEMPLATE(x86_linux, sys_ipc); +DECL_TEMPLATE(x86_linux, sys_rt_sigreturn); +DECL_TEMPLATE(x86_linux, sys_modify_ldt); + +//zz PRE(old_select, MayBlock) +//zz { +//zz /* struct sel_arg_struct { +//zz unsigned long n; +//zz fd_set *inp, *outp, *exp; +//zz struct timeval *tvp; +//zz }; +//zz */ +//zz PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args); +//zz PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) ); +//zz +//zz { +//zz UInt* arg_struct = (UInt*)ARG1; +//zz UInt a1, a2, a3, a4, a5; +//zz +//zz a1 = arg_struct[0]; +//zz a2 = arg_struct[1]; +//zz a3 = arg_struct[2]; +//zz a4 = arg_struct[3]; +//zz a5 = arg_struct[4]; +//zz +//zz PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5); +//zz if (a2 != (Addr)NULL) +//zz PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ ); +//zz if (a3 != (Addr)NULL) +//zz PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ ); +//zz if (a4 != (Addr)NULL) +//zz PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ ); +//zz if (a5 != (Addr)NULL) +//zz PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) ); +//zz } +//zz } + +PRE(sys_clone) { UInt cloneflags; @@ -1004,21 +998,21 @@ PRE(sys_clone, Special) if (ARG1 & VKI_CLONE_PARENT_SETTID) { PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int)); if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) { - SET_RESULT( -VKI_EFAULT ); + SET_STATUS_Failure( VKI_EFAULT ); return; } } if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) { PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int)); if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) { - SET_RESULT( -VKI_EFAULT ); + SET_STATUS_Failure( VKI_EFAULT ); return; } } if (ARG1 & VKI_CLONE_SETTLS) { PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t)); if (!VG_(is_addressable)(ARG4, sizeof(vki_modify_ldt_t), VKI_PROT_READ)) { - SET_RESULT( -VKI_EFAULT ); + SET_STATUS_Failure( VKI_EFAULT ); return; } } @@ -1026,7 +1020,7 @@ PRE(sys_clone, Special) cloneflags = ARG1; if (!VG_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) { - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); return; } @@ -1040,6 +1034,7 @@ PRE(sys_clone, Special) if ( (cloneflags == 0x100011 || cloneflags == 0x1200011 || cloneflags == 0x7D0F00 + || cloneflags == 0x790F00 || cloneflags == 0x3D0F00 || cloneflags == 0xF00 || cloneflags == 0xF21)) { @@ -1051,15 +1046,17 @@ PRE(sys_clone, Special) } /* Only look at the flags we really care about */ - switch(cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VFORK)) { + switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS + | VKI_CLONE_FILES | VKI_CLONE_VFORK)) { case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES: /* thread creation */ - SET_RESULT(do_clone(tid, - ARG1, /* flags */ - (Addr)ARG2, /* child ESP */ - (Int *)ARG3, /* parent_tidptr */ - (Int *)ARG5, /* child_tidptr */ - (vki_modify_ldt_t *)ARG4)); /* set_tls */ + SET_STATUS_from_SysRes( + do_clone(tid, + ARG1, /* flags */ + (Addr)ARG2, /* child ESP */ + (Int *)ARG3, /* parent_tidptr */ + (Int *)ARG5, /* child_tidptr */ + (vki_modify_ldt_t *)ARG4)); /* set_tls */ break; case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */ @@ -1067,11 +1064,12 @@ PRE(sys_clone, Special) cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM); case 0: /* plain fork */ - SET_RESULT(do_fork_clone(tid, - cloneflags, /* flags */ - (Addr)ARG2, /* child ESP */ - (Int *)ARG3, /* parent_tidptr */ - (Int *)ARG5)); /* child_tidptr */ + SET_STATUS_from_SysRes( + do_fork_clone(tid, + cloneflags, /* flags */ + (Addr)ARG2, /* child ESP */ + (Int *)ARG3, /* parent_tidptr */ + (Int *)ARG5)); /* child_tidptr */ break; default: @@ -1094,7 +1092,7 @@ PRE(sys_clone, Special) ("Valgrind does not support general clone()."); } - if (!VG_(is_kerror)(RES)) { + if (SUCCESS) { if (ARG1 & VKI_CLONE_PARENT_SETTID) POST_MEM_WRITE(ARG3, sizeof(Int)); if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) @@ -1102,53 +1100,77 @@ PRE(sys_clone, Special) /* Thread creation was successful; let the child have the chance to run */ - VG_(vg_yield)(); + *flags |= SfYieldAfter; } } -PRE(sys_sigreturn, Special) +PRE(sys_sigreturn) { + ThreadState* tst; PRINT("sigreturn ( )"); + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + /* Adjust esp to point to start of frame; skip back up over sigreturn sequence's "popl %eax" and handler ret addr */ + tst = VG_(get_ThreadState)(tid); tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word); /* This is only so that the EIP is (might be) useful to report if something goes wrong in the sigreturn */ - restart_syscall(&tst->arch); + VG_(fixup_guest_state_to_restart_syscall)(&tst->arch); VG_(sigframe_destroy)(tid, False); - /* Keep looking for signals until there are none */ - VG_(poll_signals)(tid); + /* For unclear reasons, it appears we need the syscall to return + without changing %EAX. Since %EAX is the return value, and can + denote either success or failure, we must set up so that the + driver logic copies it back unchanged. Also, note %EAX is of + the guest registers written by VG_(sigframe_destroy). */ + SET_STATUS_from_SysRes( + VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) + ); - /* placate return-must-be-set assertion */ - SET_RESULT(RES); + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; } -PRE(sys_rt_sigreturn, Special) +PRE(sys_rt_sigreturn) { + ThreadState* tst; PRINT("rt_sigreturn ( )"); + vg_assert(VG_(is_valid_tid)(tid)); + vg_assert(tid >= 1 && tid < VG_N_THREADS); + vg_assert(VG_(is_running_thread)(tid)); + /* Adjust esp to point to start of frame; skip back up over handler ret addr */ + tst = VG_(get_ThreadState)(tid); tst->arch.vex.guest_ESP -= sizeof(Addr); /* This is only so that the EIP is (might be) useful to report if something goes wrong in the sigreturn */ - restart_syscall(&tst->arch); + VG_(fixup_guest_state_to_restart_syscall)(&tst->arch); VG_(sigframe_destroy)(tid, True); - /* Keep looking for signals until there are none */ - VG_(poll_signals)(tid); + /* For unclear reasons, it appears we need the syscall to return + without changing %EAX. Since %EAX is the return value, and can + denote either success or failure, we must set up so that the + driver logic copies it back unchanged. Also, note %EAX is of + the guest registers written by VG_(sigframe_destroy). */ + SET_STATUS_from_SysRes( + VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) + ); - /* placate return-must-be-set assertion */ - SET_RESULT(RES); + /* Check to see if some any signals arose as a result of this. */ + *flags |= SfPollAfter; } -PRE(sys_modify_ldt, Special) +PRE(sys_modify_ldt) { PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3); PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr, @@ -1163,101 +1185,101 @@ PRE(sys_modify_ldt, Special) PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) ); } /* "do" the syscall ourselves; the kernel never sees it */ - SET_RESULT( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) ); + SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) ); - if (ARG1 == 0 && !VG_(is_kerror)(RES) && RES > 0) { + if (ARG1 == 0 && SUCCESS && RES > 0) { POST_MEM_WRITE( ARG2, RES ); } } -PRE(sys_set_thread_area, Special) -{ - PRINT("sys_set_thread_area ( %p )", ARG1); - PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info) - PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) ); - - /* "do" the syscall ourselves; the kernel never sees it */ - SET_RESULT( sys_set_thread_area( tid, (void *)ARG1 ) ); -} - -PRE(sys_get_thread_area, Special) -{ - PRINT("sys_get_thread_area ( %p )", ARG1); - PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info) - PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) ); - - /* "do" the syscall ourselves; the kernel never sees it */ - SET_RESULT( sys_get_thread_area( tid, (void *)ARG1 ) ); - - if (!VG_(is_kerror)(RES)) { - POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) ); - } -} - -// Parts of this are x86-specific, but the *PEEK* cases are generic. -// XXX: Why is the memory pointed to by ARG3 never checked? -PRE(sys_ptrace, 0) -{ - PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4); - PRE_REG_READ4(int, "ptrace", - long, request, long, pid, long, addr, long, data); - switch (ARG1) { - case VKI_PTRACE_PEEKTEXT: - case VKI_PTRACE_PEEKDATA: - case VKI_PTRACE_PEEKUSR: - PRE_MEM_WRITE( "ptrace(peek)", ARG4, - sizeof (long)); - break; - case VKI_PTRACE_GETREGS: - PRE_MEM_WRITE( "ptrace(getregs)", ARG4, - sizeof (struct vki_user_regs_struct)); - break; - case VKI_PTRACE_GETFPREGS: - PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4, - sizeof (struct vki_user_i387_struct)); - break; - case VKI_PTRACE_GETFPXREGS: - PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4, - sizeof(struct vki_user_fxsr_struct) ); - break; - case VKI_PTRACE_SETREGS: - PRE_MEM_READ( "ptrace(setregs)", ARG4, - sizeof (struct vki_user_regs_struct)); - break; - case VKI_PTRACE_SETFPREGS: - PRE_MEM_READ( "ptrace(setfpregs)", ARG4, - sizeof (struct vki_user_i387_struct)); - break; - case VKI_PTRACE_SETFPXREGS: - PRE_MEM_READ( "ptrace(setfpxregs)", ARG4, - sizeof(struct vki_user_fxsr_struct) ); - break; - default: - break; - } -} - -POST(sys_ptrace) -{ - switch (ARG1) { - case VKI_PTRACE_PEEKTEXT: - case VKI_PTRACE_PEEKDATA: - case VKI_PTRACE_PEEKUSR: - POST_MEM_WRITE( ARG4, sizeof (long)); - break; - case VKI_PTRACE_GETREGS: - POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct)); - break; - case VKI_PTRACE_GETFPREGS: - POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct)); - break; - case VKI_PTRACE_GETFPXREGS: - POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) ); - break; - default: - break; - } -} +//zz PRE(sys_set_thread_area, Special) +//zz { +//zz PRINT("sys_set_thread_area ( %p )", ARG1); +//zz PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info) +//zz PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) ); +//zz +//zz /* "do" the syscall ourselves; the kernel never sees it */ +//zz SET_STATUS_( sys_set_thread_area( tid, (void *)ARG1 ) ); +//zz } +//zz +//zz PRE(sys_get_thread_area, Special) +//zz { +//zz PRINT("sys_get_thread_area ( %p )", ARG1); +//zz PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info) +//zz PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) ); +//zz +//zz /* "do" the syscall ourselves; the kernel never sees it */ +//zz SET_STATUS_( sys_get_thread_area( tid, (void *)ARG1 ) ); +//zz +//zz if (!VG_(is_kerror)(RES)) { +//zz POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) ); +//zz } +//zz } +//zz +//zz // Parts of this are x86-specific, but the *PEEK* cases are generic. +//zz // XXX: Why is the memory pointed to by ARG3 never checked? +//zz PRE(sys_ptrace, 0) +//zz { +//zz PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4); +//zz PRE_REG_READ4(int, "ptrace", +//zz long, request, long, pid, long, addr, long, data); +//zz switch (ARG1) { +//zz case VKI_PTRACE_PEEKTEXT: +//zz case VKI_PTRACE_PEEKDATA: +//zz case VKI_PTRACE_PEEKUSR: +//zz PRE_MEM_WRITE( "ptrace(peek)", ARG4, +//zz sizeof (long)); +//zz break; +//zz case VKI_PTRACE_GETREGS: +//zz PRE_MEM_WRITE( "ptrace(getregs)", ARG4, +//zz sizeof (struct vki_user_regs_struct)); +//zz break; +//zz case VKI_PTRACE_GETFPREGS: +//zz PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4, +//zz sizeof (struct vki_user_i387_struct)); +//zz break; +//zz case VKI_PTRACE_GETFPXREGS: +//zz PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4, +//zz sizeof(struct vki_user_fxsr_struct) ); +//zz break; +//zz case VKI_PTRACE_SETREGS: +//zz PRE_MEM_READ( "ptrace(setregs)", ARG4, +//zz sizeof (struct vki_user_regs_struct)); +//zz break; +//zz case VKI_PTRACE_SETFPREGS: +//zz PRE_MEM_READ( "ptrace(setfpregs)", ARG4, +//zz sizeof (struct vki_user_i387_struct)); +//zz break; +//zz case VKI_PTRACE_SETFPXREGS: +//zz PRE_MEM_READ( "ptrace(setfpxregs)", ARG4, +//zz sizeof(struct vki_user_fxsr_struct) ); +//zz break; +//zz default: +//zz break; +//zz } +//zz } +//zz +//zz POST(sys_ptrace) +//zz { +//zz switch (ARG1) { +//zz case VKI_PTRACE_PEEKTEXT: +//zz case VKI_PTRACE_PEEKDATA: +//zz case VKI_PTRACE_PEEKUSR: +//zz POST_MEM_WRITE( ARG4, sizeof (long)); +//zz break; +//zz case VKI_PTRACE_GETREGS: +//zz POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct)); +//zz break; +//zz case VKI_PTRACE_GETFPREGS: +//zz POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct)); +//zz break; +//zz case VKI_PTRACE_GETFPXREGS: +//zz POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) ); +//zz break; +//zz default: +//zz break; +//zz } +//zz } // XXX: this duplicates a function in coregrind/vg_syscalls.c, yuk static Addr deref_Addr ( ThreadId tid, Addr a, Char* s ) @@ -1268,7 +1290,7 @@ static Addr deref_Addr ( ThreadId tid, Addr a, Char* s ) } // XXX: should use the constants here (eg. SHMAT), not the numbers directly! -PRE(sys_ipc, 0) +PRE(sys_ipc) { PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); // XXX: this is simplistic -- some args are not used in all circumstances. @@ -1279,7 +1301,7 @@ PRE(sys_ipc, 0) switch (ARG1 /* call */) { case VKI_SEMOP: VG_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 ); - /* tst->sys_flags |= MayBlock; */ + *flags |= SfMayBlock; break; case VKI_SEMGET: break; @@ -1291,13 +1313,12 @@ PRE(sys_ipc, 0) } case VKI_SEMTIMEDOP: VG_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 ); - /* tst->sys_flags |= MayBlock; */ + *flags |= SfMayBlock; break; case VKI_MSGSND: VG_(generic_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 ); - /* if ((ARG4 & VKI_IPC_NOWAIT) == 0) - tst->sys_flags |= MayBlock; - */ + if ((ARG4 & VKI_IPC_NOWAIT) == 0) + *flags |= SfMayBlock; break; case VKI_MSGRCV: { @@ -1313,9 +1334,8 @@ PRE(sys_ipc, 0) VG_(generic_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 ); - /* if ((ARG4 & VKI_IPC_NOWAIT) == 0) - tst->sys_flags |= MayBlock; - */ + if ((ARG4 & VKI_IPC_NOWAIT) == 0) + *flags |= SfMayBlock; break; } case VKI_MSGGET: @@ -1324,14 +1344,19 @@ PRE(sys_ipc, 0) VG_(generic_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 ); break; case VKI_SHMAT: + { + UWord w; PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) ); - ARG5 = VG_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 ); - if (ARG5 == 0) - SET_RESULT( -VKI_EINVAL ); + w = VG_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 ); + if (w == 0) + SET_STATUS_Failure( VKI_EINVAL ); + else + ARG5 = w; break; + } case VKI_SHMDT: if (!VG_(generic_PRE_sys_shmdt)(tid, ARG5)) - SET_RESULT( -VKI_EINVAL ); + SET_STATUS_Failure( VKI_EINVAL ); break; case VKI_SHMGET: break; @@ -1347,6 +1372,7 @@ PRE(sys_ipc, 0) POST(sys_ipc) { + vg_assert(SUCCESS); switch (ARG1 /* call */) { case VKI_SEMOP: case VKI_SEMGET: @@ -1412,90 +1438,471 @@ POST(sys_ipc) } } +PRE(old_mmap) +{ + /* struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; + }; */ + UWord a1, a2, a3, a4, a5, a6; + + UWord* arg_block = (UWord*)ARG1; + PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, ARG1); + PRE_MEM_READ( "old_mmap(args)", (Addr)arg_block, 6*sizeof(UWord) ); + + a1 = arg_block[0]; + a2 = arg_block[1]; + a3 = arg_block[2]; + a4 = arg_block[3]; + a5 = arg_block[4]; + a6 = arg_block[5]; + + PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )", + a1, (ULong)a2, a3, a4, a5, a6 ); + + if (a2 == 0) { + /* SuSV3 says: If len is zero, mmap() shall fail and no mapping + shall be established. */ + SET_STATUS_Failure( VKI_EINVAL ); + return; + } + + if (/*(a4 & VKI_MAP_FIXED) &&*/ (0 != (a1 & (VKI_PAGE_SIZE-1)))) { + /* zap any misaligned addresses. */ + SET_STATUS_Failure( VKI_EINVAL ); + return; + } -// jrs 20050207: this is from the svn branch -//PRE(sys_sigaction, Special) -//{ -// PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3); -// PRE_REG_READ3(int, "sigaction", -// int, signum, const struct old_sigaction *, act, -// struct old_sigaction *, oldact) -// if (ARG2 != 0) -// PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction)); -// if (ARG3 != 0) -// PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction)); -// -// VG_(do_sys_sigaction)(tid); -//} + if (a4 & VKI_MAP_FIXED) { + if (!VG_(valid_client_addr)(a1, a2, tid, "old_mmap")) { + PRINT("old_mmap failing: %p-%p\n", a1, a1+a2); + SET_STATUS_Failure( VKI_ENOMEM ); + } + } else { + Addr a = VG_(find_map_space)(a1, a2, True); + if (0) VG_(printf)("find_map_space(%p, %d) -> %p\n",a1,a2,a); + if (a == 0 && a1 != 0) { + a1 = VG_(find_map_space)(0, a2, True); + } + else + a1 = a; + if (a1 == 0) + SET_STATUS_Failure( VKI_ENOMEM ); + else + a4 |= VKI_MAP_FIXED; + } -/* Convert from non-RT to RT sigset_t's */ -static void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set) + if (! FAILURE) { + SysRes res = VG_(mmap_native)((void*)a1, a2, a3, a4, a5, a6); + SET_STATUS_from_SysRes(res); + if (!res.isError) { + vg_assert(VG_(valid_client_addr)(res.val, a2, tid, "old_mmap")); + VG_(mmap_segment)( (Addr)res.val, a2, a3, a4, a5, a6 ); + } + } + + if (0) + VG_(printf)("old_mmap( %p, fixed %d ) -> %s(%p)\n", + arg_block[0], + arg_block[3]&VKI_MAP_FIXED, + FAILURE ? "Fail" : "Success", RES_unchecked); + + /* Stay sane */ + if (SUCCESS && (arg_block[3] & VKI_MAP_FIXED)) + vg_assert(RES == arg_block[0]); +} + +// XXX: lstat64/fstat64/stat64 are generic, but not necessarily +// applicable to every architecture -- I think only to 32-bit archs. +// We're going to need something like linux/core_os32.h for such +// things, eventually, I think. --njn +PRE(sys_lstat64) { - VG_(sigemptyset)(set); - set->sig[0] = *oldset; + PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2); + PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf); + PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 ); + PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) ); } -PRE(sys_sigaction, Special) + +POST(sys_lstat64) { - struct vki_sigaction new, old; - struct vki_sigaction *newp, *oldp; + vg_assert(SUCCESS); + if (RES == 0) { + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); + } +} - PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3); - PRE_REG_READ3(int, "sigaction", - int, signum, const struct old_sigaction *, act, - struct old_sigaction *, oldact); +PRE(sys_stat64) +{ + PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2); + PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf); + PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 ); + PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) ); +} - newp = oldp = NULL; +POST(sys_stat64) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); +} - if (ARG2 != 0) - PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction)); +PRE(sys_fstat64) +{ + PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2); + PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf); + PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) ); +} - if (ARG3 != 0) { - PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction)); - oldp = &old; - } +POST(sys_fstat64) +{ + POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); +} + +PRE(sys_socketcall) +{ +# define ARG2_0 (((UWord*)ARG2)[0]) +# define ARG2_1 (((UWord*)ARG2)[1]) +# define ARG2_2 (((UWord*)ARG2)[2]) +# define ARG2_3 (((UWord*)ARG2)[3]) +# define ARG2_4 (((UWord*)ARG2)[4]) +# define ARG2_5 (((UWord*)ARG2)[5]) + + *flags |= SfMayBlock; + PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2); + PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args); + + switch (ARG1 /* request */) { + + case VKI_SYS_SOCKETPAIR: + /* int socketpair(int d, int type, int protocol, int sv[2]); */ + PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) ); + VG_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 ); + break; - //jrs 20050207: what?! how can this make any sense? - //if (VG_(is_kerror)(SYSRES)) - // return; + case VKI_SYS_SOCKET: + /* int socket(int domain, int type, int protocol); */ + PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) ); + break; - if (ARG2 != 0) { - struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2; + case VKI_SYS_BIND: + /* int bind(int sockfd, struct sockaddr *my_addr, + int addrlen); */ + PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) ); + VG_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_LISTEN: + /* int listen(int s, int backlog); */ + PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) ); + break; - new.ksa_handler = oldnew->ksa_handler; - new.sa_flags = oldnew->sa_flags; - new.sa_restorer = oldnew->sa_restorer; - convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask); - newp = &new; + case VKI_SYS_ACCEPT: { + /* int accept(int s, struct sockaddr *addr, int *addrlen); */ + PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) ); + VG_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; } - SET_RESULT( VG_(do_sys_sigaction)(ARG1, newp, oldp) ); + case VKI_SYS_SENDTO: + /* int sendto(int s, const void *msg, int len, + unsigned int flags, + const struct sockaddr *to, int tolen); */ + PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) ); + VG_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4, ARG2_5 ); + break; + + case VKI_SYS_SEND: + /* int send(int s, const void *msg, size_t len, int flags); */ + PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) ); + VG_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; - if (ARG3 != 0 && RES == 0) { - struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3; + case VKI_SYS_RECVFROM: + /* int recvfrom(int s, void *buf, int len, unsigned int flags, + struct sockaddr *from, int *fromlen); */ + PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) ); + VG_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4, ARG2_5 ); + break; + + case VKI_SYS_RECV: + /* int recv(int s, void *buf, int len, unsigned int flags); */ + /* man 2 recv says: + The recv call is normally used only on a connected socket + (see connect(2)) and is identical to recvfrom with a NULL + from parameter. + */ + PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) ); + VG_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; - oldold->ksa_handler = oldp->ksa_handler; - oldold->sa_flags = oldp->sa_flags; - oldold->sa_restorer = oldp->sa_restorer; - oldold->sa_mask = oldp->sa_mask.sig[0]; + case VKI_SYS_CONNECT: + /* int connect(int sockfd, + struct sockaddr *serv_addr, int addrlen ); */ + PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) ); + VG_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_SETSOCKOPT: + /* int setsockopt(int s, int level, int optname, + const void *optval, int optlen); */ + PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) ); + VG_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4 ); + break; + + case VKI_SYS_GETSOCKOPT: + /* int getsockopt(int s, int level, int optname, + void *optval, socklen_t *optlen); */ + PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) ); + VG_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4 ); + break; + + case VKI_SYS_GETSOCKNAME: + /* int getsockname(int s, struct sockaddr* name, int* namelen) */ + PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) ); + VG_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_GETPEERNAME: + /* int getpeername(int s, struct sockaddr* name, int* namelen) */ + PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) ); + VG_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_SHUTDOWN: + /* int shutdown(int s, int how); */ + PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) ); + break; + + case VKI_SYS_SENDMSG: { + /* int sendmsg(int s, const struct msghdr *msg, int flags); */ + + /* this causes warnings, and I don't get why. glibc bug? + * (after all it's glibc providing the arguments array) + PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) ); + */ + VG_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 ); + break; + } + + case VKI_SYS_RECVMSG: { + /* int recvmsg(int s, struct msghdr *msg, int flags); */ + + /* this causes warnings, and I don't get why. glibc bug? + * (after all it's glibc providing the arguments array) + PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) ); + */ + VG_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 ); + break; + } + + default: + VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1); + SET_STATUS_Failure( VKI_EINVAL ); + break; } +# undef ARG2_0 +# undef ARG2_1 +# undef ARG2_2 +# undef ARG2_3 +# undef ARG2_4 +# undef ARG2_5 } -POST(sys_sigaction) +POST(sys_socketcall) { - if (RES == 0 && ARG3 != 0) - POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction)); +# define ARG2_0 (((UWord*)ARG2)[0]) +# define ARG2_1 (((UWord*)ARG2)[1]) +# define ARG2_2 (((UWord*)ARG2)[2]) +# define ARG2_3 (((UWord*)ARG2)[3]) +# define ARG2_4 (((UWord*)ARG2)[4]) +# define ARG2_5 (((UWord*)ARG2)[5]) + + SysRes r; + vg_assert(SUCCESS); + switch (ARG1 /* request */) { + + case VKI_SYS_SOCKETPAIR: + r = VG_(generic_POST_sys_socketpair)( + tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, ARG2_2, ARG2_3 + ); + SET_STATUS_from_SysRes(r); + break; + + case VKI_SYS_SOCKET: + r = VG_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) ); + SET_STATUS_from_SysRes(r); + break; + + case VKI_SYS_BIND: + /* int bind(int sockfd, struct sockaddr *my_addr, + int addrlen); */ + break; + + case VKI_SYS_LISTEN: + /* int listen(int s, int backlog); */ + break; + + case VKI_SYS_ACCEPT: + /* int accept(int s, struct sockaddr *addr, int *addrlen); */ + r = VG_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, ARG2_2 ); + SET_STATUS_from_SysRes(r); + break; + + case VKI_SYS_SENDTO: + break; + + case VKI_SYS_SEND: + break; + + case VKI_SYS_RECVFROM: + VG_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, ARG2_2, + ARG2_3, ARG2_4, ARG2_5 ); + break; + + case VKI_SYS_RECV: + VG_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_CONNECT: + break; + + case VKI_SYS_SETSOCKOPT: + break; + + case VKI_SYS_GETSOCKOPT: + VG_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, + ARG2_2, ARG2_3, ARG2_4 ); + break; + + case VKI_SYS_GETSOCKNAME: + VG_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_GETPEERNAME: + VG_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES), + ARG2_0, ARG2_1, ARG2_2 ); + break; + + case VKI_SYS_SHUTDOWN: + break; + + case VKI_SYS_SENDMSG: + break; + + case VKI_SYS_RECVMSG: + VG_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 ); + break; + + default: + VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1); + VG_(core_panic)("... bye!\n"); + break; /*NOTREACHED*/ + } +# undef ARG2_0 +# undef ARG2_1 +# undef ARG2_2 +# undef ARG2_3 +# undef ARG2_4 +# undef ARG2_5 } -#undef PRE -#undef POST +//zz // jrs 20050207: this is from the svn branch +//zz //PRE(sys_sigaction, Special) +//zz //{ +//zz // PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3); +//zz // PRE_REG_READ3(int, "sigaction", +//zz // int, signum, const struct old_sigaction *, act, +//zz // struct old_sigaction *, oldact) +//zz // if (ARG2 != 0) +//zz // PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction)); +//zz // if (ARG3 != 0) +//zz // PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction)); +//zz // +//zz // VG_(do_sys_sigaction)(tid); +//zz //} +//zz +//zz /* Convert from non-RT to RT sigset_t's */ +//zz static void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set) +//zz { +//zz VG_(sigemptyset)(set); +//zz set->sig[0] = *oldset; +//zz } +//zz PRE(sys_sigaction, Special) +//zz { +//zz struct vki_sigaction new, old; +//zz struct vki_sigaction *newp, *oldp; +//zz +//zz PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3); +//zz PRE_REG_READ3(int, "sigaction", +//zz int, signum, const struct old_sigaction *, act, +//zz struct old_sigaction *, oldact); +//zz +//zz newp = oldp = NULL; +//zz +//zz if (ARG2 != 0) +//zz PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction)); +//zz +//zz if (ARG3 != 0) { +//zz PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction)); +//zz oldp = &old; +//zz } +//zz +//zz //jrs 20050207: what?! how can this make any sense? +//zz //if (VG_(is_kerror)(SYSRES)) +//zz // return; +//zz +//zz if (ARG2 != 0) { +//zz struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2; +//zz +//zz new.ksa_handler = oldnew->ksa_handler; +//zz new.sa_flags = oldnew->sa_flags; +//zz new.sa_restorer = oldnew->sa_restorer; +//zz convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask); +//zz newp = &new; +//zz } +//zz +//zz SET_STATUS_( VG_(do_sys_sigaction)(ARG1, newp, oldp) ); +//zz +//zz if (ARG3 != 0 && RES == 0) { +//zz struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3; +//zz +//zz oldold->ksa_handler = oldp->ksa_handler; +//zz oldold->sa_flags = oldp->sa_flags; +//zz oldold->sa_restorer = oldp->sa_restorer; +//zz oldold->sa_mask = oldp->sa_mask.sig[0]; +//zz } +//zz } +//zz +//zz POST(sys_sigaction) +//zz { +//zz if (RES == 0 && ARG3 != 0) +//zz POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction)); +//zz } +//zz +//zz #undef PRE +//zz #undef POST /* --------------------------------------------------------------------- The x86/Linux syscall table ------------------------------------------------------------------ */ -// Macros for adding x86/Linux-specific wrappers to the syscall table. -#define PLAX_(const, name) SYS_WRAPPER_ENTRY_X_(x86_linux, const, name) -#define PLAXY(const, name) SYS_WRAPPER_ENTRY_XY(x86_linux, const, name) +/* Add a Linux-specific, arch-independent wrapper to a syscall + table. */ +#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name) +#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name) + // This table maps from __NR_xxx syscall numbers (from // linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo() @@ -1505,8 +1912,8 @@ POST(sys_sigaction) // arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/? // (unknown). -const struct SyscallTableEntry VGA_(syscall_table)[] = { - // (restart_syscall) // 0 +const SyscallTableEntry VGP_(syscall_table)[] = { +//zz // (restart_syscall) // 0 GENX_(__NR_exit, sys_exit), // 1 GENX_(__NR_fork, sys_fork), // 2 GENXY(__NR_read, sys_read), // 3 @@ -1525,9 +1932,9 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = { GENX_(__NR_mknod, sys_mknod), // 14 GENX_(__NR_chmod, sys_chmod), // 15 - // (__NR_lchown, sys_lchown16), // 16 ## P +//zz // (__NR_lchown, sys_lchown16), // 16 ## P GENX_(__NR_break, sys_ni_syscall), // 17 - // (__NR_oldstat, sys_stat), // 18 (obsolete) +//zz // (__NR_oldstat, sys_stat), // 18 (obsolete) GENX_(__NR_lseek, sys_lseek), // 19 GENX_(__NR_getpid, sys_getpid), // 20 @@ -1535,324 +1942,324 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = { LINX_(__NR_umount, sys_oldumount), // 22 GENX_(__NR_setuid, sys_setuid16), // 23 ## P GENX_(__NR_getuid, sys_getuid16), // 24 ## P - - // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN) - PLAXY(__NR_ptrace, sys_ptrace), // 26 +//zz +//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN) +//zz PLAXY(__NR_ptrace, sys_ptrace), // 26 GENX_(__NR_alarm, sys_alarm), // 27 - // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete +//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete GENX_(__NR_pause, sys_pause), // 29 - - GENX_(__NR_utime, sys_utime), // 30 +//zz +//zz GENX_(__NR_utime, sys_utime), // 30 GENX_(__NR_stty, sys_ni_syscall), // 31 GENX_(__NR_gtty, sys_ni_syscall), // 32 GENX_(__NR_access, sys_access), // 33 - GENX_(__NR_nice, sys_nice), // 34 - +//zz GENX_(__NR_nice, sys_nice), // 34 +//zz GENX_(__NR_ftime, sys_ni_syscall), // 35 - GENX_(__NR_sync, sys_sync), // 36 +//zz GENX_(__NR_sync, sys_sync), // 36 GENX_(__NR_kill, sys_kill), // 37 GENX_(__NR_rename, sys_rename), // 38 GENX_(__NR_mkdir, sys_mkdir), // 39 - - GENX_(__NR_rmdir, sys_rmdir), // 40 +//zz +//zz GENX_(__NR_rmdir, sys_rmdir), // 40 GENXY(__NR_dup, sys_dup), // 41 GENXY(__NR_pipe, sys_pipe), // 42 - GENXY(__NR_times, sys_times), // 43 +//zz GENXY(__NR_times, sys_times), // 43 GENX_(__NR_prof, sys_ni_syscall), // 44 - +//zz GENX_(__NR_brk, sys_brk), // 45 - GENX_(__NR_setgid, sys_setgid16), // 46 - GENX_(__NR_getgid, sys_getgid16), // 47 - // (__NR_signal, sys_signal), // 48 */* (ANSI C) +//zz GENX_(__NR_setgid, sys_setgid16), // 46 +//zz GENX_(__NR_getgid, sys_getgid16), // 47 +//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C) GENX_(__NR_geteuid, sys_geteuid16), // 49 - - GENX_(__NR_getegid, sys_getegid16), // 50 - GENX_(__NR_acct, sys_acct), // 51 - LINX_(__NR_umount2, sys_umount), // 52 +//zz +//zz GENX_(__NR_getegid, sys_getegid16), // 50 +//zz GENX_(__NR_acct, sys_acct), // 51 +//zz LINX_(__NR_umount2, sys_umount), // 52 GENX_(__NR_lock, sys_ni_syscall), // 53 GENXY(__NR_ioctl, sys_ioctl), // 54 - - GENXY(__NR_fcntl, sys_fcntl), // 55 +//zz +//zz GENXY(__NR_fcntl, sys_fcntl), // 55 GENX_(__NR_mpx, sys_ni_syscall), // 56 - GENX_(__NR_setpgid, sys_setpgid), // 57 +//zz GENX_(__NR_setpgid, sys_setpgid), // 57 GENX_(__NR_ulimit, sys_ni_syscall), // 58 - // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete - - GENX_(__NR_umask, sys_umask), // 60 - GENX_(__NR_chroot, sys_chroot), // 61 - // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated +//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete +//zz +//zz GENX_(__NR_umask, sys_umask), // 60 +//zz GENX_(__NR_chroot, sys_chroot), // 61 +//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated GENXY(__NR_dup2, sys_dup2), // 63 GENX_(__NR_getppid, sys_getppid), // 64 - - GENX_(__NR_getpgrp, sys_getpgrp), // 65 - GENX_(__NR_setsid, sys_setsid), // 66 - PLAXY(__NR_sigaction, sys_sigaction), // 67 - // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C) - // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C) - - GENX_(__NR_setreuid, sys_setreuid16), // 70 - GENX_(__NR_setregid, sys_setregid16), // 71 - GENX_(__NR_sigsuspend, sys_sigsuspend), // 72 - GENXY(__NR_sigpending, sys_sigpending), // 73 - // (__NR_sethostname, sys_sethostname), // 74 */* - +//zz +//zz GENX_(__NR_getpgrp, sys_getpgrp), // 65 +//zz GENX_(__NR_setsid, sys_setsid), // 66 +//zz PLAXY(__NR_sigaction, sys_sigaction), // 67 +//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C) +//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C) +//zz +//zz GENX_(__NR_setreuid, sys_setreuid16), // 70 +//zz GENX_(__NR_setregid, sys_setregid16), // 71 +//zz GENX_(__NR_sigsuspend, sys_sigsuspend), // 72 +//zz GENXY(__NR_sigpending, sys_sigpending), // 73 +//zz // (__NR_sethostname, sys_sethostname), // 74 */* +//zz GENX_(__NR_setrlimit, sys_setrlimit), // 75 - GENXY(__NR_getrlimit, sys_old_getrlimit), // 76 - GENXY(__NR_getrusage, sys_getrusage), // 77 +//zz GENXY(__NR_getrlimit, sys_old_getrlimit), // 76 +//zz GENXY(__NR_getrusage, sys_getrusage), // 77 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78 - GENX_(__NR_settimeofday, sys_settimeofday), // 79 - - GENXY(__NR_getgroups, sys_getgroups16), // 80 - GENX_(__NR_setgroups, sys_setgroups16), // 81 - PLAX_(__NR_select, old_select), // 82 - GENX_(__NR_symlink, sys_symlink), // 83 - // (__NR_oldlstat, sys_lstat), // 84 -- obsolete - +//zz GENX_(__NR_settimeofday, sys_settimeofday), // 79 +//zz +//zz GENXY(__NR_getgroups, sys_getgroups16), // 80 +//zz GENX_(__NR_setgroups, sys_setgroups16), // 81 +//zz PLAX_(__NR_select, old_select), // 82 +//zz GENX_(__NR_symlink, sys_symlink), // 83 +//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete +//zz GENX_(__NR_readlink, sys_readlink), // 85 - // (__NR_uselib, sys_uselib), // 86 */Linux - // (__NR_swapon, sys_swapon), // 87 */Linux - // (__NR_reboot, sys_reboot), // 88 */Linux - // (__NR_readdir, old_readdir), // 89 -- superseded - - GENX_(__NR_mmap, old_mmap), // 90 +//zz // (__NR_uselib, sys_uselib), // 86 */Linux +//zz // (__NR_swapon, sys_swapon), // 87 */Linux +//zz // (__NR_reboot, sys_reboot), // 88 */Linux +//zz // (__NR_readdir, old_readdir), // 89 -- superseded +//zz + PLAX_(__NR_mmap, old_mmap), // 90 GENXY(__NR_munmap, sys_munmap), // 91 - GENX_(__NR_truncate, sys_truncate), // 92 - GENX_(__NR_ftruncate, sys_ftruncate), // 93 - GENX_(__NR_fchmod, sys_fchmod), // 94 - - GENX_(__NR_fchown, sys_fchown16), // 95 - GENX_(__NR_getpriority, sys_getpriority), // 96 - GENX_(__NR_setpriority, sys_setpriority), // 97 +//zz GENX_(__NR_truncate, sys_truncate), // 92 +//zz GENX_(__NR_ftruncate, sys_ftruncate), // 93 +//zz GENX_(__NR_fchmod, sys_fchmod), // 94 +//zz +//zz GENX_(__NR_fchown, sys_fchown16), // 95 +//zz GENX_(__NR_getpriority, sys_getpriority), // 96 +//zz GENX_(__NR_setpriority, sys_setpriority), // 97 GENX_(__NR_profil, sys_ni_syscall), // 98 - GENXY(__NR_statfs, sys_statfs), // 99 - - GENXY(__NR_fstatfs, sys_fstatfs), // 100 - LINX_(__NR_ioperm, sys_ioperm), // 101 - GENXY(__NR_socketcall, sys_socketcall), // 102 - LINXY(__NR_syslog, sys_syslog), // 103 - GENXY(__NR_setitimer, sys_setitimer), // 104 - - GENXY(__NR_getitimer, sys_getitimer), // 105 - GENXY(__NR_stat, sys_newstat), // 106 - GENXY(__NR_lstat, sys_newlstat), // 107 - GENXY(__NR_fstat, sys_newfstat), // 108 - // (__NR_olduname, sys_uname), // 109 -- obsolete - - GENX_(__NR_iopl, sys_iopl), // 110 - LINX_(__NR_vhangup, sys_vhangup), // 111 +//zz GENXY(__NR_statfs, sys_statfs), // 99 +//zz +//zz GENXY(__NR_fstatfs, sys_fstatfs), // 100 +//zz LINX_(__NR_ioperm, sys_ioperm), // 101 + PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only +//zz LINXY(__NR_syslog, sys_syslog), // 103 +//zz GENXY(__NR_setitimer, sys_setitimer), // 104 +//zz +//zz GENXY(__NR_getitimer, sys_getitimer), // 105 +//zz GENXY(__NR_stat, sys_newstat), // 106 +//zz GENXY(__NR_lstat, sys_newlstat), // 107 +//zz GENXY(__NR_fstat, sys_newfstat), // 108 +//zz // (__NR_olduname, sys_uname), // 109 -- obsolete +//zz +//zz GENX_(__NR_iopl, sys_iopl), // 110 +//zz LINX_(__NR_vhangup, sys_vhangup), // 111 GENX_(__NR_idle, sys_ni_syscall), // 112 - // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only +//zz // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only GENXY(__NR_wait4, sys_wait4), // 114 - - // (__NR_swapoff, sys_swapoff), // 115 */Linux - LINXY(__NR_sysinfo, sys_sysinfo), // 116 +//zz +//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux +//zz LINXY(__NR_sysinfo, sys_sysinfo), // 116 PLAXY(__NR_ipc, sys_ipc), // 117 - GENX_(__NR_fsync, sys_fsync), // 118 +//zz GENX_(__NR_fsync, sys_fsync), // 118 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux PLAX_(__NR_clone, sys_clone), // 120 - // (__NR_setdomainname, sys_setdomainname), // 121 */*(?) +//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?) GENXY(__NR_uname, sys_newuname), // 122 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123 - LINXY(__NR_adjtimex, sys_adjtimex), // 124 - +//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124 +//zz GENXY(__NR_mprotect, sys_mprotect), // 125 GENXY(__NR_sigprocmask, sys_sigprocmask), // 126 - // Nb: create_module() was removed 2.4-->2.6 +//zz // Nb: create_module() was removed 2.4-->2.6 GENX_(__NR_create_module, sys_ni_syscall), // 127 - GENX_(__NR_init_module, sys_init_module), // 128 - // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)? - - // Nb: get_kernel_syms() was removed 2.4-->2.6 +//zz GENX_(__NR_init_module, sys_init_module), // 128 +//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)? +//zz +//zz // Nb: get_kernel_syms() was removed 2.4-->2.6 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130 - GENX_(__NR_quotactl, sys_quotactl), // 131 - GENX_(__NR_getpgid, sys_getpgid), // 132 - GENX_(__NR_fchdir, sys_fchdir), // 133 - // (__NR_bdflush, sys_bdflush), // 134 */Linux - - // (__NR_sysfs, sys_sysfs), // 135 SVr4 - LINX_(__NR_personality, sys_personality), // 136 +//zz GENX_(__NR_quotactl, sys_quotactl), // 131 +//zz GENX_(__NR_getpgid, sys_getpgid), // 132 +//zz GENX_(__NR_fchdir, sys_fchdir), // 133 +//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux +//zz +//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4 +//zz LINX_(__NR_personality, sys_personality), // 136 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137 - LINX_(__NR_setfsuid, sys_setfsuid16), // 138 - LINX_(__NR_setfsgid, sys_setfsgid16), // 139 - +//zz LINX_(__NR_setfsuid, sys_setfsuid16), // 138 +//zz LINX_(__NR_setfsgid, sys_setfsgid16), // 139 +//zz LINXY(__NR__llseek, sys_llseek), // 140 - GENXY(__NR_getdents, sys_getdents), // 141 +//zz GENXY(__NR_getdents, sys_getdents), // 141 GENX_(__NR__newselect, sys_select), // 142 - GENX_(__NR_flock, sys_flock), // 143 - GENX_(__NR_msync, sys_msync), // 144 - +//zz GENX_(__NR_flock, sys_flock), // 143 +//zz GENX_(__NR_msync, sys_msync), // 144 +//zz GENXY(__NR_readv, sys_readv), // 145 GENX_(__NR_writev, sys_writev), // 146 - GENX_(__NR_getsid, sys_getsid), // 147 - GENX_(__NR_fdatasync, sys_fdatasync), // 148 +//zz GENX_(__NR_getsid, sys_getsid), // 147 +//zz GENX_(__NR_fdatasync, sys_fdatasync), // 148 LINXY(__NR__sysctl, sys_sysctl), // 149 - - GENX_(__NR_mlock, sys_mlock), // 150 - GENX_(__NR_munlock, sys_munlock), // 151 - GENX_(__NR_mlockall, sys_mlockall), // 152 - GENX_(__NR_munlockall, sys_munlockall), // 153 - GENXY(__NR_sched_setparam, sys_sched_setparam), // 154 - - GENXY(__NR_sched_getparam, sys_sched_getparam), // 155 - GENX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156 - GENX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157 - GENX_(__NR_sched_yield, sys_sched_yield), // 158 - GENX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159 - - GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160 - // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */* +//zz +//zz GENX_(__NR_mlock, sys_mlock), // 150 +//zz GENX_(__NR_munlock, sys_munlock), // 151 +//zz GENX_(__NR_mlockall, sys_mlockall), // 152 +//zz GENX_(__NR_munlockall, sys_munlockall), // 153 +//zz GENXY(__NR_sched_setparam, sys_sched_setparam), // 154 +//zz +//zz GENXY(__NR_sched_getparam, sys_sched_getparam), // 155 +//zz GENX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156 +//zz GENX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157 +//zz GENX_(__NR_sched_yield, sys_sched_yield), // 158 +//zz GENX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159 +//zz +//zz GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160 +//zz // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */* GENXY(__NR_nanosleep, sys_nanosleep), // 162 GENX_(__NR_mremap, sys_mremap), // 163 - LINX_(__NR_setresuid, sys_setresuid16), // 164 - - LINXY(__NR_getresuid, sys_getresuid16), // 165 - // (__NR_vm86, sys_vm86), // 166 x86/Linux-only +//zz LINX_(__NR_setresuid, sys_setresuid16), // 164 +//zz +//zz LINXY(__NR_getresuid, sys_getresuid16), // 165 +//zz // (__NR_vm86, sys_vm86), // 166 x86/Linux-only GENX_(__NR_query_module, sys_ni_syscall), // 167 GENXY(__NR_poll, sys_poll), // 168 - // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux - - LINX_(__NR_setresgid, sys_setresgid16), // 170 - LINXY(__NR_getresgid, sys_getresgid16), // 171 - LINX_(__NR_prctl, sys_prctl), // 172 +//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux +//zz +//zz LINX_(__NR_setresgid, sys_setresgid16), // 170 +//zz LINXY(__NR_getresgid, sys_getresgid16), // 171 +//zz LINX_(__NR_prctl, sys_prctl), // 172 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only? GENXY(__NR_rt_sigaction, sys_rt_sigaction), // 174 GENXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175 - GENXY(__NR_rt_sigpending, sys_rt_sigpending), // 176 +//zz GENXY(__NR_rt_sigpending, sys_rt_sigpending), // 176 GENXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177 - GENXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178 +//zz GENXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178 GENX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179 - - GENXY(__NR_pread64, sys_pread64), // 180 - GENX_(__NR_pwrite64, sys_pwrite64), // 181 - GENX_(__NR_chown, sys_chown16), // 182 +//zz +//zz GENXY(__NR_pread64, sys_pread64), // 180 +//zz GENX_(__NR_pwrite64, sys_pwrite64), // 181 +//zz GENX_(__NR_chown, sys_chown16), // 182 GENXY(__NR_getcwd, sys_getcwd), // 183 - GENXY(__NR_capget, sys_capget), // 184 - - GENX_(__NR_capset, sys_capset), // 185 +//zz GENXY(__NR_capget, sys_capget), // 184 +//zz +//zz GENX_(__NR_capset, sys_capset), // 185 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186 - LINXY(__NR_sendfile, sys_sendfile), // 187 - GENXY(__NR_getpmsg, sys_getpmsg), // 188 - GENX_(__NR_putpmsg, sys_putpmsg), // 189 +//zz LINXY(__NR_sendfile, sys_sendfile), // 187 +//zz GENXY(__NR_getpmsg, sys_getpmsg), // 188 +//zz GENX_(__NR_putpmsg, sys_putpmsg), // 189 // Nb: we treat vfork as fork GENX_(__NR_vfork, sys_fork), // 190 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191 GENXY(__NR_mmap2, sys_mmap2), // 192 - GENX_(__NR_truncate64, sys_truncate64), // 193 - GENX_(__NR_ftruncate64, sys_ftruncate64), // 194 - - GENXY(__NR_stat64, sys_stat64), // 195 - GENXY(__NR_lstat64, sys_lstat64), // 196 - GENXY(__NR_fstat64, sys_fstat64), // 197 - GENX_(__NR_lchown32, sys_lchown), // 198 +//zz GENX_(__NR_truncate64, sys_truncate64), // 193 +//zz GENX_(__NR_ftruncate64, sys_ftruncate64), // 194 +//zz + PLAXY(__NR_stat64, sys_stat64), // 195 + PLAXY(__NR_lstat64, sys_lstat64), // 196 + PLAXY(__NR_fstat64, sys_fstat64), // 197 +//zz GENX_(__NR_lchown32, sys_lchown), // 198 GENX_(__NR_getuid32, sys_getuid), // 199 - - GENX_(__NR_getgid32, sys_getgid), // 200 +//zz +//zz GENX_(__NR_getgid32, sys_getgid), // 200 GENX_(__NR_geteuid32, sys_geteuid), // 201 - GENX_(__NR_getegid32, sys_getegid), // 202 - GENX_(__NR_setreuid32, sys_setreuid), // 203 - GENX_(__NR_setregid32, sys_setregid), // 204 - - GENXY(__NR_getgroups32, sys_getgroups), // 205 - GENX_(__NR_setgroups32, sys_setgroups), // 206 - GENX_(__NR_fchown32, sys_fchown), // 207 - LINX_(__NR_setresuid32, sys_setresuid), // 208 - LINXY(__NR_getresuid32, sys_getresuid), // 209 - - LINX_(__NR_setresgid32, sys_setresgid), // 210 - LINXY(__NR_getresgid32, sys_getresgid), // 211 - GENX_(__NR_chown32, sys_chown), // 212 - GENX_(__NR_setuid32, sys_setuid), // 213 - GENX_(__NR_setgid32, sys_setgid), // 214 - - LINX_(__NR_setfsuid32, sys_setfsuid), // 215 - LINX_(__NR_setfsgid32, sys_setfsgid), // 216 - // (__NR_pivot_root, sys_pivot_root), // 217 */Linux - GENXY(__NR_mincore, sys_mincore), // 218 +//zz GENX_(__NR_getegid32, sys_getegid), // 202 +//zz GENX_(__NR_setreuid32, sys_setreuid), // 203 +//zz GENX_(__NR_setregid32, sys_setregid), // 204 +//zz +//zz GENXY(__NR_getgroups32, sys_getgroups), // 205 +//zz GENX_(__NR_setgroups32, sys_setgroups), // 206 +//zz GENX_(__NR_fchown32, sys_fchown), // 207 +//zz LINX_(__NR_setresuid32, sys_setresuid), // 208 +//zz LINXY(__NR_getresuid32, sys_getresuid), // 209 +//zz +//zz LINX_(__NR_setresgid32, sys_setresgid), // 210 +//zz LINXY(__NR_getresgid32, sys_getresgid), // 211 +//zz GENX_(__NR_chown32, sys_chown), // 212 +//zz GENX_(__NR_setuid32, sys_setuid), // 213 +//zz GENX_(__NR_setgid32, sys_setgid), // 214 +//zz +//zz LINX_(__NR_setfsuid32, sys_setfsuid), // 215 +//zz LINX_(__NR_setfsgid32, sys_setfsgid), // 216 +//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux +//zz GENXY(__NR_mincore, sys_mincore), // 218 GENX_(__NR_madvise, sys_madvise), // 219 GENXY(__NR_getdents64, sys_getdents64), // 220 GENXY(__NR_fcntl64, sys_fcntl64), // 221 GENX_(222, sys_ni_syscall), // 222 GENX_(223, sys_ni_syscall), // 223 - LINX_(__NR_gettid, sys_gettid), // 224 - - // (__NR_readahead, sys_readahead), // 225 */(Linux?) - GENX_(__NR_setxattr, sys_setxattr), // 226 - GENX_(__NR_lsetxattr, sys_lsetxattr), // 227 - GENX_(__NR_fsetxattr, sys_fsetxattr), // 228 +//zz LINX_(__NR_gettid, sys_gettid), // 224 +//zz +//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?) +//zz GENX_(__NR_setxattr, sys_setxattr), // 226 +//zz GENX_(__NR_lsetxattr, sys_lsetxattr), // 227 +//zz GENX_(__NR_fsetxattr, sys_fsetxattr), // 228 GENXY(__NR_getxattr, sys_getxattr), // 229 - - GENXY(__NR_lgetxattr, sys_lgetxattr), // 230 - GENXY(__NR_fgetxattr, sys_fgetxattr), // 231 - GENXY(__NR_listxattr, sys_listxattr), // 232 - GENXY(__NR_llistxattr, sys_llistxattr), // 233 - GENXY(__NR_flistxattr, sys_flistxattr), // 234 - - GENX_(__NR_removexattr, sys_removexattr), // 235 - GENX_(__NR_lremovexattr, sys_lremovexattr), // 236 - GENX_(__NR_fremovexattr, sys_fremovexattr), // 237 - LINX_(__NR_tkill, sys_tkill), // 238 */Linux - LINXY(__NR_sendfile64, sys_sendfile64), // 239 - - LINXY(__NR_futex, sys_futex), // 240 - GENX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241 - GENXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242 - PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243 - PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244 - - LINX_(__NR_io_setup, sys_io_setup), // 245 - LINX_(__NR_io_destroy, sys_io_destroy), // 246 - LINXY(__NR_io_getevents, sys_io_getevents), // 247 - LINX_(__NR_io_submit, sys_io_submit), // 248 - LINXY(__NR_io_cancel, sys_io_cancel), // 249 - - LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?) +//zz +//zz GENXY(__NR_lgetxattr, sys_lgetxattr), // 230 +//zz GENXY(__NR_fgetxattr, sys_fgetxattr), // 231 +//zz GENXY(__NR_listxattr, sys_listxattr), // 232 +//zz GENXY(__NR_llistxattr, sys_llistxattr), // 233 +//zz GENXY(__NR_flistxattr, sys_flistxattr), // 234 +//zz +//zz GENX_(__NR_removexattr, sys_removexattr), // 235 +//zz GENX_(__NR_lremovexattr, sys_lremovexattr), // 236 +//zz GENX_(__NR_fremovexattr, sys_fremovexattr), // 237 +//zz LINX_(__NR_tkill, sys_tkill), // 238 */Linux +//zz LINXY(__NR_sendfile64, sys_sendfile64), // 239 +//zz +//zz LINXY(__NR_futex, sys_futex), // 240 +//zz GENX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241 +//zz GENXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242 +//zz PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243 +//zz PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244 +//zz +//zz LINX_(__NR_io_setup, sys_io_setup), // 245 +//zz LINX_(__NR_io_destroy, sys_io_destroy), // 246 +//zz LINXY(__NR_io_getevents, sys_io_getevents), // 247 +//zz LINX_(__NR_io_submit, sys_io_submit), // 248 +//zz LINXY(__NR_io_cancel, sys_io_cancel), // 249 +//zz +//zz LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?) GENX_(251, sys_ni_syscall), // 251 LINX_(__NR_exit_group, sys_exit_group), // 252 - GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253 - LINXY(__NR_epoll_create, sys_epoll_create), // 254 - - LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255 - LINXY(__NR_epoll_wait, sys_epoll_wait), // 256 - // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux - GENX_(__NR_set_tid_address, sys_set_tid_address), // 258 - GENXY(__NR_timer_create, sys_timer_create), // 259 - - GENXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1) - GENXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2) - GENX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3) - GENX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4) - GENX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5) - +//zz GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253 +//zz LINXY(__NR_epoll_create, sys_epoll_create), // 254 +//zz +//zz LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255 +//zz LINXY(__NR_epoll_wait, sys_epoll_wait), // 256 +//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux +//zz GENX_(__NR_set_tid_address, sys_set_tid_address), // 258 +//zz GENXY(__NR_timer_create, sys_timer_create), // 259 +//zz +//zz GENXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1) +//zz GENXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2) +//zz GENX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3) +//zz GENX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4) +//zz GENX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5) +//zz GENXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6) - GENXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7) - // (__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */* - GENXY(__NR_statfs64, sys_statfs64), // 268 - GENXY(__NR_fstatfs64, sys_fstatfs64), // 269 - - LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux - GENX_(__NR_utimes, sys_utimes), // 271 - LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?) +//zz GENXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7) +//zz // (__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */* +//zz GENXY(__NR_statfs64, sys_statfs64), // 268 +//zz GENXY(__NR_fstatfs64, sys_fstatfs64), // 269 +//zz +//zz LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux +//zz GENX_(__NR_utimes, sys_utimes), // 271 +//zz LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?) GENX_(__NR_vserver, sys_ni_syscall), // 273 - // (__NR_mbind, sys_mbind), // 274 ?/? - - // (__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/? - // (__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/? - GENXY(__NR_mq_open, sys_mq_open), // 277 - GENX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1) - GENX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2) - - GENXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3) - GENX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4) - GENXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5) +//zz // (__NR_mbind, sys_mbind), // 274 ?/? +//zz +//zz // (__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/? +//zz // (__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/? +//zz GENXY(__NR_mq_open, sys_mq_open), // 277 +//zz GENX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1) +//zz GENX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2) +//zz +//zz GENXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3) +//zz GENX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4) +//zz GENXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5) GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283 }; -const UInt VGA_(syscall_table_size) = - sizeof(VGA_(syscall_table)) / sizeof(VGA_(syscall_table)[0]); +const UInt VGP_(syscall_table_size) = + sizeof(VGP_(syscall_table)) / sizeof(VGP_(syscall_table)[0]); /*--------------------------------------------------------------------*/ /*--- end ---*/ diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index dc06c8518..962b45ccd 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -216,7 +216,7 @@ void VG_(needs_client_requests)( void VG_(needs_syscall_wrapper)( void(*pre) (ThreadId, UInt), - void(*post)(ThreadId, UInt, Int res) + void(*post)(ThreadId, UInt, SysRes res) ) { VG_(needs).syscall_wrapper = True; diff --git a/coregrind/pub_core_libcbase.h b/coregrind/pub_core_libcbase.h index 5c20e8b79..e65c6653c 100644 --- a/coregrind/pub_core_libcbase.h +++ b/coregrind/pub_core_libcbase.h @@ -39,6 +39,74 @@ #include "pub_tool_libcbase.h" +/* --------------------------------------------------------------------- + Fundamental functions for doing syscalls on this platform. + ------------------------------------------------------------------ */ + +/* Do a syscall on this platform, with 6 args, and return the result + in canonical format in a SysRes value. */ + +extern SysRes VG_(do_syscall) ( UWord sysno, + UWord, UWord, UWord, + UWord, UWord, UWord ); + +/* Macros make life easier. */ + +#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0) +#define vgPlain_do_syscall1(s,a) VG_(do_syscall)((s),(a),0,0,0,0,0) +#define vgPlain_do_syscall2(s,a,b) VG_(do_syscall)((s),(a),(b),0,0,0,0) +#define vgPlain_do_syscall3(s,a,b,c) VG_(do_syscall)((s),(a),(b),(c),0,0,0) +#define vgPlain_do_syscall4(s,a,b,c,d) VG_(do_syscall)((s),(a),(b),\ + (c),(d),0,0) +#define vgPlain_do_syscall5(s,a,b,c,d,e) VG_(do_syscall)((s),(a),(b),\ + (c),(d),(e),0) +#define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),\ + (c),(d),(e),(f)) + + +/* Build SysRes values -- occasionally useful. */ + +static inline SysRes VG_(mk_SysRes_Error) ( UWord err ) { + SysRes r = { err, True }; + return r; +} + +static inline SysRes VG_(mk_SysRes_Success) ( UWord err ) { + SysRes r = { err, False }; + return r; +} + + +/* This is absolutely the wrong place for these, but I can't figure + out anywhere else for them to go. */ + +/* Make a SysRes value from an %eax syscall return value on + x86-linux. + + From: + http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ + linux/i386/sysdep.h? + rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc + + Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the 'lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in %eax + is a real error number. Linus said he will make sure the no + syscall returns a value in -1 .. -4095 as a valid result so we can + safely test with -4095. +*/ +static inline SysRes VG_(mk_SysRes_x86_linux) ( Int eax ) { + SysRes res; + res.isError = eax >= -4095 && eax <= -1; + res.val = res.isError ? -eax : eax; + return res; +} + + #endif // __PUB_CORE_LIBCBASE_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_scheduler.h b/coregrind/pub_core_scheduler.h index db49232a7..ddc785ff2 100644 --- a/coregrind/pub_core_scheduler.h +++ b/coregrind/pub_core_scheduler.h @@ -138,10 +138,6 @@ typedef struct { be rare. */ struct SigQueue *sig_queue; - /* Syscall the Thread is currently running; -1 if none. Should only - be set while Thread is in VgTs_WaitSys. */ - Int syscallno; - /* Client stacks. When a thread slot is freed, we don't deallocate its stack; we just leave it lying around for the next use of the slot. If the next use of the slot requires a larger stack, diff --git a/coregrind/pub_core_signals.h b/coregrind/pub_core_signals.h index ac640541c..444694d7f 100644 --- a/coregrind/pub_core_signals.h +++ b/coregrind/pub_core_signals.h @@ -40,18 +40,19 @@ extern Int VG_(max_signal); extern void VG_(sigstartup_actions) ( void ); -/* Poll a thread's set of pending signals, and update the Thread's context to deliver one */ +/* Poll a thread's set of pending signals, and update the Thread's + context to deliver one (viz, create signal frames if needed) */ extern void VG_(poll_signals) ( ThreadId ); /* Fake system calls for signal handling. */ -extern Int VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, - vki_stack_t* oss ); -extern Int VG_(do_sys_sigaction) ( Int signo, - const struct vki_sigaction *new_act, - struct vki_sigaction *old_act ); -extern Int VG_(do_sys_sigprocmask) ( ThreadId tid, Int how, - vki_sigset_t* set, - vki_sigset_t* oldset ); +extern SysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, + vki_stack_t* oss ); +extern SysRes VG_(do_sys_sigaction) ( Int signo, + const struct vki_sigaction *new_act, + struct vki_sigaction *old_act ); +extern SysRes VG_(do_sys_sigprocmask) ( ThreadId tid, Int how, + vki_sigset_t* set, + vki_sigset_t* oldset ); extern void VG_(clear_out_queued_signals) ( ThreadId tid, /* OUT */ vki_sigset_t* saved_mask ); diff --git a/coregrind/pub_core_syscalls.h b/coregrind/pub_core_syscalls.h index fed4146d5..e54dc2ca9 100644 --- a/coregrind/pub_core_syscalls.h +++ b/coregrind/pub_core_syscalls.h @@ -43,23 +43,21 @@ extern void VG_(client_syscall) ( ThreadId tid ); extern void VG_(post_syscall) ( ThreadId tid ); -// Fix up the thread's state because a syscall may have been -// interrupted with a signal. Returns True if the syscall completed -// (either interrupted or finished normally), or False if it was -// restarted (or the signal didn't actually interrupt a syscall). -extern void VGP_(interrupted_syscall)(ThreadId tid, - Word eip, UWord sysnum, UWord sysret, - Bool restart); +/* Clear this module's private state for thread 'tid' */ +extern void VG_(clear_syscallInfo) ( Int tid ); + +// Fix up a thread's state when syscall is interrupted by a signal. +extern void VG_(fixup_guest_state_after_syscall_interrupted)( + ThreadId tid, + Addr ip, + UWord sysnum, + SysRes sysret, + Bool restart + ); // Release resources held by this thread extern void VGP_(cleanup_thread) ( ThreadArchState* ); -extern Bool VG_(is_kerror) ( Word res ); - -/* Internal atfork handlers */ -typedef void (*vg_atfork_t)(ThreadId); -extern void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child); - /* fd leakage calls. */ extern void VG_(init_preopened_fds) ( void ); extern void VG_(show_open_fds) ( void ); diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index fbd97709a..b779327e6 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -135,7 +135,7 @@ typedef struct { // VG_(needs).syscall_wrapper void (*tool_pre_syscall) (ThreadId, UInt); - void (*tool_post_syscall)(ThreadId, UInt, Int); + void (*tool_post_syscall)(ThreadId, UInt, SysRes); // VG_(needs).sanity_checks Bool (*tool_cheap_sanity_check)(void); diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index 03effb9c5..6c0fe19a8 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -36,6 +36,7 @@ #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" #include "pub_core_libcprint.h" +#include "pub_core_libcfile.h" #include "pub_core_main.h" #include "pub_core_options.h" #include "pub_core_stacktrace.h" @@ -159,77 +160,76 @@ void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) */ Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset) { - Int res = VG_(do_syscall4)(__NR_rt_sigprocmask, - how, (UWord)set, (UWord)oldset, - _VKI_NSIG_WORDS * sizeof(UWord)); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask, + how, (UWord)set, (UWord)oldset, + _VKI_NSIG_WORDS * sizeof(UWord)); + return res.isError ? -1 : 0; } Int VG_(sigaction) ( Int signum, const struct vki_sigaction* act, struct vki_sigaction* oldact) { - Int res = VG_(do_syscall4)(__NR_rt_sigaction, - signum, (UWord)act, (UWord)oldact, - _VKI_NSIG_WORDS * sizeof(UWord)); - /* VG_(printf)("res = %d\n",res); */ - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall4)(__NR_rt_sigaction, + signum, (UWord)act, (UWord)oldact, + _VKI_NSIG_WORDS * sizeof(UWord)); + return res.isError ? -1 : 0; } Int VG_(sigaltstack)( const vki_stack_t* ss, vki_stack_t* oss ) { - Int res = VG_(do_syscall2)(__NR_sigaltstack, (UWord)ss, (UWord)oss); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall2)(__NR_sigaltstack, (UWord)ss, (UWord)oss); + return res.isError ? -1 : 0; } Int VG_(sigtimedwait)( const vki_sigset_t *set, vki_siginfo_t *info, const struct vki_timespec *timeout ) { - Int res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, - (UWord)timeout, sizeof(*set)); - - return res; + SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, + (UWord)timeout, sizeof(*set)); + return res.isError ? -1 : res.val; } Int VG_(signal)(Int signum, void (*sighandler)(Int)) { - Int res; + SysRes res; + Int n; struct vki_sigaction sa; sa.ksa_handler = sighandler; sa.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART; sa.sa_restorer = NULL; - res = VG_(sigemptyset)( &sa.sa_mask ); - vg_assert(res == 0); + n = VG_(sigemptyset)( &sa.sa_mask ); + vg_assert(n == 0); res = VG_(do_syscall4)(__NR_rt_sigaction, signum, (UWord)&sa, (UWord)NULL, - _VKI_NSIG_WORDS * sizeof(UWord)); - return VG_(is_kerror)(res) ? -1 : 0; + _VKI_NSIG_WORDS * sizeof(UWord)); + return res.isError ? -1 : 0; } Int VG_(kill)( Int pid, Int signo ) { - Int res = VG_(do_syscall2)(__NR_kill, pid, signo); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo); + return res.isError ? -1 : 0; } Int VG_(tkill)( ThreadId tid, Int signo ) { - Int ret = -VKI_ENOSYS; + SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); #if 0 /* This isn't right because the client may create a process structure with multiple thread groups */ - ret = VG_(do_syscall)(__NR_tgkill, VG_(getpid)(), tid, signo); + res = VG_(do_syscall)(__NR_tgkill, VG_(getpid)(), tid, signo); #endif - ret = VG_(do_syscall2)(__NR_tkill, tid, signo); + res = VG_(do_syscall2)(__NR_tkill, tid, signo); - if (ret == -VKI_ENOSYS) - ret = VG_(do_syscall2)(__NR_kill, tid, signo); + if (res.isError && res.val == VKI_ENOSYS) + res = VG_(do_syscall2)(__NR_kill, tid, signo); - return VG_(is_kerror)(ret) ? -1 : 0; + return res.isError ? -1 : 0; } Int VG_(sigpending) ( vki_sigset_t* set ) @@ -241,27 +241,23 @@ Int VG_(sigpending) ( vki_sigset_t* set ) #ifdef __amd64__ I_die_here; #else - Int res = VG_(do_syscall1)(__NR_sigpending, (UWord)set); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall1)(__NR_sigpending, (UWord)set); + return res.isError ? -1 : 0; #endif } Int VG_(waitpid)(Int pid, Int *status, Int options) { - Int ret = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0); - - return VG_(is_kerror)(ret) ? -1 : ret; + SysRes res = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0); + return res.isError ? -1 : res.val; } Int VG_(gettid)(void) { - Int ret; - - ret = VG_(do_syscall0)(__NR_gettid); + SysRes res = VG_(do_syscall0)(__NR_gettid); - if (ret == -VKI_ENOSYS) { - Char pid[16]; - + if (res.isError && res.val == VKI_ENOSYS) { + Char pid[16]; /* * The gettid system call does not exist. The obvious assumption * to make at this point would be that we are running on an older @@ -275,15 +271,16 @@ Int VG_(gettid)(void) * So instead of calling getpid here we use readlink to see where * the /proc/self link is pointing... */ - if ((ret = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self", - (UWord)pid, sizeof(pid))) >= 0) - { - pid[ret] = '\0'; - ret = VG_(atoll)(pid); + + res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self", + (UWord)pid, sizeof(pid)); + if (!res.isError && res.val > 0) { + pid[res.val] = '\0'; + res.val = VG_(atoll)(pid); } } - return ret; + return res.val; } @@ -292,11 +289,11 @@ Int VG_(gettid)(void) mmap/munmap, exit, fcntl ------------------------------------------------------------------ */ -void* VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags, - UInt fd, OffT offset) +SysRes VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags, + UInt fd, OffT offset) { - UWord ret; -#if defined(VGP_x86_linux) + SysRes res; +# if defined(VGP_x86_linux) { UWord args[6]; args[0] = (UWord)start; @@ -305,22 +302,22 @@ void* VG_(mmap_native)(void *start, SizeT length, UInt prot, UInt flags, args[3] = flags; args[4] = fd; args[5] = offset; - ret = VG_(do_syscall1)(__NR_mmap, (UWord)args ); + res = VG_(do_syscall1)(__NR_mmap, (UWord)args ); } -#elif defined(VGP_amd64_linux) - ret = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, +# elif defined(VGP_amd64_linux) + res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length, prot, flags, fd, offset); -#else -# error Unknown platform -#endif - return VG_(is_kerror)(ret) ? (void*)-1 : (void*)ret; +# else +# error Unknown platform +# endif + return res; } /* Returns -1 on failure. */ void* VG_(mmap)( void* start, SizeT length, UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset) { - Addr res; + SysRes res; if (!(flags & VKI_MAP_FIXED)) { start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT)); @@ -330,16 +327,18 @@ void* VG_(mmap)( void* start, SizeT length, if (start == 0) return (void *)-1; - res = (Addr)VG_(mmap_native)(start, length, prot, - flags & ~(VKI_MAP_NOSYMS | VKI_MAP_CLIENT), - fd, offset); + res = VG_(mmap_native)(start, length, prot, + flags & ~(VKI_MAP_NOSYMS | VKI_MAP_CLIENT), + fd, offset); // Check it ended up in the right place. - if (res != (Addr)-1) { + if (!res.isError) { if (flags & VKI_MAP_CLIENT) { - vg_assert(VG_(client_base) <= res && res+length <= VG_(client_end)); + vg_assert(VG_(client_base) <= res.val + && res.val+length <= VG_(client_end)); } else { - vg_assert(VG_(valgrind_base) <= res && res+length-1 <= VG_(valgrind_last)); + vg_assert(VG_(valgrind_base) <= res.val + && res.val+length-1 <= VG_(valgrind_last)); } sf_flags |= SF_MMAP; @@ -349,16 +348,16 @@ void* VG_(mmap)( void* start, SizeT length, if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND; if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS; - VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL); + VG_(map_fd_segment)(res.val, length, prot, sf_flags, fd, offset, NULL); } - return (void*)res; + return res.isError ? (void*)-1 : (void*)res.val; } static Int munmap_native(void *start, SizeT length) { - Int res = VG_(do_syscall2)(__NR_munmap, (UWord)start, length ); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall2)(__NR_munmap, (UWord)start, length ); + return res.isError ? -1 : 0; } /* Returns -1 on failure. */ @@ -372,8 +371,8 @@ Int VG_(munmap)( void* start, SizeT length ) Int VG_(mprotect_native)( void *start, SizeT length, UInt prot ) { - Int res = VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot ); - return VG_(is_kerror)(res) ? -1 : 0; + SysRes res = VG_(do_syscall3)(__NR_mprotect, (UWord)start, length, prot ); + return res.isError ? -1 : 0; } Int VG_(mprotect)( void *start, SizeT length, UInt prot ) @@ -398,15 +397,15 @@ void VG_(exit)( Int status ) /* Returns -1 on error. */ Int VG_(fcntl) ( Int fd, Int cmd, Int arg ) { - Int res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); - return VG_(is_kerror)(res) ? -1 : res; + SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); + return res.isError ? -1 : res.val; } Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout) { - Int res = VG_(do_syscall3)(__NR_poll, (UWord)ufds, nfds, timeout); - - return res; + SysRes res = VG_(do_syscall3)(__NR_poll, (UWord)ufds, nfds, timeout); + /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ + return res.val; } @@ -543,56 +542,49 @@ Char *VG_(getenv)(Char *varname) /* Support for getrlimit. */ Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim) { - Int res = -VKI_ENOSYS; + SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); /* res = getrlimit( resource, rlim ); */ # ifdef __NR_ugetrlimit res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim); # endif - if (res == -VKI_ENOSYS) + if (res.isError && res.val == VKI_ENOSYS) res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim); - if (VG_(is_kerror)(res)) res = -1; - return res; + return res.isError ? -1 : res.val; } /* Support for setrlimit. */ Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim) { - Int res; + SysRes res; /* res = setrlimit( resource, rlim ); */ res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim); - if (VG_(is_kerror)(res)) res = -1; - return res; + return res.isError ? -1 : res.val; } - /* You'd be amazed how many places need to know the current pid. */ Int VG_(getpid) ( void ) { - Int res; - /* res = getpid(); */ - res = VG_(do_syscall0)(__NR_getpid); - return res; + /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ + return VG_(do_syscall0)(__NR_getpid) . val; } Int VG_(getpgrp) ( void ) { - Int res; - /* res = getpgid(); */ - res = VG_(do_syscall0)(__NR_getpgrp); - return res; + /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ + return VG_(do_syscall0)(__NR_getpgrp) . val; } Int VG_(getppid) ( void ) { - Int res; - res = VG_(do_syscall0)(__NR_getppid); - return res; + /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ + return VG_(do_syscall0)(__NR_getppid) . val; } Int VG_(setpgid) ( Int pid, Int pgrp ) { - return VG_(do_syscall2)(__NR_setpgid, pid, pgrp); + /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ + return VG_(do_syscall2)(__NR_setpgid, pid, pgrp) . val; } /* Walk through a colon-separated environment variable, and remove the @@ -695,12 +687,14 @@ void VG_(env_remove_valgrind_env_stuff)(Char** envp) child! */ Int VG_(system) ( Char* cmd ) { - Int pid, res; + Int pid; + SysRes res; if (cmd == NULL) return 1; - pid = VG_(do_syscall0)(__NR_fork); - if (VG_(is_kerror)(pid)) + res = VG_(do_syscall0)(__NR_fork); + if (res.isError) return -1; + pid = res.val; if (pid == 0) { /* child */ static Char** envp = NULL; @@ -724,12 +718,8 @@ Int VG_(system) ( Char* cmd ) VG_(exit)(1); } else { /* parent */ - res = VG_(waitpid)(pid, NULL, 0); - if (VG_(is_kerror)(res)) { - return -1; - } else { - return 0; - } + Int zzz = VG_(waitpid)(pid, NULL, 0); + return zzz == -1 ? -1 : 0; } } @@ -742,8 +732,8 @@ UInt VG_(read_millisecond_timer) ( void ) { static ULong base = 0; struct vki_timeval tv_now; - ULong now; - Int res; + ULong now; + SysRes res; res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); @@ -758,7 +748,7 @@ UInt VG_(read_millisecond_timer) ( void ) void VG_(nanosleep)(struct vki_timespec *ts) { - VG_(do_syscall2)(__NR_nanosleep, (UWord)ts, (UWord)NULL); + (void)VG_(do_syscall2)(__NR_nanosleep, (UWord)ts, (UWord)NULL); } /* --------------------------------------------------------------------- @@ -795,6 +785,75 @@ void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who ) VG_(exit)(1); } +/* --------------------------------------------------------------------- + Misc stuff looking for a proper home + ------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + A simple atfork() facility for Valgrind's internal use + ------------------------------------------------------------------ */ + +struct atfork { + vg_atfork_t pre; + vg_atfork_t parent; + vg_atfork_t child; +}; + +#define VG_MAX_ATFORK 10 + +static struct atfork atforks[VG_MAX_ATFORK]; +static Int n_atfork; + +void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child) +{ + Int i; + + for(i = 0; i < n_atfork; i++) { + if (atforks[i].pre == pre && + atforks[i].parent == parent && + atforks[i].child == child) + return; + } + + if (n_atfork >= VG_MAX_ATFORK) + VG_(core_panic)("Too many VG_(atfork) handlers requested: " + "raise VG_MAX_ATFORK"); + + atforks[n_atfork].pre = pre; + atforks[n_atfork].parent = parent; + atforks[n_atfork].child = child; + + n_atfork++; +} + +void VG_(do_atfork_pre)(ThreadId tid) +{ + Int i; + + for(i = 0; i < n_atfork; i++) + if (atforks[i].pre != NULL) + (*atforks[i].pre)(tid); +} + +void VG_(do_atfork_parent)(ThreadId tid) +{ + Int i; + + for(i = 0; i < n_atfork; i++) + if (atforks[i].parent != NULL) + (*atforks[i].parent)(tid); +} + +void VG_(do_atfork_child)(ThreadId tid) +{ + Int i; + + for(i = 0; i < n_atfork; i++) + if (atforks[i].child != NULL) + (*atforks[i].child)(tid); +} + + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/include/basic_types.h b/include/basic_types.h index 10c0f3599..6e02b3d03 100644 --- a/include/basic_types.h +++ b/include/basic_types.h @@ -71,6 +71,17 @@ typedef UInt ThreadId; +/* An abstraction of syscall return values. + When .isError == False, val holds the return value. + When .isError == True, val holds the error code. +*/ +typedef + struct { + UWord val; + Bool isError; + } + SysRes; + /* --------------------------------------------------------------------- Where to send bug reports to. ------------------------------------------------------------------ */ diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index 2c4590626..5514080b0 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -235,7 +235,7 @@ extern void VG_(needs_client_requests) ( // corresponding post_ function had better free() it! extern void VG_(needs_syscall_wrapper) ( void (* pre_syscall)(ThreadId tid, UInt syscallno), - void (*post_syscall)(ThreadId tid, UInt syscallno, Int res) + void (*post_syscall)(ThreadId tid, UInt syscallno, SysRes res) ); /* Are tool-state sanity checks performed? */ |