Int nread;
HChar buf1k[1024];
Bool debug = False;
- SysRes statres;
- struct vki_stat statbuf;
+ SysRes statres;
+ struct vg_stat statbuf;
/* In short, figure out if this mapping is of interest to us, and
if so, try to guess what ld.so is doing and when/if we should
if (debug)
VG_(printf)("di_notify_mmap-2: %s\n", filename);
- /* Only try to read debug information from regular files. */
+ /* Only try to read debug information from regular files. */
statres = VG_(stat)(filename, &statbuf);
- /* If the assert below ever fails, replace the VG_(stat)() call above */
- /* by a VG_(lstat)() call. */
+
+ /* 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));
- if (statres.isError || ! VKI_S_ISREG(statbuf.st_mode))
- {
+
+ /* Don't let the stat call fail silently. Filter out some known
+ sources of noise before complaining, though. */
+ if (statres.isError) {
+ DebugInfo fake_di;
+ Bool quiet = VG_(strstr)(filename, "/var/run/nscd/") != NULL;
+ if (!quiet) {
+ VG_(memset)(&fake_di, 0, sizeof(fake_di));
+ fake_di.filename = filename;
+ ML_(symerr)(&fake_di, True, "failed to stat64/stat this file");
+ }
return;
}
+ /* Finally, the point of all this stattery: if it's not a regular file,
+ don't try to read debug info from it. */
+ if (! VKI_S_ISREG(statbuf.st_mode))
+ return;
+
+ /* no uses of statbuf below here. */
/* Peer at the first few bytes of the file, to see if it is an ELF */
/* object file. Ignore the file if we do not have read permission. */
static inline Bool fd_exists(Int fd)
{
- struct vki_stat st;
-
+ struct vg_stat st;
return VG_(fstat)(fd, &st) == 0;
}
change VG_(pread) and all other usage points. */
}
-SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf )
+
+/* stat/fstat support. It's uggerly. We have impedance-match into a
+ 'struct vg_stat' in order to have a single structure that callers
+ can use consistently on all platforms. */
+
+#define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
+ do { \
+ (_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_rdev = (ULong)( (_p_vkistat)->st_rdev ); \
+ (_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_atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
+ (_p_vgstat)->st_mtime = (ULong)( (_p_vkistat)->st_mtime ); \
+ (_p_vgstat)->st_mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
+ (_p_vgstat)->st_ctime = (ULong)( (_p_vkistat)->st_ctime ); \
+ (_p_vgstat)->st_ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
+ } while (0)
+
+SysRes VG_(stat) ( Char* file_name, struct vg_stat* vgbuf )
{
+ SysRes res;
+ VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
# if defined(VGO_linux)
- SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
- return res;
+# 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)) {
+ /* Success, or any failure except ENOSYS */
+ if (!res.isError)
+ TRANSLATE_TO_vg_stat(vgbuf, &buf64);
+ return res;
+ }
+ }
+# endif /* if defined(__NR_stat64) */
+ { struct vki_stat buf;
+ res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
+ if (!res.isError)
+ TRANSLATE_TO_vg_stat(vgbuf, &buf);
+ return res;
+ }
# elif defined(VGO_aix5)
- SysRes res = VG_(do_syscall4)(__NR_AIX5_statx,
- (UWord)file_name,
- (UWord)buf,
- sizeof(struct vki_stat),
- VKI_STX_NORMAL);
+ res = VG_(do_syscall4)(__NR_AIX5_statx,
+ (UWord)file_name,
+ (UWord)buf,
+ sizeof(struct vki_stat),
+ VKI_STX_NORMAL);
+ if (!res.isError)
+ TRANSLATE_TO_vg_stat(vgbuf, &buf);
return res;
# else
# error Unknown OS
# endif
}
-Int VG_(fstat) ( Int fd, struct vki_stat* buf )
+Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
{
+ SysRes res;
+ VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
# if defined(VGO_linux)
- SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
- return res.isError ? (-1) : 0;
+# 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)) {
+ /* Success, or any failure except ENOSYS */
+ if (!res.isError)
+ TRANSLATE_TO_vg_stat(vgbuf, &buf64);
+ return res.isError ? (-1) : 0;
+ }
+ }
+# endif /* if defined(__NR_fstat64) */
+ { struct vki_stat buf;
+ res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
+ if (!res.isError)
+ TRANSLATE_TO_vg_stat(vgbuf, &buf);
+ return res.isError ? (-1) : 0;
+ }
# elif defined(VGO_aix5)
I_die_here;
# else
# endif
}
-Int VG_(fsize) ( Int fd )
+#undef TRANSLATE_TO_vg_stat
+
+
+Long VG_(fsize) ( Int fd )
{
-# if defined(VGO_linux) && defined(__NR_fstat64)
- struct vki_stat64 buf;
- SysRes res = VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf);
- return res.isError ? (-1) : buf.st_size;
-# elif defined(VGO_linux) && !defined(__NR_fstat64)
- struct vki_stat buf;
- SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
- return res.isError ? (-1) : buf.st_size;
-# elif defined(VGO_aix5)
- I_die_here;
-# else
-# error Unknown OS
-# endif
+ struct vg_stat buf;
+ Int res = VG_(fstat)( fd, &buf );
+ return (res == -1) ? (-1LL) : buf.st_size;
}
Bool VG_(is_dir) ( HChar* f )
{
- struct vki_stat buf;
+ struct vg_stat buf;
SysRes res = VG_(stat)(f, &buf);
return res.isError ? False
: VKI_S_ISDIR(buf.st_mode) ? True : False;
/* To use this file you must first include pub_tool_vki.h. */
+/* Note that VG_(stat) and VG_(fstat) write to a 'struct vg_stat*' and
+ not a 'struct vki_stat*' or a 'struct vki_stat64*'. 'struct
+ vg_stat*' is not the same as either of the vki_ versions. No
+ specific vki_stat{,64} kernel structure will work and is
+ consistently available on different architectures on Linux, so we
+ have to use this 'struct vg_stat' impedance-matching type
+ instead. */
+struct vg_stat {
+ ULong st_dev;
+ ULong st_ino;
+ ULong st_nlink;
+ UInt st_mode;
+ UInt st_uid;
+ UInt st_gid;
+ ULong st_rdev;
+ Long st_size;
+ ULong st_blksize;
+ ULong st_blocks;
+ ULong st_atime;
+ ULong st_atime_nsec;
+ ULong st_mtime;
+ ULong st_mtime_nsec;
+ ULong st_ctime;
+ ULong st_ctime_nsec;
+};
+
extern SysRes VG_(open) ( const Char* pathname, Int flags, Int mode );
extern void VG_(close) ( Int fd );
extern Int VG_(read) ( Int fd, void* buf, Int count);
extern Int VG_(pipe) ( Int fd[2] );
extern OffT VG_(lseek) ( Int fd, OffT offset, Int whence );
-extern SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf );
-extern Int VG_(fstat) ( Int fd, struct vki_stat* buf );
+extern SysRes VG_(stat) ( Char* file_name, struct vg_stat* buf );
+extern Int VG_(fstat) ( Int fd, struct vg_stat* buf );
extern SysRes VG_(dup) ( Int oldfd );
extern Int VG_(rename) ( Char* old_name, Char* new_name );
extern Int VG_(unlink) ( Char* file_name );