[compiler-rt] r274657 - [compilter-rt] Add unittests for interception library

Manman Ren via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 6 13:59:55 PDT 2016


This seems to trigger http://lab.llvm.org:8080/green/job/clang-stage1-configure-RA_build/22513/.

And it didn’t recover with the follow up commit r r274667 (http://lab.llvm.org:8080/green/job/clang-stage1-configure-RA_build/22515/).

Can you take a look?

Thanks,
Manman

> On Jul 6, 2016, at 12:15 PM, Etienne Bergeron via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> Author: etienneb
> Date: Wed Jul  6 14:15:11 2016
> New Revision: 274657
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=274657&view=rev
> Log:
> [compilter-rt] Add unittests for interception library
> 
> Summary:
> This patch is adding unittests for the interception library.
> 
> 
> Reviewers: rnk
> 
> Subscribers: majnemer, llvm-commits, wang0109, chrisha, tberghammer, danalbert, srhines
> 
> Differential Revision: http://reviews.llvm.org/D21980
> 
> Added:
>    compiler-rt/trunk/lib/interception/tests/
>    compiler-rt/trunk/lib/interception/tests/CMakeLists.txt
>    compiler-rt/trunk/lib/interception/tests/interception_linux_test.cc
>    compiler-rt/trunk/lib/interception/tests/interception_test_main.cc
>    compiler-rt/trunk/lib/interception/tests/interception_win_test.cc
> Modified:
>    compiler-rt/trunk/lib/interception/CMakeLists.txt
>    compiler-rt/trunk/lib/interception/interception_win.cc
> 
> Modified: compiler-rt/trunk/lib/interception/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/CMakeLists.txt?rev=274657&r1=274656&r2=274657&view=diff
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/CMakeLists.txt (original)
> +++ compiler-rt/trunk/lib/interception/CMakeLists.txt Wed Jul  6 14:15:11 2016
> @@ -17,3 +17,7 @@ add_compiler_rt_object_libraries(RTInter
>     ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH}
>     SOURCES ${INTERCEPTION_SOURCES}
>     CFLAGS ${INTERCEPTION_CFLAGS})
> +
> +if(COMPILER_RT_INCLUDE_TESTS)
> +  add_subdirectory(tests)
> +endif()
> 
> Modified: compiler-rt/trunk/lib/interception/interception_win.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_win.cc?rev=274657&r1=274656&r2=274657&view=diff
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/interception_win.cc (original)
> +++ compiler-rt/trunk/lib/interception/interception_win.cc Wed Jul  6 14:15:11 2016
> @@ -201,6 +201,7 @@ static size_t RoundUpToInstrBoundary(siz
>   size_t cursor = 0;
>   while (cursor < size) {
>     switch (code[cursor]) {
> +      case '\x50':  // push eax
>       case '\x51':  // push ecx
>       case '\x52':  // push edx
>       case '\x53':  // push ebx
> @@ -341,7 +342,7 @@ bool OverrideFunction(uptr old_func, upt
> }
> 
> static void **InterestingDLLsAvailable() {
> -  const char *InterestingDLLs[] = {
> +  static const char *InterestingDLLs[] = {
>       "kernel32.dll",
>       "msvcr110.dll",      // VS2012
>       "msvcr120.dll",      // VS2013
> 
> Added: compiler-rt/trunk/lib/interception/tests/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/tests/CMakeLists.txt?rev=274657&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/tests/CMakeLists.txt (added)
> +++ compiler-rt/trunk/lib/interception/tests/CMakeLists.txt Wed Jul  6 14:15:11 2016
> @@ -0,0 +1,147 @@
> +include(CompilerRTCompile)
> +
> +clang_compiler_add_cxx_check()
> +
> +filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el)
> +
> +set(INTERCEPTION_UNITTESTS
> +  interception_linux_test.cc
> +  interception_test_main.cc
> +  interception_win_test.cc
> +)
> +
> +set(INTERCEPTION_TEST_HEADERS)
> +
> +set(INTERCEPTION_TEST_CFLAGS_COMMON
> +  ${COMPILER_RT_UNITTEST_CFLAGS}
> +  ${COMPILER_RT_GTEST_CFLAGS}
> +  -I${COMPILER_RT_SOURCE_DIR}/include
> +  -I${COMPILER_RT_SOURCE_DIR}/lib
> +  -I${COMPILER_RT_SOURCE_DIR}/lib/interception
> +  -fno-rtti
> +  -O2
> +  -Werror=sign-compare
> +  -Wno-non-virtual-dtor)
> +
> +# -gline-tables-only must be enough for these tests, so use it if possible.
> +if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang")
> +  list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gline-tables-only)
> +else()
> +  list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -g)
> +endif()
> +if(MSVC)
> +  list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gcodeview)
> +endif()
> +list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -g)
> +
> +if(NOT MSVC)
> +  list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON --driver-mode=g++)
> +endif()
> +
> +if(ANDROID)
> +  list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -pie)
> +endif()
> +
> +set(INTERCEPTION_TEST_LINK_LIBS)
> +append_list_if(COMPILER_RT_HAS_LIBLOG log INTERCEPTION_TEST_LINK_LIBS)
> +# NDK r10 requires -latomic almost always.
> +append_list_if(ANDROID atomic INTERCEPTION_TEST_LINK_LIBS)
> +
> +append_list_if(COMPILER_RT_HAS_LIBDL -ldl INTERCEPTION_TEST_LINK_FLAGS_COMMON)
> +append_list_if(COMPILER_RT_HAS_LIBRT -lrt INTERCEPTION_TEST_LINK_FLAGS_COMMON)
> +append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread INTERCEPTION_TEST_LINK_FLAGS_COMMON)
> +# x86_64 FreeBSD 9.2 additionally requires libc++ to build the tests. Also,
> +# 'libm' shall be specified explicitly to build i386 tests.
> +if(CMAKE_SYSTEM MATCHES "FreeBSD-9.2-RELEASE")
> +  list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON "-lc++ -lm")
> +endif()
> +
> +include_directories(..)
> +include_directories(../..)
> +
> +# Adds static library which contains interception object file
> +# (universal binary on Mac and arch-specific object files on Linux).
> +macro(add_interceptor_lib library)
> +  add_library(${library} STATIC ${ARGN})
> +  set_target_properties(${library} PROPERTIES
> +    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
> +endmacro()
> +
> +function(get_interception_lib_for_arch arch lib lib_name)
> +  if(APPLE)
> +    set(tgt_name "RTInterception.test.osx")
> +  else()
> +    set(tgt_name "RTInterception.test.${arch}")
> +  endif()
> +  set(${lib} "${tgt_name}" PARENT_SCOPE)
> +  if(CMAKE_CONFIGURATION_TYPES)
> +   set(configuration_path "${CMAKE_CFG_INTDIR}/")
> +  else()
> +   set(configuration_path "")
> +  endif()
> +  if(NOT MSVC)
> +    set(${lib_name} "${configuration_path}lib${tgt_name}.a" PARENT_SCOPE)
> +  else()
> +    set(${lib_name} "${configuration_path}${tgt_name}.lib" PARENT_SCOPE)
> +  endif()
> +endfunction()
> +
> +# Interception unit tests testsuite.
> +add_custom_target(InterceptionUnitTests)
> +set_target_properties(InterceptionUnitTests PROPERTIES
> +  FOLDER "Compiler-RT Tests")
> +
> +# Adds interception tests for architecture.
> +macro(add_interception_tests_for_arch arch)
> +  get_target_flags_for_arch(${arch} TARGET_FLAGS)
> +  set(INTERCEPTION_TEST_SOURCES ${INTERCEPTION_UNITTESTS}
> +                             ${COMPILER_RT_GTEST_SOURCE})
> +  set(INTERCEPTION_TEST_COMPILE_DEPS ${INTERCEPTION_TEST_HEADERS})
> +  if(NOT COMPILER_RT_STANDALONE_BUILD)
> +    list(APPEND INTERCEPTION_TEST_COMPILE_DEPS gtest)
> +  endif()
> +  set(INTERCEPTION_TEST_OBJECTS)
> +  foreach(source ${INTERCEPTION_TEST_SOURCES})
> +    get_filename_component(basename ${source} NAME)
> +    if(CMAKE_CONFIGURATION_TYPES)
> +      set(output_obj "${CMAKE_CFG_INTDIR}/${basename}.${arch}.o")
> +    else()
> +      set(output_obj "${basename}.${arch}.o")
> +    endif()
> +    clang_compile(${output_obj} ${source}
> +                  CFLAGS ${INTERCEPTION_TEST_CFLAGS_COMMON} ${TARGET_FLAGS}
> +                  DEPS ${INTERCEPTION_TEST_COMPILE_DEPS})
> +    list(APPEND INTERCEPTION_TEST_OBJECTS ${output_obj})
> +  endforeach()
> +  get_interception_lib_for_arch(${arch} INTERCEPTION_COMMON_LIB
> +                                INTERCEPTION_COMMON_LIB_NAME)
> +  # Add unittest target.
> +  set(INTERCEPTION_TEST_NAME "Interception-${arch}-Test")
> +  add_compiler_rt_test(InterceptionUnitTests ${INTERCEPTION_TEST_NAME}
> +                       OBJECTS ${INTERCEPTION_TEST_OBJECTS}
> +                               ${INTERCEPTION_COMMON_LIB_NAME}
> +                       DEPS ${INTERCEPTION_TEST_OBJECTS} ${INTERCEPTION_COMMON_LIB}
> +                       LINK_FLAGS ${INTERCEPTION_TEST_LINK_FLAGS_COMMON}
> +                                  ${TARGET_FLAGS})
> +
> +
> +endmacro()
> +
> +if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
> +  # We use just-built clang to build interception unittests, so we must
> +  # be sure that produced binaries would work.
> +  if(APPLE)
> +    add_interceptor_lib("RTInterception.test.osx"
> +                        $<TARGET_OBJECTS:RTInterception.osx>)
> +  else()
> +    foreach(arch ${INTERCEPTION_UNITTEST_SUPPORTED_ARCH})
> +      add_interceptor_lib("RTInterception.test.${arch}"
> +                          $<TARGET_OBJECTS:RTInterception.${arch}>)
> +    endforeach()
> +  endif()
> +  foreach(arch ${INTERCEPTION_UNITTEST_SUPPORTED_ARCH})
> +    add_interception_tests_for_arch(${arch})
> +  endforeach()
> +endif()
> +
> +
> 
> Added: compiler-rt/trunk/lib/interception/tests/interception_linux_test.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/tests/interception_linux_test.cc?rev=274657&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/tests/interception_linux_test.cc (added)
> +++ compiler-rt/trunk/lib/interception/tests/interception_linux_test.cc Wed Jul  6 14:15:11 2016
> @@ -0,0 +1,65 @@
> +//===-- interception_linux_test.cc ----------------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
> +// Tests for interception_linux.h.
> +//
> +//===----------------------------------------------------------------------===//
> +#include "interception/interception.h"
> +
> +#include "gtest/gtest.h"
> +
> +// Too slow for debug build
> +#if !SANITIZER_DEBUG
> +#if SANITIZER_LINUX
> +
> +static int InterceptorFunctionCalled;
> +
> +DECLARE_REAL(int, isdigit, int);
> +
> +INTERCEPTOR(int, isdigit, int d) {
> +  ++InterceptorFunctionCalled;
> +  return d >= '0' && d <= '9';
> +}
> +
> +namespace __interception {
> +
> +TEST(Interception, GetRealFunctionAddress) {
> +  uptr expected_malloc_address = (uptr)(void*)&malloc;
> +  uptr malloc_address = 0;
> +  EXPECT_TRUE(GetRealFunctionAddress("malloc", &malloc_address, 0, 0));
> +  EXPECT_EQ(expected_malloc_address, malloc_address);
> +
> +  uptr dummy_address = 0;
> +  EXPECT_TRUE(
> +      GetRealFunctionAddress("dummy_doesnt_exist__", &dummy_address, 0, 0));
> +  EXPECT_EQ(0U, dummy_address);
> +}
> +
> +TEST(Interception, Basic) {
> +  ASSERT_TRUE(INTERCEPT_FUNCTION(isdigit));
> +
> +  // After interception, the counter should be incremented.
> +  InterceptorFunctionCalled = 0;
> +  EXPECT_NE(0, isdigit('1'));
> +  EXPECT_EQ(1, InterceptorFunctionCalled);
> +  EXPECT_EQ(0, isdigit('a'));
> +  EXPECT_EQ(2, InterceptorFunctionCalled);
> +
> +  // Calling the REAL function should not affect the counter.
> +  InterceptorFunctionCalled = 0;
> +  EXPECT_NE(0, REAL(isdigit)('1'));
> +  EXPECT_EQ(0, REAL(isdigit)('a'));
> +  EXPECT_EQ(0, InterceptorFunctionCalled);
> +}
> +
> +}  // namespace __interception
> +
> +#endif  // SANITIZER_LINUX
> +#endif  // #if !SANITIZER_DEBUG
> 
> Added: compiler-rt/trunk/lib/interception/tests/interception_test_main.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/tests/interception_test_main.cc?rev=274657&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/tests/interception_test_main.cc (added)
> +++ compiler-rt/trunk/lib/interception/tests/interception_test_main.cc Wed Jul  6 14:15:11 2016
> @@ -0,0 +1,22 @@
> +//===-- interception_test_main.cc------------------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file is a part of AddressSanitizer, an address sanity checker.
> +//
> +// Testing the machinery for providing replacements/wrappers for system
> +// functions.
> +//===----------------------------------------------------------------------===//
> +
> +#include "gtest/gtest.h"
> +
> +int main(int argc, char **argv) {
> +  testing::GTEST_FLAG(death_test_style) = "threadsafe";
> +  testing::InitGoogleTest(&argc, argv);
> +  return RUN_ALL_TESTS();
> +}
> 
> Added: compiler-rt/trunk/lib/interception/tests/interception_win_test.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/tests/interception_win_test.cc?rev=274657&view=auto
> ==============================================================================
> --- compiler-rt/trunk/lib/interception/tests/interception_win_test.cc (added)
> +++ compiler-rt/trunk/lib/interception/tests/interception_win_test.cc Wed Jul  6 14:15:11 2016
> @@ -0,0 +1,142 @@
> +//===-- interception_win_test.cc ------------------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
> +// Tests for interception_win.h.
> +//
> +//===----------------------------------------------------------------------===//
> +#include "interception/interception.h"
> +
> +#include "gtest/gtest.h"
> +
> +// Too slow for debug build
> +#if !SANITIZER_DEBUG
> +#if SANITIZER_WINDOWS
> +
> +#define WIN32_LEAN_AND_MEAN
> +#include <windows.h>
> +
> +namespace {
> +
> +typedef int (*IdentityFunction)(int);
> +
> +#if !SANITIZER_WINDOWS64
> +u8 kIdentityCodeWithPrologue[] = {
> +    0x55,              // push        ebp
> +    0x8B, 0xEC,        // mov         ebp,esp
> +    0x8B, 0x45, 0x08,  // mov         eax,dword ptr [ebp + 8]
> +    0x5D,              // pop         ebp
> +    0xC3,              // ret
> +};
> +
> +u8 kIdentityCodeWithPushPop[] = {
> +    0x55,              // push        ebp
> +    0x8B, 0xEC,        // mov         ebp,esp
> +    0x53,              // push        ebx
> +    0x50,              // push        eax
> +    0x58,              // pop         eax
> +    0x8B, 0x45, 0x08,  // mov         eax,dword ptr [ebp + 8]
> +    0x5B,              // pop         ebx
> +    0x5D,              // pop         ebp
> +    0xC3,              // ret
> +};
> +
> +#endif
> +
> +// A buffer holding the dynamically generated code under test.
> +u8* ActiveCode;
> +size_t ActiveCodeLength = 4096;
> +
> +bool LoadActiveCode(u8* Code, size_t CodeLength, uptr* EntryPoint) {
> +  if (ActiveCode == nullptr) {
> +    ActiveCode =
> +        (u8*)::VirtualAlloc(nullptr, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
> +                            PAGE_EXECUTE_READWRITE);
> +    if (ActiveCode == nullptr) return false;
> +  }
> +
> +  size_t Position = 0;
> +  *EntryPoint = (uptr)&ActiveCode[0];
> +
> +  // Copy the function body.
> +  for (size_t i = 0; i < CodeLength; ++i)
> +  	ActiveCode[Position++] = Code[i];
> +
> +  return true;
> +}
> +
> +int InterceptorFunctionCalled;
> +
> +NOINLINE int InterceptorFunction(int x) {
> +  ++InterceptorFunctionCalled;
> +  return x;
> +}
> +
> +}  // namespace
> +
> +namespace __interception {
> +
> +// Tests for interception_win.h
> +TEST(Interception, InternalGetProcAddress) {
> +  HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
> +  ASSERT_NE(nullptr, ntdll_handle);
> +  uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
> +  uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
> +  uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
> +  uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
> +
> +  EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
> +  EXPECT_EQ(isdigit_expected, isdigit_address);
> +  EXPECT_NE(DbgPrint_adddress, isdigit_address);
> +}
> +
> +void TestIdentityFunctionPatching(u8* IdentityCode, size_t IdentityCodeLength) {
> +  uptr IdentityAddress;
> +  ASSERT_TRUE(
> +      LoadActiveCode(IdentityCode, IdentityCodeLength, &IdentityAddress));
> +  IdentityFunction Identity = (IdentityFunction)IdentityAddress;
> +
> +  // Validate behavior before dynamic patching.
> +  InterceptorFunctionCalled = 0;
> +  EXPECT_EQ(0, Identity(0));
> +  EXPECT_EQ(42, Identity(42));
> +  EXPECT_EQ(0, InterceptorFunctionCalled);
> +
> +  // Patch the function.
> +  uptr RealIdentityAddress = 0;
> +  EXPECT_TRUE(OverrideFunction(IdentityAddress, (uptr)&InterceptorFunction,
> +                               &RealIdentityAddress));
> +  IdentityFunction RealIdentity = (IdentityFunction)RealIdentityAddress;
> +
> +  // Calling the redirected function.
> +  InterceptorFunctionCalled = 0;
> +  EXPECT_EQ(0, Identity(0));
> +  EXPECT_EQ(42, Identity(42));
> +  EXPECT_EQ(2, InterceptorFunctionCalled);
> +
> +  // Calling the real function.
> +  InterceptorFunctionCalled = 0;
> +  EXPECT_EQ(0, RealIdentity(0));
> +  EXPECT_EQ(42, RealIdentity(42));
> +  EXPECT_EQ(0, InterceptorFunctionCalled);
> +}
> +
> +#if !SANITIZER_WINDOWS64
> +TEST(Interception, OverrideFunction) {
> +  TestIdentityFunctionPatching(kIdentityCodeWithPrologue,
> +                               sizeof(kIdentityCodeWithPrologue));
> +  TestIdentityFunctionPatching(kIdentityCodeWithPushPop,
> +                               sizeof(kIdentityCodeWithPushPop));
> +}
> +#endif
> +
> +}  // namespace __interception
> +
> +#endif  // SANITIZER_WINDOWS
> +#endif  // #if !SANITIZER_DEBUG
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list