OSDN Git Service

2004-10-12 Frank Ch. Eigler <fche@redhat.com>
authorfche <fche@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Oct 2004 18:27:16 +0000 (18:27 +0000)
committerfche <fche@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Oct 2004 18:27:16 +0000 (18:27 +0000)
* configure.ac: Check for more headers, functions.
* mf-hooks2.c (mkbuffer, unmkbuffer): New helper functions for
tracking overridden FILE buffers.
(fopen, setvbuf): New/revised hook functions for buffer overriding.
(setbuf,setlinebuf,fdopen,freopen,fopen64,freopen64,fclose): Ditto.
(fflush): Accept given NULL stream (means "all streams").
* mf-runtime.h.in:
* mf-runtime.c (__mfu_check): Accept accesses that span adjacent
HEAP/GUESS objects.
(LOOKUP_CACHE_SIZE_MAX): Raise to 64K entries tentatively.
(__mf_adapt_cache): Use them all.
* testsuite/libmudflap.c/pass35-frag.c: Update warning message.
* testsuite/libmudflap.c++/ctors.exp: Ditto.
* testsuite/libmudflap.c/{pass51,pass52}-frag.c: New tests.
* configure, config.h.in: Regenerated.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88996 138bc75d-0d04-0410-961f-82ee72b054a4

libmudflap/ChangeLog
libmudflap/config.h.in
libmudflap/configure
libmudflap/configure.ac
libmudflap/mf-hooks2.c
libmudflap/mf-runtime.c
libmudflap/mf-runtime.h.in
libmudflap/testsuite/libmudflap.c++/ctors.exp
libmudflap/testsuite/libmudflap.c/pass35-frag.c
libmudflap/testsuite/libmudflap.c/pass51-frag.c [new file with mode: 0644]
libmudflap/testsuite/libmudflap.c/pass52-frag.c [new file with mode: 0644]

index f9778d4..ee4feac 100644 (file)
@@ -1,3 +1,21 @@
+2004-10-12  Frank Ch. Eigler  <fche@redhat.com>
+
+       * configure.ac: Check for more headers, functions.
+       * mf-hooks2.c (mkbuffer, unmkbuffer): New helper functions for
+       tracking overridden FILE buffers.
+       (fopen, setvbuf): New/revised hook functions for buffer overriding.
+       (setbuf,setlinebuf,fdopen,freopen,fopen64,freopen64,fclose): Ditto.
+       (fflush): Accept given NULL stream (means "all streams").
+       * mf-runtime.h.in: 
+       * mf-runtime.c (__mfu_check): Accept accesses that span adjacent
+       HEAP/GUESS objects.
+       (LOOKUP_CACHE_SIZE_MAX): Raise to 64K entries tentatively.
+       (__mf_adapt_cache): Use them all.
+       * testsuite/libmudflap.c/pass35-frag.c: Update warning message.
+       * testsuite/libmudflap.c++/ctors.exp: Ditto.
+       * testsuite/libmudflap.c/{pass51,pass52}-frag.c: New tests.
+       * configure, config.h.in: Regenerated.
+
 2004-10-05  Frank Ch. Eigler  <fche@redhat.com>
 
        * configure.ac: Checking for sys/socket.h once is enough.
index 41e6194..7685b57 100644 (file)
@@ -33,6 +33,9 @@
 /* Define to 1 if you have the `fopen64' function. */
 #undef HAVE_FOPEN64
 
+/* Define to 1 if you have the `freopen64' function. */
+#undef HAVE_FREOPEN64
+
 /* Define to 1 if you have the `fseeko64' function. */
 #undef HAVE_FSEEKO64
 
 /* Define to 1 if you have the `memrchr' function. */
 #undef HAVE_MEMRCHR
 
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
 /* Define to 1 if you have the <mntent.h> header file. */
 #undef HAVE_MNTENT_H
 
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
 /* Define to 1 if you have the <netdb.h> header file. */
 #undef HAVE_NETDB_H
 
 /* Define to 1 if you have the <pwd.h> header file. */
 #undef HAVE_PWD_H
 
