Skip to content

Commit 1adac05

Browse files
committed
codegen: add rellic as dependency and enable rellic decompile transform
1 parent a63397f commit 1adac05

39 files changed

+736
-100
lines changed

.devcontainer/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ RUN curl -fsSL https://get.docker.com -o get-docker.sh && \
3434
# Install Python packages
3535
RUN pip3 install lit codespell jinja2 Pygments
3636

37+
COPY ./install-z3.sh /tmp/
38+
RUN chmod +x /tmp/install-z3.sh && \
39+
/tmp/install-z3.sh
40+
3741
COPY ./install-clangir.sh /tmp/
3842
RUN chmod +x /tmp/install-clangir.sh && \
3943
/tmp/install-clangir.sh

.devcontainer/dependencies.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
software-properties-common ninja-build python3-pip ccache cmake lld lcov doxygen libzstd-dev file
1+
software-properties-common ninja-build python3-pip ccache cmake lld lcov doxygen libzstd-dev file doctest-dev

.devcontainer/devcontainer.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
}
3232
},
3333
"containerEnv": {
34-
"CMAKE_PREFIX_PATH": "/usr/lib/llvm-18/lib/cmake/mlir/;/usr/lib/llvm-18/lib/cmake/clang/",
3534
"LLVM_EXTERNAL_LIT": "/usr/local/bin/lit"
3635
}
3736

.devcontainer/install-clangir.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ build_clangir() {
5757
-DLLVM_INCLUDE_TOOLS:BOOL=ON \
5858
-DLLVM_INSTALL_UTILS:BOOL=ON \
5959
-DLLVM_ENABLE_ZSTD:BOOL=OFF \
60-
-DLLVM_TARGETS_TO_BUILD="AArch64;X86;ARM" \ \
60+
-DLLVM_TARGETS_TO_BUILD="AArch64;X86;ARM" \
6161
-DCMAKE_C_COMPILER=/usr/bin/clang \
62-
-DCMAKE_CXX_COMPILER=/usr/bin/clang++
62+
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
63+
-DLLVM_ENABLE_Z3_SOLVER=ON \
64+
-DLLVM_Z3_INSTALL_DIR=/usr/local
6365
ninja install .
6466
}
6567

.devcontainer/install-z3.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
Z3_REPO="https://github.com/Z3Prover/z3.git"
6+
Z3_DIR="$HOME/z3"
7+
Z3_BUILD_DIR="$HOME/z3-build"
8+
Z3_INSTALL_DIR="/usr/local"
9+
10+
install_dependencies() {
11+
echo "Installing dependencies..."
12+
sudo apt update
13+
sudo apt install -y \
14+
build-essential \
15+
g++ \
16+
cmake \
17+
ninja-build \
18+
python3 \
19+
python3-pip \
20+
git
21+
}
22+
23+
build_z3() {
24+
echo "Cloning z3 repository..."
25+
git clone --branch z3-4.14.0 "$Z3_REPO" "$Z3_DIR"
26+
27+
echo "Installing Z3..."
28+
mkdir -p "$Z3_BUILD_DIR" && cd "$Z3_BUILD_DIR"
29+
cmake -GNinja \
30+
-DCMAKE_BUILD_TYPE=Release \
31+
-DCMAKE_INSTALL_PREFIX="$Z3_INSTALL_DIR" \
32+
-DZ3_BUILD_PYTHON_BINDINGS=OFF \
33+
-DZ3_BUILD_EXAMPLES=OFF \
34+
-DZ3_USE_LIB_GMP=OFF \
35+
$Z3_DIR
36+
ninja install .
37+
}
38+
39+
clean_up() {
40+
echo "Cleaning up..."
41+
rm -rf "$Z3_BUILD_DIR"
42+
}
43+
44+
45+
install_dependencies
46+
build_z3
47+
clean_up
48+
49+
echo "Z3 has been successfully installed!"

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,18 @@ jobs:
4848
ENABLE_SANITIZER_ADDRESS: ${{ matrix.sanitizers }}
4949

5050
steps:
51+
- name: Clean Docker to prevent space issues
52+
run: |
53+
docker system prune -af --volumes || true
54+
5155
- name: Clone the Patchestry repository
5256
uses: actions/checkout@v4
5357
with:
5458
submodules: true
5559
fetch-depth: 1
5660

