Skip to content

Commit

Permalink
CMake improvements and refactor of __remill_basic_block (#447)
Browse files Browse the repository at this point in the history
* Append project name to the check_git target to fix compound builds (#446)
* Change the way we get registers for __remill_basic_block so that it's the Arch class of the target that actually populates the function, and isn't based on reverse-engineering what's visible in the function as compiled by llvm
* Renamed a cmake var to reduce likelihood of conflicts, and tries to make sure remill only links against static llvm libraries
* Fix instruction dominance issues
* Minor fix on the type of PC on x86
* Added new implementation (in Arch.cpp) of the AArch64 __remill_basic_block function

Co-authored-by: Artem Dinaburg <artem@trailofbits.com>
Co-authored-by: Eric Kilmer <eric.d.kilmer@gmail.com>
  • Loading branch information
3 people authored Sep 17, 2020
1 parent 5f74c38 commit 3a16ad4
Show file tree
Hide file tree
Showing 28 changed files with 1,372 additions and 1,679 deletions.
226 changes: 193 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ include(CTest)
if (LLVM_Z3_INSTALL_DIR)
find_package(Z3 4.7.1)
set(need_z3 TRUE)
elseif(DEFINED ENV{TRAILOFBITS_LIBRARIES})
set(LLVM_Z3_INSTALL_DIR "$ENV{TRAILOFBITS_LIBRARIES}/z3")
elseif(DEFINED CXX_COMMON_REPOSITORY_ROOT)
set(LLVM_Z3_INSTALL_DIR "${CXX_COMMON_REPOSITORY_ROOT}/z3")
set(need_z3 TRUE)
else()
set(need_z3 FALSE)
Expand Down Expand Up @@ -67,38 +67,80 @@ endif()
# libraries
#

# LLVM
find_package(LLVM REQUIRED CONFIG HINTS ${FINDPACKAGE_LLVM_HINTS})

string(REPLACE "." ";" LLVM_VERSION_LIST ${LLVM_PACKAGE_VERSION})
list(GET LLVM_VERSION_LIST 0 LLVM_MAJOR_VERSION)
list(GET LLVM_VERSION_LIST 1 LLVM_MINOR_VERSION)

set(LLVM_LIBRARIES
LLVMCore LLVMAnalysis LLVMSupport LLVMipo LLVMIRReader
LLVMBitReader LLVMBitWriter LLVMTransformUtils LLVMScalarOpts
LLVMLTO
add_library(thirdparty_llvm INTERFACE)
target_include_directories(thirdparty_llvm SYSTEM INTERFACE
${LLVM_INCLUDE_DIRS}
)
target_compile_definitions(thirdparty_llvm INTERFACE
${LLVM_DEFINITIONS}
)

# Go find only the static libraries of LLVM, and link against those.
foreach(LLVM_LIB IN LISTS LLVM_AVAILABLE_LIBS)
get_target_property(LLVM_LIB_TYPE ${LLVM_LIB} TYPE)
if(LLVM_LIB_TYPE STREQUAL "STATIC_LIBRARY")
list(APPEND LLVM_LIBRARIES "${LLVM_LIB}")
endif()
endforeach()

# These are out-of-order in `LLVM_AVAILABLE_LIBS` and should always be last.
list(REMOVE_ITEM LLVM_LIBRARIES LLVMMC LLVMCore LLVMSupport)
list(APPEND LLVM_LIBRARIES LLVMMC LLVMCore LLVMSupport)
message(WARNING "Libraries: ${LLVM_LIBRARIES}")


target_link_libraries(thirdparty_llvm INTERFACE
${LLVM_LIBRARIES}
)

list(APPEND PROJECT_LIBRARIES ${LLVM_LIBRARIES})
list(APPEND PROJECT_DEFINITIONS ${LLVM_DEFINITIONS})
list(APPEND PROJECT_INCLUDEDIRECTORIES ${LLVM_INCLUDE_DIRS})
# Microsoft Z3
add_library(thirdparty_z3 INTERFACE)
if(Z3_FOUND)
target_include_directories(thirdparty_z3 SYSTEM INTERFACE
${Z3_INCLUDE_DIR}
)
target_link_libraries(thirdparty_z3 INTERFACE
${Z3_LIBRARIES}
)
endif()

# xed
# Intel XED
find_package(XED REQUIRED)
list(APPEND PROJECT_LIBRARIES ${XED_LIBRARIES})
list(APPEND PROJECT_INCLUDEDIRECTORIES ${XED_INCLUDE_DIRS})
add_library(thirdparty_xed INTERFACE)
target_include_directories(thirdparty_xed SYSTEM INTERFACE
${XED_INCLUDE_DIRS}
)
target_link_libraries(thirdparty_xed INTERFACE
${XED_LIBRARIES}
)

# google log module
# Google glog module
find_package(glog REQUIRED)
list(APPEND PROJECT_LIBRARIES glog::glog)
add_library(thirdparty_glog INTERFACE)
target_link_libraries(thirdparty_glog INTERFACE
glog::glog
)

# gflags
# Google gflags
find_package(gflags REQUIRED)
list(APPEND PROJECT_LIBRARIES gflags)
add_library(thirdparty_gflags INTERFACE)
target_link_libraries(thirdparty_gflags INTERFACE
gflags
)

# windows sdk
# Windows SDK
add_library(thirdparty_win32 INTERFACE)
if(DEFINED WIN32)
list(APPEND PROJECT_LIBRARIES "Kernel32.lib")
target_link_libraries(thirdparty_win32 INTERFACE
"Kernel32.lib"
)
endif()

#
Expand All @@ -122,14 +164,10 @@ endif()
set(REMILL_BUILD_SEMANTICS_DIR_X86 "${CMAKE_CURRENT_BINARY_DIR}/remill/Arch/X86/Runtime/")
set(REMILL_BUILD_SEMANTICS_DIR_AARCH64 "${CMAKE_CURRENT_BINARY_DIR}/remill/Arch/AArch64/Runtime/")

list(APPEND PROJECT_DEFINITIONS "REMILL_INSTALL_SEMANTICS_DIR=\"${REMILL_INSTALL_SEMANTICS_DIR}/\"")
list(APPEND PROJECT_DEFINITIONS "REMILL_BUILD_SEMANTICS_DIR_X86=\"${REMILL_BUILD_SEMANTICS_DIR_X86}\"")
list(APPEND PROJECT_DEFINITIONS "REMILL_BUILD_SEMANTICS_DIR_AARCH64=\"${REMILL_BUILD_SEMANTICS_DIR_AARCH64}\"")

# verion data
add_subdirectory(remill/Version)

add_library(${PROJECT_NAME} STATIC
add_library(remill STATIC
remill/Arch/AArch64/Arch.cpp
remill/Arch/AArch64/Decode.cpp
remill/Arch/AArch64/Extract.cpp
Expand All @@ -151,14 +189,102 @@ add_library(${PROJECT_NAME} STATIC
remill/OS/OS.cpp
)

set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET remill PROPERTY POSITION_INDEPENDENT_CODE ON)
set(THIRDPARTY_LIBRARY_LIST thirdparty_z3 thirdparty_llvm thirdparty_xed thirdparty_glog thirdparty_gflags)

# add everything as public.
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_LIBRARIES} RemillVersion)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${PROJECT_INCLUDEDIRECTORIES})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_DEFINITIONS} ${GLOBAL_DEFINITIONS})
target_compile_options(${PROJECT_NAME} PUBLIC ${GLOBAL_CXXFLAGS})