+/* Define to 1 if you have the `setbuf' function. */
+#undef HAVE_SETBUF
+
+/* Define to 1 if you have the `setbuffer' function. */
+#undef HAVE_SETBUFFER
+
 /* Define to 1 if you have the `sethostname' function. */
 #undef HAVE_SETHOSTNAME
 
+/* Define to 1 if you have the `setlinebuf' function. */
+#undef HAVE_SETLINEBUF
+
 /* Define to 1 if you have the `setmntent' function. */
 #undef HAVE_SETMNTENT
 
+/* Define to 1 if you have the `setvbuf' function. */
+#undef HAVE_SETVBUF
+
 /* Define to 1 if you have the `signal' function. */
 #undef HAVE_SIGNAL
 
 /* Define to 1 if you have the <sys/ipc.h> header file. */
 #undef HAVE_SYS_IPC_H
 
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
 /* Define to 1 if you have the <sys/sem.h> header file. */
 #undef HAVE_SYS_SEM_H
 
index 9b838d9..0b51fe5 100755 (executable)
@@ -3597,9 +3597,10 @@ done
 
 
 
+
 for ac_header in stdint.h execinfo.h signal.h dlfcn.h dirent.h pwd.h grp.h \
   netdb.h sys/ipc.h sys/sem.h sys/shm.h sys/wait.h ctype.h mntent.h \
-  sys/socket.h netinet/in.h arpa/inet.h dlfcn.h
+  sys/socket.h netinet/in.h arpa/inet.h dlfcn.h sys/mman.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -3858,7 +3859,113 @@ done
 
 
 
-for ac_func in fopen64 fseeko64 ftello64 stat64
+
+for ac_func in fopen64 fseeko64 ftello64 stat64 freopen64
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+for ac_func in setbuf setbuffer setlinebuf setvbuf
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -4699,7 +4806,9 @@ fi
 done
 
 
-for ac_func in inet_ntoa
+
+
+for ac_func in inet_ntoa mmap munmap
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 echo "$as_me:$LINENO: checking for $ac_func" >&5
@@ -5656,7 +5765,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
 case $host in
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5659 "configure"' > conftest.$ac_ext
+  echo '#line 5768 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
index c6e7337..9310b35 100644 (file)
@@ -61,10 +61,11 @@ enable_shared=no])
 
 AC_CHECK_HEADERS(stdint.h execinfo.h signal.h dlfcn.h dirent.h pwd.h grp.h \
   netdb.h sys/ipc.h sys/sem.h sys/shm.h sys/wait.h ctype.h mntent.h \
-  sys/socket.h netinet/in.h arpa/inet.h dlfcn.h)
+  sys/socket.h netinet/in.h arpa/inet.h dlfcn.h sys/mman.h)
 
 AC_CHECK_FUNCS(backtrace backtrace_symbols gettimeofday signal)
-AC_CHECK_FUNCS(fopen64 fseeko64 ftello64 stat64)
+AC_CHECK_FUNCS(fopen64 fseeko64 ftello64 stat64 freopen64)
+AC_CHECK_FUNCS(setbuf setbuffer setlinebuf setvbuf)
 AC_CHECK_FUNCS(strnlen memrchr strncpy memmem sethostname)
 AC_CHECK_FUNCS(__ctype_b_loc __ctype_tolower_loc __ctype_toupper_loc)
 AC_CHECK_FUNCS(getlogin cuserid getpwnam getpwuid getpwent getgrnam getgrgid getgrent)
@@ -72,7 +73,7 @@ AC_CHECK_FUNCS(getlogin_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r)
 AC_CHECK_FUNCS(getservent getservbyname getservbyport getaddrinfo gai_strerror)
 AC_CHECK_FUNCS(getprotoent getprotobyname getprotobynumber)
 AC_CHECK_FUNCS(getmntent setmntent addmntent)
