diff mbox

[3/3,LLVM,sanitizer] add conditionals for libc

Message ID 1397742577-22841-4-git-send-email-rep.dot.nop@gmail.com
State New
Headers show

Commit Message

Bernhard Reutner-Fischer April 17, 2014, 1:49 p.m. UTC
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@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

Comments

Konstantin Serebryany April 17, 2014, 2:07 p.m. UTC | #1
Hi,

If you are trying to modify the libsanitizer files, please read here:
https://code.google.com/p/address-sanitizer/wiki/HowToContribute

--kcc

On Thu, Apr 17, 2014 at 5:49 PM, Bernhard Reutner-Fischer
<rep.dot.nop@gmail.com> wrote:
> 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@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
>
Bernhard Reutner-Fischer April 17, 2014, 2:27 p.m. UTC | #2
On 17 April 2014 16:07, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> Hi,
>
> If you are trying to modify the libsanitizer files, please read here:
> https://code.google.com/p/address-sanitizer/wiki/HowToContribute

I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
please install it there, i do not have write access to the LLVM nor
compiler-rt trees.
TIA,
>
> --kcc
>
> On Thu, Apr 17, 2014 at 5:49 PM, Bernhard Reutner-Fischer
> <rep.dot.nop@gmail.com> wrote:
>> 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@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
>>
Konstantin Serebryany April 17, 2014, 2:51 p.m. UTC | #3
On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
<rep.dot.nop@gmail.com> wrote:
> On 17 April 2014 16:07, Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>> Hi,
>>
>> If you are trying to modify the libsanitizer files, please read here:
>> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
>
> I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
> please install it there, i do not have write access to the LLVM nor
> compiler-rt trees.

I can commit your patch to llvm tree only after you follow the process
described on that page.
Sorry, this is a hard rule.

--kcc

> TIA,
>>
>> --kcc
>>
>> On Thu, Apr 17, 2014 at 5:49 PM, Bernhard Reutner-Fischer
>> <rep.dot.nop@gmail.com> wrote:
>>> 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@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
>>>
Bernhard Reutner-Fischer April 17, 2014, 4:45 p.m. UTC | #4
On 17 April 2014 16:51:23 Konstantin Serebryany 
<konstantin.s.serebryany@gmail.com> wrote:

> On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
> <rep.dot.nop@gmail.com> wrote:
> > On 17 April 2014 16:07, Konstantin Serebryany
> > <konstantin.s.serebryany@gmail.com> wrote:
> >> Hi,
> >>
> >> If you are trying to modify the libsanitizer files, please read here:
> >> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
> >
> > I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
> > please install it there, i do not have write access to the LLVM nor
> > compiler-rt trees.
>
> I can commit your patch to llvm tree only after you follow the process
> described on that page.
> Sorry, this is a hard rule.

What part of the process do you think I did not follow?

I made a patch for compiler-rt, sent it to llvm-commits@cs.uiuc.edu then 
provided the corresponding GCC parts, along a backport of the new bits that 
I expect to be overwritten once you do a new merge, leaving just the GCC 
configuy bits. This is how I read the wiki page you cite.

Please tell me what you expect me to do differently?

Thanks,
>
> --kcc


Sent with AquaMail for Android
http://www.aqua-mail.com
Konstantin Serebryany April 17, 2014, 5:01 p.m. UTC | #5
On Thu, Apr 17, 2014 at 8:45 PM, Bernhard Reutner-Fischer
<rep.dot.nop@gmail.com> wrote:
> On 17 April 2014 16:51:23 Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>
>> On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
>> <rep.dot.nop@gmail.com> wrote:
>> > On 17 April 2014 16:07, Konstantin Serebryany
>> > <konstantin.s.serebryany@gmail.com> wrote:
>> >> Hi,
>> >>
>> >> If you are trying to modify the libsanitizer files, please read here:
>> >> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
>> >
>> > I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
>> > please install it there, i do not have write access to the LLVM nor
>> > compiler-rt trees.
>>
>> I can commit your patch to llvm tree only after you follow the process
>> described on that page.
>> Sorry, this is a hard rule.
>
>
> What part of the process do you think I did not follow?
>
> I made a patch for compiler-rt, sent it to llvm-commits@cs.uiuc.edu then
> provided the corresponding GCC parts, along a backport of the new bits that
> I expect to be overwritten once you do a new merge, leaving just the GCC
> configuy bits. This is how I read the wiki page you cite.
>
> Please tell me what you expect me to do differently?