if(UNIX AND NOT APPLE)
#For Linux builds, group LLVM libraries into a single group
# that avoids frustrating library ordering issues
set(LINKER_START_GROUP "-Wl,--start-group")
set(LINKER_END_GROUP "-Wl,--end-group")
else()
set(LINKER_START_GROUP "")
set(LINKER_END_GROUP "")
endif()


target_link_libraries(remill LINK_PUBLIC
${LINKER_START_GROUP} ${THIRDPARTY_LIBRARY_LIST} ${LINKER_END_GROUP}
RemillVersion
)

target_include_directories(remill PUBLIC ${CMAKE_SOURCE_DIR})

if(WIN32)
# warnings and compiler settings
target_compile_options(remill PUBLIC
/MD /nologo /W3 /EHsc /wd4141 /wd4146 /wd4180 /wd4244
/wd4258 /wd4267 /wd4291 /wd4345 /wd4351 /wd4355 /wd4456
/wd4457 /wd4458 /wd4459 /wd4503 /wd4624 /wd4722 /wd4800
/wd4100 /wd4127 /wd4512 /wd4505 /wd4610 /wd4510 /wd4702
/wd4245 /wd4706 /wd4310 /wd4701 /wd4703 /wd4389 /wd4611
/wd4805 /wd4204 /wd4577 /wd4091 /wd4592 /wd4324
)