-AC_CHECK_FUNCS(inet_ntoa)
+AC_CHECK_FUNCS(inet_ntoa mmap munmap)
 
 AC_TRY_COMPILE([#include <sys/types.h>
 #include <sys/ipc.h>
index 52ff3c1..5a001ad 100644 (file)
@@ -584,6 +584,66 @@ WRAPPER2(char *, strerror, int errnum)
 }
 
 
+
+/* An auxiliary data structure for tracking the hand-made stdio
+   buffers we generate during the fopen/fopen64 hooks.  In a civilized
+   language, this would be a simple dynamically sized FILE*->char*
+   lookup table, but this is C and we get to do it by hand.  */
+struct mf_filebuffer
+{
+  FILE *file;
+  char *buffer;
+  struct mf_filebuffer *next;
+};
+static struct mf_filebuffer *mf_filebuffers = NULL;
+
+static void
+mkbuffer (FILE *f)
+{
+  /* Reset any buffer automatically provided by libc, since this may
+     have been done via mechanisms that libmudflap couldn't
+     intercept.  */
+  int rc;
+  size_t bufsize = BUFSIZ;
+  int bufmode;
+  char *buffer = malloc (bufsize);
+  struct mf_filebuffer *b = malloc (sizeof (struct mf_filebuffer));
+  assert ((buffer != NULL) && (b != NULL));
+
+  /* Link it into list.  */
+  b->file = f;
+  b->buffer = buffer;
+  b->next = mf_filebuffers;
+  mf_filebuffers = b;
+
+  /* Determine how the file is supposed to be buffered at the moment.  */
+  bufmode = fileno (f) == 2 ? _IONBF : (isatty (fileno (f)) ? _IOLBF : _IOFBF);
+
+  rc = setvbuf (f, buffer, bufmode, bufsize);
+  assert (rc == 0);
+}
+
+static void
+unmkbuffer (FILE *f)
+{
+  struct mf_filebuffer *b = mf_filebuffers;
+  struct mf_filebuffer **pb = & mf_filebuffers;
+  while (b != NULL)
+    {
+      if (b->file == f)
+        {
+          *pb = b->next;
+          free (b->buffer);
+          free (b);
+          return;
+        }
+      pb = & b->next;
+      b = b->next;
+    }
+}
+
+
+
 WRAPPER2(FILE *, fopen, const char *path, const char *mode)
 {
   size_t n;
@@ -602,6 +662,106 @@ WRAPPER2(FILE *, fopen, const char *path, const char *mode)
     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen result");
 #endif
     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen result");
+
+    mkbuffer (p);
+  }
+
+  return p;
+}
+
+
+WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode, size_t size)
+{
+  int rc = 0;
+  TRACE ("%s\n", __PRETTY_FUNCTION__);
+
+  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE, "setvbuf stream");
+
+  unmkbuffer (stream);
+
+  if (buf != NULL)
+    MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_WRITE, "setvbuf buffer");
+
+  /* Override the user only if it's an auto-allocated buffer request.  Otherwise
+     assume that the supplied buffer is already known to libmudflap.  */
+  if ((buf == NULL) && ((mode == _IOFBF) || (mode == _IOLBF)))
+    mkbuffer (stream);
+  else
+    rc = setvbuf (stream, buf, mode, size);
+
+  return rc;
+}
+
+
+#ifdef HAVE_SETBUF
+WRAPPER2(int, setbuf, FILE* stream, char *buf)
+{
+  return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
+#endif
+
+#ifdef HAVE_SETBUFFER
+WRAPPER2(int, setbuffer, FILE* stream, char *buf, size_t sz)
+{
+  return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, sz);
+}
+#endif
+
+#ifdef HAVE_SETLINEBUF
+WRAPPER2(int, setlinebuf, FILE* stream)
+{
+  return __mfwrap_setvbuf(stream, NULL, _IOLBF, 0);
+}
+#endif
+
+
+
+WRAPPER2(FILE *, fdopen, int fd, const char *mode)
+{
+  size_t n;
+  FILE *p;
+  TRACE ("%s\n", __PRETTY_FUNCTION__);
+
+  n = strlen (mode);
+  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fdopen mode");
+
+  p = fdopen (fd, mode);
+  if (NULL != p) {
+#ifdef MF_REGISTER_fopen
+    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fdopen result");
+#endif
+    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fdopen result");
+
+    mkbuffer (p);
+  }
+
+  return p;
+}
+
+
+WRAPPER2(FILE *, freopen, const char *path, const char *mode, FILE *s)
+{
+  size_t n;
+  FILE *p;
+  TRACE ("%s\n", __PRETTY_FUNCTION__);
+
+  n = strlen (path);
+  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen path");
+
+  MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen stream");
+  unmkbuffer (s);
+
+  n = strlen (mode);
+  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen mode");
+
+  p = freopen (path, mode, s);
+  if (NULL != p) {
+#ifdef MF_REGISTER_fopen
+    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen result");
+#endif
+    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen result");
+
+    mkbuffer (p);
   }
 
   return p;
@@ -627,6 +787,39 @@ WRAPPER2(FILE *, fopen64, const char *path, const char *mode)
     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen64 result");
 #endif
     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen64 result");
+
+    mkbuffer (p);
+  }
+
+  return p;
+}
+#endif
+
+
+#ifdef HAVE_FREOPEN64
+WRAPPER2(FILE *, freopen64, const char *path, const char *mode, FILE *s)
+{
+  size_t n;
+  FILE *p;
+  TRACE ("%s\n", __PRETTY_FUNCTION__);
+
+  n = strlen (path);
+  MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 path");
+
+  MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen64 stream");
+  unmkbuffer (s);
+
+  n = strlen (mode);
+  MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 mode");
+
+  p = freopen (path, mode, s);
+  if (NULL != p) {
+#ifdef MF_REGISTER_fopen
+    __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen64 result");
+#endif
+    MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen64 result");
+
+    mkbuffer (p);
   }
 
   return p;
@@ -644,6 +837,7 @@ WRAPPER2(int, fclose, FILE *stream)
 #ifdef MF_REGISTER_fopen
   __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
 #endif
+  unmkbuffer (stream);
 
   return resp;
 }
