This repository has been archived by the owner on Sep 22, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
CMakeLists.txt
293 lines (255 loc) · 11.7 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# *-* Mode: cmake; *-*
cmake_minimum_required(VERSION 3.1.0)
project(rd C CXX ASM)
# "Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property."
# This avoids linking executables with -rdynamic. -rdynamic has been observed
# to cause rd_exec_stub to be linked with the dynamic linker with some
# version(s) of clang (but linked to an incorrect file name, causing
# exec of rd_exec_stub to fail).
if(POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
# On single configuration generators, make Debug the default configuration
if(NOT CMAKE_CONFIGURATION_TYPES)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Whether to build in `Debug` or `Release` mode." FORCE)
endif()
endif()
set(BUILD_SHARED_LIBS ON)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/rd)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(FLAGS_COMMON "-msse2 -D__MMX__ -D__SSE__ -D__SSE2__ -D__USE_LARGEFILE64 -pthread")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS_COMMON} -Wstrict-prototypes -std=gnu11")
# Define __STDC_LIMIT_MACROS so |#include <stdint.h>| works as expected.
# Define __STDC_FORMAT_MACROS so |#include <inttypes.h>| works as expected.
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" SUPPORTS_CXX14)
if (SUPPORTS_CXX14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS_COMMON} -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -std=c++14")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS_COMMON} -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS -std=c++11")
endif()
# We support three build types:
# DEBUG: suitable for debugging rd
# RELEASE: suitable for using rd in production (but keeps rd debuginfo)
# OTHER: suitable for using rd in production, but honouring distro/user opt/debug settings
# (which we assume are suitable for production use)
# Base settings for debug and release/unspecified builds.
# Use -Werror for debug builds because we assume a developer is building, not a user.
set(RD_FLAGS_DEBUG "-Wall -Wextra -DDEBUG -UNDEBUG")
set(RD_FLAGS_RELEASE "-Wall -Wextra -UDEBUG -DNDEBUG")
# The folowing settings are the defaults for the OTHER build type.
# Flags used to build the preload library. MUST have debuginfo enabled. SHOULD be optimized.
set(PRELOAD_COMPILE_FLAGS "${RD_FLAGS_RELEASE} -fno-stack-protector -g3")
# Flags used to build other files. Entirely build-type-dependent.
set(RD_FLAGS ${RD_FLAGS_RELEASE})
# Now override for build type.
string(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_CMAKE_BUILD_TYPE)
if(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL "debug")
set(PRELOAD_COMPILE_FLAGS "${PRELOAD_COMPILE_FLAGS} -O2 -Werror")
set(RD_FLAGS "${RD_FLAGS_DEBUG} -g3 -Werror")
elseif(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL "release")
# CMake itself will add optimization flags
set(RD_FLAGS "${RD_FLAGS_RELEASE} -g3")
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument")
endif()
if (CMAKE_ASM_COMPILER_ID STREQUAL "Clang")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -fno-integrated-as")
endif()
option(force32bit "Force a 32-bit rd build, rather than both 64 and 32-bit. rd will only be able to record and replay 32-bit processes.")
option(disable32bit "On a 64-bit platform, avoid requiring a 32-bit cross-compilation toolchain by not building 32-bit components. rd will be able to record 32-bit processes but not replay them.")
if(force32bit)
set(rd_32BIT true)
set(rd_64BIT false)
set(rd_MBITNESS_OPTION -m32)
else()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(disable32bit)
set(rd_32BIT false)
else()
set(rd_32BIT true)
endif()
set(rd_64BIT true)
else()
set(rd_32BIT true)
set(rd_64BIT false)
endif()
set(rd_MBITNESS_OPTION)
endif()
# Check that compiling 32-bit code on a 64-bit target works, if required.
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64" AND rd_32BIT)
# try_compile won't accept LINK_FLAGS, so do this manually.
file(WRITE "${CMAKE_BINARY_DIR}/test32.c" "int main() { return 0; }")
execute_process(COMMAND ${CMAKE_C_COMPILER} -o ${CMAKE_BINARY_DIR}/test32 ${CMAKE_BINARY_DIR}/test32.c -m32
RESULT_VARIABLE COMPILER_32BIT_RESULT)
if(NOT (COMPILER_32BIT_RESULT EQUAL 0))
message(FATAL_ERROR "Your toolchain doesn't support 32-bit cross-compilation. Install the required packages or pass -Ddisable32bit=ON to cmake.")
endif()
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${rd_MBITNESS_OPTION}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${rd_MBITNESS_OPTION}")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${rd_MBITNESS_OPTION}")
find_path(SECCOMP NAMES "linux/seccomp.h")
if(NOT SECCOMP)
message(FATAL_ERROR "Couldn't find linux/seccomp.h. You may need to upgrade your kernel.")
endif()
set(Python_ADDITIONAL_VERSIONS 3 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
find_package(PythonInterp 3 REQUIRED)
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "# nothing"
RESULT_VARIABLE python_status)
if(python_status)
message(FATAL_ERROR "Couldn't run python interpreter ${PYTHON_EXECUTABLE}.")
endif()
include_directories("${PROJECT_SOURCE_DIR}/include")
# We need to know where our generated files are.
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
# Order matters here! syscall_hook.S must be immediately before syscallbuf.c,
# breakpoint_table.S must be before overrides.c, which must be last.
set(PRELOAD_FILES
syscall_hook.S
syscallbuf.c
raw_syscall.S
breakpoint_table.S
overrides.c
)
set(PRELOAD_SOURCE_FILES
${PRELOAD_FILES}
preload_interface.h
syscallbuf.h
)
add_library(rdpreload)
foreach(file ${PRELOAD_FILES})
target_sources(rdpreload PUBLIC "${CMAKE_SOURCE_DIR}/src/preload/${file}")
set_source_files_properties("${CMAKE_SOURCE_DIR}/src/preload/${file}"
PROPERTIES COMPILE_FLAGS ${PRELOAD_COMPILE_FLAGS})
endforeach(file)
set_target_properties(rdpreload PROPERTIES LINK_FLAGS "-nostartfiles")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64_replay"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64_replay"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32_replay"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32_replay"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_rd_page.py")
# @TODO Is adding `ALL` here what we really want?
add_custom_target(Pages ALL DEPENDS
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32_replay"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64_replay")
function(post_build_executable target)
# grsecurity needs these. But if we add them ourselves, they may conflict
# with other flags added in other ways, and they all have to match :-(. So
# don't do this until a better solution presents itself
# add_custom_command(TARGET ${target}
# POST_BUILD
# COMMAND setfattr ARGS -n user.pax.flags -v m $<TARGET_FILE:${target}>)
endfunction(post_build_executable)
if(UNIX)
include(GNUInstallDirs)
else()
set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_DATADIR "share")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATADIR}/doc")
set(CMAKE_INSTALL_INCLUDEDIR "include")
endif()
target_link_libraries(rdpreload
${CMAKE_DL_LIBS}
)
add_executable(rd_exec_stub src/exec_stub.c)
post_build_executable(rd_exec_stub)
set_target_properties(rd_exec_stub
PROPERTIES LINK_FLAGS "-static -nostartfiles -nodefaultlibs")
set_source_files_properties(src/exec_stub.c
COMPILE_FLAGS "-fno-stack-protector")
set(RD_GDB_RESOURCES
32bit-avx.xml
32bit-core.xml
32bit-linux.xml
32bit-sse.xml
64bit-avx.xml
64bit-core.xml
64bit-linux.xml
64bit-seg.xml
64bit-sse.xml
amd64-avx-linux.xml
amd64-linux.xml
i386-avx-linux.xml
i386-linux.xml
)
foreach(file ${RD_GDB_RESOURCES})
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/third-party/gdb/${file}"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/${file}"
COPYONLY)
install(FILES third-party/gdb/${file}
DESTINATION ${CMAKE_INSTALL_DATADIR}/rd)
endforeach(file)
foreach(file ${PRELOAD_SOURCE_FILES})
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}"
"${CMAKE_CURRENT_BINARY_DIR}/share/rd/src/preload/${file}"
COPYONLY)
install(FILES src/preload/${file}
DESTINATION ${CMAKE_INSTALL_DATADIR}/rd/src/preload)
endforeach(file)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64
${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_64_replay
${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32
${CMAKE_CURRENT_BINARY_DIR}/share/rd/rd_page_32_replay
DESTINATION ${CMAKE_INSTALL_DATADIR}/rd)
install(TARGETS rdpreload rd_exec_stub
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rd
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/rd)
# Build 32-bit librdpreload on 64-bit builds.
# We copy the source files into '32' subdirectories in the output
# directory, so we can set different compile options on them.
# This sucks but I can't find a better way to get CMake to build
# the same source file in two different ways.
if(rd_32BIT AND rd_64BIT)
add_library(rdpreload_32)
foreach(file ${PRELOAD_SOURCE_FILES})
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}"
"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}"
COPYONLY)
endforeach(file)
foreach(file ${PRELOAD_FILES})
target_sources(rdpreload_32 PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}")
set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}"
PROPERTIES COMPILE_FLAGS "-m32 ${PRELOAD_COMPILE_FLAGS}")
endforeach(file)
set_target_properties(rdpreload_32 PROPERTIES LINK_FLAGS "-m32 -nostartfiles")
target_link_libraries(rdpreload_32
${CMAKE_DL_LIBS}
)
foreach(file exec_stub.c)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/${file}"
"${CMAKE_CURRENT_BINARY_DIR}/32/${file}"
COPYONLY)
set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/32/${file}"
PROPERTIES COMPILE_FLAGS "-m32 -fno-stack-protector")
endforeach(file)
add_executable(rd_exec_stub_32 32/exec_stub.c)
post_build_executable(rd_exec_stub_32)
set_target_properties(rd_exec_stub_32
PROPERTIES LINK_FLAGS "-static -nostartfiles -nodefaultlibs -m32")
install(TARGETS rdpreload_32 rd_exec_stub_32
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rd
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/rd)
endif()