5761
- name: Configure build - sanitizers ${{ matrix.sanitizers }}
58-
run: cmake --preset ci
62+
run: cmake --preset ci -DLLVM_EXTERNAL_LIT=$(which lit) -DLLVM_Z3_INSTALL_DIR=/usr/local
5963

6064
- name: Build ${{ matrix.build-type }} with sanitizers set ${{ matrix.sanitizers }}
6165
run: cmake --build --preset ci --config ${{ matrix.build-type }} -j $(nproc)

.gitmodules

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[submodule "vendor/clangir/src"]
2+
path = vendor/clangir/src
3+
url = https://github.com/trail-of-forks/clangir.git
4+
[submodule "vendor/rellic/src"]
5+
path = vendor/rellic/src
6+
url = https://github.com/lifting-bits/rellic.git
7+
branch = llvm20
8+
[submodule "vendor/glog/src"]
9+
path = vendor/glog/src
10+
url = https://github.com/google/glog.git
11+
[submodule "vendor/gflags/src"]
12+
path = vendor/gflags/src
13+
url = https://github.com/gflags/gflags.git

CMakeLists.txt

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ if (POLICY CMP0116)
2525
cmake_policy(SET CMP0116 NEW)
2626
endif()
2727

28+
if(POLICY CMP0127)
29+
cmake_policy(SET CMP0127 NEW)
30+
endif()
31+
2832
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
2933

3034
include(prevent_in_source_builds)
@@ -48,11 +52,9 @@ project(
4852
LANGUAGES C CXX
4953
)
5054

51-
set(CMAKE_CXX_STANDARD 20)
52-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
53-
5455
include(project_settings)
5556
include(project_utils)
57+
include(options)
5658

5759
#
5860
# Setup package version
@@ -69,6 +71,15 @@ configure_file(
6971
${CMAKE_CURRENT_BINARY_DIR}/include/patchestry/Version.inc
7072
)
7173

74+
if(PLATFORM_MACOS)
75+
set(CMAKE_MACOSX_RPATH 1)
76+
set(CMAKE_INSTALL_RPATH "@executable_path/../${PE_INSTALL_LIB_DIR}")
77+
elseif(PLATFORM_LINUX)
78+
set(CMAKE_INSTALL_RPATH "$ORIGIN/../${PE_INSTALL_LIB_DIR}")
79+
endif()
80+
81+
add_subdirectory("vendor")
82+
7283
#
7384
# CCACHE
7485
#
@@ -82,29 +93,35 @@ FindAndSelectClangCompiler()
8293
#
8394
# LLVM & MLIR & Clang
8495
#
85-
find_package(LLVM 20 REQUIRED CONFIG)
86-
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
96+
find_package(LLVM 20 CONFIG REQUIRED HINTS "${PE_VENDOR_INSTALL_DIR}")
8797
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
8898
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
8999

90100
include(TableGen)
91101
include(AddLLVM)
92102
include(HandleLLVMOptions)
93103

94-
find_package(MLIR 20 REQUIRED CONFIG)
104+
find_package(MLIR 20 CONFIG REQUIRED HINTS "${PE_VENDOR_INSTALL_DIR}")
95105
message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}")
96106
list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}")
97-
98107
include(AddMLIR)
99108

100-
find_package(Clang 20 CONFIG REQUIRED)
109+
find_package(Clang 20 CONFIG REQUIRED HINTS "${PE_VENDOR_INSTALL_DIR}")
101110
message(STATUS "Using ClangConfig.cmake in: ${Clang_DIR}")
102-
list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}")
111+
103112

104113

105114
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)
106115
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/lib)
107116

117+
118+
119+
find_package(Z3 4.8 CONFIG REQUIRED)
120+
121+
find_package(rellic REQUIRED HINTS "${PE_VENDOR_INSTALL_DIR}")
122+
message(STATUS "Using RellicConfig.cmake in: ${rellic_DIR}")
123+
get_target_property(RELLIC_INCLUDE_DIRS rellic::rellic INTERFACE_INCLUDE_DIRECTORIES)
124+
108125
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
109126
include_directories(SYSTEM ${MLIR_INCLUDE_DIRS})
110127
include_directories(${PROJECT_SOURCE_DIR}/include)

CMakePresets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"systemVars": false
1818
},
1919
"errors": {
20-
"dev": true,
20+
"dev": false,
2121
"deprecated": true
2222
}
2323
},