@@ -943,8 +1137,9 @@ WRAPPER2(int , remove, const char *path)
 WRAPPER2(int, fflush, FILE *stream)
 {
   TRACE ("%s\n", __PRETTY_FUNCTION__);
-  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
-    "fflush stream");
+  if (stream != NULL)
+    MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
+                        "fflush stream");
   return fflush (stream);
 }
 
@@ -1071,28 +1266,6 @@ WRAPPER2(int , mkfifo, const char *path, mode_t mode)
 }
 
 
-WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode , size_t size)
-{
-  TRACE ("%s\n", __PRETTY_FUNCTION__);
-  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
-    "setvbuf stream");
-  if (NULL != buf)
-    MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_READ, "setvbuf buf");
-  return setvbuf (stream, buf, mode, size);
-}
-
-
-WRAPPER2(void, setbuf, FILE *stream, char *buf)
-{
-  TRACE ("%s\n", __PRETTY_FUNCTION__);
-  MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
-    "setbuf stream");
-  if (NULL != buf)
-    MF_VALIDATE_EXTENT (buf, BUFSIZ, __MF_CHECK_READ, "setbuf buf");
-  setbuf (stream, buf);
-}
-
-
 #ifdef HAVE_DIRENT_H
 WRAPPER2(DIR *, opendir, const char *path)
 {
index a0f9f73..64b1842 100644 (file)
@@ -160,7 +160,7 @@ static void mfsplay_tree_rebalance (mfsplay_tree sp);
 /* Required globals.  */
 
 #define LOOKUP_CACHE_MASK_DFL 1023
-#define LOOKUP_CACHE_SIZE_MAX 4096 /* Allows max CACHE_MASK 0x0FFF */
+#define LOOKUP_CACHE_SIZE_MAX 65536 /* Allows max CACHE_MASK 0xFFFF */
 #define LOOKUP_CACHE_SHIFT_DFL 2
 
 struct __mf_cache __mf_lookup_cache [LOOKUP_CACHE_SIZE_MAX];
@@ -917,7 +917,7 @@ void __mfu_check (void *ptr, size_t sz, int type, const char *location)
                   judgement = -1;
               }
 
-            /* We now know that the access spans one or more valid objects.  */
+            /* We now know that the access spans one or more only valid objects.  */
             if (LIKELY (judgement >= 0))
               for (i = 0; i < obj_count; i++)
                 {
@@ -931,12 +931,58 @@ void __mfu_check (void *ptr, size_t sz, int type, const char *location)
                       entry->high = obj->high;
                       judgement = 1;
                     }