First, I did not notice that you've sent it to llvm-commits because it
was also sent to the gcc list (unusual thing to happen)
and got filtered into the gcc part of my mail. Sorry.
But second, the patch is far from trivial and you should not expect us
to commit it w/o a careful review,
so here comes another part of the wiki: "For non-trivial patches
please use Phabricator -- this will help us reply faster."

--kcc


>
> Thanks,
>>
>>
>> --kcc
>
>
>
> Sent with AquaMail for Android
> http://www.aqua-mail.com
>
>
Bernhard Reutner-Fischer April 23, 2014, 8:46 a.m. UTC | #6
On 17 April 2014 19:01, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> On Thu, Apr 17, 2014 at 8:45 PM, Bernhard Reutner-Fischer
> <rep.dot.nop@gmail.com> wrote:
>> On 17 April 2014 16:51:23 Konstantin Serebryany
>> <konstantin.s.serebryany@gmail.com> wrote:
>>
>>> On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
>>> <rep.dot.nop@gmail.com> wrote:
>>> > On 17 April 2014 16:07, Konstantin Serebryany
>>> > <konstantin.s.serebryany@gmail.com> wrote:
>>> >> Hi,
>>> >>
>>> >> If you are trying to modify the libsanitizer files, please read here:
>>> >> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
>>> >
>>> > I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
>>> > please install it there, i do not have write access to the LLVM nor
>>> > compiler-rt trees.
>>>
>>> I can commit your patch to llvm tree only after you follow the process
>>> described on that page.
>>> Sorry, this is a hard rule.
>>
>>
>> What part of the process do you think I did not follow?
>>
>> I made a patch for compiler-rt, sent it to llvm-commits@cs.uiuc.edu then
>> provided the corresponding GCC parts, along a backport of the new bits that
>> I expect to be overwritten once you do a new merge, leaving just the GCC
>> configuy bits. This is how I read the wiki page you cite.
>>
>> Please tell me what you expect me to do differently?
>
> First, I did not notice that you've sent it to llvm-commits because it
> was also sent to the gcc list (unusual thing to happen)
> and got filtered into the gcc part of my mail. Sorry.
> But second, the patch is far from trivial and you should not expect us
> to commit it w/o a careful review,
> so here comes another part of the wiki: "For non-trivial patches
> please use Phabricator -- this will help us reply faster."

http://reviews.llvm.org/D3464

thanks,
Konstantin Serebryany April 23, 2014, 8:58 a.m. UTC | #7
Thanks. Let's move the discussion there.

