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'",
VG_(free)(cachegrind_out_file);
return;
} else {
- fd = sres.res;
+ fd = sr_Res(sres);
VG_(free)(cachegrind_out_file);
}
/* 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;
/* 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;
}
}
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);
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);
*/
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();
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);
}
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 )
{
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
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;
}
# 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;
+ 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));
(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
(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
*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);
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 );
}
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 );
}
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 );
}
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;
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
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);
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 );
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;
}
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;
}
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;
}
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 );
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 )
/* 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");
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';
"%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;
}
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 */
}
/* 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) {
/* 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;
}
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;
/* 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)
}
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;
}
/* 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 */
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;
}
*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);
}
/*
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);
/* 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;
}
}
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("</valgrindoutput>\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; }
/* 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;
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");
}
vg_assert(ok);
- vg_assert(!res.isError);
+ vg_assert(!sr_isError(res));
}
/* ==================== create client stack ==================== */
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);
}
{
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;
{
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. */
}
(_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 ); \
(_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,
(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;
}
return res;
}
+
# else
# error Unknown OS
# endif
{
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
{
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;
}
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
{ 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;
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,
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
}
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 ) {
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.
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;
*/
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;
}
return sd;
-#endif
+
+# elif defined(VGO_aix5)
+ I_die_here;
+
+# else
+# error "Unknown OS"
+# endif
}
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)
# 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 )
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;
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;
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 ---*/
/*--------------------------------------------------------------------*/
-
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
{
# 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
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
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:
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;
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;
}
}
# 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);
}
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);
}
/* ---------------------------------------------------------------------
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
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);
}
}
- 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
}
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
}
{
/* 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
}
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"
{
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);
}
/* ---------------------------------------------------------------------
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
}
/* ---------------------------------------------------------------------
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,
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()
------------------------------------------------------------------ */
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 )
{
if (set == NULL)
return -1;
for (i = 0; i < _VKI_NSIG_WORDS; i++)
- set->sig[i] = ~(UWord)0x0;
+ set->sig[i] = ~0;
return 0;
}
if (set == NULL)
return -1;
for (i = 0; i < _VKI_NSIG_WORDS; i++)
- set->sig[i] = 0x0;
+ set->sig[i] = 0;
return 0;
}
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;
}
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;
}
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;
}
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;
}
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
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 )
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
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++)
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);
#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);
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=<file> (didn't work out for some reason.)");
/*NOTREACHED*/
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';
} else {
VG_(message)(Vg_DebugMsg, " (empty?)");
}
- VG_(close)(fd.res);
+ VG_(close)(sr_Res(fd));
# undef BUF_LEN
}
//--------------------------------------------------------------
// 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)();
//--------------------------------------------------------------
} else {
VG_(debugLog)(0,"mallocfree", s1, who, (ULong)szB, tot_alloc);
}
+
VG_(exit)(1);
}
// 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.
} 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);
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;
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?!?!");
/* ------ 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)
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;
{
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;
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:
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);
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
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, "
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);
}
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 );
}
}
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);
/* 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;
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);
}
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));
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;
}
}
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);
{
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);
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-<PLAT>.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);
}
}
+
static
void sync_signalhandler_from_kernel ( ThreadId tid,
Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc )
}
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",
*/
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;
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
*/
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,
/* 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;
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);
}
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))
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:
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;
}
/* 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
/* 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)
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"
#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,
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,
if (res == 0)
err = 0;
}
-
return VG_(mk_SysRes_ppc64_aix5)( res, err );
#else
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";
}
}
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;
Int o_arg7;
Int o_arg8;
Int o_retval;
+# else
+# error "Unknown platform"
+# endif
}
SyscallArgLayout;
/* 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);
}
void* guest_state, // rsi
const vki_sigset_t *sysmask, // rdx
const vki_sigset_t *postmask, // rcx
- Int nsigwords) // r8
+ Int sigsetSzB) // r8
*/
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
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
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"
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
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
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
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
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) */
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"
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
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
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
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
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) */
void* guest_state, // 4
const vki_sigset_t *sysmask, // 8
const vki_sigset_t *postmask, // 12
- Int nsigwords) // 16
+ Int sigsetSzB) // 16
*/
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;
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)
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;
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 {
}
}
- 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
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 );
}
}
}
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 );
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)) {
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;
}
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;
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;
}
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)" );
{
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)" );
}
{
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)" );
}
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;
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;
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;
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 */
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,
}
/* 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;
}
// 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;
}
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);
}
}
// 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 ( )");
SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
+ if (!SUCCESS) return;
+
+ result = RES;
+
VG_(do_atfork_pre)(tid);
if (SUCCESS && RES == 0) {
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",
|| 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 );
}
PRE_REG_READ0(long, "pause");
}
-// XXX: x86-specific
PRE(sys_sigaltstack)
{
PRINT("sigaltstack ( %#lx, %#lx )",ARG1,ARG2);
# error Unknown platform
#endif
- if (!res.isError && res.res == 0) {
+ if (!sr_isError(res) && sr_Res(res) == 0) {
/* child */
VG_(do_atfork_child)(tid);
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);
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;
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));
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)
|| 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 );
}
{
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)" );
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,
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",
}
-
/* ---------------------------------------------------------------------
Impedance matchers and misc helpers
------------------------------------------------------------------ */
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
# 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)
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)
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)
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)
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)
|| 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
}
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. */
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. */
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 {
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) );
+ }
+ }
}
}
- 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 );
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;
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);
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;
}
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",
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;
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;
}
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;
}
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",
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;
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];
}
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;
{
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++)
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");
}
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;
}
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;
}
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) {
} 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]))
// 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);
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++) {
}
// 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);
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);
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;
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++) {
// 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?
// 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]);
*/
#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
#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 ---*/
/*--------------------------------------------------------------------*/
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.
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 );
// 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))
//-------------------------------------------------------------
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 );
#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 );
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. */
extern void VG_(fixup_guest_state_after_syscall_interrupted)(
ThreadId tid,
Addr ip,
- UWord sysnum,
SysRes sysret,
Bool restart
);
/* See comment for ppc32_aix5 equivalent above. */
extern void VG_(ppc64_aix5_do_preloads_then_start_client);
#endif
-
+
#endif // __PUB_CORE_TRAMPOLINE_H
/*--------------------------------------------------------------------*/
#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
/*--------------------------------------------------------------------*/
|| (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 );
// 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");
/* 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
/* ---------------------------------------------------------------------
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 );
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. */
#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
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;
#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)
__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;
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;
__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;
#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)
__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;
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;
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 );
VG_(free)(massif_out_file);
return;
} else {
- fd = sres.res;
+ fd = sr_Res(sres);
VG_(free)(massif_out_file);
}
#include <stdio.h>
#include <stdlib.h>
+#include "pub_tool_basics.h" /* UInt et al, needed for pub_tool_vki.h */
#include "pub_tool_vki.h"
#include "m_libcbase.c"