+                }
+
+            /* This access runs off the end of one valid object.  That
+                could be okay, if other valid objects fill in all the
+                holes.  We allow this only for HEAP and GUESS type
+                objects.  Accesses to STATIC and STACK variables
+                should not be allowed to span.  */
+            if (UNLIKELY ((judgement == 0) && (obj_count > 1)))
+              {
+                unsigned uncovered = 0;
+                for (i = 0; i < obj_count; i++)
+                  {
+                    __mf_object_t *obj = all_ovr_obj[i];
+                    int j, uncovered_low_p, uncovered_high_p;
+                    uintptr_t ptr_lower, ptr_higher;
+
+                    uncovered_low_p = ptr_low < obj->low;
+                    ptr_lower = CLAMPSUB (obj->low, 1);
+                    uncovered_high_p = ptr_high > obj->high;
+                    ptr_higher = CLAMPADD (obj->high, 1);
 
-                  /* XXX: Access runs off left or right side of this
-                          object.  That could be okay, if there are
-                          other objects that fill in all the holes. */
+                    for (j = 0; j < obj_count; j++)
+                      {
+                        __mf_object_t *obj2 = all_ovr_obj[j];
+
+                        if (i == j) continue;
+
+                        /* Filter out objects that cannot be spanned across.  */
+                        if (obj2->type == __MF_TYPE_STACK 
+                            || obj2->type == __MF_TYPE_STATIC)
+                          continue;
+
+                          /* Consider a side "covered" if obj2 includes
+                             the next byte on that side.  */
+                          if (uncovered_low_p
+                              && (ptr_lower >= obj2->low && ptr_lower <= obj2->high))
+                            uncovered_low_p = 0;
+                          if (uncovered_high_p
+                              && (ptr_high >= obj2->low && ptr_higher <= obj2->high))
+                            uncovered_high_p = 0;
+                      }
+                    
+                    if (uncovered_low_p || uncovered_high_p)
+                      uncovered ++;
+                  }
+
+                /* Success if no overlapping objects are uncovered.  */
+                if (uncovered == 0)
+                  judgement = 1;
                 }
 
+
             if (dealloc_me != NULL)
               CALL_REAL (free, dealloc_me);
 
@@ -1413,7 +1459,7 @@ __mf_adapt_cache ()
       cache_utilization += 1.0;
   cache_utilization /= (1 + __mf_lc_mask);
 