cmake/FindZ3.cmake

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
INCLUDE(CheckCXXSourceRuns)
2+
3+
# Function to check Z3's version
4+
function(check_z3_version z3_include z3_lib)
5+
# Get lib path
6+
set(z3_link_libs "${z3_lib}")
7+
8+
# Try to find a threading module in case Z3 was built with threading support.
9+
# Threads are required elsewhere in LLVM, but not marked as required here because
10+
# Z3 could have been compiled without threading support.
11+
find_package(Threads)
12+
# CMAKE_THREAD_LIBS_INIT may be empty if the thread functions are provided by the
13+
# system libraries and no special flags are needed.
14+
if(CMAKE_THREAD_LIBS_INIT)
15+
list(APPEND z3_link_libs "${CMAKE_THREAD_LIBS_INIT}")
16+
endif()
17+
18+
# The program that will be executed to print Z3's version.
19+
file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testz3.cpp
20+
"#include <assert.h>
21+
#include <z3.h>
22+
int main() {
23+
unsigned int major, minor, build, rev;
24+
Z3_get_version(&major, &minor, &build, &rev);
25+
return 0;
26+
}")
27+
28+
try_run(
29+
Z3_RETURNCODE
30+
Z3_COMPILED
31+
${CMAKE_BINARY_DIR}
32+
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testz3.cpp
33+
COMPILE_DEFINITIONS -I"${z3_include}"
34+
LINK_LIBRARIES ${z3_link_libs}
35+
COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
36+
RUN_OUTPUT_VARIABLE SRC_OUTPUT
37+
)
38+
39+
if(Z3_COMPILED)
40+
string(REGEX REPLACE "([0-9]*\\.[0-9]*\\.[0-9]*)" "\\1"
41+
z3_version "${SRC_OUTPUT}")
42+
set(Z3_VERSION_STRING ${z3_version} PARENT_SCOPE)
43+
else()
44+
message(NOTICE "${COMPILE_OUTPUT}")
45+
message(WARNING "Failed to compile Z3 program that is used to determine library version.")
46+
endif()
47+
endfunction(check_z3_version)
48+
49+
# Looking for Z3 in LLVM_Z3_INSTALL_DIR
50+
find_path(Z3_INCLUDE_DIR NAMES z3.h
51+
NO_DEFAULT_PATH
52+
PATHS ${LLVM_Z3_INSTALL_DIR}/include
53+
PATH_SUFFIXES libz3 z3
54+
)
55+
56+
find_library(Z3_LIBRARIES NAMES z3 libz3
57+
NO_DEFAULT_PATH
58+
PATHS ${LLVM_Z3_INSTALL_DIR}
59+
PATH_SUFFIXES lib bin
60+
)
61+
62+
# If Z3 has not been found in LLVM_Z3_INSTALL_DIR look in the default directories
63+
find_path(Z3_INCLUDE_DIR NAMES z3.h
64+
PATH_SUFFIXES libz3 z3
65+
)
66+
67+
find_library(Z3_LIBRARIES NAMES z3 libz3
68+
PATH_SUFFIXES lib bin
69+
)
70+
71+
# Searching for the version of the Z3 library is a best-effort task
72+
unset(Z3_VERSION_STRING)
73+
74+
# First, try to check it dynamically, by compiling a small program that
75+
# prints Z3's version
76+
if(Z3_INCLUDE_DIR AND Z3_LIBRARIES)
77+
# We do not have the Z3 binary to query for a version. Try to use
78+
# a small C++ program to detect it via the Z3_get_version() API call.
79+
check_z3_version(${Z3_INCLUDE_DIR} ${Z3_LIBRARIES})
80+
endif()
81+
82+
# If the dynamic check fails, we might be cross compiling: if that's the case,
83+
# check the version in the headers, otherwise, fail with a message
84+
if(NOT Z3_VERSION_STRING AND (CMAKE_CROSSCOMPILING AND
85+
Z3_INCLUDE_DIR AND
86+
EXISTS "${Z3_INCLUDE_DIR}/z3_version.h"))
87+
# TODO: print message warning that we couldn't find a compatible lib?
88+
89+
# Z3 4.8.1+ has the version is in a public header.
90+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
91+
z3_version_str REGEX "^#define[\t ]+Z3_MAJOR_VERSION[\t ]+.*")
92+
string(REGEX REPLACE "^.*Z3_MAJOR_VERSION[\t ]+([0-9]).*$" "\\1"
93+
Z3_MAJOR "${z3_version_str}")
94+
95+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
96+
z3_version_str REGEX "^#define[\t ]+Z3_MINOR_VERSION[\t ]+.*")
97+
string(REGEX REPLACE "^.*Z3_MINOR_VERSION[\t ]+([0-9]).*$" "\\1"
98+
Z3_MINOR "${z3_version_str}")
99+
100+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
101+
z3_version_str REGEX "^#define[\t ]+Z3_BUILD_NUMBER[\t ]+.*")
102+
string(REGEX REPLACE "^.*Z3_BUILD_NUMBER[\t ]+([0-9]).*$" "\\1"
103+
Z3_BUILD "${z3_version_str}")
104+
105+
set(Z3_VERSION_STRING ${Z3_MAJOR}.${Z3_MINOR}.${Z3_BUILD})
106+
unset(z3_version_str)
107+
endif()
108+
109+
if(NOT Z3_VERSION_STRING)
110+
# Give up: we are unable to obtain a version of the Z3 library. Be
111+
# conservative and force the found version to 0.0.0 to make version
112+
# checks always fail.
113+
set(Z3_VERSION_STRING "0.0.0")
114+
message(WARNING "Failed to determine Z3 library version, defaulting to 0.0.0.")
115+
endif()
116+
117+
# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if
118+
# all listed variables are TRUE
119+
include(FindPackageHandleStandardArgs)
120+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3
121+
REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR
122+
VERSION_VAR Z3_VERSION_STRING)
123+
124+
mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES)

