mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
Alessandro/refactor/llvmmultiversion cmake (#111)
* Change copyright notice in all the places. Trying to get cmake to download all the things * CMake refactor * Added the lib repository installer * Fixed a couple of paths in library repository scripts * Spelling and a missing .gitignore file. * The google test library was not correctly linked * Removed the pre-compiled XED library * Removed unused files; fixed the INSTALL directives. Added automatic protobuf generation. * Added a package generator script for ArchLinux * Merged in Alessandro's cmake magic * Cleanups, compatibility changes * CMake cleanup. o Removed the cmake folder as it is no longer used. o Removed the library_repository_installer directory and replaced it with a submodule to the newly introduced cxx_common repository. o Added the 'use_remill_semantics' branch of mcsema as a submodule under tools/cmake. o Updated the README instructions (added --recursive to the git clone command). Warning: the mcsema submodule is pointing to my fork of the repository! * CMake: avoid re-defining the C/CXX/ASM compiler. This will prevent CMake from looping forever when using submodules. * The tools/mcsema submodule now points to the official repository. * mcsema submodule update * Updated the mcsema git submodule to track the newest changes. * Various CMake fixes (see details). o External include headers were not correctly marked as SYSTEM. This caused them to output warnings and break the build. o The PROJECT_SOURCE CMake variable has been replaced with CMAKE_SOURCE_DIR. o Updated the mcsema submodule to point to the latest CMake fixes. * Getting closer to having the test case runner work again without using the CFG protobufs. * Trying to make things use ubuntu clang/llvm packages * Update to the mcsema submodule. * Minor changes for llvm version compatibility * Test cases should run now. Had to compile the lifted testcases to a .S file, as with the .bc file, they were being optimized away.. I think. The compilation to assembly seems unusually slow, though. * Minor change * Some stuff for llvm 4.0 support * Remove mcsema sub-module * Remove cxx-common submodule * First steps toward getting travis working again * Attempt at getting travis working again * Using https for cloning instead of ssh * Minor build script update * Added ISEL_ prefix to isels to make it easier for ForEachISel to find them. Commented out the defer_inlining intrinsics. * Changes related to mcsema2 * Simplify runtime targets generation. (#110) * CMake refactor: Added a new language 'BC' for the bitcode (see details). The language is used to generate the runtimes used by the architecture modules. The required executables (clang++ and llvm-link) are automatically detected in the same way as other compilers are. A new CMake function has been added and it can be used to easily generate runtime targets in a way similar to add_executable: add_runtime(<name> SOURCE <source list> ADDRESS_SIZE <n> DEFINITIONS <definition list>) Additionally, all files ending with the *.bcpp extensions will automatically invoke the bitcode compiler when listed in an active target. This should open support for parallel compilation! You just have to list all your .cpp files when calling add_runtime. * CMake: Fixes to the BC language handler. * CMake/BC: Use '.bo' for object files. X86 runtime: Add -g/-O flags.
This commit is contained in:
+13
-1
@@ -1,4 +1,16 @@
|
||||
# Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved.
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
install_manifest.txt
|
||||
Makefile
|
||||
|
||||
@@ -20,7 +20,6 @@ install:
|
||||
- ./scripts/travis/install.sh
|
||||
before_script:
|
||||
- cd build
|
||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]] ; then make build_x86_tests ; fi
|
||||
script:
|
||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]] ; then ctest ; fi
|
||||
notifications:
|
||||
|
||||
@@ -6,6 +6,7 @@ The following individuals have graciously contributed their time to improving
|
||||
Remill:
|
||||
|
||||
- [Akshay Kumar](https://github.com/kumarak)
|
||||
- [Alessandro Gario](https://github.com/alessandrogario)
|
||||
- [Douglas Goddard](https://github.com/douggard)
|
||||
- [Kareem El-Faramawi](https://github.com/krx)
|
||||
- [Peter Goodman](https://github.com/pgoodman)
|
||||
|
||||
+173
-108
@@ -1,138 +1,203 @@
|
||||
# Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved.
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
project(remill)
|
||||
cmake_minimum_required (VERSION 3.2)
|
||||
|
||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(FATAL_ERROR "Remill and its tools are 64-bit only tools.")
|
||||
endif()
|
||||
|
||||
enable_language(ASM)
|
||||
# add the BC (bitcode) language definition
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/BCCompiler")
|
||||
|
||||
include(CTest)
|
||||
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
set(REMILL_SOURCE_DIR "${PROJECT_SOURCE_DIR}")
|
||||
|
||||
find_package(LLVM 3.9 REQUIRED)
|
||||
#
|
||||
# compiler selection
|
||||
#
|
||||
|
||||
if (DEFINED ENV{TRAILOFBITS_LIBRARIES})
|
||||
set(LIBRARY_REPOSITORY_ROOT $ENV{TRAILOFBITS_LIBRARIES})
|
||||
include("${LIBRARY_REPOSITORY_ROOT}/cmake/repository.cmake")
|
||||
|
||||
message(STATUS "Using the following library repository: ${LIBRARY_REPOSITORY_ROOT}")
|
||||
else ()
|
||||
message(STATUS "Using system libraries")
|
||||
endif ()
|
||||
|
||||
# llvm
|
||||
if (DEFINED ENV{LLVM_INSTALL_PREFIX})
|
||||
set(LLVM_INSTALL_PREFIX $ENV{LLVM_INSTALL_PREFIX})
|
||||
endif ()
|
||||
|
||||
if (DEFINED LLVM_INSTALL_PREFIX)
|
||||
list(APPEND FINDPACKAGE_LLVM_HINTS "${LLVM_INSTALL_PREFIX}/lib/cmake/llvm/")
|
||||
list(APPEND FINDPACKAGE_LLVM_HINTS "${LLVM_INSTALL_PREFIX}/share/llvm/cmake/")
|
||||
|
||||
message(STATUS "Using LLVM_INSTALL_PREFIX hints for find_package(LLVM): ${FINDPACKAGE_LLVM_HINTS}")
|
||||
endif ()
|
||||
|
||||
# it is important to avoid re-defining these variables if they have been already
|
||||
# set or you risk ending up in a configure loop!
|
||||
if (NOT DEFINED CMAKE_C_COMPILER)
|
||||
if (DEFINED LLVM_INSTALL_PREFIX)
|
||||
set(CMAKE_C_COMPILER "${LLVM_INSTALL_PREFIX}/bin/clang")
|
||||
else ()
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_COMPILER)
|
||||
if (DEFINED LLVM_INSTALL_PREFIX)
|
||||
set(CMAKE_CXX_COMPILER "${LLVM_INSTALL_PREFIX}/bin/clang++")
|
||||
else ()
|
||||
set(CMAKE_CXX_COMPILER "clang++")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED CMAKE_ASM_COMPILER)
|
||||
if (DEFINED LLVM_INSTALL_PREFIX)
|
||||
set(CMAKE_ASM_COMPILER "${LLVM_INSTALL_PREFIX}/bin/clang")
|
||||
else ()
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_CXX_COMPILER})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED CMAKE_LLVM_LINK)
|
||||
if (DEFINED LLVM_INSTALL_PREFIX)
|
||||
set(CMAKE_LLVM_LINK "${LLVM_INSTALL_PREFIX}/bin/llvm-link")
|
||||
else ()
|
||||
set(CMAKE_LLVM_LINK "llvm-link")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
enable_language(ASM)
|
||||
|
||||
#
|
||||
# compiler settings
|
||||
#
|
||||
|
||||
# enable the gnu extensions
|
||||
set(CMAKE_CXX_EXTENSIONS ON)
|
||||
|
||||
# visual studio already defaults to c++11
|
||||
if (NOT WIN32)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif ()
|
||||
|
||||
# warnings and compiler settings
|
||||
set(PROJECT_CXXWARNINGS "-Wall -Wextra -Werror -pedantic -Wno-unused-parameter -Wno-c++98-compat -Wno-unreachable-code-return -Wno-nested-anon-types -Wno-extended-offsetof -Wno-gnu-anonymous-struct -Wno-gnu-designator -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-statement-expression -Wno-return-type-c-linkage -Wno-c99-extensions -Wno-ignored-attributes -Wno-unused-local-typedef")
|
||||
set(PROJECT_CXXFLAGS "${PROJECT_CXXFLAGS} -Wno-unknown-warning-option ${PROJECT_CXXWARNINGS} -fPIC -fno-omit-frame-pointer -fvisibility-inlines-hidden -fno-exceptions -fno-asynchronous-unwind-tables -fno-rtti")
|
||||
|
||||
# default build type
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
endif ()
|
||||
|
||||
# debug symbols
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
set(PROJECT_CXXFLAGS "${PROJECT_CXXFLAGS} -gdwarf-2 -g3")
|
||||
endif ()
|
||||
|
||||
# optimization flags and definitions
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(PROJECT_CXXFLAGS "${PROJECT_CXXFLAGS} -O0")
|
||||
else ()
|
||||
set(PROJECT_CXXFLAGS "${PROJECT_CXXFLAGS} -O3")
|
||||
list(APPEND PROJECT_DEFINITIONS "NDEBUG")
|
||||
endif ()
|
||||
|
||||
#
|
||||
# libraries
|
||||
#
|
||||
|
||||
find_package(LLVM REQUIRED CONFIG HINTS ${FINDPACKAGE_LLVM_HINTS})
|
||||
|
||||
set(LLVM_LIBRARIES LLVMCore LLVMSupport LLVMAnalysis LLVMipo LLVMIRReader LLVMBitReader LLVMBitWriter LLVMTransformUtils LLVMScalarOpts LLVMLTO)
|
||||
list(APPEND PROJECT_LIBRARIES ${LLVM_LIBRARIES})
|
||||
|
||||
list(APPEND PROJECT_DEFINITIONS ${LLVM_DEFINITIONS})
|
||||
list(APPEND PROJECT_INCLUDEDIRECTORIES ${LLVM_INCLUDE_DIRS})
|
||||
|
||||
# xed
|
||||
find_package(XED REQUIRED)
|
||||
find_package(GLOG REQUIRED)
|
||||
find_package(GFLAGS REQUIRED)
|
||||
find_package(Protobuf REQUIRED)
|
||||
list(APPEND PROJECT_LIBRARIES ${XED_LIBRARIES})
|
||||
list(APPEND PROJECT_INCLUDEDIRECTORIES ${XED_INCLUDE_DIRS})
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
include_directories("${LLVM_INCLUDE_DIRS}")
|
||||
include_directories("${XED_INCLUDE_DIRS}")
|
||||
include_directories("${GLOG_INCLUDE_DIRS}")
|
||||
include_directories("${GFLAGS_INCLUDE_DIRS}")
|
||||
include_directories("${PROTOBUF_INCLUDE_DIRS}")
|
||||
include_directories("${CMAKE_CURRENT_LIST_DIR}")
|
||||
# google log module
|
||||
find_package(glog REQUIRED)
|
||||
list(APPEND PROJECT_LIBRARIES glog::glog)
|
||||
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_CXX_COMPILER})
|
||||
# gflags
|
||||
find_package(gflags REQUIRED)
|
||||
list(APPEND PROJECT_LIBRARIES gflags)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||
#
|
||||
# target settings
|
||||
#
|
||||
|
||||
if(NOT DEFINED CMAKE_C_COMPILER)
|
||||
set(CMAKE_C_COMPILER "${LLVM_INSTALL_PREFIX}/bin/clang-3.9")
|
||||
endif()
|
||||
list(APPEND PROJECT_DEFINITIONS "INSTALL_SEMANTICS_DIR=\"${CMAKE_INSTALL_PREFIX}share/remill/semantics/\"")
|
||||
list(APPEND PROJECT_DEFINITIONS "BUILD_SEMANTICS_DIR=\"${CMAKE_CURRENT_BINARY_DIR}/remill/Arch/X86/Runtime/\"")
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER)
|
||||
set(CMAKE_CXX_COMPILER ${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_ASM_COMPILER)
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_LLVM_LINK)
|
||||
set(CMAKE_LLVM_LINK "${LLVM_INSTALL_PREFIX}/bin/llvm-link")
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
-Werror
|
||||
-pedantic
|
||||
|
||||
-g3
|
||||
-O0
|
||||
|
||||
-Wno-unused-parameter
|
||||
-Wno-c++98-compat
|
||||
-Wno-unreachable-code-return
|
||||
-Wno-nested-anon-types
|
||||
-Wno-extended-offsetof
|
||||
-Wno-gnu-anonymous-struct
|
||||
-Wno-gnu-designator
|
||||
-Wno-variadic-macros
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
-Wno-gnu-statement-expression
|
||||
-Wno-return-type-c-linkage
|
||||
-Wno-c99-extensions
|
||||
-Wno-ignored-attributes
|
||||
-Wno-unused-local-typedef
|
||||
|
||||
-fno-omit-frame-pointer
|
||||
-fvisibility-inlines-hidden
|
||||
|
||||
-fno-exceptions
|
||||
-fno-rtti
|
||||
-fno-asynchronous-unwind-tables
|
||||
|
||||
-fno-rtti
|
||||
-std=gnu++11
|
||||
-m64
|
||||
|
||||
-DINSTALL_SEMANTICS_DIR="${CMAKE_INSTALL_PREFIX}/share/remill/semantics/"
|
||||
-DBUILD_SEMANTICS_DIR="${CMAKE_CURRENT_BINARY_DIR}/remill/Arch/X86/Runtime/"
|
||||
-DGOOGLE_PROTOBUF_NO_RTTI
|
||||
)
|
||||
|
||||
add_library(remill STATIC
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
remill/Arch/X86/Arch.cpp
|
||||
remill/Arch/Arch.cpp
|
||||
remill/Arch/Instruction.cpp
|
||||
remill/Arch/Name.cpp
|
||||
remill/CFG/BlockHasher.cpp
|
||||
remill/CFG/CFG.cpp
|
||||
|
||||
remill/BC/IntrinsicTable.cpp
|
||||
remill/BC/Lifter.cpp
|
||||
remill/BC/Optimizer.cpp
|
||||
remill/BC/Util.cpp
|
||||
|
||||
remill/OS/FileSystem.cpp
|
||||
remill/OS/OS.cpp
|
||||
third_party/murmurhash/MurmurHash2.cpp)
|
||||
|
||||
target_link_libraries(remill
|
||||
${GFLAGS_LIBRARIES}
|
||||
${GLOG_LIBRARIES}
|
||||
${XED_LIBRARIES}
|
||||
${PROTOBUF_LIBRARIES}
|
||||
LLVMCore
|
||||
LLVMSupport
|
||||
LLVMAnalysis
|
||||
LLVMipo
|
||||
LLVMIRReader
|
||||
LLVMBitReader
|
||||
LLVMBitWriter
|
||||
LLVMTransformUtils
|
||||
LLVMScalarOpts
|
||||
LLVMLTO
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS remill
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
# this is needed for the #include directives with absolutes paths to work correctly; it must
|
||||
# also be set to PUBLIC since remill-lift includes some files directly
|
||||
list(APPEND PROJECT_INCLUDEDIRECTORIES ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# add everything as public; the remill_lift executable will inherit all settings from us
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_LIBRARIES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC SYSTEM ${PROJECT_INCLUDEDIRECTORIES})
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_DEFINITIONS})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${PROJECT_CXXFLAGS})
|
||||
|
||||
#
|
||||
# install directives
|
||||
#
|
||||
|
||||
install(DIRECTORY DESTINATION "share/remill")
|
||||
|
||||
#
|
||||
# additional targets
|
||||
#
|
||||
|
||||
add_custom_target(semantics)
|
||||
add_subdirectory(remill/Arch/X86/Runtime)
|
||||
|
||||
add_subdirectory(tools)
|
||||
# mcsema needs to be manually cloned into this repo.
|
||||
if (EXISTS ${CMAKE_SOURCE_DIR}/tools/mcsema)
|
||||
add_subdirectory(tools/mcsema)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(tests/X86)
|
||||
|
||||
# only enable tests when compiling under x64
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(LINUX TRUE)
|
||||
add_subdirectory(tests/X86)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -173,29 +173,4 @@
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016 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.
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -1,8 +1,9 @@
|
||||
# Remill
|
||||
|
||||
|
||||
Remill is a static binary translator that translates machine code into [LLVM bitcode](http://llvm.org/docs/LangRef.html). It translates x86 and amd64 machine code (including AVX and AVX512) into LLVM bitcode.
|
||||
|
||||
Remill focuses on accurately lifting instructions. It is meant to be used as a library for other tools, e.g. [McSema](https://github.com/trailofbits/mcsema).
|
||||
|
||||
## Build Status
|
||||
|
||||
| | master |
|
||||
@@ -15,7 +16,6 @@ Remill is a static binary translator that translates machine code into [LLVM bit
|
||||
- [How to contribute](docs/CONTRIBUTING.md)
|
||||
- [How to implement the semantics of an instruction](docs/ADD_AN_INSTRUCTION.md)
|
||||
- [How instructions are lifted](docs/LIFE_OF_AN_INSTRUCTION.md)
|
||||
- [How binaries are represented](docs/CFG_FORMAT.md)
|
||||
- [The design and architecture of Remill](docs/DESIGN.md)
|
||||
|
||||
## Getting Help
|
||||
@@ -34,19 +34,14 @@ We are actively working on porting Remill to macOS.
|
||||
| ---- | ------- |
|
||||
| [Git](https://git-scm.com/) | Latest |
|
||||
| [CMake](https://cmake.org/) | 3.2+ |
|
||||
| [Google Log](https://github.com/google/glog) | 0.3.3 |
|
||||
| [Google Test](https://github.com/google/googletest) | 1.6.0 |
|
||||
| [Google Protobuf](https://github.com/google/protobuf) | 2.6.1 |
|
||||
| [LLVM](http://llvm.org/) | 3.9 |
|
||||
| [Clang](http://clang.llvm.org/) | 3.9 |
|
||||
| [Google Flags](https://github.com/google/glog) | 2.2.0 |
|
||||
| [Google Log](https://github.com/google/glog) | 0.3.4 |
|
||||
| [Google Test](https://github.com/google/googletest) | 1.8.0 |
|
||||
| [LLVM](http://llvm.org/) | 3.5+ |
|
||||
| [Clang](http://clang.llvm.org/) | 3.5+ |
|
||||
| [Intel XED](https://software.intel.com/en-us/articles/xed-x86-encoder-decoder-software-library) | 2016-02-02 |
|
||||
| [Python](https://www.python.org/) | 2.7 |
|
||||
| [Python Package Index](https://pypi.python.org/pypi) | Latest |
|
||||
| [python-magic](https://pypi.python.org/pypi/python-magic) | Latest |
|
||||
| Unzip | Latest |
|
||||
| [python-protobuf](https://pypi.python.org/pypi/protobuf) | 2.6.1 |
|
||||
| [Binary Ninja](https://binary.ninja) | Latest |
|
||||
| [IDA Pro](https://www.hex-rays.com/products/ida) | 6.7+ |
|
||||
|
||||
## Getting and Building the Code
|
||||
|
||||
@@ -63,30 +58,11 @@ sudo apt-get upgrade
|
||||
sudo apt-get install \
|
||||
git \
|
||||
cmake \
|
||||
libgoogle-glog-dev \
|
||||
libgtest-dev \
|
||||
libprotoc-dev libprotobuf-dev libprotobuf-dev protobuf-compiler \
|
||||
python2.7 python-pip \
|
||||
g++-multilib \
|
||||
build-essential \
|
||||
unzip \
|
||||
software-properties-common \
|
||||
realpath
|
||||
|
||||
sudo pip install --upgrade pip
|
||||
|
||||
sudo pip install python-magic 'protobuf==2.6.1'
|
||||
```
|
||||
|
||||
##### Using IDA on 64 bit Ubuntu
|
||||
|
||||
If your IDA install does not use the system's Python, you can add the `protobuf` library manually to IDA's zip of modules.
|
||||
|
||||
```
|
||||
# Python module dir is generally in /usr/lib or /usr/local/lib
|
||||
touch /path/to/python2.7/dist-packages/google/__init__.py
|
||||
cd /path/to/lib/python2.7/dist-packages/
|
||||
sudo zip -rv /path/to/ida-6.X/python/lib/python27.zip google/
|
||||
sudo chown your_user:your_user /home/taxicat/ida-6.7/python/lib/python27.zip
|
||||
```
|
||||
|
||||
##### Upgrade CMake (Ubuntu 14.04)
|
||||
@@ -106,14 +82,14 @@ sudo apt-get install cmake
|
||||
|
||||
```
|
||||
brew install glog
|
||||
brew install protobuf
|
||||
```
|
||||
|
||||
### Step 2: Clone and Enter the Repository
|
||||
|
||||
#### Clone the repository
|
||||
```shell
|
||||
git clone git@github.com:trailofbits/remill.git
|
||||
This will also clone the cxx_common module (used to generate a library repository) and mcsema.
|
||||
git clone --resursive git@github.com:trailofbits/remill.git
|
||||
```
|
||||
|
||||
#### Enter the repository
|
||||
@@ -121,17 +97,11 @@ git clone git@github.com:trailofbits/remill.git
|
||||
cd remill
|
||||
```
|
||||
|
||||
#### Run the Build Script
|
||||
#### Build the code.
|
||||
```shell
|
||||
./build.sh
|
||||
```
|
||||
|
||||
### Step 3: Install the disassembler
|
||||
|
||||
```shell
|
||||
sudo python tools/setup.py install
|
||||
```
|
||||
|
||||
## Building and Running the Test Suite
|
||||
|
||||
### Build Google Test
|
||||
@@ -153,20 +123,4 @@ ctest
|
||||
|
||||
## Try it Out
|
||||
|
||||
If you have a 64 bit dll, you can get started with the following commands. First, you recover control flow graph information using `remill-disass`, this can use either IDA Pro or Binary Ninja as the disassembler.
|
||||
|
||||
```shell
|
||||
remill-disass --disassembler /path/to/ida/idal64 --arch amd64 --output target.cfg --binary libsomething.dll
|
||||
```
|
||||
|
||||
Once you have the control flow graph information, you can lift the target binary using `remill-lift`.
|
||||
|
||||
```shell
|
||||
remill-lift --arch amd64 --os linux --cfg target.cfg --bc_out target.bc
|
||||
```
|
||||
|
||||
When the bitcode has been recovered by `remill-lift`, it is a good idea to optimize it using `remill-opt`.
|
||||
|
||||
```shell
|
||||
remill-opt --bc_in target.bc --bc_out opt_target.bc
|
||||
```
|
||||
Remill is a library, and so there is no single way to try it. However, you can head on over to the [McSema](https://github.com/trailofbits/mcsema) repository and try that!
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
IMPORTANT - READ BEFORE COPYING, INSTALLING OR USING.
|
||||
|
||||
Do not copy, install, or use the "Materials" provided under this
|
||||
license agreement ("Agreement"), until you have carefully read the
|
||||
following terms and conditions. By copying, installing, or otherwise
|
||||
using the Materials, you agree to be bound by the terms of this
|
||||
Agreement. If you do not agree to the terms of this Agreement, do not
|
||||
copy, install, or use the Materials.
|
||||
|
||||
Pre-Release License Agreement for Pre-Release Software
|
||||
|
||||
1. PRE-RELEASE: The Materials are pre-release code, which may not be
|
||||
fully functional and which Intel may substantially modify in producing
|
||||
any final version. Intel can provide no assurance that it will ever
|
||||
produce or make generally available a final version.
|
||||
|
||||
2. LICENSE DEFINITIONS:
|
||||
|
||||
A. "Materials" are defined as the software, documentation, license key
|
||||
codes and other materials, including any updates and upgrade thereto,
|
||||
for the applicable pre-release software (which may be found at
|
||||
http://whatif.intel.com/), that are provided to you under this
|
||||
Agreement.
|
||||
|
||||
3. LICENSE GRANT:
|
||||
|
||||
A. Subject to all of the terms and conditions of this Agreement, Intel
|
||||
Corporation ("Intel") grants to you a non-exclusive, non-assignable
|
||||
copyright license to make only the minimum number of copies of the
|
||||
Materials reasonably necessary for your internal testing and
|
||||
development of your products.
|
||||
|
||||
B. Subject to all of the terms and conditions of this Agreement, Intel
|
||||
grants to you a non-exclusive, non-assignable copyright license to
|
||||
modify the Materials that are provided in source code (human readable)
|
||||
form.
|
||||
|
||||
C. If the Materials include the file named 'redist.txt', then subject
|
||||
to all of the terms and conditions of this Agreement and any specific
|
||||
restrictions which may appear in the 'redist.txt' file, Intel grants
|
||||
to you a non-exclusive, non-assignable copyright license to
|
||||
redistribute the files (unmodified or modified by you) listed in the
|
||||
'redist.txt' file only as part of the application you develop with the
|
||||
Materials.
|
||||
|
||||
4. LICENSE RESTRICTIONS:
|
||||
|
||||
A. You may not reverse-assemble, reverse-compile, or otherwise
|
||||
reverse-engineer any software provided solely in binary form.
|
||||
|
||||
B. You may not distribute any portion of Materials, whether in source
|
||||
or binary form, to any third party, except as specified in this
|
||||
Agreement.
|
||||
|
||||
5. COPYRIGHT: Title to the Materials and all copies thereof remain
|
||||
with Intel or its suppliers. The Materials are copyrighted and are
|
||||
protected by United States copyright laws and international treaty
|
||||
provisions. You will not remove any copyright notice from the
|
||||
Materials. You agree to prevent any unauthorized copying of the
|
||||
Materials. Except as expressly provided herein, Intel does not grant
|
||||
any express or implied right to you under Intel patents, copyrights,
|
||||
trademarks, or trade secret information. Subject to Intel's ownership
|
||||
of the Materials, all right, title and interest in and to your
|
||||
modifications shall belong to you.
|
||||
|
||||
6. REPLACEMENTS: The Materials are provided "AS IS" without warranty
|
||||
of any kind. If the media on which the Materials are furnished are
|
||||
found to be defective in material or workmanship under normal use for
|
||||
a period of ninety (90) days from the date of receipt, Intel's entire
|
||||
liability and your exclusive remedy shall be the replacement of the
|
||||
media. This offer is void if the media defect results from accident,
|
||||
abuse, or misapplication.
|
||||
|
||||
7. LIMITATION OF LIABILITY: THE ABOVE REPLACEMENT PROVISION IS THE
|
||||
ONLY WARRANTY OF ANY KIND. INTEL OFFERS NO OTHER WARRANTY EITHER
|
||||
EXPRESS OR IMPLIED INCLUDING THOSE OF MERCHANTABILITY, NONINFRINGEMENT
|
||||
OF THIRD- PARTY INTELLECTUAL PROPERTY OR FITNESS FOR A PARTICULAR
|
||||
PURPOSE. NEITHER INTEL NOR ITS SUPPLIERS SHALL BE LIABLE FOR ANY
|
||||
DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF
|
||||
BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,
|
||||
OR OTHER LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
|
||||
SOFTWARE, EVEN IF INTEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR
|
||||
LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE
|
||||
ABOVE LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
8. UNAUTHORIZED USE: THE MATERIALS ARE NOT DESIGNED, INTENDED, OR
|
||||
AUTHORIZED FOR USE IN ANY TYPE OF SYSTEM OR APPLICATION IN WHICH THE
|
||||
FAILURE OF THE MATERIALS COULD CREATE A SITUATION WHERE PERSONAL
|
||||
INJURY OR DEATH MAY OCCUR (E.G MEDICAL SYSTEMS, LIFE SUSTAINING OR
|
||||
LIFE SAVING SYSTEMS). Should the buyer purchase or use the Materials
|
||||
for any such unintended or unauthorized use, the buyer shall indemnify
|
||||
and hold Intel and its officers, subsidiaries and affiliates harmless
|
||||
against all claims, costs, damages, and expenses, and reasonable
|
||||
attorney fees arising out of, directly or indirectly, any claim of
|
||||
product liability, personal injury or death associated with such
|
||||
unintended or unauthorized use, even if such claim alleges that Intel
|
||||
was negligent regarding the design or manufacture of the part.
|
||||
|
||||
9. USER SUBMISSIONS: You agree that any material, information or other
|
||||
communication, including all data, images, sounds, text, and other
|
||||
things embodied therein, you transmit or post to an Intel website or
|
||||
provide to Intel under this Agreement will be considered
|
||||
non-confidential ("Communications"). Intel will have no
|
||||
confidentiality obligations with respect to the Communications. You
|
||||
agree that Intel and its designees will be free to copy, modify,
|
||||
create derivative works, publicly display, disclose, distribute,
|
||||
license and sublicense through multiple tiers of distribution and
|
||||
licensees, incorporate and otherwise use the Communications, including
|
||||
derivative works thereto, for any and all commercial or non-commercial
|
||||
purposes.
|
||||
|
||||
10. TERMINATION OF THIS LICENSE: The term of this Agreement will
|
||||
commence on the date this Agreement is accepted by You and will
|
||||
continue until terminated. This Agreement will terminate without
|
||||
notice on the last day of the pre-release period, which is specified
|
||||
elsewhere in the Materials, or upon the commercial release of the
|
||||
Materials. Intel may terminate this Agreement at any time, with or
|
||||
without cause, with written notice to you. Upon termination, you will
|
||||
immediately destroy the Materials or return all copies of the
|
||||
Materials to Intel along with any copies you have made.
|
||||
|
||||
11. U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
|
||||
"RESTRICTED RIGHTS". Use, duplication or disclosure by the Government
|
||||
is subject to restrictions set forth in FAR52.227-14 and
|
||||
DFAR252.227-7013 et seq. or its successor. Use of the Materials by the
|
||||
Government constitutes acknowledgment of Intel's rights in them.
|
||||
|
||||
12. EXPORT RESTRICTED RIGHTS: This software is subject to the
|
||||
U.S. Export Administration Regulations and other U.S. law, and may not
|
||||
be exported or re-exported to certain countries (Burma, Cuba, Iran,
|
||||
North Korea, Sudan, and Syria) or to persons or entities prohibited
|
||||
from receiving U.S. exports (including Denied Parties, Specially
|
||||
Designated Nationals, and entities on the Bureau of Export
|
||||
Administration Entity List or involved with missile technology or
|
||||
nuclear, chemical or biological weapons).
|
||||
|
||||
13. APPLICABLE LAWS: Any claim arising under or relating to this
|
||||
Agreement shall be governed by the internal substantive laws of the
|
||||
State of Delaware or federal courts located in Delaware, without
|
||||
regard to principles of conflict of laws. You may not export the
|
||||
Materials in violation of applicable export laws.
|
||||
|
||||
* Other names and brands may be claimed as the property of others
|
||||
@@ -1,6 +0,0 @@
|
||||
This file is redist.txt.
|
||||
|
||||
The files in the directories "include", "lib", "doc", "misc",
|
||||
"mbuild", and "examples" if present, are allowed to be redistributed
|
||||
subject to the terms of the license found in the LICENSE.txt file.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
-33252
File diff suppressed because it is too large
Load Diff
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved.
|
||||
|
||||
set -e
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
BUILD_DIR=${DIR}/build
|
||||
LLVM_DIR=llvm
|
||||
|
||||
ARCH=$(uname -m)
|
||||
LLVM_VER=3.9.0
|
||||
|
||||
case $(uname -s) in
|
||||
Darwin)
|
||||
OS=apple-darwin
|
||||
FILE=clang+llvm-${LLVM_VER}-${ARCH}-${OS}.tar.xz
|
||||
;;
|
||||
Linux)
|
||||
OS=linux-gnu
|
||||
DISTRO=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
|
||||
DIST_VERSION=$(lsb_release -sr)
|
||||
if [ $DIST_VERSION == "15.04" ]; then
|
||||
DIST_VERSION="14.04"
|
||||
fi
|
||||
FILE=clang+llvm-${LLVM_VER}-${ARCH}-${OS}-${DISTRO}-${DIST_VERSION}.tar.xz
|
||||
;;
|
||||
*)
|
||||
echo '[!] Unsupported OS'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
echo "[+] Creating '${BUILD_DIR}'"
|
||||
mkdir -p ${BUILD_DIR}
|
||||
pushd ${BUILD_DIR}
|
||||
|
||||
if [ ! -f ${FILE} ]; then
|
||||
echo "[+] Downloading Clang+LLVM.."
|
||||
wget http://llvm.org/releases/${LLVM_VER}/${FILE}
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "[!] Unsupported operating system."
|
||||
echo "[!] Check http://llvm.org/releases/${LLVM_VER}/ to see what LLVM"
|
||||
echo "[!] packages are available."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -d ${LLVM_DIR} ]; then
|
||||
echo "[+] Extracting.."
|
||||
mkdir ${LLVM_DIR}
|
||||
tar xf ${FILE} -C ${LLVM_DIR} --strip-components=1
|
||||
fi
|
||||
echo "[+] Installing Xed"
|
||||
$DIR/scripts/unix/install_xed.sh
|
||||
echo "[+] Installing gtest"
|
||||
$DIR/scripts/unix/install_gtest.sh
|
||||
echo "[+] Compiling protobufs"
|
||||
$DIR/scripts/unix/compile_protobufs.sh
|
||||
echo "[+] Running cmake"
|
||||
|
||||
LLVM_DIR=${BUILD_DIR}/${LLVM_DIR}
|
||||
LLVM_DIR=$(realpath ${LLVM_DIR})
|
||||
BINDIR=${LLVM_DIR}/bin
|
||||
LLVM_DIR=${LLVM_DIR}/lib/cmake/llvm
|
||||
|
||||
cmake -DLLVM_DIR=${LLVM_DIR} -DCMAKE_C_COMPILER=${BINDIR}/clang -DCMAKE_CXX_COMPILER=${BINDIR}/clang++ -DCMAKE_LLVM_LINK=${BINDIR}/llvm-link ${DIR}
|
||||
echo "[+] Building"
|
||||
make
|
||||
echo "[+] installing"
|
||||
sudo make install
|
||||
@@ -0,0 +1,8 @@
|
||||
set(CMAKE_BC_COMPILER "@CMAKE_BC_COMPILER@")
|
||||
set(CMAKE_BC_LINKER "@CMAKE_BC_LINKER@")
|
||||
|
||||
set(CMAKE_BC_COMPILER_LOADED 1)
|
||||
set(CMAKE_BC_SOURCE_FILE_EXTENSIONS bcpp)
|
||||
set(CMAKE_BC_OUTPUT_EXTENSION .bo)
|
||||
set(CMAKE_BC_OUTPUT_EXTENSION_REPLACE 1)
|
||||
set(CMAKE_BC_COMPILER_ENV_VAR "BC_COMPILER")
|
||||
@@ -0,0 +1,69 @@
|
||||
set(DEFAULT_BC_COMPILER_FLAGS "-std=gnu++11 -emit-llvm -Wno-unknown-warning-option -Werror -Wall -Wshadow -Wconversion -Wpadded -pedantic -Wshorten-64-to-32 -Wno-gnu-anonymous-struct -Wno-return-type-c-linkage -Wno-gnu-zero-variadic-macro-arguments -Wno-nested-anon-types -Wno-extended-offsetof -Wno-gnu-statement-expression -Wno-c99-extensions -Wno-ignored-attributes -mtune=generic -fno-vectorize -fno-slp-vectorize -ffreestanding -fno-common -fno-builtin -fno-exceptions -fno-rtti -fno-asynchronous-unwind-tables -Wno-unneeded-internal-declaration -Wno-unused-function")
|
||||
|
||||
if (NOT CMAKE_BC_COMPILE_OBJECT)
|
||||
if (NOT DEFINED CMAKE_BC_COMPILER)
|
||||
message(SEND_ERROR "The bitcode compiler was not found!")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_BC_COMPILE_OBJECT "${CMAKE_BC_COMPILER} <DEFINES> <INCLUDES> ${DEFAULT_BC_COMPILER_FLAGS} <FLAGS> -c <SOURCE> -o <OBJECT>")
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BC_LINK_EXECUTABLE)
|
||||
if (NOT DEFINED CMAKE_BC_LINKER)
|
||||
message(SEND_ERROR "The bitcode linker was not found!")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_BC_LINK_EXECUTABLE "${CMAKE_BC_LINKER} <OBJECTS> -o <TARGET>")
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_INCLUDE_FLAG_BC)
|
||||
set(CMAKE_INCLUDE_FLAG_BC -I)
|
||||
endif ()
|
||||
|
||||
# this is the runtime target generator, used in a similar way to add_executable
|
||||
set(add_runtime_usage "add_runtime(target_name SOURCES <source file list> ADDRESS_SIZE <size>")
|
||||
|
||||
function (add_runtime target_name)
|
||||
foreach (macro_parameter ${ARGN})
|
||||
if ("${macro_parameter}" STREQUAL "SOURCES")
|
||||
set(state "${macro_parameter}")
|
||||
continue ()
|
||||
|
||||
elseif ("${macro_parameter}" STREQUAL "ADDRESS_SIZE")
|
||||
set(state "${macro_parameter}")
|
||||
continue ()
|
||||
endif ()
|
||||
|
||||
if ("${state}" STREQUAL "SOURCES")
|
||||
set_source_files_properties("${macro_parameter}" PROPERTIES LANGUAGE BC)
|
||||
list(APPEND source_file_list "${macro_parameter}")
|
||||
|
||||
elseif ("${state}" STREQUAL "ADDRESS_SIZE")
|
||||
if (NOT "${macro_parameter}" MATCHES "^[0-9]+$")
|
||||
message(SEND_ERROR "Invalid ADDRESS_SIZE parameter passed to add_runtime")
|
||||
endif ()
|
||||
|
||||
list(APPEND definitions "ADDRESS_SIZE_BITS=${macro_parameter}")
|
||||
set(address_size_bits_found True)
|
||||
|
||||
else ()
|
||||
message(SEND_ERROR "Syntax error. Usage: ${add_runtime_usage}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
foreach (source_file ${sourcefile_list})
|
||||
set_source_files_properties("${source_file}" PROPERTIES LANGUAGE BC)
|
||||
endforeach ()
|
||||
|
||||
if (NOT address_size_bits_found)
|
||||
message(SEND_ERROR "Missing address size.")
|
||||
endif ()
|
||||
|
||||
if ("${source_file_list}" STREQUAL "")
|
||||
message(SEND_ERROR "No source files specified.")
|
||||
endif ()
|
||||
|
||||
add_executable("${target_name}" ${source_file_list})
|
||||
target_compile_definitions("${target_name}" PRIVATE ${definitions})
|
||||
set_target_properties("${target_name}" PROPERTIES SUFFIX ".bc")
|
||||
endfunction ()
|
||||
@@ -0,0 +1,54 @@
|
||||
if (NOT DEFINED CMAKE_BC_COMPILER)
|
||||
if (NOT "$ENV{LLVM_INSTALL_PREFIX}" STREQUAL "")
|
||||
message(STATUS "Setting LLVM_INSTALL_PREFIX from the environment variable...")
|
||||
set(LLVM_INSTALL_PREFIX $ENV{TRAILOFBITS_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
if (NOT "${LLVM_INSTALL_PREFIX}" STREQUAL "")
|
||||
message(STATUS "Using LLVM_INSTALL_PREFIX to locate the bitcode compiler")
|
||||
|
||||
if (NOT EXISTS "${LLVM_INSTALL_PREFIX}/bin/clang++")
|
||||
message(SEND_ERROR "Could not find the bitcode compiler set in environment variable LLVM_INSTALL_PREFIX: $ENV{LLVM_INSTALL_PREFIX}.")
|
||||
endif ()
|
||||
|
||||
if (NOT EXISTS "${LLVM_INSTALL_PREFIX}/bin/llvm-link")
|
||||
message(SEND_ERROR "Could not find the bitcode linker set in environment variable LLVM_INSTALL_PREFIX: $ENV{LLVM_INSTALL_PREFIX}.")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_BC_COMPILER "${LLVM_INSTALL_PREFIX}/bin/clang++" CACHE PATH "Bitcode Compiler")
|
||||
set(CMAKE_BC_LINKER "${LLVM_INSTALL_PREFIX}/bin/llvm-link" CACHE PATH "Bitcode Linker")
|
||||
set(CMAKE_BC_COMPILER_ENV_VAR "BC_COMPILER")
|
||||
else ()
|
||||
find_program(CLANG_PATH
|
||||
NAMES "clang++"
|
||||
PATHS "/usr/bin" "/usr/local/bin"
|
||||
)
|
||||
|
||||
find_program(LLVMLINK_PATH
|
||||
NAMES "llvm-link"
|
||||
PATHS "/usr/bin" "/usr/local/bin"
|
||||
)
|
||||
|
||||
if (NOT DEFINED CLANG_PATH OR NOT DEFINED LLVMLINK_PATH)
|
||||
message(SEND_ERROR "Could not find the bitcode compiler and linker. Either install Clang in the default or define the LLVM_INSTALL_PREFIX environment variable.")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_BC_COMPILER "${CLANG_PATH}" CACHE PATH "Bitcode Compiler")
|
||||
set(CMAKE_BC_LINKER "${LLVMLINK_PATH}" CACHE PATH "Bitcode Linker")
|
||||
set(CMAKE_BC_COMPILER_ENV_VAR "BC_COMPILER")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
mark_as_advanced(CMAKE_BC_COMPILER)
|
||||
mark_as_advanced(CMAKE_BC_LINKER)
|
||||
mark_as_advanced(CMAKE_BC_COMPILER_ENV_VAR)
|
||||
|
||||
if (NOT "${CMAKE_BC_COMPILER}" STREQUAL "")
|
||||
message(STATUS "Found bitcode compiler: ${CMAKE_BC_COMPILER}")
|
||||
endif ()
|
||||
|
||||
if (NOT "${CMAKE_BC_LINKER}" STREQUAL "")
|
||||
message(STATUS "Found bitcode linker: ${CMAKE_BC_LINKER}")
|
||||
endif ()
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/BCCompiler/CMakeBCCompiler.cmake.in ${CMAKE_PLATFORM_INFO_DIR}/CMakeBCCompiler.cmake @ONLY)
|
||||
@@ -0,0 +1 @@
|
||||
set(CMAKE_BC_COMPILER_WORKS 1 CACHE INTERNAL "")
|
||||
@@ -1,52 +0,0 @@
|
||||
# https://github.com/yahoo/caffe/blob/master/cmake/Modules/FindGFlags.cmake
|
||||
|
||||
# - Try to find GFLAGS
|
||||
#
|
||||
# The following variables are optionally searched for defaults
|
||||
# GFLAGS_ROOT_DIR: Base directory where all GFLAGS components are found
|
||||
#
|
||||
# The following are set after configuration is done:
|
||||
# GFLAGS_FOUND
|
||||
# GFLAGS_INCLUDE_DIRS
|
||||
# GFLAGS_LIBRARIES
|
||||
# GFLAGS_LIBRARYRARY_DIRS
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set(GFLAGS_ROOT_DIR "" CACHE PATH "Folder contains Gflags")
|
||||
|
||||
# We are testing only a couple of files in the include directories
|
||||
if(WIN32)
|
||||
find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h
|
||||
PATHS ${GFLAGS_ROOT_DIR}/src/windows)
|
||||
else()
|
||||
find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h
|
||||
PATHS ${GFLAGS_ROOT_DIR})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
find_library(GFLAGS_LIBRARY_RELEASE
|
||||
NAMES libgflags
|
||||
PATHS ${GFLAGS_ROOT_DIR}
|
||||
PATH_SUFFIXES Release)
|
||||
|
||||
find_library(GFLAGS_LIBRARY_DEBUG
|
||||
NAMES libgflags-debug
|
||||
PATHS ${GFLAGS_ROOT_DIR}
|
||||
PATH_SUFFIXES Debug)
|
||||
|
||||
set(GFLAGS_LIBRARY optimized ${GFLAGS_LIBRARY_RELEASE} debug ${GFLAGS_LIBRARY_DEBUG})
|
||||
else()
|
||||
find_library(GFLAGS_LIBRARY gflags)
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(GFlags DEFAULT_MSG GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)
|
||||
|
||||
|
||||
if(GFLAGS_FOUND)
|
||||
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})
|
||||
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY})
|
||||
message(STATUS "Found gflags (include: ${GFLAGS_INCLUDE_DIR}, library: ${GFLAGS_LIBRARY})")
|
||||
mark_as_advanced(GFLAGS_LIBRARY_DEBUG GFLAGS_LIBRARY_RELEASE
|
||||
GFLAGS_LIBRARY GFLAGS_INCLUDE_DIR GFLAGS_ROOT_DIR)
|
||||
endif()
|
||||
@@ -1,81 +0,0 @@
|
||||
# https://github.com/yahoo/caffe/blob/master/cmake/Modules/FindGlog.cmake
|
||||
|
||||
# - Try to find the Google Glog library
|
||||
#
|
||||
# This module defines the following variables
|
||||
#
|
||||
# GLOG_FOUND - Was Glog found
|
||||
# GLOG_INCLUDE_DIRS - the Glog include directories
|
||||
# GLOG_LIBRARIES - Link to this
|
||||
#
|
||||
# This module accepts the following variables
|
||||
#
|
||||
# GLOG_ROOT - Can be set to Glog install path or Windows build path
|
||||
#
|
||||
|
||||
if (NOT DEFINED GLOG_ROOT)
|
||||
set (GLOG_ROOT /usr /usr/local)
|
||||
endif (NOT DEFINED GLOG_ROOT)
|
||||
|
||||
if(MSVC)
|
||||
set(LIB_PATHS ${GLOG_ROOT} ${GLOG_ROOT}/Release)
|
||||
else(MSVC)
|
||||
set (LIB_PATHS ${GLOG_ROOT} ${GLOG_ROOT}/lib)
|
||||
endif(MSVC)
|
||||
|
||||
macro(_FIND_GLOG_LIBRARIES _var)
|
||||
find_library(${_var}
|
||||
NAMES ${ARGN}
|
||||
PATHS ${LIB_PATHS} /opt/local/lib
|
||||
/usr/lib/x86_64-linux-gnu
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
mark_as_advanced(${_var})
|
||||
endmacro()
|
||||
|
||||
macro(_GLOG_APPEND_LIBRARIES _list _release)
|
||||
set(_debug ${_release}_DEBUG)
|
||||
if(${_debug})
|
||||
set(${_list} ${${_list}} optimized ${${_release}} debug ${${_debug}})
|
||||
else()
|
||||
set(${_list} ${${_list}} ${${_release}})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
# Linux/OS X builds
|
||||
find_path(GLOG_INCLUDE_DIR NAMES raw_logging.h
|
||||
PATHS ${GLOG_ROOT}/include/glog
|
||||
/usr/include/glog
|
||||
/opt/local/include/glog # default location in Macports
|
||||
)
|
||||
|
||||
# Find the libraries
|
||||
# Linux/OS X builds
|
||||
if(UNIX)
|
||||
_FIND_GLOG_LIBRARIES(GLOG_LIBRARIES libglog.so)
|
||||
endif(UNIX)
|
||||
if(APPLE)
|
||||
_FIND_GLOG_LIBRARIES(GLOG_LIBRARIES libglog.dylib)
|
||||
endif(APPLE)
|
||||
|
||||
if(GLOG_FOUND)
|
||||
message(STATUS "glog library found at ${GLOG_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set GLOG_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include("${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake")
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Glog DEFAULT_MSG
|
||||
GLOG_LIBRARIES)
|
||||
|
||||
# Linux/OS X builds
|
||||
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
|
||||
string(REGEX REPLACE "/libglog.so" "" GLOG_LIBRARIES_DIR ${GLOG_LIBRARIES})
|
||||
|
||||
if(GLOG_FOUND)
|
||||
message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIRS}, library: ${GLOG_LIBRARIES})")
|
||||
# _GLOG_APPEND_LIBRARIES(GLOG GLOG_LIBRARIES)
|
||||
endif()
|
||||
@@ -1,159 +0,0 @@
|
||||
# Locate the Google C++ Testing Framework.
|
||||
#
|
||||
# Defines the following variables:
|
||||
#
|
||||
# GTEST_FOUND - Found the Google Testing framework
|
||||
# GTEST_INCLUDE_DIRS - Include directories
|
||||
#
|
||||
# Also defines the library variables below as normal
|
||||
# variables. These contain debug/optimized keywords when
|
||||
# a debugging library is found.
|
||||
#
|
||||
# GTEST_BOTH_LIBRARIES - Both libgtest & libgtest-main
|
||||
# GTEST_LIBRARIES - libgtest
|
||||
# GTEST_MAIN_LIBRARIES - libgtest-main
|
||||
#
|
||||
# Accepts the following variables as input:
|
||||
#
|
||||
# GTEST_ROOT - (as a CMake or environment variable)
|
||||
# The root directory of the gtest install prefix
|
||||
#
|
||||
# GTEST_MSVC_SEARCH - If compiling with MSVC, this variable can be set to
|
||||
# "MD" or "MT" to enable searching a GTest build tree
|
||||
# (defaults: "MD")
|
||||
#
|
||||
#-----------------------
|
||||
# Example Usage:
|
||||
#
|
||||
# enable_testing()
|
||||
# find_package(GTest REQUIRED)
|
||||
# include_directories(${GTEST_INCLUDE_DIRS})
|
||||
#
|
||||
# add_executable(foo foo.cc)
|
||||
# target_link_libraries(foo ${GTEST_BOTH_LIBRARIES})
|
||||
#
|
||||
# add_test(AllTestsInFoo foo)
|
||||
#
|
||||
#-----------------------
|
||||
#
|
||||
# If you would like each Google test to show up in CTest as
|
||||
# a test you may use the following macro.
|
||||
# NOTE: It will slow down your tests by running an executable
|
||||
# for each test and test fixture. You will also have to rerun
|
||||
# CMake after adding or removing tests or test fixtures.
|
||||
#
|
||||
# GTEST_ADD_TESTS(executable extra_args ARGN)
|
||||
# executable = The path to the test executable
|
||||
# extra_args = Pass a list of extra arguments to be passed to
|
||||
# executable enclosed in quotes (or "" for none)
|
||||
# ARGN = A list of source files to search for tests & test
|
||||
# fixtures.
|
||||
#
|
||||
# Example:
|
||||
# set(FooTestArgs --foo 1 --bar 2)
|
||||
# add_executable(FooTest FooUnitTest.cc)
|
||||
# GTEST_ADD_TESTS(FooTest "${FooTestArgs}" FooUnitTest.cc)
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009 Kitware, Inc.
|
||||
# Copyright 2009 Philip Lowman <philip@yhbt.com>
|
||||
# Copyright 2009 Daniel Blezek <blezek@gmail.com>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distributed this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
#
|
||||
# Thanks to Daniel Blezek <blezek@gmail.com> for the GTEST_ADD_TESTS code
|
||||
|
||||
function(GTEST_ADD_TESTS executable extra_args)
|
||||
if(NOT ARGN)
|
||||
message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS")
|
||||
endif()
|
||||
foreach(source ${ARGN})
|
||||
file(READ "${source}" contents)
|
||||
string(REGEX MATCHALL "TEST_?F?\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents})
|
||||
foreach(hit ${found_tests})
|
||||
string(REGEX REPLACE ".*\\( *([A-Za-z_0-9]+), *([A-Za-z_0-9]+) *\\).*" "\\1.\\2" test_name ${hit})
|
||||
add_test(${test_name} ${executable} --gtest_filter=${test_name} ${extra_args})
|
||||
list(APPEND _test_names ${test_name})
|
||||
endforeach()
|
||||
endforeach()
|
||||
set(GTEST_ADD_TEST_NAMES ${_test_names} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_gtest_append_debugs _endvar _library)
|
||||
if(${_library} AND ${_library}_DEBUG)
|
||||
set(_output optimized ${${_library}} debug ${${_library}_DEBUG})
|
||||
else()
|
||||
set(_output ${${_library}})
|
||||
endif()
|
||||
set(${_endvar} ${_output} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(_gtest_find_library _name)
|
||||
find_library(${_name}
|
||||
NAMES ${ARGN}
|
||||
HINTS
|
||||
$ENV{GTEST_ROOT}
|
||||
${GTEST_ROOT}
|
||||
PATH_SUFFIXES ${_gtest_libpath_suffixes}
|
||||
)
|
||||
mark_as_advanced(${_name})
|
||||
endfunction()
|
||||
|
||||
#
|
||||
|
||||
if(NOT DEFINED GTEST_MSVC_SEARCH)
|
||||
set(GTEST_MSVC_SEARCH MD)
|
||||
endif()
|
||||
|
||||
set(_gtest_libpath_suffixes lib)
|
||||
if(MSVC)
|
||||
if(GTEST_MSVC_SEARCH STREQUAL "MD")
|
||||
list(APPEND _gtest_libpath_suffixes
|
||||
msvc/gtest-md/Debug
|
||||
msvc/gtest-md/Release)
|
||||
elseif(GTEST_MSVC_SEARCH STREQUAL "MT")
|
||||
list(APPEND _gtest_libpath_suffixes
|
||||
msvc/gtest/Debug
|
||||
msvc/gtest/Release)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
find_path(GTEST_INCLUDE_DIR gtest/gtest.h
|
||||
HINTS
|
||||
$ENV{GTEST_ROOT}/include
|
||||
${GTEST_ROOT}/include
|
||||
)
|
||||
mark_as_advanced(GTEST_INCLUDE_DIR)
|
||||
|
||||
if(MSVC AND GTEST_MSVC_SEARCH STREQUAL "MD")
|
||||
# The provided /MD project files for Google Test add -md suffixes to the
|
||||
# library names.
|
||||
_gtest_find_library(GTEST_LIBRARY gtest-md gtest)
|
||||
_gtest_find_library(GTEST_LIBRARY_DEBUG gtest-mdd gtestd)
|
||||
_gtest_find_library(GTEST_MAIN_LIBRARY gtest_main-md gtest_main)
|
||||
_gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_main-mdd gtest_maind)
|
||||
else()
|
||||
_gtest_find_library(GTEST_LIBRARY gtest)
|
||||
_gtest_find_library(GTEST_LIBRARY_DEBUG gtestd)
|
||||
_gtest_find_library(GTEST_MAIN_LIBRARY gtest_main)
|
||||
_gtest_find_library(GTEST_MAIN_LIBRARY_DEBUG gtest_maind)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTest DEFAULT_MSG GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY)
|
||||
|
||||
if(GTEST_FOUND)
|
||||
set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIR})
|
||||
_gtest_append_debugs(GTEST_LIBRARIES GTEST_LIBRARY)
|
||||
_gtest_append_debugs(GTEST_MAIN_LIBRARIES GTEST_MAIN_LIBRARY)
|
||||
set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
endif()
|
||||
@@ -1,75 +0,0 @@
|
||||
# - Try to find the Intel XED library
|
||||
#
|
||||
# This module defines the following variables
|
||||
#
|
||||
# XED_FOUND - Was XED found
|
||||
# XED_INCLUDE_DIRS - the XED include directories
|
||||
# XED_LIBRARIES - Link to this
|
||||
#
|
||||
# This module accepts the following variables
|
||||
#
|
||||
# XED_ROOT - Can be set to XED install path or Windows build path
|
||||
#
|
||||
|
||||
if (NOT DEFINED XED_ROOT)
|
||||
set (XED_ROOT /usr /usr/local)
|
||||
endif (NOT DEFINED XED_ROOT)
|
||||
|
||||
set (LIB_PATHS ${XED_ROOT} ${XED_ROOT}/lib)
|
||||
|
||||
macro(_FIND_XED_LIBRARIES _var)
|
||||
find_library(${_var}
|
||||
NAMES ${ARGN}
|
||||
PATHS ${LIB_PATHS} /opt/local/lib
|
||||
/usr/lib/x86_64-linux-gnu
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
mark_as_advanced(${_var})
|
||||
endmacro()
|
||||
|
||||
macro(_XED_APPEND_LIBRARIES _list _release)
|
||||
set(_debug ${_release}_DEBUG)
|
||||
if(${_debug})
|
||||
set(${_list} ${${_list}} optimized ${${_release}} debug ${${_debug}})
|
||||
else()
|
||||
set(${_list} ${${_list}} ${${_release}})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
# Linux/OS X builds
|
||||
find_path(XED_INCLUDE_DIR NAMES intel/xed-interface.h
|
||||
PATHS ${XED_ROOT}/include
|
||||
/usr/include
|
||||
/opt/local/include
|
||||
)
|
||||
|
||||
# Find the libraries
|
||||
# Linux/OS X builds
|
||||
if(UNIX)
|
||||
_FIND_XED_LIBRARIES(XED_LIBRARIES libxed.so)
|
||||
endif(UNIX)
|
||||
if(APPLE)
|
||||
_FIND_XED_LIBRARIES(XED_LIBRARIES libxed.a)
|
||||
endif(APPLE)
|
||||
|
||||
if(XED_FOUND)
|
||||
message(STATUS "xed library found at ${XED_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set XED_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include("${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake")
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(XED DEFAULT_MSG
|
||||
XED_LIBRARIES)
|
||||
|
||||
# Linux/OS X builds
|
||||
set(XED_INCLUDE_DIRS ${XED_INCLUDE_DIR})
|
||||
string(REGEX REPLACE "/libxed.so" "" XED_LIBRARIES_DIR ${XED_LIBRARIES})
|
||||
|
||||
if(XED_FOUND)
|
||||
message(STATUS "Found xed (include: ${XED_INCLUDE_DIRS}, library: ${XED_LIBRARIES})")
|
||||
# _XED_APPEND_LIBRARIES(XED XED_LIBRARIES)
|
||||
endif()
|
||||
@@ -0,0 +1,5 @@
|
||||
pkg
|
||||
remill
|
||||
src
|
||||
*.pkg.tar.xz
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
pkgname=remill
|
||||
pkgver=20170417_35c6221
|
||||
pkgrel=0
|
||||
arch=('x86_64')
|
||||
|
||||
pkgdesc="Machine code to LLVM binary translator."
|
||||
url="https://github.com/trailofbits/remill"
|
||||
license=('Apache')
|
||||
|
||||
makedepends=('git')
|
||||
|
||||
provides=('remill')
|
||||
conflicts=('remill')
|
||||
|
||||
source=("${pkgname}::git+https://github.com/trailofbits/remill.git#branch=alessandro/refactor/cmake")
|
||||
sha1sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname}"
|
||||
git log -1 --date=format:%Y%m%d --pretty=format:%ad_%h
|
||||
}
|
||||
|
||||
build() {
|
||||
if [ ! -d build ] ; then
|
||||
mkdir build
|
||||
cd build
|
||||
else
|
||||
cd build
|
||||
make clean
|
||||
fi
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=${pkgdir} ${srcdir}/${pkgname}
|
||||
make -j `nproc`
|
||||
}
|
||||
|
||||
package() {
|
||||
cd build
|
||||
make install
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
# How Remill reads code: the control-flow graph format
|
||||
|
||||
This document describes one of the main inputs to Remill, a control-flow graph
|
||||
formatted and stored as a protocol buffer. The file format is described in the
|
||||
[CFG.proto](/remill/CFG/CFG.proto) file.
|
||||
|
||||
## Instructions
|
||||
|
||||
Instructions are encoded with the `Instr` message type:
|
||||
|
||||
```protobuf
|
||||
message Instr {
|
||||
required bytes bytes = 1;
|
||||
required uint64 address = 2;
|
||||
}
|
||||
```
|
||||
|
||||
The two fields of this message are:
|
||||
- `bytes`: The raw bytes of the instruction
|
||||
- `address`: The address of the instruction within the executable or object file
|
||||
|
||||

|
||||
|
||||
In the above example from Binary Ninja, an `Instr` data structure for the `call sub_8048a40` would have:
|
||||
- `bytes` as `"\xe8\xa3\xd2\xff\xff"`
|
||||
- `address` as `0804b798`
|
||||
|
||||
In practice, the `address` field is really just an offset from the beginning of a binary. The location at which binaries can be loaded varies according to the OS, as well as the current execution of the binary. For example, a shared library is likely to be loaded at different runtime memory addresses during different program executions when [ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization) is enabled.
|
||||
|
||||
## Basic blocks
|
||||
|
||||
Basic blocks of code an encoded with the `Block` message type:
|
||||
|
||||
```protobuf
|
||||
message Block {
|
||||
required uint64 address = 1;
|
||||
required bool is_addressable = 2;
|
||||
repeated Instr instructions = 3;
|
||||
}
|
||||
```
|
||||
|
||||
Basic blocks in the CFG format are not equivalent to basic blocks as presented in the IDA or Binary Ninja GUIs. Notice that the basic block in the above image has four instructions. In Remill, this assembly listing correspond to the three highlighted basic blocks:
|
||||
|
||||

|
||||
|
||||
In Remill, all basic blocks end at control-flow instructions, or at fall-through instructions. The following general rules apply:
|
||||
|
||||
- The ends of blocks in IDA or Binary Ninja are also the ends of `Block`s in Remill
|
||||
- Blocks in IDA or Binary Ninja containing `call` instructions must be split into distinct `Block`s in remill, each "sub" block ending at the `call` instruction. Other split points (on x86) are `syscall`, `sysret`, `sysenter`, `sysexit`, `int`, `int3`, `into`, `bound`, and `cpuid`.
|
||||
|
||||
The `address`es of the individual `Block`s are `0804b793` (red), `0804b798` (green), and `0804b79d` (blue), respectively.
|
||||
|
||||
The `is_addressable` field in the `Block` message is more subtle and exposes a detail about how control-flow in Remill is represented. Remill is a block-based binary translator. Whereas [McSema](https://github.com/trailofbits/mcsema) translates whole functions at a time, Remill only translates one block at a time.
|
||||
|
||||
Each `Block` message in the CFG protocol buffer is represented by a distinct LLVM function in the lifted bitcode. Control-flow between basic blocks in the machine code is represented as function [tail calls](https://en.wikipedia.org/wiki/Tail_call) between between lifted block functions. This raises the following question: how are "indirect" control-flows (`ret`, `jmp reg`, `jmp mem`, `call reg`, and `call mem`) represented in the LLVM bitcode?
|
||||
|
||||
The transfer of control for indirect control-flows are modelled using the following Remill [intrinsics](INTRINSICS.md). These instrinsics do not encode the mechanics of the control flows, however. For example, a function call instruction on x86 (`call`) modifies the stack and then jumps to the target. The [semantics functions](/remill/Arch/X86/Semantics/CALL_RET.cpp) are responsible for performing the stack manipulations of the call and modifying the instruction pointer. The intrinsics are responsible for the actual "transfer" of control to another lifted basic block.
|
||||
|
||||
- `jmp reg/mem` is represented as a tail-call to `__remill_jump`
|
||||
- `call reg/mem` is represented as a tail-call to `__remill_function_call`
|
||||
- `ret` is represented as a tail-call to `__remill_function_return`
|
||||
|
||||
Getting back to the `is_addressable` field. The idea here is that any basic block that *could* be targeted by an indirect control-flow should have its corresponding `Block` marked as `is_addressible`. To that end, the block following a `call` instruction is addressable because it is likely to be the target of a `ret` instruction. The block beginning an exported function is addressable because it is exposed to the outside world. The entry blocks associated with function pointers stored in [vtables](https://en.wikipedia.org/wiki/Virtual_method_table) in the `.data` section are addressable because they are likely to be the targets of indirect `call`s.
|
||||
|
||||
Finally, the `instructions` list is as you would expect: a list of `Instr` messages, each corresponding to a machine code instruction within the block.
|
||||
|
||||
## Named blocks
|
||||
|
||||
Named basic blocks are used to represent imported and exported functions. For example, an executable that imports libc and calls `printf` would have a named block, whose address would be the address of `sprintf`. The following message type is used to represent a named block:
|
||||
|
||||
```protobuf
|
||||
enum Visibility {
|
||||
EXPORTED = 0;
|
||||
IMPORTED = 1;
|
||||
}
|
||||
|
||||
message NamedBlock {
|
||||
required string name = 1;
|
||||
required uint64 address = 2;
|
||||
required Visibility visibility = 3;
|
||||
}
|
||||
```
|
||||
|
||||
Following along with the `sprintf` example, the `NamedBlock` associated with the entry point to `sprintf` would be `"sprintf"`. The `address` field is a bit more subtle than what was described above.
|
||||
|
||||
If `sprintf` is an imported function, then how can we know its address? In practice (at least in ELF binaries), there is a [thunk](https://en.wikipedia.org/wiki/Thunk) used to represent the address of `sprintf`. For example, below is the thunk for sprintf:
|
||||
|
||||

|
||||
|
||||
```assembly
|
||||
sprintf@plt:
|
||||
0x0000000000404b60 <+0>: jmp QWORD PTR [rip+0x63ba02] # 0xa40568
|
||||
0x0000000000404b66 <+6>: push 0xc
|
||||
0x0000000000404b6b <+11>: jmp 0x404a90
|
||||
```
|
||||
|
||||
So, in the `NamedBlock` message, the `address` of `sprintf` will be `0404b60`.
|
||||
|
||||
The `sprintf` function is imported, and so we will assign its `visibility` to be `IMPORTED`. Importantly, we don't want to have a `Block` that conflicts with an imported `NamedBlock`. That is, the CFG file *must not* contain a `Block` with the same address as a `NamedBlock` that is `IMPORTED`.
|
||||
|
||||
If we were lifting a shared library, and our shared library exported the function `foo`, then the `visibility` of `foo` would be `EXPORTED`. In this case, there *must be* a `Block` whose `address` matches that in the `NamedBlock`.
|
||||
|
||||
## Module
|
||||
|
||||
The `Module` message ties everything together. It includes all `Block`s and `NamedBlock`s:
|
||||
|
||||
```protobuf
|
||||
message Module {
|
||||
repeated Block blocks = 1;
|
||||
repeated NamedBlock named_blocks = 2;
|
||||
repeated uint64 referenced_blocks = 3;
|
||||
}
|
||||
```
|
||||
|
||||
It also includes `referenced_blocks`. The `Module` message is not required to, but can, contain all code within a binary. In fact, one can produce one `Module` message per function/subroutine found within the binary.
|
||||
|
||||
The `referenced_blocks` must be populated in the case where a `Module` does not include all blocks within the binary. For example, suppose our `Module` did not contain the code associated with `sub_804b89c` and `sub_8048a40`. In this case, the addresses `0804b89c` and `08048a40` must be added to the `referenced_blocks` list.
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
|
||||
# Design and architecture of Remill
|
||||
|
||||
Remill translates machine code, and *only* machine code, into LLVM bitcode. Remill's translation approach is inspired by [dynamic](https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool)
|
||||
[binary](https://github.com/DynamoRIO/dynamorio) [translators](https://github.com/Granary/granary2). Remill translates one [basic block](https://en.wikipedia.org/wiki/Basic_block) of machine code into LLVM bitcode at a time. The translation process defers many decisions to downstream consumers on how the translated bitcode should be interpreted.
|
||||
Remill translates machine code, and *only* machine code, into LLVM bitcode. The translation process defers many decisions to downstream consumers on how the translated bitcode should be interpreted.
|
||||
|
||||
## Intrinsics
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# What problem Remill solves
|
||||
|
||||
Remill is designed first and foremost for dynamic program analysis. The two motivating use cases are [taint tracking](https://en.wikipedia.org/wiki/Taint_checking), and [symbolic execution](https://en.wikipedia.org/wiki/Symbolic_execution).
|
||||
|
||||
|
||||
|
||||
Remill was designed with the following goals in mind.
|
||||
|
||||
- It should be easy to add new instruction implementations. Instruction semantics are implemented using C++. Instruction implementations should be thoroughly tested.
|
||||
|
||||
- Remill-produced bitcode should achieve the sometimes conflicting goals of maintaining the semantics of the translated machine code and enabling aggressive optimization of the produced bitcode.
|
||||
|
||||
- Decisions affecting the use of the produced bitcode should be deferred via intrinsics. Remill-produced bitcode should not commit a consumer of that bitcode to one use case.
|
||||
+19
-2
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gflags/gflags.h>
|
||||
@@ -10,7 +24,10 @@
|
||||
#include "remill/Arch/Name.h"
|
||||
#include "remill/OS/OS.h"
|
||||
|
||||
DECLARE_string(arch);
|
||||
DEFINE_string(arch, "", "Architecture of the code being translated. "
|
||||
"Valid architectures: x86, amd64 (with or without "
|
||||
"`_avx` or `_avx512` appended).");
|
||||
|
||||
DECLARE_string(os);
|
||||
|
||||
namespace remill {
|
||||
|
||||
+15
-1
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_ARCH_H_
|
||||
#define REMILL_ARCH_ARCH_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_INSTRUCTION_H_
|
||||
#define REMILL_ARCH_INSTRUCTION_H_
|
||||
|
||||
+15
-1
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "remill/Arch/Name.h"
|
||||
|
||||
|
||||
+15
-1
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_NAME_H_
|
||||
#define REMILL_ARCH_NAME_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_DEFINITIONS_H_
|
||||
#define REMILL_ARCH_RUNTIME_DEFINITIONS_H_
|
||||
@@ -34,7 +48,7 @@
|
||||
|
||||
// Define a specific instruction selection variable.
|
||||
#define DEF_ISEL(name) \
|
||||
extern "C" constexpr auto name [[gnu::used]]
|
||||
extern "C" constexpr auto ISEL_ ## name [[gnu::used]]
|
||||
|
||||
// Define a semantics implementing function.
|
||||
#define DEF_SEM(name, ...) \
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_HYPERCALL_H_
|
||||
#define REMILL_ARCH_RUNTIME_HYPERCALL_H_
|
||||
@@ -17,8 +31,6 @@ class SyncHyperCall {
|
||||
kAMD64EmulateInstruction,
|
||||
|
||||
kAssertPrivileged,
|
||||
|
||||
kDebugBreakpoint
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_SEMANTICS_INSTRINSICS_CPP_
|
||||
#define REMILL_ARCH_SEMANTICS_INSTRINSICS_CPP_
|
||||
@@ -49,7 +63,7 @@ extern "C" void __remill_intrinsics(void) {
|
||||
USED(__remill_atomic_begin);
|
||||
USED(__remill_atomic_end);
|
||||
|
||||
USED(__remill_defer_inlining);
|
||||
// USED(__remill_defer_inlining);
|
||||
|
||||
USED(__remill_error);
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_INTRINSICS_H_
|
||||
#define REMILL_ARCH_RUNTIME_INTRINSICS_H_
|
||||
@@ -74,11 +88,11 @@ extern float32_t __remill_undefined_f32(void);
|
||||
[[gnu::used, gnu::const]]
|
||||
extern float64_t __remill_undefined_f64(void);
|
||||
|
||||
// Inlining control. The idea here is that sometimes we want to defer inlining
|
||||
// until a later time, and we need to communicate what should eventually be
|
||||
// inlined, even if it's not currently inlined.
|
||||
[[gnu::used]]
|
||||
extern void __remill_defer_inlining(void);
|
||||
//// Inlining control. The idea here is that sometimes we want to defer inlining
|
||||
//// until a later time, and we need to communicate what should eventually be
|
||||
//// inlined, even if it's not currently inlined.
|
||||
//[[gnu::used]]
|
||||
//extern void __remill_defer_inlining(void);
|
||||
|
||||
// Generic error.
|
||||
[[gnu::used]]
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_OPERATORS_H_
|
||||
#define REMILL_ARCH_RUNTIME_OPERATORS_H_
|
||||
@@ -89,6 +103,18 @@ uint64_t _Read(Memory *, uint64_t val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
// Read a value directly.
|
||||
ALWAYS_INLINE static
|
||||
float32_t _Read(Memory *, float32_t val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
// Read a value directly.
|
||||
ALWAYS_INLINE static
|
||||
float64_t _Read(Memory *, float64_t val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ALWAYS_INLINE static
|
||||
T _Read(Memory *, In<T> imm) {
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_RUNTIME_H_
|
||||
#define REMILL_ARCH_RUNTIME_RUNTIME_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_STATE_H_
|
||||
#define REMILL_ARCH_RUNTIME_STATE_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_RUNTIME_TYPES_H_
|
||||
#define REMILL_ARCH_RUNTIME_TYPES_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
@@ -6,6 +20,8 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <llvm/IR/Attributes.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
|
||||
#undef HAS_FEATURE_AVX
|
||||
@@ -21,6 +37,7 @@
|
||||
#include "remill/Arch/X86/Arch.h"
|
||||
#include "remill/Arch/X86/XED.h"
|
||||
#include "remill/Arch/X86/Runtime/State.h"
|
||||
#include "remill/BC/Version.h"
|
||||
#include "remill/OS/OS.h"
|
||||
|
||||
namespace remill {
|
||||
@@ -299,7 +316,35 @@ static bool DecodeXED(xed_decoded_inst_t *xedd,
|
||||
static Operand::Register RegOp(xed_reg_enum_t reg) {
|
||||
Operand::Register reg_op;
|
||||
if (XED_REG_INVALID != reg) {
|
||||
reg_op.name = xed_reg_enum_t2str(reg);
|
||||
switch (reg) {
|
||||
case XED_REG_ST0:
|
||||
reg_op.name = "ST0";
|
||||
break;
|
||||
case XED_REG_ST1:
|
||||
reg_op.name = "ST1";
|
||||
break;
|
||||
case XED_REG_ST2:
|
||||
reg_op.name = "ST2";
|
||||
break;
|
||||
case XED_REG_ST3:
|
||||
reg_op.name = "ST3";
|
||||
break;
|
||||
case XED_REG_ST4:
|
||||
reg_op.name = "ST4";
|
||||
break;
|
||||
case XED_REG_ST5:
|
||||
reg_op.name = "ST5";
|
||||
break;
|
||||
case XED_REG_ST6:
|
||||
reg_op.name = "ST6";
|
||||
break;
|
||||
case XED_REG_ST7:
|
||||
reg_op.name = "ST7";
|
||||
break;
|
||||
default:
|
||||
reg_op.name = xed_reg_enum_t2str(reg);
|
||||
break;
|
||||
}
|
||||
if (XED_REG_X87_FIRST <= reg && XED_REG_X87_LAST >= reg) {
|
||||
reg_op.size = 64;
|
||||
} else {
|
||||
@@ -722,14 +767,24 @@ void X86Arch::PrepareModule(llvm::Module *mod) const {
|
||||
mod->setTargetTriple(triple);
|
||||
|
||||
// Go and remove compile-time attributes added into the semantics. These
|
||||
// can screw up later compilation.
|
||||
// can screw up later compilation. We purposefully compile semantics with
|
||||
// things like auto-vectorization disabled so that it keeps the bitcode
|
||||
// to a simpler subset of the available LLVM instruction set. If/when we
|
||||
// compile this bitcode back into machine code, we may want to use those
|
||||
// features, and clang will complain if we try to do so if these metadata
|
||||
// remain present.
|
||||
auto &context = mod->getContext();
|
||||
|
||||
llvm::AttributeSet target_attribs;
|
||||
target_attribs = target_attribs.addAttribute(
|
||||
context, llvm::AttributeSet::FunctionIndex, "target-features");
|
||||
target_attribs = target_attribs.addAttribute(
|
||||
context, llvm::AttributeSet::FunctionIndex, "target-cpu");
|
||||
|
||||
for (llvm::Function &func : *mod) {
|
||||
auto attribs = func.getAttributes();
|
||||
attribs = attribs.removeAttribute(
|
||||
context, llvm::AttributeSet::FunctionIndex, "target-features");
|
||||
attribs = attribs.removeAttribute(
|
||||
context, llvm::AttributeSet::FunctionIndex, "target-cpu");
|
||||
attribs = attribs.removeAttributes(
|
||||
context, llvm::AttributeSet::FunctionIndex, target_attribs);
|
||||
func.setAttributes(attribs);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_ARCH_H_
|
||||
#define REMILL_ARCH_X86_ARCH_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "remill/Arch/X86/Runtime/State.h"
|
||||
|
||||
|
||||
@@ -1,110 +1,39 @@
|
||||
# Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved.
|
||||
cmake_minimum_required (VERSION 3.2)
|
||||
project(x86_runtime BC)
|
||||
|
||||
macro(COMPILE_X86_SEMANTICS name address_size has_avx has_avx512)
|
||||
set(SEMANTICS_CXX_FLAGS
|
||||
set(X86RUNTIME_SOURCEFILES
|
||||
Instructions.cpp
|
||||
BasicBlock.cpp
|
||||
)
|
||||
|
||||
-I${PROJECT_SOURCE_DIR}
|
||||
-emit-llvm
|
||||
-DADDRESS_SIZE_BITS=${address_size}
|
||||
-DHAS_FEATURE_AVX=${has_avx}
|
||||
-DHAS_FEATURE_AVX512=${has_avx512}
|
||||
set_source_files_properties(Instructions.cpp PROPERTIES COMPILE_FLAGS "-O3 -g0")
|
||||
set_source_files_properties(BasicBlock.cpp PROPERTIES COMPILE_FLAGS "-O0 -g3")
|
||||
|
||||
-std=gnu++11
|
||||
|
||||
# TODO(pag): This should be what I do, but I've observed strange LLVM
|
||||
# code gen issues, where 32-bit code whose data layout is
|
||||
# converted to 64-bit code will sometimes miscompile pointers
|
||||
# as 32-bit. This is, of course, in bitcode that doesn't
|
||||
# do any ptrtoint or inttoptr casts! And this issue doesn't
|
||||
# show up when certain amounts of very aggressive
|
||||
# optimizations are performed to the file before converting
|
||||
# to 32-bit >:-(
|
||||
# -m${address_size}
|
||||
|
||||
-Wall
|
||||
-Werror
|
||||
-Wshadow
|
||||
-Wconversion
|
||||
-Wpadded
|
||||
-pedantic
|
||||
|
||||
-Wshorten-64-to-32
|
||||
-Wno-gnu-anonymous-struct
|
||||
-Wno-return-type-c-linkage
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
-Wno-nested-anon-types
|
||||
-Wno-extended-offsetof
|
||||
-Wno-gnu-statement-expression
|
||||
-Wno-c99-extensions
|
||||
-Wno-ignored-attributes
|
||||
set(X86RUNTIME_COMPILEOPTIONS
|
||||
-mno-sse
|
||||
-mno-avx
|
||||
-mno-3dnow
|
||||
)
|
||||
|
||||
# All of these are needed to disable vectorization, both in the LLVM
|
||||
# optimizer, and in the Clang front-end.
|
||||
-mtune=generic
|
||||
-mno-sse
|
||||
-mno-avx
|
||||
-mno-3dnow
|
||||
-fno-vectorize
|
||||
-fno-slp-vectorize
|
||||
|
||||
-ffreestanding
|
||||
-fno-common
|
||||
-fno-builtin
|
||||
-fno-exceptions
|
||||
-fno-rtti
|
||||
-fno-asynchronous-unwind-tables
|
||||
set(X86RUNTIME_INCLUDEDIRECTORIES ${CMAKE_SOURCE_DIR})
|
||||
|
||||
-Wno-unneeded-internal-declaration
|
||||
-Wno-unused-function
|
||||
)
|
||||
function (add_runtime_helper target_name address_bit_size enable_avx enable_avx512)
|
||||
message(" > Generating runtime target: ${target_name}")
|
||||
|
||||
add_custom_target(${name}.bc
|
||||
COMMAND ${CMAKE_LLVM_LINK}
|
||||
BasicBlock.${name}.bc
|
||||
Instructions.${name}.bc
|
||||
-o ${name}.bc
|
||||
DEPENDS BasicBlock.${name}.bc
|
||||
Instructions.${name}.bc
|
||||
)
|
||||
add_runtime(${target_name} SOURCES ${X86RUNTIME_SOURCEFILES} ADDRESS_SIZE ${address_bit_size})
|
||||
|
||||
# Note: `-O0 -g3` is significant here. We need to make sure that we can
|
||||
# recover variables names within `__remill_basic_block` that may have
|
||||
# been lost when the code was compiled.
|
||||
add_custom_command(
|
||||
OUTPUT BasicBlock.${name}.bc
|
||||
COMMAND ${CMAKE_CXX_COMPILER}
|
||||
${SEMANTICS_CXX_FLAGS}
|
||||
-O0 -g3
|
||||
-c ${CMAKE_CURRENT_SOURCE_DIR}/BasicBlock.cpp
|
||||
-o BasicBlock.${name}.bc
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/BasicBlock.cpp
|
||||
)
|
||||
|
||||
# Note: Some debug info *must* be preserved. This is so that we can have
|
||||
# debug info on lifted blocks that call these inlinable instruction
|
||||
# functions, without LLVM going and complaining about calling an
|
||||
# inlineable function with debug info.
|
||||
add_custom_command(
|
||||
OUTPUT Instructions.${name}.bc
|
||||
COMMAND ${CMAKE_CXX_COMPILER}
|
||||
${SEMANTICS_CXX_FLAGS}
|
||||
-O3 -g0
|
||||
-c ${CMAKE_CURRENT_SOURCE_DIR}/Instructions.cpp
|
||||
-o Instructions.${name}.bc
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Instructions.cpp
|
||||
)
|
||||
target_include_directories(${target_name} PRIVATE ${X86RUNTIME_INCLUDEDIRECTORIES})
|
||||
target_compile_options(${target_name} PRIVATE ${X86RUNTIME_COMPILEOPTIONS})
|
||||
target_compile_definitions(${target_name} PRIVATE "HAS_FEATURE_AVX=${enable_avx}")
|
||||
target_compile_definitions(${target_name} PRIVATE "HAS_FEATURE_AVX512=${enable_avx512}")
|
||||
endfunction ()
|
||||
|
||||
add_dependencies(semantics ${name}.bc)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.bc
|
||||
DESTINATION share/remill/semantics
|
||||
)
|
||||
add_runtime_helper(x86 32 0 0)
|
||||
add_runtime_helper(x86_avx 32 1 0)
|
||||
add_runtime_helper(x86_avx512 32 1 1)
|
||||
|
||||
endmacro()
|
||||
|
||||
COMPILE_X86_SEMANTICS(x86 32 0 0)
|
||||
COMPILE_X86_SEMANTICS(x86_avx 32 1 0)
|
||||
COMPILE_X86_SEMANTICS(x86_avx512 32 1 1)
|
||||
COMPILE_X86_SEMANTICS(amd64 64 0 0)
|
||||
COMPILE_X86_SEMANTICS(amd64_avx 64 1 0)
|
||||
COMPILE_X86_SEMANTICS(amd64_avx512 64 1 1)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_runtime_helper(amd64 64 0 0)
|
||||
add_runtime_helper(amd64_avx 64 1 0)
|
||||
add_runtime_helper(amd64_avx512 64 1 1)
|
||||
endif ()
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "remill/Arch/Runtime/Intrinsics.h"
|
||||
#include "remill/Arch/Runtime/Operators.h"
|
||||
@@ -130,17 +144,11 @@ DEF_SEM(HandleInvalidInstruction) {
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(HandleBreakpoint) {
|
||||
return __remill_sync_hyper_call(
|
||||
memory, state, SyncHyperCall::kDebugBreakpoint);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Takes the place of an unsupported instruction.
|
||||
DEF_ISEL(UNSUPPORTED_INSTRUCTION) = HandleUnsupported;
|
||||
DEF_ISEL(INVALID_INSTRUCTION) = HandleInvalidInstruction;
|
||||
DEF_ISEL(BREAKPOINT_INSTRUCTION) = HandleBreakpoint;
|
||||
|
||||
#include "remill/Arch/X86/Semantics/FLAGS.cpp"
|
||||
#include "remill/Arch/X86/Semantics/BINARY.cpp"
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_RUNTIME_OPERATORS_H_
|
||||
#define REMILL_ARCH_X86_RUNTIME_OPERATORS_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_RUNTIME_STATE_H_
|
||||
#define REMILL_ARCH_X86_RUNTIME_STATE_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_RUNTIME_TYPES_H_
|
||||
#define REMILL_ARCH_X86_RUNTIME_TYPES_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_BINARY_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_BINARY_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_CALL_RET_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_CALL_RET_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_CMOV_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_CMOV_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_CONVERT_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_CONVERT_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_DATAXFER_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_DATAXFER_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_FLAGOP_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_FLAGOP_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_FLAGS_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_FLAGS_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_FMA_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_FMA_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_INTERRUPT_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_INTERRUPT_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_LOGICAL_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_LOGICAL_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_MISC_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_MISC_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Akshay Kumar (iit.akshay@gmail.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_MMX_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_MMX_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_NOP_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_NOP_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_POP_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_POP_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_PUSH_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_PUSH_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_ROTATE_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_ROTATE_H_
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
DEF_SEM(XBEGIN, R8W cond, PC taken, PC not_taken) {
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_SHIFT_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_SHIFT_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_SSE_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_SSE_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_STRINGOP_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_STRINGOP_H_
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_X87_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_X87_H_
|
||||
@@ -45,107 +59,107 @@ DEF_SEM(FLD, RF80W, T src1) {
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDLN2, RF80W) {
|
||||
DEF_SEM(DoFLDLN2) {
|
||||
uint64_t ln_2 = 0x3fe62e42fefa39efULL;
|
||||
PUSH_X87_STACK(reinterpret_cast<float64_t &>(ln_2));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLD1, RF80W) {
|
||||
DEF_SEM(DoFLD1) {
|
||||
PUSH_X87_STACK(1.0); // +1.0.
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDZ, RF80W) {
|
||||
DEF_SEM(DoFLDZ) {
|
||||
PUSH_X87_STACK(0.0); // +0.0.
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDLG2, RF80W) {
|
||||
DEF_SEM(DoFLDLG2) {
|
||||
uint64_t log10_2 = 0x3fd34413509f79ffULL;
|
||||
PUSH_X87_STACK(reinterpret_cast<float64_t &>(log10_2));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDL2T, RF80W) {
|
||||
DEF_SEM(DoFLDL2T) {
|
||||
uint64_t log2_10 = 0x400a934f0979a371ULL;
|
||||
PUSH_X87_STACK(reinterpret_cast<float64_t &>(log2_10));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDL2E, RF80W) {
|
||||
DEF_SEM(DoFLDL2E) {
|
||||
uint64_t log2_e = 0x3ff71547652b82feULL;
|
||||
PUSH_X87_STACK(reinterpret_cast<float64_t &>(log2_e));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FLDPI, RF80W) {
|
||||
DEF_SEM(DoFLDPI) {
|
||||
uint64_t pi = 0x400921fb54442d18ULL;
|
||||
PUSH_X87_STACK(reinterpret_cast<float64_t &>(pi));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FABS, RF80W dst, RF80 src) {
|
||||
Write(dst, FAbs(Read(src)));
|
||||
DEF_SEM(DoFABS) {
|
||||
Write(X87_ST0, FAbs(Read(X87_ST0)));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FCHS, RF80W dst, RF80 src) {
|
||||
Write(dst, FNeg(Read(src)));
|
||||
DEF_SEM(DoFCHS) {
|
||||
Write(X87_ST0, FNeg(Read(X87_ST0)));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FCOS, RF80W dst, RF80 src) {
|
||||
Write(dst, __builtin_cos(Read(src)));
|
||||
DEF_SEM(DoFCOS) {
|
||||
Write(X87_ST0, __builtin_cos(Read(X87_ST0)));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FSIN, RF80W dst, RF80 src) {
|
||||
Write(dst, __builtin_sin(Read(src)));
|
||||
DEF_SEM(DoFSIN) {
|
||||
Write(X87_ST0, __builtin_sin(Read(X87_ST0)));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FPTAN, RF80W dst, RF80 src, RF80W) {
|
||||
Write(dst, __builtin_tan(Read(src)));
|
||||
DEF_SEM(DoFPTAN) {
|
||||
Write(X87_ST0, __builtin_tan(Read(X87_ST0)));
|
||||
PUSH_X87_STACK(1.0);
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FPATAN, RF80 st0, RF80W st1_dst, RF80 st1) {
|
||||
Write(st1_dst, __builtin_atan(FDiv(Read(st1), Read(st0))));
|
||||
DEF_SEM(DoFPATAN) {
|
||||
Write(X87_ST1, __builtin_atan(FDiv(Read(X87_ST1), Read(X87_ST0))));
|
||||
(void) POP_X87_STACK();
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FSQRT, RF80W dst, RF80 src) {
|
||||
Write(dst, __builtin_sqrt(Read(src)));
|
||||
DEF_SEM(DoFSQRT) {
|
||||
Write(X87_ST0, __builtin_sqrt(Read(X87_ST0)));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FSINCOS, RF80W dst, RF80 src, RF80W) {
|
||||
auto val = Read(src);
|
||||
Write(dst, __builtin_sin(val));
|
||||
DEF_SEM(DoFSINCOS) {
|
||||
auto val = Read(X87_ST0);
|
||||
Write(X87_ST0, __builtin_sin(val));
|
||||
PUSH_X87_STACK(__builtin_cos(val));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FSCALE, RF80W dst, RF80 st0, RF80 st1) {
|
||||
auto st1_int = __builtin_trunc(Read(st1)); // Round toward zero.
|
||||
DEF_SEM(DoFSCALE) {
|
||||
auto st1_int = __builtin_trunc(Read(X87_ST1)); // Round toward zero.
|
||||
auto shift = __builtin_exp2(st1_int);
|
||||
Write(dst, FMul(Read(st0), shift));
|
||||
Write(X87_ST0, FMul(Read(X87_ST0), shift));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(F2XM1, RF80W dst, RF80 src) {
|
||||
Write(dst, FSub(__builtin_exp2(Read(src)), 1.0));
|
||||
DEF_SEM(DoF2XM1) {
|
||||
Write(X87_ST0, FSub(__builtin_exp2(Read(X87_ST0)), 1.0));
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FPREM, RF80W dst, RF80 src1, RF80 src2) {
|
||||
float64_t st0 = Read(src1);
|
||||
float64_t st1 = Read(src2);
|
||||
DEF_SEM(DoFPREM) {
|
||||
float64_t st0 = Read(X87_ST0);
|
||||
float64_t st1 = Read(X87_ST1);
|
||||
auto rem = __builtin_fmod(st0, st1);
|
||||
Write(dst, rem);
|
||||
Write(X87_ST0, rem);
|
||||
|
||||
auto quot = Int64(FTruncTowardZero64(FDiv(st0, st1)));
|
||||
auto quot_lsb = TruncTo<uint8_t>(UInt64(SAbs(quot)));
|
||||
@@ -156,11 +170,11 @@ DEF_SEM(FPREM, RF80W dst, RF80 src1, RF80 src2) {
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FPREM1, RF80W dst, RF80 src1, RF80 src2) {
|
||||
float64_t st0 = Read(src1);
|
||||
float64_t st1 = Read(src2);
|
||||
DEF_SEM(DoFPREM1) {
|
||||
float64_t st0 = Read(X87_ST0);
|
||||
float64_t st1 = Read(X87_ST1);
|
||||
auto rem = __builtin_remainder(st0, st1);
|
||||
Write(dst, rem);
|
||||
Write(X87_ST0, rem);
|
||||
auto quot = Float64ToInt64(FDiv(st0, st1));
|
||||
auto quot_lsb = TruncTo<uint8_t>(UInt64(SAbs(quot)));
|
||||
state.sw.c0 = UAnd(UShr(quot_lsb, 2_u8), 1_u8); // Q2.
|
||||
@@ -196,29 +210,29 @@ DEF_ISEL(FLD_ST0_X87) = FLD<RF80>;
|
||||
DEF_ISEL(FLD_ST0_MEMm64real) = FLD<MF64>;
|
||||
DEF_ISEL(FLD_ST0_MEMmem80real) = FLD<MF80>;
|
||||
|
||||
DEF_ISEL(FLDLN2_ST0) = FLDLN2;
|
||||
DEF_ISEL(FLD1_ST0) = FLD1;
|
||||
DEF_ISEL(FLDZ_ST0) = FLDZ;
|
||||
DEF_ISEL(FLDLG2_ST0) = FLDLG2;
|
||||
DEF_ISEL(FLDL2T_ST0) = FLDL2T;
|
||||
DEF_ISEL(FLDL2E_ST0) = FLDL2E;
|
||||
DEF_ISEL(FLDPI_ST0) = FLDPI;
|
||||
DEF_ISEL(FLDLN2) = DoFLDLN2;
|
||||
DEF_ISEL(FLD1) = DoFLD1;
|
||||
DEF_ISEL(FLDZ) = DoFLDZ;
|
||||
DEF_ISEL(FLDLG2) = DoFLDLG2;
|
||||
DEF_ISEL(FLDL2T) = DoFLDL2T;
|
||||
DEF_ISEL(FLDL2E) = DoFLDL2E;
|
||||
DEF_ISEL(FLDPI) = DoFLDPI;
|
||||
|
||||
DEF_ISEL(FNOP) = FPU_NOP;
|
||||
DEF_ISEL(FWAIT) = DoFWAIT;
|
||||
DEF_ISEL(FNCLEX) = DoFNCLEX;
|
||||
DEF_ISEL(FABS_ST0) = FABS;
|
||||
DEF_ISEL(FCHS_ST0) = FCHS;
|
||||
DEF_ISEL(FCOS_ST0) = FCOS;
|
||||
DEF_ISEL(FSIN_ST0) = FSIN;
|
||||
DEF_ISEL(FPTAN_ST0_ST1) = FPTAN;
|
||||
DEF_ISEL(FPATAN_ST0_ST1) = FPATAN;
|
||||
DEF_ISEL(FSQRT_ST0) = FSQRT;
|
||||
DEF_ISEL(FSINCOS_ST0_ST1) = FSINCOS;
|
||||
DEF_ISEL(FSCALE_ST0_ST1) = FSCALE;
|
||||
DEF_ISEL(F2XM1_ST0) = F2XM1;
|
||||
DEF_ISEL(FPREM_ST0_ST1) = FPREM;
|
||||
DEF_ISEL(FPREM1_ST0_ST1) = FPREM1;
|
||||
DEF_ISEL(FABS) = DoFABS;
|
||||
DEF_ISEL(FCHS) = DoFCHS;
|
||||
DEF_ISEL(FCOS) = DoFCOS;
|
||||
DEF_ISEL(FSIN) = DoFSIN;
|
||||
DEF_ISEL(FPTAN) = DoFPTAN;
|
||||
DEF_ISEL(FPATAN) = DoFPATAN;
|
||||
DEF_ISEL(FSQRT) = DoFSQRT;
|
||||
DEF_ISEL(FSINCOS) = DoFSINCOS;
|
||||
DEF_ISEL(FSCALE) = DoFSCALE;
|
||||
DEF_ISEL(F2XM1) = DoF2XM1;
|
||||
DEF_ISEL(FPREM) = DoFPREM;
|
||||
DEF_ISEL(FPREM1) = DoFPREM1;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -520,8 +534,8 @@ DEF_ISEL(FXCH_ST0_X87_DDC1) = FXCH;
|
||||
|
||||
namespace {
|
||||
|
||||
DEF_SEM(FXAM, RF80W, RF80 src) {
|
||||
auto st0 = Read(src);
|
||||
DEF_SEM(DoFXAM) {
|
||||
auto st0 = Read(X87_ST0);
|
||||
|
||||
uint8_t sign = __builtin_signbit(st0) == 0 ? 0_u8 : 1_u8;
|
||||
auto c = __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
|
||||
@@ -596,8 +610,8 @@ DEF_HELPER(UnorderedCompare, float64_t src1, float64_t src2) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_SEM(FTST, RF80W, RF80 src1) {
|
||||
auto st0 = Read(src1);
|
||||
DEF_SEM(DoFTST) {
|
||||
auto st0 = Read(X87_ST0);
|
||||
state.sw.c1 = 0;
|
||||
UnorderedCompare(memory, state, st0, 0.0);
|
||||
return memory;
|
||||
@@ -620,8 +634,10 @@ DEF_SEM(FUCOMP, RF80 src1, S2 src2) {
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FUCOMPP, RF80 src1, RF80 src2) {
|
||||
memory = FUCOM<RF80>(memory, state, src1, src2);
|
||||
DEF_SEM(DoFUCOMPP) {
|
||||
RF80 st0 = {X87_ST0};
|
||||
RF80 st1 = {X87_ST1};
|
||||
memory = FUCOM<RF80>(memory, state, st0, st1);
|
||||
(void) POP_X87_STACK();
|
||||
(void) POP_X87_STACK();
|
||||
return memory;
|
||||
@@ -668,12 +684,12 @@ DEF_SEM(FUCOMIP, RF80 src1, RF80 src2) {
|
||||
|
||||
} // namespace
|
||||
|
||||
DEF_ISEL(FXAM_ST0) = FXAM;
|
||||
DEF_ISEL(FTST_ST0) = FTST;
|
||||
DEF_ISEL(FXAM) = DoFXAM;
|
||||
DEF_ISEL(FTST) = DoFTST;
|
||||
|
||||
DEF_ISEL(FUCOM_ST0_X87) = FUCOM<RF80>;
|
||||
DEF_ISEL(FUCOMP_ST0_X87) = FUCOMP<RF80>;
|
||||
DEF_ISEL(FUCOMPP_ST0_ST1) = FUCOMPP;
|
||||
DEF_ISEL(FUCOMPP) = DoFUCOMPP;
|
||||
|
||||
DEF_ISEL(FUCOMI_ST0_X87) = FUCOMI;
|
||||
DEF_ISEL(FUCOMIP_ST0_X87) = FUCOMIP;
|
||||
@@ -691,7 +707,7 @@ DEF_ISEL(FCOMP_ST0_MEMmem32real) = FUCOMP<MF32>;
|
||||
DEF_ISEL(FCOMP_ST0_MEMm64real) = FUCOMP<MF64>;
|
||||
DEF_ISEL(FCOMP_ST0_X87_DCD1) = FUCOMP<RF80>;
|
||||
DEF_ISEL(FCOMP_ST0_X87_DED0) = FUCOMP<RF80>;
|
||||
DEF_ISEL(FCOMPP_ST0_ST1) = FUCOMPP;
|
||||
DEF_ISEL(FCOMPP) = DoFUCOMPP;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -762,26 +778,26 @@ DEF_ISEL(FLDCW_MEMmem16) = FLDCW;
|
||||
|
||||
namespace {
|
||||
|
||||
DEF_SEM(FRNDINT, RF80W dst, RF80 src) {
|
||||
auto st0 = Read(src);
|
||||
DEF_SEM(DoFRNDINT) {
|
||||
auto st0 = Read(X87_ST0);
|
||||
auto rounded = FRoundUsingMode64(st0);
|
||||
// state.sw.c1 = __builtin_isgreater(FAbs(rounded), FAbs(st0)) ? 1_u8 : 0_u8;
|
||||
Write(dst, rounded);
|
||||
Write(X87_ST0, rounded);
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FYL2X, RF80 src1, RF80W dst2, RF80 src2) {
|
||||
auto st0 = Read(src1);
|
||||
auto st1 = Read(src2);
|
||||
Write(dst2, FMul(st1, __builtin_log2(st0)));
|
||||
DEF_SEM(DoFYL2X) {
|
||||
auto st0 = Read(X87_ST0);
|
||||
auto st1 = Read(X87_ST1);
|
||||
Write(X87_ST1, FMul(st1, __builtin_log2(st0)));
|
||||
(void) POP_X87_STACK();
|
||||
return memory;
|
||||
}
|
||||
|
||||
DEF_SEM(FYL2XP1, RF80 src1, RF80W dst2, RF80 src2) {
|
||||
auto st0 = Read(src1);
|
||||
auto st1 = Read(src2);
|
||||
Write(dst2, FMul(st1, __builtin_log2(FAdd(st0, 1.0))));
|
||||
DEF_SEM(DoFYL2XP1) {
|
||||
auto st0 = Read(X87_ST0);
|
||||
auto st1 = Read(X87_ST1);
|
||||
Write(X87_ST1, FMul(st1, __builtin_log2(FAdd(st0, 1.0))));
|
||||
(void) POP_X87_STACK();
|
||||
return memory;
|
||||
}
|
||||
@@ -797,9 +813,9 @@ DEF_SEM(FFREEP, RF80) {
|
||||
|
||||
} // namespace
|
||||
|
||||
DEF_ISEL(FRNDINT_ST0) = FRNDINT;
|
||||
DEF_ISEL(FYL2X_ST0_ST1) = FYL2X;
|
||||
DEF_ISEL(FYL2XP1_ST0_ST1) = FYL2XP1;
|
||||
DEF_ISEL(FRNDINT) = DoFRNDINT;
|
||||
DEF_ISEL(FYL2X) = DoFYL2X;
|
||||
DEF_ISEL(FYL2XP1) = DoFYL2XP1;
|
||||
|
||||
DEF_ISEL(FFREE_X87) = FFREE;
|
||||
DEF_ISEL(FFREEP_X87) = FFREEP;
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_SEMANTICS_XOP_H_
|
||||
#define REMILL_ARCH_X86_SEMANTICS_XOP_H_
|
||||
|
||||
+16
-2
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_ARCH_X86_XED_H_
|
||||
#define REMILL_ARCH_X86_XED_H_
|
||||
@@ -11,7 +25,7 @@
|
||||
#pragma clang diagnostic ignored "-Wswitch-enum"
|
||||
extern "C" {
|
||||
#define XED_DLL
|
||||
#include <intel/xed-interface.h>
|
||||
#include <xed/xed-interface.h>
|
||||
} // extern C
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
|
||||
+15
-1
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_ABI_H_
|
||||
#define REMILL_BC_ABI_H_
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_BITCODEREADERWRITER_H_
|
||||
#define REMILL_BC_COMPAT_BITCODEREADERWRITER_H_
|
||||
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#if LLVM_VERSION_NUMBER >= LLVM_VERSION(4, 0)
|
||||
# include <llvm/Bitcode/BitcodeReader.h>
|
||||
# include <llvm/Bitcode/BitcodeWriter.h>
|
||||
#else
|
||||
# include <llvm/Bitcode/ReaderWriter.h>
|
||||
#endif
|
||||
|
||||
#endif // REMILL_BC_COMPAT_BITCODEREADERWRITER_H_
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_DEBUGINFO_H_
|
||||
#define REMILL_BC_COMPAT_DEBUGINFO_H_
|
||||
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#if LLVM_VERSION_NUMBER >= LLVM_VERSION(3, 7)
|
||||
# include <llvm/IR/DebugInfoMetadata.h>
|
||||
#else
|
||||
# include <llvm/IR/DebugInfo.h>
|
||||
#endif
|
||||
|
||||
#include <llvm/IR/DebugLoc.h>
|
||||
|
||||
#endif // REMILL_BC_COMPAT_DEBUGINFO_H_
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_GLOBALVALUE_H_
|
||||
#define REMILL_BC_COMPAT_GLOBALVALUE_H_
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#include <llvm/IR/GlobalValue.h>
|
||||
|
||||
namespace remill {
|
||||
|
||||
inline static llvm::Type *GetValueType(llvm::GlobalValue *global) {
|
||||
#if LLVM_VERSION_NUMBER < LLVM_VERSION(3, 7)
|
||||
return global->getType()->getElementType();
|
||||
#else
|
||||
return global->getValueType();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace remill
|
||||
|
||||
#endif // REMILL_BC_COMPAT_GLOBALVALUE_H_
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_IRREADER_H_
|
||||
#define REMILL_BC_COMPAT_IRREADER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#include <llvm/IRReader/IRReader.h>
|
||||
|
||||
#if LLVM_VERSION_NUMBER < LLVM_VERSION(3, 6)
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
|
||||
template <typename ...Args>
|
||||
inline static std::unique_ptr<Module> parseIRFile(Args&... args) {
|
||||
return std::unique_ptr<Module>(ParseIRFile(args...));
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
#endif // REMILL_BC_COMPAT_IRREADER_H_
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_TARGETLIBRARYINFO_H_
|
||||
#define REMILL_BC_COMPAT_TARGETLIBRARYINFO_H_
|
||||
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#if LLVM_VERSION_NUMBER >= LLVM_VERSION(3, 7)
|
||||
# include <llvm/Analysis/TargetLibraryInfo.h>
|
||||
#else
|
||||
# include <llvm/Target/TargetLibraryInfo.h>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
using TargetLibraryInfoImpl = TargetLibraryInfo;
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
#endif // REMILL_BC_COMPAT_TARGETLIBRARYINFO_H_
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_COMPAT_VERIFIER_H_
|
||||
#define REMILL_BC_COMPAT_VERIFIER_H_
|
||||
|
||||
#include "remill/BC/Version.h"
|
||||
|
||||
#if LLVM_VERSION_NUMBER >= LLVM_VERSION(3, 5)
|
||||
# include <llvm/IR/Verifier.h>
|
||||
#else
|
||||
# include <llvm/Analysis/Verifier.h>
|
||||
#endif
|
||||
|
||||
#endif // REMILL_BC_COMPAT_VERIFIER_H_
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
@@ -16,7 +30,7 @@ namespace remill {
|
||||
namespace {
|
||||
|
||||
// Find a specific function.
|
||||
static llvm::Function *FindIntrinsic(const llvm::Module *module,
|
||||
static llvm::Function *FindIntrinsic(llvm::Module *module,
|
||||
const char *name) {
|
||||
auto function = FindFunction(module, name);
|
||||
CHECK(nullptr != function)
|
||||
@@ -39,7 +53,7 @@ static llvm::Function *FindIntrinsic(const llvm::Module *module,
|
||||
}
|
||||
|
||||
// Find a specific function.
|
||||
static llvm::Function *FindPureIntrinsic(const llvm::Module *module,
|
||||
static llvm::Function *FindPureIntrinsic(llvm::Module *module,
|
||||
const char *name) {
|
||||
auto function = FindIntrinsic(module, name);
|
||||
|
||||
@@ -49,28 +63,20 @@ static llvm::Function *FindPureIntrinsic(const llvm::Module *module,
|
||||
return function;
|
||||
}
|
||||
|
||||
// Find a specific function.
|
||||
static llvm::Function *FindArgMemOnlyIntrinsic(const llvm::Module *module,
|
||||
const char *name) {
|
||||
auto function = FindIntrinsic(module, name);
|
||||
function->addFnAttr(llvm::Attribute::ArgMemOnly);
|
||||
return function;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
IntrinsicTable::IntrinsicTable(const llvm::Module *module)
|
||||
IntrinsicTable::IntrinsicTable(llvm::Module *module)
|
||||
: error(FindIntrinsic(module, "__remill_error")),
|
||||
|
||||
// Control-flow.
|
||||
function_call(FindArgMemOnlyIntrinsic(module, "__remill_function_call")),
|
||||
function_return(FindArgMemOnlyIntrinsic(
|
||||
function_call(FindIntrinsic(module, "__remill_function_call")),
|
||||
function_return(FindIntrinsic(
|
||||
module, "__remill_function_return")),
|
||||
jump(FindArgMemOnlyIntrinsic(module, "__remill_jump")),
|
||||
missing_block(FindArgMemOnlyIntrinsic(module, "__remill_missing_block")),
|
||||
jump(FindIntrinsic(module, "__remill_jump")),
|
||||
missing_block(FindIntrinsic(module, "__remill_missing_block")),
|
||||
|
||||
// OS interaction.
|
||||
async_hyper_call(FindArgMemOnlyIntrinsic(
|
||||
async_hyper_call(FindIntrinsic(
|
||||
module, "__remill_async_hyper_call")),
|
||||
|
||||
// Memory access.
|
||||
@@ -105,11 +111,11 @@ IntrinsicTable::IntrinsicTable(const llvm::Module *module)
|
||||
atomic_begin(FindPureIntrinsic(module, "__remill_atomic_begin")),
|
||||
atomic_end(FindPureIntrinsic(module, "__remill_atomic_end")),
|
||||
|
||||
// Optimization guides.
|
||||
//
|
||||
// Note: NOT pure! This is a total hack: we call an unpure function
|
||||
// within a pure one so that it is not optimized out!
|
||||
defer_inlining(FindIntrinsic(module, "__remill_defer_inlining")),
|
||||
// // Optimization guides.
|
||||
// //
|
||||
// // Note: NOT pure! This is a total hack: we call an unpure function
|
||||
// // within a pure one so that it is not optimized out!
|
||||
// defer_inlining(FindIntrinsic(module, "__remill_defer_inlining")),
|
||||
|
||||
// Optimization enablers.
|
||||
undefined_8(FindPureIntrinsic(module, "__remill_undefined_8")),
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_INTRINSICTABLE_H_
|
||||
#define REMILL_BC_INTRINSICTABLE_H_
|
||||
@@ -13,7 +27,7 @@ namespace remill {
|
||||
|
||||
class IntrinsicTable {
|
||||
public:
|
||||
IntrinsicTable(const llvm::Module *M);
|
||||
IntrinsicTable(llvm::Module *M);
|
||||
|
||||
llvm::Function * const error;
|
||||
|
||||
@@ -55,8 +69,8 @@ class IntrinsicTable {
|
||||
llvm::Function * const atomic_begin;
|
||||
llvm::Function * const atomic_end;
|
||||
|
||||
// Optimization control.
|
||||
llvm::Function * const defer_inlining;
|
||||
// // Optimization control.
|
||||
// llvm::Function * const defer_inlining;
|
||||
|
||||
// Optimization enabling.
|
||||
llvm::Function *undefined_8;
|
||||
|
||||
+40
-380
@@ -1,6 +1,19 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <functional>
|
||||
@@ -17,7 +30,6 @@
|
||||
#include <llvm/IR/BasicBlock.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/DataLayout.h>
|
||||
#include <llvm/IR/DebugInfoMetadata.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
@@ -26,7 +38,6 @@
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/LegacyPassManager.h>
|
||||
#include <llvm/IR/Type.h>
|
||||
#include <llvm/IR/Verifier.h>
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
@@ -35,375 +46,26 @@
|
||||
#include <llvm/Transforms/Utils/ValueMapper.h>
|
||||
|
||||
#include "remill/Arch/Arch.h"
|
||||
#include "remill/Arch/Instruction.h"
|
||||
|
||||
#include "remill/BC/ABI.h"
|
||||
#include "remill/BC/IntrinsicTable.h"
|
||||
#include "remill/BC/Lifter.h"
|
||||
#include "remill/BC/Util.h"
|
||||
#include "remill/CFG/BlockHasher.h"
|
||||
#include "remill/CFG/CFG.h"
|
||||
|
||||
#include "remill/OS/OS.h"
|
||||
|
||||
DEFINE_bool(add_breakpoints, false,
|
||||
"Add calls to the `BREAKPOINT_INSTRUCTION` before every lifted "
|
||||
"instruction. The semantics for this instruction call into a "
|
||||
"breakpoint hyper call.");
|
||||
|
||||
namespace remill {
|
||||
|
||||
|
||||
Lifter::Lifter(const Arch *arch_, llvm::Module *module_)
|
||||
: arch(arch_),
|
||||
module(module_),
|
||||
pc_to_block(),
|
||||
basic_block(FindFunction(module, "__remill_basic_block")),
|
||||
word_type(llvm::Type::getIntNTy(
|
||||
module->getContext(), arch->address_size)),
|
||||
intrinsics(new IntrinsicTable(module)) {
|
||||
|
||||
CHECK(nullptr != basic_block)
|
||||
<< "Unable to find __remill_basic_block.";
|
||||
|
||||
CHECK(1 == basic_block->size())
|
||||
<< "Basic block template function " << basic_block->getName().str()
|
||||
<< " should only have one basic block.";
|
||||
|
||||
EnableDeferredInlining();
|
||||
}
|
||||
|
||||
Lifter::~Lifter(void) {
|
||||
delete intrinsics;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Make sure that a function cannot be inlined by the optimizer. We use this
|
||||
// as a way of ensuring that code that should be inlined later (i.e. invokes
|
||||
// `__remill_defer_inlining`) definitely have the no-inline attributes set.
|
||||
static void DisableInlining(llvm::Function *function) {
|
||||
function->removeFnAttr(llvm::Attribute::AlwaysInline);
|
||||
function->removeFnAttr(llvm::Attribute::InlineHint);
|
||||
function->addFnAttr(llvm::Attribute::NoInline);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Enable deferred inlining. The goal is to support better dead-store
|
||||
// elimination for flags.
|
||||
void Lifter::EnableDeferredInlining(void) {
|
||||
DisableInlining(intrinsics->defer_inlining);
|
||||
|
||||
for (auto callers : intrinsics->defer_inlining->users()) {
|
||||
if (auto call_instr = llvm::dyn_cast_or_null<llvm::CallInst>(callers)) {
|
||||
auto bb = call_instr->getParent();
|
||||
auto caller = bb->getParent();
|
||||
DisableInlining(caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static uint64_t GetBlockId(const cfg::Block &cfg_block) {
|
||||
if (cfg_block.has_id()) {
|
||||
return cfg_block.id();
|
||||
} else {
|
||||
return BlockHasher().HashBlock(cfg_block);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Create a function for a single decoded block.
|
||||
void Lifter::CreateBlock(const cfg::Block &cfg_block) {
|
||||
auto id = GetBlockId(cfg_block);
|
||||
auto pc = cfg_block.address();
|
||||
|
||||
auto id_it = id_to_block.find(id);
|
||||
if (id_it != id_to_block.end()) {
|
||||
pc_to_block[pc] = id_it->second;
|
||||
}
|
||||
|
||||
auto &block_func = pc_to_block[pc];
|
||||
if (!block_func) {
|
||||
std::stringstream ss;
|
||||
ss << "__remill_sub_" << std::hex << id;
|
||||
auto func_name = ss.str();
|
||||
auto func_type = basic_block->getFunctionType();
|
||||
|
||||
block_func = llvm::Function::Create(
|
||||
func_type, llvm::GlobalValue::PrivateLinkage, ".", module);
|
||||
|
||||
auto block_var = new llvm::GlobalVariable(
|
||||
*module, llvm::PointerType::get(func_type, 0), true,
|
||||
llvm::GlobalValue::ExternalLinkage, block_func, func_name);
|
||||
|
||||
CHECK(block_var->getName() == func_name)
|
||||
<< "Duplicate block for " << func_name;
|
||||
|
||||
InitFunctionAttributes(block_func);
|
||||
SetBlockPC(block_var, pc);
|
||||
SetBlockId(block_var, id);
|
||||
|
||||
id_to_block[id] = block_func;
|
||||
|
||||
if (cfg_block.has_name()) {
|
||||
DLOG(INFO)
|
||||
<< "Block at " << std::hex << pc << " has name " << cfg_block.name();
|
||||
SetBlockName(block_func, cfg_block.name());
|
||||
}
|
||||
|
||||
} else {
|
||||
uint64_t other_id = 0;
|
||||
if (!TryGetBlockId(block_func, other_id) || other_id != id) {
|
||||
DLOG(FATAL)
|
||||
<< "Duplicate cfg_block at PC " << std::hex << pc << " exists in "
|
||||
<< "the CFG proto. There should only be one version of each block "
|
||||
<< "in a given CFG Module.";
|
||||
} else {
|
||||
DLOG(ERROR)
|
||||
<< "Duplicate cfg_block at PC " << std::hex << pc << " exists in "
|
||||
<< "the CFG Module, but they both have the same ID.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a function for a single block.
|
||||
llvm::Function *Lifter::GetBlock(uint64_t addr) {
|
||||
auto &block_func = pc_to_block[addr];
|
||||
if (!block_func) {
|
||||
LOG(WARNING)
|
||||
<< "Unable find block for PC " << std::hex << addr
|
||||
<< " reverting to `__remill_missing_block`.";
|
||||
block_func = intrinsics->missing_block;
|
||||
}
|
||||
return block_func;
|
||||
}
|
||||
|
||||
// Lift the control-flow graph specified by `cfg` into this bitcode module.
|
||||
void Lifter::LiftCFG(const cfg::Module *cfg_module) {
|
||||
ForEachBlock(module,
|
||||
[this] (uint64_t pc, uint64_t id, llvm::Function *func) {
|
||||
id_to_block[id] = func;
|
||||
});
|
||||
|
||||
for (auto &cfg_block : cfg_module->blocks()) {
|
||||
CreateBlock(cfg_block);
|
||||
}
|
||||
|
||||
LiftBlocks(cfg_module);
|
||||
|
||||
pc_to_block.clear();
|
||||
id_to_block.clear();
|
||||
}
|
||||
|
||||
// Lift code contained in blocks into the block methods.
|
||||
void Lifter::LiftBlocks(const cfg::Module *cfg_module) {
|
||||
llvm::legacy::FunctionPassManager func_pass_manager(module);
|
||||
func_pass_manager.add(llvm::createCFGSimplificationPass());
|
||||
func_pass_manager.add(llvm::createPromoteMemoryToRegisterPass());
|
||||
func_pass_manager.add(llvm::createReassociatePass());
|
||||
func_pass_manager.add(llvm::createDeadStoreEliminationPass());
|
||||
func_pass_manager.add(llvm::createDeadCodeEliminationPass());
|
||||
|
||||
func_pass_manager.doInitialization();
|
||||
for (const auto &cfg_block : cfg_module->blocks()) {
|
||||
auto func = LiftBlock(cfg_block);
|
||||
CHECK(!func->isDeclaration())
|
||||
<< "Lifted block function " << func->getName().str()
|
||||
<< " should have an implementation.";
|
||||
|
||||
func_pass_manager.run(*func);
|
||||
}
|
||||
|
||||
func_pass_manager.doFinalization();
|
||||
}
|
||||
|
||||
// Lift code contained within a single block.
|
||||
llvm::Function *Lifter::LiftBlock(const cfg::Block &cfg_block) {
|
||||
auto block_func = GetBlock(cfg_block.address());
|
||||
if (!block_func->isDeclaration()) {
|
||||
return block_func;
|
||||
}
|
||||
|
||||
CloneBlockFunctionInto(block_func);
|
||||
|
||||
InstructionLifter lifter(word_type, intrinsics);
|
||||
|
||||
// Create a block for each instruction.
|
||||
auto last_block = &block_func->back();
|
||||
auto instr_addr = cfg_block.address();
|
||||
Instruction *instr = nullptr;
|
||||
for (const auto &cfg_instr : cfg_block.instructions()) {
|
||||
CHECK(cfg_instr.address() == instr_addr)
|
||||
<< "CFG Instr address " << std::hex << cfg_instr.address()
|
||||
<< " doesn't match implied instruction address ("
|
||||
<< std::hex << instr_addr << ") based on CFG Block structure.";
|
||||
|
||||
auto instr_bytes = cfg_instr.bytes();
|
||||
|
||||
// Check and delete the last instruction lifted.
|
||||
if (instr) {
|
||||
CHECK(Instruction::kCategoryNoOp == instr->category ||
|
||||
Instruction::kCategoryNormal == instr->category)
|
||||
<< "Predecessor of instruction at " << std::hex << instr_addr
|
||||
<< " must be a normal or no-op instruction, and not one that"
|
||||
<< " should end a block.";
|
||||
|
||||
delete instr;
|
||||
instr = nullptr;
|
||||
}
|
||||
|
||||
instr = arch->DecodeInstruction(instr_addr, instr_bytes);
|
||||
DLOG_IF(WARNING, instr_bytes.size() != instr->NumBytes())
|
||||
<< "Size of decoded instruction at " << std::hex << instr_addr
|
||||
<< " (" << std::dec << instr->NumBytes()
|
||||
<< ") doesn't match input instruction size ("
|
||||
<< instr_bytes.size() << ").";
|
||||
|
||||
// DLOG(INFO)
|
||||
// << "Lifting instruction '" << instr->Serialize();
|
||||
|
||||
if (auto curr_block = LiftInstruction(block_func, instr, lifter)) {
|
||||
llvm::IRBuilder<> ir(last_block);
|
||||
ir.CreateBr(curr_block);
|
||||
last_block = curr_block;
|
||||
instr_addr += instr_bytes.size();
|
||||
|
||||
// Unable to lift the instruction; likely because the instruction
|
||||
// semantics are not implemented.
|
||||
} else {
|
||||
AddTerminatingTailCall(last_block, intrinsics->error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(nullptr != instr)
|
||||
<< "Logic error: must lift at least one instruction.";
|
||||
|
||||
if (!last_block->getTerminator()) {
|
||||
LiftTerminator(last_block, instr);
|
||||
}
|
||||
|
||||
delete instr;
|
||||
return block_func;
|
||||
}
|
||||
|
||||
// Lift a single instruction into a basic block.
|
||||
llvm::BasicBlock *Lifter::LiftInstruction(llvm::Function *block_func,
|
||||
Instruction *instr,
|
||||
InstructionLifter &lifter) {
|
||||
auto &context = block_func->getContext();
|
||||
auto block = llvm::BasicBlock::Create(context, "", block_func);
|
||||
if (!lifter.LiftIntoBlock(instr, block)) {
|
||||
block->eraseFromParent();
|
||||
return nullptr;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Lift both targets of a conditional branch into a branch in the bitcode,
|
||||
// where each side of the branch tail-calls to the functions associated with
|
||||
// the lifted blocks for those branch targets.
|
||||
static void LiftConditionalBranch(llvm::BasicBlock *source,
|
||||
llvm::Function *dest_true,
|
||||
llvm::Function *dest_false) {
|
||||
auto &context = source->getContext();
|
||||
auto function = source->getParent();
|
||||
auto block_true = llvm::BasicBlock::Create(context, "", function);
|
||||
auto block_false = llvm::BasicBlock::Create(context, "", function);
|
||||
|
||||
// TODO(pag): This is a bit ugly. The idea here is that, from the semantics
|
||||
// code, we need a way to communicate what direction of the
|
||||
// conditional branch should be followed. It turns out to be
|
||||
// easiest just to write to a special variable :-)
|
||||
auto branch_taken = FindVarInFunction(function, "BRANCH_TAKEN");
|
||||
|
||||
llvm::IRBuilder<> cond_ir(source);
|
||||
auto cond_addr = cond_ir.CreateLoad(branch_taken);
|
||||
auto cond = cond_ir.CreateLoad(cond_addr);
|
||||
cond_ir.CreateCondBr(
|
||||
cond_ir.CreateICmpEQ(
|
||||
cond,
|
||||
llvm::ConstantInt::get(cond->getType(), 1)),
|
||||
block_true,
|
||||
block_false);
|
||||
|
||||
AddTerminatingTailCall(block_true, dest_true);
|
||||
AddTerminatingTailCall(block_false, dest_false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Lift the last instruction of a block as a block terminator.
|
||||
void Lifter::LiftTerminator(llvm::BasicBlock *block,
|
||||
const Instruction *arch_instr) {
|
||||
switch (arch_instr->category) {
|
||||
case Instruction::kCategoryInvalid:
|
||||
AddTerminatingTailCall(block, intrinsics->async_hyper_call);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryNormal:
|
||||
case Instruction::kCategoryNoOp:
|
||||
AddTerminatingTailCall(
|
||||
block,
|
||||
GetBlock(arch_instr->next_pc));
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryError:
|
||||
AddTerminatingTailCall(block, intrinsics->error);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryDirectJump:
|
||||
AddTerminatingTailCall(
|
||||
block,
|
||||
GetBlock(arch_instr->branch_taken_pc));
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryIndirectJump:
|
||||
AddTerminatingTailCall(block, intrinsics->jump);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryDirectFunctionCall:
|
||||
AddTerminatingTailCall(
|
||||
block,
|
||||
GetBlock(arch_instr->branch_taken_pc));
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryIndirectFunctionCall:
|
||||
AddTerminatingTailCall(block, intrinsics->function_call);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryFunctionReturn:
|
||||
AddTerminatingTailCall(block, intrinsics->function_return);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryConditionalBranch:
|
||||
LiftConditionalBranch(
|
||||
block,
|
||||
GetBlock(arch_instr->branch_taken_pc),
|
||||
GetBlock(arch_instr->branch_not_taken_pc));
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryAsyncHyperCall:
|
||||
AddTerminatingTailCall(block, intrinsics->async_hyper_call);
|
||||
break;
|
||||
|
||||
case Instruction::kCategoryConditionalAsyncHyperCall:
|
||||
LiftConditionalBranch(
|
||||
block,
|
||||
intrinsics->async_hyper_call,
|
||||
GetBlock(arch_instr->next_pc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Try to find the function that implements this semantics.
|
||||
llvm::Function *GetInstructionFunction(llvm::Module *module,
|
||||
const std::string &function) {
|
||||
auto isel = FindGlobaVariable(module, function);
|
||||
std::stringstream ss;
|
||||
ss << "ISEL_" << function;
|
||||
auto isel_name = ss.str();
|
||||
|
||||
auto isel = FindGlobaVariable(module, isel_name);
|
||||
if (!isel) {
|
||||
return nullptr; // Falls back on `UNIMPLEMENTED_INSTRUCTION`.
|
||||
}
|
||||
@@ -429,14 +91,17 @@ InstructionLifter::InstructionLifter(llvm::IntegerType *word_type_,
|
||||
intrinsics(intrinsics_) {}
|
||||
|
||||
// Lift a single instruction into a basic block.
|
||||
bool InstructionLifter::LiftIntoBlock(
|
||||
LiftStatus InstructionLifter::LiftIntoBlock(
|
||||
Instruction *arch_instr, llvm::BasicBlock *block) {
|
||||
|
||||
auto module = block->getModule();
|
||||
llvm::Function *func = block->getParent();
|
||||
llvm::Module *module = func->getParent();
|
||||
auto isel_func = GetInstructionFunction(module, arch_instr->function);
|
||||
auto status = LiftStatus::kLifted;
|
||||
|
||||
if (Instruction::kCategoryInvalid == arch_instr->category) {
|
||||
isel_func = GetInstructionFunction(module, "INVALID_INSTRUCTION");
|
||||
status = LiftStatus::kInvalid;
|
||||
}
|
||||
|
||||
if (!isel_func) {
|
||||
@@ -449,14 +114,13 @@ bool InstructionLifter::LiftIntoBlock(
|
||||
LOG(ERROR)
|
||||
<< "UNSUPPORTED_INSTRUCTION doesn't exist; not using it in place of "
|
||||
<< arch_instr->function;
|
||||
return false;
|
||||
return LiftStatus::kError;
|
||||
}
|
||||
|
||||
status = LiftStatus::kUnsupported;
|
||||
arch_instr->operands.clear();
|
||||
}
|
||||
|
||||
isel_func->addFnAttr(llvm::Attribute::ArgMemOnly);
|
||||
|
||||
llvm::IRBuilder<> ir(block);
|
||||
auto mem_ptr = LoadMemoryPointerRef(block);
|
||||
auto state_ptr = LoadStatePointer(block);
|
||||
@@ -464,8 +128,9 @@ bool InstructionLifter::LiftIntoBlock(
|
||||
|
||||
// Begin an atomic block.
|
||||
if (arch_instr->is_atomic_read_modify_write) {
|
||||
std::vector<llvm::Value *> args = {ir.CreateLoad(mem_ptr)};
|
||||
ir.CreateStore(
|
||||
ir.CreateCall(intrinsics->atomic_begin, {ir.CreateLoad(mem_ptr)}),
|
||||
ir.CreateCall(intrinsics->atomic_begin, args),
|
||||
mem_ptr);
|
||||
}
|
||||
|
||||
@@ -477,15 +142,6 @@ bool InstructionLifter::LiftIntoBlock(
|
||||
args.push_back(nullptr);
|
||||
args.push_back(state_ptr);
|
||||
|
||||
// Call out to a special 'breakpoint' instruction function, that lets us
|
||||
// interpose on the machine state just before every lifted instruction.
|
||||
if (FLAGS_add_breakpoints) {
|
||||
ir.CreateStore(
|
||||
ir.CreateCall(GetInstructionFunction(module, "BREAKPOINT_INSTRUCTION"),
|
||||
args),
|
||||
mem_ptr);
|
||||
}
|
||||
|
||||
auto isel_func_type = isel_func->getFunctionType();
|
||||
auto arg_num = 2U;
|
||||
|
||||
@@ -523,12 +179,13 @@ bool InstructionLifter::LiftIntoBlock(
|
||||
|
||||
// End an atomic block.
|
||||
if (arch_instr->is_atomic_read_modify_write) {
|
||||
std::vector<llvm::Value *> args = {ir.CreateLoad(mem_ptr)};
|
||||
ir.CreateStore(
|
||||
ir.CreateCall(intrinsics->atomic_end, {ir.CreateLoad(mem_ptr)}),
|
||||
ir.CreateCall(intrinsics->atomic_end, args),
|
||||
mem_ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -583,6 +240,9 @@ static llvm::Value *LoadWordRegValOrZero(llvm::BasicBlock *block,
|
||||
llvm::Value *InstructionLifter::LiftRegisterOperand(
|
||||
Instruction *, llvm::BasicBlock *block,
|
||||
llvm::Type *arg_type, Operand &op) {
|
||||
|
||||
llvm::Function *func = block->getParent();
|
||||
llvm::Module *module = func->getParent();
|
||||
auto &arch_reg = op.reg;
|
||||
|
||||
if (auto ptr_type = llvm::dyn_cast_or_null<llvm::PointerType>(arg_type)) {
|
||||
@@ -602,7 +262,7 @@ llvm::Value *InstructionLifter::LiftRegisterOperand(
|
||||
|
||||
auto val = LoadRegValue(block, arch_reg.name);
|
||||
|
||||
const llvm::DataLayout data_layout(block->getModule());
|
||||
const llvm::DataLayout data_layout(module);
|
||||
auto val_type = val->getType();
|
||||
auto val_size = data_layout.getTypeAllocSizeInBits(val_type);
|
||||
auto arg_size = data_layout.getTypeAllocSizeInBits(arg_type);
|
||||
|
||||
+24
-95
@@ -1,16 +1,22 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_LIFTER_H_
|
||||
#define REMILL_BC_LIFTER_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include "remill/Arch/Instruction.h"
|
||||
|
||||
#include "remill/BC/ABI.h"
|
||||
#include "remill/BC/Util.h"
|
||||
|
||||
namespace llvm {
|
||||
class Function;
|
||||
class Module;
|
||||
@@ -19,93 +25,16 @@ class IntegerType;
|
||||
} // namespace llvm
|
||||
|
||||
namespace remill {
|
||||
namespace cfg {
|
||||
class Block;
|
||||
class Instr;
|
||||
class Module;
|
||||
} // namespace cfg
|
||||
|
||||
class Arch;
|
||||
class Instruction;
|
||||
class IntrinsicTable;
|
||||
class InstructionLifter;
|
||||
class Operand;
|
||||
|
||||
// Lifts CFG files into a bitcode module. This is mostly a big bag of state
|
||||
// needed for all the parts of of lifting to coordinate.
|
||||
class Lifter {
|
||||
public:
|
||||
Lifter(const Arch *arch_, llvm::Module *module_);
|
||||
~Lifter(void);
|
||||
|
||||
// Lift the control-flow graph specified by `cfg` into this bitcode module.
|
||||
void LiftCFG(const cfg::Module *cfg);
|
||||
|
||||
private:
|
||||
Lifter(void) = delete;
|
||||
Lifter(const Lifter &) = delete;
|
||||
|
||||
// Enable deferred inlining. The goal is to support better dead-store
|
||||
// elimination for flags.
|
||||
void EnableDeferredInlining(void);
|
||||
|
||||
// Create a function for a single decoded block.
|
||||
void CreateBlock(const cfg::Block &block);
|
||||
|
||||
// Create a function for a single block.
|
||||
llvm::Function *GetBlock(uint64_t address);
|
||||
|
||||
// Lift code contained in blocks into the block methods.
|
||||
void LiftBlocks(const cfg::Module *cfg);
|
||||
|
||||
// Lift code contained within a single block.
|
||||
llvm::Function *LiftBlock(const cfg::Block &block);
|
||||
|
||||
// Lift the last instruction of a block as a block terminator.
|
||||
void LiftTerminator(llvm::BasicBlock *block,
|
||||
const Instruction *instr);
|
||||
|
||||
// Lift a single instruction into a basic block.
|
||||
llvm::BasicBlock *LiftInstruction(llvm::Function *block,
|
||||
Instruction *instr,
|
||||
InstructionLifter &lifter);
|
||||
|
||||
// Lift an operand to an instruction.
|
||||
llvm::Value *LiftOperand(llvm::BasicBlock *block,
|
||||
llvm::Type *op_type,
|
||||
const Operand &op);
|
||||
|
||||
// Lift a register operand to a value.
|
||||
llvm::Value *LiftRegisterOperand(llvm::BasicBlock *block,
|
||||
llvm::Type *arg_type,
|
||||
const Operand::Register ®);
|
||||
|
||||
// Lift an immediate operand.
|
||||
llvm::Value *LiftImmediateOperand(llvm::Type *arg_type,
|
||||
const Operand &op);
|
||||
|
||||
// Lift an indirect memory operand to a value.
|
||||
llvm::Value *LiftAddressOperand(llvm::BasicBlock *block,
|
||||
const Operand::Address &mem);
|
||||
|
||||
// Architecture of the code contained within the CFG being lifted.
|
||||
const Arch * const arch;
|
||||
|
||||
// Module into which code is lifted.
|
||||
llvm::Module * const module;
|
||||
|
||||
// Blocks that we've added, indexed by their entry address and their ID.
|
||||
std::unordered_map<uint64_t, llvm::Function *> pc_to_block;
|
||||
std::unordered_map<uint64_t, llvm::Function *> id_to_block;
|
||||
|
||||
// Basic block template.
|
||||
llvm::Function * const basic_block;
|
||||
|
||||
// Machine word type for this architecture.
|
||||
llvm::IntegerType * const word_type;
|
||||
|
||||
public:
|
||||
|
||||
// Set of intrinsics.
|
||||
const IntrinsicTable * const intrinsics;
|
||||
enum class LiftStatus {
|
||||
kLifted,
|
||||
kInvalid,
|
||||
kUnsupported,
|
||||
kError
|
||||
};
|
||||
|
||||
// Wraps the process of lifting an instruction into a block. This resolves
|
||||
@@ -119,8 +48,8 @@ class InstructionLifter {
|
||||
const IntrinsicTable *intrinsics_);
|
||||
|
||||
// Lift a single instruction into a basic block.
|
||||
virtual bool LiftIntoBlock(Instruction *instr,
|
||||
llvm::BasicBlock *block);
|
||||
virtual LiftStatus LiftIntoBlock(
|
||||
Instruction *instr, llvm::BasicBlock *block);
|
||||
|
||||
// Machine word type for this architecture.
|
||||
llvm::IntegerType * const word_type;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
#ifndef REMILL_BC_OPTIMIZER_H_
|
||||
#define REMILL_BC_OPTIMIZER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
} // namespace llvm
|
||||
namespace remill {
|
||||
class Optimizer {
|
||||
public:
|
||||
virtual ~Optimizer(void);
|
||||
|
||||
static std::unique_ptr<Optimizer> Create(llvm::Module *module_);
|
||||
|
||||
virtual void Optimize(void) = 0;
|
||||
|
||||
protected:
|
||||
explicit Optimizer(llvm::Module *module_);
|
||||
|
||||
llvm::Module *module;
|
||||
|
||||
private:
|
||||
Optimizer(void) = delete;
|
||||
|
||||
};
|
||||
} // namespace remill
|
||||
|
||||
#endif // REMILL_BC_OPTIMIZER_H_
|
||||
+91
-115
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
@@ -13,11 +27,7 @@
|
||||
|
||||
#include <llvm/ADT/SmallVector.h>
|
||||
|
||||
#include <llvm/Bitcode/ReaderWriter.h>
|
||||
|
||||
#include <llvm/IR/BasicBlock.h>
|
||||
#include <llvm/IR/DebugInfoMetadata.h>
|
||||
#include <llvm/IR/DebugLoc.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
@@ -25,9 +35,6 @@
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/Metadata.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/Verifier.h>
|
||||
|
||||
#include <llvm/IRReader/IRReader.h>
|
||||
|
||||
#include <llvm/Support/FileSystem.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
@@ -35,7 +42,13 @@
|
||||
#include <llvm/Support/ToolOutputFile.h>
|
||||
|
||||
#include "remill/BC/ABI.h"
|
||||
#include "remill/BC/Compat/BitcodeReaderWriter.h"
|
||||
#include "remill/BC/Compat/DebugInfo.h"
|
||||
#include "remill/BC/Compat/GlobalValue.h"
|
||||
#include "remill/BC/Compat/IRReader.h"
|
||||
#include "remill/BC/Compat/Verifier.h"
|
||||
#include "remill/BC/Util.h"
|
||||
#include "remill/BC/Version.h"
|
||||
#include "remill/OS/FileSystem.h"
|
||||
|
||||
namespace remill {
|
||||
@@ -76,7 +89,7 @@ llvm::CallInst *AddTerminatingTailCall(llvm::Function *source_func,
|
||||
llvm::CallInst *call_target_instr = ir.CreateCall(dest_func, args);
|
||||
|
||||
// Make sure we tail-call from one block method to another.
|
||||
call_target_instr->setTailCallKind(llvm::CallInst::TCK_MustTail);
|
||||
call_target_instr->setTailCallKind(llvm::CallInst::TCK_Tail);
|
||||
call_target_instr->setCallingConv(llvm::CallingConv::Fast);
|
||||
ir.CreateRet(call_target_instr);
|
||||
return call_target_instr;
|
||||
@@ -90,8 +103,7 @@ llvm::CallInst *AddTerminatingTailCall(llvm::BasicBlock *source_block,
|
||||
CHECK(nullptr != dest_func)
|
||||
<< "Target function/block does not exist!";
|
||||
|
||||
LOG_IF(ERROR, source_block->getTerminator() ||
|
||||
source_block->getTerminatingMustTailCall())
|
||||
LOG_IF(ERROR, source_block->getTerminator())
|
||||
<< "Block already has a terminator; not adding fall-through call to: "
|
||||
<< (dest_func ? dest_func->getName().str() : "<unreachable>");
|
||||
|
||||
@@ -115,7 +127,7 @@ llvm::CallInst *AddTerminatingTailCall(llvm::BasicBlock *source_block,
|
||||
llvm::CallInst *call_target_instr = ir.CreateCall(dest_func, args);
|
||||
|
||||
// Make sure we tail-call from one block method to another.
|
||||
call_target_instr->setTailCallKind(llvm::CallInst::TCK_MustTail);
|
||||
call_target_instr->setTailCallKind(llvm::CallInst::TCK_Tail);
|
||||
call_target_instr->setCallingConv(llvm::CallingConv::Fast);
|
||||
ir.CreateRet(call_target_instr);
|
||||
return call_target_instr;
|
||||
@@ -174,26 +186,44 @@ llvm::Value *LoadProgramCounterRef(llvm::BasicBlock *block) {
|
||||
return ir.CreateLoad(FindVarInFunction(block->getParent(), "PC"));
|
||||
}
|
||||
|
||||
// Update the program counter in the state struct with a hard-coded value.
|
||||
void StoreProgramCounter(llvm::BasicBlock *block, uint64_t pc) {
|
||||
auto pc_ptr = LoadProgramCounterRef(block);
|
||||
auto type = llvm::dyn_cast<llvm::PointerType>(pc_ptr->getType());
|
||||
(void) new llvm::StoreInst(
|
||||
llvm::ConstantInt::get(type->getElementType(), pc), pc_ptr, block);
|
||||
}
|
||||
|
||||
// Return the current memory pointer.
|
||||
llvm::Value *LoadMemoryPointer(llvm::BasicBlock *block) {
|
||||
llvm::IRBuilder<> ir(block);
|
||||
return ir.CreateLoad(LoadMemoryPointerRef(block));
|
||||
}
|
||||
|
||||
// Return an `llvm::Value *` that is an `i1` (bool type) representing whether
|
||||
// or not a conditional branch is taken.
|
||||
llvm::Value *LoadBranchTaken(llvm::BasicBlock *block) {
|
||||
llvm::IRBuilder<> ir(block);
|
||||
auto cond = ir.CreateLoad(ir.CreateLoad(
|
||||
FindVarInFunction(block->getParent(), "BRANCH_TAKEN")));
|
||||
auto true_val = llvm::ConstantInt::get(cond->getType(), 1);
|
||||
return ir.CreateICmpEQ(cond, true_val);
|
||||
}
|
||||
|
||||
// Return a reference to the memory pointer.
|
||||
llvm::Value *LoadMemoryPointerRef(llvm::BasicBlock *block) {
|
||||
return FindVarInFunction(block->getParent(), "MEMORY");
|
||||
}
|
||||
|
||||
// Find a function with name `name` in the module `M`.
|
||||
llvm::Function *FindFunction(const llvm::Module *module, std::string name) {
|
||||
llvm::Function *FindFunction(llvm::Module *module, std::string name) {
|
||||
return module->getFunction(name);
|
||||
}
|
||||
|
||||
// Find a global variable with name `name` in the module `M`.
|
||||
llvm::GlobalVariable *FindGlobaVariable(const llvm::Module *module,
|
||||
llvm::GlobalVariable *FindGlobaVariable(llvm::Module *module,
|
||||
std::string name) {
|
||||
return module->getGlobalVariable(name);
|
||||
return module->getGlobalVariable(name, true);
|
||||
}
|
||||
|
||||
// Reads an LLVM module from a file.
|
||||
@@ -207,7 +237,9 @@ llvm::Module *LoadModuleFromFile(llvm::LLVMContext *context,
|
||||
CHECK(nullptr != module)
|
||||
<< "Unable to parse module file: " << file_name << ".";
|
||||
|
||||
module->materializeAll(); // Just in case.
|
||||
auto ec = module->materializeAll(); // Just in case.
|
||||
CHECK(!ec)
|
||||
<< "Unable to materialize everything from " << file_name;
|
||||
|
||||
std::string error;
|
||||
llvm::raw_string_ostream error_stream(error);
|
||||
@@ -235,15 +267,21 @@ void StoreModuleToFile(llvm::Module *module, std::string file_name) {
|
||||
<< "Error writing module to file " << file_name << ": " << error;
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_NUMBER > LLVM_VERSION(3, 5)
|
||||
std::error_code ec;
|
||||
llvm::tool_output_file bc(tmp_name.c_str(), ec, llvm::sys::fs::F_RW);
|
||||
|
||||
CHECK(!ec)
|
||||
<< "Unable to open output bitcode file for writing: " << tmp_name;
|
||||
#else
|
||||
llvm::tool_output_file bc(tmp_name.c_str(), error, llvm::sys::fs::F_RW);
|
||||
CHECK(error.empty() && !bc.os().has_error())
|
||||
<< "Unable to open output bitcode file for writing: " << tmp_name
|
||||
<< ": " << error;
|
||||
#endif
|
||||
|
||||
llvm::WriteBitcodeToFile(module, bc.os());
|
||||
bc.keep();
|
||||
if (!ec) {
|
||||
if (!bc.os().has_error()) {
|
||||
RenameFile(tmp_name, file_name);
|
||||
} else {
|
||||
RemoveFile(tmp_name);
|
||||
@@ -290,6 +328,7 @@ std::string FindSemanticsBitcodeFile(const std::string &path,
|
||||
|
||||
LOG(FATAL)
|
||||
<< "Cannot find path to " << arch << " semantics bitcode file.";
|
||||
return "";
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -326,28 +365,40 @@ llvm::Argument *NthArgument(llvm::Function *func, size_t index) {
|
||||
return &*it;
|
||||
}
|
||||
|
||||
// Run a callback function for every indirect block entry in a remill-lifted
|
||||
// bitcode module.
|
||||
void ForEachBlock(llvm::Module *module, BlockCallback on_each_function) {
|
||||
for (auto &global_var : module->globals()) {
|
||||
uint64_t pc = 0;
|
||||
uint64_t id = 0;
|
||||
if (!TryGetBlockPC(&global_var, pc)) {
|
||||
// Apply a callback function to every semantics bitcode function.
|
||||
void ForEachISel(llvm::Module *module, ISelCallback callback) {
|
||||
for (auto &global : module->globals()) {
|
||||
if (!global.hasInitializer() || !global.getName().startswith("ISEL_")) {
|
||||
continue;
|
||||
}
|
||||
if (!TryGetBlockId(&global_var, id)) {
|
||||
id = pc;
|
||||
}
|
||||
|
||||
auto func = llvm::dyn_cast<llvm::Function>(global_var.getInitializer());
|
||||
CHECK(func != nullptr)
|
||||
<< "Global variable " << global_var.getName().str()
|
||||
<< " should be initialized with a function.";
|
||||
auto sem = llvm::dyn_cast<llvm::Function>(
|
||||
global.getInitializer()->stripPointerCasts());
|
||||
|
||||
on_each_function(pc, id, func);
|
||||
callback(&global, sem);
|
||||
}
|
||||
}
|
||||
|
||||
// Declare a lifted function of the correct type.
|
||||
llvm::Function *DeclareLiftedFunction(llvm::Module *module,
|
||||
const std::string &name) {
|
||||
auto bb = module->getFunction("__remill_basic_block");
|
||||
CHECK(nullptr != bb)
|
||||
<< "Cannot declare lifted function " << name << " because the "
|
||||
<< " intrinsics __remill_basic_block cannot be found.";
|
||||
auto func_type = bb->getFunctionType();
|
||||
|
||||
auto func = llvm::dyn_cast<llvm::Function>(
|
||||
module->getOrInsertFunction(name, func_type));
|
||||
|
||||
CHECK(nullptr != func)
|
||||
<< "Could not insert function " << name << " into module";
|
||||
|
||||
InitFunctionAttributes(func);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
// Clone function `source_func` into `dest_func`. This will strip out debug
|
||||
// info during the clone.
|
||||
void CloneFunctionInto(llvm::Function *source_func, llvm::Function *dest_func) {
|
||||
@@ -360,7 +411,10 @@ void CloneFunctionInto(llvm::Function *source_func, llvm::Function *dest_func) {
|
||||
dest_func->setLinkage(source_func->getLinkage());
|
||||
dest_func->setVisibility(source_func->getVisibility());
|
||||
dest_func->setCallingConv(source_func->getCallingConv());
|
||||
|
||||
#if LLVM_VERSION_NUMBER >= LLVM_VERSION(3, 6)
|
||||
dest_func->setIsMaterializable(source_func->isMaterializable());
|
||||
#endif
|
||||
|
||||
std::unordered_map<llvm::Value *, llvm::Value *> value_map;
|
||||
for (llvm::Argument &old_arg : source_func->args()) {
|
||||
@@ -449,12 +503,12 @@ void CloneFunctionInto(llvm::Function *source_func, llvm::Function *dest_func) {
|
||||
dest_mod->getOrInsertFunction(
|
||||
global_val->getName(),
|
||||
llvm::dyn_cast<llvm::FunctionType>(
|
||||
global_val->getValueType())));
|
||||
GetValueType(global_val))));
|
||||
|
||||
} else if (llvm::isa<llvm::GlobalVariable>(global_val)) {
|
||||
new_global_val = llvm::dyn_cast<llvm::GlobalValue>(
|
||||
dest_mod->getOrInsertGlobal(
|
||||
global_val->getName(), global_val->getValueType()));
|
||||
global_val->getName(), GetValueType(global_val)));
|
||||
|
||||
} else {
|
||||
LOG(FATAL)
|
||||
@@ -493,86 +547,9 @@ void CloneFunctionInto(llvm::Function *source_func, llvm::Function *dest_func) {
|
||||
|
||||
namespace {
|
||||
|
||||
static bool TryGetBlockInt(llvm::GlobalObject *func, uint64_t &pc,
|
||||
const char *name) {
|
||||
auto md = func->getMetadata(name);
|
||||
if (!md) {
|
||||
return false;
|
||||
}
|
||||
auto val = llvm::dyn_cast<llvm::ValueAsMetadata>(md->getOperand(0).get());
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
auto pc_val = llvm::dyn_cast<llvm::ConstantInt>(val->getValue());
|
||||
if (!pc_val) {
|
||||
return false;
|
||||
}
|
||||
pc = pc_val->getZExtValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetBlockMeta(llvm::GlobalObject *func, const char *name, uint64_t val) {
|
||||
auto &context = func->getContext();
|
||||
auto int_type = llvm::Type::getInt64Ty(context);
|
||||
auto const_val = llvm::ConstantInt::get(int_type, val);
|
||||
auto md = llvm::ValueAsMetadata::get(const_val);
|
||||
func->setMetadata(name, llvm::MDNode::get(context, md));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Try to get the address of a block.
|
||||
bool TryGetBlockPC(llvm::GlobalObject *func, uint64_t &pc) {
|
||||
return TryGetBlockInt(func, pc, "pc");
|
||||
}
|
||||
|
||||
// Try to get the ID of this block. This may be the same as the block's PC.
|
||||
bool TryGetBlockId(llvm::GlobalObject *func, uint64_t &id) {
|
||||
return TryGetBlockInt(func, id, "id");
|
||||
}
|
||||
|
||||
// Try to get the ID of this block. This may be the same as the block's PC.
|
||||
bool TryGetBlockName(llvm::Function *func, std::string &name) {
|
||||
auto md = func->getMetadata("name");
|
||||
if (!md) {
|
||||
return false;
|
||||
}
|
||||
auto val = llvm::dyn_cast<llvm::ValueAsMetadata>(md->getOperand(0).get());
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
auto name_val = llvm::dyn_cast<llvm::ConstantDataArray>(val->getValue());
|
||||
if (!name_val) {
|
||||
return false;
|
||||
}
|
||||
name = name_val->getAsString().str();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the PC of a block.
|
||||
void SetBlockPC(llvm::GlobalObject *func, uint64_t pc) {
|
||||
SetBlockMeta(func, "pc", pc);
|
||||
}
|
||||
|
||||
// Set the ID of a block.
|
||||
void SetBlockId(llvm::GlobalObject *func, uint64_t id) {
|
||||
SetBlockMeta(func, "id", id);
|
||||
}
|
||||
|
||||
void SetBlockName(llvm::Function *func, const std::string &name) {
|
||||
auto &context = func->getContext();
|
||||
auto const_val = llvm::ConstantDataArray::getString(
|
||||
context, name, false /* AddNull */);
|
||||
auto addr_md = llvm::ValueAsMetadata::get(const_val);
|
||||
func->setMetadata("name", llvm::MDNode::get(context, addr_md));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Initialize some attributes that are common to all newly created block
|
||||
// functions. Also, give pretty names to the arguments of block functions.
|
||||
static void InitBlockFunctionAttributes(llvm::Function *block_func) {
|
||||
|
||||
block_func->setLinkage(llvm::GlobalValue::ExternalLinkage);
|
||||
block_func->setVisibility(llvm::GlobalValue::DefaultVisibility);
|
||||
|
||||
@@ -616,11 +593,10 @@ static void FixupBasicBlockVariables(llvm::Function *basic_block) {
|
||||
|
||||
// Make `func` a clone of the `__remill_basic_block` function.
|
||||
void CloneBlockFunctionInto(llvm::Function *func) {
|
||||
auto module = func->getParent();
|
||||
llvm::Module *module = func->getParent();
|
||||
auto basic_block = module->getFunction("__remill_basic_block");
|
||||
CHECK(nullptr != basic_block)
|
||||
<< "Unable to find __remill_basic_block in module "
|
||||
<< module->getName().str();
|
||||
<< "Unable to find __remill_basic_block in module";
|
||||
|
||||
if (!BlockHasSpecialVars(basic_block)) {
|
||||
InitFunctionAttributes(basic_block);
|
||||
|
||||
+31
-27
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_UTIL_H_
|
||||
#define REMILL_BC_UTIL_H_
|
||||
@@ -55,18 +69,24 @@ llvm::Value *LoadProgramCounter(llvm::BasicBlock *block);
|
||||
// Return a reference to the current program counter.
|
||||
llvm::Value *LoadProgramCounterRef(llvm::BasicBlock *block);
|
||||
|
||||
// Update the program counter in the state struct with a hard-coded value.
|
||||
void StoreProgramCounter(llvm::BasicBlock *block, uint64_t pc);
|
||||
|
||||
// Return the current memory pointer.
|
||||
llvm::Value *LoadMemoryPointer(llvm::BasicBlock *block);
|
||||
|
||||
// Return a reference to the memory pointer.
|
||||
llvm::Value *LoadMemoryPointerRef(llvm::BasicBlock *block);
|
||||
|
||||
// Return an `llvm::Value *` that is an `i1` (bool type) representing whether
|
||||
// or not a conditional branch is taken.
|
||||
llvm::Value *LoadBranchTaken(llvm::BasicBlock *block);
|
||||
|
||||
// Find a function with name `name` in the module `M`.
|
||||
llvm::Function *FindFunction(const llvm::Module *M, std::string name);
|
||||
llvm::Function *FindFunction(llvm::Module *M, std::string name);
|
||||
|
||||
// Find a global variable with name `name` in the module `M`.
|
||||
llvm::GlobalVariable *FindGlobaVariable(const llvm::Module *M,
|
||||
std::string name);
|
||||
llvm::GlobalVariable *FindGlobaVariable(llvm::Module *M, std::string name);
|
||||
|
||||
// Parses and loads a bitcode file into memory.
|
||||
llvm::Module *LoadModuleFromFile(llvm::LLVMContext *context,
|
||||
@@ -86,11 +106,14 @@ llvm::Argument *NthArgument(llvm::Function *func, size_t index);
|
||||
std::string LLVMThingToString(llvm::Value *thing);
|
||||
std::string LLVMThingToString(llvm::Type *thing);
|
||||
|
||||
using BlockCallback = std::function<void(uint64_t, uint64_t, llvm::Function *)>;
|
||||
// Apply a callback function to every semantics bitcode function.
|
||||
using ISelCallback = std::function<
|
||||
void(llvm::GlobalVariable *, llvm::Function *)>;
|
||||
void ForEachISel(llvm::Module *module, ISelCallback callback);
|
||||
|
||||
// Run a callback function for every indirect block entry in a remill-lifted
|
||||
// bitcode module.
|
||||
void ForEachBlock(llvm::Module *module, BlockCallback callback);
|
||||
// Declare a lifted function of the correct type.
|
||||
llvm::Function *DeclareLiftedFunction(llvm::Module *module,
|
||||
const std::string &name);
|
||||
|
||||
// Clone function `source_func` into `dest_func`. This will strip out debug
|
||||
// info during the clone.
|
||||
@@ -99,25 +122,6 @@ void ForEachBlock(llvm::Module *module, BlockCallback callback);
|
||||
// `source_func` into the module of `dest_func`.
|
||||
void CloneFunctionInto(llvm::Function *source_func, llvm::Function *dest_func);
|
||||
|
||||
// Try to get the address of a block.
|
||||
bool TryGetBlockPC(llvm::GlobalObject *func, uint64_t &pc);
|
||||
|
||||
// Try to get the ID of this block. This may be the same as the block's PC.
|
||||
bool TryGetBlockId(llvm::GlobalObject *func, uint64_t &id);
|
||||
|
||||
// Try to get the ID of this block. This may be the same as the block's PC.
|
||||
bool TryGetBlockName(llvm::Function *func, std::string &name);
|
||||
|
||||
// Set the PC of a block.
|
||||
void SetBlockPC(llvm::GlobalObject *func, uint64_t pc);
|
||||
|
||||
// Set the ID of a block.
|
||||
void SetBlockId(llvm::GlobalObject *func, uint64_t id);
|
||||
|
||||
// Set the name of a block. This associates some high-level name, e.g. `malloc`
|
||||
// with the metadata of some block function.
|
||||
void SetBlockName(llvm::Function *func, const std::string &name);
|
||||
|
||||
// Make `func` a clone of the `__remill_basic_block` function.
|
||||
void CloneBlockFunctionInto(llvm::Function *func);
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef REMILL_BC_VERSION_H_
|
||||
#define REMILL_BC_VERSION_H_
|
||||
|
||||
#include <llvm/Config/llvm-config.h>
|
||||
|
||||
#define LLVM_VERSION(major, minor) ((major * 100) + minor)
|
||||
|
||||
#define LLVM_VERSION_NUMBER \
|
||||
LLVM_VERSION(LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR)
|
||||
|
||||
#if LLVM_VERSION_NUMBER < LLVM_VERSION(3, 5)
|
||||
# error "Minimum supported LLVM version is 3.5"
|
||||
#endif
|
||||
|
||||
#endif // REMILL_BC_VERSION_H_
|
||||
@@ -1,29 +0,0 @@
|
||||
/* Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
#include "remill/CFG/BlockHasher.h"
|
||||
#include "remill/CFG/CFG.h"
|
||||
|
||||
#include "third_party/murmurhash/MurmurHash2.h"
|
||||
|
||||
namespace remill {
|
||||
|
||||
BlockHasher::BlockHasher(void)
|
||||
: BlockHasher(0) {}
|
||||
|
||||
BlockHasher::BlockHasher(uint64_t seed_)
|
||||
: seed(seed_) {}
|
||||
|
||||
uint64_t BlockHasher::HashBlock(const cfg::Block &block) const {
|
||||
std::string data;
|
||||
for (const auto &inst : block.instructions()) {
|
||||
auto pc = inst.address();
|
||||
auto pc_ptr = reinterpret_cast<char *>(&pc);
|
||||
auto &bytes = inst.bytes();
|
||||
data.insert(data.end(), pc_ptr, pc_ptr + sizeof(pc));
|
||||
data.insert(data.end(), bytes.begin(), bytes.end());
|
||||
}
|
||||
return MurmurHash64A(data.data(), data.size(), seed);
|
||||
}
|
||||
|
||||
|
||||
} // namespace remill
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Copyright 2017 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
#ifndef REMILL_CFG_BLOCKHASHER_H_
|
||||
#define REMILL_CFG_BLOCKHASHER_H_
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace remill {
|
||||
namespace cfg {
|
||||
class Block;
|
||||
} // namespace cfg
|
||||
|
||||
// Used to create a position- and data-dependent hash of a basic block. This
|
||||
// is part of the block versioning scheme to handle self-modifying code. The
|
||||
// seed of the hasher should be a hash of some region of executable code.
|
||||
//
|
||||
// The reason we want a hash is so that we can identify blocks in a way that
|
||||
// is representative of their content and location, as opposed to just being
|
||||
// represented by their program counters.
|
||||
class BlockHasher {
|
||||
public:
|
||||
BlockHasher(void);
|
||||
|
||||
explicit BlockHasher(uint64_t seed_);
|
||||
|
||||
uint64_t HashBlock(const cfg::Block &block) const;
|
||||
|
||||
const uint64_t seed;
|
||||
};
|
||||
|
||||
} // namespace remill
|
||||
|
||||
#endif // REMILL_CFG_BLOCKHASHER_H_
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
#include <fstream>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "remill/CFG/CFG.h"
|
||||
|
||||
namespace remill {
|
||||
|
||||
const cfg::Module *ReadCFG(std::string cfg_file_name) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
std::ifstream cfg(cfg_file_name);
|
||||
CHECK(cfg.good()) << "Invalid CFG file: " << cfg_file_name;
|
||||
|
||||
auto cfg_pb = new cfg::Module;
|
||||
auto parsed = cfg_pb->ParseFromIstream(&cfg);
|
||||
CHECK(parsed)
|
||||
<< "Unable to parse CFG file: " << cfg_file_name
|
||||
<< " with error " << cfg_pb->DebugString();
|
||||
|
||||
return cfg_pb;
|
||||
}
|
||||
|
||||
} // namespace remill
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
||||
#include "generated/CFG/CFG.pb.cc"
|
||||
#pragma clang diagnostic pop
|
||||
@@ -1,26 +0,0 @@
|
||||
/* Copyright 2015 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
|
||||
#ifndef REMILL_CFG_CFG_H_
|
||||
#define REMILL_CFG_CFG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
|
||||
#include "generated/CFG/CFG.pb.h"
|
||||
#pragma clang diagnostic pop
|
||||
class Module;
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
} // namespace llvm
|
||||
|
||||
namespace remill {
|
||||
|
||||
class Arch;
|
||||
|
||||
const cfg::Module *ReadCFG(std::string cfg_file_name);
|
||||
|
||||
} // namespace remill
|
||||
|
||||
#endif // REMILL_CFG_CFG_H_
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved.
|
||||
|
||||
package remill.cfg;
|
||||
|
||||
message Instr {
|
||||
required bytes bytes = 1;
|
||||
required uint64 address = 2;
|
||||
}
|
||||
|
||||
// A block has an ID that can be distinct from its address. The idea here is
|
||||
// that the block should represent a position- and content dependent hash of
|
||||
// the block. This scheme permits multiple blocks at the same address to exist
|
||||
// (e.g. to model runtime code modification).
|
||||
message Block {
|
||||
optional string name = 1;
|
||||
optional uint64 id = 2;
|
||||
required uint64 address = 3;
|
||||
repeated Instr instructions = 4;
|
||||
}
|
||||
|
||||
message Module {
|
||||
repeated Block blocks = 1;
|
||||
}
|
||||
@@ -1,4 +1,18 @@
|
||||
/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user