├── .clang-format
├── .gitattributes
├── .github
└── workflows
│ ├── anghabench-after-build.yml
│ ├── anghabench-cron-jobs.yml
│ ├── ci.yml
│ └── diff_tests.yml
├── .gitignore
├── .gitmodules
├── ACKNOWLEDGEMENTS.md
├── CMakeLists.txt
├── CMakePresets.json
├── CODEOWNERS
├── Dockerfile
├── LICENSE
├── README.md
├── ci
└── angha_1k_test_settings.json
├── cmake
├── git_watcher.cmake
├── modules
│ ├── FindZ3.cmake
│ ├── Findgflags.cmake
│ ├── Findglog.cmake
│ └── utils.cmake
├── options.cmake
├── packaging.cmake
└── settings.cmake
├── docs
├── HelpingJohnny.pdf
└── NoMoreGotos.pdf
├── include
└── rellic
│ ├── AST
│ ├── ASTBuilder.h
│ ├── ASTPass.h
│ ├── CXXToCDecl.h
│ ├── CondBasedRefine.h
│ ├── DeadStmtElim.h
│ ├── DebugInfoCollector.h
│ ├── DecompilationContext.h
│ ├── ExprCombine.h
│ ├── GenerateAST.h
│ ├── IRToASTVisitor.h
│ ├── InferenceRule.h
│ ├── LocalDeclRenamer.h
│ ├── LoopRefine.h
│ ├── MaterializeConds.h
│ ├── NestedCondProp.h
│ ├── NestedScopeCombine.h
│ ├── ReachBasedRefine.h
│ ├── StructFieldRenamer.h
│ ├── StructGenerator.h
│ ├── SubprogramGenerator.h
│ ├── TransformVisitor.h
│ ├── TypeProvider.h
│ ├── Util.h
│ └── Z3CondSimplify.h
│ ├── BC
│ ├── Util.h
│ └── Version.h
│ ├── Dec2Hex.h
│ ├── Decompiler.h
│ ├── Exception.h
│ ├── Result.h
│ └── Version.h
├── lib
├── AST
│ ├── ASTBuilder.cpp
│ ├── CXXToCDecl.cpp
│ ├── CondBasedRefine.cpp
│ ├── DeadStmtElim.cpp
│ ├── DebugInfoCollector.cpp
│ ├── ExprCombine.cpp
│ ├── GenerateAST.cpp
│ ├── IRToASTVisitor.cpp
│ ├── InferenceRule.cpp
│ ├── LocalDeclRenamer.cpp
│ ├── LoopRefine.cpp
│ ├── MaterializeConds.cpp
│ ├── NestedCondProp.cpp
│ ├── NestedScopeCombine.cpp
│ ├── ReachBasedRefine.cpp
│ ├── StructFieldRenamer.cpp
│ ├── StructGenerator.cpp
│ ├── SubprogramGenerator.cpp
│ ├── TypeProvider.cpp
│ ├── Util.cpp
│ └── Z3CondSimplify.cpp
├── BC
│ └── Util.cpp
├── CMakeLists.txt
├── Dec2Hex.cpp
├── Decompiler.cpp
├── Exception.cpp
└── Version.cpp.in
├── packaging
├── README.md
├── cmake
│ ├── dispatcher.cmake
│ └── system
│ │ ├── linux
│ │ └── generators
│ │ │ ├── deb.cmake
│ │ │ ├── rpm.cmake
│ │ │ └── tgz.cmake
│ │ └── macos
│ │ └── generators
│ │ └── tgz.cmake
└── main.cmake
├── rellicConfig.cmake.in
├── scripts
├── build-preset.sh
├── build.sh
├── decompile.py
├── docker-decomp-entrypoint.sh
├── generate_changelog.sh
├── requirements.txt
├── roundtrip.py
├── run-on-anghabench.sh
├── test-angha-1k.sh
└── test-headergen.py
├── tests
└── tools
│ ├── decomp
│ ├── array_swap.c
│ ├── assert.c
│ ├── binops.c
│ ├── bitmask.c
│ ├── bitops.c
│ ├── bool.c
│ ├── branch.c
│ ├── byval_struct.c
│ ├── byval_tail_gep.ll
│ ├── byval_tail_nogep.ll
│ ├── cast.c
│ ├── conflicting_global.c
│ ├── conflicting_names.c
│ ├── diff_outputs.mk
│ ├── failing-rebuild
│ │ ├── README.md
│ │ ├── chal-1.c
│ │ └── issue_333_inline_asm.c
│ ├── fcmp.c
│ ├── fizzbuzz.c
│ ├── fizzbuzz_stateful.c
│ ├── float.c
│ ├── func_cond_two_arg.c
│ ├── func_cond_zero_arg.c
│ ├── funcptr.c
│ ├── global_using_function_decl.c
│ ├── goto_loop.c
│ ├── init_list.c
│ ├── inttoptr.c
│ ├── issue_123_uint128_t.c
│ ├── issue_127_uint128_t_lit.c
│ ├── issue_183_literal_structs.c
│ ├── issue_335_z3_ite.ll
│ ├── issue_4.c
│ ├── issue_94_strncmp.c
│ ├── known-failures
│ │ └── issue_126_bool2bv.c
│ ├── loop.c
│ ├── nested_struct.c
│ ├── nested_while.c
│ ├── nullptr.c
│ ├── reg_test_structure_fields.c
│ ├── ret0.c
│ ├── short.c
│ ├── struct.c
│ ├── struct_swap.c
│ ├── switch.c
│ ├── switch_loop.c
│ ├── template_parameter_pack.cpp
│ ├── trunc.c
│ ├── typedefs_of_typedefs.c
│ ├── vectors.c
│ ├── zeroinit.c
│ └── zext.c
│ └── headergen
│ ├── alias.cpp
│ ├── alignment.c
│ ├── anon_union.c
│ ├── atomic.c
│ ├── bigstruct.cpp
│ ├── bitfield.c
│ ├── enum_basetype.cpp
│ ├── fwddecl.cpp
│ ├── inheritance.cpp
│ ├── multiple_bases.cpp
│ ├── packed.c
│ ├── packed_bitfield.c
│ ├── packed_bitfield_mix.c
│ ├── static_member.cpp
│ ├── union.c
│ ├── unordered_map.cpp
│ ├── vector.cpp
│ └── vector_string.cpp
├── tools
├── CMakeLists.txt
├── dec2hex
│ └── dec2hex.cpp
├── decomp
│ └── Decomp.cpp
├── headergen
│ ├── HeaderGen.cpp
│ └── README.md
├── plugins
│ └── ida-rellic.py
├── repl
│ └── Repl.cpp
└── xref
│ ├── DeclPrinter.cpp
│ ├── Printer.h
│ ├── README.md
│ ├── StmtPrinter.cpp
│ ├── TypePrinter.cpp
│ ├── Xref.cpp
│ └── www
│ ├── index.html
│ ├── main.js
│ └── style.css
└── unittests
├── AST
├── ASTBuilder.cpp
├── StructGenerator.cpp
├── Util.cpp
├── Util.h
└── Z3ConvVisitor.cpp
├── CMakeLists.txt
└── UnitTest.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | BasedOnStyle: Google
4 | SpaceBeforeParens: ControlStatements
5 | ...
6 |
7 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.sh eol=lf
4 |
--------------------------------------------------------------------------------
/.github/workflows/diff_tests.yml:
--------------------------------------------------------------------------------
1 | name: Diff test outputs
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - '*'
7 |
8 | jobs:
9 | do-the-job:
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | image:
14 | - { name: 'ubuntu', tag: '20.04', codename: 'focal' }
15 | llvm: [ '16' ]
16 | common_base: [ 'https://github.com/lifting-bits/cxx-common/releases/download/v0.4.1' ]
17 |
18 | env:
19 | CC: clang-${{ matrix.llvm }}
20 | CXX: clang++-${{ matrix.llvm }}
21 |
22 | name: Diff in ouput between old and new rellic
23 | runs-on: gha-ubuntu-32
24 | container:
25 | image: ghcr.io/lifting-bits/cxx-common/vcpkg-builder-${{ matrix.image.name }}-v2:${{ matrix.image.tag }}
26 | credentials:
27 | username: ${{ github.actor }}
28 | password: ${{ secrets.GITHUB_TOKEN }}
29 |
30 | steps:
31 | - name: Adding github workspace as safe directory
32 | # See issue https://github.com/actions/checkout/issues/760
33 | run: git config --global --add safe.directory $GITHUB_WORKSPACE
34 | - name: Fetch merge
35 | uses: actions/checkout@v3
36 | with:
37 | fetch-depth: 0
38 | submodules: true
39 | - name: Fetch base branch
40 | uses: actions/checkout@v3
41 | with:
42 | ref: ${{ github.base_ref }}
43 | fetch-depth: 0
44 | submodules: true
45 | path: old
46 | - name: Install utility tools
47 | shell: bash
48 | run: |
49 | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
50 | echo "deb http://apt.llvm.org/${{ matrix.image.codename }}/ llvm-toolchain-${{ matrix.image.codename }}-${{ matrix.llvm }} main" >> /etc/apt/sources.list
51 | echo "deb-src http://apt.llvm.org/${{ matrix.image.codename }}/ llvm-toolchain-${{ matrix.image.codename }}-${{ matrix.llvm }} main" >> /etc/apt/sources.list
52 | apt-get update
53 | apt-get install -y ninja-build pixz xz-utils make rpm python3.8 clang-${{ matrix.llvm }}
54 | update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 100
55 | - name: Download cxx-commons
56 | shell: bash
57 | run: |
58 | curl ${{ matrix.common_base }}/vcpkg_${{ matrix.image.name }}-${{ matrix.image.tag }}_llvm-${{ matrix.llvm }}_amd64.tar.xz \
59 | -L -o vcpkg_${{ matrix.image.name }}-${{ matrix.image.tag }}_llvm-${{ matrix.llvm }}_amd64.tar.xz
60 | tar xf vcpkg_${{ matrix.image.name }}-${{ matrix.image.tag }}_llvm-${{ matrix.llvm }}_amd64.tar.xz
61 |
62 | - name: Build old rellic
63 | shell: bash
64 | run: |
65 | cmake -G Ninja -S old -B rellic-build-old -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/vcpkg_${{ matrix.image.name }}-${{ matrix.image.tag }}_llvm-${{ matrix.llvm }}_amd64/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET="x64-linux-rel"
66 | cmake --build rellic-build-old
67 |
68 | - name: Build new rellic
69 | shell: bash
70 | run: |
71 | cmake -G Ninja -S . -B rellic-build -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/vcpkg_${{ matrix.image.name }}-${{ matrix.image.tag }}_llvm-${{ matrix.llvm }}_amd64/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET="x64-linux-rel"
72 | cmake --build rellic-build
73 |
74 | - name: Print job summary
75 | shell: bash
76 | run: |
77 | echo "# Test diffs" >> $GITHUB_STEP_SUMMARY
78 | cd $GITHUB_WORKSPACE/tests/tools/decomp
79 | env CLANG=clang-${{ matrix.llvm }} \
80 | OLD_RELLIC=$GITHUB_WORKSPACE/rellic-build-old/tools/rellic-decomp \
81 | NEW_RELLIC=$GITHUB_WORKSPACE/rellic-build/tools/rellic-decomp \
82 | make -s -j1 -f diff_outputs.mk >> $GITHUB_STEP_SUMMARY
83 |
84 | - name: Output generated markdown
85 | shell: bash
86 | id: md
87 | run: |
88 | cd $GITHUB_WORKSPACE/tests/tools/decomp
89 | env CLANG=clang-${{ matrix.llvm }} \
90 | OLD_RELLIC=$GITHUB_WORKSPACE/rellic-build-old/tools/rellic-decomp \
91 | NEW_RELLIC=$GITHUB_WORKSPACE/rellic-build/tools/rellic-decomp \
92 | make -s -j1 -f diff_outputs.mk >> $GITHUB_WORKSPACE/test-diff.md
93 |
94 | - name: Add comment
95 | uses: actions/github-script@v6
96 | with:
97 | script: |
98 | const fs = require('fs')
99 | const body = fs.readFileSync('test-diff.md', {encoding:'utf-8'})
100 | const message = `See the diff generated by this PR for the tests here: https://github.com/lifting-bits/rellic/actions/runs/${{ github.run_id }}
101 |
102 |
103 | ${body}
104 |
105 | `
106 |
107 | github.rest.issues.createComment({
108 | issue_number: context.issue.number,
109 | owner: context.repo.owner,
110 | repo: context.repo.repo,
111 | body: message
112 | })
113 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2021-present, Trail of Bits, Inc.
3 | # All rights reserved.
4 | #
5 | # This source code is licensed in accordance with the terms specified in
6 | # the LICENSE file found in the root directory of this source tree.
7 | #
8 |
9 | install_manifest.txt
10 | Makefile
11 |
12 | CMakeLists.txt.user
13 | .vscode
14 | .idea
15 | .cache
16 | cmake-build-debug
17 | cmake-build-release
18 | compile_commands.json
19 |
20 | third_party/*
21 | build/*
22 | generated/*
23 |
24 | tools/build/*
25 |
26 | rellic-build*
27 | rellic-angha-test-1k
28 |
29 | # LLVM bitcode files
30 | *.ll
31 | *.bc
32 |
33 | # Compiled Object files
34 | *.slo
35 | *.lo
36 | *.o
37 | *.obj
38 |
39 | # Precompiled Headers
40 | *.gch
41 | *.pch
42 |
43 | # Compiled Dynamic libraries
44 | *.so
45 | *.dylib
46 | *.dll
47 |
48 | # Compiled Static libraries
49 | *.lai
50 | *.la
51 | *.a
52 | *.lib
53 |
54 | # Executables
55 | *.exe
56 | *.out
57 | *.app
58 |
59 | *.pyc
60 |
61 | # VIM
62 | *.swp
63 |
64 | # Diff files from testing
65 | *.diff
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/lifting-tools-ci"]
2 | path = external/lifting-tools-ci
3 | url = https://github.com/lifting-bits/lifting-tools-ci.git
4 | branch = master
5 |
--------------------------------------------------------------------------------
/ACKNOWLEDGEMENTS.md:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 |
3 | ## Individuals
4 |
5 | The following individuals have graciously contributed their time to improving
6 | Rellic:
7 |
8 | - [Alessandro Gario](https://github.com/alessandrogario)
9 | - [Peter Goodman](https://github.com/pgoodman)
10 | - [Marek Surovič](https://github.com/surovic)
11 |
12 | ## Companies
13 |
14 | The following companies have graciously supported the development of Rellic:
15 |
16 | - [Trail of Bits](https://github.com/trailofbits)
17 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2020-present, Trail of Bits, Inc.
3 | # All rights reserved.
4 | #
5 | # This source code is licensed in accordance with the terms specified in
6 | # the LICENSE file found in the root directory of this source tree.
7 | #
8 |
9 | cmake_minimum_required(VERSION 3.21)
10 |
11 | include("cmake/options.cmake")
12 |
13 | project(rellic)
14 | set(CMAKE_CXX_VISIBILITY_PRESET hidden)
15 | set(CMAKE_C_VISIBILITY_PRESET hidden)
16 | set (VISIBILITY_INLINES_HIDDEN YES)
17 | include("cmake/settings.cmake")
18 | include(GNUInstallDirs)
19 |
20 | if(RELLIC_ENABLE_INSTALL)
21 | include("cmake/packaging.cmake")
22 | endif(RELLIC_ENABLE_INSTALL)
23 |
24 | enable_language(C CXX ASM)
25 |
26 | set(RELLIC_SOURCE_DIR "${PROJECT_SOURCE_DIR}")
27 |
28 | add_library("${PROJECT_NAME}_cxx_settings" INTERFACE)
29 | target_compile_features("${PROJECT_NAME}_cxx_settings"
30 | INTERFACE
31 | cxx_std_17
32 | )
33 |
34 | # warnings and compiler settings
35 | if(NOT DEFINED WIN32)
36 | target_compile_options("${PROJECT_NAME}_cxx_settings"
37 | INTERFACE
38 | -Werror
39 | # -Wconversion
40 | -pedantic
41 | -Wno-unreachable-code-return
42 | )
43 | endif(NOT DEFINED WIN32)
44 |
45 | #
46 | # libraries
47 | #
48 |
49 | find_package(gflags CONFIG REQUIRED)
50 | find_package(glog CONFIG REQUIRED)
51 | find_package(Z3 4.8 CONFIG REQUIRED)
52 | find_package(doctest CONFIG REQUIRED)
53 | find_package(LLVM CONFIG REQUIRED)
54 | llvm_map_components_to_libnames(llvm_libs support core irreader bitreader bitwriter)
55 | find_package(Clang CONFIG REQUIRED)
56 |
57 |
58 | #
59 | # helper macro to set target properties
60 | #
61 |
62 | if(RELLIC_ENABLE_INSTALL)
63 | export(PACKAGE "${PROJECT_NAME}")
64 |
65 | set(cmake_install_dir "lib/cmake/${PROJECT_NAME}")
66 |
67 | include(CMakePackageConfigHelpers)
68 | configure_package_config_file("${PROJECT_NAME}Config.cmake.in"
69 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
70 | INSTALL_DESTINATION "${cmake_install_dir}"
71 | )
72 |
73 | install(
74 | FILES
75 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
76 | DESTINATION "${cmake_install_dir}"
77 | )
78 | install(EXPORT "${PROJECT_NAME}Targets"
79 | DESTINATION "${cmake_install_dir}"
80 | NAMESPACE "${PROJECT_NAME}::"
81 | )
82 | install(
83 | TARGETS
84 | "${PROJECT_NAME}_cxx_settings"
85 | EXPORT
86 | "${PROJECT_NAME}Targets"
87 | )
88 | endif(RELLIC_ENABLE_INSTALL)
89 |
90 | #
91 | # rellic libraries
92 | #
93 |
94 | add_subdirectory(lib)
95 |
96 | #
97 | # rellic executables
98 | #
99 |
100 | add_subdirectory(tools)
101 |
102 | #
103 | # tests
104 | #
105 |
106 |
107 | if (RELLIC_ENABLE_TESTING)
108 | enable_testing()
109 |
110 | add_subdirectory(unittests)
111 |
112 | get_target_property(CLANG_PATH clang LOCATION)
113 | message(STATUS "Clang path for tests: \"${CLANG_PATH}\"")
114 |
115 | find_package(Python3 COMPONENTS Interpreter REQUIRED)
116 | message(STATUS "Python path for tests: \"${Python3_EXECUTABLE}\"")
117 |
118 | if(DEFINED CMAKE_OSX_SYSROOT)
119 | set(RELLIC_TEST_ARGS "--cflags=-isysroot" "--cflags=${CMAKE_OSX_SYSROOT}")
120 | else()
121 | set(RELLIC_TEST_ARGS "")
122 | endif()
123 |
124 | # Tests that survive a complete roundtrip
125 | add_test(NAME test_roundtrip_rebuild
126 | COMMAND "${Python3_EXECUTABLE}" scripts/roundtrip.py $ tests/tools/decomp/ "${CLANG_PATH}" --timeout 30 ${RELLIC_TEST_ARGS}
127 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
128 | )
129 |
130 | # Tests that may not roundtrip yet, but should emit C
131 | add_test(NAME test_roundtrip_translate_only
132 | COMMAND "${Python3_EXECUTABLE}" scripts/roundtrip.py --translate-only $ tests/tools/decomp/failing-rebuild/ "${CLANG_PATH}" --timeout 30 ${RELLIC_TEST_ARGS}
133 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
134 | )
135 |
136 | # Tests that can be decompiled
137 | add_test(NAME test_decompile
138 | COMMAND "${Python3_EXECUTABLE}" scripts/decompile.py $ tests/tools/decomp/ --timeout 30
139 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
140 | )
141 |
142 | add_test(NAME test_headergen
143 | COMMAND "${Python3_EXECUTABLE}" scripts/test-headergen.py $ tests/tools/headergen/ "${CLANG_PATH}" ${RELLIC_TEST_ARGS}
144 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
145 | )
146 | endif()
147 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @frabert
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Choose your LLVM version (only _some_ versions are supported)
2 | ARG LLVM_VERSION=16
3 | ARG UBUNTU_VERSION=22.04
4 | ARG DISTRO_BASE=ubuntu${UBUNTU_VERSION}
5 | ARG BUILD_BASE=ubuntu:${UBUNTU_VERSION}
6 | ARG LIBRARIES=/opt/trailofbits
7 |
8 |
9 | # Run-time dependencies go here
10 | FROM ${BUILD_BASE} as base
11 |
12 | # Build-time dependencies go here
13 | # See here for full list of those dependencies
14 | # https://github.com/lifting-bits/cxx-common/blob/master/docker/Dockerfile.ubuntu.vcpkg
15 | FROM ghcr.io/lifting-bits/cxx-common/vcpkg-builder-ubuntu-v2:${UBUNTU_VERSION} as deps
16 | ARG UBUNTU_VERSION
17 | ARG LLVM_VERSION
18 | ARG LIBRARIES
19 |
20 | RUN apt-get update && \
21 | apt-get install -qqy python3 python3-pip libc6-dev wget liblzma-dev zlib1g-dev curl git build-essential ninja-build libselinux1-dev libbsd-dev ccache pixz xz-utils make rpm && \
22 | if [ "$(uname -m)" = "x86_64" ]; then dpkg --add-architecture i386 && apt-get update && apt-get install -qqy gcc-multilib g++-multilib zip zlib1g-dev:i386; fi && \
23 | rm -rf /var/lib/apt/lists/*
24 |
25 | # Source code build
26 | FROM deps as build
27 | ARG LLVM_VERSION
28 | ARG LIBRARIES
29 | ENV TRAILOFBITS_LIBRARIES="${LIBRARIES}"
30 | ENV PATH="${LIBRARIES}/llvm/bin/:${LIBRARIES}/cmake/bin:${PATH}"
31 | ENV CC=clang
32 | ENV CXX=clang++
33 |
34 | WORKDIR /rellic
35 | COPY ./ ./
36 | RUN ./scripts/build.sh \
37 | --llvm-version ${LLVM_VERSION} \
38 | --prefix /opt/trailofbits \
39 | --extra-cmake-args "-DCMAKE_BUILD_TYPE=Release" \
40 | --install
41 |
42 | # Small installation image
43 | FROM base as install
44 | ARG LLVM_VERSION
45 |
46 | COPY --from=build /opt/trailofbits /opt/trailofbits
47 | COPY scripts/docker-decomp-entrypoint.sh /opt/trailofbits
48 | ENV LLVM_VERSION=llvm${LLVM_VERSION}
49 | ENTRYPOINT ["/opt/trailofbits/docker-decomp-entrypoint.sh"]
50 |
--------------------------------------------------------------------------------
/ci/angha_1k_test_settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "tests.ignore": [
3 | "amd64/SoftEtherVPN/src/See/extr_memory_t.h_SW_LONG_AT.bc",
4 | "arm64/SoftEtherVPN/src/See/extr_memory_t.h_SW_LONG_AT.bc",
5 | "armv7/SoftEtherVPN/src/See/extr_memory_t.h_SW_LONG_AT.bc",
6 | "x86/SoftEtherVPN/src/See/extr_memory_t.h_SW_LONG_AT.bc"
7 | ]
8 | }
--------------------------------------------------------------------------------
/cmake/modules/FindZ3.cmake:
--------------------------------------------------------------------------------
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
21 | #include
22 | int main() {
23 | unsigned int major, minor, build, rev;
24 | Z3_get_version(&major, &minor, &build, &rev);
25 | printf(\"%u.%u.%u\", major, minor, build);
26 | return 0;
27 | }")
28 |
29 | try_run(
30 | Z3_RETURNCODE
31 | Z3_COMPILED
32 | ${CMAKE_BINARY_DIR}
33 | ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testz3.cpp
34 | COMPILE_DEFINITIONS -I"${z3_include}"
35 | LINK_LIBRARIES ${z3_link_libs}
36 | COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
37 | RUN_OUTPUT_VARIABLE SRC_OUTPUT
38 | )
39 |
40 | if(Z3_COMPILED)
41 | string(REGEX REPLACE "([0-9]*\\.[0-9]*\\.[0-9]*)" "\\1"
42 | z3_version "${SRC_OUTPUT}")
43 | set(Z3_VERSION_STRING ${z3_version} PARENT_SCOPE)
44 | else()
45 | message(NOTICE "${COMPILE_OUTPUT}")
46 | message(WARNING "Failed to compile Z3 program that is used to determine library version.")
47 | endif()
48 | endfunction(check_z3_version)
49 |
50 | # Looking for Z3 in LLVM_Z3_INSTALL_DIR
51 | find_path(Z3_INCLUDE_DIR NAMES z3.h
52 | NO_DEFAULT_PATH
53 | PATHS ${LLVM_Z3_INSTALL_DIR}/include
54 | PATH_SUFFIXES libz3 z3
55 | )
56 |
57 | find_library(Z3_LIBRARIES NAMES z3 libz3
58 | NO_DEFAULT_PATH
59 | PATHS ${LLVM_Z3_INSTALL_DIR}
60 | PATH_SUFFIXES lib bin
61 | )
62 |
63 | # If Z3 has not been found in LLVM_Z3_INSTALL_DIR look in the default directories
64 | find_path(Z3_INCLUDE_DIR NAMES z3.h
65 | PATH_SUFFIXES libz3 z3
66 | )
67 |
68 | find_library(Z3_LIBRARIES NAMES z3 libz3
69 | PATH_SUFFIXES lib bin
70 | )
71 |
72 | # Searching for the version of the Z3 library is a best-effort task
73 | unset(Z3_VERSION_STRING)
74 |
75 | # First, try to check it dynamically, by compiling a small program that
76 | # prints Z3's version
77 | if(Z3_INCLUDE_DIR AND Z3_LIBRARIES)
78 | # We do not have the Z3 binary to query for a version. Try to use
79 | # a small C++ program to detect it via the Z3_get_version() API call.
80 | check_z3_version(${Z3_INCLUDE_DIR} ${Z3_LIBRARIES})
81 | endif()
82 |
83 | # If the dynamic check fails, we might be cross compiling: if that's the case,
84 | # check the version in the headers, otherwise, fail with a message
85 | if(NOT Z3_VERSION_STRING AND (CMAKE_CROSSCOMPILING AND
86 | Z3_INCLUDE_DIR AND
87 | EXISTS "${Z3_INCLUDE_DIR}/z3_version.h"))
88 | # TODO: print message warning that we couldn't find a compatible lib?
89 |
90 | # Z3 4.8.1+ has the version is in a public header.
91 | file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
92 | z3_version_str REGEX "^#define[\t ]+Z3_MAJOR_VERSION[\t ]+.*")
93 | string(REGEX REPLACE "^.*Z3_MAJOR_VERSION[\t ]+([0-9]).*$" "\\1"
94 | Z3_MAJOR "${z3_version_str}")
95 |
96 | file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
97 | z3_version_str REGEX "^#define[\t ]+Z3_MINOR_VERSION[\t ]+.*")
98 | string(REGEX REPLACE "^.*Z3_MINOR_VERSION[\t ]+([0-9]).*$" "\\1"
99 | Z3_MINOR "${z3_version_str}")
100 |
101 | file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
102 | z3_version_str REGEX "^#define[\t ]+Z3_BUILD_NUMBER[\t ]+.*")
103 | string(REGEX REPLACE "^.*Z3_BUILD_NUMBER[\t ]+([0-9]).*$" "\\1"
104 | Z3_BUILD "${z3_version_str}")
105 |
106 | set(Z3_VERSION_STRING ${Z3_MAJOR}.${Z3_MINOR}.${Z3_BUILD})
107 | unset(z3_version_str)
108 | endif()
109 |
110 | if(NOT Z3_VERSION_STRING)
111 | # Give up: we are unable to obtain a version of the Z3 library. Be
112 | # conservative and force the found version to 0.0.0 to make version
113 | # checks always fail.
114 | set(Z3_VERSION_STRING "0.0.0")
115 | message(WARNING "Failed to determine Z3 library version, defaulting to 0.0.0.")
116 | endif()
117 |
118 | # handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if
119 | # all listed variables are TRUE
120 | include(FindPackageHandleStandardArgs)
121 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3
122 | REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR
123 | VERSION_VAR Z3_VERSION_STRING)
124 |
125 | mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES)
126 |
--------------------------------------------------------------------------------
/cmake/modules/Findgflags.cmake:
--------------------------------------------------------------------------------
1 | include("${CMAKE_CURRENT_LIST_DIR}/utils.cmake")
2 |
3 | set(RELLIC_GFLAGS_LOCATION "/usr" CACHE FILEPATH "gflags install directory")
4 |
5 | set(gflags_library_list
6 | "gflags"
7 | )
8 |
9 | message(STATUS "Attempting to locate: gflags (hints: RELLIC_GFLAGS_LOCATION=\"${RELLIC_GFLAGS_LOCATION}\")")
10 |
11 | locateLibrary(
12 | NAME "gflags"
13 | HINT "${RELLIC_GFLAGS_LOCATION}"
14 | LIBRARIES ${gflags_library_list}
15 | MAIN_INCLUDE "gflags/gflags.h"
16 | )
17 |
--------------------------------------------------------------------------------
/cmake/modules/Findglog.cmake:
--------------------------------------------------------------------------------
1 | include("${CMAKE_CURRENT_LIST_DIR}/utils.cmake")
2 |
3 | set(RELLIC_GLOG_LOCATION "/usr" CACHE FILEPATH "glog install directory")
4 |
5 | set(glog_library_list
6 | "glog"
7 | )
8 |
9 | message(STATUS "Attempting to locate: glog (hints: RELLIC_GLOG_LOCATION=\"${RELLIC_GLOG_LOCATION}\")")
10 |
11 | locateLibrary(
12 | NAME "glog" # Compatibility name for upstream real glog import
13 | HINT "${RELLIC_GLOG_LOCATION}"
14 | LIBRARIES ${glog_library_list}
15 | MAIN_INCLUDE "glog/logging.h"
16 | )
17 |
--------------------------------------------------------------------------------
/cmake/modules/utils.cmake:
--------------------------------------------------------------------------------
1 | function(locateLibrary)
2 | cmake_parse_arguments(
3 | PARSE_ARGV
4 | 0
5 | "LOCATELIBRARY"
6 | ""
7 | "NAME;HINT"
8 | "LIBRARIES;MAIN_INCLUDE"
9 | )
10 |
11 | add_library("${LOCATELIBRARY_NAME}" INTERFACE)
12 |
13 | # Import the (sub)libraries
14 | foreach(library ${LOCATELIBRARY_LIBRARIES})
15 | set(target_name "${LOCATELIBRARY_NAME}_${library}")
16 |
17 | set(location_name "${target_name}_lib_location")
18 | find_library("${location_name}"
19 | NAMES "${library}"
20 | PATHS "${LOCATELIBRARY_HINT}"
21 | PATH_SUFFIXES "lib"
22 | )
23 |
24 | if("${${location_name}}" STREQUAL "${location_name}-NOTFOUND")
25 | message(FATAL_ERROR "Failed to locate the following library: ${library}")
26 | endif()
27 |
28 | add_library("${target_name}" UNKNOWN IMPORTED GLOBAL)
29 | set_target_properties("${target_name}" PROPERTIES
30 | IMPORTED_LOCATION "${${location_name}}"
31 | )
32 |
33 | target_link_libraries("${LOCATELIBRARY_NAME}" INTERFACE
34 | "${target_name}"
35 | )
36 |
37 | message(STATUS "Found: ${${location_name}}")
38 | endforeach()
39 |
40 | # Locate the include header
41 | set(location_name "${target_name}_header_location")
42 | find_path("${location_name}"
43 | NAMES "${LOCATELIBRARY_MAIN_INCLUDE}"
44 | PATHS "${LOCATELIBRARY_HINT}"
45 | PATH_SUFFIXES "include"
46 | )
47 |
48 | if("${${location_name}}" STREQUAL "${location_name}-NOTFOUND")
49 | message(FATAL_ERROR "Failed to locate the following header file: ${library}")
50 | endif()
51 |
52 | message(STATUS "Found: ${${location_name}}")
53 |
54 | target_include_directories("${LOCATELIBRARY_NAME}" INTERFACE
55 | "${${location_name}}"
56 | )
57 |
58 | set("${LOCATELIBRARY_NAME}_FOUND" true PARENT_SCOPE)
59 | endfunction()
60 |
--------------------------------------------------------------------------------
/cmake/options.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2021-present, Trail of Bits, Inc.
3 | # All rights reserved.
4 | #
5 | # This source code is licensed in accordance with the terms specified in
6 | # the LICENSE file found in the root directory of this source tree.
7 | #
8 |
9 |
10 | # test options
11 | option(RELLIC_ENABLE_TESTING "Enable Test Builds" ON)
12 | option(RELLIC_ENABLE_INSTALL "Set to true to enable the install target" ON)
13 |
--------------------------------------------------------------------------------
/cmake/packaging.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2021-present, Trail of Bits, Inc.
3 | # All rights reserved.
4 | #
5 | # This source code is licensed in accordance with the terms specified in
6 | # the LICENSE file found in the root directory of this source tree.
7 | #
8 |
9 | # Common settings
10 | set(CPACK_PACKAGE_DESCRIPTION "Rellic")
11 | set(CPACK_PACKAGE_NAME "Rellic")
12 | set(CPACK_PACKAGE_VERSION "1.0.0")
13 | set(CPACK_PACKAGE_VENDOR "Trail of Bits")
14 | set(CPACK_PACKAGE_CONTACT "marek.surovic@trailofbits.com")
15 | set(CPACK_PACKAGE_HOMEPAGE_URL "https://www.trailofbits.com")
16 |
17 | # DEB settings
18 | set(CPACK_DEBIAN_PACKAGE_PRIORITY "extra")
19 | set(CPACK_DEBIAN_PACKAGE_SECTION "default")
20 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_PACKAGE_HOMEPAGE_URL}")
21 |
22 | # RPM settings
23 | set(CPACK_RPM_PACKAGE_RELEASE "${CPACK_PACKAGE_VERSION}")
24 | set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
25 | set(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
26 | set(CPACK_RPM_PACKAGE_GROUP "default")
27 | set(CPACK_RPM_PACKAGE_LICENSE "Apache 2")
28 |
29 | # ZIP settings
30 | if("${CPACK_GENERATOR}" STREQUAL "ZIP")
31 | set(CPACK_SET_DESTDIR ON)
32 | endif()
33 |
34 | if (NOT CPack_CMake_INCLUDED)
35 | include("CPack")
36 | endif()
37 |
--------------------------------------------------------------------------------
/cmake/settings.cmake:
--------------------------------------------------------------------------------
1 | # This is only executed once; use a macro (and not a function) so that
2 | # everything defined here does not end up in a separate namespace
3 | macro(main)
4 | # default build type
5 | if(WIN32)
6 | set(CMAKE_BUILD_TYPE Release)
7 | else()
8 | if(NOT CMAKE_BUILD_TYPE)
9 | set(CMAKE_BUILD_TYPE "RelWithDebInfo")
10 | endif()
11 | endif()
12 |
13 | # overwrite the default install prefix
14 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
15 | if(DEFINED WIN32)
16 | set(CMAKE_INSTALL_PREFIX "C:/")
17 | else()
18 | set(CMAKE_INSTALL_PREFIX "/usr/local")
19 | endif()
20 | endif()
21 |
22 | message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
23 |
24 | # generate a compile commands JSON file.
25 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
26 |
27 | #
28 | # compiler and linker flags
29 | #
30 |
31 | # Globally set the required C++ standard
32 |
33 | set(CMAKE_CXX_EXTENSIONS OFF)
34 |
35 | if(WIN32)
36 | # warnings and compiler settings
37 | set(GLOBAL_CXXFLAGS
38 | /MD /nologo /W3 /EHsc /wd4141 /wd4146 /wd4180 /wd4244
39 | /wd4258 /wd4267 /wd4291 /wd4345 /wd4351 /wd4355 /wd4456
40 | /wd4457 /wd4458 /wd4459 /wd4503 /wd4624 /wd4722 /wd4800
41 | /wd4100 /wd4127 /wd4512 /wd4505 /wd4610 /wd4510 /wd4702
42 | /wd4245 /wd4706 /wd4310 /wd4701 /wd4703 /wd4389 /wd4611
43 | /wd4805 /wd4204 /wd4577 /wd4091 /wd4592 /wd4324
44 | )
45 |
46 | set(GLOBAL_DEFINITIONS
47 | _CRT_SECURE_NO_DEPRECATE
48 | _CRT_SECURE_NO_WARNINGS
49 | _CRT_NONSTDC_NO_DEPRECATE
50 | _CRT_NONSTDC_NO_WARNINGS
51 | _SCL_SECURE_NO_DEPRECATE
52 | _SCL_SECURE_NO_WARNINGS
53 | GOOGLE_PROTOBUF_NO_RTTI
54 | )
55 |
56 | else()
57 | # warnings and compiler settings
58 | set(GLOBAL_CXXFLAGS
59 | -Wall -Wextra -Wno-unused-parameter -Wno-c++98-compat
60 | -Wno-unreachable-code-return -Wno-nested-anon-types
61 | -Wno-extended-offsetof
62 | -Wno-variadic-macros -Wno-return-type-c-linkage
63 | -Wno-c99-extensions -Wno-ignored-attributes -Wno-unused-local-typedef
64 | -Wno-unknown-pragmas -Wno-unknown-warning-option -fPIC
65 | -fno-omit-frame-pointer -fvisibility-inlines-hidden
66 | -fno-asynchronous-unwind-tables
67 | )
68 |
69 | if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
70 | set(GLOBAL_CXXFLAGS
71 | ${GLOBAL_CXXFLAGS}
72 | -Wgnu-alignof-expression -Wno-gnu-anonymous-struct -Wno-gnu-designator
73 | -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-statement-expression
74 | )
75 | endif()
76 |
77 | # debug symbols
78 | if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
79 | list(APPEND GLOBAL_CXXFLAGS
80 | -ggdb
81 | )
82 | endif()
83 |
84 | # optimization flags and definitions
85 | if(CMAKE_BUILD_TYPE STREQUAL "Debug")
86 | list(APPEND GLOBAL_CXXFLAGS -O0)
87 | list(APPEND PROJECT_DEFINITIONS "DEBUG")
88 | else()
89 | list(APPEND GLOBAL_CXXFLAGS -O3)
90 | list(APPEND PROJECT_DEFINITIONS "NDEBUG")
91 | endif()
92 | endif()
93 |
94 | if(UNIX)
95 | if(APPLE)
96 | set(PLATFORM_NAME "macos")
97 | else()
98 | set(PLATFORM_NAME "linux")
99 | endif()
100 |
101 | elseif(WIN32)
102 | set(PLATFORM_NAME "windows")
103 |
104 | else()
105 | message("This platform is not officially supported")
106 | endif()
107 |
108 | set(SETTINGS_CMAKE_ true)
109 | endmacro()
110 |
111 | if(NOT DEFINED SETTINGS_CMAKE_)
112 | main()
113 | endif()
114 |
--------------------------------------------------------------------------------
/docs/HelpingJohnny.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lifting-bits/rellic/22f65d60996958f028620e3effac4bf79a375c12/docs/HelpingJohnny.pdf
--------------------------------------------------------------------------------
/docs/NoMoreGotos.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lifting-bits/rellic/22f65d60996958f028620e3effac4bf79a375c12/docs/NoMoreGotos.pdf
--------------------------------------------------------------------------------
/include/rellic/AST/ASTPass.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2022-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | namespace rellic {
19 |
20 | class ASTPass {
21 | std::atomic_bool stop{false};
22 |
23 | protected:
24 | DecompilationContext& dec_ctx;
25 |
26 | bool changed{false};
27 |
28 | virtual void RunImpl() = 0;
29 | virtual void StopImpl() {}
30 |
31 | public:
32 | ASTPass(DecompilationContext& dec_ctx)
33 | : dec_ctx(dec_ctx) {}
34 | virtual ~ASTPass() = default;
35 | void Stop() {
36 | stop = true;
37 | StopImpl();
38 | }
39 |
40 | bool Run() {
41 | changed = false;
42 | stop = false;
43 | RunImpl();
44 | return changed;
45 | }
46 |
47 | unsigned Fixpoint() {
48 | unsigned iter_count{0};
49 | changed = false;
50 | auto DoIter = [this]() {
51 | changed = false;
52 | RunImpl();
53 | return changed;
54 | };
55 | stop = false;
56 | while (DoIter()) {
57 | ++iter_count;
58 | }
59 |
60 | return iter_count;
61 | }
62 |
63 | bool Stopped() { return stop; }
64 | };
65 |
66 | class CompositeASTPass : public ASTPass {
67 | std::vector> passes;
68 |
69 | protected:
70 | void StopImpl() override {
71 | for (auto& pass : passes) {
72 | pass->Stop();
73 | }
74 | }
75 |
76 | void RunImpl() override {
77 | for (auto& pass : passes) {
78 | if (Stopped()) {
79 | break;
80 | }
81 | changed |= pass->Run();
82 | }
83 | }
84 |
85 | public:
86 | CompositeASTPass(DecompilationContext& dec_ctx)
87 | : ASTPass(dec_ctx) {}
88 | std::vector>& GetPasses() { return passes; }
89 | };
90 | } // namespace rellic
--------------------------------------------------------------------------------
/include/rellic/AST/CXXToCDecl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 |
17 | #include "rellic/AST/ASTBuilder.h"
18 |
19 | namespace clang {
20 | class ASTUnit;
21 | }
22 |
23 | namespace rellic {
24 |
25 | class CXXToCDeclVisitor : public clang::RecursiveASTVisitor {
26 | private:
27 | clang::ASTContext &ast_ctx;
28 | clang::TranslationUnitDecl *c_tu;
29 |
30 | ASTBuilder ast;
31 |
32 | std::unordered_map c_decls;
33 |
34 | clang::QualType GetAsCType(clang::QualType type);
35 |
36 | public:
37 | CXXToCDeclVisitor(clang::ASTUnit &unit);
38 |
39 | bool shouldVisitTemplateInstantiations() { return true; }
40 |
41 | bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl *decl) {
42 | // Ignore function templates
43 | return true;
44 | }
45 |
46 | bool TraverseClassTemplateDecl(clang::ClassTemplateDecl *decl) {
47 | // Only process class template specializations
48 | for (auto spec : decl->specializations()) {
49 | TraverseDecl(spec);
50 | }
51 | return true;
52 | }
53 |
54 | bool VisitFunctionDecl(clang::FunctionDecl *func);
55 | bool VisitCXXMethodDecl(clang::CXXMethodDecl *method);
56 | bool VisitRecordDecl(clang::RecordDecl *record);
57 | bool VisitCXXRecordDecl(clang::CXXRecordDecl *cls);
58 | bool VisitFieldDecl(clang::FieldDecl *field);
59 | };
60 |
61 | } // namespace rellic
--------------------------------------------------------------------------------
/include/rellic/AST/CondBasedRefine.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include "rellic/AST/ASTPass.h"
12 | #include "rellic/AST/IRToASTVisitor.h"
13 | #include "rellic/AST/TransformVisitor.h"
14 |
15 | namespace rellic {
16 |
17 | /*
18 | * This pass converts a sequence of if statements shaped like
19 | *
20 | * if(cond) {
21 | * body_then;
22 | * }
23 | * if(!cond) {
24 | * body_else;
25 | * }
26 | *
27 | * into
28 | *
29 | * if(cond) {
30 | * body_then;
31 | * } else {
32 | * body_else;
33 | * }
34 | */
35 | class CondBasedRefine : public TransformVisitor {
36 | private:
37 | protected:
38 | void RunImpl() override;
39 |
40 | public:
41 | CondBasedRefine(DecompilationContext &dec_ctx);
42 |
43 | bool VisitCompoundStmt(clang::CompoundStmt *compound);
44 | };
45 |
46 | } // namespace rellic
47 |
--------------------------------------------------------------------------------
/include/rellic/AST/DeadStmtElim.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include "rellic/AST/ASTPass.h"
12 | #include "rellic/AST/IRToASTVisitor.h"
13 | #include "rellic/AST/TransformVisitor.h"
14 |
15 | namespace rellic {
16 |
17 | /*
18 | * This pass eliminates statements that have no effect
19 | */
20 | class DeadStmtElim : public TransformVisitor {
21 | protected:
22 | void RunImpl() override;
23 |
24 | public:
25 | DeadStmtElim(DecompilationContext &dec_ctx);
26 |
27 | bool VisitIfStmt(clang::IfStmt *ifstmt);
28 | bool VisitCompoundStmt(clang::CompoundStmt *compound);
29 | };
30 |
31 | } // namespace rellic
--------------------------------------------------------------------------------
/include/rellic/AST/DebugInfoCollector.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | namespace rellic {
20 |
21 | using IRToNameMap = std::unordered_map;
22 | using IRToScopeMap = std::unordered_map;
23 | using IRToDITypeMap = std::unordered_map;
24 | using IRTypeToDITypeMap = std::unordered_map;
25 | using IRFuncToDITypeMap =
26 | std::unordered_map;
27 | using IRArgToDITypeMap = std::unordered_map;
28 |
29 | class DebugInfoCollector : public llvm::InstVisitor {
30 | private:
31 | IRToNameMap names;
32 | IRToScopeMap scopes;
33 | IRToDITypeMap valtypes;
34 | IRTypeToDITypeMap types;
35 | IRFuncToDITypeMap funcs;
36 | IRArgToDITypeMap args;
37 | std::unordered_set type_set;
38 | std::vector subprograms;
39 |
40 | void WalkType(llvm::Type *type, llvm::DIType *ditype);
41 |
42 | public:
43 | IRToNameMap &GetIRToNameMap() { return names; }
44 | IRToScopeMap &GetIRToScopeMap() { return scopes; }
45 | IRToDITypeMap &GetIRToDITypeMap() { return valtypes; }
46 | IRTypeToDITypeMap &GetIRTypeToDITypeMap() { return types; }
47 | IRFuncToDITypeMap &GetIRFuncToDITypeMap() { return funcs; }
48 | IRArgToDITypeMap &GetIRArgToDITypeMap() { return args; }
49 | std::unordered_set &GetTypes() { return type_set; }
50 | std::vector &GetSubprograms() { return subprograms; }
51 |
52 | void visitDbgDeclareInst(llvm::DbgDeclareInst &inst);
53 | void visitInstruction(llvm::Instruction &inst);
54 |
55 | void visitFunction(llvm::Function &func);
56 | };
57 |
58 | } // namespace rellic
--------------------------------------------------------------------------------
/include/rellic/AST/DecompilationContext.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include "rellic/AST/ASTBuilder.h"
20 | #include "rellic/AST/TypeProvider.h"
21 |
22 | namespace rellic {
23 |
24 | struct DecompilationContext {
25 | using StmtToIRMap = std::unordered_map;
26 | using ExprToUseMap = std::unordered_map;
27 | using IRToTypeDeclMap = std::unordered_map;
28 | using IRToValDeclMap = std::unordered_map;
29 | using IRToStmtMap = std::unordered_map;
30 | using ArgToTempMap = std::unordered_map;
31 | using BlockToUsesMap =
32 | std::unordered_map>;
33 | using Z3CondMap = std::unordered_map;
34 |
35 | using BBEdge = std::pair;
36 | using BrEdge = std::pair;
37 | using SwEdge = std::pair;
38 |
39 | DecompilationContext(clang::ASTUnit &ast_unit);
40 |
41 | clang::ASTUnit &ast_unit;
42 | clang::ASTContext &ast_ctx;
43 | ASTBuilder ast;
44 |
45 | std::unique_ptr type_provider;
46 |
47 | StmtToIRMap stmt_provenance;
48 | ExprToUseMap use_provenance;
49 | IRToTypeDeclMap type_decls;
50 | IRToValDeclMap value_decls;
51 | ArgToTempMap temp_decls;
52 | BlockToUsesMap outgoing_uses;
53 | z3::context z3_ctx;
54 | z3::expr_vector z3_exprs{z3_ctx};
55 | Z3CondMap conds;
56 |
57 | clang::Expr *marker_expr;
58 |
59 | std::unordered_map z3_br_edges_inv;
60 |
61 | // Pairs do not have a std::hash specialization so we can't use unordered maps
62 | // here. If this turns out to be a performance issue, investigate adding hash
63 | // specializations for these specifically
64 | std::map z3_br_edges;
65 |
66 | std::unordered_map z3_sw_vars;
67 | std::unordered_map z3_sw_vars_inv;
68 | std::map z3_sw_edges;
69 |
70 | std::map z3_edges;
71 | std::unordered_map reaching_conds;
72 |
73 | size_t num_literal_structs = 0;
74 | size_t num_declared_structs = 0;
75 |
76 | // Inserts an expression into z3_exprs and returns its index
77 | unsigned InsertZExpr(const z3::expr &e);
78 |
79 | clang::QualType GetQualType(llvm::Type *type);
80 | };
81 |
82 | } // namespace rellic
--------------------------------------------------------------------------------
/include/rellic/AST/ExprCombine.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include "rellic/AST/TransformVisitor.h"
12 |
13 | namespace rellic {
14 |
15 | /*
16 | * This pass performs a number of different trasnformations on expressions,
17 | * like turning *&a into a, or !(a == b) into a != b
18 | */
19 | class ExprCombine : public TransformVisitor {
20 | protected:
21 | void RunImpl() override;
22 |
23 | public:
24 | ExprCombine(DecompilationContext &dec_ctx);
25 |
26 | bool VisitCStyleCastExpr(clang::CStyleCastExpr *cast);
27 | bool VisitUnaryOperator(clang::UnaryOperator *op);
28 | bool VisitBinaryOperator(clang::BinaryOperator *op);
29 | bool VisitArraySubscriptExpr(clang::ArraySubscriptExpr *expr);
30 | bool VisitMemberExpr(clang::MemberExpr *expr);
31 | bool VisitParenExpr(clang::ParenExpr *paren);
32 | };
33 |
34 | } // namespace rellic
35 |
--------------------------------------------------------------------------------
/include/rellic/AST/GenerateAST.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2021-present, Trail of Bits, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed in accordance with the terms specified in
6 | * the LICENSE file found in the root directory of this source tree.
7 | */
8 |
9 | #pragma once
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include
17 | #include