On Wed, Apr 23, 2014 at 12:46 PM, Bernhard Reutner-Fischer
<rep.dot.nop@gmail.com> wrote:
> On 17 April 2014 19:01, Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>> On Thu, Apr 17, 2014 at 8:45 PM, Bernhard Reutner-Fischer
>> <rep.dot.nop@gmail.com> wrote:
>>> On 17 April 2014 16:51:23 Konstantin Serebryany
>>> <konstantin.s.serebryany@gmail.com> wrote:
>>>
>>>> On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
>>>> <rep.dot.nop@gmail.com> wrote:
>>>> > On 17 April 2014 16:07, Konstantin Serebryany
>>>> > <konstantin.s.serebryany@gmail.com> wrote:
>>>> >> Hi,
>>>> >>
>>>> >> If you are trying to modify the libsanitizer files, please read here:
>>>> >> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
>>>> >
>>>> > I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
>>>> > please install it there, i do not have write access to the LLVM nor
>>>> > compiler-rt trees.
>>>>
>>>> I can commit your patch to llvm tree only after you follow the process
>>>> described on that page.
>>>> Sorry, this is a hard rule.
>>>
>>>
>>> What part of the process do you think I did not follow?
>>>
>>> I made a patch for compiler-rt, sent it to llvm-commits@cs.uiuc.edu then
>>> provided the corresponding GCC parts, along a backport of the new bits that
>>> I expect to be overwritten once you do a new merge, leaving just the GCC
>>> configuy bits. This is how I read the wiki page you cite.
>>>
>>> Please tell me what you expect me to do differently?
>>
>> First, I did not notice that you've sent it to llvm-commits because it
>> was also sent to the gcc list (unusual thing to happen)
>> and got filtered into the gcc part of my mail. Sorry.
>> But second, the patch is far from trivial and you should not expect us
>> to commit it w/o a careful review,
>> so here comes another part of the wiki: "For non-trivial patches
>> please use Phabricator -- this will help us reply faster."
>
> http://reviews.llvm.org/D3464
>
> thanks,
Bernhard Reutner-Fischer Sept. 21, 2018, 8:25 a.m. UTC | #8
On Wed, 23 Apr 2014 at 10:58, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
>
> Thanks. Let's move the discussion there.

4-early ping..
Thanks to Yuri for his remark there.
Just asking if any of you folks had more comments?

thanks,
>
> On Wed, Apr 23, 2014 at 12:46 PM, Bernhard Reutner-Fischer
> <rep.dot.nop@gmail.com> wrote:
> > On 17 April 2014 19:01, Konstantin Serebryany
> > <konstantin.s.serebryany@gmail.com> wrote:
> >> On Thu, Apr 17, 2014 at 8:45 PM, Bernhard Reutner-Fischer
> >> <rep.dot.nop@gmail.com> wrote:
> >>> On 17 April 2014 16:51:23 Konstantin Serebryany
> >>> <konstantin.s.serebryany@gmail.com> wrote:
> >>>
> >>>> On Thu, Apr 17, 2014 at 6:27 PM, Bernhard Reutner-Fischer
> >>>> <rep.dot.nop@gmail.com> wrote:
> >>>> > On 17 April 2014 16:07, Konstantin Serebryany
> >>>> > <konstantin.s.serebryany@gmail.com> wrote:
> >>>> >> Hi,
> >>>> >>
> >>>> >> If you are trying to modify the libsanitizer files, please read here:
> >>>> >> https://code.google.com/p/address-sanitizer/wiki/HowToContribute
> >>>> >
> >>>> > I read that, thanks. Patch 3/3 is for current compiler-rt git repo,
> >>>> > please install it there, i do not have write access to the LLVM nor
> >>>> > compiler-rt trees.
> >>>>
> >>>> I can commit your patch to llvm tree only after you follow the process
> >>>> described on that page.
> >>>> Sorry, this is a hard rule.
> >>>
> >>>
> >>> What part of the process do you think I did not follow?
> >>>
> >>> I made a patch for compiler-rt, sent it to llvm-commits@cs.uiuc.edu then
> >>> provided the corresponding GCC parts, along a backport of the new bits that
> >>> I expect to be overwritten once you do a new merge, leaving just the GCC
> >>> configuy bits. This is how I read the wiki page you cite.
> >>>
> >>> Please tell me what you expect me to do differently?
> >>
> >> First, I did not notice that you've sent it to llvm-commits because it
> >> was also sent to the gcc list (unusual thing to happen)
> >> and got filtered into the gcc part of my mail. Sorry.
> >> But second, the patch is far from trivial and you should not expect us
> >> to commit it w/o a careful review,
> >> so here comes another part of the wiki: "For non-trivial patches
> >> please use Phabricator -- this will help us reply faster."
> >
> > http://reviews.llvm.org/D3464
> >
> > thanks,
diff mbox

Patch

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