[PATCH 3/3] [LLVM] [sanitizer] add conditionals for libc
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Thu Apr 17 06:49:37 PDT 2014
Conditionalize usage of dlvsym(), nanosleep(), usleep();
Conditionalize layout of struct sigaction and type of it's member
sa_flags.
Conditionalize glob_t members gl_closedir, gl_readdir, gl_opendir,
gl_flags, gl_lstat, gl_stat.
Check for availability of glob.h for use with above members.
Check for availability of netrom/netrom.h, sys/ustat.h (for obsolete
ustat() function), utime.h (for obsolete utime() function), wordexp.h.
Determine size of sigset_t instead of hardcoding it.
Determine size of struct statfs64, if available.
Leave defaults to match what glibc expects but probe them for uClibc.
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com>
---
CMakeLists.txt | 58 +++++++
cmake/Modules/CompilerRTUtils.cmake | 15 ++
cmake/Modules/FunctionExistsNotStub.cmake | 56 +++++++
lib/interception/interception_linux.cc | 2 +
lib/interception/interception_linux.h | 9 ++
.../sanitizer_common_interceptors.inc | 101 +++++++++++-
.../sanitizer_platform_limits_posix.cc | 44 ++++-
.../sanitizer_platform_limits_posix.h | 27 +++-
lib/sanitizer_common/sanitizer_posix_libcdep.cc | 9 ++
make/platform/clang_linux.mk | 180 +++++++++++++++++++++
make/platform/clang_linux_test_libc.c | 68 ++++++++
11 files changed, 561 insertions(+), 8 deletions(-)
create mode 100644 cmake/Modules/FunctionExistsNotStub.cmake
create mode 100644 make/platform/clang_linux_test_libc.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1a7a1f..af8073e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -330,6 +330,64 @@ if(APPLE)
-isysroot ${IOSSIM_SDK_DIR})
endif()
+set(ct_c ${COMPILER_RT_SOURCE_DIR}/make/platform/clang_linux_test_libc.c)
+check_include_file(sys/ustat.h HAVE_SYS_USTAT_H)
+check_include_file(utime.h HAVE_UTIME_H)
+check_include_file(wordexp.h HAVE_WORDEXP_H)
+check_include_file(glob.h HAVE_GLOB_H)
+include(FunctionExistsNotStub)
+check_function_exists_not_stub(${ct_c} nanosleep HAVE_NANOSLEEP)
+check_function_exists_not_stub(${ct_c} usleep HAVE_USLEEP)
+include(CheckTypeSize)
+# check for sizeof sigset_t
+set(oCMAKE_EXTRA_INCLUDE_FILES "${CMAKE_EXTRA_INCLUDE_FILES}")
+set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} signal.h)
+check_type_size("sigset_t" SIZEOF_SIGSET_T BUILTIN_TYPES_ONLY)
+if(EXISTS HAVE_SIZEOF_SIGSET_T)
+ set(SIZEOF_SIGSET_T ${HAVE_SIZEOF_SIGSET_T})
+endif()
+set(CMAKE_EXTRA_INCLUDE_FILES "${oCMAKE_EXTRA_INCLUDE_FILES}")
+# check for sizeof struct statfs64
+set(oCMAKE_EXTRA_INCLUDE_FILES "${CMAKE_EXTRA_INCLUDE_FILES}")
+check_include_file(sys/statfs.h HAVE_SYS_STATFS_H)
+check_include_file(sys/vfs.h HAVE_SYS_VFS_H)
+if(HAVE_SYS_STATFS_H)
+ set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} sys/statfs.h)
+endif()
+if(HAVE_SYS_VFS_H)
+ set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} sys/vfs.h)
+endif()
+# Have to pass _LARGEFILE64_SOURCE otherwise there is no struct statfs64.
+# We forcefully enable LFS to retain glibc legacy behaviour herein.
+set(oCMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
+set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_LARGEFILE64_SOURCE)
+check_type_size("struct statfs64" SIZEOF_STRUCT_STATFS64)
+if(EXISTS HAVE_SIZEOF_STRUCT_STATFS64)
+ set(SIZEOF_STRUCT_STATFS64 ${HAVE_SIZEOF_STRUCT_STATFS64})
+else()
+ set(CMAKE_REQUIRED_DEFINITIONS ${oCMAKE_REQUIRED_DEFINITIONS})
+endif()
+set(CMAKE_EXTRA_INCLUDE_FILES "${oCMAKE_EXTRA_INCLUDE_FILES}")
+# do not set(CMAKE_REQUIRED_DEFINITIONS ${oCMAKE_REQUIRED_DEFINITIONS})
+# it back here either way.
+include(CheckStructHasMember)
+check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_T_GL_FLAGS)
+check_struct_has_member(glob_t gl_closedir glob.h HAVE_GLOB_T_GL_CLOSEDIR)
+check_struct_has_member(glob_t gl_readdir glob.h HAVE_GLOB_T_GL_READDIR)
+check_struct_has_member(glob_t gl_opendir glob.h HAVE_GLOB_T_GL_OPENDIR)
+check_struct_has_member(glob_t gl_lstat glob.h HAVE_GLOB_T_GL_LSTAT)
+check_struct_has_member(glob_t gl_stat glob.h HAVE_GLOB_T_GL_STAT)
+
+# folks seem to have an aversion to configure_file? So be it..
+foreach(x HAVE_SYS_USTAT_H HAVE_UTIME_H HAVE_WORDEXP_H HAVE_GLOB_H
+HAVE_NANOSLEEP HAVE_USLEEP SIZEOF_SIGSET_T SIZEOF_STRUCT_STATFS64
+HAVE_GLOB_T_GL_FLAGS HAVE_GLOB_T_GL_CLOSEDIR
+HAVE_GLOB_T_GL_READDIR HAVE_GLOB_T_GL_OPENDIR
+HAVE_GLOB_T_GL_LSTAT HAVE_GLOB_T_GL_STAT)
+def_undef_string(${x} SANITIZER_COMMON_CFLAGS)
+endforeach()
+
+
# Architectures supported by Sanitizer runtimes. Specific sanitizers may
# support only subset of these (e.g. TSan works on x86_64 only).
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
diff --git a/cmake/Modules/CompilerRTUtils.cmake b/cmake/Modules/CompilerRTUtils.cmake
index e22e775..3a0beec 100644
--- a/cmake/Modules/CompilerRTUtils.cmake
+++ b/cmake/Modules/CompilerRTUtils.cmake
@@ -59,3 +59,18 @@ macro(append_no_rtti_flag list)
append_if(COMPILER_RT_HAS_FNO_RTTI_FLAG -fno-rtti ${list})
append_if(COMPILER_RT_HAS_GR_FLAG /GR- ${list})
endmacro()
+
+# Appends -Dvalue=${value}/-Uvalue to all strings in ARGN
+macro(def_undef_string condition)
+ if("${${condition}}" STREQUAL "")
+ foreach(str ${ARGN})
+ set(${str} "${${str}} -U${condition}")
+ endforeach()
+ else()
+ foreach(str ${ARGN})
+ set(${str} "${${str}} '-D${condition}=${${condition}}'")
+ endforeach()
+ endif()
+endmacro()
+
+
diff --git a/cmake/Modules/FunctionExistsNotStub.cmake b/cmake/Modules/FunctionExistsNotStub.cmake
new file mode 100644
index 0000000..9f944dd
--- /dev/null
+++ b/cmake/Modules/FunctionExistsNotStub.cmake
@@ -0,0 +1,56 @@
+INCLUDE(CheckFunctionExists)
+
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+# CMAKE_REQUIRED_FLAGS = string of compile command line flags
+# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+# CMAKE_REQUIRED_INCLUDES = list of include directories
+
+macro(CHECK_FUNCTION_EXISTS_NOT_STUB CSRC FUNCTION VARIABLE)
+ if(NOT DEFINED CHECKED_STUB_${VARIABLE})
+ set(CHECKED_STUB_${VARIABLE} "done" CACHE INTERNAL "checked stub of ${FUNCTION}")
+ CHECK_FUNCTION_EXISTS("${FUNCTION}" "${VARIABLE}")
+ if(DEFINED ${VARIABLE})
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for stubbed out ${FUNCTION}")
+ endif()
+ if(CMAKE_REQUIRED_INCLUDES)
+ set(MACRO_CHECK_FUNCTION_EXISTS_NOT_STUB_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+ else()
+ set(MACRO_CHECK_FUNCTION_EXISTS_NOT_STUB_INCLUDES)
+ endif()
+ set(MACRO_CHECK_FUNCTION_EXISTS_NOT_STUB_FLAGS ${CMAKE_REQUIRED_FLAGS})
+ try_compile(${VARIABLE}
+ ${CMAKE_BINARY_DIR}
+ "${CSRC}"
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+ CMAKE_FLAGS
+ "-DCOMPILE_DEFINITIONS:STRING=-DL_features_h -DL_AC_CHECK_FUNC=${FUNCTION} -DL_AC_CHECK_FUNC_stub='defined __stub_${FUNCTION} || defined __stub___${FUNCTION}'"
+ "${MACRO_CHECK_FUNCTION_EXISTS_NOT_STUB_FLAGS}"
+ "${MACRO_CHECK_FUNCTION_EXISTS_NOT_STUB_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT
+ )
+ endif()
+ if(${VARIABLE})
+ set(${VARIABLE} 1 CACHE INTERNAL "Have function ${FUNCTION}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if function ${FUNCTION} is a stub "
+ "passed with the following output:\n"
+ "${OUTPUT}\n\n")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for stubbed out ${FUNCTION} - no stub")
+ endif()
+ else()
+ set(${VARIABLE} "" CACHE INTERNAL "Have function ${FUNCTION}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if function ${FUNCTION} is a stub "
+ "failed with the following output:\n"
+ "${OUTPUT}\n\n")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for stubbed out ${FUNCTION} - stub found")
+ endif()
+ endif()
+ endif()
+endmacro()
diff --git a/lib/interception/interception_linux.cc b/lib/interception/interception_linux.cc
index 6e908ac..c9b4a6e 100644
--- a/lib/interception/interception_linux.cc
+++ b/lib/interception/interception_linux.cc
@@ -24,11 +24,13 @@ bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
return real == wrapper;
}
+#ifdef HAVE_DLVSYM
#if !defined(__ANDROID__) // android does not have dlvsym
void *GetFuncAddrVer(const char *func_name, const char *ver) {
return dlvsym(RTLD_NEXT, func_name, ver);
}
#endif // !defined(__ANDROID__)
+#endif // HAVE_DLVSYM
} // namespace __interception
diff --git a/lib/interception/interception_linux.h b/lib/interception/interception_linux.h
index d3f774b..4802fe5 100644
--- a/lib/interception/interception_linux.h
+++ b/lib/interception/interception_linux.h
@@ -25,7 +25,9 @@ namespace __interception {
// returns true if a function with the given name was found.
bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
uptr real, uptr wrapper);
+# ifdef HAVE_DLVSYM
void *GetFuncAddrVer(const char *func_name, const char *ver);
+# endif /* HAVE_DLVSYM */
} // namespace __interception
#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
@@ -43,5 +45,12 @@ void *GetFuncAddrVer(const char *func_name, const char *ver);
INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
#endif // !defined(__ANDROID__)
+#ifndef HAVE_DLVSYM
+/* Undo marketing crap above. Probe functionality, use result to decide. */
+# undef INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD
+# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+#endif
+
#endif // INTERCEPTION_LINUX_H
#endif // __linux__ || __FreeBSD__
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 0d076a0..0a767d4 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -1273,33 +1273,43 @@ static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
static THREADLOCAL __sanitizer_glob_t *pglob_copy;
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
static void wrapped_gl_closedir(void *dir) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
IndirectExternCall(pglob_copy->gl_closedir)(dir);
}
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
static void *wrapped_gl_readdir(void *dir) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
return IndirectExternCall(pglob_copy->gl_readdir)(dir);
}
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
static void *wrapped_gl_opendir(const char *s) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
return IndirectExternCall(pglob_copy->gl_opendir)(s);
}
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
static int wrapped_gl_lstat(const char *s, void *st) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
return IndirectExternCall(pglob_copy->gl_lstat)(s, st);
}
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
static int wrapped_gl_stat(const char *s, void *st) {
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
return IndirectExternCall(pglob_copy->gl_stat)(s, st);
}
+#endif
INTERCEPTOR(int, glob, const char *pattern, int flags,
int (*errfunc)(const char *epath, int eerrno),
@@ -1307,24 +1317,64 @@ INTERCEPTOR(int, glob, const char *pattern, int flags,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
__sanitizer_glob_t glob_copy = {
- 0, 0, 0,
- 0, wrapped_gl_closedir, wrapped_gl_readdir,
- wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat};
+ 0,
+ 0,
+ 0
+#ifdef HAVE_GLOB_T_GL_FLAGS
+ ,0
+#endif
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
+ ,wrapped_gl_closedir
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
+ ,wrapped_gl_readdir
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
+ ,wrapped_gl_opendir
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
+ ,wrapped_gl_lstat
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
+ ,wrapped_gl_stat
+#endif
+ };
+
if (flags & glob_altdirfunc) {
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
Swap(pglob->gl_stat, glob_copy.gl_stat);
+#endif
pglob_copy = &glob_copy;
}
int res = REAL(glob)(pattern, flags, errfunc, pglob);
if (flags & glob_altdirfunc) {
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
Swap(pglob->gl_stat, glob_copy.gl_stat);
+#endif
}
pglob_copy = 0;
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
@@ -1337,24 +1387,63 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags,
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
__sanitizer_glob_t glob_copy = {
- 0, 0, 0,
- 0, wrapped_gl_closedir, wrapped_gl_readdir,
- wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat};
+ 0,
+ 0,
+ 0
+#ifdef HAVE_GLOB_T_GL_FLAGS
+ ,0
+#endif
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
+ ,wrapped_gl_closedir
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
+ ,wrapped_gl_readdir
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
+ ,wrapped_gl_opendir
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
+ ,wrapped_gl_lstat
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
+ ,wrapped_gl_stat
+#endif
+ };
if (flags & glob_altdirfunc) {
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
Swap(pglob->gl_stat, glob_copy.gl_stat);
+#endif
pglob_copy = &glob_copy;
}
int res = REAL(glob64)(pattern, flags, errfunc, pglob);
if (flags & glob_altdirfunc) {
+#ifdef HAVE_GLOB_T_GL_CLOSEDIR
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+#endif
+#ifdef HAVE_GLOB_T_GL_READDIR
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+#endif
+#ifdef HAVE_GLOB_T_GL_OPENDIR
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+#endif
+#ifdef HAVE_GLOB_T_GL_LSTAT
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+#endif
+#ifdef HAVE_GLOB_T_GL_STAT
Swap(pglob->gl_stat, glob_copy.gl_stat);
+#endif
}
pglob_copy = 0;
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
index 9ae4870..645777f 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -103,14 +103,18 @@
#endif
#if SANITIZER_LINUX || SANITIZER_FREEBSD
+# ifdef HAVE_UTIME_H
# include <utime.h>
+# endif
# include <sys/ptrace.h>
#endif
#if !SANITIZER_ANDROID
#include <ifaddrs.h>
#include <sys/ucontext.h>
+# ifdef HAVE_WORDEXP_H
#include <wordexp.h>
+# endif
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -119,7 +123,9 @@
#include <net/if_ppp.h>
#include <netax25/ax25.h>
#include <netipx/ipx.h>
+# ifdef HAVE_NETROM_NETROM_H
#include <netrom/netrom.h>
+# endif
#include <rpc/xdr.h>
#include <scsi/scsi.h>
#include <sys/mtio.h>
@@ -128,7 +134,9 @@
#include <sys/statvfs.h>
#include <sys/timex.h>
#include <sys/user.h>
+# ifdef HAVE_SYS_USTAT_H
#include <sys/ustat.h>
+# endif
#include <linux/cyclades.h>
#include <linux/if_eql.h>
#include <linux/if_plip.h>
@@ -215,12 +223,16 @@ namespace __sanitizer {
#if SANITIZER_LINUX || SANITIZER_FREEBSD
unsigned struct_rlimit_sz = sizeof(struct rlimit);
unsigned struct_timespec_sz = sizeof(struct timespec);
+# ifdef HAVE_UTIME_H
unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
+# endif
unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
#if SANITIZER_LINUX && !SANITIZER_ANDROID
+# ifdef HAVE_SYS_USTAT_H
unsigned struct_ustat_sz = sizeof(struct ustat);
+# endif
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
@@ -266,7 +278,9 @@ namespace __sanitizer {
#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
int glob_nomatch = GLOB_NOMATCH;
+# ifdef GLOB_ALTDIRFUNC
int glob_altdirfunc = GLOB_ALTDIRFUNC;
+# endif
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
@@ -370,7 +384,9 @@ namespace __sanitizer {
unsigned struct_kbkeycode_sz = sizeof(struct kbkeycode);
unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
+# ifdef HAVE_NETROM_NETROM_H
unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
+# endif
unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
unsigned struct_scc_stat_sz = sizeof(struct scc_stat);
unsigned struct_serial_multiport_struct_sz
@@ -805,10 +821,18 @@ namespace __sanitizer {
unsigned IOCTL_SIOCAX25SETPARMS = SIOCAX25SETPARMS;
unsigned IOCTL_SIOCDEVPLIP = SIOCDEVPLIP;
unsigned IOCTL_SIOCIPXCFGDATA = SIOCIPXCFGDATA;
+# ifdef SIOCNRDECOBS
unsigned IOCTL_SIOCNRDECOBS = SIOCNRDECOBS;
+# endif
+# ifdef SIOCNRGETPARMS
unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS;
+# endif
+# ifdef SIOCNRRTCTL
unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL;
+# endif
+# ifdef SIOCNRSETPARMS
unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS;
+# endif
unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL;
unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI;
unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
@@ -890,12 +914,24 @@ CHECK_TYPE_SIZE(glob_t);
CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+# ifdef HAVE_GLOB_T_GL_FLAGS
CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
+# endif
+# ifdef HAVE_GLOB_T_GL_CLOSEDIR
CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
+# endif
+# ifdef HAVE_GLOB_T_GL_READDIR
CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
+# endif
+# ifdef HAVE_GLOB_T_GL_OPENDIR
CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
+# endif
+# ifdef HAVE_GLOB_T_GL_LSTAT
CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
+# endif
+# ifdef HAVE_GLOB_T_GL_STAT
CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
+# endif
#endif
CHECK_TYPE_SIZE(addrinfo);
@@ -967,11 +1003,17 @@ CHECK_TYPE_SIZE(sigset_t);
COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
// Can't write checks for sa_handler and sa_sigaction due to them being
// preprocessor macros.
+#if HAVE_STRUCT_SIGACTION_SA_MASK_LAST
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+#else // HAVE_STRUCT_SIGACTION_SA_MASK_LAST
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
#if SANITIZER_LINUX
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
#endif
+#endif // HAVE_STRUCT_SIGACTION_SA_MASK_LAST
#if SANITIZER_LINUX
CHECK_TYPE_SIZE(__sysctl_args);
@@ -991,7 +1033,7 @@ CHECK_TYPE_SIZE(__kernel_loff_t);
CHECK_TYPE_SIZE(__kernel_fd_set);
#endif
-#if !SANITIZER_ANDROID
+#ifdef HAVE_WORDEXP_H
CHECK_TYPE_SIZE(wordexp_t);
CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index a780ee2..04c6a96 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -478,7 +478,8 @@ namespace __sanitizer {
#elif SANITIZER_LINUX
struct __sanitizer_sigset_t {
// The size is determined by looking at sizeof of real sigset_t on linux.
- uptr val[128 / sizeof(uptr)];
+ /* .. except this should be * sizeof(uptr), not '/', no? */
+ uptr val[SIZEOF_SIGSET_T / sizeof(uptr)];
};
#elif SANITIZER_FREEBSD
struct __sanitizer_sigset_t {
@@ -487,6 +488,17 @@ namespace __sanitizer {
};
#endif
+#if HAVE_STRUCT_SIGACTION_SA_MASK_LAST
+ struct __sanitizer_sigaction {
+ union {
+ void (*sigaction)(int sig, void *siginfo, void *uctx);
+ void (*handler)(int sig);
+ };
+ STRUCT_SIGACTION_SA_FLAGS_TYPE sa_flags;
+ void (*sa_restorer)();
+ __sanitizer_sigset_t sa_mask;
+ };
+#else // HAVE_STRUCT_SIGACTION_SA_MASK_LAST
// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
struct __sanitizer_sigaction {
union {
@@ -504,6 +516,7 @@ namespace __sanitizer {
void (*sa_restorer)();
#endif
};
+#endif // HAVE_STRUCT_SIGACTION_SA_MASK_LAST
#if SANITIZER_FREEBSD
typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
@@ -588,13 +601,25 @@ namespace __sanitizer {
uptr gl_pathc;
char **gl_pathv;
uptr gl_offs;
+# ifdef HAVE_GLOB_T_GL_FLAGS
int gl_flags;
+# endif
+# ifdef HAVE_GLOB_T_GL_CLOSEDIR
void (*gl_closedir)(void *dirp);
+# endif
+# ifdef HAVE_GLOB_T_GL_READDIR
void *(*gl_readdir)(void *dirp);
+# endif
+# ifdef HAVE_GLOB_T_GL_OPENDIR
void *(*gl_opendir)(const char *);
+# endif
+# ifdef HAVE_GLOB_T_GL_LSTAT
int (*gl_lstat)(const char *, void *);
+# endif
+# ifdef HAVE_GLOB_T_GL_STAT
int (*gl_stat)(const char *, void *);
+# endif
};
# elif SANITIZER_FREEBSD
struct __sanitizer_glob_t {
diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc
index bb6e587..973f698 100644
--- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -73,7 +73,16 @@ void SleepForSeconds(int seconds) {
}
void SleepForMillis(int millis) {
+#ifdef HAVE_NANOSLEEP
+ struct timespec ts;
+ ts.tv_sec = millis / 1000;
+ ts.tv_nsec = (millis % 1000) * 1000000;
+ nanosleep(&ts, NULL); /* could as well loop here */
+#elif defined HAVE_USLEEP
usleep(millis * 1000);
+# else
+ dunno how to SleepForMillis
+#endif
}
void Abort() {
diff --git a/make/platform/clang_linux.mk b/make/platform/clang_linux.mk
index c6921ea..5ce1567 100644
--- a/make/platform/clang_linux.mk
+++ b/make/platform/clang_linux.mk
@@ -74,6 +74,185 @@ Arch.dfsan-x86_64 := x86_64
Arch.lsan-x86_64 := x86_64
endif
+# TryCompile2 compiler source flags
+# Returns exit code of running a compiler invocation.
+# Same as TryCompile but in outer scope, don't want to touch the other one
+TryCompile2 = \
+ $(shell \
+ cflags=""; \
+ for flag in $(3); do \
+ cflags="$$cflags $$flag"; \
+ done; \
+ $(1) $$cflags $(2) -o /dev/null > /dev/null 2> /dev/null ; \
+ echo $$?)
+
+# our conftest.c
+ct_c = $(ProjSrcRoot)/make/platform/clang_linux_test_libc.c
+
+HAVE_DLVSYM := 1
+HAVE_NETROM_NETROM_H := 1
+HAVE_GLOB_H := 1
+HAVE_NANOSLEEP := 1
+HAVE_GLOB_T_GL_CLOSEDIR := 1
+HAVE_GLOB_T_GL_FLAGS := 1
+HAVE_GLOB_T_GL_LSTAT := 1
+HAVE_GLOB_T_GL_OPENDIR := 1
+HAVE_GLOB_T_GL_READDIR := 1
+HAVE_GLOB_T_GL_STAT := 1
+HAVE_STRUCT_SIGACTION_SA_MASK_LAST := 0
+HAVE_SYS_USTAT_H := 1
+HAVE_USLEEP := 1
+HAVE_UTIME_H := 1
+HAVE_WORDEXP_H := 1
+SIZEOF_STRUCT_STATFS64 := 120
+SIZEOF_SIGSET_T := 128
+STRUCT_SIGACTION_SA_FLAGS_TYPE := int
+
+#ifneq ($(findstring -uclibc,$(CompilerTargetTriple)),)
+# does not work, cross-compilation seems to be non-working?
+ifeq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_UCLIBC -DL_AC_CHECK_HEADER="<stdio.h>",),0)
+ HAVE_DLVSYM :=
+ HAVE_NETROM_NETROM_H :=
+ STRUCT_SIGACTION_SA_FLAGS_TYPE := unsigned long
+ifneq ($(filter alpha%,$(CompilerTargetTriple)),)
+ STRUCT_SIGACTION_SA_FLAGS_TYPE := unsigned
+endif
+ifneq ($(filter mips%,$(CompilerTargetTriple)),)
+ STRUCT_SIGACTION_SA_FLAGS_TYPE := unsigned
+endif
+ HAVE_STRUCT_SIGACTION_SA_MASK_LAST := 1
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_HEADER="<sys/ustat.h>",),0)
+ HAVE_SYS_USTAT_H :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_HEADER="<utime.h>",),0)
+ HAVE_UTIME_H :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_HEADER="<wordexp.h>",),0)
+ HAVE_WORDEXP_H :=
+endif
+glob_h := -DL_AC_CHECK_HEADER="<glob.h>"
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN $(glob_h),),0)
+ HAVE_GLOB_H :=
+endif
+# check for struct glob members (check for GNU extensions)
+glob_h += -DL_AC_STRUCT="glob_t"
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_flags,),0)
+ HAVE_GLOB_T_GL_FLAGS :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_closedir,),0)
+ HAVE_GLOB_T_GL_CLOSEDIR :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_readdir,),0)
+ HAVE_GLOB_T_GL_READDIR :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_opendir,),0)
+ HAVE_GLOB_T_GL_OPENDIR :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_lstat,),0)
+ HAVE_GLOB_T_GL_LSTAT :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) $(glob_h) -DL_AC_CHECK_STRUCT_MEMBER=gl_stat,),0)
+ HAVE_GLOB_T_GL_STAT :=
+endif
+# check misc functions
+# for __stub_* on glibc and uClibc including features.h is enough
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_features_h -DL_AC_CHECK_FUNC=nanosleep -DL_AC_CHECK_FUNC_stub="defined __stub_nanosleep || defined __stub___nanosleep",),0)
+ HAVE_NANOSLEEP :=
+endif
+ifneq ($(call TryCompile2,$(CC),$(ct_c) -DL_features_h -DL_AC_CHECK_FUNC=usleep -DL_AC_CHECK_FUNC_stub="defined __stub_usleep || defined __stub___usleep",),0)
+ HAVE_USLEEP :=
+endif
+
+# AC_CHECK_SIZEOF, in make
+define ac_check_sizeof
+$(shell \
+if test $$($(CC) $(1) -DL_AC_SIZEOF_GE=0 -o /dev/null > /dev/null 2> /dev/null; echo $$?) -eq 0; \
+then \
+ ac_lo=0 ac_mid=0; \
+ while :; \
+ do \
+ if test $$($(CC) $(1) -DL_AC_SIZEOF_LE=$$ac_mid -o /dev/null > /dev/null 2> /dev/null; echo $$?) -eq 0; then \
+ ac_hi=$$ac_mid; \
+ break; \
+ else \
+ ac_lo=$$(( $$ac_mid + 1 )); \
+ if test $$ac_lo -le $$ac_mid; then ac_lo= ac_hi=; break; fi; \
+ ac_mid=$$(( 2 * $$ac_mid + 1 )); \
+ fi; \
+ done; \
+else \
+ if test $$($(CC) $(1) -DL_AC_SIZEOF_LT=0 -o /dev/null > /dev/null 2> /dev/null; echo $$?) -eq 0; then \
+ ac_hi=-1 ac_mid=-1; \
+ while :; \
+ do \
+ if test $$($(CC) $(1) -DL_AC_SIZEOF_GE=$$ac_mid -o /dev/null > /dev/null 2> /dev/null; echo $$?) -eq 0; then \
+ ac_lo=$$ac_mid; \
+ break; \
+ else \
+ ac_hi=$$(( ($$ac_mid) - 1 )); \
+ if test $$ac_mid -le $$ac_hi; then ac_lo= ac_hi=; break; fi; \
+ ac_mid=$$(( 2 * $$ac_mid )); \
+ fi; \
+ done; \
+ else \
+ ac_lo= ac_hi=; \
+ fi; \
+fi; \
+while test "x$$ac_lo" != "x$$ac_hi"; \
+do \
+ ac_mid=$$(( ($$ac_hi - $$ac_lo) / 2 + $$ac_lo )); \
+ if test $$($(CC) $(1) -DL_AC_SIZEOF_LE=$$ac_mid -o /dev/null > /dev/null 2> /dev/null; echo $$?) -eq 0; then \
+ ac_hi=$$ac_mid; \
+ else \
+ ac_lo=$$(( ($$ac_mid) + 1 )); \
+ fi; \
+done; \
+echo $$(( $$ac_lo + 0 )); \
+)
+endef
+
+# determine sizeof sigset_t
+SIZEOF_SIGSET_T := $(call ac_check_sizeof,$(ct_c) -DL_AC_CHECK_HEADER="<signal.h>" -DL_AC_SIZEOF="sigset_t")
+
+# determine sizeof struct statfs64
+SIZEOF_STRUCT_STATFS64 := 0
+ifeq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_HEADER="<sys/statfs.h>",),0)
+SIZEOF_STRUCT_STATFS64 := $(call ac_check_sizeof,$(ct_c) -DL_AC_CHECK_HEADER="<sys/statfs.h>" -DL_AC_SIZEOF="struct statfs64")
+else
+ ifeq ($(call TryCompile2,$(CC),$(ct_c) -DL_MAIN -DL_AC_CHECK_HEADER="<sys/vfs.h>",),0)
+ SIZEOF_STRUCT_STATFS64 := $(call ac_check_sizeof,$(ct_c) -DL_AC_CHECK_HEADER="<sys/vfs.h>" -DL_AC_SIZEOF="struct statfs64")
+ endif
+endif
+# end of -uclibc handling
+endif
+
+define add_config_h_cppflag
+ifeq ($($(1)),)
+CONFIG_H_CPPFLAGS += -U$(1)
+else
+CONFIG_H_CPPFLAGS += '-D$(1)=$($(1))'
+endif
+endef
+
+CONFIG_H_CPPFLAGS :=
+$(eval $(call add_config_h_cppflag,HAVE_DLVSYM))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_H))
+$(eval $(call add_config_h_cppflag,HAVE_NANOSLEEP))
+$(eval $(call add_config_h_cppflag,HAVE_NETROM_NETROM_H))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_CLOSEDIR))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_FLAGS))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_LSTAT))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_OPENDIR))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_READDIR))
+$(eval $(call add_config_h_cppflag,HAVE_GLOB_T_GL_STAT))
+$(eval $(call add_config_h_cppflag,HAVE_STRUCT_SIGACTION_SA_MASK_LAST))
+$(eval $(call add_config_h_cppflag,HAVE_SYS_USTAT_H))
+$(eval $(call add_config_h_cppflag,HAVE_USLEEP))
+$(eval $(call add_config_h_cppflag,HAVE_UTIME_H))
+$(eval $(call add_config_h_cppflag,HAVE_WORDEXP_H))
+$(eval $(call add_config_h_cppflag,SIZEOF_STRUCT_STATFS64))
+$(eval $(call add_config_h_cppflag,SIZEOF_SIGSET_T))
+$(eval $(call add_config_h_cppflag,STRUCT_SIGACTION_SA_FLAGS_TYPE))
endif
ifneq ($(LLVM_ANDROID_TOOLCHAIN_DIR),)
@@ -87,6 +266,7 @@ endif
CFLAGS := -Wall -Werror -O3 -fomit-frame-pointer
SANITIZER_CFLAGS := -fPIE -fno-builtin -gline-tables-only
+CFLAGS += $(CONFIG_H_CPPFLAGS)
CFLAGS.full-i386 := $(CFLAGS) -m32
CFLAGS.full-x86_64 := $(CFLAGS) -m64
diff --git a/make/platform/clang_linux_test_libc.c b/make/platform/clang_linux_test_libc.c
new file mode 100644
index 0000000..2f9bba8
--- /dev/null
+++ b/make/platform/clang_linux_test_libc.c
@@ -0,0 +1,68 @@
+/* This file is used to check for libc characteristics and features */
+#ifdef L_features_h
+# include <features.h>
+#endif
+
+#ifdef L_AC_CHECK_HEADER
+/* compile-time check for availability of a header */
+# include L_AC_CHECK_HEADER
+#endif
+
+#ifdef L_AC_CHECK_UCLIBC
+# ifndef __UCLIBC__
+choke me /* not uClibc */
+# endif
+#endif
+
+#ifdef L_MAIN
+/* provide a dummy main for the linker */
+int main()
+{
+ return 0;
+}
+#endif
+
+#ifdef L_AC_CHECK_STRUCT_MEMBER
+/* compile-time check for presence of struct member */
+int main()
+{
+ static L_AC_STRUCT ac_aggr;
+ if (ac_aggr.L_AC_CHECK_STRUCT_MEMBER)
+ return 0;
+ return 0;
+}
+#endif
+
+#ifdef L_AC_CHECK_FUNC
+/* check if function (or macro) is available */
+# ifdef __cplusplus
+extern "C"
+# endif
+# if L_AC_CHECK_FUNC_stub
+choke me /* function 'L_AC_CHECK_FUNC' stubbed out! */
+# endif
+char L_AC_CHECK_FUNC ();
+int main ()
+{
+ return L_AC_CHECK_FUNC ();
+}
+#endif
+
+#ifdef L_AC_SIZEOF
+/* Determine sizeof expression */
+int main ()
+{
+# define s (long int) (sizeof (L_AC_SIZEOF))
+# if defined L_AC_SIZEOF_GE
+ static int test_array [1 - 2 * !((s) >= L_AC_SIZEOF_GE)];
+# elif defined L_AC_SIZEOF_LE
+ static int test_array [1 - 2 * !((s) <= L_AC_SIZEOF_LE)];
+# elif defined L_AC_SIZEOF_LT
+ static int test_array [1 - 2 * !((s) < L_AC_SIZEOF_LT)];
+# else
+# error no such comparison operator
+# endif
+ test_array [0] = 0;
+ return 0;
+}
+#endif
--
1.9.1
More information about the llvm-commits
mailing list