-  new_mask |= 0x3ff; /* XXX: force a large cache.  */
+  new_mask |= 0xffff; /* XXX: force a large cache.  */
   new_mask &= (LOOKUP_CACHE_SIZE_MAX - 1);
 
   VERBOSE_TRACE ("adapt cache obj=%u/%u sizes=%lu/%.0f/%.0f => "
index 298ed6e..0f8f9e3 100644 (file)
@@ -108,6 +108,8 @@ extern int __mf_set_options (const char *opts);
 #pragma redefine_extname time __mfwrap_time
 #pragma redefine_extname strerror __mfwrap_strerror
 #pragma redefine_extname fopen __mfwrap_fopen
+#pragma redefine_extname fdopen __mfwrap_fdopen
+#pragma redefine_extname freopen __mfwrap_freopen
 #pragma redefine_extname fclose __mfwrap_fclose
 #pragma redefine_extname fread __mfwrap_fread
 #pragma redefine_extname fwrite __mfwrap_fwrite
@@ -146,6 +148,8 @@ extern int __mf_set_options (const char *opts);
 #pragma redefine_extname mkfifo __mfwrap_mkfifo
 #pragma redefine_extname setvbuf __mfwrap_setvbuf
 #pragma redefine_extname setbuf __mfwrap_setbuf
+#pragma redefine_extname setbuffer __mfwrap_setbuffer
+#pragma redefine_extname setlinebuf __mfwrap_setlinebuf
 #pragma redefine_extname opendir __mfwrap_opendir
 #pragma redefine_extname closedir __mfwrap_closedir
 #pragma redefine_extname readdir __mfwrap_readdir
@@ -176,6 +180,7 @@ extern int __mf_set_options (const char *opts);
 #pragma redefine_extname dlsym __mfwrap_dlsym
 #pragma redefine_extname dlclose __mfwrap_dlclose
 #pragma redefine_extname fopen64 __mfwrap_fopen64
+#pragma redefine_extname freopen64 __mfwrap_freopen64
 #pragma redefine_extname stat64 __mfwrap_stat64
 #pragma redefine_extname fseeko64 __mfwrap_fseeko64
 #pragma redefine_extname ftello64 __mfwrap_ftello64
index a160bc9..5d4f1ef 100644 (file)
@@ -8,7 +8,7 @@ global srcdir subdir
 foreach flags [list {} {-static} {-O2} {-O3}] {
     set l1 [libmudflap_target_compile "$srcdir/$subdir/ctors-1.cxx" "ctors-1.o" object {additional_flags=-fmudflap}]
     set test "ctors-1 compilation ${flags}"
-    if [string match "*mudflap cannot track lifetime of*k*" $l1] { pass $test } { fail $test }
+    if [string match "*mudflap cannot track unknown size extern *k*" $l1] { pass $test } { fail $test }
 
     set l2 [libmudflap_target_compile "$srcdir/$subdir/ctors-2.cxx" "ctors-2.o" object {additional_flags=-fmudflap}]
     set test "ctors-2 compilation ${flags}"
index dbd9737..95dafab 100644 (file)
@@ -3,7 +3,7 @@
 #include <string.h>
 
 extern char end [];   /* Any old symbol we're sure will be defined. */
-/* { dg-warning "cannot track lifetime of 'end'" "cannot track lifetime" { target *-*-* } 0 } */
+/* { dg-warning "cannot track unknown size extern 'end'" "cannot track unknown size extern" { target *-*-* } 0 } */
 
 int main ()
 {
diff --git a/libmudflap/testsuite/libmudflap.c/pass51-frag.c b/libmudflap/testsuite/libmudflap.c/pass51-frag.c
new file mode 100644 (file)
index 0000000..b830b3a
--- /dev/null
@@ -0,0 +1,41 @@
+/* Test object-spanning accesses.  This is most conveniently done with
+   mmap, thus the config.h specificity here.  */
+#include "../config.h"
+
+#include <unistd.h>
+#include <string.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+int main ()
+{
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#ifdef HAVE_MMAP
+  void *p;
+  unsigned pg = getpagesize ();
+  int rc;
+
+  p = mmap (NULL, 4 * pg, PROT_READ|PROT_WRITE, 
+            MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+  if (p == NULL)
+    return 1;
+
+  memset (p, 0, 4*pg);
+  rc = munmap (p, pg);
+  if (rc < 0) return 1;
+  memset (p+pg, 0, 3*pg);
+  rc = munmap (p+pg, pg);
+  if (rc < 0) return 1;
+  memset (p+2*pg, 0, 2*pg);
+  rc = munmap (p+2*pg, pg);
+  if (rc < 0) return 1;
+  memset (p+3*pg, 0, pg);
+  rc = munmap (p+3*pg, pg);
+  if (rc < 0) return 1;
+#endif
+
+  return 0;
+}
diff --git a/libmudflap/testsuite/libmudflap.c/pass52-frag.c b/libmudflap/testsuite/libmudflap.c/pass52-frag.c
new file mode 100644 (file)
index 0000000..7ff9d57
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdio.h>
+
+
+void writestuff (FILE *f)
+{
+  fprintf (f, "hello world\n");
+  fputc ('y', f);
+  putc ('e', f);
+}
+
+void readstuff (FILE *f)
+{
+  int c, d;
+  char stuff[100], *s;
+  c = fgetc (f);
+  ungetc (c, f);
+  d = fgetc (f);
+  s = fgets (stuff, sizeof(stuff), f);
+}
+
+int main ()
+{
+  FILE *f;
+  writestuff (stdout);
+  writestuff (stderr);
+  f = fopen ("/dev/null", "w");
+  writestuff (f);
+  fclose (f);
+  f = fopen ("/dev/zero", "r");
+  readstuff (f);
+  f = freopen ("/dev/null", "w", f);
+  writestuff (f);
+  fclose (f);
+
+  return 0;
+}