target_compile_definitions(remill PUBLIC
_CRT_SECURE_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_DEPRECATE
_CRT_NONSTDC_NO_WARNINGS
_SCL_SECURE_NO_DEPRECATE
_SCL_SECURE_NO_WARNINGS
GOOGLE_PROTOBUF_NO_RTTI
)

else()
# warnings and compiler settings
target_compile_options(remill PUBLIC
-Wall -Wextra -Wno-unused-parameter -Wno-c++98-compat
-Wno-unreachable-code-return -Wno-nested-anon-types
-Wno-extended-offsetof
-Wno-variadic-macros -Wno-return-type-c-linkage
-Wno-c99-extensions -Wno-ignored-attributes -Wno-unused-local-typedef
-Wno-unknown-pragmas -Wno-unknown-warning-option -fPIC
-fno-omit-frame-pointer -fvisibility-inlines-hidden
-fno-asynchronous-unwind-tables
)

# Clang-specific warnings/error options
if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(remill PUBLIC
-Wgnu-alignof-expression -Wno-gnu-anonymous-struct -Wno-gnu-designator
-Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-statement-expression
-fno-aligned-allocation
)
endif()

# debug symbols
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
target_compile_options(remill PUBLIC
-gdwarf-2 -g3
)
endif()

# optimization flags and definitions
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(remill PUBLIC
-O0
)
target_compile_definitions(remill PUBLIC
"DEBUG"
)
else()
target_compile_options(remill PUBLIC
-O2
)
target_compile_definitions(remill PUBLIC
"NDEBUG"
)
endif()
endif()

target_compile_definitions(remill PUBLIC
"REMILL_INSTALL_SEMANTICS_DIR=\"${REMILL_INSTALL_SEMANTICS_DIR}/\""
"REMILL_BUILD_SEMANTICS_DIR_X86=\"${REMILL_BUILD_SEMANTICS_DIR_X86}\""
"REMILL_BUILD_SEMANTICS_DIR_AARCH64=\"${REMILL_BUILD_SEMANTICS_DIR_AARCH64}\""
)

#
# Also install clang, libllvm and llvm-link
Expand Down Expand Up @@ -234,7 +360,7 @@ endfunction()
set(INSTALLED_CLANG_NAME "remill-clang-${REMILL_LLVM_VERSION}${executable_extension}")
set(INSTALLED_LLVMLINK_NAME "remill-llvm-link-${REMILL_LLVM_VERSION}${executable_extension}")

if("${LIBRARY_REPOSITORY_ROOT}" STREQUAL "" OR NOT EXISTS "${LIBRARY_REPOSITORY_ROOT}/llvm")
if("${CXX_COMMON_REPOSITORY_ROOT}" STREQUAL "" OR NOT EXISTS "${CXX_COMMON_REPOSITORY_ROOT}/llvm")
set(INSTALLED_LIBLLVM_NAME "${dynamic_lib_prefix}LLVM-${REMILL_LLVM_VERSION}.${dynamic_lib_extension}")