cmake/options.cmake

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#
2+
# Copyright (c) 2025-present, Trail of Bits, Inc.
3+
#
4+
# This source code is licensed in accordance with the terms specified in
5+
# the LICENSE file found in the root directory of this source tree.
6+
#
7+
8+
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type")
9+
set(CMAKE_EXPORT_COMPILE_COMMANDS true CACHE BOOL "Generate the compile_commands.json file (forced)" FORCE)
10+
11+
set(CMAKE_INSTALL_LIBDIR "lib" CACHE PATH "Default library installation directory")
12+
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "Default binary installation directory")
13+
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "Default include installation directory")
14+
set(CMAKE_INSTALL_DATADIR "share" CACHE PATH "Default data installation directory")
15+
16+
set(PE_INSTALL_LIB_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE PATH "Directory in which Multiplier libraries will be installed")
17+
set(PE_INSTALL_BIN_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH "Directory in which Multiplier binaries will be installed")
18+
set(PE_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH "Directory in which Multiplier headers will be installed")
19+
set(PE_INSTALL_SHARE_DIR "${CMAKE_INSTALL_DATADIR}" CACHE PATH "Directory in which Multiplier CMake files will be installed")
20+
set(PE_VENDOR_INSTALL_DIR "${PROJECT_BINARY_DIR}/vendor/install" CACHE PATH "Directory in which multiplier's vendored dependencies are installed")
21+
22+
option(PE_USE_VENDORED_GLOG "Set to OFF to disable default building of Google glog as a vendored library." ON)
23+
option(PE_USE_VENDORED_GFLAGS "Set to OFF to disable default building of gflags as a vendored library." ON)
24+
option(PE_USE_VENDORED_CLANG "Set to OFF to disable default building of Clang/LLVM as a vendored library." OFF)

cmake/project_settings.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ macro(settings_main)
4040
endif()
4141

4242
# Globally set the required C++ standard
43-
set(CMAKE_CXX_STANDARD 23)
43+
set(CMAKE_CXX_STANDARD 20)
4444
set(CMAKE_CXX_EXTENSIONS OFF)
45+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
4546

4647
if(UNIX)
4748
if(APPLE)

include/patchestry/AST/ASTConsumer.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ namespace patchestry::ast {
5555
clang::ASTContext &ctx, FunctionMap &serialized_functions, TypeMap &serialized_types
5656
);
5757

58-
Program &get_program(void) const { return program.get(); }
58+
std::unique_ptr< clang::ASTUnit > create_astunit(clang::ASTContext &ctx) const;
5959

60-
clang::Sema &sema(void) const { return ci.get().getSema(); }
60+
Program &get_program(void) const { return program; }
6161

62-
std::reference_wrapper< Program > program;
63-
std::reference_wrapper< clang::CompilerInstance > ci;
62+
clang::Sema &sema(void) const { return ci.getSema(); }
63+
64+
Program &program;
65+
clang::CompilerInstance &ci;
6466

6567
const patchestry::Options &options; // NOLINT
6668
std::unique_ptr< TypeBuilder > type_builder;

0 commit comments

Comments
 (0)