From: Nicholas Nethercote Date: Mon, 18 May 2009 02:12:08 +0000 (+0000) Subject: Merged non-Darwin-specific parts of r9397,r9423,r9490, 9461, 9462 from the X-Git-Tag: svn/VALGRIND_3_5_0~702 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=131ab0074458f065ce6dbe67e4fa4b700c828828;p=thirdparty%2Fvalgrind.git Merged non-Darwin-specific parts of r9397,r9423,r9490, 9461, 9462 from the DARWIN branch. A big ugly DARWIN/trunk sync commit, mostly to do with changing the representation of SysRes and vki_sigset_t. Functionality of the trunk shouldn't be changed by it. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9876 --- diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index 6d7ce8767d..279356bd5e 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -1262,7 +1262,7 @@ static void fprint_CC_table_and_calc_totals(void) sres = VG_(open)(cachegrind_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY, VKI_S_IRUSR|VKI_S_IWUSR); - if (sres.isError) { + if (sr_isError(sres)) { // If the file can't be opened for whatever reason (conflict // between multiple cachegrinded processes?), give up now. VG_UMSG("error: can't open cache simulation output file '%s'", @@ -1271,7 +1271,7 @@ static void fprint_CC_table_and_calc_totals(void) VG_(free)(cachegrind_out_file); return; } else { - fd = sres.res; + fd = sr_Res(sres); VG_(free)(cachegrind_out_file); } diff --git a/callgrind/command.c b/callgrind/command.c index 46c7f4419d..78f57d85a5 100644 --- a/callgrind/command.c +++ b/callgrind/command.c @@ -108,18 +108,18 @@ static void setup_control(void) /* create info file to indicate that we are running */ res = VG_(open)(info_file, VKI_O_WRONLY|VKI_O_TRUNC, 0); - if (res.isError) { + if (sr_isError(res)) { res = VG_(open)(info_file, VKI_O_CREAT|VKI_O_WRONLY, VKI_S_IRUSR|VKI_S_IWUSR); - if (res.isError) { + if (sr_isError(res)) { VG_(message)(Vg_DebugMsg, "warning: can't write info file '%s'", info_file); info_file = 0; fd = -1; } } - if (!res.isError) - fd = (Int) res.res; + if (!sr_isError(res)) + fd = (Int) sr_Res(res); if (fd>=0) { Char buf[512]; Int i; @@ -177,8 +177,8 @@ static Int createRes(Int fd) /* VG_(open) can return any negative number on error. Remap errors to -1, * to not confuse it with our special value -2 */ - if (res.isError) fd = -1; - else fd = (Int) res.res; + if (sr_isError(res)) fd = -1; + else fd = (Int) sr_Res(res); return fd; } @@ -380,8 +380,8 @@ void CLG_(check_command)() } res = VG_(open)(current_command_file, VKI_O_RDONLY,0); - if (!res.isError) { - fd = (Int) res.res; + if (!sr_isError(res)) { + fd = (Int) sr_Res(res); bytesRead = VG_(read)(fd,cmdBuffer,500); cmdBuffer[500] = 0; /* no command overrun please */ VG_(close)(fd); diff --git a/callgrind/dump.c b/callgrind/dump.c index 17414cae18..28bb8eb298 100644 --- a/callgrind/dump.c +++ b/callgrind/dump.c @@ -1303,20 +1303,20 @@ static int new_dumpfile(Char buf[BUF_LEN], int tid, Char* trigger) else { VG_(sprintf)(filename, "%s", out_file); res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_APPEND, 0); - if (!res.isError && out_counter>1) + if (!sr_isError(res) && out_counter>1) appending = True; } - if (res.isError) { + if (sr_isError(res)) { res = VG_(open)(filename, VKI_O_CREAT|VKI_O_WRONLY, VKI_S_IRUSR|VKI_S_IWUSR); - if (res.isError) { + if (sr_isError(res)) { /* If the file can not be opened for whatever reason (conflict between multiple supervised processes?), give up now. */ file_err(); } } - fd = (Int) res.res; + fd = (Int) sr_Res(res); CLG_DEBUG(2, " new_dumpfile '%s'\n", filename); @@ -1724,14 +1724,14 @@ void CLG_(init_dumps)() */ VG_(strcpy)(filename, out_file); res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_TRUNC, 0); - if (res.isError) { + if (sr_isError(res)) { res = VG_(open)(filename, VKI_O_CREAT|VKI_O_WRONLY, VKI_S_IRUSR|VKI_S_IWUSR); - if (res.isError) { + if (sr_isError(res)) { file_err(); } } - if (!res.isError) VG_(close)( (Int)res.res ); + if (!sr_isError(res)) VG_(close)( (Int)sr_Res(res) ); if (!dumps_initialized) init_cmdbuf(); diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c index dd1238e52c..f6f0488870 100644 --- a/coregrind/m_aspacemgr/aspacemgr-common.c +++ b/coregrind/m_aspacemgr/aspacemgr-common.c @@ -95,8 +95,8 @@ void ML_(am_assert_fail)( const HChar* expr, Int ML_(am_getpid)( void ) { SysRes sres = VG_(do_syscall0)(__NR_getpid); - aspacem_assert(!sres.isError); - return sres.res; + aspacem_assert(!sr_isError(sres)); + return sr_Res(sres); } @@ -238,7 +238,7 @@ SysRes ML_(am_open) ( const Char* pathname, Int flags, Int mode ) Int ML_(am_read) ( Int fd, void* buf, Int count) { SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } void ML_(am_close) ( Int fd ) @@ -250,13 +250,17 @@ Int ML_(am_readlink)(HChar* path, HChar* buf, UInt bufsiz) { SysRes res; res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg ) { +# if defined(VGO_linux) || defined(VGO_aix5) SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); - return res.isError ? -1 : res.res; +# else +# error "Unknown OS" +# endif + return sr_isError(res) ? -1 : sr_Res(res); } /* Get the dev, inode and mode info for a file descriptor, if @@ -273,7 +277,7 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, binaries on amd64 systems where fstat seems to be broken. */ struct vki_stat64 buf64; res = VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf64); - if (!res.isError) { + if (!sr_isError(res)) { *dev = (ULong)buf64.st_dev; *ino = (ULong)buf64.st_ino; *mode = (UInt) buf64.st_mode; @@ -281,7 +285,7 @@ Bool ML_(am_get_fd_d_i_m)( Int fd, } # endif res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf); - if (!res.isError) { + if (!sr_isError(res)) { *dev = (ULong)buf.st_dev; *ino = (ULong)buf.st_ino; *mode = (UInt) buf.st_mode; @@ -339,10 +343,10 @@ VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp ) + VG_STACK_ACTIVE_SZB + VG_STACK_GUARD_SZB; sres = VG_(am_mmap_anon_float_valgrind)( szB ); - if (sres.isError) + if (sr_isError(sres)) return NULL; - stack = (VgStack*)sres.res; + stack = (VgStack*)(AddrH)sr_Res(sres); aspacem_assert(VG_IS_PAGE_ALIGNED(szB)); aspacem_assert(VG_IS_PAGE_ALIGNED(stack)); @@ -352,7 +356,7 @@ VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp ) (Addr) &stack[0], VG_STACK_GUARD_SZB, VKI_PROT_NONE ); - if (sres.isError) goto protect_failed; + if (sr_isError(sres)) goto protect_failed; VG_(am_notify_mprotect)( (Addr) &stack->bytes[0], VG_STACK_GUARD_SZB, VKI_PROT_NONE @@ -362,7 +366,7 @@ VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp ) (Addr) &stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB], VG_STACK_GUARD_SZB, VKI_PROT_NONE ); - if (sres.isError) goto protect_failed; + if (sr_isError(sres)) goto protect_failed; VG_(am_notify_mprotect)( (Addr) &stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB], VG_STACK_GUARD_SZB, VKI_PROT_NONE @@ -377,7 +381,7 @@ VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp ) *initial_sp = (Addr)&stack->bytes[VG_STACK_GUARD_SZB + VG_STACK_ACTIVE_SZB]; *initial_sp -= 8; - *initial_sp &= ~((Addr)0xF); + *initial_sp &= ~((Addr)0x1F); /* 32-align it */ VG_(debugLog)( 1,"aspacem","allocated thread stack at 0x%llx size %d\n", (ULong)(Addr)stack, szB); diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index 57772dcb61..4f09b67922 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -2121,14 +2121,14 @@ SysRes VG_(am_mmap_file_fixed_client) VKI_MAP_FIXED|VKI_MAP_PRIVATE, fd, offset ); - if (sres.isError) + if (sr_isError(sres)) return sres; - if (sres.res != start) { + if (sr_Res(sres) != start) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to repair the damage, then return saying the mapping failed. */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, length ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); return VG_(mk_SysRes_Error)( VKI_EINVAL ); } @@ -2187,14 +2187,14 @@ SysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot ) VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, 0 ); - if (sres.isError) + if (sr_isError(sres)) return sres; - if (sres.res != start) { + if (sr_Res(sres) != start) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to repair the damage, then return saying the mapping failed. */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, length ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); return VG_(mk_SysRes_Error)( VKI_EINVAL ); } @@ -2244,14 +2244,14 @@ SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot ) VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, 0 ); - if (sres.isError) + if (sr_isError(sres)) return sres; - if (sres.res != advised) { + if (sr_Res(sres) != advised) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to repair the damage, then return saying the mapping failed. */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, length ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); return VG_(mk_SysRes_Error)( VKI_EINVAL ); } @@ -2318,21 +2318,21 @@ SysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, 0 ); - if (sres.isError) + if (sr_isError(sres)) return sres; - if (sres.res != advised) { + if (sr_Res(sres) != advised) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to repair the damage, then return saying the mapping failed. */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, length ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); return VG_(mk_SysRes_Error)( VKI_EINVAL ); } /* Ok, the mapping succeeded. Now notify the interval map. */ init_nsegment( &seg ); seg.kind = SkAnonV; - seg.start = advised; + seg.start = sr_Res(sres); seg.end = seg.start + VG_PGROUNDUP(length) - 1; seg.hasR = True; seg.hasW = True; @@ -2348,7 +2348,7 @@ SysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) void* VG_(am_shadow_alloc)(SizeT size) { SysRes sres = VG_(am_mmap_anon_float_valgrind)( size ); - return sres.isError ? NULL : (void*)sres.res; + return sr_isError(sres) ? NULL : (void*)sr_Res(sres); } /* Same comments apply as per VG_(am_sbrk_anon_float_client). On @@ -2396,21 +2396,21 @@ SysRes VG_(am_mmap_file_float_valgrind) ( SizeT length, UInt prot, VKI_MAP_FIXED|VKI_MAP_PRIVATE, fd, offset ); - if (sres.isError) + if (sr_isError(sres)) return sres; - if (sres.res != advised) { + if (sr_Res(sres) != advised) { /* I don't think this can happen. It means the kernel made a fixed map succeed but not at the requested location. Try to repair the damage, then return saying the mapping failed. */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, length ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); return VG_(mk_SysRes_Error)( VKI_EINVAL ); } /* Ok, the mapping succeeded. Now notify the interval map. */ init_nsegment( &seg ); seg.kind = SkFileV; - seg.start = sres.res; + seg.start = sr_Res(sres); seg.end = seg.start + VG_PGROUNDUP(length) - 1; seg.offset = offset; seg.hasR = toBool(prot & VKI_PROT_READ); @@ -2467,7 +2467,7 @@ SysRes am_munmap_both_wrk ( /*OUT*/Bool* need_discard, d = any_Ts_in_range( start, len ); sres = ML_(am_do_munmap_NO_NOTIFY)( start, len ); - if (sres.isError) + if (sr_isError(sres)) return sres; VG_(am_notify_munmap)( start, len ); @@ -2501,7 +2501,7 @@ SysRes VG_(am_munmap_valgrind)( Addr start, SizeT len ) start, len, False/*valgrind*/ ); /* If this assertion fails, it means we allowed translations to be made from a V-owned section. Which shouldn't happen. */ - if (!r.isError) + if (!sr_isError(r)) aspacem_assert(!need_discard); return r; } @@ -2693,11 +2693,11 @@ Bool VG_(am_extend_into_adjacent_reservation_client) ( NSegment* seg, VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, 0 ); - if (sres.isError) + if (sr_isError(sres)) return False; /* kernel bug if this happens? */ - if (sres.res != nsegments[segR].start) { + if (sr_Res(sres) != nsegments[segR].start) { /* kernel bug if this happens? */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, delta ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); return False; } @@ -2728,11 +2728,11 @@ Bool VG_(am_extend_into_adjacent_reservation_client) ( NSegment* seg, VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, 0 ); - if (sres.isError) + if (sr_isError(sres)) return False; /* kernel bug if this happens? */ - if (sres.res != nsegments[segA].start-delta) { + if (sr_Res(sres) != nsegments[segA].start-delta) { /* kernel bug if this happens? */ - (void)ML_(am_do_munmap_NO_NOTIFY)( sres.res, delta ); + (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); return False; } @@ -2787,12 +2787,12 @@ Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard, sres = ML_(am_do_extend_mapping_NO_NOTIFY)( seg->start, seg_old_len, seg_old_len + delta ); - if (sres.isError) { + if (sr_isError(sres)) { AM_SANITY_CHECK; return False; } else { /* the area must not have moved */ - aspacem_assert(sres.res == seg->start); + aspacem_assert(sr_Res(sres) == seg->start); } *need_discard = any_Ts_in_range( seg_copy.end+1, delta ); @@ -2852,11 +2852,11 @@ Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, sres = ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY) ( old_addr, old_len, new_addr, new_len ); - if (sres.isError) { + if (sr_isError(sres)) { AM_SANITY_CHECK; return False; } else { - aspacem_assert(sres.res == new_addr); + aspacem_assert(sr_Res(sres) == new_addr); } *need_discard = any_Ts_in_range( old_addr, old_len ) @@ -2983,18 +2983,18 @@ static void read_procselfmaps_into_buf ( void ) /* Read the initial memory mapping from the /proc filesystem. */ fd = ML_(am_open)( "/proc/self/maps", VKI_O_RDONLY, 0 ); - if (fd.isError) + if (sr_isError(fd)) ML_(am_barf)("can't open /proc/self/maps"); buf_n_tot = 0; do { - n_chunk = ML_(am_read)( fd.res, &procmap_buf[buf_n_tot], + n_chunk = ML_(am_read)( sr_Res(fd), &procmap_buf[buf_n_tot], M_PROCMAP_BUF - buf_n_tot ); if (n_chunk >= 0) buf_n_tot += n_chunk; } while ( n_chunk > 0 && buf_n_tot < M_PROCMAP_BUF ); - ML_(am_close)(fd.res); + ML_(am_close)(sr_Res(fd)); if (buf_n_tot >= M_PROCMAP_BUF-5) ML_(am_barf_toolow)("M_PROCMAP_BUF"); diff --git a/coregrind/m_commandline.c b/coregrind/m_commandline.c index 713fa4ce49..60c4d3dcc1 100644 --- a/coregrind/m_commandline.c +++ b/coregrind/m_commandline.c @@ -64,15 +64,15 @@ static HChar* read_dot_valgrindrc ( HChar* dir ) VG_(snprintf)(filename, VKI_PATH_MAX, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) ); fd = VG_(open)(filename, 0, VKI_S_IRUSR); - if ( !fd.isError ) { - Int res = VG_(fstat)( fd.res, &stat_buf ); + if ( !sr_isError(fd) ) { + Int res = VG_(fstat)( sr_Res(fd), &stat_buf ); // Ignore if not owned by current user or world writeable (CVE-2008-4865) if (!res && stat_buf.st_uid == VG_(geteuid)() && (!(stat_buf.st_mode & VKI_S_IWOTH))) { if ( stat_buf.st_size > 0 ) { f_clo = VG_(malloc)("commandline.rdv.1", stat_buf.st_size+1); vg_assert(f_clo); - n = VG_(read)(fd.res, f_clo, stat_buf.st_size); + n = VG_(read)(sr_Res(fd), f_clo, stat_buf.st_size); if (n == -1) n = 0; vg_assert(n >= 0 && n <= stat_buf.st_size+1); f_clo[n] = '\0'; @@ -83,7 +83,7 @@ static HChar* read_dot_valgrindrc ( HChar* dir ) "%s was not read as it is world writeable or not owned by the " "current user", filename); - VG_(close)(fd.res); + VG_(close)(sr_Res(fd)); } return f_clo; } diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c index 5ce4801473..00699c1714 100644 --- a/coregrind/m_coredump/coredump-elf.c +++ b/coregrind/m_coredump/coredump-elf.c @@ -300,12 +300,12 @@ void make_elf_coredump(ThreadId tid, const vki_siginfo_t *si, UInt max_size) sres = VG_(open)(buf, VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC, VKI_S_IRUSR|VKI_S_IWUSR); - if (!sres.isError) { - core_fd = sres.res; + if (!sr_isError(sres)) { + core_fd = sr_Res(sres); break; } - if (sres.isError && sres.err != VKI_EEXIST) + if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST) return; /* can't create file */ } diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index b4e2e63756..1aa6125e26 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -645,11 +645,11 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) /* stat dereferences symlinks, so we don't expect it to succeed and yet produce something that is a symlink. */ - vg_assert(statres.isError || ! VKI_S_ISLNK(statbuf.st_mode)); + vg_assert(sr_isError(statres) || ! VKI_S_ISLNK(statbuf.st_mode)); /* Don't let the stat call fail silently. Filter out some known sources of noise before complaining, though. */ - if (statres.isError) { + if (sr_isError(statres)) { DebugInfo fake_di; Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL; if (!quiet && VG_(clo_verbosity) > 1) { @@ -726,9 +726,8 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) /* object file. Ignore the file if we do not have read permission. */ VG_(memset)(buf1k, 0, sizeof(buf1k)); fd = VG_(open)( filename, VKI_O_RDONLY, 0 ); - if (fd.isError) { - if (fd.err != VKI_EACCES) - { + if (sr_isError(fd)) { + if (sr_Err(fd) != VKI_EACCES) { DebugInfo fake_di; VG_(memset)(&fake_di, 0, sizeof(fake_di)); fake_di.filename = filename; @@ -736,8 +735,8 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) } return 0; } - nread = VG_(read)( fd.res, buf1k, sizeof(buf1k) ); - VG_(close)( fd.res ); + nread = VG_(read)( sr_Res(fd), buf1k, sizeof(buf1k) ); + VG_(close)( sr_Res(fd) ); if (nread == 0) return 0; @@ -948,7 +947,7 @@ void VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj, /* See if we can find it, and check it's in-dateness. */ sres = VG_(stat)(pdbname, &stat_buf); - if (sres.isError) { + if (sr_isError(sres)) { VG_(message)(Vg_UserMsg, "Warning: Missing or un-stat-able %s", pdbname); if (VG_(clo_verbosity) > 0) @@ -965,17 +964,17 @@ void VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj, } sres = VG_(open)(pdbname, VKI_O_RDONLY, 0); - if (sres.isError) { + if (sr_isError(sres)) { VG_(message)(Vg_UserMsg, "Warning: Can't open %s", pdbname); goto out; } /* Looks promising; go on to try and read stuff from it. */ - fd_pdbimage = sres.res; + fd_pdbimage = sr_Res(sres); n_pdbimage = stat_buf.st_size; sres = VG_(am_mmap_file_float_valgrind)( n_pdbimage, VKI_PROT_READ, fd_pdbimage, 0 ); - if (sres.isError) { + if (sr_isError(sres)) { VG_(close)(fd_pdbimage); goto out; } @@ -989,7 +988,7 @@ void VG_(di_notify_pdb_debuginfo)( Int fd_obj, Addr avma_obj, /* dump old info for this range, if any */ discard_syms_in_range( avma_obj, total_size ); - { void* pdbimage = (void*)sres.res; + { void* pdbimage = (void*)sr_Res(sres); DebugInfo* di = find_or_create_DebugInfo_for(exename, NULL/*membername*/ ); /* this di must be new, since we just nuked any old stuff in the range */ diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index e0eef8c9cf..6a0329de0f 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -919,11 +919,11 @@ Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size ) UInt calccrc; fd = VG_(open)(name, VKI_O_RDONLY, 0); - if (fd.isError) + if (sr_isError(fd)) return 0; - if (VG_(fstat)(fd.res, &stat_buf) != 0) { - VG_(close)(fd.res); + if (VG_(fstat)(sr_Res(fd), &stat_buf) != 0) { + VG_(close)(sr_Res(fd)); return 0; } @@ -933,24 +933,24 @@ Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size ) *size = stat_buf.st_size; sres = VG_(am_mmap_file_float_valgrind) - ( *size, VKI_PROT_READ, fd.res, 0 ); + ( *size, VKI_PROT_READ, sr_Res(fd), 0 ); - VG_(close)(fd.res); + VG_(close)(sr_Res(fd)); - if (sres.isError) + if (sr_isError(sres)) return 0; - calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size); + calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sr_Res(sres), *size); if (calccrc != crc) { - SysRes res = VG_(am_munmap_valgrind)(sres.res, *size); - vg_assert(!res.isError); + SysRes res = VG_(am_munmap_valgrind)(sr_Res(sres), *size); + vg_assert(!sr_isError(res)); if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, ".. CRC mismatch (computed %08x wanted %08x)", calccrc, crc); return 0; } - return sres.res; + return sr_Res(sres); } /* @@ -1126,32 +1126,32 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) thereafter; it is only aboard transiently. */ fd = VG_(open)(di->filename, VKI_O_RDONLY, 0); - if (fd.isError) { + if (sr_isError(fd)) { ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!"); return False; } - { Long n_oimageLL = VG_(fsize)(fd.res); + { Long n_oimageLL = VG_(fsize)(sr_Res(fd)); if (n_oimageLL <= 0) { ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!"); - VG_(close)(fd.res); + VG_(close)(sr_Res(fd)); return False; } n_oimage = (UWord)(ULong)n_oimageLL; } sres = VG_(am_mmap_file_float_valgrind) - ( n_oimage, VKI_PROT_READ, fd.res, 0 ); + ( n_oimage, VKI_PROT_READ, sr_Res(fd), 0 ); - VG_(close)(fd.res); + VG_(close)(sr_Res(fd)); - if (sres.isError) { + if (sr_isError(sres)) { VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", di->filename ); VG_(message)(Vg_UserMsg, " no symbols or debug info loaded" ); return False; } - oimage = sres.res; + oimage = sr_Res(sres); /* Check against wraparound. am_mmap_file_float_valgrind should not produce a wrapped-around mapping. */ vg_assert(n_oimage > 0); @@ -2040,10 +2040,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) /* Last, but not least, heave the image(s) back overboard. */ if (dimage) { m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage ); - vg_assert(!m_res.isError); + vg_assert(!sr_isError(m_res)); } m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage ); - vg_assert(!m_res.isError); + vg_assert(!sr_isError(m_res)); return res; } } diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index e784d0fc85..14bdd7f1a5 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -953,13 +953,13 @@ static void load_one_suppressions_file ( Char* filename ) SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS]; sres = VG_(open)( filename, VKI_O_RDONLY, 0 ); - if (sres.isError) { + if (sr_isError(sres)) { if (VG_(clo_xml)) VG_UMSG("\n"); VG_UMSG("FATAL: can't open suppressions file \"%s\"", filename ); VG_(exit)(1); } - fd = sres.res; + fd = sr_Res(sres); # define BOMB(S) { err_str = S; goto syntax_error; } diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index e80dc22024..ec8ca0a31c 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -189,8 +189,8 @@ static void load_client ( /*OUT*/ExeInfo* info, /* Get hold of a file descriptor which refers to the client executable. This is needed for attaching to GDB. */ res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); - if (!res.isError) - VG_(cl_exec_fd) = res.res; + if (!sr_isError(res)) + VG_(cl_exec_fd) = sr_Res(res); /* Copy necessary bits of 'info' that were filled in */ *client_ip = info->init_ip; @@ -625,7 +625,7 @@ Addr setup_client_stack( void* init_sp, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC ); } - if ((!ok) || res.isError) { + if ((!ok) || sr_isError(res)) { /* Allocation of the stack failed. We have to stop. */ VG_(printf)("valgrind: " "I failed to allocate space for the application's stack.\n"); @@ -636,7 +636,7 @@ Addr setup_client_stack( void* init_sp, } vg_assert(ok); - vg_assert(!res.isError); + vg_assert(!sr_isError(res)); } /* ==================== create client stack ==================== */ @@ -866,8 +866,8 @@ static void setup_client_dataseg ( SizeT max_size ) anon_size, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC ); - vg_assert(!sres.isError); - vg_assert(sres.res == anon_start); + vg_assert(!sr_isError(sres)); + vg_assert(sr_Res(sres) == anon_start); } diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 99da85c218..9a972bf102 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -107,11 +107,11 @@ Int VG_(read) ( Int fd, void* buf, Int count) { Int ret; SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); - if (res.isError) { - ret = - (Int)(Word)res.err; + if (sr_isError(res)) { + ret = - (Int)(Word)sr_Err(res); vg_assert(ret < 0); } else { - ret = (Int)(Word)res.res; + ret = (Int)(Word)sr_Res(res); vg_assert(ret >= 0); } return ret; @@ -121,26 +121,37 @@ Int VG_(write) ( Int fd, const void* buf, Int count) { Int ret; SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); - if (res.isError) { - ret = - (Int)(Word)res.err; + if (sr_isError(res)) { + ret = - (Int)(Word)sr_Err(res); vg_assert(ret < 0); } else { - ret = (Int)(Word)res.res; + ret = (Int)(Word)sr_Res(res); vg_assert(ret >= 0); } return ret; } + Int VG_(pipe) ( Int fd[2] ) { +# if defined(VGO_linux) || defined(VGO_aix5) SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); - return res.isError ? -1 : 0; + return sr_isError(res) ? -1 : 0; +# else +# error "Unknown OS" +# endif } OffT VG_(lseek) ( Int fd, OffT offset, Int whence ) { +#if defined(VGO_linux) || defined(VGO_aix5) + /* all other platforms */ SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); - return res.isError ? (-1) : res.res; + vg_assert(sizeof(OffT) == sizeof(Word)); +# else +# error "Unknown plat" +# endif + return sr_isError(res) ? (-1) : sr_Res(res); /* if you change the error-reporting conventions of this, also change VG_(pread) and all other usage points. */ } @@ -155,11 +166,11 @@ OffT VG_(lseek) ( Int fd, OffT offset, Int whence ) (_p_vgstat)->st_dev = (ULong)( (_p_vkistat)->st_dev ); \ (_p_vgstat)->st_ino = (ULong)( (_p_vkistat)->st_ino ); \ (_p_vgstat)->st_nlink = (ULong)( (_p_vkistat)->st_nlink ); \ - (_p_vgstat)->st_mode = (UInt)( (_p_vkistat)->st_mode ); \ - (_p_vgstat)->st_uid = (UInt)( (_p_vkistat)->st_uid ); \ - (_p_vgstat)->st_gid = (UInt)( (_p_vkistat)->st_gid ); \ + (_p_vgstat)->st_mode = (UInt) ( (_p_vkistat)->st_mode ); \ + (_p_vgstat)->st_uid = (UInt) ( (_p_vkistat)->st_uid ); \ + (_p_vgstat)->st_gid = (UInt) ( (_p_vkistat)->st_gid ); \ (_p_vgstat)->st_rdev = (ULong)( (_p_vkistat)->st_rdev ); \ - (_p_vgstat)->st_size = (Long)( (_p_vkistat)->st_size ); \ + (_p_vgstat)->st_size = (Long) ( (_p_vkistat)->st_size ); \ (_p_vgstat)->st_blksize = (ULong)( (_p_vkistat)->st_blksize ); \ (_p_vgstat)->st_blocks = (ULong)( (_p_vkistat)->st_blocks ); \ (_p_vgstat)->st_atime = (ULong)( (_p_vkistat)->st_atime ); \ @@ -170,28 +181,32 @@ OffT VG_(lseek) ( Int fd, OffT offset, Int whence ) (_p_vgstat)->st_ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \ } while (0) -SysRes VG_(stat) ( Char* file_name, struct vg_stat* vgbuf ) +SysRes VG_(stat) ( const Char* file_name, struct vg_stat* vgbuf ) { SysRes res; VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); + # if defined(VGO_linux) + /* First try with stat64. If that doesn't work out, fall back to + the vanilla version. */ # if defined(__NR_stat64) { struct vki_stat64 buf64; res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64); - if (!(res.isError && res.err == VKI_ENOSYS)) { + if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { /* Success, or any failure except ENOSYS */ - if (!res.isError) + if (!sr_isError(res)) TRANSLATE_TO_vg_stat(vgbuf, &buf64); return res; } } -# endif /* if defined(__NR_stat64) */ +# endif /* defined(__NR_stat64) */ { struct vki_stat buf; res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf); - if (!res.isError) + if (!sr_isError(res)) TRANSLATE_TO_vg_stat(vgbuf, &buf); return res; } + # elif defined(VGO_aix5) { struct vki_stat buf; res = VG_(do_syscall4)(__NR_AIX5_statx, @@ -199,7 +214,7 @@ SysRes VG_(stat) ( Char* file_name, struct vg_stat* vgbuf ) (UWord)&buf, sizeof(struct vki_stat), VKI_STX_NORMAL); - if (!res.isError) { + if (!sr_isError(res)) { VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); vgbuf->st_dev = (ULong)buf.st_dev; vgbuf->st_ino = (ULong)buf.st_ino; @@ -210,6 +225,7 @@ SysRes VG_(stat) ( Char* file_name, struct vg_stat* vgbuf ) } return res; } + # else # error Unknown OS # endif @@ -219,26 +235,31 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf ) { SysRes res; VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); + # if defined(VGO_linux) + /* First try with fstat64. If that doesn't work out, fall back to + the vanilla version. */ # if defined(__NR_fstat64) { struct vki_stat64 buf64; res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64); - if (!(res.isError && res.err == VKI_ENOSYS)) { + if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { /* Success, or any failure except ENOSYS */ - if (!res.isError) + if (!sr_isError(res)) TRANSLATE_TO_vg_stat(vgbuf, &buf64); - return res.isError ? (-1) : 0; + return sr_isError(res) ? (-1) : 0; } } # endif /* if defined(__NR_fstat64) */ { struct vki_stat buf; res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf); - if (!res.isError) + if (!sr_isError(res)) TRANSLATE_TO_vg_stat(vgbuf, &buf); - return res.isError ? (-1) : 0; + return sr_isError(res) ? (-1) : 0; } + # elif defined(VGO_aix5) I_die_here; + # else # error Unknown OS # endif @@ -258,7 +279,7 @@ Bool VG_(is_dir) ( HChar* f ) { struct vg_stat buf; SysRes res = VG_(stat)(f, &buf); - return res.isError ? False + return sr_isError(res) ? False : VKI_S_ISDIR(buf.st_mode) ? True : False; } @@ -282,19 +303,19 @@ SysRes VG_(dup2) ( Int oldfd, Int newfd ) Int VG_(fcntl) ( Int fd, Int cmd, Int arg ) { SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } Int VG_(rename) ( Char* old_name, Char* new_name ) { SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); - return res.isError ? (-1) : 0; + return sr_isError(res) ? (-1) : 0; } Int VG_(unlink) ( Char* file_name ) { SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); - return res.isError ? (-1) : 0; + return sr_isError(res) ? (-1) : 0; } /* The working directory at startup. AIX doesn't provide an easy @@ -322,7 +343,7 @@ Bool VG_(record_startup_wd) ( void ) { SysRes res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1); vg_assert(startup_wd[szB-1] == 0); - if (res.isError) { + if (sr_isError(res)) { return False; } else { startup_wd_acquired = True; @@ -369,15 +390,19 @@ Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz) SysRes res; /* res = readlink( path, buf, bufsiz ); */ res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } -Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count) +Int VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count) { +# if defined(VGO_linux) || defined(VGO_aix5) SysRes res; /* res = getdents( fd, dirp, count ); */ res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); +# else +# error "Unknown OS" +# endif } /* Check accessibility of a file. Returns zero for access granted, @@ -389,19 +414,21 @@ Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr ) the kernel interfaces. Therefore I reluctantly resort to hardwiring in these magic numbers that I determined by experimentation. */ - UWord w = (irusr ? 4/*R_OK*/ : 0) - | (iwusr ? 2/*W_OK*/ : 0) - | (ixusr ? 1/*X_OK*/ : 0); - SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); - return res.isError ? 1 : 0; -# elif defined(VGO_aix5) +# define VKI_R_OK 4 +# define VKI_W_OK 2 +# define VKI_X_OK 1 +# endif + UWord w = (irusr ? VKI_R_OK : 0) | (iwusr ? VKI_W_OK : 0) | (ixusr ? VKI_X_OK : 0); SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); - return res.isError ? 1 : 0; -# else -# error "Don't know how to do VG_(access) on this OS" + return sr_isError(res) ? 1 : 0; + +# if defined(VGO_linux) +# undef VKI_R_OK +# undef VKI_W_OK +# undef VKI_X_OK # endif } @@ -434,8 +461,8 @@ Int VG_(check_executable)(/*OUT*/Bool* is_setuid, if (is_setuid) *is_setuid = False; - if (res.isError) { - return res.err; + if (sr_isError(res)) { + return sr_Err(res); } if ( (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) { @@ -477,12 +504,22 @@ Int VG_(check_executable)(/*OUT*/Bool* is_setuid, return 0; } +/* Note this moves (or at least, is believed to move) the file pointer + on Linux and AIX5 but doesn't on Darwin. This inconsistency should + be fixed. */ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) { - OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET); + SysRes res; +# if defined(VGO_linux) || defined(VGO_aix5) + /* Linux, AIX5 */ + OffT off = VG_(lseek)( fd, offset, VKI_SEEK_SET); if (off < 0) return VG_(mk_SysRes_Error)( VKI_EINVAL ); - return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count ); + res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count ); + return res; +# else +# error "Unknown platform" +# endif } /* Create and open (-rw------) a tmp file name incorporating said arg. @@ -515,10 +552,10 @@ Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname ) sres = VG_(open)(buf, VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC, VKI_S_IRUSR|VKI_S_IWUSR); - if (sres.isError) + if (sr_isError(sres)) continue; /* VG_(safe_fd) doesn't return if it fails. */ - fd = VG_(safe_fd)( sres.res ); + fd = VG_(safe_fd)( sr_Res(sres) ); if (fullname) VG_(strcpy)( fullname, buf ); return fd; @@ -601,9 +638,7 @@ UShort VG_(ntohs) ( UShort x ) */ Int VG_(connect_via_socket)( UChar* str ) { -#if defined(VGO_aix5) - I_die_here; -#else /* Yay, Linux */ +# if defined(VGO_linux) Int sd, res; struct vki_sockaddr_in servAddr; UInt ip = 0; @@ -638,7 +673,13 @@ Int VG_(connect_via_socket)( UChar* str ) } return sd; -#endif + +# elif defined(VGO_aix5) + I_die_here; + +# else +# error "Unknown OS" +# endif } @@ -689,28 +730,30 @@ static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) static Int my_socket ( Int domain, Int type, Int protocol ) { -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_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); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown arch" +# endif } + static Int my_connect ( Int sockfd, # if defined(VGO_linux) @@ -720,26 +763,27 @@ Int my_connect ( Int sockfd, # endif Int addrlen ) { -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_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); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown arch" +# endif } Int VG_(write_socket)( Int sd, void *msg, Int count ) @@ -749,7 +793,8 @@ Int VG_(write_socket)( Int sd, void *msg, Int count ) errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned. */ -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_linux) SysRes res; UWord args[4]; args[0] = sd; @@ -757,76 +802,79 @@ Int VG_(write_socket)( Int sd, void *msg, Int count ) args[2] = count; args[3] = VKI_MSG_NOSIGNAL; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, VKI_MSG_NOSIGNAL, 0,0); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown platform" +# endif } Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) { -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_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); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getsockname, (UWord)sd, (UWord)name, (UWord)namelen ); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown platform" +# endif } Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) { -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_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); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall3)( __NR_getpeername, (UWord)sd, (UWord)name, (UWord)namelen ); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown platform" +# endif } Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, Int *optlen) { -#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) +# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ + || defined(VGP_ppc64_linux) SysRes res; UWord args[5]; args[0] = sd; @@ -835,26 +883,24 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, args[3] = (UWord)optval; args[4] = (UWord)optlen; res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_amd64_linux) +# elif defined(VGP_amd64_linux) SysRes res; res = VG_(do_syscall5)( __NR_getsockopt, (UWord)sd, (UWord)level, (UWord)optname, (UWord)optval, (UWord)optlen ); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); -#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) I_die_here; -#else -# error Unknown arch -#endif +# else +# error "Unknown platform" +# endif } - /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ - diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c index 0af540a27d..86ebd23a71 100644 --- a/coregrind/m_libcproc.c +++ b/coregrind/m_libcproc.c @@ -128,6 +128,7 @@ Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val ) return oldenv; } + /* Walk through a colon-separated environment variable, and remove the entries which match remove_pattern. It slides everything down over the removed entries, and pads the remaining space with '\0'. It @@ -231,15 +232,15 @@ Int VG_(waitpid)(Int pid, Int *status, Int options) { # if defined(VGO_linux) SysRes res = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); # elif defined(VGO_aix5) /* magic number 4 obtained by truss-ing a C program doing 'waitpid'. Note status and pid args opposite way round from POSIX. */ SysRes res = VG_(do_syscall5)(__NR_AIX5_kwaitpid, (UWord)status, pid, 4 | options,0,0); - if (0) VG_(printf)("waitpid: got 0x%lx 0x%lx\n", res.res, res.err); - return res.isError ? -1 : res.res; + if (0) VG_(printf)("waitpid: got 0x%lx 0x%lx\n", sr_Res(res), res.err); + return sr_isError(res) ? -1 : sr_Res(res); # else # error Unknown OS # endif @@ -286,7 +287,7 @@ void VG_(execv) ( Char* filename, Char** argv ) res = VG_(do_syscall3)(__NR_execve, (UWord)filename, (UWord)argv, (UWord)envp); - VG_(printf)("EXEC failed, errno = %ld\n", res.res); + VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res)); } /* Return -1 if error, else 0. NOTE does not indicate return code of @@ -308,7 +309,6 @@ Int VG_(system) ( Char* cmd ) VG_(exit)(1); } else { /* parent */ - Int ir, zzz; /* We have to set SIGCHLD to its default behaviour in order that VG_(waitpid) works (at least on AIX). According to the Linux man page for waitpid: @@ -321,8 +321,10 @@ Int VG_(system) ( Char* cmd ) set to ECHILD. (The original POSIX standard left the behaviour of setting SIGCHLD to SIG_IGN unspecified.) */ - struct vki_sigaction sa, saved_sa; - VG_(memset)( &sa, 0, sizeof(struct vki_sigaction) ); + Int ir, zzz; + vki_sigaction_toK_t sa, sa2; + vki_sigaction_fromK_t saved_sa; + VG_(memset)( &sa, 0, sizeof(sa) ); VG_(sigemptyset)(&sa.sa_mask); sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; @@ -331,9 +333,9 @@ Int VG_(system) ( Char* cmd ) zzz = VG_(waitpid)(pid, NULL, 0); - ir = VG_(sigaction)(VKI_SIGCHLD, &saved_sa, NULL); + VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 ); + ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL); vg_assert(ir == 0); - return zzz == -1 ? -1 : 0; } } @@ -350,9 +352,9 @@ Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim) # ifdef __NR_ugetrlimit res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim); # endif - if (res.isError && res.err == VKI_ENOSYS) + if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS) res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } @@ -362,7 +364,7 @@ Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim) SysRes res; /* res = setrlimit( resource, rlim ); */ res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } /* --------------------------------------------------------------------- @@ -371,18 +373,10 @@ Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim) Int VG_(gettid)(void) { -# if defined(VGO_aix5) - SysRes res; - Int r; - vg_assert(__NR_AIX5__thread_self != __NR_AIX5_UNKNOWN); - res = VG_(do_syscall0)(__NR_AIX5__thread_self); - r = res.res; - return r; - -# else +# if defined(VGO_linux) SysRes res = VG_(do_syscall0)(__NR_gettid); - if (res.isError && res.res == VKI_ENOSYS) { + if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) { Char pid[16]; /* * The gettid system call does not exist. The obvious assumption @@ -400,10 +394,10 @@ Int VG_(gettid)(void) res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self", (UWord)pid, sizeof(pid)); - if (!res.isError && res.res > 0) { + if (!sr_isError(res) && sr_Res(res) > 0) { Char* s; - pid[res.res] = '\0'; - res.res = VG_(strtoll10)(pid, &s); + pid[sr_Res(res)] = '\0'; + res = VG_(mk_SysRes_Success)( VG_(strtoll10)(pid, &s) ); if (*s != '\0') { VG_(message)(Vg_DebugMsg, "Warning: invalid file name linked to by /proc/self: %s", pid); @@ -411,7 +405,18 @@ Int VG_(gettid)(void) } } - return res.res; + return sr_Res(res); + +# elif defined(VGO_aix5) + SysRes res; + Int r; + vg_assert(__NR_AIX5__thread_self != __NR_AIX5_UNKNOWN); + res = VG_(do_syscall0)(__NR_AIX5__thread_self); + r = sr_Res(res); + return r; + +# else +# error "Unknown OS" # endif } @@ -419,32 +424,32 @@ Int VG_(gettid)(void) Int VG_(getpid) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ - return VG_(do_syscall0)(__NR_getpid) . res; + return sr_Res( VG_(do_syscall0)(__NR_getpid) ); } Int VG_(getpgrp) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ - return VG_(do_syscall0)(__NR_getpgrp) . res; + return sr_Res( VG_(do_syscall0)(__NR_getpgrp) ); } Int VG_(getppid) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ - return VG_(do_syscall0)(__NR_getppid) . res; + return sr_Res( VG_(do_syscall0)(__NR_getppid) ); } Int VG_(geteuid) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ # if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) - return VG_(do_syscall1)(__NR_AIX5_getuidx, 1) . res; + return sr_Res( VG_(do_syscall1)(__NR_AIX5_getuidx, 1) ); # elif defined(__NR_geteuid32) // We use the 32-bit version if it's supported. Otherwise, IDs greater // than 65536 cause problems, as bug #151209 showed. - return VG_(do_syscall0)(__NR_geteuid32) . res; + return sr_Res( VG_(do_syscall0)(__NR_geteuid32) ); # else - return VG_(do_syscall0)(__NR_geteuid) . res; + return sr_Res( VG_(do_syscall0)(__NR_geteuid) ); # endif } @@ -452,13 +457,13 @@ Int VG_(getegid) ( void ) { /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ # if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) - return VG_(do_syscall1)(__NR_AIX5_getgidx, 1) . res; + return sr_Res( VG_(do_syscall1)(__NR_AIX5_getgidx, 1) ); # elif defined(__NR_getegid32) // We use the 32-bit version if it's supported. Otherwise, IDs greater // than 65536 cause problems, as bug #151209 showed. - return VG_(do_syscall0)(__NR_getegid32) . res; + return sr_Res( VG_(do_syscall0)(__NR_getegid32) ); # else - return VG_(do_syscall0)(__NR_getegid) . res; + return sr_Res( VG_(do_syscall0)(__NR_getegid) ); # endif } @@ -475,21 +480,21 @@ Int VG_(getgroups)( Int size, UInt* list ) if (size < 0) return -1; if (size > 64) size = 64; sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16); - if (sres.isError) + if (sr_isError(sres)) return -1; - if (sres.res > size) + if (sr_Res(sres) > size) return -1; - for (i = 0; i < sres.res; i++) + for (i = 0; i < sr_Res(sres); i++) list[i] = (UInt)list16[i]; - return sres.res; + return sr_Res(sres); # elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) SysRes sres; sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list); - if (sres.isError) + if (sr_isError(sres)) return -1; - return sres.res; + return sr_Res(sres); # else # error "VG_(getgroups): needs implementation on this platform" @@ -504,9 +509,9 @@ Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data ) { SysRes res; res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data); - if (res.isError) + if (sr_isError(res)) return -1; - return res.res; + return sr_Res(res); } /* --------------------------------------------------------------------- @@ -515,11 +520,16 @@ Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data ) Int VG_(fork) ( void ) { +# if defined(VGO_linux) || defined(VGO_aix5) SysRes res; res = VG_(do_syscall0)(__NR_fork); - if (res.isError) + if (sr_isError(res)) return -1; - return res.res; + return sr_Res(res); + +# else +# error "Unknown OS" +# endif } /* --------------------------------------------------------------------- @@ -532,7 +542,22 @@ UInt VG_(read_millisecond_timer) ( void ) static ULong base = 0; ULong now; -# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +# if defined(VGO_linux) + { SysRes res; + struct vki_timespec ts_now; + res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC, + (UWord)&ts_now); + if (sr_isError(res) == 0) { + now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000; + } else { + struct vki_timeval tv_now; + res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); + vg_assert(! sr_isError(res)); + now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec; + } + } + +# elif defined(VGO_aix5) /* AIX requires a totally different implementation since sys_gettimeofday doesn't exist. We use the POWER real-time register facility. This will SIGILL on PowerPC 970 on AIX, @@ -550,31 +575,19 @@ UInt VG_(read_millisecond_timer) ( void ) vg_assert(nsec < 1000*1000*1000); now = ((ULong)sec1) * 1000000ULL; now += (ULong)(nsec / 1000); -# else - struct vki_timespec ts_now; - SysRes res; - res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC, - (UWord)&ts_now); - if (res.isError == 0) - { - now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000; - } - else - { - struct vki_timeval tv_now; - res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); - vg_assert(! res.isError); - now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec; - } +# else +# error "Unknown OS" # endif - + + /* COMMON CODE */ if (base == 0) base = now; return (now - base) / 1000; } + /* --------------------------------------------------------------------- atfork() ------------------------------------------------------------------ */ diff --git a/coregrind/m_libcsignal.c b/coregrind/m_libcsignal.c index 0fbc353e5d..edd9a674aa 100644 --- a/coregrind/m_libcsignal.c +++ b/coregrind/m_libcsignal.c @@ -41,6 +41,10 @@ success and -1 on error. */ /* I believe the indexing scheme in ->sig[] is also correct for 32- and 64-bit AIX (verified 27 July 06). */ +/* In the sigset routines below, be aware that _VKI_NSIG_BPW can be + either 32 or 64, and hence the sig[] words can either be 32- or + 64-bits. And which they are it doesn't necessarily follow from the + host word size. */ Int VG_(sigfillset)( vki_sigset_t* set ) { @@ -48,7 +52,7 @@ Int VG_(sigfillset)( vki_sigset_t* set ) if (set == NULL) return -1; for (i = 0; i < _VKI_NSIG_WORDS; i++) - set->sig[i] = ~(UWord)0x0; + set->sig[i] = ~0; return 0; } @@ -58,7 +62,7 @@ Int VG_(sigemptyset)( vki_sigset_t* set ) if (set == NULL) return -1; for (i = 0; i < _VKI_NSIG_WORDS; i++) - set->sig[i] = 0x0; + set->sig[i] = 0; return 0; } @@ -67,7 +71,7 @@ Bool VG_(isemptysigset)( const vki_sigset_t* set ) Int i; vg_assert(set != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) - if (set->sig[i] != 0x0) return False; + if (set->sig[i] != 0) return False; return True; } @@ -76,7 +80,7 @@ Bool VG_(isfullsigset)( const vki_sigset_t* set ) Int i; vg_assert(set != NULL); for (i = 0; i < _VKI_NSIG_WORDS; i++) - if (set->sig[i] != ~(UWord)0x0) return False; + if (set->sig[i] != ~0) return False; return True; } @@ -97,7 +101,7 @@ Int VG_(sigaddset)( vki_sigset_t* set, Int signum ) if (signum < 1 || signum > _VKI_NSIG) return -1; signum--; - set->sig[signum / _VKI_NSIG_BPW] |= (1UL << (signum % _VKI_NSIG_BPW)); + set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW)); return 0; } @@ -108,7 +112,7 @@ Int VG_(sigdelset)( vki_sigset_t* set, Int signum ) if (signum < 1 || signum > _VKI_NSIG) return -1; signum--; - set->sig[signum / _VKI_NSIG_BPW] &= ~(1UL << (signum % _VKI_NSIG_BPW)); + set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW)); return 0; } @@ -143,45 +147,100 @@ void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src ) dst->sig[i] &= ~(src->sig[i]); } +/* dst = dst `intersect` src. */ +void VG_(sigintersectset)( vki_sigset_t* dst, vki_sigset_t* src ) +{ + Int i; + vg_assert(dst != NULL && src != NULL); + for (i = 0; i < _VKI_NSIG_WORDS; i++) + dst->sig[i] &= src->sig[i]; +} + +/* dst = ~src */ +void VG_(sigcomplementset)( vki_sigset_t* dst, vki_sigset_t* src ) +{ + Int i; + vg_assert(dst != NULL && src != NULL); + for (i = 0; i < _VKI_NSIG_WORDS; i++) + dst->sig[i] = ~ src->sig[i]; +} + /* The functions sigaction, sigprocmask, sigpending and sigsuspend return 0 on success and -1 on error. */ Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset) { +# if defined(VGO_linux) || defined(VGO_aix5) +# if defined(__NR_rt_sigprocmask) SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask, how, (UWord)set, (UWord)oldset, _VKI_NSIG_WORDS * sizeof(UWord)); - return res.isError ? -1 : 0; +# else + SysRes res = VG_(do_syscall3)(__NR_sigprocmask, + how, (UWord)set, (UWord)oldset); +# endif + +# else +# error "Unknown OS" +# endif + return sr_isError(res) ? -1 : 0; } -Int VG_(sigaction) ( Int signum, const struct vki_sigaction* act, - struct vki_sigaction* oldact) +Int VG_(sigaction) ( Int signum, + const vki_sigaction_toK_t* act, + vki_sigaction_fromK_t* oldact) { +# if defined(VGO_linux) || defined(VGO_aix5) + /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are + identical types. */ SysRes res = VG_(do_syscall4)(__NR_rt_sigaction, signum, (UWord)act, (UWord)oldact, _VKI_NSIG_WORDS * sizeof(UWord)); - return res.isError ? -1 : 0; + return sr_isError(res) ? -1 : 0; + +# else +# error "Unsupported OS" +# endif +} + + +/* See explanation in pub_core_libcsignal.h. */ +void +VG_(convert_sigaction_fromK_to_toK)( vki_sigaction_fromK_t* fromK, + /*OUT*/vki_sigaction_toK_t* toK ) +{ +# if defined(VGO_linux) || defined(VGO_aix5) + *toK = *fromK; +# else +# error "Unsupported OS" +# endif } Int VG_(kill)( Int pid, Int signo ) { SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo); - return res.isError ? -1 : 0; + return sr_isError(res) ? -1 : 0; } Int VG_(tkill)( ThreadId tid, Int signo ) { +# if defined(__NR_tkill) SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); res = VG_(do_syscall2)(__NR_tkill, tid, signo); - if (res.isError && res.err == VKI_ENOSYS) + if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS) res = VG_(do_syscall2)(__NR_kill, tid, signo); - return res.isError ? -1 : 0; + return sr_isError(res) ? -1 : 0; + +# else +# error "Unsupported plat" +# endif } +/* ---------------------- sigtimedwait_zero ----------------------- */ /* A cut-down version of POSIX sigtimedwait: poll for pending signals mentioned in the sigset_t, and if any are present, select one @@ -199,6 +258,8 @@ Int VG_(tkill)( ThreadId tid, Int signo ) obscure ways. I suspect it's only thread-safe because V forces single-threadedness. */ +/* ---------- sigtimedwait_zero: Linux ----------- */ + #if defined(VGO_linux) Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vki_siginfo_t *info ) @@ -206,9 +267,11 @@ Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, static const struct vki_timespec zero = { 0, 0 }; SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info, (UWord)&zero, sizeof(*set)); - return res.isError ? -1 : res.res; + return sr_isError(res) ? -1 : sr_Res(res); } +/* ---------- sigtimedwait_zero: AIX5 ----------- */ + #elif defined(VGO_aix5) /* The general idea is: - use sigpending to find out which signals are pending @@ -254,8 +317,7 @@ Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vg_assert(ir == 0); /* pending = pending `intersect` blocked */ - for (i = 0; i < _VKI_NSIG_WORDS; i++) - pending.sig[i] &= blocked.sig[i]; + VG_(sigintersectset)(&pending, blocked); /* decide which signal we're going to snarf */ for (i = 1; i < _VKI_NSIG; i++) diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 8d5901f443..85a8099f71 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -401,13 +401,20 @@ Bool VG_(machine_get_hwcaps)( void ) AT_PLATFORM entries in the ELF auxiliary table -- see also the_iifii.client_auxv in m_main.c. */ - vki_sigset_t saved_set, tmp_set; - struct vki_sigaction saved_sigill_act, tmp_sigill_act; - struct vki_sigaction saved_sigfpe_act, tmp_sigfpe_act; + vki_sigset_t saved_set, tmp_set; + vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act; + vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act; volatile Bool have_F, have_V, have_FX, have_GX; Int r; + /* This is a kludge. Really we ought to back-convert saved_act + into a toK_t using VG_(convert_sigaction_fromK_to_toK), but + since that's a no-op on all ppc32 platforms so far supported, + it's not worth the typing effort. At least include most basic + sanity check: */ + vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t)); + VG_(sigemptyset)(&tmp_set); VG_(sigaddset)(&tmp_set, VKI_SIGILL); VG_(sigaddset)(&tmp_set, VKI_SIGFPE); @@ -512,19 +519,29 @@ Bool VG_(machine_get_hwcaps)( void ) #elif defined(VGA_ppc64) { /* Same instruction set detection algorithm as for ppc32. */ - vki_sigset_t saved_set, tmp_set; - struct vki_sigaction saved_sigill_act, tmp_sigill_act; - struct vki_sigaction saved_sigfpe_act, tmp_sigfpe_act; + vki_sigset_t saved_set, tmp_set; + vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act; + vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act; volatile Bool have_F, have_V, have_FX, have_GX; + Int r; + + /* This is a kludge. Really we ought to back-convert saved_act + into a toK_t using VG_(convert_sigaction_fromK_to_toK), but + since that's a no-op on all ppc64 platforms so far supported, + it's not worth the typing effort. At least include most basic + sanity check: */ + vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t)); VG_(sigemptyset)(&tmp_set); VG_(sigaddset)(&tmp_set, VKI_SIGILL); VG_(sigaddset)(&tmp_set, VKI_SIGFPE); - VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set); + r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set); + vg_assert(r == 0); - VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act); + r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act); + vg_assert(r == 0); tmp_sigill_act = saved_sigill_act; VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act); diff --git a/coregrind/m_main.c b/coregrind/m_main.c index c8f271daaf..a913dadb7f 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -614,12 +614,12 @@ static Bool main_process_cmd_line_options( const HChar* toolname ) sres = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC, VKI_S_IRUSR|VKI_S_IWUSR); - if (!sres.isError) { - tmp_log_fd = sres.res; + if (!sr_isError(sres)) { + tmp_log_fd = sr_Res(sres); } else { VG_(message)(Vg_UserMsg, "Can't create log file '%s' (%s); giving up!", - logfilename, VG_(strerror)(sres.err)); + logfilename, VG_(strerror)(sr_Err(sres))); VG_(err_bad_option)( "--log-file= (didn't work out for some reason.)"); /*NOTREACHED*/ @@ -903,12 +903,12 @@ static void print_preamble(Bool logging_to_fd, const char* toolname) VG_(message)(Vg_DebugMsg, "Contents of /proc/version:"); fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 ); - if (fd.isError) { + if (sr_isError(fd)) { VG_(message)(Vg_DebugMsg, " can't open /proc/version"); } else { # define BUF_LEN 256 Char version_buf[BUF_LEN]; - Int n = VG_(read) ( fd.res, version_buf, BUF_LEN ); + Int n = VG_(read) ( sr_Res(fd), version_buf, BUF_LEN ); vg_assert(n <= BUF_LEN); if (n > 0) { version_buf[n-1] = '\0'; @@ -916,7 +916,7 @@ static void print_preamble(Bool logging_to_fd, const char* toolname) } else { VG_(message)(Vg_DebugMsg, " (empty?)"); } - VG_(close)(fd.res); + VG_(close)(sr_Res(fd)); # undef BUF_LEN } @@ -1945,6 +1945,9 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp ) //-------------------------------------------------------------- // Nb: temporarily parks the saved blocking-mask in saved_sigmask. VG_(debugLog)(1, "main", "Initialise signal management\n"); + /* Check that the kernel-interface signal definitions look sane */ + VG_(vki_do_initial_consistency_checks)(); + /* .. and go on to use them. */ VG_(sigstartup_actions)(); //-------------------------------------------------------------- diff --git a/coregrind/m_mallocfree.c b/coregrind/m_mallocfree.c index 966d965e4d..275b9997fc 100644 --- a/coregrind/m_mallocfree.c +++ b/coregrind/m_mallocfree.c @@ -641,6 +641,7 @@ void VG_(out_of_memory_NORETURN) ( HChar* who, SizeT szB ) } else { VG_(debugLog)(0,"mallocfree", s1, who, (ULong)szB, tot_alloc); } + VG_(exit)(1); } @@ -672,9 +673,9 @@ Superblock* newSuperblock ( Arena* a, SizeT cszB ) // client allocation -- return 0 to client if it fails sres = VG_(am_sbrk_anon_float_client) ( cszB, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC ); - if (sres.isError) + if (sr_isError(sres)) return 0; - sb = (Superblock*)sres.res; + sb = (Superblock*)(AddrH)sr_Res(sres); // Mark this segment as containing client heap. The leak // checker needs to be able to identify such segments so as not // to use them as sources of roots during leak checks. @@ -684,12 +685,12 @@ Superblock* newSuperblock ( Arena* a, SizeT cszB ) } else { // non-client allocation -- abort if it fails sres = VG_(am_sbrk_anon_float_valgrind)( cszB ); - if (sres.isError) { + if (sr_isError(sres)) { VG_(out_of_memory_NORETURN)("newSuperblock", cszB); /* NOTREACHED */ sb = NULL; /* keep gcc happy */ } else { - sb = (Superblock*)sres.res; + sb = (Superblock*)(AddrH)sr_Res(sres); } } vg_assert(NULL != sb); @@ -1327,12 +1328,12 @@ void* VG_(arena_malloc) ( ArenaId aid, HChar* cc, SizeT req_pszB ) Superblock ** array; SysRes sres = VG_(am_sbrk_anon_float_valgrind)(sizeof(Superblock *) * a->sblocks_size * 2); - if (sres.isError) { + if (sr_isError(sres)) { VG_(out_of_memory_NORETURN)("arena_init", sizeof(Superblock *) * a->sblocks_size * 2); /* NOTREACHED */ } - array = (Superblock**) sres.res; + array = (Superblock**)(AddrH)sr_Res(sres); for (i = 0; i < a->sblocks_used; ++i) array[i] = a->sblocks[i]; a->sblocks_size *= 2; diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index e1e0f1ce1a..3752e85caf 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -1148,13 +1148,11 @@ VgSchedReturnCode VG_(scheduler) ( ThreadId tid ) guest_EIP to point at the code to execute after the sysenter, since Vex-generated code will not have set it -- vex does not know what it should be. Vex sets the next - address to zero, so if you don't guest_EIP, the thread will - jump to zero afterwards and probably die as a result. */ -# if defined(VGA_x86) - //FIXME: VG_(threads)[tid].arch.vex.guest_EIP = .... - //handle_sysenter_x86(tid); + address to zero, so if you don't set guest_EIP, the thread + will jump to zero afterwards and probably die as a result. */ +# if defined(VGP_x86_linux) vg_assert2(0, "VG_(scheduler), phase 3: " - "sysenter_x86 on not yet implemented"); + "sysenter_x86 on x86-linux is not supported"); # else vg_assert2(0, "VG_(scheduler), phase 3: " "sysenter_x86 on non-x86 platform?!?!"); diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index e673a43521..0b1150aace 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -251,16 +251,16 @@ typedef struct SigQueue { /* ------ Macros for pulling stuff out of ucontexts ------ */ -/* Q: what does UCONTEXT_SYSCALL_SYSRES do? A: let's suppose the +/* Q: what does VG_UCONTEXT_SYSCALL_SYSRES do? A: let's suppose the machine context (uc) reflects the situation that a syscall had just completed, quite literally -- that is, that the program counter was now at the instruction following the syscall. (or we're slightly downstream, but we're sure no relevant register has yet changed - value.) Then UCONTEXT_SYSCALL_SYSRES returns a SysRes reflecting + value.) Then VG_UCONTEXT_SYSCALL_SYSRES returns a SysRes reflecting the result of the syscall; it does this by fishing relevant bits of the machine state out of the uc. Of course if the program counter was somewhere else entirely then the result is likely to be - meaningless, so the caller of UCONTEXT_SYSCALL_SYSRES has to be + meaningless, so the caller of VG_UCONTEXT_SYSCALL_SYSRES has to be very careful to pay attention to the results only when it is sure that the said constraint on the program counter is indeed valid. */ #if defined(VGP_x86_linux) @@ -491,6 +491,10 @@ typedef UInt scss_flags; vki_sigset_t scss_mask; void* scss_restorer; /* where sigreturn goes */ + void* scss_sa_tramp; /* sa_tramp setting, Darwin only */ + /* re _restorer and _sa_tramp, we merely record the values + supplied when the client does 'sigaction' and give them back + when requested. Otherwise they are simply ignored. */ } SCSS_Per_Signal; @@ -748,7 +752,8 @@ static void handle_SCSS_change ( Bool force_update ) { Int res, sig; SKSS skss_old; - struct vki_sigaction ksa, ksa_old; + vki_sigaction_toK_t ksa; + vki_sigaction_fromK_t ksa_old; /* Remember old SKSS and calculate new one. */ skss_old = skss; @@ -775,7 +780,7 @@ static void handle_SCSS_change ( Bool force_update ) ksa.ksa_handler = skss.skss_per_sig[sig].skss_handler; ksa.sa_flags = skss.skss_per_sig[sig].skss_flags; # if !defined(VGP_ppc32_linux) && !defined(VGP_ppc32_aix5) \ - && !defined(VGP_ppc64_aix5) + && !defined(VGP_ppc64_aix5) ksa.sa_restorer = my_sigreturn; # endif /* Re above ifdef (also the assertion below), PaulM says: @@ -791,11 +796,12 @@ static void handle_SCSS_change ( Bool force_update ) if (VG_(clo_trace_signals) && VG_(clo_verbosity) > 2) VG_DMSG("setting ksig %d to: hdlr %p, flags 0x%lx, " - "mask(63..0) 0x%lx 0x%lx", + "mask(msb..lsb) 0x%llx 0x%llx", sig, ksa.ksa_handler, (UWord)ksa.sa_flags, - (UWord)ksa.sa_mask.sig[1], - (UWord)ksa.sa_mask.sig[0]); + _VKI_NSIG_WORDS > 1 ? (ULong)ksa.sa_mask.sig[1] : 0, + (ULong)ksa.sa_mask.sig[0] + ); res = VG_(sigaction)( sig, &ksa, &ksa_old ); vg_assert(res == 0); @@ -808,7 +814,7 @@ static void handle_SCSS_change ( Bool force_update ) vg_assert(ksa_old.sa_flags == skss_old.skss_per_sig[sig].skss_flags); # if !defined(VGP_ppc32_linux) && !defined(VGP_ppc32_aix5) \ - && !defined(VGP_ppc64_aix5) + && !defined(VGP_ppc64_aix5) vg_assert(ksa_old.sa_restorer == my_sigreturn); # endif @@ -894,8 +900,8 @@ SysRes VG_(do_sys_sigaltstack) ( ThreadId tid, vki_stack_t* ss, vki_stack_t* oss SysRes VG_(do_sys_sigaction) ( Int signo, - const struct vki_sigaction *new_act, - struct vki_sigaction *old_act ) + const vki_sigaction_toK_t* new_act, + vki_sigaction_fromK_t* old_act ) { if (VG_(clo_trace_signals)) VG_EMSG("sys_sigaction: sigNo %d, " @@ -940,11 +946,13 @@ SysRes VG_(do_sys_sigaction) ( Int signo, scss.scss_per_sig[signo].scss_flags = new_act->sa_flags; scss.scss_per_sig[signo].scss_mask = new_act->sa_mask; - scss.scss_per_sig[signo].scss_restorer = 0; + scss.scss_per_sig[signo].scss_restorer = NULL; # if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5) scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer; # endif + scss.scss_per_sig[signo].scss_sa_tramp = NULL; + VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGKILL); VG_(sigdelset)(&scss.scss_per_sig[signo].scss_mask, VKI_SIGSTOP); } @@ -1069,16 +1077,16 @@ SysRes VG_(do_sys_sigprocmask) ( ThreadId tid, vki_sigset_t* oldset ) { switch(how) { - case VKI_SIG_BLOCK: - case VKI_SIG_UNBLOCK: - case VKI_SIG_SETMASK: - vg_assert(VG_(is_valid_tid)(tid)); - do_setmask ( tid, how, set, oldset ); - return VG_(mk_SysRes_Success)( 0 ); + case VKI_SIG_BLOCK: + case VKI_SIG_UNBLOCK: + case VKI_SIG_SETMASK: + vg_assert(VG_(is_valid_tid)(tid)); + do_setmask ( tid, how, set, oldset ); + return VG_(mk_SysRes_Success)( 0 ); - default: - VG_DMSG("sigprocmask: unknown 'how' field %d", how); - return VG_(mk_SysRes_Error)( VKI_EINVAL ); + default: + VG_DMSG("sigprocmask: unknown 'how' field %d", how); + return VG_(mk_SysRes_Error)( VKI_EINVAL ); } } @@ -1220,14 +1228,18 @@ static const Char *signame(Int sigNo) case VKI_SIGPROF: return "SIGPROF"; case VKI_SIGWINCH: return "SIGWINCH"; case VKI_SIGIO: return "SIGIO"; +# if defined(VKI_SIGPWR) case VKI_SIGPWR: return "SIGPWR"; +# endif # if defined(VKI_SIGUNUSED) case VKI_SIGUNUSED: return "SIGUNUSED"; # endif +# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) case VKI_SIGRTMIN ... VKI_SIGRTMAX: VG_(sprintf)(buf, "SIGRT%d", sigNo-VKI_SIGRTMIN); return buf; +# endif default: VG_(sprintf)(buf, "SIG%d", sigNo); @@ -1238,8 +1250,9 @@ static const Char *signame(Int sigNo) /* Hit ourselves with a signal using the default handler */ void VG_(kill_self)(Int sigNo) { - vki_sigset_t mask, origmask; - struct vki_sigaction sa, origsa; + vki_sigset_t mask, origmask; + vki_sigaction_toK_t sa, origsa2; + vki_sigaction_fromK_t origsa; sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; @@ -1256,7 +1269,8 @@ void VG_(kill_self)(Int sigNo) VG_(kill)(VG_(getpid)(), sigNo); - VG_(sigaction)(sigNo, &origsa, NULL); + VG_(convert_sigaction_fromK_to_toK)( &origsa, &origsa2 ); + VG_(sigaction)(sigNo, &origsa2, NULL); VG_(sigprocmask)(VKI_SIG_SETMASK, &origmask, NULL); } @@ -1302,35 +1316,39 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) vg_assert(VG_(is_running_thread)(tid)); switch(sigNo) { - case VKI_SIGQUIT: /* core */ - case VKI_SIGILL: /* core */ - case VKI_SIGABRT: /* core */ - case VKI_SIGFPE: /* core */ - case VKI_SIGSEGV: /* core */ - case VKI_SIGBUS: /* core */ - case VKI_SIGTRAP: /* core */ - case VKI_SIGXCPU: /* core */ - case VKI_SIGXFSZ: /* core */ - terminate = True; - core = True; - break; - - case VKI_SIGHUP: /* term */ - case VKI_SIGINT: /* term */ - case VKI_SIGKILL: /* term - we won't see this */ - case VKI_SIGPIPE: /* term */ - case VKI_SIGALRM: /* term */ - case VKI_SIGTERM: /* term */ - case VKI_SIGUSR1: /* term */ - case VKI_SIGUSR2: /* term */ - case VKI_SIGIO: /* term */ - case VKI_SIGPWR: /* term */ - case VKI_SIGSYS: /* term */ - case VKI_SIGPROF: /* term */ - case VKI_SIGVTALRM: /* term */ - case VKI_SIGRTMIN ... VKI_SIGRTMAX: /* term */ - terminate = True; - break; + case VKI_SIGQUIT: /* core */ + case VKI_SIGILL: /* core */ + case VKI_SIGABRT: /* core */ + case VKI_SIGFPE: /* core */ + case VKI_SIGSEGV: /* core */ + case VKI_SIGBUS: /* core */ + case VKI_SIGTRAP: /* core */ + case VKI_SIGXCPU: /* core */ + case VKI_SIGXFSZ: /* core */ + terminate = True; + core = True; + break; + + case VKI_SIGHUP: /* term */ + case VKI_SIGINT: /* term */ + case VKI_SIGKILL: /* term - we won't see this */ + case VKI_SIGPIPE: /* term */ + case VKI_SIGALRM: /* term */ + case VKI_SIGTERM: /* term */ + case VKI_SIGUSR1: /* term */ + case VKI_SIGUSR2: /* term */ + case VKI_SIGIO: /* term */ +# if defined(VKI_SIGPWR) + case VKI_SIGPWR: /* term */ +# endif + case VKI_SIGSYS: /* term */ + case VKI_SIGPROF: /* term */ + case VKI_SIGVTALRM: /* term */ +# if defined(VKI_SIGRTMIN) && defined(VKI_SIGRTMAX) + case VKI_SIGRTMIN ... VKI_SIGRTMAX: /* term */ +# endif + terminate = True; + break; } vg_assert(!core || (core && terminate)); @@ -1560,7 +1578,6 @@ static void deliver_signal ( ThreadId tid, const vki_siginfo_t *info, if (!(handler->scss_flags & VKI_SA_NOMASK)) { VG_(sigaddset_from_set)(&tst->sig_mask, &handler->scss_mask); VG_(sigaddset)(&tst->sig_mask, sigNo); - tst->tmp_sig_mask = tst->sig_mask; } } @@ -1646,12 +1663,13 @@ void VG_(synth_sigtrap)(ThreadId tid) VG_(memset)(&uc, 0, sizeof(uc)); info.si_signo = VKI_SIGTRAP; info.si_code = VKI_TRAP_BRKPT; /* tjh: only ever called for a brkpt ins */ -#if defined(VGA_x86) || defined(VGA_amd64) + +# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) uc.uc_mcontext.trapno = 3; /* tjh: this is the x86 trap number for a breakpoint trap... */ uc.uc_mcontext.err = 0; /* tjh: no error code for x86 breakpoint trap... */ -#endif +# endif resume_scheduler(tid); deliver_signal(tid, &info, &uc); @@ -1773,6 +1791,7 @@ void async_signalhandler ( Int sigNo, { ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)()); ThreadState* tst = VG_(get_ThreadState)(tid); + SysRes sres; /* The thread isn't currently running, make it so before going on */ vg_assert(tst->status == VgTs_WaitSys); @@ -1784,19 +1803,59 @@ void async_signalhandler ( Int sigNo, VG_DMSG("async signal handler: signal=%d, tid=%d, si_code=%d", sigNo, tid, info->si_code); - /* Update thread state properly */ + /* Update thread state properly. The signal can only have been + delivered whilst we were in + coregrind/m_syswrap/syscall-.S, and only then in the + window between the two sigprocmask calls, since at all other + times, we run with async signals on the host blocked. Hence + make enquiries on the basis that we were in or very close to a + syscall, and attempt to fix up the guest state accordingly. + + (normal async signals occurring during computation are blocked, + but periodically polled for using VG_(sigtimedwait_zero), and + delivered at a point convenient for us. Hence this routine only + deals with signals that are delivered to a thread during a + syscall.) */ + + /* First, extract a SysRes from the ucontext_t* given to this + handler. If it is subsequently established by + VG_(fixup_guest_state_after_syscall_interrupted) that the + syscall was complete but the results had not been committed yet + to the guest state, then it'll have to commit the results itself + "by hand", and so we need to extract the SysRes. Of course if + the thread was not in that particular window then the + SysRes will be meaningless, but that's OK too because + VG_(fixup_guest_state_after_syscall_interrupted) will detect + that the thread was not in said window and ignore the SysRes. */ + + sres = VG_UCONTEXT_SYSCALL_SYSRES(uc); + + /* (1) */ VG_(fixup_guest_state_after_syscall_interrupted)( tid, VG_UCONTEXT_INSTR_PTR(uc), - VG_UCONTEXT_SYSCALL_NUM(uc), - VG_UCONTEXT_SYSCALL_SYSRES(uc), + sres, !!(scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART) ); + /* (2) */ /* Set up the thread's state to deliver a signal */ if (!is_sig_ign(info->si_signo)) deliver_signal(tid, info, uc); + /* It's crucial that (1) and (2) happen in the order (1) then (2) + and not the other way around. (1) fixes up the guest thread + state to reflect the fact that the syscall was interrupted -- + either to restart the syscall or to return EINTR. (2) then sets + up the thread state to deliver the signal. Then we resume + execution. First, the signal handler is run, since that's the + second adjustment we made to the thread state. If that returns, + then we resume at the guest state created by (1), viz, either + the syscall returns EINTR or is restarted. + + If (2) was done before (1) the outcome would be completely + different, and wrong. */ + /* longjmp back to the thread's main loop to start executing the handler. */ resume_scheduler(tid); @@ -2007,6 +2066,7 @@ static Bool extend_stack_if_appropriate(ThreadId tid, vki_siginfo_t* info) } } + static void sync_signalhandler_from_kernel ( ThreadId tid, Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc ) @@ -2170,7 +2230,7 @@ static void sigvgkill_handler(int signo, vki_siginfo_t *si, } static __attribute((unused)) -void pp_ksigaction ( struct vki_sigaction* sa ) +void pp_ksigaction ( vki_sigaction_toK_t* sa ) { Int i; VG_(printf)("pp_ksigaction: handler %p, flags 0x%x, restorer %p\n", @@ -2194,7 +2254,7 @@ void pp_ksigaction ( struct vki_sigaction* sa ) */ void VG_(set_default_handler)(Int signo) { - struct vki_sigaction sa; + vki_sigaction_toK_t sa; sa.ksa_handler = VKI_SIG_DFL; sa.sa_flags = 0; @@ -2214,14 +2274,11 @@ void VG_(poll_signals)(ThreadId tid) vki_siginfo_t si, *sip; vki_sigset_t pollset; ThreadState *tst = VG_(get_ThreadState)(tid); - Int i; vki_sigset_t saved_mask; /* look for all the signals this thread isn't blocking */ - for(i = 0; i < _VKI_NSIG_WORDS; i++) - pollset.sig[i] = ~tst->sig_mask.sig[i]; - - //VG_(printf)("tid %d pollset=%08x%08x\n", tid, pollset.sig[1], pollset.sig[0]); + /* pollset = ~tst->sig_mask */ + VG_(sigcomplementset)( &pollset, &tst->sig_mask ); block_all_host_signals(&saved_mask); // protect signal queue @@ -2261,9 +2318,18 @@ void VG_(poll_signals)(ThreadId tid) */ void VG_(sigstartup_actions) ( void ) { - Int i, ret; + Int i, ret, vKI_SIGRTMIN; vki_sigset_t saved_procmask; - struct vki_sigaction sa; + vki_sigaction_fromK_t sa; + + VG_(memset)(&scss, 0, sizeof(scss)); + VG_(memset)(&skss, 0, sizeof(skss)); + +# if defined(VKI_SIGRTMIN) + vKI_SIGRTMIN = VKI_SIGRTMIN; +# else + vKI_SIGRTMIN = 0; /* eg Darwin */ +# endif /* VG_(printf)("SIGSTARTUP\n"); */ /* Block all signals. saved_procmask remembers the previous mask, @@ -2281,8 +2347,9 @@ void VG_(sigstartup_actions) ( void ) /* Try setting it back to see if this signal is really available */ - if (i >= VKI_SIGRTMIN) { - struct vki_sigaction tsa; + if (vKI_SIGRTMIN > 0 /* it actually exists on this platform */ + && i >= vKI_SIGRTMIN) { + vki_sigaction_toK_t tsa, sa2; tsa.ksa_handler = (void *)sync_signalhandler; tsa.sa_flags = VKI_SA_SIGINFO; @@ -2297,7 +2364,8 @@ void VG_(sigstartup_actions) ( void ) break; } - ret = VG_(sigaction)(i, &sa, NULL); + VG_(convert_sigaction_fromK_to_toK)( &sa, &sa2 ); + ret = VG_(sigaction)(i, &sa2, NULL); vg_assert(ret == 0); } @@ -2310,10 +2378,13 @@ void VG_(sigstartup_actions) ( void ) scss.scss_per_sig[i].scss_handler = sa.ksa_handler; scss.scss_per_sig[i].scss_flags = sa.sa_flags; scss.scss_per_sig[i].scss_mask = sa.sa_mask; - scss.scss_per_sig[i].scss_restorer = 0; + + scss.scss_per_sig[i].scss_restorer = NULL; # if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5) scss.scss_per_sig[i].scss_restorer = sa.sa_restorer; # endif + + scss.scss_per_sig[i].scss_sa_tramp = NULL; } if (VG_(clo_trace_signals)) diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c index 676254a5ab..0970e6b837 100644 --- a/coregrind/m_syscall.c +++ b/coregrind/m_syscall.c @@ -37,7 +37,9 @@ Building syscall return values. ------------------------------------------------------------------ */ -/* Make a SysRes value from an syscall return value. This is +#if defined(VGO_linux) + +/* Make a SysRes value from a syscall return value. This is Linux-specific. From: @@ -56,29 +58,26 @@ syscall returns a value in -1 .. -4095 as a valid result so we can safely test with -4095. */ -SysRes VG_(mk_SysRes_x86_linux) ( UInt val ) { + +SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { SysRes res; - res.isError = val >= -4095 && val <= -1; - if (res.isError) { - res.err = -val; - res.res = 0; + res._isError = val >= -4095 && val <= -1; + if (res._isError) { + res._val = (UInt)(-val); } else { - res.err = 0; - res.res = val; + res._val = (UInt)val; } return res; } /* Similarly .. */ -SysRes VG_(mk_SysRes_amd64_linux) ( ULong val ) { +SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) { SysRes res; - res.isError = val >= -4095 && val <= -1; - if (res.isError) { - res.err = -val; - res.res = 0; + res._isError = val >= -4095 && val <= -1; + if (res._isError) { + res._val = (ULong)(-val); } else { - res.err = 0; - res.res = val; + res._val = (ULong)val; } return res; } @@ -87,31 +86,37 @@ SysRes VG_(mk_SysRes_amd64_linux) ( ULong val ) { /* Note this must be in the bottom bit of the second arg */ SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) { SysRes res; - res.isError = (cr0so & 1) != 0; - if (res.isError) { - res.err = val; - res.res = 0; - } else { - res.err = 0; - res.res = val; - } + res._isError = (cr0so & 1) != 0; + res._val = val; return res; } /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */ SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) { SysRes res; - res.isError = (cr0so & 1) != 0; - if (res.isError) { - res.err = val; - res.res = 0; - } else { - res.err = 0; - res.res = val; - } + res._isError = (cr0so & 1) != 0; + res._val = val; return res; } +/* Generic constructors. */ +SysRes VG_(mk_SysRes_Error) ( UWord err ) { + SysRes r; + r._isError = True; + r._val = err; + return r; +} + +SysRes VG_(mk_SysRes_Success) ( UWord res ) { + SysRes r; + r._isError = False; + r._val = res; + return r; +} + + +#elif defined(VGO_aix5) + /* AIX scheme: we have to record both 'res' (r3) and 'err' (r4). If 'err' is nonzero then the call has failed, but it could still be that AIX userspace will ignore 'err' and instead consult 'res' to @@ -135,23 +140,28 @@ SysRes VG_(mk_SysRes_ppc64_aix5) ( ULong res, ULong err ) { /* Generic constructors. */ SysRes VG_(mk_SysRes_Error) ( UWord err ) { SysRes r; - r.res = 0; - r.err = err; - r.isError = True; + r._res = 0; + r._err = err; + r._isError = True; return r; } SysRes VG_(mk_SysRes_Success) ( UWord res ) { SysRes r; - r.res = res; - r.err = 0; - r.isError = False; + r._res = res; + r._err = 0; + r._isError = False; return r; } +#else +# error "Unknown OS" +#endif + + /* --------------------------------------------------------------------- - A function for doing syscalls. + VG_(do_syscall): A function for doing syscalls. ------------------------------------------------------------------ */ #if defined(VGP_x86_linux) @@ -268,7 +278,7 @@ asm( different from the ppc32 case. The single arg register points to a 7-word block containing the syscall # and the 6 args. The syscall result proper is put in [0] of the block, and %cr0.so is in the - bottom but of [1]. */ + bottom bit of [1]. */ extern void do_syscall_WRK ( ULong* argblock ); asm( ".align 2\n" @@ -455,37 +465,40 @@ static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4, #endif +/* Finally, the generic code. This sends the call to the right + helper. */ + SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, UWord a6, UWord a7, UWord a8 ) { -#if defined(VGP_x86_linux) - UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); - return VG_(mk_SysRes_x86_linux)( val ); - -#elif defined(VGP_amd64_linux) - UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); - return VG_(mk_SysRes_amd64_linux)( val ); - -#elif defined(VGP_ppc32_linux) - ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); - UInt val = (UInt)(ret>>32); - UInt cr0so = (UInt)(ret); - return VG_(mk_SysRes_ppc32_linux)( val, cr0so ); - -#elif defined(VGP_ppc64_linux) - ULong argblock[7]; - argblock[0] = sysno; - argblock[1] = a1; - argblock[2] = a2; - argblock[3] = a3; - argblock[4] = a4; - argblock[5] = a5; - argblock[6] = a6; - do_syscall_WRK( &argblock[0] ); - return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] ); - -#elif defined(VGP_ppc32_aix5) +# if defined(VGP_x86_linux) + UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); + return VG_(mk_SysRes_x86_linux)( val ); + +# elif defined(VGP_amd64_linux) + UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); + return VG_(mk_SysRes_amd64_linux)( val ); + +# elif defined(VGP_ppc32_linux) + ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); + UInt val = (UInt)(ret>>32); + UInt cr0so = (UInt)(ret); + return VG_(mk_SysRes_ppc32_linux)( val, cr0so ); + +# elif defined(VGP_ppc64_linux) + ULong argblock[7]; + argblock[0] = sysno; + argblock[1] = a1; + argblock[2] = a2; + argblock[3] = a3; + argblock[4] = a4; + argblock[5] = a5; + argblock[6] = a6; + do_syscall_WRK( &argblock[0] ); + return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] ); + +# elif defined(VGP_ppc32_aix5) UWord res; UWord err; do_syscall_WRK( &res, &err, @@ -502,10 +515,9 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, if (res == 0) err = 0; } - return VG_(mk_SysRes_ppc32_aix5)( res, err ); -#elif defined(VGP_ppc64_aix5) +# elif defined(VGP_ppc64_aix5) UWord res; UWord err; do_syscall_WRK( &res, &err, @@ -522,7 +534,6 @@ SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, if (res == 0) err = 0; } - return VG_(mk_SysRes_ppc64_aix5)( res, err ); #else @@ -556,7 +567,9 @@ const HChar* VG_(strerror) ( UWord errnum ) case VKI_EMFILE: return "Too many open files"; case VKI_ENOSYS: return "Function not implemented"; case VKI_EOVERFLOW: return "Value too large for defined data type"; +# if defined(VKI_ERESTARTSYS) case VKI_ERESTARTSYS: return "ERESTARTSYS"; +# endif default: return "VG_(strerror): unknown error"; } } diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h index 28c0ab95e1..bdb4b4fc60 100644 --- a/coregrind/m_syswrap/priv_types_n_macros.h +++ b/coregrind/m_syswrap/priv_types_n_macros.h @@ -81,6 +81,18 @@ typedef typedef struct { Int o_sysno; +# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ + || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) + Int o_arg1; + Int o_arg2; + Int o_arg3; + Int o_arg4; + Int o_arg5; + Int o_arg6; + Int uu_arg7; + Int uu_arg8; + Int o_retval; +# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) Int o_arg1; Int o_arg2; Int o_arg3; @@ -90,6 +102,9 @@ typedef Int o_arg7; Int o_arg8; Int o_retval; +# else +# error "Unknown platform" +# endif } SyscallArgLayout; @@ -274,22 +289,29 @@ SyscallTableEntry* ML_(get_ppc64_aix5_syscall_entry) ( UInt sysno ); /* Reference to the syscall's current result status/value. General paranoia all round. */ -#define SUCCESS (status->what == SsComplete && !status->sres.isError) -#define FAILURE (status->what == SsComplete && status->sres.isError) +#define SUCCESS (status->what == SsComplete && !sr_isError(status->sres)) +#define FAILURE (status->what == SsComplete && sr_isError(status->sres)) #define SWHAT (status->what) #define RES (getRES(status)) +#define RESHI (getRESHI(status)) #define ERR (getERR(status)) static inline UWord getRES ( SyscallStatus* st ) { vg_assert(st->what == SsComplete); - vg_assert(!st->sres.isError); - return st->sres.res; + vg_assert(!sr_isError(st->sres)); + return sr_Res(st->sres); +} + +static inline UWord getRESHI ( SyscallStatus* st ) { + vg_assert(st->what == SsComplete); + vg_assert(!sr_isError(st->sres)); + return sr_ResHI(st->sres); } static inline UWord getERR ( SyscallStatus* st ) { vg_assert(st->what == SsComplete); - vg_assert(st->sres.isError); - return st->sres.err; + vg_assert(sr_isError(st->sres)); + return sr_Err(st->sres); } diff --git a/coregrind/m_syswrap/syscall-amd64-linux.S b/coregrind/m_syswrap/syscall-amd64-linux.S index b6f913a009..c539f885fe 100644 --- a/coregrind/m_syswrap/syscall-amd64-linux.S +++ b/coregrind/m_syswrap/syscall-amd64-linux.S @@ -66,7 +66,7 @@ void* guest_state, // rsi const vki_sigset_t *sysmask, // rdx const vki_sigset_t *postmask, // rcx - Int nsigwords) // r8 + Int sigsetSzB) // r8 */ @@ -113,7 +113,7 @@ ML_(do_syscall_for_client_WRK): movq $VKI_SIG_SETMASK, %rdi // how movq %rdx, %rsi // sysmask movq %rcx, %rdx // postmask - movq %r8, %r10 // nsigwords + movq %r8, %r10 // sigsetSzB syscall POP_di_si_dx_cx_8 @@ -155,7 +155,7 @@ ML_(do_syscall_for_client_WRK): movq $VKI_SIG_SETMASK, %rdi // how movq %rcx, %rsi // postmask xorq %rdx, %rdx // NULL - movq %r8, %r10 // nsigwords + movq %r8, %r10 // sigsetSzB syscall POP_di_si_dx_cx_8 diff --git a/coregrind/m_syswrap/syscall-ppc32-aix5.S b/coregrind/m_syswrap/syscall-ppc32-aix5.S index b1e1a19e8f..c5dbcdd6a4 100644 --- a/coregrind/m_syswrap/syscall-ppc32-aix5.S +++ b/coregrind/m_syswrap/syscall-ppc32-aix5.S @@ -72,7 +72,7 @@ void* guest_state, // r4 const vki_sigset_t *sysmask, // r5 const vki_sigset_t *postmask, // r6 - Int nsigwords, // r7 + Int sigsetSzB, // r7 Int __nr_sigprocmask) // r8 */ .file "syscall-ppc32-aix6.S" @@ -101,7 +101,7 @@ ML_(do_syscall_for_client_WRK): mr 31,3 /* syscall number */ mr 30,4 /* guest_state */ mr 29,6 /* postmask */ - mr 28,7 /* nsigwords */ + mr 28,7 /* sigsetSzB */ mr 27,8 /* __nr_sigprocmask */ Lvg1: /* Even though we can't take a signal until the sigprocmask @@ -114,7 +114,7 @@ Lvg1: /* Even though we can't take a signal until the sigprocmask li 3,VKI_SIG_SETMASK mr 4,5 mr 5,6 - mr 6,7 /* nsigwords -- needed on AIX ? */ + mr 6,7 /* sigsetSzB -- needed on AIX ? */ /* actually do the sigprocmask */ crorc 6,6,6 @@ -164,7 +164,7 @@ Lvg4: mr 2,27 li 3,VKI_SIG_SETMASK mr 4,29 li 5,0 - mr 6,28 /* nsigwords -- needed on AIX ? */ + mr 6,28 /* sigsetSzB -- needed on AIX ? */ /* actually do the sigprocmask */ crorc 6,6,6 diff --git a/coregrind/m_syswrap/syscall-ppc32-linux.S b/coregrind/m_syswrap/syscall-ppc32-linux.S index a88dcc3f00..48b174d1c9 100644 --- a/coregrind/m_syswrap/syscall-ppc32-linux.S +++ b/coregrind/m_syswrap/syscall-ppc32-linux.S @@ -66,7 +66,7 @@ void* guest_state, // r4 const vki_sigset_t *sysmask, // r5 const vki_sigset_t *postmask, // r6 - Int nsigwords) // r7 + Int sigsetSzB) // r7 */ /* from vki_arch.h */ #define VKI_SIG_SETMASK 2 @@ -82,7 +82,7 @@ ML_(do_syscall_for_client_WRK): mr 31,3 /* syscall number */ mr 30,4 /* guest_state */ mr 29,6 /* postmask */ - mr 28,7 /* nsigwords */ + mr 28,7 /* sigsetSzB */ /* set the signal mask for doing the system call */ /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */ diff --git a/coregrind/m_syswrap/syscall-ppc64-aix5.S b/coregrind/m_syswrap/syscall-ppc64-aix5.S index bbf3909e07..5d308e171e 100644 --- a/coregrind/m_syswrap/syscall-ppc64-aix5.S +++ b/coregrind/m_syswrap/syscall-ppc64-aix5.S @@ -72,7 +72,7 @@ void* guest_state, // r4 const vki_sigset_t *sysmask, // r5 const vki_sigset_t *postmask, // r6 - Int nsigwords, // r7 + Int sigsetSzB, // r7 Int __nr_sigprocmask) // r8 */ .file "syscall-ppc64-aix6.S" @@ -101,7 +101,7 @@ ML_(do_syscall_for_client_WRK): mr 31,3 /* syscall number */ mr 30,4 /* guest_state */ mr 29,6 /* postmask */ - mr 28,7 /* nsigwords */ + mr 28,7 /* sigsetSzB */ mr 27,8 /* __nr_sigprocmask */ Lvg1: /* Even though we can't take a signal until the sigprocmask @@ -114,7 +114,7 @@ Lvg1: /* Even though we can't take a signal until the sigprocmask li 3,VKI_SIG_SETMASK mr 4,5 mr 5,6 - mr 6,7 /* nsigwords -- needed on AIX ? */ + mr 6,7 /* sigsetSzB -- needed on AIX ? */ /* actually do the sigprocmask */ crorc 6,6,6 @@ -164,7 +164,7 @@ Lvg4: mr 2,27 li 3,VKI_SIG_SETMASK mr 4,29 li 5,0 - mr 6,28 /* nsigwords -- needed on AIX ? */ + mr 6,28 /* sigsetSzB -- needed on AIX ? */ /* actually do the sigprocmask */ crorc 6,6,6 diff --git a/coregrind/m_syswrap/syscall-ppc64-linux.S b/coregrind/m_syswrap/syscall-ppc64-linux.S index 5e17995e3b..479300b4a4 100644 --- a/coregrind/m_syswrap/syscall-ppc64-linux.S +++ b/coregrind/m_syswrap/syscall-ppc64-linux.S @@ -66,7 +66,7 @@ void* guest_state, // r4 const vki_sigset_t *sysmask, // r5 const vki_sigset_t *postmask, // r6 - Int nsigwords) // r7 + Int sigsetSzB) // r7 */ /* from vki_arch.h */ #define VKI_SIG_SETMASK 2 @@ -90,7 +90,7 @@ ML_(do_syscall_for_client_WRK): mr 31,3 /* syscall number */ mr 30,4 /* guest_state */ mr 29,6 /* postmask */ - mr 28,7 /* nsigwords */ + mr 28,7 /* sigsetSzB */ /* set the signal mask for doing the system call */ /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */ diff --git a/coregrind/m_syswrap/syscall-x86-linux.S b/coregrind/m_syswrap/syscall-x86-linux.S index 4806f5178f..d7001891d2 100644 --- a/coregrind/m_syswrap/syscall-x86-linux.S +++ b/coregrind/m_syswrap/syscall-x86-linux.S @@ -67,7 +67,7 @@ void* guest_state, // 4 const vki_sigset_t *sysmask, // 8 const vki_sigset_t *postmask, // 12 - Int nsigwords) // 16 + Int sigsetSzB) // 16 */ diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 995d067ba3..27e158bc92 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -297,7 +297,7 @@ static SysRes do_clone ( ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); out: - if (res.isError) { + if (sr_isError(res)) { /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 4d0326237c..5871bc3669 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -481,7 +481,7 @@ SysRes do_mremap( Addr old_addr, SizeT old_len, shrink_in_place: { SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len ); - if (sres.isError) + if (sr_isError(sres)) return sres; VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len ); if (d) @@ -765,12 +765,12 @@ void VG_(init_preopened_fds)(void) SysRes f; f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0); - if (f.isError) { + if (sr_isError(f)) { init_preopened_fds_without_proc_self_fd(); return; } - while ((ret = VG_(getdents)(f.res, &d, sizeof(d))) != 0) { + while ((ret = VG_(getdents)(sr_Res(f), &d, sizeof(d))) != 0) { if (ret == -1) goto out; @@ -778,7 +778,7 @@ void VG_(init_preopened_fds)(void) Char* s; Int fno = VG_(strtoll10)(d.d_name, &s); if (*s == '\0') { - if (fno != f.res) + if (fno != sr_Res(f)) if (VG_(clo_track_fds)) ML_(record_fd_open_named)(-1, fno); } else { @@ -787,11 +787,11 @@ void VG_(init_preopened_fds)(void) } } - VG_(lseek)(f.res, d.d_off, VKI_SEEK_SET); + VG_(lseek)(sr_Res(f), d.d_off, VKI_SEEK_SET); } out: - VG_(close)(f.res); + VG_(close)(sr_Res(f)); #else # error Unknown OS @@ -985,7 +985,8 @@ void ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p, if (VG_(tdict).track_pre_mem_write) { UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s); if (buflen_in > 0) { - VG_(tdict).track_pre_mem_write( Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in ); + VG_(tdict).track_pre_mem_write( + Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in ); } } } @@ -993,7 +994,7 @@ void ML_(buf_and_len_pre_check) ( ThreadId tid, Addr buf_p, Addr buflen_p, void ML_(buf_and_len_post_check) ( ThreadId tid, SysRes res, Addr buf_p, Addr buflen_p, Char* s ) { - if (!res.isError && VG_(tdict).track_post_mem_write) { + if (!sr_isError(res) && 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 ); @@ -1216,7 +1217,7 @@ ML_(generic_POST_sys_socketpair) ( ThreadId tid, SysRes r = res; Int fd1 = ((Int*)arg3)[0]; Int fd2 = ((Int*)arg3)[1]; - vg_assert(!res.isError); /* guaranteed by caller */ + vg_assert(!sr_isError(res)); /* guaranteed by caller */ POST_MEM_WRITE( arg3, 2*sizeof(int) ); if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) || !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) { @@ -1239,13 +1240,13 @@ SysRes ML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res ) { SysRes r = res; - vg_assert(!res.isError); /* guaranteed by caller */ - if (!ML_(fd_allowed)(res.res, "socket", tid, True)) { - VG_(close)(res.res); + vg_assert(!sr_isError(res)); /* guaranteed by caller */ + if (!ML_(fd_allowed)(sr_Res(res), "socket", tid, True)) { + VG_(close)(sr_Res(res)); r = VG_(mk_SysRes_Error)( VKI_EMFILE ); } else { if (VG_(clo_track_fds)) - ML_(record_fd_open_nameless)(tid, res.res); + ML_(record_fd_open_nameless)(tid, sr_Res(res)); } return r; } @@ -1285,9 +1286,9 @@ ML_(generic_POST_sys_accept) ( ThreadId tid, UWord arg0, UWord arg1, UWord arg2 ) { SysRes r = res; - vg_assert(!res.isError); /* guaranteed by caller */ - if (!ML_(fd_allowed)(res.res, "accept", tid, True)) { - VG_(close)(res.res); + vg_assert(!sr_isError(res)); /* guaranteed by caller */ + if (!ML_(fd_allowed)(sr_Res(res), "accept", tid, True)) { + VG_(close)(sr_Res(res)); r = VG_(mk_SysRes_Error)( VKI_EMFILE ); } else { Addr addr_p = arg1; @@ -1296,7 +1297,7 @@ ML_(generic_POST_sys_accept) ( ThreadId tid, ML_(buf_and_len_post_check) ( tid, res, addr_p, addrlen_p, "socketcall.accept(addrlen_out)" ); if (VG_(clo_track_fds)) - ML_(record_fd_open_nameless)(tid, res.res); + ML_(record_fd_open_nameless)(tid, sr_Res(res)); } return r; } @@ -1364,7 +1365,7 @@ ML_(generic_POST_sys_recvfrom) ( ThreadId tid, Addr from_p = arg4; Addr fromlen_p = arg5; - vg_assert(!res.isError); /* guaranteed by caller */ + vg_assert(!sr_isError(res)); /* guaranteed by caller */ if (from_p != (Addr)NULL) ML_(buf_and_len_post_check) ( tid, res, from_p, fromlen_p, "socketcall.recvfrom(fromlen_out)" ); @@ -1451,7 +1452,7 @@ ML_(generic_POST_sys_getsockname) ( ThreadId tid, { Addr name_p = arg1; Addr namelen_p = arg2; - vg_assert(!res.isError); /* guaranteed by caller */ + vg_assert(!sr_isError(res)); /* guaranteed by caller */ ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p, "socketcall.getsockname(namelen_out)" ); } @@ -1478,7 +1479,7 @@ ML_(generic_POST_sys_getpeername) ( ThreadId tid, { Addr name_p = arg1; Addr namelen_p = arg2; - vg_assert(!res.isError); /* guaranteed by caller */ + vg_assert(!sr_isError(res)); /* guaranteed by caller */ ML_(buf_and_len_post_check) ( tid, res, name_p, namelen_p, "socketcall.getpeername(namelen_out)" ); } @@ -1565,7 +1566,7 @@ UInt get_sem_count( Int semid ) res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, VKI_IPC_STAT, (UWord)&arg); # endif - if (res.isError) + if (sr_isError(res)) return 0; return buf.sem_nsems; @@ -1658,15 +1659,20 @@ ML_(generic_POST_sys_semctl) ( ThreadId tid, static UInt get_shm_size ( Int shmid ) { -# ifdef __NR_shmctl +#ifdef __NR_shmctl +# ifdef VKI_IPC_64 struct vki_shmid64_ds buf; SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf); # else + struct vki_shmid_ds buf; + SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf); +# endif +#else struct vki_shmid_ds buf; SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, VKI_IPC_STAT, 0, (UWord)&buf); -# endif - if (__res.isError) +#endif + if (sr_isError(__res)) return 0; return buf.shm_segsz; @@ -1916,7 +1922,7 @@ ML_(generic_PRE_sys_mmap) ( ThreadId tid, of address. If we were originally asked for a hinted mapping, there is still a last chance: try again at any address. Hence: */ - if (mreq.rkind == MHint && sres.isError) { + if (mreq.rkind == MHint && sr_isError(sres)) { mreq.start = 0; mreq.len = arg2; mreq.rkind = MAny; @@ -1931,11 +1937,11 @@ ML_(generic_PRE_sys_mmap) ( ThreadId tid, arg5, arg6); } - if (!sres.isError) { + if (!sr_isError(sres)) { ULong di_handle; /* Notify aspacem. */ notify_core_of_mmap( - (Addr)sres.res, /* addr kernel actually assigned */ + (Addr)sr_Res(sres), /* addr kernel actually assigned */ arg2, /* length */ arg3, /* prot */ arg4, /* the original flags value */ @@ -1943,10 +1949,11 @@ ML_(generic_PRE_sys_mmap) ( ThreadId tid, arg6 /* offset */ ); /* Load symbols? */ - di_handle = VG_(di_notify_mmap)( (Addr)sres.res, False/*allow_SkFileV*/ ); + di_handle = VG_(di_notify_mmap)( (Addr)sr_Res(sres), + False/*allow_SkFileV*/ ); /* Notify the tool. */ notify_tool_of_mmap( - (Addr)sres.res, /* addr kernel actually assigned */ + (Addr)sr_Res(sres), /* addr kernel actually assigned */ arg2, /* length */ arg3, /* prot */ di_handle /* so the tool can refer to the read debuginfo later, @@ -1955,8 +1962,8 @@ ML_(generic_PRE_sys_mmap) ( ThreadId tid, } /* Stay sane */ - if (!sres.isError && (arg4 & VKI_MAP_FIXED)) - vg_assert(sres.res == arg1); + if (!sr_isError(sres) && (arg4 & VKI_MAP_FIXED)) + vg_assert(sr_Res(sres) == arg1); return sres; } @@ -2429,8 +2436,8 @@ PRE(sys_execve) // we are not simulating them, that is, they to be run natively. setuid_allowed = VG_(clo_trace_children) ? False : True; res = VG_(pre_exec_check)((const Char*)ARG1, NULL, setuid_allowed); - if (res.isError) { - SET_STATUS_Failure( res.err ); + if (sr_isError(res)) { + SET_STATUS_Failure( sr_Err(res) ); return; } @@ -2572,14 +2579,20 @@ PRE(sys_execve) vki_sigset_t allsigs; vki_siginfo_t info; + /* What this loop does: it queries SCSS (the signal state that + the client _thinks_ the kernel is in) by calling + VG_(do_sys_sigaction), and modifies the real kernel signal + state accordingly. */ for (i = 1; i < VG_(max_signal); i++) { - struct vki_sigaction sa; - VG_(do_sys_sigaction)(i, NULL, &sa); - if (sa.ksa_handler == VKI_SIG_IGN) - VG_(sigaction)(i, &sa, NULL); + vki_sigaction_fromK_t sa_f; + vki_sigaction_toK_t sa_t; + VG_(do_sys_sigaction)(i, NULL, &sa_f); + VG_(convert_sigaction_fromK_to_toK)(&sa_f, &sa_t); + if (sa_t.ksa_handler == VKI_SIG_IGN) + VG_(sigaction)(i, &sa_t, NULL); else { - sa.ksa_handler = VKI_SIG_DFL; - VG_(sigaction)(i, &sa, NULL); + sa_t.ksa_handler = VKI_SIG_DFL; + VG_(sigaction)(i, &sa_t, NULL); } } @@ -2792,6 +2805,7 @@ static vki_sigset_t fork_saved_mask; // ignore the various args it gets, and so it looks arch-neutral. Hmm. PRE(sys_fork) { + UWord result; vki_sigset_t mask; PRINT("sys_fork ( )"); @@ -2804,6 +2818,10 @@ PRE(sys_fork) SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) ); + if (!SUCCESS) return; + + result = RES; + VG_(do_atfork_pre)(tid); if (SUCCESS && RES == 0) { @@ -3148,7 +3166,11 @@ PRE(sys_kill) if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) SET_STATUS_Success(0); else - SET_STATUS_from_SysRes( VG_(do_syscall2)(SYSNO, ARG1, ARG2) ); + /* re syscall3: Darwin has a 3rd arg, which is a flag (boolean) + affecting how posix-compliant the call is. I guess it is + harmless to pass the 3rd arg on other platforms; hence pass + it on all. */ + SET_STATUS_from_SysRes( VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3) ); if (VG_(clo_trace_signals)) VG_(message)(Vg_DebugMsg, "kill: sent signal %ld to pid %ld", @@ -3341,8 +3363,8 @@ PRE(sys_open) || VG_(strcmp)((Char *)ARG1, "/proc/self/cmdline") == 0)) { sres = VG_(dup)( VG_(cl_cmdline_fd) ); SET_STATUS_from_SysRes( sres ); - if (!sres.isError) { - OffT off = VG_(lseek)( sres.res, 0, VKI_SEEK_SET ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); if (off < 0) SET_STATUS_Failure( VKI_EMFILE ); } @@ -3848,7 +3870,6 @@ PRE(sys_pause) PRE_REG_READ0(long, "pause"); } -// XXX: x86-specific PRE(sys_sigaltstack) { PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2); diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index a1023a1773..a753a2ad69 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -331,7 +331,7 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, # error Unknown platform #endif - if (!res.isError && res.res == 0) { + if (!sr_isError(res) && sr_Res(res) == 0) { /* child */ VG_(do_atfork_child)(tid); @@ -346,13 +346,13 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, VG_(clo_log_fd) = -1; } else - if (!res.isError && res.res > 0) { + if (!sr_isError(res) && sr_Res(res) > 0) { /* parent */ VG_(do_atfork_parent)(tid); if (VG_(clo_trace_syscalls)) VG_(printf)(" clone(fork): process %d created child %ld\n", - VG_(getpid)(), res.res); + VG_(getpid)(), sr_Res(res)); /* restore signal mask */ VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL); @@ -1744,9 +1744,9 @@ static Bool linux_kernel_2_6_22(void) if (result == -1) { res = VG_(open)("/proc/sys/kernel/osrelease", 0, 0); - if (res.isError) + if (sr_isError(res)) return False; - fd = res.res; + fd = sr_Res(res); read = VG_(read)(fd, release, sizeof(release) - 1); vg_assert(read >= 0); release[read] = 0; @@ -2482,7 +2482,7 @@ PRE(sys_rt_sigaction) struct sigaction *, oldact, vki_size_t, sigsetsize); if (ARG2 != 0) { - struct vki_sigaction *sa = (struct vki_sigaction *)ARG2; + vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2; PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); @@ -2490,22 +2490,22 @@ PRE(sys_rt_sigaction) PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer)); } if (ARG3 != 0) - PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(struct vki_sigaction)); + PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(vki_sigaction_fromK_t)); // XXX: doesn't seem right to be calling do_sys_sigaction for // sys_rt_sigaction... perhaps this function should be renamed // VG_(do_sys_rt_sigaction)() --njn SET_STATUS_from_SysRes( - VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2, - (struct vki_sigaction *)ARG3) + VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, + (vki_sigaction_fromK_t *)ARG3) ); } POST(sys_rt_sigaction) { vg_assert(SUCCESS); if (RES == 0 && ARG3 != 0) - POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction)); + POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t)); } PRE(sys_rt_sigprocmask) @@ -2735,8 +2735,8 @@ PRE(sys_openat) || VG_(strcmp)((Char *)ARG2, "/proc/self/cmdline") == 0)) { sres = VG_(dup)( VG_(cl_cmdline_fd) ); SET_STATUS_from_SysRes( sres ); - if (!sres.isError) { - OffT off = VG_(lseek)( sres.res, 0, VKI_SEEK_SET ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); if (off < 0) SET_STATUS_Failure( VKI_EMFILE ); } @@ -5217,7 +5217,7 @@ ML_(linux_POST_sys_getsockopt) ( ThreadId tid, { Addr optval_p = arg3; Addr optlen_p = arg4; - vg_assert(!res.isError); /* guaranteed by caller */ + vg_assert(!sr_isError(res)); /* guaranteed by caller */ if (optval_p != (Addr)NULL) { ML_(buf_and_len_post_check) ( tid, res, optval_p, optlen_p, "socketcall.getsockopt(optlen_out)" ); diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c index 63a03f6e3f..3e589e3074 100644 --- a/coregrind/m_syswrap/syswrap-main.c +++ b/coregrind/m_syswrap/syswrap-main.c @@ -232,17 +232,33 @@ in coregrind/m_syswrap/syscall-$PLAT.S. It has some very magic properties. See comments at the top of VG_(fixup_guest_state_after_syscall_interrupted) below for details. + + This function (these functions) are required to return zero in case + of success (even if the syscall itself failed), and nonzero if the + sigprocmask-swizzling calls failed. We don't actually care about + the failure values from sigprocmask, although most of the assembly + implementations do attempt to return that, using the convention + 0 for success, or 0x8000 | error-code for failure. */ +#if defined(VGO_linux) +extern +UWord ML_(do_syscall_for_client_WRK)( Word syscallno, + void* guest_state, + const vki_sigset_t *syscall_mask, + const vki_sigset_t *restore_mask, + Word sigsetSzB ); +#elif defined(VGO_aix5) extern UWord ML_(do_syscall_for_client_WRK)( Word syscallno, void* guest_state, const vki_sigset_t *syscall_mask, const vki_sigset_t *restore_mask, - Word nsigwords -# if defined(VGO_aix5) - , Word __nr_sigprocmask -# endif - ); + Word sigsetSzB, /* unused */ + Word __nr_sigprocmask ); +#else +# error "Unknown OS" +#endif + static void do_syscall_for_client ( Int syscallno, @@ -250,14 +266,21 @@ void do_syscall_for_client ( Int syscallno, const vki_sigset_t* syscall_mask ) { vki_sigset_t saved; - UWord err - = ML_(do_syscall_for_client_WRK)( - syscallno, &tst->arch.vex, - syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord) -# if defined(VGO_aix5) - , __NR_rt_sigprocmask -# endif - ); + UWord err; +# if defined(VGO_linux) + err = ML_(do_syscall_for_client_WRK)( + syscallno, &tst->arch.vex, + syscall_mask, &saved, sizeof(vki_sigset_t) + ); +# elif defined(VGO_aix5) + err = ML_(do_syscall_for_client_WRK)( + syscallno, &tst->arch.vex, + syscall_mask, &saved, 0/*unused:sigsetSzB*/, + __NR_rt_sigprocmask + ); +# else +# error "Unknown OS" +# endif vg_assert2( err == 0, "ML_(do_syscall_for_client_WRK): sigprocmask error %d", @@ -266,7 +289,6 @@ void do_syscall_for_client ( Int syscallno, } - /* --------------------------------------------------------------------- Impedance matchers and misc helpers ------------------------------------------------------------------ */ @@ -288,12 +310,12 @@ Bool eq_SyscallArgs ( SyscallArgs* a1, SyscallArgs* a2 ) static Bool eq_SyscallStatus ( SyscallStatus* s1, SyscallStatus* s2 ) { - return s1->what == s2->what - && s1->sres.res == s2->sres.res - && s1->sres.err == s2->sres.err; + /* was: return s1->what == s2->what && sr_EQ( s1->sres, s2->sres ); */ + if (s1->what == s2->what && sr_EQ( s1->sres, s2->sres )) + return True; + return False; } - /* Convert between SysRes and SyscallStatus, to the extent possible. */ static @@ -519,53 +541,53 @@ void putSyscallStatusIntoGuestState ( /*IN*/ SyscallStatus* canonical, # if defined(VGP_x86_linux) VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; vg_assert(canonical->what == SsComplete); - if (canonical->sres.isError) { + if (sr_isError(canonical->sres)) { /* 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->sres.err; + gst->guest_EAX = - (Int)sr_Err(canonical->sres); } else { - gst->guest_EAX = canonical->sres.res; + gst->guest_EAX = sr_Res(canonical->sres); } # elif defined(VGP_amd64_linux) VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; vg_assert(canonical->what == SsComplete); - if (canonical->sres.isError) { + if (sr_isError(canonical->sres)) { /* 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_RAX = - (Long)canonical->sres.err; + gst->guest_RAX = - (Long)sr_Err(canonical->sres); } else { - gst->guest_RAX = canonical->sres.res; + gst->guest_RAX = sr_Res(canonical->sres); } # elif defined(VGP_ppc32_linux) VexGuestPPC32State* gst = (VexGuestPPC32State*)gst_vanilla; UInt old_cr = LibVEX_GuestPPC32_get_CR(gst); vg_assert(canonical->what == SsComplete); - if (canonical->sres.isError) { + if (sr_isError(canonical->sres)) { /* set CR0.SO */ LibVEX_GuestPPC32_put_CR( old_cr | (1<<28), gst ); - gst->guest_GPR3 = canonical->sres.err; + gst->guest_GPR3 = sr_Err(canonical->sres); } else { /* clear CR0.SO */ LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), gst ); - gst->guest_GPR3 = canonical->sres.res; + gst->guest_GPR3 = sr_Res(canonical->sres); } # elif defined(VGP_ppc64_linux) VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla; UInt old_cr = LibVEX_GuestPPC64_get_CR(gst); vg_assert(canonical->what == SsComplete); - if (canonical->sres.isError) { + if (sr_isError(canonical->sres)) { /* set CR0.SO */ LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst ); - gst->guest_GPR3 = canonical->sres.err; + gst->guest_GPR3 = sr_Err(canonical->sres); } else { /* clear CR0.SO */ LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst ); - gst->guest_GPR3 = canonical->sres.res; + gst->guest_GPR3 = sr_Res(canonical->sres); } # elif defined(VGP_ppc32_aix5) @@ -601,8 +623,8 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->o_arg4 = OFFSET_x86_ESI; layout->o_arg5 = OFFSET_x86_EDI; layout->o_arg6 = OFFSET_x86_EBP; - layout->o_arg7 = -1; /* impossible value */ - layout->o_arg8 = -1; /* impossible value */ + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ layout->o_retval = OFFSET_x86_EAX; #elif defined(VGP_amd64_linux) @@ -613,8 +635,8 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->o_arg4 = OFFSET_amd64_R10; layout->o_arg5 = OFFSET_amd64_R8; layout->o_arg6 = OFFSET_amd64_R9; - layout->o_arg7 = -1; /* impossible value */ - layout->o_arg8 = -1; /* impossible value */ + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ layout->o_retval = OFFSET_amd64_RAX; #elif defined(VGP_ppc32_linux) @@ -625,8 +647,8 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->o_arg4 = OFFSET_ppc32_GPR6; layout->o_arg5 = OFFSET_ppc32_GPR7; layout->o_arg6 = OFFSET_ppc32_GPR8; - layout->o_arg7 = -1; /* impossible value */ - layout->o_arg8 = -1; /* impossible value */ + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ layout->o_retval = OFFSET_ppc32_GPR3; #elif defined(VGP_ppc64_linux) @@ -637,8 +659,8 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout ) layout->o_arg4 = OFFSET_ppc64_GPR6; layout->o_arg5 = OFFSET_ppc64_GPR7; layout->o_arg6 = OFFSET_ppc64_GPR8; - layout->o_arg7 = -1; /* impossible value */ - layout->o_arg8 = -1; /* impossible value */ + layout->uu_arg7 = -1; /* impossible value */ + layout->uu_arg8 = -1; /* impossible value */ layout->o_retval = OFFSET_ppc64_GPR3; #elif defined(VGP_ppc32_aix5) @@ -956,14 +978,15 @@ void VG_(client_syscall) ( ThreadId tid ) || sci->status.what == SsComplete); vg_assert(sci->args.sysno == sci->orig_args.sysno); - if (sci->status.what == SsComplete && !sci->status.sres.isError) { + if (sci->status.what == SsComplete && !sr_isError(sci->status.sres)) { /* The pre-handler completed the syscall itself, declaring success. */ if (sci->flags & SfNoWriteResult) { PRINT(" --> [pre-success] NoWriteResult\n"); } else { - PRINT(" --> [pre-success] Success(0x%llx)\n", - (ULong)sci->status.sres.res ); + PRINT(" --> [pre-success] Success(0x%llx:0x%llx)\n", + (ULong)sr_ResHI(sci->status.sres), + (ULong)sr_Res(sci->status.sres)); } /* In this case the allowable flags are to ask for a signal-poll and/or a yield after the call. Changing the args isn't @@ -974,9 +997,9 @@ void VG_(client_syscall) ( ThreadId tid ) } else - if (sci->status.what == SsComplete && sci->status.sres.isError) { + if (sci->status.what == SsComplete && sr_isError(sci->status.sres)) { /* The pre-handler decided to fail syscall itself. */ - PRINT(" --> [pre-fail] Failure(0x%llx)\n", (ULong)sci->status.sres.err ); + PRINT(" --> [pre-fail] Failure(0x%llx)\n", (ULong)sr_Err(sci->status.sres)); /* 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. */ @@ -1020,8 +1043,12 @@ void VG_(client_syscall) ( ThreadId tid ) vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex ); - /* Drop the lock */ + /* Drop the bigLock */ VG_(release_BigLock)(tid, VgTs_WaitSys, "VG_(client_syscall)[async]"); + /* Urr. We're now in a race against other threads trying to + acquire the bigLock. I guess that doesn't matter provided + that do_syscall_for_client only touches thread-local + state. */ /* Do the call, which operates directly on the guest state, not on our abstracted copies of the args/result. */ @@ -1043,11 +1070,22 @@ void VG_(client_syscall) ( ThreadId tid ) getSyscallStatusFromGuestState( &sci->status, &tst->arch.vex ); vg_assert(sci->status.what == SsComplete); - PRINT("SYSCALL[%d,%d](%3ld) ... [async] --> %s(0x%llx)\n", - VG_(getpid)(), tid, sysno, - sci->status.sres.isError ? "Failure" : "Success", - sci->status.sres.isError ? (ULong)sci->status.sres.err - : (ULong)sci->status.sres.res ); + /* Be decorative, if required. */ + if (VG_(clo_trace_syscalls)) { + Bool failed = sr_isError(sci->status.sres); + Word tmp_sysno = sysno; + if (failed) { + PRINT("SYSCALL[%d,%d](%5ld) ... [async] --> Failure(0x%llx)\n", + VG_(getpid)(), tid, tmp_sysno, + (ULong)sr_Err(sci->status.sres)); + } else { + PRINT("SYSCALL[%d,%d](%5ld) ... [async] --> " + "Success(0x%llx:0x%llx)\n", + VG_(getpid)(), tid, tmp_sysno, + (ULong)sr_ResHI(sci->status.sres), + (ULong)sr_Res(sci->status.sres) ); + } + } } else { @@ -1064,10 +1102,18 @@ void VG_(client_syscall) ( ThreadId tid ) sci->args.arg7, sci->args.arg8 ); sci->status = convert_SysRes_to_SyscallStatus(sres); - PRINT("[sync] --> %s(0x%llx)\n", - sci->status.sres.isError ? "Failure" : "Success", - sci->status.sres.isError ? (ULong)sci->status.sres.err - : (ULong)sci->status.sres.res ); + /* Be decorative, if required. */ + if (VG_(clo_trace_syscalls)) { + Bool failed = sr_isError(sci->status.sres); + if (failed) { + PRINT("[sync] --> Failure(0x%llx)\n", + (ULong)sr_Err(sci->status.sres) ); + } else { + PRINT("[sync] --> Success(0x%llx:0x%llx)\n", + (ULong)sr_ResHI(sci->status.sres), + (ULong)sr_Res(sci->status.sres) ); + } + } } } @@ -1159,8 +1205,8 @@ void VG_(post_syscall) (ThreadId tid) - Success or (Failure and PostOnFail is set) */ if (ent->after - && ((!sci->status.sres.isError) - || (sci->status.sres.isError + && ((!sr_isError(sci->status.sres)) + || (sr_isError(sci->status.sres) && (sci->flags & SfPostOnFail) ))) { (ent->after)( tid, &sci->args, &sci->status ); @@ -1355,14 +1401,17 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch ) void VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, Addr ip, - UWord sysnum, SysRes sres, 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. */ + printf. + + Furthermore, 'sres' is only used in the case where the syscall + is complete, but the result has not been committed to the guest + state yet. */ static const Bool debug = False; @@ -1372,14 +1421,13 @@ VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, SyscallInfo* sci; if (debug) - VG_(printf)( "interrupted_syscall %d: tid=%d, IP=0x%llx, " + VG_(printf)( "interrupted_syscall: tid=%d, IP=0x%llx, " "restart=%s, sysret.isError=%s, sysret.val=%lld\n", - (Int)sysnum, (Int)tid, (ULong)ip, restart ? "True" : "False", - sres.isError ? "True" : "False", - (Long)(Word)(sres.isError ? sres.err : sres.res) ); + sr_isError(sres) ? "True" : "False", + (Long)(sr_isError(sres) ? sr_Err(sres) : sr_Res(sres)) ); vg_assert(VG_(is_valid_tid)(tid)); vg_assert(tid >= 1 && tid < VG_N_THREADS); diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index 60c2886fad..c2bd8e41bf 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -349,7 +349,7 @@ static SysRes do_clone ( ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); out: - if (res.isError) { + if (sr_isError(res)) { /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; @@ -1379,8 +1379,8 @@ void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set) } PRE(sys_sigaction) { - struct vki_sigaction new, old; - struct vki_sigaction *newp, *oldp; + vki_sigaction_toK_t new, *newp; + vki_sigaction_fromK_t old, *oldp; PRINT("sys_sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); PRE_REG_READ3(int, "sigaction", diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c index 2ee91e4eb7..dc82f4ac10 100644 --- a/coregrind/m_syswrap/syswrap-ppc64-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c @@ -379,7 +379,7 @@ static SysRes do_clone ( ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); out: - if (res.isError) { + if (sr_isError(res)) { /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 6207a54756..d72892ba5d 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -299,7 +299,7 @@ static SysRes do_clone ( ThreadId ptid, ptst->arch.vex.guest_ESP, ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS); res = sys_set_thread_area(ctid, tlsinfo); - if (res.isError) + if (sr_isError(res)) goto out; } @@ -318,7 +318,7 @@ static SysRes do_clone ( ThreadId ptid, VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); out: - if (res.isError) { + if (sr_isError(res)) { /* clone failed */ VG_(cleanup_thread)(&ctst->arch); ctst->status = VgTs_Empty; @@ -1680,8 +1680,8 @@ void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set) } PRE(sys_sigaction) { - struct vki_sigaction new, old; - struct vki_sigaction *newp, *oldp; + vki_sigaction_toK_t new, *newp; + vki_sigaction_fromK_t old, *oldp; PRINT("sys_sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); PRE_REG_READ3(int, "sigaction", @@ -1711,9 +1711,8 @@ PRE(sys_sigaction) if (ARG2 != 0) { struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2; - new.ksa_handler = oldnew->ksa_handler; - new.sa_flags = oldnew->sa_flags; + new.sa_flags = oldnew->sa_flags; new.sa_restorer = oldnew->sa_restorer; convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask); newp = &new; @@ -1723,9 +1722,8 @@ PRE(sys_sigaction) if (ARG3 != 0 && SUCCESS && RES == 0) { struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3; - oldold->ksa_handler = oldp->ksa_handler; - oldold->sa_flags = oldp->sa_flags; + oldold->sa_flags = oldp->sa_flags; oldold->sa_restorer = oldp->sa_restorer; oldold->sa_mask = oldp->sa_mask.sig[0]; } diff --git a/coregrind/m_transtab.c b/coregrind/m_transtab.c index 956e2991b9..a224b48760 100644 --- a/coregrind/m_transtab.c +++ b/coregrind/m_transtab.c @@ -714,21 +714,21 @@ static void initialiseSector ( Int sno ) VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno); sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ ); - if (sres.isError) { + if (sr_isError(sres)) { VG_(out_of_memory_NORETURN)("initialiseSector(TC)", 8 * tc_sector_szQ ); /*NOTREACHED*/ } - sec->tc = (ULong*)sres.res; + sec->tc = (ULong*)(AddrH)sr_Res(sres); sres = VG_(am_mmap_anon_float_valgrind) ( N_TTES_PER_SECTOR * sizeof(TTEntry) ); - if (sres.isError) { + if (sr_isError(sres)) { VG_(out_of_memory_NORETURN)("initialiseSector(TT)", N_TTES_PER_SECTOR * sizeof(TTEntry) ); /*NOTREACHED*/ } - sec->tt = (TTEntry*)sres.res; + sec->tt = (TTEntry*)(AddrH)sr_Res(sres); for (i = 0; i < N_TTES_PER_SECTOR; i++) { sec->tt[i].status = Empty; @@ -1313,12 +1313,14 @@ static void init_unredir_tt_tc ( void ) { Int i; if (unredir_tc == NULL) { - SysRes sres = VG_(am_mmap_anon_float_valgrind)( N_UNREDIR_TT * UNREDIR_SZB ); - if (sres.isError) { - VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", N_UNREDIR_TT * UNREDIR_SZB); + SysRes sres = VG_(am_mmap_anon_float_valgrind) + ( N_UNREDIR_TT * UNREDIR_SZB ); + if (sr_isError(sres)) { + VG_(out_of_memory_NORETURN)("init_unredir_tt_tc", + N_UNREDIR_TT * UNREDIR_SZB); /*NOTREACHED*/ } - unredir_tc = (ULong *)sres.res; + unredir_tc = (ULong *)(AddrH)sr_Res(sres); } unredir_tc_used = 0; for (i = 0; i < N_UNREDIR_TT; i++) diff --git a/coregrind/m_ume/elf.c b/coregrind/m_ume/elf.c index b3edc20726..f7719605cf 100644 --- a/coregrind/m_ume/elf.c +++ b/coregrind/m_ume/elf.c @@ -72,12 +72,12 @@ struct elfinfo static void check_mmap(SysRes res, Addr base, SizeT len) { - if (res.isError) { + if (sr_isError(res)) { VG_(printf)("valgrind: mmap(0x%llx, %lld) failed in UME " "with error %lu (%s).\n", (ULong)base, (Long)len, - res.err, VG_(strerror)(res.err) ); - if (res.err == VKI_EINVAL) { + sr_Err(res), VG_(strerror)(sr_Err(res)) ); + if (sr_Err(res) == VKI_EINVAL) { VG_(printf)("valgrind: this can be caused by executables with " "very large text, data or bss segments.\n"); } @@ -100,9 +100,9 @@ struct elfinfo *readelf(Int fd, const char *filename) e->fd = fd; sres = VG_(pread)(fd, &e->e, sizeof(e->e), 0); - if (sres.isError || sres.res != sizeof(e->e)) { + if (sr_isError(sres) || sr_Res(sres) != sizeof(e->e)) { VG_(printf)("valgrind: %s: can't read ELF header: %s\n", - filename, VG_(strerror)(sres.err)); + filename, VG_(strerror)(sr_Err(sres))); goto bad; } @@ -140,9 +140,9 @@ struct elfinfo *readelf(Int fd, const char *filename) vg_assert(e->p); sres = VG_(pread)(fd, e->p, phsz, e->e.e_phoff); - if (sres.isError || sres.res != phsz) { + if (sr_isError(sres) || sr_Res(sres) != phsz) { VG_(printf)("valgrind: can't read phdr: %s\n", - VG_(strerror)(sres.err)); + VG_(strerror)(sr_Err(sres))); VG_(free)(e->p); goto bad; } @@ -373,11 +373,11 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info) buf[ph->p_filesz] = '\0'; sres = VG_(open)(buf, VKI_O_RDONLY, 0); - if (sres.isError) { + if (sr_isError(sres)) { VG_(printf)("valgrind: m_ume.c: can't open interpreter\n"); VG_(exit)(1); } - intfd = sres.res; + intfd = sr_Res(sres); interp = readelf(intfd, buf); if (interp == NULL) { diff --git a/coregrind/m_ume/main.c b/coregrind/m_ume/main.c index 786e176b17..b2fb502a9e 100644 --- a/coregrind/m_ume/main.c +++ b/coregrind/m_ume/main.c @@ -52,12 +52,12 @@ typedef struct { } ExeHandler; static ExeHandler exe_handlers[] = { -#if defined(HAVE_ELF) +# if defined(HAVE_ELF) { "ELF", VG_(match_ELF), VG_(load_ELF) }, -#endif -#if defined(HAVE_SCRIPT) +# endif +# if defined(HAVE_SCRIPT) { "script", VG_(match_script), VG_(load_script) }, -#endif +# endif }; #define EXE_HANDLER_COUNT (sizeof(exe_handlers)/sizeof(exe_handlers[0])) @@ -74,10 +74,10 @@ VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid) // Check it's readable res = VG_(open)(exe_name, VKI_O_RDONLY, 0); - if (res.isError) { + if (sr_isError(res)) { return res; } - fd = res.res; + fd = sr_Res(res); // Check we have execute permissions ret = VG_(check_executable)(&is_setuid, (HChar*)exe_name, allow_setuid); @@ -100,11 +100,11 @@ VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid) bufsz = fsz; res = VG_(pread)(fd, buf, bufsz, 0); - if (res.isError || res.res != bufsz) { + if (sr_isError(res) || sr_Res(res) != bufsz) { VG_(close)(fd); return VG_(mk_SysRes_Error)(VKI_EACCES); } - bufsz = res.res; + bufsz = sr_Res(res); // Look for a matching executable format for (i = 0; i < EXE_HANDLER_COUNT; i++) { @@ -119,7 +119,7 @@ VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid) } // Write the 'out_fd' param if necessary, or close the file. - if (!res.isError && out_fd) { + if (!sr_isError(res) && out_fd) { *out_fd = fd; } else { VG_(close)(fd); @@ -140,13 +140,13 @@ Int VG_(do_exec_inner)(const HChar* exe, ExeInfo* info) Int ret; res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/); - if (res.isError) - return res.err; + if (sr_isError(res)) + return sr_Err(res); - vg_assert2(res.res >= 0 && res.res < EXE_HANDLER_COUNT, + vg_assert2(sr_Res(res) >= 0 && sr_Res(res) < EXE_HANDLER_COUNT, "invalid VG_(pre_exec_check) result"); - ret = (*exe_handlers[res.res].load_fn)(fd, exe, info); + ret = (*exe_handlers[sr_Res(res)].load_fn)(fd, exe, info); VG_(close)(fd); @@ -157,9 +157,9 @@ Int VG_(do_exec_inner)(const HChar* exe, ExeInfo* info) static Bool is_hash_bang_file(Char* f) { SysRes res = VG_(open)(f, VKI_O_RDONLY, 0); - if (!res.isError) { + if (!sr_isError(res)) { Char buf[3] = {0,0,0}; - Int fd = res.res; + Int fd = sr_Res(res); Int n = VG_(read)(fd, buf, 2); if (n == 2 && VG_STREQ("#!", buf)) return True; @@ -173,9 +173,9 @@ static Bool is_hash_bang_file(Char* f) static Bool is_binary_file(Char* f) { SysRes res = VG_(open)(f, VKI_O_RDONLY, 0); - if (!res.isError) { + if (!sr_isError(res)) { UChar buf[80]; - Int fd = res.res; + Int fd = sr_Res(res); Int n = VG_(read)(fd, buf, 80); Int i; for (i = 0; i < n; i++) { @@ -235,7 +235,7 @@ static Int do_exec_shell_followup(Int ret, HChar* exe_name, ExeInfo* info) // Was it a directory? res = VG_(stat)(exe_name, &st); - if (!res.isError && VKI_S_ISDIR(st.st_mode)) { + if (!sr_isError(res) && VKI_S_ISDIR(st.st_mode)) { VG_(printf)("valgrind: %s: is a directory\n", exe_name); // Was it not executable? diff --git a/coregrind/m_ume/script.c b/coregrind/m_ume/script.c index 8df563e569..9b875c9ac5 100644 --- a/coregrind/m_ume/script.c +++ b/coregrind/m_ume/script.c @@ -90,11 +90,11 @@ Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info) // Read the first part of the file. res = VG_(pread)(fd, hdr, len, 0); - if (res.isError) { + if (sr_isError(res)) { VG_(close)(fd); return VKI_EACCES; } else { - len = res.res; + len = sr_Res(res); } vg_assert('#' == hdr[0] && '!' == hdr[1]); diff --git a/coregrind/m_vki.c b/coregrind/m_vki.c index 6d0631c08d..25beafbf62 100644 --- a/coregrind/m_vki.c +++ b/coregrind/m_vki.c @@ -30,6 +30,7 @@ */ #include "pub_core_basics.h" +#include "pub_core_libcassert.h" #include "pub_core_vki.h" /* self */ /* We have pub_{core,tool}_vki.h. This is the matching implementation @@ -47,6 +48,52 @@ unsigned long VKI_PAGE_SIZE = 1UL << 12; #endif +/* Do initial consistency checks on some of the definitions to do with + signals (vki_sigset_t and vki_sigaction_{toK,fromK}_t). This stuff + is fragile enough that it's important to check at startup that + the world looks like what we expect it to look like. + + The most important thing is to check that the definition of signal + sets for this platform is right. A signal set consists of some + number _VKI_NSIG_WORDS of 32- or 64-bit words. Because the kernel + itself has some indexing scheme to set/clear individual bits in the + set, we must make sure we use the same layout/scheme: where this + requirement bites us is in the VG_(sigfillset) etc functions in + m_libcsignal.c. So we check carefully here that it's all sensible. +*/ +void VG_(vki_do_initial_consistency_checks) ( void ) +{ + /* --- Platform-independent checks on signal sets --- */ + + vki_sigset_t set; + // Set's size must agree with _VKI_NSIG + vg_assert( 8 * sizeof(set) == _VKI_NSIG ); + // Set's word size must agree with _VKI_NSIG_BPW + vg_assert( 8 * sizeof(set.sig[0]) == _VKI_NSIG_BPW ); + // The set elements are 32- or 64-bit + vg_assert( _VKI_NSIG_BPW == 32 || _VKI_NSIG_BPW == 64 ); + + /* --- Platform-specific checks on signal sets --- */ + +# if defined(VGO_linux) || defined(VGO_aix5) + /* nothing to check */ +# else +# error "Unknown plat" +# endif + + /* --- Platform-specific checks on sigactions --- */ + +# if defined(VGO_linux) || defined(VGO_aix5) + /* the toK- and fromK- forms are identical */ + vg_assert( sizeof(vki_sigaction_toK_t) + == sizeof(vki_sigaction_fromK_t) ); + +# else +# error "Unknown OS" +# endif +} + + /*--------------------------------------------------------------------*/ /*--- end m_vki.c ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_libcfile.h b/coregrind/pub_core_libcfile.h index 310a5d70e6..4ff074f821 100644 --- a/coregrind/pub_core_libcfile.h +++ b/coregrind/pub_core_libcfile.h @@ -74,6 +74,9 @@ extern Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr ); extern Int VG_(check_executable)(/*OUT*/Bool* is_setuid, HChar* f, Bool allow_setuid); +/* Note this moves (or at least, is believed to move) the file pointer + on Linux and AIX5 but doesn't on Darwin. This inconsistency should + be fixed. */ extern SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ); /* Create and open (-rw------) a tmp file name incorporating said arg. diff --git a/coregrind/pub_core_libcsignal.h b/coregrind/pub_core_libcsignal.h index 9e8ebe713c..c323fc0afd 100644 --- a/coregrind/pub_core_libcsignal.h +++ b/coregrind/pub_core_libcsignal.h @@ -57,13 +57,23 @@ extern Int VG_(sigismember) ( const vki_sigset_t* set, Int signum ); extern void VG_(sigaddset_from_set) ( vki_sigset_t* dst, vki_sigset_t* src ); extern void VG_(sigdelset_from_set) ( vki_sigset_t* dst, vki_sigset_t* src ); +extern void VG_(sigintersectset) ( vki_sigset_t* dst, vki_sigset_t* src ); +extern void VG_(sigcomplementset) ( vki_sigset_t* dst, vki_sigset_t* src ); /* --- Mess with the kernel's sig state --- */ /* VG_(sigprocmask) is in pub_tool_libcsignal.h. */ extern Int VG_(sigaction) ( Int signum, - const struct vki_sigaction* act, - struct vki_sigaction* oldact ); + const vki_sigaction_toK_t* act, + vki_sigaction_fromK_t* oldact ); + +/* Convert a sigaction which you got from the kernel (a _fromK_t) to + one which you can give back to the kernel (a _toK_t). On Linux and + AIX, vki_sigaction_{toK,fromK}_t are identical, so this is a no-op + (structure copy), but on Darwin it's not a no-op. */ +extern void VG_(convert_sigaction_fromK_to_toK)( + vki_sigaction_fromK_t*, /*OUT*/vki_sigaction_toK_t*); + extern Int VG_(kill) ( Int pid, Int signo ); extern Int VG_(tkill) ( ThreadId tid, Int signo ); diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h index 5da26dcc8f..9a26c547eb 100644 --- a/coregrind/pub_core_machine.h +++ b/coregrind/pub_core_machine.h @@ -91,6 +91,7 @@ // Offsets for the Vex state #define VG_O_STACK_PTR (offsetof(VexGuestArchState, VG_STACK_PTR)) +#define VG_O_INSTR_PTR (offsetof(VexGuestArchState, VG_INSTR_PTR)) //------------------------------------------------------------- diff --git a/coregrind/pub_core_signals.h b/coregrind/pub_core_signals.h index 9d174ae079..6d6f68364c 100644 --- a/coregrind/pub_core_signals.h +++ b/coregrind/pub_core_signals.h @@ -54,8 +54,8 @@ extern void VG_(poll_signals) ( ThreadId ); 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 ); + const vki_sigaction_toK_t* new_act, + vki_sigaction_fromK_t* old_act ); extern SysRes VG_(do_sys_sigprocmask) ( ThreadId tid, Int how, vki_sigset_t* set, vki_sigset_t* oldset ); diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h index 9954754091..7cabdcb65d 100644 --- a/coregrind/pub_core_syscall.h +++ b/coregrind/pub_core_syscall.h @@ -65,8 +65,8 @@ extern SysRes VG_(do_syscall) ( UWord sysno, #define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),(c),\ (d),(e),(f),0,0) -extern SysRes VG_(mk_SysRes_x86_linux) ( UInt val ); -extern SysRes VG_(mk_SysRes_amd64_linux) ( ULong val ); +extern SysRes VG_(mk_SysRes_x86_linux) ( Int val ); +extern SysRes VG_(mk_SysRes_amd64_linux) ( Long val ); extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ); extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ); extern SysRes VG_(mk_SysRes_ppc32_aix5) ( UInt val, UInt err ); @@ -75,6 +75,7 @@ extern SysRes VG_(mk_SysRes_Error) ( UWord val ); extern SysRes VG_(mk_SysRes_Success) ( UWord val ); + /* Return a string which gives the name of an error value. Note, unlike the standard C syserror fn, the returned string is not malloc-allocated or writable -- treat it as a constant. */ diff --git a/coregrind/pub_core_syswrap.h b/coregrind/pub_core_syswrap.h index 57bfa074f1..89f0d8cbb2 100644 --- a/coregrind/pub_core_syswrap.h +++ b/coregrind/pub_core_syswrap.h @@ -51,7 +51,6 @@ extern void VG_(clear_syscallInfo) ( Int tid ); extern void VG_(fixup_guest_state_after_syscall_interrupted)( ThreadId tid, Addr ip, - UWord sysnum, SysRes sysret, Bool restart ); diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 630e52b812..cbda7ab571 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -111,7 +111,7 @@ extern void VG_(ppctoc_magic_redirect_return_stub); /* See comment for ppc32_aix5 equivalent above. */ extern void VG_(ppc64_aix5_do_preloads_then_start_client); #endif - + #endif // __PUB_CORE_TRAMPOLINE_H /*--------------------------------------------------------------------*/ diff --git a/coregrind/pub_core_vki.h b/coregrind/pub_core_vki.h index e01df8bcce..c5afeb01fd 100644 --- a/coregrind/pub_core_vki.h +++ b/coregrind/pub_core_vki.h @@ -43,6 +43,12 @@ #include "pub_tool_vki.h" +/* Do initial consistency checks on some of the definitions to do with + signals (vki_sigset_t and vki_sigaction_{toK,fromK}_t). This stuff + is fragile enough that it's important to check at startup that + the world looks like what we expect it to look like. */ +void VG_(vki_do_initial_consistency_checks)(void); + #endif // __PUB_CORE_VKI_H /*--------------------------------------------------------------------*/ diff --git a/exp-ptrcheck/h_main.c b/exp-ptrcheck/h_main.c index c452e7e95b..50f4154cd5 100644 --- a/exp-ptrcheck/h_main.c +++ b/exp-ptrcheck/h_main.c @@ -2549,7 +2549,7 @@ void h_post_syscall ( ThreadId tid, UInt sysno, SysRes res ) || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN) # endif ) { - if (res.isError) { + if (sr_isError(res)) { // mmap() had an error, return value is a small negative integer VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0, /*err*/ (UWord)NONPTR, 0 ); @@ -2566,7 +2566,7 @@ void h_post_syscall ( ThreadId tid, UInt sysno, SysRes res ) // notification via new_mem_mmap. Just set the return value shadow. # if defined(__NR_shmat) if (sysno == __NR_shmat) { - if (res.isError) { + if (sr_isError(res)) { VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0, /*err*/ (UWord)NONPTR, 0 ); if (0) VG_(printf)("ZZZZZZZ shmat res -> NONPTR\n"); diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h index 9bff837fcb..89d66f5a61 100644 --- a/include/pub_tool_basics.h +++ b/include/pub_tool_basics.h @@ -135,32 +135,88 @@ typedef UInt ThreadId; /* An abstraction of syscall return values. Linux: - When .isError == False, - res holds the return value, and err is zero. - When .isError == True, - err holds the error code, and res is zero. + When _isError == False, + _val holds the return value. + When _isError == True, + _err holds the error code. AIX: - res is the POSIX result of the syscall. - err is the corresponding errno value. - isError === err==0 + _res is the POSIX result of the syscall. + _err is the corresponding errno value. + _isError === _err==0 - Unlike on Linux, it is possible for 'err' to be nonzero (thus an - error has occurred), nevertheless 'res' is also nonzero. AIX - userspace does not appear to consistently inspect 'err' to + Unlike on Linux, it is possible for _err to be nonzero (thus an + error has occurred), nevertheless _res is also nonzero. AIX + userspace does not appear to consistently inspect _err to determine whether or not an error has occurred. For example, - sys_open() will return -1 for 'val' if a file cannot be opened, - as well as the relevant errno value in 'err', but AIX userspace - then consults 'val' to figure out if the syscall failed, rather - than looking at 'err'. Hence we need to represent them both. + sys_open() will return -1 for _val if a file cannot be opened, + as well as the relevant errno value in _err, but AIX userspace + then consults _val to figure out if the syscall failed, rather + than looking at _err. Hence we need to represent them both. + + Darwin: + Interpretation depends on _mode: + MACH, MDEP: + these can never 'fail' (apparently). The result of the + syscall is a single host word, _wLO. + UNIX: + Can record a double-word error or a double-word result: + When _mode is SysRes_UNIX_OK, _wHI:_wLO holds the result. + When _mode is SysRes_UNIX_ERR, _wHI:_wLO holds the error code. + Probably the high word of an error is always ignored by + userspace, but we have to record it, so that we can correctly + update both EDX and EAX (in guest state) given a SysRes, if + we're required to. */ +#if defined(VGO_linux) typedef struct { - UWord res; - UWord err; - Bool isError; + UWord _val; + Bool _isError; } SysRes; +#elif defined(VGO_aix5) +typedef + struct { + UWord _res; + UWord _err; + Bool _isError; + } + SysRes; +#else +# error "Unknown OS" +#endif + + +/* ---- And now some basic accessor functions for it. ---- */ + +#if defined(VGO_linux) + +static inline Bool sr_isError ( SysRes sr ) { + return sr._isError; +} +static inline UWord sr_Res ( SysRes sr ) { + return sr._isError ? 0 : sr._val; +} +static inline UWord sr_ResHI ( SysRes sr ) { + return 0; +} +static inline UWord sr_Err ( SysRes sr ) { + return sr._isError ? sr._val : 0; +} +static inline Bool sr_EQ ( SysRes sr1, SysRes sr2 ) { + return sr1._val == sr2._val + && ((sr1._isError && sr2._isError) + || (!sr1._isError && !sr2._isError)); +} + +#elif defined(VGO_aix5) +# error "need to define SysRes accessors on AIX5 (copy from 3.4.1 sources)" + + +#else +# error "Unknown OS" +#endif /* --------------------------------------------------------------------- diff --git a/include/pub_tool_libcfile.h b/include/pub_tool_libcfile.h index f870109f3f..63fb0b39a5 100644 --- a/include/pub_tool_libcfile.h +++ b/include/pub_tool_libcfile.h @@ -70,7 +70,7 @@ extern Int VG_(write) ( Int fd, const void* buf, Int count); extern Int VG_(pipe) ( Int fd[2] ); extern OffT VG_(lseek) ( Int fd, OffT offset, Int whence ); -extern SysRes VG_(stat) ( Char* file_name, struct vg_stat* buf ); +extern SysRes VG_(stat) ( const Char* file_name, struct vg_stat* buf ); extern Int VG_(fstat) ( Int fd, struct vg_stat* buf ); extern SysRes VG_(dup) ( Int oldfd ); extern SysRes VG_(dup2) ( Int oldfd, Int newfd ); @@ -78,7 +78,7 @@ extern Int VG_(rename) ( Char* old_name, Char* new_name ); extern Int VG_(unlink) ( Char* file_name ); extern Int VG_(readlink)( Char* path, Char* buf, UInt bufsize ); -extern Int VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count ); +extern Int VG_(getdents)( Int fd, struct vki_dirent *dirp, UInt count ); /* Copy the working directory at startup into buf[0 .. size-1], or return False if buf is too small. */ diff --git a/include/vki/vki-amd64-linux.h b/include/vki/vki-amd64-linux.h index 50e7dcbc3e..bc5c455121 100644 --- a/include/vki/vki-amd64-linux.h +++ b/include/vki/vki-amd64-linux.h @@ -143,7 +143,7 @@ typedef __vki_restorefn_t __user *__vki_sigrestore_t; #define VKI_SIG_DFL ((__vki_sighandler_t)0) /* default signal handling */ #define VKI_SIG_IGN ((__vki_sighandler_t)1) /* ignore signal */ -struct vki_sigaction { +struct vki_sigaction_base { // [[Nb: a 'k' prefix is added to "sa_handler" because // bits/sigaction.h (which gets dragged in somehow via signal.h) // #defines it as something else. Since that is done for glibc's @@ -154,6 +154,12 @@ struct vki_sigaction { vki_sigset_t sa_mask; /* mask last for extensibility */ }; +/* On Linux we use the same type for passing sigactions to + and from the kernel. Hence: */ +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + + typedef struct vki_sigaltstack { void __user *ss_sp; int ss_flags; diff --git a/include/vki/vki-ppc32-linux.h b/include/vki/vki-ppc32-linux.h index 074a8f84ec..69932c04ca 100644 --- a/include/vki/vki-ppc32-linux.h +++ b/include/vki/vki-ppc32-linux.h @@ -154,6 +154,10 @@ typedef struct { #define VKI_SS_ONSTACK 1 #define VKI_SS_DISABLE 2 +/* These are 'legacy' sigactions in which the size of sa_mask is fixed + (cannot be expanded at any future point) because it is sandwiched + between two other fields. + (there is identical kludgery in vki-x86-linux.h) */ struct vki_old_sigaction { // [[Nb: a 'k' prefix is added to "sa_handler" because // bits/sigaction.h (which gets dragged in somehow via signal.h) @@ -165,7 +169,7 @@ struct vki_old_sigaction { __vki_sigrestore_t sa_restorer; }; -struct vki_sigaction { +struct vki_sigaction_base { // [[See comment about extra 'k' above]] __vki_sighandler_t ksa_handler; unsigned long sa_flags; @@ -173,6 +177,12 @@ struct vki_sigaction { vki_sigset_t sa_mask; /* mask last for extensibility */ }; +/* On Linux we use the same type for passing sigactions to + and from the kernel. Hence: */ +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + + typedef struct vki_sigaltstack { void __user *ss_sp; int ss_flags; diff --git a/include/vki/vki-ppc64-linux.h b/include/vki/vki-ppc64-linux.h index 063fc55a47..610a163617 100644 --- a/include/vki/vki-ppc64-linux.h +++ b/include/vki/vki-ppc64-linux.h @@ -164,13 +164,19 @@ struct vki_old_sigaction { __vki_sigrestore_t sa_restorer; }; -struct vki_sigaction { +struct vki_sigaction_base { __vki_sighandler_t ksa_handler; unsigned long sa_flags; __vki_sigrestore_t sa_restorer; vki_sigset_t sa_mask; /* mask last for extensibility */ }; +/* On Linux we use the same type for passing sigactions to + and from the kernel. Hence: */ +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + + typedef struct vki_sigaltstack { void __user *ss_sp; int ss_flags; diff --git a/include/vki/vki-x86-linux.h b/include/vki/vki-x86-linux.h index 13a4e4e968..08aed502f6 100644 --- a/include/vki/vki-x86-linux.h +++ b/include/vki/vki-x86-linux.h @@ -149,6 +149,10 @@ typedef struct { #define VKI_SS_ONSTACK 1 #define VKI_SS_DISABLE 2 +/* These are 'legacy' sigactions in which the size of sa_mask is fixed + (cannot be expanded at any future point) because it is sandwiched + between two other fields. + (there is identical kludgery in vki-ppc32-linux.h) */ struct vki_old_sigaction { // [[Nb: a 'k' prefix is added to "sa_handler" because // bits/sigaction.h (which gets dragged in somehow via signal.h) @@ -160,7 +164,7 @@ struct vki_old_sigaction { __vki_sigrestore_t sa_restorer; }; -struct vki_sigaction { +struct vki_sigaction_base { // [[See comment about extra 'k' above]] __vki_sighandler_t ksa_handler; unsigned long sa_flags; @@ -168,6 +172,12 @@ struct vki_sigaction { vki_sigset_t sa_mask; /* mask last for extensibility */ }; +/* On Linux we use the same type for passing sigactions to + and from the kernel. Hence: */ +typedef struct vki_sigaction_base vki_sigaction_toK_t; +typedef struct vki_sigaction_base vki_sigaction_fromK_t; + + typedef struct vki_sigaltstack { void __user *ss_sp; int ss_flags; diff --git a/massif/ms_main.c b/massif/ms_main.c index 7cd2603f4a..f2e84e776f 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -2141,7 +2141,7 @@ static void write_snapshots_to_file(void) sres = VG_(open)(massif_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY, VKI_S_IRUSR|VKI_S_IWUSR); - if (sres.isError) { + if (sr_isError(sres)) { // If the file can't be opened for whatever reason (conflict // between multiple cachegrinded processes?), give up now. VG_UMSG("error: can't open output file '%s'", massif_out_file ); @@ -2149,7 +2149,7 @@ static void write_snapshots_to_file(void) VG_(free)(massif_out_file); return; } else { - fd = sres.res; + fd = sr_Res(sres); VG_(free)(massif_out_file); } diff --git a/memcheck/tests/unit_libcbase.c b/memcheck/tests/unit_libcbase.c index fab5d2865f..0aef0806ea 100644 --- a/memcheck/tests/unit_libcbase.c +++ b/memcheck/tests/unit_libcbase.c @@ -4,6 +4,7 @@ #include #include +#include "pub_tool_basics.h" /* UInt et al, needed for pub_tool_vki.h */ #include "pub_tool_vki.h" #include "m_libcbase.c"