# system binaries are not built statically, so we need to fix the rpath
Expand Down Expand Up @@ -268,10 +394,10 @@ if("${LIBRARY_REPOSITORY_ROOT}" STREQUAL "" OR NOT EXISTS "${LIBRARY_REPOSITORY_
else()
# The executable in our binary repository are statically built, meaning that we don't need
# to change the rpath
InstallExternalTarget("ext_clang" "${LIBRARY_REPOSITORY_ROOT}/llvm/bin/clang${executable_extension}"
InstallExternalTarget("ext_clang" "${CXX_COMMON_REPOSITORY_ROOT}/llvm/bin/clang${executable_extension}"
"${install_folder}/bin" "${INSTALLED_CLANG_NAME}")

InstallExternalTarget("ext_llvmlink" "${LIBRARY_REPOSITORY_ROOT}/llvm/bin/llvm-link${executable_extension}"
InstallExternalTarget("ext_llvmlink" "${CXX_COMMON_REPOSITORY_ROOT}/llvm/bin/llvm-link${executable_extension}"
"${install_folder}/bin" "${INSTALLED_LLVMLINK_NAME}")
endif()

Expand All @@ -282,9 +408,42 @@ install(TARGETS "${PROJECT_NAME}"

set(REMILL_LIBRARY_LOCATION "${install_folder}/lib/libremill.a")
set(REMILL_INCLUDE_LOCATION "${install_folder}/include")
get_target_property(REMILL_COMPILE_OPTIONS remill COMPILE_OPTIONS)
get_target_property(REMILL_COMPILE_DEFINITIONS remill COMPILE_DEFINITIONS)

GetTargetTree(THIRDPARTY_LIBRARIES ${THIRDPARTY_LIBRARY_LIST})
GetPublicIncludeFolders(THIRDPARTY_INCLUDE_DIRECTORIES ${THIRDPARTY_LIBRARIES})
foreach(THIRDPARTY_LIB IN LISTS THIRDPARTY_LIBRARIES)
string(SUBSTRING "${THIRDPARTY_LIB}" 0 1 THIRDPARTY_LIB_PREFIX)
if(TARGET ${THIRDPARTY_LIB})
get_target_property(THIRDPARTY_LIB_TYPE ${THIRDPARTY_LIB} TYPE)
if(THIRDPARTY_LIB_TYPE STREQUAL "STATIC_LIBRARY" OR THIRDPARTY_LIB_TYPE STREQUAL "SHARED_LIBRARY")
list(APPEND THIRDPARTY_LIBRARY_FILES "$${}<TARGET_FILE:${THIRDPARTY_LIB}>")
endif()
elseif("${THIRDPARTY_LIB_PREFIX}" STREQUAL "$${}")
# E.g. $<LINK_ONLY:...>
else()
list(APPEND THIRDPARTY_LIBRARY_FILES "${THIRDPARTY_LIB}")
endif()
endforeach()

list(REMOVE_DUPLICATES THIRDPARTY_LIBRARY_FILES)
if(NOT "x{$LINKER_START_GROUP}x" STREQUAL "xx")
list(INSERT THIRDPARTY_LIBRARY_FILES 0 "${LINKER_START_GROUP}")
list(APPEND THIRDPARTY_LIBRARY_FILES "${LINKER_END_GROUP}")
endif()

# First do the basic substitutions.
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/remillConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/remillConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/remillConfig.cmake.pregen"
@ONLY
)

# Then expand the generator expressions added to `THIRDPARTY_LIBRARY_FILES`.
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/remillConfig.cmake"
INPUT "${CMAKE_CURRENT_BINARY_DIR}/remillConfig.cmake.pregen"
)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/remillConfig.cmake"
Expand Down Expand Up @@ -316,6 +475,7 @@ install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/Attributes.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/BitcodeReaderWriter.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/CallingConvention.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/CTypes.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/DataLayout.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/DebugInfo.h"
"${CMAKE_CURRENT_SOURCE_DIR}/remill/BC/Compat/Error.h"
Expand Down
1 change: 1 addition & 0 deletions cmake/BCCompiler.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(DEFAULT_BC_COMPILER_FLAGS
-ffreestanding -fno-common -fno-builtin -fno-exceptions -fno-rtti
-fno-asynchronous-unwind-tables -Wno-unneeded-internal-declaration
-Wno-unused-function -Wgnu-inline-cpp-without-extern -std=c++14
-Wno-pass-failed=transform-warning
${EXTRA_BC_SYSROOT}
)

Expand Down
5 changes: 3 additions & 2 deletions cmake/git_watcher.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,18 @@ function(GetGitState _working_dir)

RunGitCommand(show -s "--format=%s" ${object})
if(exit_code EQUAL 0)
string(REPLACE "\"" "\\\"" output "${output}")
set(ENV{GIT_COMMIT_SUBJECT} "${output}")
endif()

RunGitCommand(show -s "--format=%b" ${object})
if(exit_code EQUAL 0)
if(output)
# Escape line breaks in the commit message.
string(REPLACE "\r\n" "\\r\\n\\\r\n" safe ${output})
string(REPLACE "\r\n" "\\r\\n\\\r\n" safe "${output}")
if(safe STREQUAL output)
# Didn't have windows lines - try unix lines.
string(REPLACE "\n" "\\n\\\n" safe ${output})
string(REPLACE "\n" "\\n\\\n" safe "${output}")
endif()
else()
# There was no commit body - set the safe string to empty.
Expand Down
28 changes: 18 additions & 10 deletions cmake/remillConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,28 @@ cmake_minimum_required(VERSION 3.2)

if(NOT TARGET remill)
if(WIN32)
set(REMILL_LIBRARY_LOCATION "${CMAKE_INSTALL_PREFIX}/remill/lib/remill.lib")
set(REMILL_INCLUDE_LOCATION "${CMAKE_INSTALL_PREFIX}/remill/include")
set(REMILL_LIBRARY_LOCATION "@CMAKE_INSTALL_PREFIX@/remill/lib/remill.lib")
set(REMILL_INCLUDE_LOCATION "@CMAKE_INSTALL_PREFIX@/remill/include")
else()
set(REMILL_LIBRARY_LOCATION "${CMAKE_INSTALL_PREFIX}/lib/libremill.a")
set(REMILL_INCLUDE_LOCATION "${CMAKE_INSTALL_PREFIX}/include")
set(REMILL_LIBRARY_LOCATION "@CMAKE_INSTALL_PREFIX@/lib/libremill.a")
set(REMILL_INCLUDE_LOCATION "@CMAKE_INSTALL_PREFIX@/include")
endif()

add_library(remill STATIC IMPORTED)
set_property(TARGET remill PROPERTY IMPORTED_LOCATION "${REMILL_LIBRARY_LOCATION}")
target_include_directories(remill INTERFACE "${REMILL_INCLUDE_LOCATION}")
if(NOT "x@CXX_COMMON_REPOSITORY_ROOT@x" STREQUAL "xx")
set(CXX_COMMON_REPOSITORY_ROOT "@CXX_COMMON_REPOSITORY_ROOT@")
endif()

target_compile_definitions(remill INTERFACE "REMILL_INSTALL_SEMANTICS_DIR=\"${REMILL_INSTALL_SEMANTICS_DIR}\"")
target_compile_definitions(remill INTERFACE "REMILL_BUILD_SEMANTICS_DIR_X86=\"${REMILL_INSTALL_SEMANTICS_DIR}\"")
target_compile_definitions(remill INTERFACE "REMILL_BUILD_SEMANTICS_DIR_AARCH64=\"${REMILL_INSTALL_SEMANTICS_DIR}\"")
set(LLVM_MAJOR_VERSION @LLVM_MAJOR_VERSION@)
set(LLVM_MINOR_VERSION @LLVM_MINOR_VERSION@)
set(REMILL_LLVM_VERSION "@LLVM_MAJOR_VERSION@.@LLVM_MINOR_VERSION@")

add_library(remill STATIC IMPORTED)
set_property(TARGET remill PROPERTY IMPORTED_LOCATION "@REMILL_LIBRARY_LOCATION@")
target_include_directories(remill INTERFACE @THIRDPARTY_INCLUDE_DIRECTORIES@)
target_include_directories(remill INTERFACE @REMILL_INCLUDE_LOCATION@)
target_compile_options(remill INTERFACE @REMILL_COMPILE_OPTIONS@)
target_compile_definitions(remill INTERFACE @REMILL_COMPILE_DEFINITIONS@)
target_link_libraries(remill INTERFACE @THIRDPARTY_LIBRARY_FILES@)

# Add a dummy 'semantics' target to satisfy the protobuf generator
add_custom_target(semantics)
Expand Down
Loading

0 comments on commit 3a16ad4

Please sign in to comment.