# GIT_SHALLOW requires cmake 3.6. cmake_minimum_required(VERSION 3.10) project(funchook VERSION 2.0.0 LANGUAGES C ASM) include("GNUInstallDirs") if(NOT FUNCHOOK_CPU) set(FUNCHOOK_CPU ${CMAKE_SYSTEM_PROCESSOR}) if (FUNCHOOK_CPU MATCHES "x86_64" OR FUNCHOOK_CPU MATCHES "i.86" OR FUNCHOOK_CPU MATCHES "AMD64") set(FUNCHOOK_CPU x86) endif () if (FUNCHOOK_CPU MATCHES "aarch64") set(FUNCHOOK_CPU arm64) endif () if (FUNCHOOK_CPU MATCHES "ARM64") set(FUNCHOOK_CPU arm64) endif () endif () if (FUNCHOOK_CPU MATCHES "arm64") set(FUNCHOOK_DEFAULT_DISASM "capstone") else () set(FUNCHOOK_DEFAULT_DISASM "distorm") endif () option(FUNCHOOK_BUILD_SHARED "build shared library" OFF) option(FUNCHOOK_BUILD_STATIC "build static library" ON) option(FUNCHOOK_BUILD_TESTS "Build tests" OFF) option(FUNCHOOK_INSTALL "Install Funchook" OFF) set(FUNCHOOK_DISASM ${FUNCHOOK_DEFAULT_DISASM} CACHE STRING "disassembler engine") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") set(_GNU_SOURCE 1) include(CheckCSourceCompiles) # musl libc doesn't provide the GNU-specific version of strerror_r # even when _GNU_SOURCE is defined. check_c_source_compiles( "#define _GNU_SOURCE 1 #include int main() { char dummy[128]; return *strerror_r(0, dummy, sizeof(dummy)); } " GNU_SPECIFIC_STRERROR_R ) endif () include(CheckCCompilerFlag) check_c_compiler_flag(-fvisibility=hidden HAVE_FVISIBILITY_HIDDEN) if (FUNCHOOK_DISASM STREQUAL capstone) set(DISASM_CAPSTONE 1) elseif (FUNCHOOK_DISASM STREQUAL distorm) set(DISASM_DISTORM 1) elseif (FUNCHOOK_DISASM STREQUAL zydis) set(DISASM_ZYDIS 1) else () message(FATAL_ERROR "Unknown FUNCHOOK_DISASM type: ${FUNCHOOK_DISASM}") endif () if (CMAKE_TOOLCHAIN_FILE) get_filename_component(TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") else () set(TOOLCHAIN_FILE "") endif () if (WIN32) set(FUNCHOOK_OS windows) set(FUNCHOOK_DEPS psapi) else () set(FUNCHOOK_OS unix) set(FUNCHOOK_DEPS dl) endif () function(add_subdirectory_pic source_dir binary_dir) set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_subdirectory(${source_dir} ${binary_dir}) endfunction(add_subdirectory_pic) # # capstone # if (DISASM_CAPSTONE) string(TOUPPER ${FUNCHOOK_CPU} FUNCHOOK_CPU_UPPER) set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "") set(CAPSTONE_BUILD_STATIC_RUNTIME OFF CACHE BOOL "") set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "") set(CAPSTONE_BUILD_CSTOOL OFF CACHE BOOL "") set(CAPSTONE_ARCHITECTURE_DEFAULT OFF CACHE BOOL "") set(CAPSTONE_${FUNCHOOK_CPU_UPPER}_SUPPORT ON CACHE BOOL "") add_subdirectory_pic(capstone capstone) list(APPEND FUNCHOOK_DEPS capstone-static) set(DISASM capstone) endif () # # distorm # if (DISASM_DISTORM) set(DISTORM_PATH distorm/) set(DISTORM_SRC_DIR ${DISTORM_PATH}/src/) set(DISTORM_SOURCES ${DISTORM_SRC_DIR}/decoder.c ${DISTORM_SRC_DIR}/distorm.c ${DISTORM_SRC_DIR}/instructions.c ${DISTORM_SRC_DIR}/insts.c ${DISTORM_SRC_DIR}/mnemonics.c ${DISTORM_SRC_DIR}/operands.c ${DISTORM_SRC_DIR}/prefix.c ${DISTORM_SRC_DIR}/textdefs.c) if (MSVC) # Suppress warning C4819: # The file contains a character that cannot be represented in the current code # page (number). Save the file in Unicode format to prevent data loss. # # prefix.c includes non-ascii chracters and C compiler warns C4819 on multibyte Windows # environment. set_source_files_properties(${DISTORM_SRC_DIR}/prefix.c PROPERTIES COMPILE_FLAGS /wd4819) endif () add_library(distorm STATIC ${DISTORM_SOURCES}) set_target_properties(distorm PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories(distorm PUBLIC ${DISTORM_PATH}/include) if (HAVE_FVISIBILITY_HIDDEN) target_compile_options(distorm PRIVATE -fvisibility=hidden) endif () set(DISASM distorm) list(APPEND FUNCHOOK_DEPS distorm) endif () # # zydis # if (DISASM_ZYDIS) include(ExternalProject) ExternalProject_Add(Zydis_src GIT_REPOSITORY https://github.com/zyantific/zydis.git GIT_TAG v3.1.0 GIT_SHALLOW TRUE CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DZYDIS_BUILD_SHARED_LIB=OFF -DZYDIS_BUILD_EXAMPLES=OFF -DZYDIS_BUILD_TOOLS=OFF INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install && ${CMAKE_COMMAND} --build zycore --target install ) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/include) add_library(Zydis STATIC IMPORTED) set_property(TARGET Zydis PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}Zydis${CMAKE_STATIC_LIBRARY_SUFFIX}) set_property(TARGET Zydis PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_BINARY_DIR}/include) list(APPEND FUNCHOOK_DEPS Zydis) set(DISASM Zydis) endif () # # funchook # set(FUNCHOOK_SOURCES src/funchook.c src/arch_${FUNCHOOK_CPU}.c src/os_${FUNCHOOK_OS}.c src/disasm_${DISASM}.c) if ((FUNCHOOK_CPU STREQUAL x86) AND (CMAKE_SIZEOF_VOID_P EQUAL "8")) if (MSVC) # Microsoft x64 calling convention (Microsoft Visual C++) enable_language(ASM_MASM) set(FUNCHOOK_SOURCES ${FUNCHOOK_SOURCES} src/prehook-x86_64-ms.asm) elseif (WIN32) # Microsoft x64 calling convention (Mingw-w64) set(FUNCHOOK_SOURCES ${FUNCHOOK_SOURCES} src/prehook-x86_64-ms.S) else () # System V ABI (Linux, macOS) set(FUNCHOOK_SOURCES ${FUNCHOOK_SOURCES} src/prehook-x86_64-sysv.S) endif () endif () set(FUNCHOOK_PROPERTIES OUTPUT_NAME funchook VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} DEFINE_SYMBOL FUNCHOOK_EXPORTS) configure_file(src/cmake_config.h.in config.h) function (add_funchook_library target_name target_type) add_library(${target_name} ${target_type} ${FUNCHOOK_SOURCES}) if (DISASM_ZYDIS) add_dependencies(${target_name} Zydis_src) endif () set_target_properties(${target_name} PROPERTIES ${FUNCHOOK_PROPERTIES}) target_include_directories(${target_name} PUBLIC include) target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # to include config.h if (DISASM_CAPSTONE) target_include_directories(${target_name} PRIVATE capstone/include) endif() target_link_libraries(${target_name} PRIVATE ${FUNCHOOK_DEPS}) if (HAVE_FVISIBILITY_HIDDEN) target_compile_options(${target_name} PRIVATE -fvisibility=hidden) endif () if (CMAKE_COMPILER_IS_GNUCC) target_compile_options(${target_name} PRIVATE -Wall) endif () endfunction () if (FUNCHOOK_BUILD_SHARED) add_funchook_library(funchook-shared SHARED) if (MINGW) set_target_properties(funchook-shared PROPERTIES PREFIX "") endif () if (MSVC) set_target_properties(funchook-shared PROPERTIES IMPORT_SUFFIX _dll.lib) endif () endif () if (FUNCHOOK_BUILD_STATIC) add_funchook_library(funchook-static STATIC) endif () # # tests # enable_testing() if (FUNCHOOK_BUILD_TESTS) add_subdirectory(test) endif () # # install # if (FUNCHOOK_INSTALL) install(FILES include/funchook.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) if (FUNCHOOK_BUILD_SHARED) install(TARGETS funchook-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) if (MSVC) install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) endif () endif () if (FUNCHOOK_BUILD_STATIC) install(TARGETS funchook-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () endif ()