aboutsummaryrefslogtreecommitdiff
path: root/libmudflap
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2004-10-13 18:27:16 +0000
committerFrank Ch. Eigler <fche@gcc.gnu.org>2004-10-13 18:27:16 +0000
commitddfabf89bbf2d7295725609ac997490160adf8fc (patch)
tree5ba143b308278286023d43a624647837da8e9cbd /libmudflap
parentccab73c3b7c38e3c7ac7e3a0b37f063856575953 (diff)
downloadgcc-ddfabf89bbf2d7295725609ac997490160adf8fc.zip
gcc-ddfabf89bbf2d7295725609ac997490160adf8fc.tar.gz
gcc-ddfabf89bbf2d7295725609ac997490160adf8fc.tar.bz2
configure.ac: Check for more headers, functions.
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. From-SVN: r88996
Diffstat (limited to 'libmudflap')
-rw-r--r--libmudflap/ChangeLog18
-rw-r--r--libmudflap/config.h.in24
-rwxr-xr-xlibmudflap/configure117
-rw-r--r--libmudflap/configure.ac7
-rw-r--r--libmudflap/mf-hooks2.c221
-rw-r--r--libmudflap/mf-runtime.c58
-rw-r--r--libmudflap/mf-runtime.h.in5
-rw-r--r--libmudflap/testsuite/libmudflap.c++/ctors.exp2
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass35-frag.c2
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass51-frag.c41
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass52-frag.c36
11 files changed, 492 insertions, 39 deletions
diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog
index f9778d4..ee4feac 100644
--- a/libmudflap/ChangeLog
+++ b/libmudflap/ChangeLog
@@ -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.
diff --git a/libmudflap/config.h.in b/libmudflap/config.h.in
index 41e6194..7685b57 100644
--- a/libmudflap/config.h.in
+++ b/libmudflap/config.h.in
@@ -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
@@ -126,9 +129,15 @@
/* 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
@@ -141,12 +150,24 @@
/* 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
@@ -180,6 +201,9 @@
/* 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
diff --git a/libmudflap/configure b/libmudflap/configure
index 9b838d9..0b51fe5 100755
--- a/libmudflap/configure
+++ b/libmudflap/configure
@@ -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=$?
diff --git a/libmudflap/configure.ac b/libmudflap/configure.ac
index c6e7337..9310b35 100644
--- a/libmudflap/configure.ac
+++ b/libmudflap/configure.ac
@@ -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>
diff --git a/libmudflap/mf-hooks2.c b/libmudflap/mf-hooks2.c
index 52ff3c1..5a001ad 100644
--- a/libmudflap/mf-hooks2.c
+++ b/libmudflap/mf-hooks2.c
@@ -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)
{
diff --git a/libmudflap/mf-runtime.c b/libmudflap/mf-runtime.c
index a0f9f73..64b1842 100644
--- a/libmudflap/mf-runtime.c
+++ b/libmudflap/mf-runtime.c
@@ -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 => "
diff --git a/libmudflap/mf-runtime.h.in b/libmudflap/mf-runtime.h.in
index 298ed6e..0f8f9e3 100644
--- a/libmudflap/mf-runtime.h.in
+++ b/libmudflap/mf-runtime.h.in
@@ -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
diff --git a/libmudflap/testsuite/libmudflap.c++/ctors.exp b/libmudflap/testsuite/libmudflap.c++/ctors.exp
index a160bc9..5d4f1ef 100644
--- a/libmudflap/testsuite/libmudflap.c++/ctors.exp
+++ b/libmudflap/testsuite/libmudflap.c++/ctors.exp
@@ -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}"
diff --git a/libmudflap/testsuite/libmudflap.c/pass35-frag.c b/libmudflap/testsuite/libmudflap.c/pass35-frag.c
index dbd9737..95dafab 100644
--- a/libmudflap/testsuite/libmudflap.c/pass35-frag.c
+++ b/libmudflap/testsuite/libmudflap.c/pass35-frag.c
@@ -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
index 0000000..b830b3a
--- /dev/null
+++ b/libmudflap/testsuite/libmudflap.c/pass51-frag.c
@@ -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
index 0000000..7ff9d57
--- /dev/null
+++ b/libmudflap/testsuite/libmudflap.c/pass52-frag.c
@@ -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;
+}