This repository has been archived by the owner on Oct 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
CMakeLists.txt
373 lines (293 loc) · 11.3 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
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# Copyright (c) 2018-present, Trail of Bits, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.9.3)
project(abigen)
include(cmake/cxxcommon.cmake)
include(cmake/globalsettings.cmake)
if(WIN32)
set(WINDOWS_INSTALL_ROOT "abigen")
set(PROFILE_INSTALL_FOLDER "${WINDOWS_INSTALL_ROOT}/data")
set(BINARY_INSTALL_FOLDER "${WINDOWS_INSTALL_ROOT}")
else()
set(PROFILE_INSTALL_FOLDER "share/abigen")
set(BINARY_INSTALL_FOLDER "bin")
endif()
set(COMMON_SOURCE_FILES
src/istatus.h
src/std_filesystem.h
src/types.h
src/profilemanager.h
src/profilemanager.cpp
src/languagemanager.h
src/languagemanager.cpp
src/cmdline.h
src/cmdline.cpp
src/list_commands.cpp
src/version_command.cpp
src/generate_command.h
src/generate_command.cpp
src/compile_command.cpp
src/generate_utils.h
src/generate_utils.cpp
src/compilerinstance.h
src/compilerinstance.cpp
src/abi_lib_generator.h
src/abi_lib_generator.cpp
src/astvisitor.h
src/astvisitor.cpp
)
function(abigen)
fetchAbigenVersionInformation()
set(source_files
${COMMON_SOURCE_FILES}
src/main.cpp
)
importLLVM()
set(abigen_target_name "${PROJECT_NAME}-${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
add_executable("${abigen_target_name}" ${source_files})
target_link_libraries("${abigen_target_name}" PRIVATE globalsettings stdc++fs)
target_compile_definitions("${abigen_target_name}" PRIVATE
PROFILE_INSTALL_FOLDER="${CMAKE_INSTALL_PREFIX}/${PROFILE_INSTALL_FOLDER}"
ABIGEN_COMMIT_DESCRIPTION="${ABIGEN_COMMIT_DESCRIPTION}"
ABIGEN_BRANCH_NAME="${ABIGEN_BRANCH_NAME}"
ABIGEN_COMMIT_HASH="${ABIGEN_COMMIT_HASH}"
)
generateInstallTargets("${abigen_target_name}")
importJson11()
importCli11()
target_link_libraries("${abigen_target_name}" PRIVATE json11 cli11 llvm_libraries)
generateMcsemaTestTargets()
endfunction()
function(fetchAbigenVersionInformation)
message(STATUS "Fetching version information from git...")
execute_process(
COMMAND git fetch --tags --all
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_QUIET
ERROR_QUIET
TIMEOUT 15
)
execute_process(
COMMAND git describe --tags --always --abbrev=0
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE abigen_commit_description
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(ABIGEN_COMMIT_DESCRIPTION "${abigen_commit_description}" PARENT_SCOPE)
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE abigen_commit_hash
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(ABIGEN_COMMIT_HASH "${abigen_commit_hash}" PARENT_SCOPE)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE abigen_branch_name
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(ABIGEN_BRANCH_NAME "${abigen_branch_name}" PARENT_SCOPE)
endfunction()
function(generateMcsemaTestTargets)
if(NOT "${CMAKE_CXX_COMPILER}" MATCHES "clang")
message(WARNING "The CMake compiler should be set to clang when trying to run the tests. Skipping...")
return()
endif()
# Attempt to grab the paths from the environment variables
if(NOT "$ENV{MCSEMA_LIFT_PATH}" STREQUAL "")
set(MCSEMA_LIFT_PATH "$ENV{MCSEMA_LIFT_PATH}")
endif()
if(NOT "$ENV{MCSEMA_DISASS_PATH}" STREQUAL "")
set(MCSEMA_DISASS_PATH "$ENV{MCSEMA_DISASS_PATH}")
endif()
if(NOT "$ENV{REMILL_CLANG_PATH}" STREQUAL "")
set(REMILL_CLANG_PATH "$ENV{REMILL_CLANG_PATH}")
endif()
if(NOT "$ENV{IDAT64_PATH}" STREQUAL "")
set(IDAT64_PATH "$ENV{IDAT64_PATH}")
endif()
if(NOT "$ENV{MCSEMA_RT_PATH}" STREQUAL "")
set(MCSEMA_RT_PATH "$ENV{MCSEMA_RT_PATH}")
endif()
# Attempt to find the missing tools from the PATH
if(NOT DEFINED MCSEMA_LIFT_PATH)
find_program(lift_tool_path "mcsema-lift-${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
if(NOT "${lift_tool_path}" STREQUAL "lift_tool_path-NOTFOUND")
set(MCSEMA_LIFT_PATH "${lift_tool_path}")
endif()
endif()
if(NOT DEFINED MCSEMA_DISASS_PATH)
find_program(disass_tool_path "mcsema-disass")
if(NOT "${disass_tool_path}" STREQUAL "disass_tool_path-NOTFOUND")
set(MCSEMA_DISASS_PATH "${disass_tool_path}")
endif()
endif()
if(NOT DEFINED REMILL_CLANG_PATH)
find_program(remill_clang_tool_path "remill-clang-${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
if(NOT "${remill_clang_tool_path}" STREQUAL "remill_clang_tool_path-NOTFOUND")
set(REMILL_CLANG_PATH "${remill_clang_tool_path}")
endif()
endif()
if(NOT DEFINED IDAT64_PATH)
find_program(ida_tool_path "idat64")
if(NOT "${ida_tool_path}" STREQUAL "ida_tool_path-NOTFOUND")
set(IDAT64_PATH "${ida_tool_path}")
endif()
endif()
if(NOT DEFINED MCSEMA_RT_PATH)
set(mcsema_rt_system_path "/usr/local/lib/libmcsema_rt64-${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}.a")
if(EXISTS "${mcsema_rt_system_path}")
set(MCSEMA_RT_PATH "${mcsema_rt_system_path}")
endif()
endif()
# Make sure we have everything we need
if(NOT EXISTS "${MCSEMA_LIFT_PATH}")
message(WARNING "The mcsema-lift executable was not found. Either define MCSEMA_LIFT_PATH or make sure the tool is in PATH. Skipping the tests...")
return()
endif()
if(NOT EXISTS "${MCSEMA_DISASS_PATH}")
message(WARNING "The mcsema-disass executable was not found. Either define MCSEMA_DISASS_PATH or make sure the tool is in PATH. Skipping the tests...")
return()
endif()
if(NOT EXISTS "${IDAT64_PATH}")
message(WARNING "The idat64 executable was not found. Either define IDAT64_PATH or make sure the tool is in PATH. Skipping the tests...")
return()
endif()
if(NOT EXISTS "${REMILL_CLANG_PATH}")
message(WARNING "The remill-clang executable was not found. Either define REMILL_CLANG_PATH or make sure the tool is in PATH. Skipping the tests...")
return()
endif()
if(NOT EXISTS "${MCSEMA_RT_PATH}")
message(WARNING "The libmcsema_rt64 library was not found. Either define MCSEMA_RT_PATH or install the library. Skipping the tests...")
return()
endif()
message(STATUS "Using mcsema-lift: ${MCSEMA_LIFT_PATH}")
message(STATUS "Using mcsema-disass: ${MCSEMA_DISASS_PATH}")
message(STATUS "Using idat64: ${IDAT64_PATH}")
message(STATUS "Using remill-clang: ${REMILL_CLANG_PATH}")
message(STATUS "Using libmcsema_rt64: ${MCSEMA_RT_PATH}")
add_custom_target(mcsema_tests)
add_subdirectory("mcsema_tests")
message(STATUS "Tests can be run with `make mcsema_tests`")
endfunction()
function(importJson11)
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/json11/json11.cpp")
message(SEND_ERROR "The Json11 git submodule has not been initialized")
endif()
add_library(json11
libraries/json11/json11.hpp
libraries/json11/json11.cpp
)
set_target_properties(json11 PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
target_include_directories(json11 PUBLIC libraries/json11)
endfunction()
function(importCli11)
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/CLI11/include/CLI")
message(SEND_ERROR "The CLI11 git submodule has not been initialized")
endif()
add_library(cli11 INTERFACE)
target_include_directories(cli11 INTERFACE libraries/CLI11/include)
endfunction()
function(generateInstallTargets target_name)
install(TARGETS "${target_name}" DESTINATION "${BINARY_INSTALL_FOLDER}")
install(DIRECTORY "data" DESTINATION "${PROFILE_INSTALL_FOLDER}")
if(WIN32)
list(APPEND remove_commands
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_INSTALL_PREFIX}/${WINDOWS_INSTALL_ROOT}"
)
else()
list(APPEND remove_commands
COMMAND "${CMAKE_COMMAND}" -E remove "${CMAKE_INSTALL_PREFIX}/${BINARY_INSTALL_FOLDER}/abigen"
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_INSTALL_PREFIX}/${PROFILE_INSTALL_FOLDER}"
)
endif()
add_custom_target(uninstall
${remove_commands}
COMMENT "Uninstalling ${target_name}..."
VERBATIM
)
endfunction()
function(importLLVM)
add_library(llvm_libraries INTERFACE)
if(DEFINED LIBRARY_REPOSITORY_ROOT)
set(llvm_find_package_hints HINTS "${LIBRARY_REPOSITORY_ROOT}/llvm")
endif()
find_package(LLVM REQUIRED CONFIG ${llvm_find_package_hints})
target_include_directories(llvm_libraries SYSTEM INTERFACE "${LLVM_INCLUDE_DIRS}")
target_compile_definitions(llvm_libraries INTERFACE ${LLVM_DEFINITIONS})
string(REPLACE "." ";" LLVM_VERSION_LIST ${LLVM_PACKAGE_VERSION})
list(GET LLVM_VERSION_LIST 1 LLVM_MINOR_VERSION)
list(GET LLVM_VERSION_LIST 0 LLVM_MAJOR_VERSION)
target_compile_definitions(llvm_libraries INTERFACE
LLVM_MINOR_VERSION=${LLVM_MINOR_VERSION}
LLVM_MAJOR_VERSION=${LLVM_MAJOR_VERSION}
)
set(LLVM_MINOR_VERSION ${LLVM_MINOR_VERSION} PARENT_SCOPE)
set(LLVM_MAJOR_VERSION ${LLVM_MAJOR_VERSION} PARENT_SCOPE)
# It is important to match the RTTI setting used to compile the library
detectLLVMrttiSetting()
if(NOT "${detectLLVMrttiSetting_OUTPUT}")
message(SEND_ERROR "LLVM was compiled without RTTI")
endif()
# This would be the preferred way, but we are required to support old LLVM/Clang versions!
#
# llvm_map_components_to_libnames(llvm_libraries support)
# target_link_libraries("${PROJECT_NAME}" PUBLIC "${llvm_libraries}")
# if(LLVM_MAJOR_VERSION GREATER 6)
# target_link_libraries(llvm_libraries INTERFACE "LLVM")
# endif()
# This should work for every reasonable version of LLVM. If not, fall back on the above.
target_link_libraries(llvm_libraries INTERFACE LLVMSupport)
find_package(Clang REQUIRED ${llvm_find_package_hints})
target_include_directories(llvm_libraries SYSTEM INTERFACE ${CLANG_INCLUDE_DIRS})
target_link_libraries(llvm_libraries INTERFACE
clangBasic
clangAST
clangTooling
clangFrontend
clangParse
clangCodeGen
)
endfunction()
function(detectLLVMrttiSetting)
# Detect the llvm-config path
get_filename_component(llvm_config_path "${LLVM_LIBRARY_DIR}" DIRECTORY)
set(llvm_config_path "${llvm_config_path}/bin/llvm-config")
if(WIN32)
set(llvm_config_path "${llvm_config_path}.exe")
endif()
message(STATUS "llvm-config path: ${llvm_config_path}")
# Execute the llvm-config program and the get rtti setting
message(STATUS "Detecting RTTI setting..")
execute_process(
COMMAND "${llvm_config_path}" --has-rtti
OUTPUT_VARIABLE llvm_config_output
)
string(STRIP "${llvm_config_output}" llvm_config_output)
if("${llvm_config_output}" STREQUAL "YES")
message(STATUS "RTTI appears to be enabled")
elseif("${llvm_config_output}" STREQUAL "NO")
message(STATUS "RTTI appears to be disabled")
else()
message(SEND_ERROR "Failed to determine the rtti setting")
set(detectLLVMrttiSetting_OUTPUT "NO" PARENT_SCOPE)
endif()
set(detectLLVMrttiSetting_OUTPUT "${llvm_config_output}" PARENT_SCOPE)
endfunction()
abigen()