[compiler-rt] r274657 - [compilter-rt] Add unittests for interception library
Etienne Bergeron via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 6 14:10:16 PDT 2016
Ok, I think I've found the issue.
These tests need to be fixed on Apple.
On Wed, Jul 6, 2016 at 4:59 PM, Manman Ren <mren at apple.com> wrote:
> 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
>
>
--
Etienne Bergeron
Chrome
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160706/cba45671/attachment.html>
More information about the llvm-commits
mailing list