No boost (#88)

* Reformatting Annotation.cpp

* WIP

* Things build for me, but I need to do more extensive testing.

* Missing instruction

* Updated docs; got demos working, except demo17, which probably never ran.

* entry_pc can be 0; use -1 instead
This commit is contained in:
Peter Goodman
2017-01-27 13:53:15 -05:00
committed by GitHub
parent 51cd6e4c4e
commit 641cfef7e5
1279 changed files with 8453 additions and 37879 deletions
+12
View File
@@ -18,6 +18,18 @@
# Object files
*.o
*.idb
*.id0
*.id1
*.id2
*.log
*.nam
*.til
mc-sema/tests/*.bc
mc-sema/tests/*.cfg
mc-sema/tests/*.exe
#autogenerated file: test_a.auto.asm
mc-sema/validator/valTest/test_a.auto.asm
mc-sema/validator/x86_64/valTest/test_a.auto.asm
-48
View File
@@ -1,48 +0,0 @@
=========
ChangeLog
=========
This is the list of all noteworthy changes made in every public release of
the tool. See README for the general instruction manual.
----------------
Staying informed
----------------
Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <mcsema-dev+subscribe@googlegroups.com>.
--------------
July 29 2015:
--------------
- Initial set of changes from CGC:
- Annotation of bitcode with original x86 instruction
- Fixes for signed multiplication and division
- MUL16r/MUL16m/MUL8r/MUL8m, SHLD32mrCL
- BSF, SETP, FLDLN2, FLDL2E, FLDLG2, FPTAN, FPREM, FCHS, FISTT, FUCOMI
- *LOTS* of new SSE instructions
- Lots of new instruction semanticts tests
--------------
July 08 2015
--------------
- Added 64-bit [x86_64] support
--------------
Apr 04 2014:
--------------
- Better IDA based CFG recovery
- New Instructions
- Registers are now an enum
- Better implementation of shifts
- Much better implementtion of CMOVxx
- Support for VS2013, CMake 3.1
--------------
Jan 30 2015:
--------------
- Upgrade from LLVM 3.2 to LLVM 3.5
- Many new instructions
-73
View File
@@ -1,79 +1,6 @@
project(mc-sema)
cmake_minimum_required(VERSION 2.8)
include(ExternalProject)
ExternalProject_add(boost
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/boost
CMAKE_CACHE_ARGS
-DBUILD_PROJECTS:STRING=thread;system;filesystem;date_time;program_options
-DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_CURRENT_BINARY_DIR}/boost
)
#WHY CAN'T IT EVER BE SMOOTH
if(WIN32)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/boost/include)
else(WIN32)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/boost/include/boost-1.52.0)
endif(WIN32)
if (MSVC60)
set(BOOST_TOOLSET "vc6")
elseif(MSVC70)
set(BOOST_TOOLSET "vc7")
elseif(MSVC71)
set(BOOST_TOOLSET "vc71")
elseif(MSVC80)
set(BOOST_TOOLSET "vc80")
elseif(MSVC90)
set(BOOST_TOOLSET "vc90")
elseif(MSVC10)
set(BOOST_TOOLSET "vc100")
elseif(MSVC11)
set(BOOST_TOOLSET "vc110")
elseif(MSVC12)
set(BOOST_TOOLSET "vc120")
elseif(MSVC14)
set(BOOST_TOOLSET "vc140")
else(MSVC14)
set(BOOST_TOOLSET "vc")
endif(MSVC60)
if(CMAKE_BUILD_TYPE MATCHES Debug)
if(WIN32)
#use .lib paths here
set(Boost_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_filesystem-${BOOST_TOOLSET}-mt-gd-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_date_time-${BOOST_TOOLSET}-mt-gd-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_program_options-${BOOST_TOOLSET}-mt-gd-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_system-${BOOST_TOOLSET}-mt-gd-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_thread-${BOOST_TOOLSET}-mt-gd-1_52.lib)
else(WIN32)
#use .a / .so paths here
set(Boost_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_program_options-mt-d.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_system-mt-d.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_date_time-mt-d.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_filesystem-mt-d.a)
endif(WIN32)
else(CMAKE_BUILD_TYPE MATCHES Debug)
if(WIN32)
#use .lib paths here
set(Boost_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_filesystem-${BOOST_TOOLSET}-mt-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_date_time-${BOOST_TOOLSET}-mt-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_program_options-${BOOST_TOOLSET}-mt-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_system-${BOOST_TOOLSET}-mt-1_52.lib
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost_thread-${BOOST_TOOLSET}-mt-1_52.lib)
else(WIN32)
#use .a / .so paths here
set(Boost_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_program_options-mt.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_system-mt.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_date_time-mt.a
${CMAKE_CURRENT_BINARY_DIR}/boost/lib/boost-1.52.0/libboost_filesystem-mt.a)
endif(WIN32)
endif(CMAKE_BUILD_TYPE MATCHES Debug)
if(WIN32)
SET(CMAKE_EXE_LINKER_FLAGS "/LARGEADDRESSAWARE ${CMAKE_EXE_LINKER_FLAGS}")
endif(WIN32)
+1 -1
View File
@@ -1,4 +1,4 @@
akshay kumarak <iit.akshay@gmail.com>
Akshay Kumar <iit.akshay@gmail.com>
Andrew Ruef <andrew@trailofbits.com>
Artem Dinaburg <artem@trailofbits.com>
Clayton Walker <clayton.m.walker@gmail.com>
-13
View File
@@ -1,13 +0,0 @@
-> Support for 64-bit binaries;
-> Updated Registers list, Calling Convention;
-> Added Target component to initialize MCDisassembler;
-> Handling of 64-bit relocation types and Data section Layout;
-> Handling of 64-bit pointers and stack layout
-> New instructions
-> Updated Unit-test framework
TODO:
-> Handling statically linked binaries
-> RIP-relative instructions
-> Support new instructions; Update Unit-testcases
-> Test COFF and PE Target binaries
+6 -2
View File
@@ -17,11 +17,11 @@ We hope that this library is useful to the program analysis and reverse engineer
## Separation of Components
MC-Semantics is separated into two conceptual parts: control flow recovery and instruction translation.
McSema is separated into two conceptual parts: control flow recovery and instruction translation.
The two parts communicate via a control flow graph structure that contains native code. This control flow graph structure connects basic blocks and defines information about external calls, but provides no further semantic information.
The `bin_descend` program attempts to recover a control flow graph from a given binary file. It will write the recovered control flow graph into a Google Protocol Buffer serialized file. There is also an IDAPython script to recover control flow from within IDA Pro.
An IDAPython script, `get_cfg.py`, attempts to recover a control flow graph from a given binary file. It will write the recovered control flow graph into a Google Protocol Buffer serialized file. There is also an IDAPython script to recover control flow from within IDA Pro.
The `cfg_to_bc` program attempts to convert a control flow graph structure into LLVM bitcode. This translation process is more a transcription act than an analysis, since a control flow structure has already been recovered.
@@ -57,6 +57,10 @@ mcsema uses external code which has been included in this source release:
mcsema uses Intel Pin, which has not been included in this source release, but is freely available. Pin is used only for testing of instruction semantics and is not required to use the library.
### Pronunciation
McSema is pronounced as "mick sema".
## Contact
For any questions:
+1 -1
View File
@@ -6,7 +6,7 @@ The output of each demo appears after its description.
The demos live in `mc-sema\tests` in the source tree. These demos require that a **debug version** of the mc-sema be built prior to execution.
The output may differ in debug statements from what you see. Demos are usually tested by using IDAPython as the CFG recovery script, but should work with `bin_descend`.
The output may differ in debug statements from what you see. Demos are tested by using IDAPython as the CFG recovery script.
## demo1
+19 -64
View File
@@ -2,54 +2,17 @@
This document describes where in the code features of `mc-sema` are located. Additionally, this document describes some of the internal functions and macros that are used throughout the code.
## PE/COFF Parsing
The code to parse PE/COFF files and map them into a programatically accessible state lives in `mc-sema/binary_common`. This code is split into two parts: the core parsing, and binary object abstraction. The core parsing reads data structures from the PE/COFF file, determines validity, and makes the data structures accessible programatically. The binary object abstraction provides higher-level utilities for working with executable files, such as relocating addresses, iterating over sections, import tables, and export tables, etc.
The core of the PE/COFF parsing is provided by a separate open source project, [pe-parse](https://github.com/trailofbits/pe-parse). The pe-parse code is located in `mc-sema/binary_common/pe-parse`. For more details, please see the project website.
### Binary Object Abstraction
The binary object abstraction lives in `mc-sema/binary_common/bincomm.{h,cpp}`. An abstract base class, `ExecutableContainer`, is the external interface for working with both COFF and PE files. The internal concrete classes, `PeTarget` and `CoffTarget` should never be used in the rest of the code.
The class method `ExecutableContainer *open(std::string filename, const llvm::Target *target)` will open a PE or COFF file and return an `ExecutableSection` object representation of it. The `target` argument is currently unused. The extension of `filename` determines whether a file is PE or COFF.
The `ExecutableContainer` class provides helper methods for operating on executables. All methods return a boolean indicating whether they succeeded (true) or failed (false). A description of some of the methods:
* `bool find_import_name(uint32_t addr, std::string &s)`: Get the name of the imported function referenced at address `addr`.
* `bool is_addr_relocated(uint32_t addr)`: is the address `addr` relocated?
* `bool relocate_addr(uint32_t addr, uint32_t &toAddr)`: Find the relocation at `addr`. Store the address of the symbol the relocation references in `toAddr`. Note that this is a **double** indirection: it will get the address of the relocated symbol, not the address of the relocation in the relocation table. This is usually what you want, anyway.
* `bool get_exports(std::list<std::pair<std::string, uint64_t> > &exports)`: Parse the export table and store it in `exports`. The entries are a tuple of (export name, virtual address of export). The entry point is included as an export named 'entry'.
* `bool get_sections(std::vector<SectionDesc> &sections)`: Get a reference to this binary's sections. The `ExecutableContainer` class defines an internal struct, `SectionDesc`, that is a simple way to describe binary sections. The struct is defined in `bincomm.h` and is fairly self explanatory.
* `uint64_t getBase()`: The base address of this executable.
* `uint64_t getExtent()`: The size of this executable.
* `int readByte(uint64_t addr, uint8_t *b)`: Attempt to read a byte at virtual address `addr` (as seen from inside the executable), and store it in `b`.
### COFF Headaches
COFF object have every section based at 0x0. This makes sense, since the final executable is not yet created, and sections may be merged/deleted/changed. However, this present a problem for translation, since each virtual address reference should be unambiguious. Each COFF section is rebaesd internally, by the order in which it appears in the COFF file. So for example, if a COFF file has two sections of size 0x80 both based at 0x0, the first section will have virtual addresses 0x0 - 0x7F, and the second will have virtual addresses 0x80 - 0xFF. This is similar to what tools like IDA Pro to when working with object files. The rebasing code lives in `CoffTarget::CoffTarget` in `bincomm.cpp`.
## CFG Recovery
The high-level actions of the CFG recovery code are in `bin_descend/bin_descend.cpp`:`makeNativeModule`. This function will first identify an entry point into the code via a symbol or numerical value supplied on the command line. Then unless `-ignore-native-entry-points` is specified, all exported code symbols are added to the entry point work list. Finally, `addDataEntryPoints` will loops through the data section looking for relocations that point to the code section. Any such relocations are assumed to be function pointers and are also added to the entry point work list.
The high-level actions of the CFG recovery code are in `bin_descend/get_cfg.py`. McSema uses IDA Pro for disassembling programs and producing CFG files.
Once the entry point worklist is created, every function in it is recursively disassembled by `bin_descend/cfg_recover.cpp`:`getFuncs`. The main loop in `getFuncs` will recursively disassemble starting at an entry point, and return a list of disassembled functions.
### `llvm::MCInst` and `NativeInst`
`getFuncs` will repeatedly call `bin_descend/cfg_recover.cpp`:`getFunc` until all functions reachable from the entry point are disassebmled. The `getFunc` code will disassemble a function via `bin_descend/cfg_recover.cpp`:`decodeBlock`, which builds basic blocks from disassembly and has special per-instruction processing.
The `llvm::MCInst` class is defined by LLVM and stores the disassembly of a machine instruction. Unfortunately, the class is missing control flow related information and other data useful for translation. The `Inst` class, defined in `peToCFG/peToCFG.h`, augments `llvm::MCInst` with data not needed by LLVM itself. For instance, `Inst` records instruction prefixes, whether the instruction is the last in a block, whether any others point to it, whether it references external data, etc. All of the `mc-sema` code will operate on `NativeInst` instances, and not `llvm:MCInst`.
It is `decodeBlock` that does special per-instruction processing. For example, this is where `call` instructions are identified and new functions are added to the work list. Also this is where external calls (including calls to APIs), and data references are identified. The actual graph portion of the CFG is also made here via terminating and connecting instructions. `decodeBlock` doesn't do the x86 opcode to metadata conversion itself. That is done in `peToCFG/inst_decoder_fe.cpp`:`LLVMByteDecoder::getInstFromBuff`, which is covered in a later section.
New instances of the `NativeInst` class are created in `peToCFG/inst_decoder_fe.cpp`:`LLVMByteDecoder::getInstFromBuff`. The `getInstFromBuff` method starts with an `llvm::MCInst` from the LLVM disassembler, and then augments additional information: the instruction prefix, whether the instruction terminates a block, and whether it points to another instruction. Later code will then modify more instruction parameters.
After recovering the CFG, `makeNativeModule` must still create a data section for the recovered code. The data section is an LLVM structure made from data blobs and references to code and data. These are created by calling `bin_descend/cfg_recover.cpp`:`processDataSection` for every data section in the original binary.
Finally, `makeNativeModule` calls `peToCFG/peToCFG.cpp`:`addExterns` to visit every node of the CFG and add any external function references to the global `NativeModule` container. This is done to simplify referencing all external calls in the recovered code.
### `llvm::MCInst` and `Inst`
The `llvm::MCInst` class is defined by LLVM and stores the disassembly of a machine instruction. Unfortunately, the class is missing control flow related information and other data useful for translation. The `Inst` class, defined in `peToCFG/peToCFG.h`, augments `llvm::MCInst` with data not needed by LLVM itself. For instance, `Inst` records instruction prefixes, whether the instruction is the last in a block, whether any others point to it, whether it references external data, etc. All of the `mc-sema` code will operate on `Inst` instances, and not `llvm:MCInst`.
New instances of the `Inst` class are created in `peToCFG/inst_decoder_fe.cpp`:`LLVMByteDecoder::getInstFromBuff`. The `getInstFromBuff` method starts with an `llvm::MCInst` from the LLVM disassembler, and then augments additional information: the instruction prefix, whether the instruction terminates a block, and whether it points to another instruction. Later code will then modify more instruction parameters.
To enable some of the Inst functionality, such as determining operand location and prefix, changes to LLVM's MCInst class had to be made. Most of those should be in `lib/Target/X86/Disassembler/X86Disassembler.cpp` and `lib/Target/X86/Disassembler/X86DisassemblerDecoder.c`.
To enable some of the Inst functionality, such as determining operand location and prefix, changes to LLVM's `MCInst` class had to be made. Most of those should be in `lib/Target/X86/Disassembler/X86Disassembler.cpp` and `lib/Target/X86/Disassembler/X86DisassemblerDecoder.c`.
### Relocations / Code and Data References
@@ -57,29 +20,27 @@ Determining what is code and what is data, and what is a code or a data referenc
## External Functions
Call instructions to external functions have an extra annotation indicating the external call and the function name, calling convention, and arument count. The actual annotation is done in `bin_descend/cfg_recover.cpp`:`decodeBlock`.
Call instructions to external functions have an extra annotation indicating the external call and the function name, calling convention, and arument count.
External functions cannot be modeled like translated functions, and the control flow recovery tool need to know the calling convention and argument count of these extrnal functions. The calling convention and argument count are specified by an external function map file. More details on this file are in [USAGE_AND_APIS.md](USAGE_AND_APIS.md). There is a default external function map in `tests/std_defs.txt`. This function map should cover the vast majority of the Windows API and the C runtime.
## Serialization and Deserialization
The serialization functions that convert a NativeModule to a .cfg file are all in `peToCFG/peToCFG.cpp`. The serialization functions are generally prefixed with `dump`, and the deserialization functions are prefixed with `read`. The main serialization function is `dumpProtoBuf`, and the main deserialization function is `readProtoBuf`.
The protobuf format is defined in `peToCFG/CFG.proto`, and described in more detail in [USAGE_AND_APIS.md](USAGE_AND_APIS.md).
## Translation
Instruction translation begins life in the cfg_to_bc executable, which takes a serialized Google protocol buffer CFG, and converts it to LLVM bitcode. The high-level actions of translation are defined in `bitcode_from_cfg/cfg_to_bc.cpp`:`main` and described in this section.
First, the CFG it re-serialized via a call to `peToCFG/peToCFG.cpp`:`readModule`, which will in turn de-serialze the protocol buffer file via `readProtobuf`. The CFG is then transformed into an `llvm::Module`, with some initial data structures populated.
First, the CFG it re-serialized via a call to `peToCFG/peToCFG.cpp`:`ReadProtoBuf`, which will in turn de-serialze the protocol buffer file. The CFG is then transformed into an `llvm::Module`, with some initial data structures populated.
Next, the real translation can begin. The raw translation loop is in `cfgToLLVM/raiseX86.cpp`:`natModToModule`. The first action of `natModToModule` is to pre-populate all defined functions as stubs without any code. This is done so that these functions may be referenced in the data section and by other functions, as translation happens. Then, the data sections can be inserted.
Next, the real translation can begin. The raw translation loop is in `cfgToLLVM/raiseX86.cpp`:`LiftCodeIntoModule`. The first action of `LiftCodeIntoModule` is to pre-populate all defined functions (`InitLiftedFunctions`) as stubs without any code. This is done so that these functions may be referenced in the data section and by other functions, as translation happens. Then, the data sections can be inserted. After the data sections are inserted, the code contents of each function are lifted into the pre-defined LLVM functions. This is done by the `LiftFunctionsIntoModule`. Each function is lifted using the `InsertFunctionIntoModule`.
### Data Section Translation
Data sections from the CFG are transformed into bitcode in `cfgToLLVM/raiseX86.cpp`:`insertDataSections`.
Data sections from the CFG are transformed into bitcode in `cfgToLLVM/raiseX86.cpp`:`InsertDataSections`.
First, `insertDataSections` will create blank stubs for every data section. Once again, the purpose is to allow cross-data section references.
First, `InsertDataSections` will create blank stubs for every data section. Once again, the purpose is to allow cross-data section references.
Then the actual data insertion begins. Data sections are translated to packed LLVM structures. Representing data as a packed structure lets us reference individual data items and to insert references to other code and data sections, that will be correctly relocated in bitcode. The translation happens via two nested loops: the first one loops over every data section in the CFG, and the second one loops over every item in the data section.
@@ -87,19 +48,21 @@ For every data section item, one of three things can happen. The item can be a a
### External Function References
After data insertion, external function references are populated. These must be populated before any instruction translation, since instructions may reference these external functions. The translation loop in `natModToModule` is pretty straightforward: all external definitions are simply converted to an `llvm::Function` object with appropriate return type and arguments and added to the module.
After data insertion, external function references are populated. These must be populated before any instruction translation, since instructions may reference these external functions. The translation loop in `LiftCodeIntoModule` is pretty straightforward: all external definitions are simply converted to an `llvm::Function` object with appropriate return type and arguments and added to the module.
### Instruction Translation
Once the external function mappings are added, each function in the CFG is translated to LLVM bitcode. The function translation is done by `cfgToLLVM/raiseX86.cpp`:`insertFunctionIntoModule`.
Once the external function mappings are added, each function in the CFG is translated to LLVM bitcode. The function translation is done by `cfgToLLVM/raiseX86.cpp`:`InsertFunctionIntoModule`.
Each translated function takes a single argument, the register state. Then this register state is spilled into local variables for use within the function. The allocation of the local register state is done by `allocateLocals`, and the spilling of the register state is done by `cfgToLLVM/x86Instrs.cpp`:`writeContextToLocals`.
Each translated function takes a single argument, the register state. Then this register state is referenced by local variables for use within the function. The creation of the local references into the register state is done by `ArchAllocRegisterVars`.
Next, every basic block in the CFG is visited by `cfgToLLVM/raiseX86.cpp`:`bfs_cfg_visitor::discover_vertex`. This function will create an llvm::BasicBlock object to represent the block and any following blocks, and then begin populating the block with translated instructions.
Next, an empty LLVM `BasicBlock` is created for every machine code basic block. The basic blocks are defined ahead-of-time so that the basic blocks can be referenced when lifting control-flow instructions.
The `disInstr` function does the actual intruction translation. More literally, it adds an annotation so one can tell what instruction is being translated in the resulting IR, and calls `cfgToLLVM/x86Instrs.cpp`:`disInstrX86` to do the translation. This is done in case there is a need for multiple decoders or architectures.
Next, the contents every basic block in the CFG is visited by `cfgToLLVM/raiseX86.cpp`:`LiftBlockIntoFunction`. This function will begin populating the block with translated instructions.
`disInstrX86` is a dispatch routine that calls the appropriate translation function based on the instruction's LLVM opcode. The translation map is stored in `cfgToLLVM/InstructionDispatch.cpp`:`translationDispatchMap`.
The `LiftInstIntoBlock` function does the actual intruction translation. More literally, it adds an annotation so one can tell what instruction is being translated in the resulting IR, and calls `cfgToLLVM/x86Instrs.cpp`:`LiftInstIntoBlockImpl` to do the translation. This is done in case there is a need for multiple decoders or architectures.
`LiftInstIntoBlockImpl` is a dispatch routine that calls the appropriate translation function based on the instruction's LLVM opcode. The translation map is stored in `cfgToLLVM/InstructionDispatch.cpp`:`translationDispatchMap`.
The `translationDispatchMap` variable is populated by `cfgToLLVM/InstructionDispatch.cpp`:`initInstructionDispatch`. The actual population routines, described briefly below, appear in their own files. The files are named `cfgToLLVM/x86Instrs_<suffix>.cpp`, where `<suffix>` correpsonds to the types of instructions translated there.
@@ -209,12 +172,4 @@ The functionality demos are meant to only run on Win32 and live in `mc-sema/test
### Instruction Semantics Tests
Other than the full transformation demos, there are separate instruction semantics tests that verify only that instruction semantics in LLVM match those of x86. These tets are run via the `testSemantics` appliation, more detail of which are in the TOOLS document. The rest of this section will describe how `testSematics` is implemented.
The actual test cases are all in `validator/tests`. Each test is in its own `.asm` file, with the file name being the test name. Each file is valid nasm-style x86 assembly with a special format, described in the ADD A TEST document.
Since the number of tests is always changing, the ground truth results and the test driver are determined at build time. First, lets describe how the ground truth for instruction semantics is generated. The main build script responsible for this is `validator/valTest/CMakeLists.txt`. The ground truth for instruction semantics is determined by each instruction's effect on register state as seen by Intel's PIN tool. There is a custom pin tool used to record instruction semantics compiled in `validator/valTool`. The build script calls `valiator/testgen.py` to combine all of the individual test `.asm` files into one file, adds code to re-set state between each instruction, and runs this combined file through the semantics recording pin tool. The pin tool then outputs a ground truth file called `tests.out`.
The test driver is built via the build script `validator/testSemantics/CMakeLists.txt`. This script uses the file `validator/testSemantics/testSemantics.tempalte` as a tempalte for the C++ code of the final driver. The individual test assembly files are parsed, and test information is inserted into the template driver. After all tests are inserted, a file named `testSemantics.auto.cpp` is emitted and used to build the `testSemantics.exe` executable.
The `testSemantics` executable uses the Google testing framework as the base for verifying unit tests. It compares the register state saved in `tests.out` with the register state produced after JITting the LLVM code produced by the mc-sema for the same x86 instructions. The actual JITting happens in `ModuleTest::runFunctionOnState`. New tests are defined via the `TEST_F` macro, provided by the Google test framework. The `IN_OUT_TEST` macro is used to wrap the creation of a new test and output comparison. The Intel PIN output and raw register state output are not directly comparable, and need some massaging (e.g. transforming FPU state from a flat index to one relative to the TOP flag). The `DEBUG` compile time symbol can be defined to enable very verbose debugging of the semantics testing.
Instruction semantics tests have been temporarily removed, pending a reimplementation that simplifies the testing process.
+1 -79
View File
@@ -81,90 +81,12 @@ Recover control flow from `demo_dll_6.dll`. Start recovery at the symbol `get_va
`"%IDA_PATH%\idaq.exe" -B -S"%GET_CFG_PY% --batch --std-defs \"%STD_DEFS%\" demo_6_defs.txt --entry-symbol get_value --output demo_dll_6.cfg" demo_dll_6.dll`
## bin_descend
bin_descend is a recursive descent disassembler and control flow recovery tool. As input, bin_descend accepts COFF object files and Windows PE DLLs. To accurately recover control flow, it is imperative that relocation information *not* be stripped from the input file.
The output file is named `<input name without extension>.cfg`. That is, an input of `foo.obj` will produce `foo.cfg`.
When recovering control flow, bin_descend uses certain heuristics to attempt accurate control flow recovery:
* Relocated immediate values in code (e.g. PUSH imm32) that point to the code section are assumed to be function pointers. These will be added to the list of entry points from which to recover control flow.
* Relocated values in the data section that point to the code section are assumed to be function pointers. These will be added to the list of entry points from which to recover control flow.
* Additionally, relocated function pointers in the data section are assumed to be used as callbacks. A thunk that takes current register state and transforms it into a translator specific register context will automatically be created for these functions, and used in place of the function when it referenced not by a direct call.
* Relocated immediate values in code (e.g. PUSH imm32) that point to the data section are assumed to be data values.
* Relocated immediate values in the data section that point to the data section are assumed to be data values.
### Limitations
COFF files will have several sections based at address zero. As there is no specification for how to assign addresses, we will assign addresses to sections in the order in which they are processed. This usually matches the address what other tools (e.g. IDA Pro) select, but not always. It is recommended that the entry point for COFF object should be specified by `-entry-symbol` and not `-e`.
### Usage
C:\>bin_descend -help
OVERVIEW: binary recursive descent
USAGE: bin_descend.exe [options]
OPTIONS:
-d - Print debug information
-e=<VA> - Entry point
-entry-symbol=<symbol1,symbol2,symbol3,...> - Entry point symbol(s)
-func-map=<std_defs.txt,custom_defs.txt,other_mapping.txt> - Function map files
-help - Display available options (-help-hidden for more)
-i=<filename> - Input filename
-ignore-native-entry-points - Ignore any exported functions not explicitly specified via -e or -entry-symbol
-mc-x86-disable-arith-relaxation - Disable relaxation of arithmetic instruction for X86
-mtriple=<target triple> - Target Triple
-stats - Enable statistics output from program
-v=<level> - Verbosity level
-version - Display the version of this program
-x86-asm-syntax - Choose style of code to emit from X86 backend:
=att - Emit AT&T-style assembly
=intel - Emit Intel-style assembly
* `-d`: This flag will enable output of extra debugging information to standard out.
* `-e=<VA>`: Specify the entry point address where disassembly will begin. This value should be a virtual address in the target module. Both decimal and hex values are accepted. Hex values must be prefixed with 0x or 0X.
* `-entry-symbol`: Specify entry point symbol(s) from which to start disassembly. This is particualrly useful for COFF files where several sections based at address zero will be rebased during control flow recovery.
* `-func-map=<std_defs.txt,custom_defs.txt,other_mapping.txt>`: Location of file(s) that specify arguments and calling conventions of externally referenced functions. Externally referenced functions are those that are not a part of the translated code: APIs, functions in other compilation units, etc. The file `std_defs.txt` is a pre-existing define file that provides definitions for most of the Win32 API and the standard C library.
* `-help`: Display the help screen above.
* `-i=<filename>`: Specify the input file. This should be a COFF object or a Window PE DLL.
* `-ignore-native-entry-points`: Do not process any exported functions other than the one specified by `-e` or `-entry-symbol`. This option should be used when processing DLLs that import C runtime initialization code or include exports unrelated to the one you are trying to lift.
* `-mc-x86-disable-arith-relaxation`:
* `-mtriple=<target triple>`: Specify the target triple (e.g. i686-pc-win32, i686-pc-linux-gnu) of the input file. This option should be used when processing Windows object files on Linux, or vice versa.
* `-stats`:
* `-v=<level>`:
* `-version`: Display the version of bin_descend.
* `-x86-asm-syntax`: Chose whether assembly output will use ATT or Intel syntax.
### Examples
These examples are taken from the tests present in `mc-sema/tests`.
Recover control flow for `demo_test1.obj` starting at symbol `start` and enable debugging output:
`bin_descend.exe -d -entry-symbol=start -i=demo_test1.obj`
Recover control flow for `demo_test4.obj` starting at symbol `_doTrans`, enable debugging, and specify a definitions file for external functions (to properly link API calls):
`bin_descend.exe -d -func-map=std_defs.txt -entry-symbol=_doTrans -i=demo_test4.obj`
Recover control flow for `sailboat.obj` starting at symbol `_keycomp`, enable debugging, and specify two external function definition files:
`bin_descend.exe -d -func-map=sailboat.txt,std_defs.txt -entry-symbol=_keycomp -i=sailboat.obj`
Recover control flow from `demo_dll_1.dll`, starting at symbol `HelloWorld`, enable debugging, specify an external function definition, and ignore all entry points other than `HelloWorld`:
`bin_descend.exe -d -entry-symbol=HelloWorld -ignore-native-entry-points=true -i=demo_dll_1.dll -func-map=std_defs.txt`
## cfg_to_bc
The cfg_to_bc tool will take a control flow graph in the format produced by bin_descend, and translate it to LLVM bitcode. The resulting bitcode will have a driver function, specified by `-driver-name`. The driver is an exported function that takes place of the entrypoint in the original code. If the original function accepted arguments as 32-bit values pushed onto the stack, a stub to place these into a register context can be automatically generated by specifying the argument count via `-driver-argc`. In case of other calling conventions, a raw driver that accepts a complete register context can be defined via `-driver-raw`.
The CFG is in Google protocol buffer format. The definition of the protocol is in `mc-sema/peToCFG/CFG.proto`. The CFG does not have to be created by bin_descend, but it can be created by any tool (e.g. IDA Python) that can write to the protocol buffer format. The control flow recovery and translation portions were explicitly designed to be separable.
The CFG is in Google protocol buffer format. The definition of the protocol is in `mc-sema/peToCFG/CFG.proto`. The CFG can be created by any tool (e.g. IDA Python) that can write to the protocol buffer format. The control flow recovery and translation portions were explicitly designed to be separable.
### Limitations
+4 -4
View File
@@ -1,12 +1,12 @@
# Usage and APIs
To use mcsema on its valid input files, two tools are provided: `bin_descend` for control flow recovery and `cfg_to_bc` for translation. The `bin_descend` tool takes as input a valid COFF object or PE DLL, and recovers its control flow. The `cfg_to_bc` tool takes a control flow graph in Google protocol buffer format, and translates it into LLVM bitcode. The generated bitcode is not optimized and will be very noisy with unnecessarily live variables. Unoptimized bitcode is useful for debugging translation errors, but before use this bitcode should be run through the LLVM `opt` tool.
The `cfg_to_bc` tool takes a control flow graph in Google protocol buffer format, and translates it into LLVM bitcode. The generated bitcode is not optimized and will be very noisy with unnecessarily live variables. Unoptimized bitcode is useful for debugging translation errors, but before use this bitcode should be run through the LLVM `opt` tool.
More information on the syntax and usage of each tool is in the TOOLS document.
## CFG Recovery
The `bin_descend` tool performs recursive descent based control flow recovery on COFF objects and PE DLLs. The output is a serialized Google protocol buffer, defined in `CFG.proto`. This CFG is then used in by the translator to generate LLVM bitcode.
CFG recovery is performed using an IDAPython script, `mc-sema/bin_descend/get_cfg.py`. The output is a serialized Google protocol buffer, defined in `CFG.proto`. This CFG is then used in by the translator to generate LLVM bitcode.
The following is a description of the current (November, 2013) of the fields in the protocol.
@@ -190,7 +190,7 @@ The Module message represents all the recovered information about the input prog
### External Calls
Since external calls (e.g. calls to APIs or other compilation units) are not translated by mcsema, their semantics must be accurately known to reference them from translated code. The information needed about external calls is external name, calling convention, number of arguments, and whether or not the call returns. The `bin_descend` tool identifies information about external calls from a definition file specified by the `-func-map` argument. A default mapping, that includes the vast majority of the Windows API, is provided in `mc-sema/std_defs/std_defs.txt`.
Since external calls (e.g. calls to APIs or other compilation units) are not translated by mcsema, their semantics must be accurately known to reference them from translated code. The information needed about external calls is external name, calling convention, number of arguments, and whether or not the call returns. A default mapping, that includes the vast majority of the Windows API, is provided in `mc-sema/std_defs/std_defs.txt`.
## Translation
@@ -217,7 +217,7 @@ All functions referenced in the data section are assumed to be used as callbacks
## Using the bitcode
The bitcode output can be used as input to `opt` for optimization and to `llc` as input for object file generation. The demos in `mc-sema/tests` show how to use `bin_descend`, `cfg_to_bc`, `opt` and `llc` to take a COFF object, translate it, and link it with existing code.
The bitcode output can be used as input to `opt` for optimization and to `llc` as input for object file generation. The demos in `mc-sema/tests` show how to use `cfg_to_bc`, `opt` and `llc` to take a COFF object, translate it, and link it with existing code.
Prior to using any generated bitcode, it is recommended to run it through `opt` with the `-O3` optimization level.
-34
View File
@@ -96,37 +96,3 @@ add_subdirectory(bitcode_from_cfg)
add_subdirectory(binary_common)
add_subdirectory(bin_descend)
add_subdirectory(runtime)
if(MCSEMA_ENABLE_PIN_VALIDATOR)
find_package(Pin)
if(NOT PIN_FOUND AND NOT WIN32)
if(UNIX)
set(PIN_DOWNLOAD_URL https://software.intel.com/sites/landingpage/pintool/downloads/pin-2.14-67254-gcc.4.4.7-linux.tar.gz)
set(PIN_DOWNLOAD_HASH 792eaaa199e9deba84cde79858e93ffc)
endif(UNIX)
if(APPLE)
set(PIN_DOWNLOAD_URL https://software.intel.com/sites/landingpage/pintool/downloads/pin-2.14-67254-clang.5.1-mac.tar.gz)
set(PIN_DOWNLOAD_HASH 0f93c64484d039ceca828cd2909d321b)
endif(APPLE)
ExternalProject_add(Pin
URL ${PIN_DOWNLOAD_URL}
URL_MD5 ${PIN_DOWNLOAD_HASH}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
SOURCE_DIR pin
INSTALL_COMMAND ""
)
set(PIN_PATH ${CMAKE_CURRENT_BINARY_DIR}/pin)
set(PIN_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/pin/pin)
add_subdirectory(validator)
endif(NOT PIN_FOUND AND NOT WIN32)
if(WIN32 AND PIN_FOUND)
add_subdirectory(validator)
endif(WIN32 AND PIN_FOUND)
endif(MCSEMA_ENABLE_PIN_VALIDATOR)
+39 -97
View File
@@ -8,7 +8,8 @@
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the {organization} nor the names of its
@@ -67,10 +68,6 @@
#include "../common/LExcn.h"
#include "../common/Defaults.h"
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
using namespace llvm;
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
@@ -94,55 +91,14 @@ static cl::opt<bool> OutputModule("m", cl::desc("Output native module format"));
static cl::opt<bool> IgnoreUnsupported(
"ignore-unsupported", cl::desc("Ignore unsupported instructions"));
static cl::opt<bool> ShouldVerify(
"should-verify", cl::desc("Verify module after bitcode emission?"),
cl::init(true));
static void printVersion(void) {
std::cout << "0.6" << std::endl;
}
class block_label_writer {
private:
NativeFunctionPtr func;
public:
block_label_writer(NativeFunctionPtr f)
: func(f) {
return;
}
template<class VertexOrEdge>
void operator()(std::ostream &out, const VertexOrEdge &v) const {
NativeBlockPtr curB = this->func->block_from_id(v);
if (curB) {
std::string blockS = curB->print_block();
out << "[label=\"" << blockS << "\"]";
}
return;
}
};
static void doPrintModule(NativeModulePtr m) {
std::string pathBase = "./";
for (auto f : m->get_funcs()) {
std::string n = pathBase + to_string<uint64_t>(f->get_start(), std::hex)
+ ".dot";
std::ofstream out(n.c_str());
block_label_writer bgl(f);
CFG g = f->get_cfg();
write_graphviz(out, g, bgl);
}
return;
}
llvm::Module *createModuleForArch(std::string name, const std::string &triple) {
llvm::Module *M = new llvm::Module(name, llvm::getGlobalContext());
llvm::Triple TT = llvm::Triple(triple);
static llvm::Module *CreateModule(std::string name,
const std::string &triple) {
auto M = new llvm::Module(name, llvm::getGlobalContext());
llvm::Triple TT(triple);
M->setTargetTriple(triple);
std::string layout;
@@ -150,7 +106,9 @@ llvm::Module *createModuleForArch(std::string name, const std::string &triple) {
if (TT.getOS() == llvm::Triple::Win32) {
if (TT.getArch() == llvm::Triple::x86) {
layout =
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32";
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:"
"32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:"
"32:32-n8:16:32-S32";
} else if (TT.getArch() == llvm::Triple::x86_64) {
layout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
} else {
@@ -160,7 +118,9 @@ llvm::Module *createModuleForArch(std::string name, const std::string &triple) {
} else if (TT.getOS() == llvm::Triple::Linux) {
if (TT.getArch() == llvm::Triple::x86) {
layout =
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128";
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:"
"32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:"
"16:32-S128";
} else if (TT.getArch() == llvm::Triple::x86_64) {
// x86_64-linux-gnu
layout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128";
@@ -177,13 +137,13 @@ llvm::Module *createModuleForArch(std::string name, const std::string &triple) {
return M;
}
static VA findSymInModule(NativeModulePtr mod, const std::string &sym_name) {
static VA FindSymbolInModule(NativeModulePtr mod, const std::string &sym_name) {
for (auto &sym : mod->getEntryPoints()) {
if (sym.getName() == sym_name) {
return sym.getAddr();
}
}
return (VA)(-1);
return static_cast<VA>(-1);
}
int main(int argc, char *argv[]) {
@@ -202,9 +162,8 @@ int main(int argc, char *argv[]) {
std::string errstr;
std::cerr << "Looking up target..." << std::endl;
auto x86Target = llvm::TargetRegistry::lookupTarget(TargetTriple, errstr);
if (!x86Target) {
auto target = llvm::TargetRegistry::lookupTarget(TargetTriple, errstr);
if (!target) {
std::cerr
<< "Could not find target triple: " << TargetTriple << std::endl
<< "Error: " << errstr << "\n";
@@ -214,58 +173,39 @@ int main(int argc, char *argv[]) {
//reproduce NativeModule from CFG input argument
std::cerr << "Reading module ..." << std::endl;
try {
auto mod = readModule(InputFilename, ProtoBuff, std::list<VA>(), x86Target);
auto mod = ReadProtoBuf(InputFilename, TargetTriple, target);
if (!mod) {
std::cerr << "Could not process input module: " << InputFilename
<< std::endl;
<< std::endl;
return EXIT_FAILURE;
}
// set native module target
std::cerr << "Setting initial triples..." << std::endl;
mod->setTarget(x86Target);
mod->setTargetTriple(TargetTriple);
if ( !mod) {
if (!mod) {
std::cerr << "Unable to read module from CFG" << std::endl;
return EXIT_FAILURE;
}
if (OutputModule) {
doPrintModule(mod);
}
if (IgnoreUnsupported) {
ignoreUnsupportedInsts = true;
}
//now, convert it to an LLVM module
std::cerr << "Getting LLVM module..." << std::endl;
auto M = createModuleForArch(mod->name(), TargetTriple);
if ( !M) {
std::cerr << "Unable to get LLVM module" << std::endl;
return EXIT_FAILURE;
}
initRegStateStruct(M);
auto M = CreateModule(mod->name(), TargetTriple);
ArchInitRegStateStruct(M);
ArchInitAttachDetach(M);
initInstructionDispatch();
ArchInitInstructionDispatch();
std::cerr << "Converting to LLVM..." << std::endl;
if (!liftNativeCodeIntoModule(mod, M)) {
if (!LiftCodeIntoModule(mod, M)) {
std::cerr << "Failure to convert to LLVM module!" << std::endl;
return EXIT_FAILURE;
}
std::set<VA> entry_point_pcs;
for (const auto &entry_point_name : EntryPoints) {
std::cerr << "Adding entry point: " << entry_point_name << std::endl;
auto entry_pc = findSymInModule(mod, entry_point_name);
if ((VA)(-1) != entry_pc) {
std::cerr << entry_point_name << " is implemented by sub_" << std::hex
auto entry_pc = FindSymbolInModule(mod, entry_point_name);
if (entry_pc != static_cast<VA>(-1)) {
std::cerr << "Adding entry point: " << entry_point_name << std::endl
<< entry_point_name << " is implemented by sub_" << std::hex
<< entry_pc << std::endl;
if (!ArchAddEntryPointDriver(M, entry_point_name, entry_pc)) {
@@ -274,32 +214,34 @@ int main(int argc, char *argv[]) {
entry_point_pcs.insert(entry_pc);
} else {
llvm::errs() << "Could not find entry point: " << entry_point_name
<< "; aborting\n";
std::cerr << "Could not find entry point: " << entry_point_name
<< "; aborting" << std::endl;
return EXIT_FAILURE;
}
}
renameLiftedFunctions(mod, M, entry_point_pcs);
RenameLiftedFunctions(mod, M, entry_point_pcs);
// will abort if verification fails
if (ShouldVerify && llvm::verifyModule( *M, &errs())) {
std::cerr << "Could not verify module!\n";
if (llvm::verifyModule(*M, &errs())) {
std::cerr << "Could not verify module!" << std::endl;
return EXIT_FAILURE;
}
M->addModuleFlag(Module::Error, "Debug Info Version",
DEBUG_METADATA_VERSION);
M->addModuleFlag(Module::Error, "Dwarf Version", 3);
M->addModuleFlag(llvm::Module::Error, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION);
M->addModuleFlag(llvm::Module::Error, "Dwarf Version", 3);
std::string errorInfo;
llvm::tool_output_file Out(OutputFilename.c_str(), errorInfo,
sys::fs::F_None);
WriteBitcodeToFile(M, Out.os());
llvm::sys::fs::F_None);
llvm::WriteBitcodeToFile(M, Out.os());
Out.keep();
} catch (std::exception &e) {
std::cerr << "error: " << std::endl << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
+11 -23
View File
@@ -8,35 +8,23 @@
#include <string>
using namespace std;
using namespace llvm;
const char MCSEMA_ANNOT_STRING[] = "mcsema_real_eip";
const char * const kRealEIPAnnotation = "mcsema_real_eip";
void addAnnotation(llvm::Instruction *inst, VA addr) {
Constant *C = ConstantInt::get(Type::getInt64Ty(llvm::getGlobalContext()), addr);
MDNode *n = MDNode::get(llvm::getGlobalContext(), C);
inst->setMetadata(MCSEMA_ANNOT_STRING, n);
auto C = llvm::ConstantInt::get(
llvm::Type::getInt64Ty(llvm::getGlobalContext()), addr);
auto n = llvm::MDNode::get(llvm::getGlobalContext(), C);
inst->setMetadata(kRealEIPAnnotation, n);
}
bool getAnnotation(llvm::Instruction *inst, VA &its_eip) {
MDNode *metad = inst->getMetadata(MCSEMA_ANNOT_STRING);
if(metad == nullptr) {
return false;
}
Value *val = metad->getOperand(0);
if(val == nullptr) {
return false;
}
if (ConstantInt *ci = dyn_cast<ConstantInt>(val)) {
if (auto metad = inst->getMetadata(kRealEIPAnnotation)) {
if (auto val = metad->getOperand(0)) {
if (auto ci = llvm::dyn_cast<llvm::ConstantInt>(val)) {
its_eip = ci->getLimitedValue();
return true;
}
}
return false;
}
return false;
}
+5 -2
View File
@@ -27,11 +27,14 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <cstdint>
#include <memory>
#include "llvm/IR/Module.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
typedef uint64_t VA;
void addAnnotation(llvm::Instruction *inst, VA addr);
+42 -44
View File
@@ -162,49 +162,49 @@ static void LinuxAddPushJumpStub(llvm::Module *M, llvm::Function *F,
M->appendModuleInlineAsm(as.str());
}
std::string ArchNameMcsemaCall(const std::string &name) {
std::string ArchNameMcSemaCall(const std::string &name) {
return "__mcsema_" + name;
}
static std::string WindowsDecorateName(llvm::Function *F, const std::string &name) {
static std::string WindowsDecorateName(llvm::Function *F,
const std::string &name) {
// 64-bit doesn't mangle
Module *M = F->getParent();
if(64 == ArchPointerSize(M)) {
return name;
Module *M = F->getParent();
if (64 == ArchPointerSize(M)) {
return name;
}
switch (F->getCallingConv()) {
case CallingConv::C:
return "_" + name;
break;
case CallingConv::X86_StdCall: {
std::stringstream as;
int argc = F->arg_size();
as << "_" << name << "@" << argc * 4;
return as.str();
}
switch(F->getCallingConv())
{
case CallingConv::C:
return "_" + name;
break;
case CallingConv::X86_StdCall:
{
std::stringstream as;
int argc = F->arg_size();
as << "_" << name << "@" << argc*4;
return as.str();
}
break;
case CallingConv::X86_FastCall:
{
std::stringstream as;
int argc = F->arg_size();
as << "@" << name << "@" << argc*4;
return as.str();
}
break;
default:
TASSERT(false, "Unsupported Calling Convention for 32-bit Windows");
break;
}
return "";
break;
case CallingConv::X86_FastCall: {
std::stringstream as;
int argc = F->arg_size();
as << "@" << name << "@" << argc * 4;
return as.str();
}
break;
default:
TASSERT(false, "Unsupported Calling Convention for 32-bit Windows")
;
break;
}
return "";
}
static void WindowsAddPushJumpStub(bool decorateStub, llvm::Module *M, llvm::Function *F,
llvm::Function *W, const char *stub_handler) {
static void WindowsAddPushJumpStub(bool decorateStub, llvm::Module *M,
llvm::Function *F, llvm::Function *W,
const char *stub_handler) {
auto stub_name = W->getName().str();
auto stubbed_func_name = F->getName().str();
@@ -405,17 +405,15 @@ bool shouldSubtractImageBase(llvm::Module *M) {
llvm::Value *doSubtractImageBaseInt(llvm::Value *original,
llvm::BasicBlock *block) {
llvm::Module *M = block->getParent()->getParent();
llvm::Value *ImageBase = archGetImageBase(M);
auto M = block->getParent()->getParent();
auto ImageBase = archGetImageBase(M);
// convert image base pointer to int
llvm::Value *ImageBase_int = new llvm::PtrToIntInst(
ImageBase, llvm::Type::getIntNTy(block->getContext(), 64), "", block);
auto ImageBase_int = new llvm::PtrToIntInst(
ImageBase, llvm::Type::getIntNTy(block->getContext(), ArchPointerSize(M)),
"", block);
// do the subtraction
llvm::Value *data_v = BinaryOperator::CreateSub(original, ImageBase_int, "",
block);
return data_v;
return llvm::BinaryOperator::CreateSub(original, ImageBase_int, "", block);
}
+3 -3
View File
@@ -1,14 +1,14 @@
#ifndef ARCHOPS_H
#define ARCHOPS_H
#include <cstdint>
#include "llvm/IR/Value.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/ADT/Triple.h"
#include <boost/cstdint.hpp>
typedef uint64_t VA;
enum SystemArchType {
@@ -44,7 +44,7 @@ SystemArchType SystemArch(llvm::Module *M);
PointerSize ArchPointerSize(llvm::Module *M);
std::string ArchNameMcsemaCall(const std::string &name);
std::string ArchNameMcSemaCall(const std::string &name);
template <int width>
+133 -93
View File
@@ -1,131 +1,171 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EXTERNALS_H
#define _EXTERNALS_H
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
#include <cstdint>
#include <string>
using boost::int8_t;
#include <memory>
class ExternalRef {
public:
ExternalRef(const std::string &sn)
: symbolName(sn),
weak(false) {}
public:
ExternalRef(const std::string &sn): symbolName(sn) {};
virtual std::string getSymbolName(void) { return this->symbolName; }
virtual void setWeak(bool w) { this->weak = w; }
virtual bool isWeak(void) { return this->weak; }
virtual ~ExternalRef() {};
virtual const std::string &getSymbolName(void) {
return this->symbolName;
}
protected:
std::string symbolName;
bool weak;
virtual void setWeak(bool w) {
this->weak = w;
}
virtual bool isWeak(void) {
return this->weak;
}
virtual ~ExternalRef() {}
protected:
std::string symbolName;
bool weak;
};
class ExternalDataRef : public ExternalRef {
protected:
size_t dataSize;
protected:
size_t dataSize;
public:
public:
ExternalDataRef(const std::string &name): dataSize(0), ExternalRef(name)
{
}
ExternalDataRef(const std::string &name, size_t dtsz) : dataSize(dtsz), ExternalRef(name)
{
// empty constructor
}
ExternalDataRef(const std::string &name)
: dataSize(0),
ExternalRef(name) {}
void setDataSize(size_t newsize) { this->dataSize = newsize; }
size_t getDataSize() { return this->dataSize; }
ExternalDataRef(const std::string &name, size_t dtsz)
: dataSize(dtsz),
ExternalRef(name) {}
void setDataSize(size_t newsize) {
this->dataSize = newsize;
}
size_t getDataSize() {
return this->dataSize;
}
};
class ExternalCodeRef : public ExternalRef {
public:
enum CallingConvention {
CallerCleanup,
CalleeCleanup,
FastCall,
X86_64_SysV,
X86_64_Win64,
McsemaCall
};
public:
enum CallingConvention {
CallerCleanup,
CalleeCleanup,
FastCall,
X86_64_SysV,
X86_64_Win64,
McsemaCall
};
enum ReturnType {
Unknown,
VoidTy,
IntTy,
NoReturn
};
enum ReturnType {
Unknown,
VoidTy,
IntTy,
NoReturn
};
int8_t getNumArgs(void) { return this->numArgs; }
ReturnType getReturnType(void) { return this->ret; }
CallingConvention getCallingConvention(void) { return this->conv; }
int8_t getNumArgs(void) {
return this->numArgs;
}
void setReturnType(ReturnType r) { this->ret = r; }
ReturnType getReturnType(void) {
return this->ret;
}
std::string getFunctionSignature(void) { return this->funcSign; }
CallingConvention getCallingConvention(void) {
return this->conv;
}
ExternalCodeRef(const std::string &fn, int8_t d, CallingConvention c, ReturnType r, const std::string &sign) :
numArgs(d),
conv(c),
ret(r), ExternalRef(fn), funcSign(sign) { }
void setReturnType(ReturnType r) {
this->ret = r;
}
ExternalCodeRef(const std::string &fn, int8_t d, CallingConvention c, ReturnType r) :
numArgs(d),
conv(c),
ret(r), ExternalRef(fn), funcSign("") { }
const std::string &getFunctionSignature(void) {
return this->funcSign;
}
ExternalCodeRef(const std::string &fn, int8_t d, CallingConvention c) :
numArgs(d),
conv(c),
ret(Unknown), ExternalRef(fn), funcSign("") { }
ExternalCodeRef(const std::string &fn, int d, CallingConvention c,
ReturnType r, const std::string &sign)
: numArgs(d),
conv(c),
ret(r),
ExternalRef(fn),
funcSign(sign) {}
ExternalCodeRef(const std::string &fn, int8_t d) : numArgs(d),
conv(CallerCleanup),
ret(Unknown), ExternalRef(fn), funcSign("") { }
ExternalCodeRef(const std::string &fn, int d, CallingConvention c,
ReturnType r)
: numArgs(d),
conv(c),
ret(r),
ExternalRef(fn),
funcSign("") {}
ExternalCodeRef(const std::string &fn) : numArgs(-1),
conv(CallerCleanup),
ret(Unknown), ExternalRef(fn), funcSign("") { }
ExternalCodeRef(const std::string &fn, int d, CallingConvention c)
: numArgs(d),
conv(c),
ret(Unknown),
ExternalRef(fn),
funcSign("") {}
protected:
ExternalCodeRef(const std::string &fn, int d)
: numArgs(d),
conv(CallerCleanup),
ret(Unknown),
ExternalRef(fn),
funcSign("") {}
int8_t numArgs;
CallingConvention conv;
ReturnType ret;
std::string funcSign;
ExternalCodeRef(const std::string &fn)
: numArgs(-1),
conv(CallerCleanup),
ret(Unknown),
ExternalRef(fn),
funcSign("") {}
protected:
int numArgs;
CallingConvention conv;
ReturnType ret;
std::string funcSign;
};
typedef boost::shared_ptr<ExternalCodeRef> ExternalCodeRefPtr;
typedef boost::shared_ptr<ExternalDataRef> ExternalDataRefPtr;
typedef ExternalCodeRef *ExternalCodeRefPtr;
typedef ExternalDataRef *ExternalDataRefPtr;
#endif
+1 -1
View File
@@ -50,7 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
DispatchMap translationDispatchMap;
bool initInstructionDispatch() {
bool ArchInitInstructionDispatch(void) {
FPU_populateDispatchMap(translationDispatchMap);
MOV_populateDispatchMap(translationDispatchMap);
+29 -8
View File
@@ -40,12 +40,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "peToCFG.h"
#include "raiseX86.h"
typedef InstTransResult(*TranslationFuncPtr)(NativeModulePtr natM, llvm::BasicBlock *&block, InstPtr ip, llvm::MCInst &inst);
struct TranslationContext {
NativeModulePtr natM;
NativeFunctionPtr natF;
NativeBlockPtr natB;
NativeInstPtr natI;
llvm::Module *M;
llvm::Function *F;
std::map<VA, llvm::BasicBlock *> va_to_bb;
};
typedef InstTransResult(*TranslationFuncPtr)(TranslationContext &, llvm::BasicBlock *&);
typedef std::map<unsigned, TranslationFuncPtr> DispatchMap;
extern DispatchMap translationDispatchMap;
bool initInstructionDispatch();
bool ArchInitInstructionDispatch(void);
#define OP(x) inst.getOperand(x)
@@ -54,12 +64,16 @@ bool initInstructionDispatch();
ADDR_NOREF_IMPL<32>(natM, block, x, ip, inst) :\
ADDR_NOREF_IMPL<64>(natM, block, x, ip, inst)
#define CREATE_BLOCK(nm, b) BasicBlock *block_ ## nm = BasicBlock::Create((b)->getContext(), #nm, (b)->getParent())
#define CREATE_BLOCK(nm, b) auto block_ ## nm = llvm::BasicBlock::Create((b)->getContext(), #nm, (b)->getParent())
#define MEM_REFERENCE(which) MEM_AS_DATA_REF(block, natM, inst, ip, which)
#define GENERIC_TRANSLATION_MI(NAME, NOREFS, MEMREF, IMMREF, TWOREFS) static InstTransResult translate_ ## NAME (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst) {\
#define GENERIC_TRANSLATION_MI(NAME, NOREFS, MEMREF, IMMREF, TWOREFS) \
static InstTransResult translate_ ## NAME (TranslationContext &ctx, llvm::BasicBlock *&block) {\
InstTransResult ret;\
Function *F = block->getParent(); \
auto natM = ctx.natM; \
Function *F = ctx.F; \
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
if( ip->has_mem_reference && ip->has_imm_reference) {\
TWOREFS; \
} else if( ip->has_mem_reference ) { \
@@ -73,9 +87,12 @@ bool initInstructionDispatch();
}
#define GENERIC_TRANSLATION_REF(NAME, NOREFS, HASREF) static InstTransResult translate_ ## NAME (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst) {\
#define GENERIC_TRANSLATION_REF(NAME, NOREFS, HASREF) static InstTransResult translate_ ## NAME (TranslationContext &ctx, BasicBlock *&block) {\
InstTransResult ret;\
Function *F = block->getParent(); \
auto natM = ctx.natM; \
Function *F = ctx.F; \
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
if( ip->has_mem_reference || ip->has_imm_reference || ip->has_external_ref() ) {\
HASREF;\
} else {\
@@ -84,8 +101,12 @@ bool initInstructionDispatch();
return ContinueBlock;\
}
#define GENERIC_TRANSLATION(NAME, NOREFS) static InstTransResult translate_ ## NAME (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst) {\
#define GENERIC_TRANSLATION(NAME, NOREFS) static InstTransResult translate_ ## NAME (TranslationContext &ctx, BasicBlock *&block) {\
InstTransResult ret;\
auto natM = ctx.natM; \
Function *F = ctx.F; \
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
ret = NOREFS;\
return ret;\
}
+319 -404
View File
@@ -1,31 +1,31 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <vector>
#include <unordered_set>
#include <string>
@@ -48,439 +48,354 @@ using namespace llvm;
extern llvm::PointerType *g_PRegStruct;
// convert a jump table to a data section of symbols
static DataSection* tableToDataSection(VA new_base, const MCSJumpTable& jt) {
DataSection *ds = new DataSection();
const vector<VA>& entries = jt.getJumpTable();
VA curAddr = new_base;
static DataSection* tableToDataSection(VA new_base, const MCSJumpTable &jt) {
auto ds = new DataSection();
const auto &entries = jt.getJumpTable();
VA curAddr = new_base;
for(vector<VA>::const_iterator itr = entries.begin();
itr != entries.end();
itr++)
{
string sub_name = "sub_" + to_string<VA>(*itr, hex);
DataSectionEntry dse(curAddr, sub_name);
ds->addEntry(dse);
curAddr += 4;
}
for (auto va : entries) {
std::string sub_name = "sub_" + to_string<VA>(va, hex);
DataSectionEntry dse(curAddr, sub_name);
ds->addEntry(dse);
curAddr += 4;
}
return ds;
return ds;
}
// convert an index table to a data blob
static DataSection* tableToDataSection(VA new_base, const JumpIndexTable& jit) {
DataSection *ds = new DataSection();
const vector<uint8_t>& entries = jit.getJumpIndexTable();
DataSectionEntry dse(new_base, entries);
ds->addEntry(dse);
return ds;
static DataSection *tableToDataSection(VA new_base, const JumpIndexTable &jit) {
auto ds = new DataSection();
const auto &entries = jit.getJumpIndexTable();
DataSectionEntry dse(new_base, entries);
ds->addEntry(dse);
return ds;
}
template <class T>
static bool addTableDataSection(NativeModulePtr natMod,
Module *M, VA &newVA, const T& table)
{
template <typename T>
static bool addTableDataSection(TranslationContext &ctx,
VA &newVA, const T &table) {
auto natMod = ctx.natM;
auto M = ctx.M;
list<DataSection> &globaldata = natMod->getData();
list<DataSection>::const_iterator git = globaldata.begin();
// ensure we make this the last data section
newVA = 0;
while( git != globaldata.end() ) {
const DataSection &dt = *git;
uint64_t extent = dt.getBase() + dt.getSize();
if(newVA < extent) {
newVA = extent;
}
git++;
// ensure we make this the last data section
newVA = 0;
for (const auto &dt : natMod->getData()) {
uint64_t extent = dt.getBase() + dt.getSize();
if (newVA < extent) {
newVA = extent;
}
}
// skip a few
newVA += 4;
// skip a few
newVA += 4;
// create a new data section from the table
DataSection *ds = tableToDataSection(newVA, table);
// add to global data section list
globaldata.push_back(*ds);
// create a new data section from the table
DataSection *ds = tableToDataSection(newVA, table);
// create the GlobalVariable
string bufferName = "data_0x" + to_string<VA>(newVA, hex);
StructType *st_opaque = StructType::create(M->getContext());
GlobalVariable *gv = new GlobalVariable(*M,
st_opaque,
true,
GlobalVariable::InternalLinkage,
NULL,
bufferName);
// add to global data section list
natMod->addDataSection(*ds);
vector<Type*> data_section_types;
vector<Constant*> secContents;
// create the GlobalVariable
std::string bufferName = "data_0x" + to_string<VA>(newVA, std::hex);
auto st_opaque = llvm::StructType::create(M->getContext());
auto gv = new llvm::GlobalVariable( *M, st_opaque, true,
llvm::GlobalVariable::InternalLinkage,
NULL,
bufferName);
dataSectionToTypesContents(globaldata,
*ds,
M,
secContents,
data_section_types,
false);
std::vector<llvm::Type *> data_section_types;
std::vector<llvm::Constant *> secContents;
dataSectionToTypesContents(natMod->getData(), *ds, M, secContents,
data_section_types, false);
st_opaque->setBody(data_section_types, true);
Constant *cst = ConstantStruct::get(st_opaque, secContents);
gv->setAlignment(4);
gv->setInitializer(cst);
st_opaque->setBody(data_section_types, true);
auto cst = llvm::ConstantStruct::get(st_opaque, secContents);
gv->setAlignment(4);
gv->setInitializer(cst);
return true;
return true;
}
bool addJumpTableDataSection(NativeModulePtr natMod,
Module *M,
VA &newVA,
const MCSJumpTable& table)
{
return addTableDataSection<MCSJumpTable>(natMod, M, newVA, table);
}
bool addJumpTableDataSection(TranslationContext &ctx, VA &newVA,
const MCSJumpTable &table) {
return addTableDataSection<MCSJumpTable>(ctx, newVA, table);
}
bool addJumpIndexTableDataSection(NativeModulePtr natMod,
Module *M,
VA &newVA,
const JumpIndexTable& table)
{
return addTableDataSection<JumpIndexTable>(natMod, M, newVA, table);
bool addJumpIndexTableDataSection(TranslationContext &ctx, VA &newVA, const JumpIndexTable &table) {
return addTableDataSection<JumpIndexTable>(ctx, newVA, table);
}
void doJumpTableViaData(
BasicBlock *& block,
Value *fptr,
const int bitness)
{
Function *ourF = block->getParent();
//make the call, the only argument should be our parents arguments
TASSERT(ourF->arg_size() == 1, "");
void doJumpTableViaData(llvm::BasicBlock *&block, llvm::Value *fptr,
const int bitness) {
auto ourF = block->getParent();
//make the call, the only argument should be our parents arguments
TASSERT(ourF->arg_size() == 1, "");
if(!fptr->getType()->isPtrOrPtrVectorTy()) {
Module *M = ourF->getParent();
// get mem address
std::vector<Type *> args;
args.push_back(g_PRegStruct);
Type *returnTy = Type::getVoidTy(M->getContext());
FunctionType *FT = FunctionType::get(returnTy, args, false);
PointerType *FptrTy = PointerType::get(FT, 0);
fptr = new IntToPtrInst(fptr, FptrTy, "", block);
}
std::vector<Value*> subArgs;
subArgs.push_back(ourF->arg_begin());
CallInst *c = CallInst::Create(fptr, subArgs, "", block);
}
void doJumpTableViaData(
NativeModulePtr natM,
BasicBlock *& block,
InstPtr ip,
MCInst &inst,
const int bitness)
{
Value *addr = MEM_REFERENCE(0);
//doJumpTableViaData(block, addr, bitness);
llvm::errs() << __FUNCTION__ << ": Doing jump table via data\n";
Function *ourF = block->getParent();
Module *M = ourF->getParent();
if (!fptr->getType()->isPtrOrPtrVectorTy()) {
auto M = ourF->getParent();
// get mem address
std::vector<Type *> args;
std::vector<llvm::Type *> args;
args.push_back(g_PRegStruct);
Type *returnTy = Type::getVoidTy(M->getContext());
FunctionType *FT = FunctionType::get(returnTy, args, false);
PointerType *FptrTy = PointerType::get(FT, 0);
PointerType *Fptr2Ty = PointerType::get(FptrTy, 0);
Value *func_addr = CastInst::CreatePointerCast(addr, Fptr2Ty, "", block);
// read in entry from table
Instruction *new_func = noAliasMCSemaScope(new LoadInst(func_addr, "", block));
doJumpTableViaData(block, new_func, bitness);
auto returnTy = llvm::Type::getVoidTy(M->getContext());
auto FT = llvm::FunctionType::get(returnTy, args, false);
auto FptrTy = llvm::PointerType::get(FT, 0);
fptr = new llvm::IntToPtrInst(fptr, FptrTy, "", block);
}
std::vector<llvm::Value *> subArgs;
subArgs.push_back(ourF->arg_begin());
llvm::CallInst::Create(fptr, subArgs, "", block);
}
template <int bitness>
static void doJumpTableViaSwitch(
NativeModulePtr natM,
BasicBlock *& block,
InstPtr ip,
MCInst &inst)
{
void doJumpTableViaData(TranslationContext &ctx, llvm::BasicBlock *&block,
const int bitness) {
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto natM = ctx.natM;
llvm::errs() << __FUNCTION__ << ": Doing jumpt table via switch\n";
Function *F = block->getParent();
Module *M = F->getParent();
// we know this conforms to
// jmp [reg*4+displacement]
llvm::Value *addr = MEM_REFERENCE(0);
//doJumpTableViaData(block, addr, bitness);
// sanity check
const MCOperand& scale = OP(1);
const MCOperand& index = OP(2);
llvm::errs() << __FUNCTION__ << ": Doing jump table via data\n";
auto ourF = block->getParent();
auto M = ourF->getParent();
// get mem address
std::vector<llvm::Type *> args;
args.push_back(g_PRegStruct);
auto returnTy = llvm::Type::getVoidTy(M->getContext());
auto FT = llvm::FunctionType::get(returnTy, args, false);
TASSERT(index.isReg(), "Conformant jump tables need index to be a register");
TASSERT(scale.isImm() && scale.getImm() == (bitness/8), "Conformant jump tables have scale == 4");
auto FptrTy = llvm::PointerType::get(FT, 0);
auto Fptr2Ty = llvm::PointerType::get(FptrTy, 0);
auto func_addr = llvm::CastInst::CreatePointerCast(addr, Fptr2Ty, "", block);
MCSJumpTablePtr jmpptr = ip->get_jump_table();
// to ensure no negative entries
Value *adjustment = CONST_V<bitness>(block, jmpptr->getInitialEntry());
Value *reg_val = R_READ<bitness>(block, index.getReg());
Value *real_index =
BinaryOperator::Create(Instruction::Add, adjustment, reg_val, "", block);
// create a default block that just traps
BasicBlock *defaultBlock =
BasicBlock::Create(block->getContext(), "", block->getParent(), 0);
Function *trapFn = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapFn, "", defaultBlock);
ReturnInst::Create(defaultBlock->getContext(), defaultBlock);
// end default block
const std::vector<VA> &jmpblocks = jmpptr->getJumpTable();
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
real_index,
defaultBlock,
jmpblocks.size(),
block);
// populate switch
int myindex = 0;
for(std::vector<VA>::const_iterator itr = jmpblocks.begin();
itr != jmpblocks.end();
itr++)
{
std::string bbname = "block_0x"+to_string<VA>(*itr, std::hex);
BasicBlock *toBlock = bbFromStrName(bbname, F);
TASSERT(toBlock != NULL, "Could not find block: "+bbname);
theSwitch->addCase(CONST_V<bitness>(block, myindex), toBlock);
++myindex;
}
// read in entry from table
auto new_func = noAliasMCSemaScope(new llvm::LoadInst(func_addr, "", block));
doJumpTableViaData(block, new_func, bitness);
}
void doJumpTableViaSwitch(
NativeModulePtr natM,
BasicBlock *& block,
InstPtr ip,
MCInst &inst,
const int bitness)
{
switch(bitness)
{
case 32:
return doJumpTableViaSwitch<32>(natM, block, ip, inst);
case 64:
return doJumpTableViaSwitch<64>(natM, block, ip, inst);
default:
TASSERT(false, "Invalid bitness!");
}
template<int bitness>
static void doJumpTableViaSwitch(TranslationContext &ctx, llvm::BasicBlock *&block) {
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto natM = ctx.natM;
llvm::errs() << __FUNCTION__ << ": Doing jump table via switch\n";
auto F = block->getParent();
auto M = F->getParent();
// we know this conforms to
// jmp [reg*4+displacement]
// sanity check
const auto &scale = OP(1);
const auto &index = OP(2);
TASSERT(index.isReg(), "Conformant jump tables need index to be a register");
TASSERT(scale.isImm() && scale.getImm() == (bitness / 8),
"Conformant jump tables have scale == 4");
MCSJumpTablePtr jmpptr = ip->get_jump_table();
// to ensure no negative entries
llvm::Value *adjustment = CONST_V<bitness>(block, jmpptr->getInitialEntry());
llvm::Value *reg_val = R_READ<bitness>(block, index.getReg());
llvm::Value *real_index = llvm::BinaryOperator::Create(llvm::Instruction::Add,
adjustment, reg_val,
"", block);
// create a default block that just traps
auto defaultBlock = llvm::BasicBlock::Create(block->getContext(), "",
block->getParent(), 0);
auto trapFn = llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap);
llvm::CallInst::Create(trapFn, "", defaultBlock);
llvm::ReturnInst::Create(defaultBlock->getContext(), defaultBlock);
// end default block
const auto &jmpblocks = jmpptr->getJumpTable();
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(real_index, defaultBlock,
jmpblocks.size(), block);
// populate switch
int myindex = 0;
for (auto jmp_block_va : jmpblocks) {
BasicBlock *toBlock = ctx.va_to_bb[jmp_block_va];
TASSERT(toBlock != NULL, "Could not find block");
theSwitch->addCase(CONST_V<bitness>(block, myindex), toBlock);
++myindex;
}
}
template <int bitness>
static void doJumpTableViaSwitchReg(
BasicBlock *& block,
InstPtr ip,
Value *regVal,
BasicBlock *&default_block)
{
llvm::errs() << __FUNCTION__ << ": Doing jumpt table via switch(reg)\n";
Function *F = block->getParent();
Module *M = F->getParent();
MCSJumpTablePtr jmpptr = ip->get_jump_table();
// create a default block that just traps
default_block =
BasicBlock::Create(block->getContext(), "", block->getParent(), 0);
// end default block
const std::vector<VA> &jmpblocks = jmpptr->getJumpTable();
std::unordered_set<VA> uniq_blocks(jmpblocks.begin(), jmpblocks.end());
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
regVal,
default_block,
uniq_blocks.size(),
block);
// populate switch
for(auto blockVA : uniq_blocks)
{
std::string bbname = "block_0x"+to_string<VA>(blockVA, std::hex);
BasicBlock *toBlock = bbFromStrName(bbname, F);
llvm::errs() << __FUNCTION__ << ": Mapping from " << to_string<VA>(blockVA, std::hex) << " => " << bbname << "\n";
TASSERT(toBlock != NULL, "Could not find block: "+bbname);
ConstantInt *thecase = CONST_V<bitness>(block, blockVA);
theSwitch->addCase(
thecase,
toBlock);
}
void doJumpTableViaSwitch(TranslationContext &ctx, llvm::BasicBlock *&block, int bitness) {
switch (bitness) {
case 32:
doJumpTableViaSwitch<32>(ctx, block);
break;
case 64:
doJumpTableViaSwitch<64>(ctx, block);
break;
default:
TASSERT(false, "Invalid bitness!")
;
}
}
void doJumpOffsetTableViaSwitchReg(
BasicBlock *& block,
InstPtr ip,
Value *regVal,
BasicBlock *&default_block,
Value *data_location,
MCSOffsetTablePtr ot_ptr)
{
template<int bitness>
static void doJumpTableViaSwitchReg(TranslationContext &ctx,
llvm::BasicBlock *&block,
llvm::Value *regVal,
llvm::BasicBlock *&default_block) {
llvm::errs() << __FUNCTION__ << ": Doing jump offset table via switch(reg)\n";
Function *F = block->getParent();
llvm::errs() << __FUNCTION__ << ": Doing jump table via switch(reg)\n";
// create a default block that just traps
default_block =
BasicBlock::Create(block->getContext(), "", block->getParent(), 0);
// end default block
auto F = block->getParent();
auto M = F->getParent();
auto ip = ctx.natI;
auto jmpptr = ip->get_jump_table();
const std::vector< std::pair<VA,VA> > &offset_dest = ot_ptr->getConstTable();
std::unordered_map<VA,VA> uniq_blocks;
for (auto const & blockpair : offset_dest) {
uniq_blocks[blockpair.first] = blockpair.second;
}
// create a default block that just traps
default_block = BasicBlock::Create(block->getContext(), "",
block->getParent(), 0);
// end default block
// switch on the offset, not the memory value
Value *switch_val = BinaryOperator::CreateSub(regVal, data_location, "", block);
switch_val = BinaryOperator::CreateAnd(switch_val, CONST_V<64>(block, 0xFFFFFFFF), "", block);
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
switch_val,
default_block,
uniq_blocks.size(),
block);
const std::vector<VA> &jmpblocks = jmpptr->getJumpTable();
std::unordered_set<VA> uniq_blocks(jmpblocks.begin(), jmpblocks.end());
// populate switch
for(const auto & entry : uniq_blocks)
{
std::string bbname = "block_0x"+to_string<VA>(entry.second, std::hex);
BasicBlock *toBlock = bbFromStrName(bbname, F);
llvm::errs() << __FUNCTION__ << ": Mapping from " << to_string<VA>(entry.first, std::hex) << " => " << bbname << "\n";
TASSERT(toBlock != NULL, "Could not find block: "+bbname);
ConstantInt *thecase = CONST_V<64>(block, entry.first);
theSwitch->addCase(
thecase,
toBlock);
}
// create a switch inst
auto theSwitch = llvm::SwitchInst::Create(regVal, default_block,
uniq_blocks.size(), block);
// populate switch
for (auto blockVA : uniq_blocks) {
auto toBlock = ctx.va_to_bb[blockVA];
TASSERT(toBlock != NULL, "Could not find block!");
auto thecase = CONST_V<bitness>(block, blockVA);
theSwitch->addCase(thecase, toBlock);
}
}
void doJumpTableViaSwitchReg(
BasicBlock *& block,
InstPtr ip,
Value *regVal,
BasicBlock *&default_block,
const int bitness)
{
switch(bitness)
{
case 32:
return doJumpTableViaSwitchReg<32>(block, ip, regVal, default_block);
case 64:
return doJumpTableViaSwitchReg<64>(block, ip, regVal, default_block);
default:
TASSERT(false, "Invalid bitness!");
}
void doJumpOffsetTableViaSwitchReg(TranslationContext &ctx, llvm::BasicBlock *&block,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
llvm::Value *data_location,
MCSOffsetTablePtr ot_ptr) {
auto ip = ctx.natI;
llvm::errs() << __FUNCTION__ << ": Doing jump offset table via switch(reg)\n";
auto F = block->getParent();
// create a default block that just traps
default_block = llvm::BasicBlock::Create(block->getContext(), "",
block->getParent(), 0);
// end default block
const auto &offset_dest = ot_ptr->getConstTable();
std::unordered_map<VA, VA> uniq_blocks;
for (auto const &blockpair : offset_dest) {
uniq_blocks[blockpair.first] = blockpair.second;
}
// switch on the offset, not the memory value
llvm::Value *switch_val = llvm::BinaryOperator::CreateSub(regVal,
data_location, "",
block);
switch_val = llvm::BinaryOperator::CreateAnd(switch_val,
CONST_V<64>(block, 0xFFFFFFFF),
"", block);
// create a switch inst
auto theSwitch = llvm::SwitchInst::Create(switch_val, default_block,
uniq_blocks.size(), block);
// populate switch
for (const auto &entry : uniq_blocks) {
auto toBlock = ctx.va_to_bb[entry.second];
TASSERT(toBlock != NULL, "Could not find block!");
auto thecase = CONST_V<64>(block, entry.first);
theSwitch->addCase(thecase, toBlock);
}
}
static BasicBlock *emitJumpIndexWrite(
Function *F,
uint8_t idx_val,
unsigned dest_reg,
BasicBlock *contBlock
)
{
// create new block
BasicBlock *writeBlock =
BasicBlock::Create(F->getContext(), "", F, 0);
// write index to destination register
R_WRITE<32>(writeBlock, dest_reg, CONST_V<32>(writeBlock, idx_val));
// jump to continue block
BranchInst::Create(contBlock, writeBlock);
return writeBlock;
void doJumpTableViaSwitchReg(TranslationContext &ctx, llvm::BasicBlock *&block,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
const int bitness) {
switch (bitness) {
case 32:
return doJumpTableViaSwitchReg<32>(ctx, block, regVal, default_block);
case 64:
return doJumpTableViaSwitchReg<64>(ctx, block, regVal, default_block);
default:
TASSERT(false, "Invalid bitness!")
;
}
}
void doJumpIndexTableViaSwitch(
BasicBlock *&block,
InstPtr ip)
{
Function *F = block->getParent();
Module *M = F->getParent();
// we know this conforms to
// movzx reg32, [base+disp]
static llvm::BasicBlock *emitJumpIndexWrite(llvm::Function *F, uint8_t idx_val,
unsigned dest_reg,
llvm::BasicBlock *contBlock) {
// create new block
auto writeBlock = llvm::BasicBlock::Create(F->getContext(), "", F, 0);
// sanity check
const MCInst &inst = ip->get_inst();
const MCOperand& dest = OP(0);
const MCOperand& base = OP(1);
// write index to destination register
R_WRITE<32>(writeBlock, dest_reg, CONST_V<32>(writeBlock, idx_val));
TASSERT(base.isReg(), "Conformant jump index tables need base to be a register");
TASSERT(dest.isReg(), "Conformant jump index tables need to write to a register");
// jump to continue block
llvm::BranchInst::Create(contBlock, writeBlock);
JumpIndexTablePtr idxptr = ip->get_jump_index_table();
// to ensure no negative entries
Value *adjustment = CONST_V<32>(block, idxptr->getInitialEntry());
Value *reg_val = R_READ<32>(block, base.getReg());
Value *real_index =
BinaryOperator::Create(Instruction::Add, adjustment, reg_val, "", block);
BasicBlock *continueBlock =
BasicBlock::Create(block->getContext(), "", F, 0);
// create a default block that just traps
BasicBlock *defaultBlock =
BasicBlock::Create(block->getContext(), "", F, 0);
Function *trapFn = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapFn, "", defaultBlock);
BranchInst::Create(continueBlock, defaultBlock);
// end default block
const std::vector<uint8_t> &idxblocks = idxptr->getJumpIndexTable();
// create a switch inst
SwitchInst *theSwitch = SwitchInst::Create(
real_index,
defaultBlock,
idxblocks.size(),
block);
// populate switch
int myindex = 0;
for(std::vector<uint8_t>::const_iterator itr = idxblocks.begin();
itr != idxblocks.end();
itr++)
{
BasicBlock *writeBl = emitJumpIndexWrite(F, *itr, dest.getReg(), continueBlock );
theSwitch->addCase(CONST_V<32>(block, myindex), writeBl);
++myindex;
}
// new block to write to is continue block
block = continueBlock;
return writeBlock;
}
void doJumpIndexTableViaSwitch(llvm::BasicBlock *&block, NativeInstPtr ip) {
auto F = block->getParent();
auto M = F->getParent();
// we know this conforms to
// movzx reg32, [base+disp]
// sanity check
const auto &inst = ip->get_inst();
const auto &dest = OP(0);
const auto &base = OP(1);
TASSERT(base.isReg(),
"Conformant jump index tables need base to be a register");
TASSERT(dest.isReg(),
"Conformant jump index tables need to write to a register");
JumpIndexTablePtr idxptr = ip->get_jump_index_table();
// to ensure no negative entries
llvm::Value *adjustment = CONST_V<32>(block, idxptr->getInitialEntry());
llvm::Value *reg_val = R_READ<32>(block, base.getReg());
llvm::Value *real_index = llvm::BinaryOperator::Create(llvm::Instruction::Add,
adjustment, reg_val,
"", block);
auto continueBlock = llvm::BasicBlock::Create(block->getContext(), "", F, 0);
// create a default block that just traps
auto defaultBlock = llvm::BasicBlock::Create(block->getContext(), "", F, 0);
auto trapFn = Intrinsic::getDeclaration(M, llvm::Intrinsic::trap);
llvm::CallInst::Create(trapFn, "", defaultBlock);
llvm::BranchInst::Create(continueBlock, defaultBlock);
// end default block
const auto &idxblocks = idxptr->getJumpIndexTable();
// create a switch inst
auto theSwitch = llvm::SwitchInst::Create(real_index, defaultBlock,
idxblocks.size(), block);
// populate switch
int myindex = 0;
for (auto index : idxblocks) {
BasicBlock *writeBl = emitJumpIndexWrite(F, index, dest.getReg(),
continueBlock);
theSwitch->addCase(CONST_V<32>(block, myindex), writeBl);
++myindex;
}
// new block to write to is continue block
block = continueBlock;
}
+141 -126
View File
@@ -1,171 +1,186 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _JUMPTABLES_H
#define _JUMPTABLES_H
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <utility>
template <class T> class Table {
public:
Table(const std::vector<T> &table, int entry): m_table(table), m_entry(entry) {};
virtual int getInitialEntry() const { return this->m_entry; }
virtual ~Table() {};
virtual const std::vector<T>& getTable(void) const { return this->m_table; }
virtual const std::vector<T>& getConstTable(void) const { return this->m_table; }
struct TranslationContext;
protected:
std::vector<T> m_table;
int m_entry;
virtual std::vector<T>& getTable(void) { return this->m_table; }
template<class T>
class Table {
public:
Table(const std::vector<T> &table, int entry)
: m_table(table),
m_entry(entry) {}
virtual int getInitialEntry(void) const {
return this->m_entry;
}
virtual ~Table(void) {}
virtual const std::vector<T> &getTable(void) const {
return this->m_table;
}
virtual const std::vector<T> &getConstTable(void) const {
return this->m_table;
}
protected:
std::vector<T> m_table;
int m_entry;
virtual std::vector<T> &getTable(void) {
return this->m_table;
}
};
class MCSOffsetTable : public Table< std::pair<VA,VA> > {
protected:
VA m_start_addr;
public:
MCSOffsetTable(const std::vector< std::pair<VA,VA> > &table, int entry, VA start):
Table< std::pair <VA,VA>>::Table(table, entry), m_start_addr(start) {};
virtual ~MCSOffsetTable() {};
class MCSOffsetTable : public Table<std::pair<VA, VA>> {
protected:
VA m_start_addr;
public:
MCSOffsetTable(const std::vector<std::pair<VA, VA>> &table,
int entry, VA start)
: Table<std::pair<VA, VA>>::Table(table, entry),
m_start_addr(start) {}
virtual VA getStartAddr() const {return this->m_start_addr;}
virtual ~MCSOffsetTable(void) {}
virtual VA getStartAddr(void) const {
return this->m_start_addr;
}
};
class MCSJumpTable : public Table<VA> {
protected:
VA m_offset_from_data;
protected:
VA m_offset_from_data;
public:
MCSJumpTable(const std::vector<VA> &table, int entry, VA data_offset):
Table<VA>::Table(table, entry), m_offset_from_data(data_offset) {};
virtual const std::vector<VA>& getJumpTable(void) const { return this->getTable(); }
virtual std::vector<VA>& getJumpTable(void) { return this->getTable(); }
virtual VA getOffsetFromData() const {return this->m_offset_from_data; }
virtual ~MCSJumpTable() {};
public:
MCSJumpTable(const std::vector<VA> &table, int entry, VA data_offset)
: Table<VA>::Table(table, entry),
m_offset_from_data(data_offset) {}
virtual const std::vector<VA> &getJumpTable(void) const {
return this->getTable();
}
virtual std::vector<VA> &getJumpTable(void) {
return this->getTable();
}
virtual VA getOffsetFromData(void) const {
return this->m_offset_from_data;
}
virtual ~MCSJumpTable(void) {}
};
class JumpIndexTable : public Table<uint8_t> {
public:
JumpIndexTable(const std::vector<uint8_t> &table, int entry):
Table<uint8_t>::Table(table, entry) {};
virtual const std::vector<uint8_t>& getJumpIndexTable(void) const { return this->getTable(); }
virtual std::vector<uint8_t>& getJumpIndexTable(void) { return this->getTable(); }
virtual ~JumpIndexTable() {};
public:
JumpIndexTable(const std::vector<uint8_t> &table, int entry)
: Table<uint8_t>::Table(table, entry) {}
virtual const std::vector<uint8_t> &getJumpIndexTable(void) const {
return this->getTable();
}
virtual std::vector<uint8_t> &getJumpIndexTable(void) {
return this->getTable();
}
virtual ~JumpIndexTable() {}
};
typedef MCSJumpTable *MCSJumpTablePtr;
typedef JumpIndexTable *JumpIndexTablePtr;
typedef boost::shared_ptr<MCSJumpTable> MCSJumpTablePtr;
typedef boost::shared_ptr<JumpIndexTable> JumpIndexTablePtr;
bool addJumpTableDataSection(TranslationContext &ctx, VA &newVA,
const MCSJumpTable &table);
bool addJumpTableDataSection(NativeModulePtr natMod,
llvm::Module *M,
VA &newVA,
const MCSJumpTable& table);
bool addJumpIndexTableDataSection(NativeModulePtr natMod,
llvm::Module *M,
VA &newVA,
const JumpIndexTable& table);
bool addJumpIndexTableDataSection(TranslationContext &ctx,
VA &newVA, const JumpIndexTable &table);
// check for the format:
// jmp [reg*4+<relocated offset>]
static bool isConformantJumpInst(InstPtr jmpinst) {
//
// TODO(pag): This is x86-specific; factor into an arch-specific place.
static bool isConformantJumpInst(NativeInstPtr jmpinst) {
const llvm::MCInst &inst = jmpinst->get_inst();
const auto &inst = jmpinst->get_inst();
// these are now done via switch()
if(inst.getOpcode() == llvm::X86::JMP32r ||
inst.getOpcode() == llvm::X86::JMP64r) {
return true;
}
if (inst.getNumOperands() < 4) {
return false;
}
const llvm::MCOperand& scale = inst.getOperand(1);
const llvm::MCOperand& index = inst.getOperand(2);
const llvm::MCOperand& disp = inst.getOperand(3);
if(scale.isImm() && // scale:
// can be 4 (32-bit) or 8 (64-bit)
(scale.getImm() == 4 || scale.getImm() == 8) &&
index.isReg() && // index must be a register
disp.isImm())
{
return true;
}
// these are now done via switch()
if (inst.getOpcode() == llvm::X86::JMP32r ||
inst.getOpcode() == llvm::X86::JMP64r) {
return true;
}
if (inst.getNumOperands() < 4) {
return false;
}
const auto &scale = inst.getOperand(1);
const auto &index = inst.getOperand(2);
const auto &disp = inst.getOperand(3);
// scale: can be 4 (32-bit) or 8 (64-bit)
// index must be a register
return scale.isImm() && index.isReg() && disp.isImm() &&
(scale.getImm() == 4 || scale.getImm() == 8);
}
void doJumpTableViaData(
NativeModulePtr natM,
llvm::BasicBlock *& block,
InstPtr ip,
llvm::MCInst &inst,
const int bitness);
void doJumpTableViaData(TranslationContext &ctx, llvm::BasicBlock *&block,
const int bitness);
void doJumpTableViaData(
llvm::BasicBlock *& block,
llvm::Value *val,
const int bitness);
void doJumpTableViaData(llvm::BasicBlock *&block, llvm::Value *val,
const int bitness);
void doJumpTableViaSwitch(
NativeModulePtr natM,
llvm::BasicBlock *& block,
InstPtr ip,
llvm::MCInst &inst,
const int bitness);
void doJumpTableViaSwitch(TranslationContext &ctx, llvm::BasicBlock *&block,
const int bitness);
void doJumpTableViaSwitchReg(
llvm::BasicBlock *& block,
InstPtr ip,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
const int bitness);
void doJumpTableViaSwitchReg(TranslationContext &ctx, llvm::BasicBlock *& block,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
const int bitness);
void doJumpIndexTableViaSwitch(
llvm::BasicBlock *& block,
InstPtr ip);
void doJumpIndexTableViaSwitch(llvm::BasicBlock *& block, NativeInstPtr ip);
void doJumpOffsetTableViaSwitchReg(
llvm::BasicBlock *& block,
InstPtr ip,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
llvm::Value *data_location,
MCSOffsetTablePtr ot_ptr);
void doJumpOffsetTableViaSwitchReg(TranslationContext &ctx, llvm::BasicBlock *&block,
llvm::Value *regVal,
llvm::BasicBlock *&default_block,
llvm::Value *data_location,
MCSOffsetTablePtr ot_ptr);
#endif
+197 -320
View File
@@ -32,6 +32,7 @@
#include "x86Helpers.h"
#include "ArchOps.h"
#include "RegisterUsage.h"
#include "InstructionDispatch.h"
#include "llvm/ADT/StringSwitch.h"
@@ -52,7 +53,6 @@
#include "llvm/Support/CommandLine.h"
#include <boost/graph/breadth_first_search.hpp>
#include "Externals.h"
#include "../common/to_string.h"
#include "../common/Defaults.h"
@@ -71,14 +71,6 @@ static llvm::cl::opt<bool> AddBreakpoints(
"Add debug breakpoint function calls before each lifted instruction."),
llvm::cl::init(false));
static llvm::cl::opt<bool> BlockPerInstr(
"put-instrs-in-blocks",
llvm::cl::desc(
"Add debug breakpoint function calls before each lifted instruction."),
llvm::cl::init(false));
#include <llvm/ADT/SmallVector.h>
Instruction *noAliasMCSemaScope(Instruction *inst) {
@@ -168,7 +160,7 @@ void INTERNAL_M_WRITE(int width, unsigned addrspace, llvm::BasicBlock *b,
return;
}
void M_WRITE_T(InstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
void M_WRITE_T(NativeInstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
llvm::Value *data, llvm::Type *ptrtype) {
//this is also straightforward
llvm::Value *writeLoc = addr;
@@ -193,23 +185,6 @@ void M_WRITE_T(InstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
return;
}
class bfs_cfg_visitor : public boost::default_bfs_visitor {
private:
NativeFunctionPtr natFun;
Function *F;
NativeModulePtr natMod;
bool &didError;
public:
bfs_cfg_visitor(NativeFunctionPtr n, NativeModulePtr m, Function *F_, bool &e)
: natFun(n),
F(F_),
natMod(m),
didError(e) {
}
template<typename Vertex, typename Graph>
void discover_vertex(Vertex u, const Graph & g) const;
};
Value *MCRegToValue(BasicBlock *b, unsigned reg) {
Module *M = b->getParent()->getParent();
@@ -876,18 +851,18 @@ static Instruction *GEPLocal(Type *Ty, const char *name, Instruction *I) {
} // namespace x86
void allocateLocals(Function *F, int bits) {
void ArchAllocRegisterVars(llvm::BasicBlock *begin, int bits) {
auto &C = begin->getContext();
//always at the beginning of a function
//we need to allocate local variables via alloca, these locals will
//live for the life of the function context and be the sources/sinks
//of any activity involving registers or flags
BasicBlock *begin = &F->getEntryBlock();
switch (bits) {
case 32: {
//UPDATEREGS -- when we add something to 'regs' struct change here
//create a local for every member in the 'regs' struct
//create 32-bit width general purpose registers
Type *RegTy = Type::getInt32Ty(F->getContext());
Type *RegTy = Type::getInt32Ty(C);
Instruction *eipA = x86::GEPLocal(RegTy, "XIP", begin);
Instruction *eaxA = x86::GEPLocal(RegTy, "XAX", eipA);
@@ -900,7 +875,7 @@ void allocateLocals(Function *F, int bits) {
Instruction *espA = x86::GEPLocal(RegTy, "XSP", ebpA);
//create other fields for flags
Type *boolTy = Type::getInt1Ty(F->getContext());
Type *boolTy = Type::getInt1Ty(C);
Instruction *zfA = x86::GEPLocal(boolTy, "ZF", espA);
Instruction *sfA = x86::GEPLocal(boolTy, "PF", zfA);
Instruction *ofA = x86::GEPLocal(boolTy, "AF", sfA);
@@ -911,7 +886,7 @@ void allocateLocals(Function *F, int bits) {
TASSERT(dfA != nullptr, "");
// FPU STACK
Type *floatTy = Type::getX86_FP80Ty(F->getContext());
Type *floatTy = Type::getX86_FP80Ty(C);
// 8 float values make up the ST registers
Type *floatArrayTy = ArrayType::get(floatTy, 8);
Instruction *stRegs = x86::GEPLocal(floatArrayTy, "STi", afA);
@@ -922,7 +897,7 @@ void allocateLocals(Function *F, int bits) {
// TOP of stack from FPU flags
// really a 3-bit integer
Type *topTy = Type::getIntNTy(F->getContext(), 3);
Type *topTy = Type::getIntNTy(C, 3);
Instruction *fpu_TOP = x86::GEPLocal(topTy, "FPU_FLAG_TOP", fpu_C3);
TASSERT(fpu_TOP != nullptr, "");
@@ -942,7 +917,7 @@ void allocateLocals(Function *F, int bits) {
TASSERT(fpu_IE != nullptr, "");
// FPU CONTROL FLAGS
Type *int2Ty = Type::getIntNTy(F->getContext(), 2);
Type *int2Ty = Type::getIntNTy(C, 2);
Instruction *fpu_X = x86::GEPLocal(boolTy, "FPU_CONTROL_X", fpu_IE);
Instruction *fpu_RC = x86::GEPLocal(int2Ty, "FPU_CONTROL_RC", fpu_X);
Instruction *fpu_PC = x86::GEPLocal(int2Ty, "FPU_CONTROL_PC", fpu_RC);
@@ -960,54 +935,40 @@ void allocateLocals(Function *F, int bits) {
Type *tagArrayType = ArrayType::get(int2Ty, 8);
Instruction *fpu_TagWord = x86::GEPLocal(tagArrayType, "FPU_TAG", fpu_IM);
Instruction *fpu_LASTIP_SEG = x86::GEPLocal(
Type::getInt16Ty(F->getContext()), "FPU_LASTIP_SEG", fpu_TagWord);
Instruction *fpu_LASTIP_SEG = x86::GEPLocal(Type::getInt16Ty(C),
"FPU_LASTIP_SEG",
fpu_TagWord);
Instruction *fpu_LASTIP_OFF = x86::GEPLocal(RegTy, "FPU_LASTIP_OFF",
fpu_LASTIP_SEG);
Instruction *fpu_LASTDATA_SEG = x86::GEPLocal(
Type::getInt16Ty(F->getContext()), "FPU_LASTDATA_SEG",
fpu_LASTIP_OFF);
Instruction *fpu_LASTDATA_SEG = x86::GEPLocal(Type::getInt16Ty(C),
"FPU_LASTDATA_SEG",
fpu_LASTIP_OFF);
Instruction *fpu_LASTDATA_OFF = x86::GEPLocal(RegTy, "FPU_LASTDATA_OFF",
fpu_LASTDATA_SEG);
Instruction *fpu_FOPCODE = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 11), "FPU_FOPCODE",
fpu_LASTDATA_OFF);
Instruction *fpu_FOPCODE = x86::GEPLocal(Type::getIntNTy(C, 11),
"FPU_FOPCODE", fpu_LASTDATA_OFF);
TASSERT(fpu_FOPCODE != nullptr, "");
auto Int128Ty = Type::getIntNTy(C, 128);
//vector registers
Instruction *vec_xmm0 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM0", fpu_FOPCODE);
Instruction *vec_xmm1 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM1", vec_xmm0);
Instruction *vec_xmm2 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM2", vec_xmm1);
Instruction *vec_xmm3 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM3", vec_xmm2);
Instruction *vec_xmm4 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM4", vec_xmm3);
Instruction *vec_xmm5 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM5", vec_xmm4);
Instruction *vec_xmm6 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM6", vec_xmm5);
Instruction *vec_xmm7 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM7", vec_xmm6);
Instruction *vec_xmm8 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM8", vec_xmm7);
Instruction *vec_xmm9 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM9", vec_xmm8);
Instruction *vec_xmm10 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM10", vec_xmm9);
Instruction *vec_xmm11 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM11", vec_xmm10);
Instruction *vec_xmm12 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM12", vec_xmm11);
Instruction *vec_xmm13 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM13", vec_xmm12);
Instruction *vec_xmm14 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM14", vec_xmm13);
Instruction *vec_xmm15 = x86::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM15", vec_xmm14);
Instruction *vec_xmm0 = x86::GEPLocal(Int128Ty, "XMM0", fpu_FOPCODE);
Instruction *vec_xmm1 = x86::GEPLocal(Int128Ty, "XMM1", vec_xmm0);
Instruction *vec_xmm2 = x86::GEPLocal(Int128Ty, "XMM2", vec_xmm1);
Instruction *vec_xmm3 = x86::GEPLocal(Int128Ty, "XMM3", vec_xmm2);
Instruction *vec_xmm4 = x86::GEPLocal(Int128Ty, "XMM4", vec_xmm3);
Instruction *vec_xmm5 = x86::GEPLocal(Int128Ty, "XMM5", vec_xmm4);
Instruction *vec_xmm6 = x86::GEPLocal(Int128Ty, "XMM6", vec_xmm5);
Instruction *vec_xmm7 = x86::GEPLocal(Int128Ty, "XMM7", vec_xmm6);
Instruction *vec_xmm8 = x86::GEPLocal(Int128Ty, "XMM8", vec_xmm7);
Instruction *vec_xmm9 = x86::GEPLocal(Int128Ty, "XMM9", vec_xmm8);
Instruction *vec_xmm10 = x86::GEPLocal(Int128Ty, "XMM10", vec_xmm9);
Instruction *vec_xmm11 = x86::GEPLocal(Int128Ty, "XMM11", vec_xmm10);
Instruction *vec_xmm12 = x86::GEPLocal(Int128Ty, "XMM12", vec_xmm11);
Instruction *vec_xmm13 = x86::GEPLocal(Int128Ty, "XMM13", vec_xmm12);
Instruction *vec_xmm14 = x86::GEPLocal(Int128Ty, "XMM14", vec_xmm13);
Instruction *vec_xmm15 = x86::GEPLocal(Int128Ty, "XMM15", vec_xmm14);
// stack base and limit
Instruction *stack_base = x86::GEPLocal(RegTy, "STACK_BASE", vec_xmm15);
@@ -1018,7 +979,7 @@ void allocateLocals(Function *F, int bits) {
case 64: {
//create 64-bit width general purpose registers
Type *RegTy = Type::getInt64Ty(F->getContext());
Type *RegTy = Type::getInt64Ty(C);
Instruction *ripA = x86_64::GEPLocal(RegTy, "XIP", begin);
Instruction *raxA = x86_64::GEPLocal(RegTy, "XAX", ripA);
Instruction *rbxA = x86_64::GEPLocal(RegTy, "XBX", raxA);
@@ -1031,7 +992,7 @@ void allocateLocals(Function *F, int bits) {
//create other fields for flags
Type *boolTy = Type::getInt1Ty(F->getContext());
Type *boolTy = Type::getInt1Ty(C);
Instruction *zfA = x86_64::GEPLocal(boolTy, "ZF", rspA);
Instruction *sfA = x86_64::GEPLocal(boolTy, "PF", zfA);
Instruction *ofA = x86_64::GEPLocal(boolTy, "AF", sfA);
@@ -1043,7 +1004,7 @@ void allocateLocals(Function *F, int bits) {
// FPU STACK
//Type *floatTy = IntegerType::get(F->getContext(), 128);
Type *floatTy = Type::getX86_FP80Ty(F->getContext());
Type *floatTy = Type::getX86_FP80Ty(C);
// 8 float values make up the ST registers
Type *floatArrayTy = ArrayType::get(floatTy, 8);
Instruction *stRegs = x86_64::GEPLocal(floatArrayTy, "STi", dfA);
@@ -1057,7 +1018,7 @@ void allocateLocals(Function *F, int bits) {
// TOP of stack from FPU flags
// really a 3-bit integer
Type *topTy = Type::getIntNTy(F->getContext(), 3);
Type *topTy = Type::getIntNTy(C, 3);
Instruction *fpu_TOP = x86_64::GEPLocal(topTy, "FPU_FLAG_TOP", fpu_C3);
TASSERT(fpu_TOP != nullptr, "");
@@ -1077,7 +1038,7 @@ void allocateLocals(Function *F, int bits) {
TASSERT(fpu_IE != nullptr, "");
// FPU CONTROL FLAGS
Type *int2Ty = Type::getIntNTy(F->getContext(), 2);
Type *int2Ty = Type::getIntNTy(C, 2);
Instruction *fpu_X = x86_64::GEPLocal(boolTy, "FPU_CONTROL_X", fpu_IE);
Instruction *fpu_RC = x86_64::GEPLocal(int2Ty, "FPU_CONTROL_RC", fpu_X);
Instruction *fpu_PC = x86_64::GEPLocal(int2Ty, "FPU_CONTROL_PC", fpu_RC);
@@ -1098,55 +1059,42 @@ void allocateLocals(Function *F, int bits) {
TASSERT(fpu_TagWord != nullptr, "");
Instruction *fpu_LASTIP_SEG = x86_64::GEPLocal(
Type::getInt16Ty(F->getContext()), "FPU_LASTIP_SEG", fpu_TagWord);
Instruction *fpu_LASTIP_SEG = x86_64::GEPLocal(Type::getInt16Ty(C),
"FPU_LASTIP_SEG",
fpu_TagWord);
Instruction *fpu_LASTIP_OFF = x86_64::GEPLocal(RegTy, "FPU_LASTIP_OFF",
fpu_LASTIP_SEG);
Instruction *fpu_LASTDATA_SEG = x86_64::GEPLocal(
Type::getInt16Ty(F->getContext()), "FPU_LASTDATA_SEG",
fpu_LASTIP_OFF);
Instruction *fpu_LASTDATA_SEG = x86_64::GEPLocal(Type::getInt16Ty(C),
"FPU_LASTDATA_SEG",
fpu_LASTIP_OFF);
Instruction *fpu_LASTDATA_OFF = x86_64::GEPLocal(RegTy,
"FPU_LASTDATA_OFF",
fpu_LASTDATA_SEG);
Instruction *fpu_FOPCODE = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 11), "FPU_FOPCODE",
fpu_LASTDATA_OFF);
Instruction *fpu_FOPCODE = x86_64::GEPLocal(Type::getIntNTy(C, 11),
"FPU_FOPCODE",
fpu_LASTDATA_OFF);
TASSERT(fpu_FOPCODE != nullptr, "");
auto Int128Ty = Type::getIntNTy(C, 128);
//vector registers
Instruction *vec_xmm0 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM0", fpu_FOPCODE);
Instruction *vec_xmm1 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM1", vec_xmm0);
Instruction *vec_xmm2 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM2", vec_xmm1);
Instruction *vec_xmm3 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM3", vec_xmm2);
Instruction *vec_xmm4 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM4", vec_xmm3);
Instruction *vec_xmm5 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM5", vec_xmm4);
Instruction *vec_xmm6 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM6", vec_xmm5);
Instruction *vec_xmm7 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM7", vec_xmm6);
Instruction *vec_xmm8 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM8", vec_xmm7);
Instruction *vec_xmm9 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM9", vec_xmm8);
Instruction *vec_xmm10 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM10", vec_xmm9);
Instruction *vec_xmm11 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM11", vec_xmm10);
Instruction *vec_xmm12 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM12", vec_xmm11);
Instruction *vec_xmm13 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM13", vec_xmm12);
Instruction *vec_xmm14 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM14", vec_xmm13);
Instruction *vec_xmm15 = x86_64::GEPLocal(
Type::getIntNTy(F->getContext(), 128), "XMM15", vec_xmm14);
Instruction *vec_xmm0 = x86_64::GEPLocal(Int128Ty, "XMM0", fpu_FOPCODE);
Instruction *vec_xmm1 = x86_64::GEPLocal(Int128Ty, "XMM1", vec_xmm0);
Instruction *vec_xmm2 = x86_64::GEPLocal(Int128Ty, "XMM2", vec_xmm1);
Instruction *vec_xmm3 = x86_64::GEPLocal(Int128Ty, "XMM3", vec_xmm2);
Instruction *vec_xmm4 = x86_64::GEPLocal(Int128Ty, "XMM4", vec_xmm3);
Instruction *vec_xmm5 = x86_64::GEPLocal(Int128Ty, "XMM5", vec_xmm4);
Instruction *vec_xmm6 = x86_64::GEPLocal(Int128Ty, "XMM6", vec_xmm5);
Instruction *vec_xmm7 = x86_64::GEPLocal(Int128Ty, "XMM7", vec_xmm6);
Instruction *vec_xmm8 = x86_64::GEPLocal(Int128Ty, "XMM8", vec_xmm7);
Instruction *vec_xmm9 = x86_64::GEPLocal(Int128Ty, "XMM9", vec_xmm8);
Instruction *vec_xmm10 = x86_64::GEPLocal(Int128Ty, "XMM10", vec_xmm9);
Instruction *vec_xmm11 = x86_64::GEPLocal(Int128Ty, "XMM11", vec_xmm10);
Instruction *vec_xmm12 = x86_64::GEPLocal(Int128Ty, "XMM12", vec_xmm11);
Instruction *vec_xmm13 = x86_64::GEPLocal(Int128Ty, "XMM13", vec_xmm12);
Instruction *vec_xmm14 = x86_64::GEPLocal(Int128Ty, "XMM14", vec_xmm13);
Instruction *vec_xmm15 = x86_64::GEPLocal(Int128Ty, "XMM15", vec_xmm14);
// stack base and limit
Instruction *stack_base = x86_64::GEPLocal(RegTy, "STACK_BASE",
@@ -1173,21 +1121,6 @@ void allocateLocals(Function *F, int bits) {
return;
}
BasicBlock *bbFromStrName(string n, Function *F) {
BasicBlock *found = nullptr;
for (Function::iterator it = F->begin(); it != F->end(); ++it) {
BasicBlock *b = it;
if (b->getName() == n) {
found = b;
break;
}
}
return found;
}
static void CreateInstrBreakpoint(llvm::BasicBlock *B, VA pc) {
auto M = B->getParent()->getParent();
auto &C = M->getContext();
@@ -1218,21 +1151,11 @@ static void CreateInstrBreakpoint(llvm::BasicBlock *B, VA pc) {
llvm::CallInst::Create(IFT, "", B);
}
InstTransResult liftInstr(InstPtr ip, BasicBlock *&block, NativeBlockPtr nb,
Function *F, NativeFunctionPtr natF,
NativeModulePtr natM, bool doAnnotation) {
static InstTransResult LiftInstIntoBlock(TranslationContext &ctx,
llvm::BasicBlock *&block,
bool doAnnotation) {
auto pc = ip->get_loc();
// Put each instruction into its own basic block.
if (BlockPerInstr) {
std::stringstream ss;
ss << "instr_0x" << std::hex << pc;
auto &C = F->getContext();
auto instr_block = BasicBlock::Create(C, ss.str(), F);
BranchInst::Create(instr_block, block);
block = instr_block;
}
auto pc = ctx.natI->get_loc();
// At the beginning of the block, make a call to a dummy function with the
// same name as the block. This function call cannot be optimized away, and
@@ -1241,15 +1164,15 @@ InstTransResult liftInstr(InstPtr ip, BasicBlock *&block, NativeBlockPtr nb,
CreateInstrBreakpoint(block, pc);
}
InstTransResult disInst_result = liftInstrImpl(ip, block, nb, F, natF, natM);
InstTransResult disInst_result = LiftInstIntoBlockImpl(ctx, block);
// we need to loop over this function and find any un-annotated instructions.
// then we annotate each instruction
if (doAnnotation) {
for (auto &B : *F) {
for (auto &B : *ctx.F) {
for (auto &I : B) {
VA inst_eip;
if (!getAnnotation( &I, inst_eip)) {
if (!getAnnotation(&I, inst_eip)) {
addAnnotation(&I, pc);
}
}
@@ -1259,124 +1182,93 @@ InstTransResult liftInstr(InstPtr ip, BasicBlock *&block, NativeBlockPtr nb,
return disInst_result;
}
template<typename Vertex, typename Graph>
void bfs_cfg_visitor::discover_vertex(Vertex u, const Graph &g) const {
auto curBlock = this->natFun->block_from_id(u);
llvm::BasicBlock *curLLVMBlock = nullptr;
if ( !curBlock) {
throw TErr(__LINE__, __FILE__,
"Could not look up block " + to_string<Vertex>(u, dec));
}
static bool LiftBlockIntoFunction(TranslationContext &ctx) {
auto didError = false;
//first, either create or look up the LLVM basic block for this native
//block. we are either creating it for the first time, or, we are
//going to look up a blank block
curLLVMBlock = bbFromStrName(curBlock->get_name(), this->F);
if (curLLVMBlock == nullptr) {
//we need to create the block, so do that
curLLVMBlock = BasicBlock::Create(this->F->getContext(),
curBlock->get_name(), this->F);
TASSERT(curLLVMBlock != nullptr, "");
}
auto block_name = ctx.natB->get_name();
auto curLLVMBlock = ctx.va_to_bb[ctx.natB->get_base()];
//then, create a basic block for every follow of this block, if we do not
//already have that basic block in our LLVM CFG
const auto &follows = curBlock->get_follows();
for (auto blockBase : follows) {
//try and look up a block that has this blocks name
auto followNat = this->natFun->block_from_base(blockBase);
auto followName = followNat->get_name();
auto fBB = bbFromStrName(followName, this->F);
if ( !fBB) {
fBB = BasicBlock::Create(this->F->getContext(), followNat->get_name(),
this->F);
const auto &follows = ctx.natB->get_follows();
for (auto succ_block_va : follows) {
if (!ctx.va_to_bb.count(succ_block_va)) {
throw TErr(__LINE__, __FILE__, "Missing successor block!");
}
}
//now, go through each statement and translate it into LLVM IR
//statements that branch SHOULD be the last statement in a block
for (InstPtr inst : curBlock->get_insts()) {
auto r = liftInstr(inst, curLLVMBlock, curBlock, this->F, this->natFun,
this->natMod, true);
for (auto inst : ctx.natB->get_insts()) {
ctx.natI = inst;
auto r = LiftInstIntoBlock(ctx, curLLVMBlock, true);
if (r == TranslateError) {
this->didError = true;
didError = true;
break;
} else if (r == TranslateErrorUnsupported
&& ignoreUnsupportedInsts == false) {
this->didError = true;
} else if (r == TranslateErrorUnsupported && !ignoreUnsupportedInsts) {
didError = true;
break;
}
}
if (curLLVMBlock->getTerminator()) {
return;
return didError;
}
// we may need to insert a branch inst to the successor
// if the block ended on a non-terminator (this happens since we
// may split blocks in cfg recovery to avoid code duplication)
if (follows.size() == 1) {
VA blockBase = *(follows.begin());
std::string bbName = "block_0x" + to_string<VA>(blockBase, std::hex);
BasicBlock *nextBB = bbFromStrName(bbName, this->F);
BranchInst::Create(nextBB, curLLVMBlock);
llvm::BranchInst::Create(ctx.va_to_bb[follows.front()], curLLVMBlock);
} else {
new UnreachableInst(curLLVMBlock->getContext(), curLLVMBlock);
new llvm::UnreachableInst(curLLVMBlock->getContext(), curLLVMBlock);
}
return didError;
}
static bool insertFunctionIntoModule(NativeModulePtr mod,
static bool InsertFunctionIntoModule(NativeModulePtr mod,
NativeFunctionPtr func, Module *M) {
//okay, now we traverse the graph and add the instructions and blocks
//into the llvm module
//first, get the LLVM function for this native function
Function *F = M->getFunction(func->get_name());
if ( !F) {
auto &C = M->getContext();
auto F = M->getFunction(func->get_name());
if (!F) {
throw TErr(__LINE__, __FILE__, "Could not get func " + func->get_name());
}
if (F->empty() == false) {
cout << "WARNING: Asking to re-insert function: " << func->get_name()
<< std::endl;
cout << "\tReturning current function instead" << std::endl;
if (!F->empty()) {
std::cout << "WARNING: Asking to re-insert function: " << func->get_name()
<< std::endl << "\tReturning current function instead"
<< std::endl;
return true;
}
//create the entry block for the function
//this block will alloca cells on the 'stack' for every register in the
//register member structure
BasicBlock *entryBlock = BasicBlock::Create(F->getContext(), "entry", F);
TASSERT(entryBlock != nullptr, "");
auto entryBlock = llvm::BasicBlock::Create(F->getContext(), "entry", F);
ArchAllocRegisterVars(entryBlock, ArchPointerSize(M));
allocateLocals(F, ArchPointerSize(M));
TranslationContext ctx;
ctx.natM = mod;
ctx.natF = func;
ctx.M = M;
ctx.F = F;
//then we put an unconditional branch from the 'entry' block to the first
//block, and we create the first block
NativeBlockPtr funcEntry = func->block_from_base(func->get_start());
BasicBlock *firstBlock = BasicBlock::Create(F->getContext(),
funcEntry->get_name(), F);
TASSERT(firstBlock != nullptr, "");
//create a branch from the end of the entry block to the first block
BranchInst::Create(firstBlock, entryBlock);
// Create basic blocks for each basic block in the original function.
for (auto block_info : func->get_blocks()) {
ctx.va_to_bb[block_info.first] = llvm::BasicBlock::Create(
C, block_info.second->get_name(), F);
}
//now, start crawling everything in NativeFunctionPtr
CFG funcGraph = func->get_cfg();
bool error = false;
bfs_cfg_visitor v(func, mod, F, error);
// Create a branch from the end of the entry block to the first block
llvm::BranchInst::Create(ctx.va_to_bb[func->get_start()], entryBlock);
//visit every vertex in the graph, starting from the entry block, which
//always should be block 0
//this traversal wil build us the LLVM graph from the native graph
boost::breadth_first_search(funcGraph,
boost::vertex(func->entry_block_id(), funcGraph),
boost::visitor(v));
// Lift every basic block into the functions.
auto error = false;
for (auto block_info : func->get_blocks()) {
ctx.natB = block_info.second;
error = LiftBlockIntoFunction(ctx) || error;
}
// For ease of debugging generated code, don't allow lifted functions to
// be inlined. This will make lifted and native call graphs one-to-one.
@@ -1387,22 +1279,19 @@ static bool insertFunctionIntoModule(NativeModulePtr mod,
}
static Constant* makeConstantBlob(llvm::LLVMContext &ctx,
const std::vector<uint8_t> &blob) {
Type *charTy = llvm::Type::getInt8Ty(ctx);
static Constant *CreateConstantBlob(llvm::LLVMContext &ctx,
const std::vector<uint8_t> &blob) {
auto charTy = llvm::Type::getInt8Ty(ctx);
auto arrT = llvm::ArrayType::get(charTy, blob.size());
std::vector<llvm::Constant *> array_elements;
for (auto cur : blob) {
auto ty = llvm::Type::getInt8Ty(ctx);
auto c = llvm::ConstantInt::get(ty, cur);
auto c = llvm::ConstantInt::get(charTy, cur);
array_elements.push_back(c);
}
return llvm::ConstantArray::get(arrT, array_elements);
}
static llvm::GlobalVariable *getSectionForDataAddr(
static llvm::GlobalVariable *GetSectionForDataAddr(
const std::list<DataSection> &dataSecs, llvm::Module *M, VA data_addr,
VA &section_base) {
@@ -1411,15 +1300,12 @@ static llvm::GlobalVariable *getSectionForDataAddr(
VA end = start + dt.getSize();
if (data_addr >= start && data_addr < end) {
std::string gvar_name = "data_0x" + to_string<VA>(start, hex); //+"_ptr";
std::string gvar_name = "data_0x" + to_string<VA>(start, std::hex);
section_base = start;
return M->getNamedGlobal(gvar_name);
}
}
return nullptr;
}
static llvm::Constant* getPtrSizedValue(llvm::Module *M, llvm::Constant *v,
@@ -1443,7 +1329,7 @@ static llvm::Constant* getPtrSizedValue(llvm::Module *M, llvm::Constant *v,
}
void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
DataSection& ds, llvm::Module *M,
const DataSection &ds, llvm::Module *M,
std::vector<llvm::Constant *> &secContents,
std::vector<llvm::Type *> &data_section_types,
bool convert_to_callback) {
@@ -1464,32 +1350,29 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
// };
//
const std::list<DataSectionEntry> &ds_entries = ds.getEntries();
for (list<DataSectionEntry>::const_iterator dsec_itr = ds_entries.begin();
dsec_itr != ds_entries.end(); dsec_itr++) {
string sym_name;
for (auto &data_sec_entry : ds_entries) {
std::string sym_name;
if (dsec_itr->getSymbol(sym_name)) {
if (data_sec_entry.getSymbol(sym_name)) {
const char *func_addr_str = sym_name.c_str() + 4;
VA func_addr = strtoull(func_addr_str, nullptr, 16);
std::cout << __FUNCTION__ << ": Found symbol: " << sym_name << "\n";
std::cout << __FUNCTION__ << ": Found symbol: " << sym_name << std::endl;
if (sym_name.find("ext_") == 0) {
Constant *final_val = nullptr;
GlobalValue *ext_v = M->getNamedValue(func_addr_str);
llvm::Constant *final_val = nullptr;
auto ext_v = M->getNamedValue(func_addr_str);
if (ext_v != nullptr && isa<Function>(ext_v)) {
final_val = getPtrSizedValue(M, ext_v, dsec_itr->getSize());
final_val = getPtrSizedValue(M, ext_v, data_sec_entry.getSize());
//cout << "External function" << sym_name << " has type: " << final_val->getType() << "\n";
} else if (ext_v != nullptr) {
final_val = getPtrSizedValue(M, ext_v, dsec_itr->getSize());
final_val = getPtrSizedValue(M, ext_v, data_sec_entry.getSize());
//cout << "External data" << sym_name << " has type: " << final_val->getType() << "\n";
// assume ext data
} else {
TASSERT(ext_v != nullptr,
"Could not find external: " + string(func_addr_str));
"Could not find external: " + std::string(func_addr_str));
//cout << "External fail" << sym_name << " has type: " << final_val->getType() << "\n";
}
@@ -1501,7 +1384,7 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
// to do this, create a callback driver for
// it first (since it may be called externally)
Function *func = nullptr;
llvm::Function *func = nullptr;
if (convert_to_callback) {
func = ArchAddCallbackDriver(M, func_addr);
@@ -1511,7 +1394,7 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
TASSERT(func != nullptr, "Could not find function: " + sym_name);
}
Constant *final_val = getPtrSizedValue(M, func, dsec_itr->getSize());
auto final_val = getPtrSizedValue(M, func, data_sec_entry.getSize());
secContents.push_back(final_val);
data_section_types.push_back(final_val->getType());
@@ -1521,29 +1404,29 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
// then compute the offset from base of data
// and store as integer value of (base+offset)
VA section_base;
GlobalVariable *g_ref = getSectionForDataAddr(globaldata, M, func_addr,
section_base);
auto g_ref = GetSectionForDataAddr(globaldata, M, func_addr,
section_base);
TASSERT(g_ref != nullptr,
"Could not get data addr for:" + string(func_addr_str));
"Could not get data addr for:" + std::string(func_addr_str));
// instead of referencing an element directly
// we just convert the pointer to an integer
// and add its offset from the base of data
// to the new data section pointer
VA addr_diff = func_addr - section_base;
Constant *final_val;
llvm::Constant *final_val = nullptr;
//cout << " Symbol name : " << string(func_addr_str) << " : "
// << to_string<VA>(func_addr, hex) << " : "
// << to_string<VA>(section_base, hex) << "\n";
//cout.flush();
if (ArchPointerSize(M) == Pointer32) {
Constant *int_val = ConstantExpr::getPtrToInt(
g_ref, Type::getInt32Ty(M->getContext()));
final_val = ConstantExpr::getAdd(
auto int_val = llvm::ConstantExpr::getPtrToInt(
g_ref, llvm::Type::getInt32Ty(M->getContext()));
final_val = llvm::ConstantExpr::getAdd(
int_val, CONST_V_INT<32>(M->getContext(), addr_diff));
} else {
Constant *int_val = ConstantExpr::getPtrToInt(
g_ref, Type::getInt64Ty(M->getContext()));
final_val = ConstantExpr::getAdd(
auto int_val = llvm::ConstantExpr::getPtrToInt(
g_ref, llvm::Type::getInt64Ty(M->getContext()));
final_val = llvm::ConstantExpr::getAdd(
int_val, CONST_V_INT<64>(M->getContext(), addr_diff));
}
secContents.push_back(final_val);
@@ -1552,7 +1435,7 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
} else {
// add array
// this holds opaque data in a byte array
Constant *arr = makeConstantBlob(M->getContext(), dsec_itr->getBytes());
auto arr = CreateConstantBlob(M->getContext(), data_sec_entry.getBytes());
secContents.push_back(arr);
data_section_types.push_back(arr->getType());
} // if dsec_itr
@@ -1560,16 +1443,14 @@ void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
}
struct DataSectionVar {
DataSection *section;
const DataSection *section;
llvm::StructType *opaque_type;
llvm::GlobalVariable *var;
};
static bool insertDataSections(NativeModulePtr natMod, Module *M) {
list<DataSection> &globaldata = natMod->getData();
list<DataSection>::iterator git = globaldata.begin();
static bool InsertDataSections(NativeModulePtr natMod, Module *M) {
auto &globaldata = natMod->getData();
//insert all global data before we insert the CFG
std::vector<DataSectionVar> gvars;
@@ -1578,9 +1459,9 @@ static bool insertDataSections(NativeModulePtr natMod, Module *M) {
// as later we may have data references that are
// from one section into another
for (DataSection &dt : globaldata) {
for (auto &dt : globaldata) {
std::string bufferName;
bufferName = "data_0x" + to_string<VA>(dt.getBase(), hex);
bufferName = "data_0x" + to_string<VA>(dt.getBase(), std::hex);
//report << "inserting global data section named ";
//report << bufferName << "\n";
std::cout << "inserting global data section named ";
@@ -1597,7 +1478,7 @@ static bool insertDataSections(NativeModulePtr natMod, Module *M) {
}
// actually populate the data sections
for (DataSectionVar &var : gvars) {
for (auto &var : gvars) {
//data we use to create LLVM values for this section
// secContents is the actual values we will be inserting
@@ -1606,7 +1487,6 @@ static bool insertDataSections(NativeModulePtr natMod, Module *M) {
// the global variable
std::vector<llvm::Type *> data_section_types;
dataSectionToTypesContents(globaldata, *var.section, M, secContents,
data_section_types, true);
@@ -1615,45 +1495,44 @@ static bool insertDataSections(NativeModulePtr natMod, Module *M) {
// create an initializer list using the now filled in opaque
// structure type
auto cst = ConstantStruct::get(var.opaque_type, secContents);
auto cst = llvm::ConstantStruct::get(var.opaque_type, secContents);
// align on pointer size boundary, max needed by SSE instructions
var.var->setAlignment(ArchPointerSize(M));
var.var->setInitializer(cst);
}
return true;
}
void renameLiftedFunctions(NativeModulePtr natMod, llvm::Module *M,
void RenameLiftedFunctions(NativeModulePtr natMod, llvm::Module *M,
const std::set<VA> &entry_point_pcs) {
list<NativeFunctionPtr> funcs = natMod->get_funcs();
// Rename the functions to have their 'nice' names, where available.
for (auto f : funcs) {
if (entry_point_pcs.count(f->get_start())) {
for (auto &f : natMod->get_funcs()) {
auto native_func = f.second;
if (entry_point_pcs.count(native_func->get_start())) {
continue;
}
auto sub_name = f->get_name();
auto sub_name = native_func->get_name();
auto F = M->getFunction(sub_name);
std::stringstream ss;
ss << "callback_" << sub_name;
if ( !M->getFunction(ss.str())) {
auto &sym_name = f->get_symbol_name();
if ( !sym_name.empty()) {
if (!M->getFunction(ss.str())) {
auto &sym_name = native_func->get_symbol_name();
if (!sym_name.empty()) {
F->setName(sym_name);
}
}
}
}
static void initLiftedFunctions(NativeModulePtr natMod, llvm::Module *M) {
for (auto f : natMod->get_funcs()) {
auto fname = f->get_name();
static void InitLiftedFunctions(NativeModulePtr natMod, llvm::Module *M) {
for (auto &f : natMod->get_funcs()) {
auto native_func = f.second;
auto fname = native_func->get_name();
auto F = M->getFunction(fname);
if ( !F) {
if (!F) {
F = llvm::dyn_cast<llvm::Function>(
M->getOrInsertFunction(fname, getBaseFunctionType(M)));
@@ -1662,33 +1541,32 @@ static void initLiftedFunctions(NativeModulePtr natMod, llvm::Module *M) {
ArchSetCallingConv(M, F);
// make local functions 'static'
F->setLinkage(llvm::GlobalValue::InternalLinkage);
cout << "Inserted function: " << fname << std::endl;
std::cout << "Inserted function: " << fname << std::endl;
} else {
cout << "Already inserted function: " << fname << ", skipping."
<< std::endl;
std::cout << "Already inserted function: " << fname << ", skipping."
<< std::endl;
}
}
}
static void initExternalData(NativeModulePtr natMod, llvm::Module *M) {
static void InitExternalData(NativeModulePtr natMod, llvm::Module *M) {
for (auto dr : natMod->getExtDataRefs()) {
auto dsize = dr->getDataSize();
auto symname = dr->getSymbolName();
auto extType = llvm::ArrayType::get(llvm::Type::getInt8Ty(M->getContext()),
dsize);
auto gv = llvm::dyn_cast<llvm::GlobalValue>(
M->getOrInsertGlobal(symname, extType));
TASSERT(gv != nullptr, "Could not make global value!");
if (dr->isWeak()) {
gv->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
} else {
gv->setLinkage(llvm::GlobalValue::ExternalLinkage);
}
const auto &triple = M->getTargetTriple();
if (WINDOWS_TRIPLE == triple) {
// this only makes sense for win32
llvm::Triple triple(M->getTargetTriple());
if (llvm::Triple::Win32 == triple.getOS()) {
gv->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
}
}
@@ -1696,7 +1574,7 @@ static void initExternalData(NativeModulePtr natMod, llvm::Module *M) {
// Iterate over the list of external functions and insert them as
// global functions.
static void initExternalCode(NativeModulePtr natMod, llvm::Module *M) {
static void InitExternalCode(NativeModulePtr natMod, llvm::Module *M) {
for (auto e : natMod->getExtCalls()) {
auto conv = e->getCallingConvention();
auto argCount = e->getNumArgs();
@@ -1710,16 +1588,16 @@ static void initExternalCode(NativeModulePtr natMod, llvm::Module *M) {
continue;
}
if(conv == ExternalCodeRef::McsemaCall) {
if (ExternalCodeRef::McsemaCall == conv) {
// normal mcsema function prototypes
llvm::Function *newF = llvm::dyn_cast<llvm::Function>(
M->getOrInsertFunction(ArchNameMcsemaCall(symName), getBaseFunctionType(M)));
ArchSetCallingConv(M, newF);
newF->setLinkage(llvm::GlobalValue::ExternalLinkage);
F = llvm::dyn_cast<llvm::Function>(M->getOrInsertFunction(
ArchNameMcSemaCall(symName), getBaseFunctionType(M)));
ArchSetCallingConv(M, F);
F->setLinkage(llvm::GlobalValue::ExternalLinkage);
continue;
}
std::vector<llvm::Type*> arguments;
std::vector<llvm::Type *> arguments;
llvm::Type *returnType = nullptr;
// Create arguments.
@@ -1788,25 +1666,24 @@ static void initExternalCode(NativeModulePtr natMod, llvm::Module *M) {
}
}
static bool liftFunctionsIntoModule(NativeModulePtr natMod, Module *M) {
static bool LiftFunctionsIntoModule(NativeModulePtr natMod, Module *M) {
// populate functions
for (auto f : natMod->get_funcs()) {
if ( !insertFunctionIntoModule(natMod, f, M)) {
for (auto &func_info : natMod->get_funcs()) {
auto f = func_info.second;
if (!InsertFunctionIntoModule(natMod, f, M)) {
std::string fname = f->get_name();
cerr << "Could not insert function: " << fname
<< " into the LLVM module\n";
std::cerr << "Could not insert function: " << fname
<< " into the LLVM module" << std::endl;
return false;
break;
}
}
return true;
}
bool liftNativeCodeIntoModule(NativeModulePtr natMod, Module *M) {
bool result = true;
initLiftedFunctions(natMod, M);
initExternalData(natMod, M);
initExternalCode(natMod, M);
insertDataSections(natMod, M);
return liftFunctionsIntoModule(natMod, M);
bool LiftCodeIntoModule(NativeModulePtr natMod, Module *M) {
InitLiftedFunctions(natMod, M);
InitExternalData(natMod, M);
InitExternalCode(natMod, M);
InsertDataSections(natMod, M);
return LiftFunctionsIntoModule(natMod, M);
}
+7 -17
View File
@@ -64,8 +64,6 @@ typedef std::vector<llvm::Value*> regDefT;
//registers via alloca and then copies into them from the structure argument
void setupFlow(llvm::Function *, regDefT &);
llvm::BasicBlock *bbFromStrName(std::string n, llvm::Function *F);
///////////////////////////////////////////////////////////////////////////////
// state modeling functions
///////////////////////////////////////////////////////////////////////////////
@@ -106,7 +104,6 @@ static llvm::ConstantInt *CONST_V(llvm::BasicBlock *b, uint64_t width,
return llvm::ConstantInt::get(bTy, val);
}
llvm::Value *MCRegToValue(llvm::BasicBlock *b, unsigned reg);
void GENERIC_WRITEREG(llvm::BasicBlock *b, MCSemaRegs reg, llvm::Value *v);
@@ -149,11 +146,11 @@ llvm::Value *R_READ(llvm::BasicBlock *b, int reg) {
}
}
llvm::Value *INTERNAL_M_READ(unsigned width, unsigned addrspace, llvm::BasicBlock *b,
llvm::Value *addr);
llvm::Value *INTERNAL_M_READ(unsigned width, unsigned addrspace,
llvm::BasicBlock *b, llvm::Value *addr);
template<int width>
llvm::Value *M_READ(InstPtr ip, llvm::BasicBlock *b, llvm::Value *addr) {
llvm::Value *M_READ(NativeInstPtr ip, llvm::BasicBlock *b, llvm::Value *addr) {
return INTERNAL_M_READ(width, ip->get_addr_space(), b, addr);
}
@@ -163,14 +160,14 @@ llvm::Value *M_READ_0(llvm::BasicBlock *b, llvm::Value *addr) {
}
// defined in raiseX86.cpp
void M_WRITE_T(InstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
void M_WRITE_T(NativeInstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
llvm::Value *data, llvm::Type *ptrtype);
void INTERNAL_M_WRITE(int width, unsigned addrspace, llvm::BasicBlock *b,
llvm::Value *addr, llvm::Value *data);
template<int width>
void M_WRITE(InstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
void M_WRITE(NativeInstPtr ip, llvm::BasicBlock *b, llvm::Value *addr,
llvm::Value *data) {
return INTERNAL_M_WRITE(width, ip->get_addr_space(), b, addr, data);
}
@@ -189,23 +186,16 @@ void F_SET(llvm::BasicBlock *b, MCSemaRegs flag);
void F_CLEAR(llvm::BasicBlock *b, MCSemaRegs flag);
void allocateLocals(llvm::Function *, int);
llvm::BasicBlock *bbFromStrName(std::string, llvm::Function *);
void ArchAllocRegisterVars(llvm::BasicBlock *, int);
///////////////////////////////////////////////////////////////////////////////
// API usage functions
///////////////////////////////////////////////////////////////////////////////
InstTransResult liftInstr(InstPtr ip, llvm::BasicBlock *&block,
NativeBlockPtr nb, llvm::Function *F,
NativeFunctionPtr natF, NativeModulePtr natM,
bool doAnnotation);
llvm::Value *makeCallbackForLocalFunction(llvm::Module *M, VA local_target);
void dataSectionToTypesContents(const std::list<DataSection> &globaldata,
DataSection& ds, llvm::Module *M,
const DataSection &ds, llvm::Module *M,
std::vector<llvm::Constant*>& secContents,
std::vector<llvm::Type*>& data_section_types,
bool convert_to_callback);
+28 -40
View File
@@ -34,41 +34,31 @@
#include <llvm/IR/InstrTypes.h>
#include <cstdio>
using namespace llvm;
using namespace std;
llvm::StructType *g_RegStruct = nullptr;
llvm::PointerType *g_PRegStruct = nullptr;
StructType *g_RegStruct;
PointerType *g_PRegStruct;
FunctionType *getBaseFunctionType(Module *M) {
vector<Type *> baseFunctionArgs;
llvm::FunctionType *getBaseFunctionType(llvm::Module *M) {
std::vector<llvm::Type *> baseFunctionArgs;
baseFunctionArgs.push_back(g_PRegStruct);
FunctionType *funcTy = FunctionType::get(Type::getVoidTy(M->getContext()),
baseFunctionArgs, false);
TASSERT(funcTy != NULL, "");
auto funcTy = llvm::FunctionType::get(
llvm::Type::getVoidTy(M->getContext()),
baseFunctionArgs, false);
return funcTy;
}
Triple *getTargetTriple(const llvm::Target *T) {
if (T->getName() == "x86")
return new Triple("i386", "unknown", "unknown");
else if (T->getName() == "x86-64")
return new Triple("x86_64", "unknown", "unknown");
}
void initRegStateStruct(Module *M) {
void ArchInitRegStateStruct(llvm::Module *M) {
unsigned int regWidth = ArchPointerSize(M);
//create the "reg" struct type
auto &C = M->getContext();
StructType *regs = StructType::create(C, "RegState");
vector<Type *> regFields;
auto regs = llvm::StructType::create(C, "RegState");
std::vector<llvm::Type *> regFields;
Type *RegTy = IntegerType::getIntNTy(C, regWidth);
Type *XMMTy = IntegerType::getIntNTy(C, 128);
Type *FlagTy = IntegerType::getInt8Ty(C);
auto RegTy = llvm::IntegerType::getIntNTy(C, regWidth);
auto XMMTy = llvm::IntegerType::getIntNTy(C, 128);
auto FlagTy = llvm::IntegerType::getInt8Ty(C);
auto SegTy = llvm::Type::getInt16Ty(C);
//UPDATEREGS -- when we add something to 'regs', add it here
//GPRs
@@ -91,7 +81,7 @@ void initRegStateStruct(Module *M) {
regFields.push_back(FlagTy); // OF // 14
regFields.push_back(FlagTy); // DF // 15
ArrayType *fpu_regs = ArrayType::get(Type::getX86_FP80Ty(C), 8);
auto fpu_regs = llvm::ArrayType::get(llvm::Type::getX86_FP80Ty(C), 8);
regFields.push_back(fpu_regs); // 80 bytes 24
// FPU Status Word
@@ -121,18 +111,18 @@ void initRegStateStruct(Module *M) {
regFields.push_back(FlagTy); // FPU Invalid Operation Mask // 39
// FPU tag word; 8 element array of 2-bit entries
ArrayType *fpu_tag_word = ArrayType::get(FlagTy, 8);
auto fpu_tag_word = llvm::ArrayType::get(FlagTy, 8);
regFields.push_back(fpu_tag_word); // 40
// Last Instruction.
regFields.push_back(Type::getInt16Ty(C)); // Segment // 41
regFields.push_back(SegTy); // Segment // 41
regFields.push_back(RegTy); // Offset // 42
// Last Data
regFields.push_back(Type::getInt16Ty(C)); // Segment // 43
regFields.push_back(SegTy); // Segment // 43
regFields.push_back(RegTy); // Offset // 44
regFields.push_back(Type::getInt16Ty(C)); // FPU FOPCODE // 45
regFields.push_back(llvm::Type::getInt16Ty(C)); // FPU FOPCODE // 45
// vector registers
regFields.push_back(XMMTy); // XMM0 46
@@ -158,21 +148,19 @@ void initRegStateStruct(Module *M) {
regFields.push_back(RegTy); // 71: stack limit (smallest value)
if (64 == regWidth) {
regFields.push_back(RegTy); // R8 // 8
regFields.push_back(RegTy); // R9 // 9
regFields.push_back(RegTy); // R10 // 10
regFields.push_back(RegTy); // R11 // 11
regFields.push_back(RegTy); // R12 // 12
regFields.push_back(RegTy); // R13 // 13
regFields.push_back(RegTy); // R14 // 14
regFields.push_back(RegTy); // R15 // 15
regFields.push_back(RegTy); // R8 72
regFields.push_back(RegTy); // R9 73
regFields.push_back(RegTy); // R10 74
regFields.push_back(RegTy); // R11 75
regFields.push_back(RegTy); // R12 76
regFields.push_back(RegTy); // R13 77
regFields.push_back(RegTy); // R14 78
regFields.push_back(RegTy); // R15 79
}
PointerType *ptrToRegs = PointerType::get(regs, 0);
auto ptrToRegs = llvm::PointerType::get(regs, 0);
regs->setBody(regFields, true);
g_RegStruct = regs;
g_PRegStruct = ptrToRegs;
return;
}
+1 -2
View File
@@ -60,9 +60,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stack>
llvm::FunctionType *getBaseFunctionType(llvm::Module *M);
llvm::Triple *getTargetTriple(const llvm::Target *T);
extern llvm::StructType *g_RegStruct;
extern llvm::PointerType *g_PRegStruct;
void initRegStateStruct(llvm::Module *);
void ArchInitRegStateStruct(llvm::Module *);
+2 -2
View File
@@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Externals.h"
//translate a NativeModule into an LLVM Module
void renameLiftedFunctions(NativeModulePtr natMod, llvm::Module *M,
void RenameLiftedFunctions(NativeModulePtr mod, llvm::Module *M,
const std::set<VA> &entry_point_pcs);
bool liftNativeCodeIntoModule(NativeModulePtr, llvm::Module *);
bool LiftCodeIntoModule(NativeModulePtr, llvm::Module *);
#endif
+155 -196
View File
@@ -1,31 +1,31 @@
/*
Copyright (c) 2013, Trail of Bits
All rights reserved.
Copyright (c) 2013, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "toLLVM.h"
#include "raiseX86.h"
#include "Externals.h"
@@ -42,34 +42,30 @@ using namespace std;
// is a data reference or an immediate value; in some cases data is mapped
// at 0x0 and determining this could be tricky
bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0 ) {
list<DataSection> &sections = m->getData();
list<DataSection>::iterator it = sections.begin();
// sanity check:
// assume no data references before minAddr.
if (addr < minAddr) {
return false;
}
if(sections.size() == 0) {
llvm::dbgs() << __FUNCTION__ << ": WARNING: no data sections!\n";
return false;
}
while( it != sections.end() ) {
DataSection &curSec = *it;
VA low = curSec.getBase();
VA high = low+curSec.getSize();
if( addr >= low && addr < high ) {
base = low;
return true;
}
++it;
}
bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0) {
// sanity check:
// assume no data references before minAddr.
if (addr < minAddr) {
return false;
}
auto &sections = m->getData();
if (sections.empty()) {
llvm::dbgs() << __FUNCTION__ << ": WARNING: no data sections!\n";
return false;
}
for (auto &curSec : sections) {
VA low = curSec.getBase();
VA high = low + curSec.getSize();
if (addr >= low && addr < high) {
base = low;
return true;
}
}
return false;
}
// Compute a Value from a complex address expression
@@ -78,177 +74,140 @@ bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0 ) {
// that in the computation instead of assuming values
// are opaque immediates
namespace x86 {
Value *getAddrFromExpr( BasicBlock *b,
NativeModulePtr mod,
const MCOperand &Obase,
const MCOperand &Oscale,
const MCOperand &Oindex,
const int64_t Odisp,
const MCOperand &Oseg,
bool dataOffset)
{
TASSERT(Obase.isReg(), "");
TASSERT(Oscale.isImm(), "");
TASSERT(Oindex.isReg(), "");
TASSERT(Oseg.isReg(), "");
Value *getAddrFromExpr(BasicBlock *b, NativeModulePtr mod,
const MCOperand &Obase, const MCOperand &Oscale,
const MCOperand &Oindex, const int64_t Odisp,
const MCOperand &Oseg, bool dataOffset) {
TASSERT(Obase.isReg(), "");
TASSERT(Oscale.isImm(), "");
TASSERT(Oindex.isReg(), "");
TASSERT(Oseg.isReg(), "");
unsigned baseReg = Obase.getReg();
int64_t disp = Odisp;
unsigned baseReg = Obase.getReg();
int64_t disp = Odisp;
//first, we should ask, is disp an absolute reference to
//some global symbol in the original source module?
//if it is, we can replace its value with that of a pointer
//to global data
//HANDY HEURISTIC HACK
//if the base register is the stack pointer or the frame
//pointer, then skip this part
Value *d = NULL;
IntegerType *iTy = IntegerType::getInt32Ty(b->getContext());
//first, we should ask, is disp an absolute reference to
//some global symbol in the original source module?
//if it is, we can replace its value with that of a pointer
//to global data
//HANDY HEURISTIC HACK
//if the base register is the stack pointer or the frame
//pointer, then skip this part
Value *d = NULL;
IntegerType *iTy = IntegerType::getInt32Ty(b->getContext());
if( dataOffset ||
(mod && disp && baseReg != X86::EBP && baseReg!= X86::ESP) )
{
Value *int_val = getGlobalFromOriginalAddr<32>(
disp, mod, dataOffset ? 0 : 0x1000, b);
d = int_val;
} else {
//there is no disp value, or its relative to esp/ebp in which case
//we might not want to do anything
if (dataOffset
|| (mod && disp && baseReg != X86::EBP && baseReg != X86::ESP)) {
Value *int_val = getGlobalFromOriginalAddr<32>(disp, mod,
dataOffset ? 0 : 0x1000, b);
d = int_val;
} else {
//there is no disp value, or its relative to esp/ebp in which case
//we might not want to do anything
}
if (nullptr == d) {
//create a constant integer out of the raw displacement
//we were unable to assign the displacement to an address
d = ConstantInt::getSigned(iTy, disp);
}
Value *rVal = nullptr;
//read the base register (if given)
if (baseReg != X86::NoRegister) {
rVal = R_READ<32>(b, baseReg);
} else {
//if the base is not present, just use 0
rVal = CONST_V<32>(b, 0);
}
Value *dispComp;
dispComp = BinaryOperator::Create(Instruction::Add, rVal, d, "", b);
//add the index amount, if present
if (Oindex.getReg() != X86::NoRegister) {
Value *index = R_READ<32>(b, Oindex.getReg());
int64_t scaleAmt = Oscale.getImm();
if (scaleAmt > 1) {
index = BinaryOperator::CreateMul(index, CONST_V<32>(b, scaleAmt), "", b);
}
if( nullptr == d ) {
//create a constant integer out of the raw displacement
//we were unable to assign the displacement to an address
d = ConstantInt::getSigned(iTy, disp);
}
dispComp = BinaryOperator::CreateAdd(dispComp, index, "", b);
Value *rVal = nullptr;
}
//read the base register (if given)
if( baseReg != X86::NoRegister ) {
rVal = R_READ<32>(b, baseReg);
} else {
//if the base is not present, just use 0
rVal = CONST_V<32>(b, 0);
}
//convert the resulting integer into a pointer type
PointerType *piTy = Type::getInt32PtrTy(b->getContext());
Value *dispPtr = new IntToPtrInst(dispComp, piTy, "", b);
Value *dispComp;
dispComp =
BinaryOperator::Create( Instruction::Add, rVal, d, "", b);
//add the index amount, if present
if( Oindex.getReg() != X86::NoRegister ) {
Value *index = R_READ<32>(b, Oindex.getReg());
int64_t scaleAmt = Oscale.getImm();
if( scaleAmt > 1 ) {
index =
BinaryOperator::CreateMul(index,CONST_V<32>(b, scaleAmt),"",b);
}
dispComp =
BinaryOperator::CreateAdd(dispComp, index, "", b);
}
//convert the resulting integer into a pointer type
PointerType *piTy = Type::getInt32PtrTy(b->getContext());
Value *dispPtr = new IntToPtrInst(dispComp, piTy, "", b);
return dispPtr;
return dispPtr;
}
}
Value *getAddrFromExpr(BasicBlock *b, NativeModulePtr mod, const MCInst &inst,
NativeInstPtr ip, uint32_t which) {
const MCOperand& base = inst.getOperand(which + 0);
const MCOperand& scale = inst.getOperand(which + 1);
const MCOperand& index = inst.getOperand(which + 2);
const MCOperand& disp = inst.getOperand(which + 3);
const MCOperand& seg = inst.getOperand(which + 4);
Value *getAddrFromExpr( BasicBlock *b,
NativeModulePtr mod,
const MCInst &inst,
InstPtr ip,
uint32_t which)
{
const MCOperand& base = inst.getOperand( which +0);
const MCOperand& scale = inst.getOperand( which +1);
const MCOperand& index = inst.getOperand( which +2);
const MCOperand& disp = inst.getOperand( which +3);
const MCOperand& seg = inst.getOperand( which +4);
TASSERT(base.isReg(), "");
TASSERT(scale.isImm(), "");
TASSERT(index.isReg(), "");
TASSERT(disp.isImm(), "");
TASSERT(seg.isReg(), "");
TASSERT(base.isReg(), "");
TASSERT(scale.isImm(), "");
TASSERT(index.isReg(), "");
TASSERT(disp.isImm(), "");
TASSERT(seg.isReg(), "");
// determine if this instruction is using a memory reference
// or if the displacement should be used at face value
bool has_ref = ip->has_reference(NativeInst::MEMRef);
int64_t real_disp = has_ref ? ip->get_reference(NativeInst::MEMRef) : disp.getImm();
llvm::Module *M = b->getParent()->getParent();
// determine if this instruction is using a memory reference
// or if the displacement should be used at face value
bool has_ref = ip->has_reference(Inst::MEMRef);
int64_t real_disp = has_ref ? ip->get_reference(Inst::MEMRef) : disp.getImm();
llvm::Module *M = b->getParent()->getParent();
if(ArchPointerSize(M) == Pointer32) {
if (ArchPointerSize(M) == Pointer32) {
return x86::getAddrFromExpr(b,
mod,
base,
scale,
index,
real_disp,
seg,
has_ref);
} else {
return x86_64::getAddrFromExpr(b,
mod,
base,
scale,
index,
real_disp,
seg,
has_ref);
}
return x86::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
has_ref);
} else {
return x86_64::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
has_ref);
}
}
Value *MEM_AS_DATA_REF(BasicBlock *B,
NativeModulePtr natM,
const MCInst &inst,
InstPtr ip,
uint32_t which)
{
if(false == ip->has_mem_reference) {
throw TErr(__LINE__, __FILE__, "Want to use MEM as data ref but have no MEM reference");
}
return getAddrFromExpr(B, natM, inst, ip, which);
Value *MEM_AS_DATA_REF(BasicBlock *B, NativeModulePtr natM, const MCInst &inst,
NativeInstPtr ip, uint32_t which) {
if (false == ip->has_mem_reference) {
throw TErr(__LINE__, __FILE__,
"Want to use MEM as data ref but have no MEM reference");
}
return getAddrFromExpr(B, natM, inst, ip, which);
}
Instruction* callMemcpy(BasicBlock *B, Value *dest, Value *src, uint32_t size,
uint32_t align, bool isVolatile) {
Value *copySize = CONST_V<32>(B, size);
// ALIGN: 4 byte alignment, i think
Value *alignSize = CONST_V<32>(B, align);
// VOLATILE: false
Value *vIsVolatile = CONST_V<1>(B, isVolatile);
Instruction* callMemcpy(BasicBlock *B, Value *dest, Value *src, uint32_t size,
uint32_t align, bool isVolatile)
{
Value *copySize = CONST_V<32>(B, size);
// ALIGN: 4 byte alignment, i think
Value *alignSize = CONST_V<32>(B, align);
// VOLATILE: false
Value *vIsVolatile = CONST_V<1>(B, isVolatile);
Type *Tys[] = {dest->getType(), src->getType(), copySize->getType()};
Type *Tys[] = {
dest->getType(),
src->getType(),
copySize->getType()};
Module *M = B->getParent()->getParent();
Module *M = B->getParent()->getParent();
Function *doMemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys);
Function *doMemCpy =
Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys);
Value *callArgs[] = {dest, // DST
src, // SRC
copySize, // SIZE
alignSize, // ALIGN
vIsVolatile // VOLATILE
};
Value *callArgs[] = {
dest, // DST
src, // SRC
copySize, // SIZE
alignSize, // ALIGN
vIsVolatile // VOLATILE
};
// actually call llvm.memcpy
return CallInst::Create(doMemCpy, callArgs, "", B);
// actually call llvm.memcpy
return CallInst::Create(doMemCpy, callArgs, "", B);
}
+216 -221
View File
@@ -1,292 +1,287 @@
/*
Copyright (c) 2013, Trail of Bits
All rights reserved.
Copyright (c) 2013, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <string>
#include "ArchOps.h"
template <int width>
llvm::Value *getValueForExternal(llvm::Module *M, InstPtr ip, llvm::BasicBlock *block) {
template<int width>
llvm::Value *getValueForExternal(llvm::Module *M, NativeInstPtr ip,
llvm::BasicBlock *block) {
llvm::Value *addrInt = NULL;
llvm::Value *addrInt = NULL;
if( ip->has_ext_call_target() ) {
std::string target = ip->get_ext_call_target()->getSymbolName();
llvm::Value *ext_fn = M->getFunction(target);
TASSERT(ext_fn != NULL, "Could not find external: " + target);
addrInt = new llvm::PtrToIntInst(
ext_fn, llvm::Type::getIntNTy(block->getContext(), width), "", block);
} else if (ip->has_ext_data_ref() ) {
std::string target = ip->get_ext_data_ref()->getSymbolName();
llvm::GlobalValue *gvar = M->getGlobalVariable(target);
TASSERT(gvar != NULL, "Could not find external data: " + target);
std::cout << __FUNCTION__ << ": Found external data ref to: " << target << "\n";
if (SystemOS(M) == llvm::Triple::Win32) {
gvar->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
// sometimes windows will import this directly as the variable instead of
// as a reference to a variable. But the rest of the code wants a pointer to var
llvm::Value *toPtr = new llvm::AllocaInst(gvar->getType(), "", block);
llvm::Value *writeIt = new llvm::StoreInst(gvar, toPtr, block);
addrInt = new llvm::PtrToIntInst(
toPtr, llvm::Type::getIntNTy(block->getContext(), width), "", block);
} else {
addrInt = new llvm::PtrToIntInst(
gvar, llvm::Type::getIntNTy(block->getContext(), width), "", block);
}
if (ip->has_ext_call_target()) {
std::string target = ip->get_ext_call_target()->getSymbolName();
llvm::Value *ext_fn = M->getFunction(target);
TASSERT(ext_fn != NULL, "Could not find external: " + target);
addrInt = new llvm::PtrToIntInst(
ext_fn, llvm::Type::getIntNTy(block->getContext(), width), "", block);
} else if (ip->has_ext_data_ref()) {
std::string target = ip->get_ext_data_ref()->getSymbolName();
llvm::GlobalValue *gvar = M->getGlobalVariable(target);
TASSERT(gvar != NULL, "Could not find external data: " + target);
std::cout << __FUNCTION__ << ": Found external data ref to: " << target
<< "\n";
if (SystemOS(M) == llvm::Triple::Win32) {
gvar->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
// sometimes windows will import this directly as the variable instead of
// as a reference to a variable. But the rest of the code wants a pointer to var
llvm::Value *toPtr = new llvm::AllocaInst(gvar->getType(), "", block);
llvm::Value *writeIt = new llvm::StoreInst(gvar, toPtr, block);
addrInt = new llvm::PtrToIntInst(
toPtr, llvm::Type::getIntNTy(block->getContext(), width), "", block);
} else {
throw TErr(__LINE__, __FILE__, "No external refernce to get value for!");
addrInt = new llvm::PtrToIntInst(
gvar, llvm::Type::getIntNTy(block->getContext(), width), "", block);
}
return addrInt;
} else {
throw TErr(__LINE__, __FILE__, "No external refernce to get value for!");
}
return addrInt;
}
template <int width>
template<int width>
llvm::Value *concatInts(llvm::BasicBlock *b, llvm::Value *a1, llvm::Value *a2) {
TASSERT(width == 8 || width == 16 || width == 32 || width == 64, "");
llvm::Type *typeTo = llvm::Type::getIntNTy(b->getContext(), width*2);
TASSERT(typeTo != NULL, "");
//bitcast a to twice width
assert(a1->getType()->getScalarSizeInBits() < typeTo->getScalarSizeInBits());
llvm::Value *twiceLarger = new llvm::ZExtInst(a1, typeTo, "", b);
//shift twiceL to the left by width
llvm::Value *tlShifted = llvm::BinaryOperator::Create(llvm::Instruction::Shl,
twiceLarger,
CONST_V<width*2>(b, width),
"",
b);
TASSERT(width == 8 || width == 16 || width == 32 || width == 64, "");
llvm::Type *typeTo = llvm::Type::getIntNTy(b->getContext(), width * 2);
//add a2 to the result, after zero-extending a2
llvm::Value *a2Larger = new llvm::SExtInst(a2, typeTo, "", b);
llvm::Value *addRes =
llvm::BinaryOperator::CreateOr(tlShifted, a2Larger, "", b);
TASSERT(typeTo != NULL, "");
//bitcast a to twice width
assert(a1->getType()->getScalarSizeInBits() < typeTo->getScalarSizeInBits());
llvm::Value *twiceLarger = new llvm::ZExtInst(a1, typeTo, "", b);
//shift twiceL to the left by width
llvm::Value *tlShifted = llvm::BinaryOperator::Create(
llvm::Instruction::Shl, twiceLarger, CONST_V<width * 2>(b, width), "", b);
return addRes;
//add a2 to the result, after zero-extending a2
llvm::Value *a2Larger = new llvm::SExtInst(a2, typeTo, "", b);
llvm::Value *addRes = llvm::BinaryOperator::CreateOr(tlShifted, a2Larger, "",
b);
return addRes;
}
// Compute a complex address expression, such as
// [0x1245678+eax*4] and return a Value that represents the computation
// result
llvm::Value *getAddrFromExpr(
llvm::BasicBlock *b,
NativeModulePtr mod,
const llvm::MCInst &inst,
InstPtr ip,
uint32_t which);
llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
const llvm::MCInst &inst, NativeInstPtr ip,
uint32_t which);
bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr);
template <int width>
llvm::Value* getGlobalFromOriginalAddr(
VA original_addr, NativeModulePtr mod,
VA addr_start, llvm::BasicBlock *b)
{
VA baseGlobal;
if( addrIsInData(original_addr, mod, baseGlobal, addr_start) ) {
//we should be able to find a reference to this in global data
llvm::Module *M = b->getParent()->getParent();
std::string sn = "data_0x" + to_string<VA>(baseGlobal, std::hex);
template<int width>
llvm::Value* getGlobalFromOriginalAddr(VA original_addr, NativeModulePtr mod,
VA addr_start, llvm::BasicBlock *b) {
VA baseGlobal;
if (addrIsInData(original_addr, mod, baseGlobal, addr_start)) {
//we should be able to find a reference to this in global data
llvm::Module *M = b->getParent()->getParent();
std::string sn = "data_0x" + to_string<VA>(baseGlobal, std::hex);
llvm::GlobalVariable *gData = M->getNamedGlobal(sn);
llvm::GlobalVariable *gData = M->getNamedGlobal(sn);
//if we thought it was a global, we should be able to
//pin it to a global array we made during module setup
if( gData == NULL)
throw TErr(__LINE__, __FILE__, "Global variable not found");
//if we thought it was a global, we should be able to
//pin it to a global array we made during module setup
if (gData == NULL)
throw TErr(__LINE__, __FILE__, "Global variable not found");
// since globals are now a structure
// we cannot simply slice into them.
// Need to get ptr and then add integer displacement to ptr
//
llvm::Type *int_ty = llvm::Type::getIntNTy(b->getContext(), width);
llvm::Value *globalGEPV[] =
{ llvm::ConstantInt::get(int_ty, 0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(b->getContext()), 0)
};
llvm::Instruction *globalGEP =
llvm::GetElementPtrInst::Create(gData, globalGEPV, "", b);
llvm::Value *intVal = new llvm::PtrToIntInst(globalGEP, int_ty, "", b);
uint64_t addr_offset = original_addr-baseGlobal;
llvm::Value *int_adjusted =
llvm::BinaryOperator::CreateAdd(intVal, CONST_V<width>(b, addr_offset), "", b);
return int_adjusted;
} else {
return nullptr;
}
// since globals are now a structure
// we cannot simply slice into them.
// Need to get ptr and then add integer displacement to ptr
//
llvm::Type *int_ty = llvm::Type::getIntNTy(b->getContext(), width);
llvm::Value *globalGEPV[] = {llvm::ConstantInt::get(int_ty, 0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(b->getContext()), 0)};
llvm::Instruction *globalGEP = llvm::GetElementPtrInst::Create(gData,
globalGEPV,
"", b);
llvm::Value *intVal = new llvm::PtrToIntInst(globalGEP, int_ty, "", b);
uint64_t addr_offset = original_addr - baseGlobal;
llvm::Value *int_adjusted = llvm::BinaryOperator::CreateAdd(
intVal, CONST_V<width>(b, addr_offset), "", b);
return int_adjusted;
} else {
return nullptr;
}
}
// same as the simpler form, see above
namespace x86 {
llvm::Value *getAddrFromExpr( llvm::BasicBlock *b,
NativeModulePtr mod,
const llvm::MCOperand &Obase,
const llvm::MCOperand &Oscale,
const llvm::MCOperand &Oindex,
const int64_t Odisp,
const llvm::MCOperand &Oseg,
bool dataOffset);
llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
const llvm::MCOperand &Obase,
const llvm::MCOperand &Oscale,
const llvm::MCOperand &Oindex, const int64_t Odisp,
const llvm::MCOperand &Oseg, bool dataOffset);
}
namespace x86_64 {
llvm::Value *getAddrFromExpr( llvm::BasicBlock *b,
NativeModulePtr mod,
const llvm::MCOperand &Obase,
const llvm::MCOperand &Oscale,
const llvm::MCOperand &Oindex,
const int64_t Odisp,
const llvm::MCOperand &Oseg,
bool dataOffset);
llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
const llvm::MCOperand &Obase,
const llvm::MCOperand &Oscale,
const llvm::MCOperand &Oindex, const int64_t Odisp,
const llvm::MCOperand &Oseg, bool dataOffset);
}
// Convert the number to a constant in LLVM IR
llvm::ConstantInt *CONST_V(llvm::BasicBlock *b, uint64_t val);
// this is an alias for getAddressFromExpr, but used when
// we expect the address computation to contain a data reference
llvm::Value *MEM_AS_DATA_REF(llvm::BasicBlock *B,
NativeModulePtr natM,
const llvm::MCInst &inst,
InstPtr ip,
uint32_t which);
llvm::Value *MEM_AS_DATA_REF(llvm::BasicBlock *B, NativeModulePtr natM,
const llvm::MCInst &inst, NativeInstPtr ip,
uint32_t which);
// emit an llvm memcpy intrinsic
llvm::Instruction* callMemcpy(llvm::BasicBlock *B, llvm::Value *dest, llvm::Value *src, uint32_t size,
uint32_t align=4, bool isVolatile=false);
llvm::Instruction* callMemcpy(llvm::BasicBlock *B, llvm::Value *dest,
llvm::Value *src, uint32_t size, uint32_t align =
4,
bool isVolatile = false);
using namespace llvm;
using namespace std;
// return a computed pointer to that data reference for 32/64 bit architecture
template <int width>
llvm::Value* IMM_AS_DATA_REF(BasicBlock *b, NativeModulePtr mod , InstPtr ip)
{
TASSERT(width == 32 || width == 64, "Pointer size must be sane");
VA baseGlobal;
// off is the displacement part of a memory reference
template<int width>
llvm::Value* IMM_AS_DATA_REF(llvm::BasicBlock *B, NativeModulePtr mod,
NativeInstPtr ip) {
auto &C = B->getContext();
if( ip->has_external_ref()) {
Function *F = b->getParent();
Value *addrInt = getValueForExternal<width>(F->getParent(), ip, b);
TASSERT(addrInt != 0, "Could not get external data reference");
return addrInt;
}
TASSERT(width == 32 || width == 64, "Pointer size must be sane");
VA baseGlobal;
// off is the displacement part of a memory reference
if(false == ip->has_imm_reference) {
throw TErr(__LINE__, __FILE__, "Want to use IMM as data ref but have no IMM reference");
}
uint64_t off = ip->get_reference(Inst::IMMRef);
if(ip->has_code_ref()) {
Value *callback_fn = ArchAddCallbackDriver(
b->getParent()->getParent(),
ip->get_reference(Inst::IMMRef));
Value *addrInt = new PtrToIntInst(
callback_fn, llvm::Type::getIntNTy(b->getContext(), width), "", b);
return addrInt;
} else if( addrIsInData(off, mod, baseGlobal, 0) ) {
//we should be able to find a reference to this in global data
Module *M = b->getParent()->getParent();
string sn = "data_0x" + to_string<VA>(baseGlobal, hex);
Value *int_adjusted;
GlobalVariable *gData = M->getNamedGlobal(sn);
if (ip->has_external_ref()) {
Function *F = B->getParent();
Value *addrInt = getValueForExternal<width>(F->getParent(), ip, B);
TASSERT(addrInt != 0, "Could not get external data reference");
return addrInt;
}
//if we thought it was a global, we should be able to
//pin it to a global variable we made during module setup
if( gData == NULL)
throw TErr(__LINE__, __FILE__, "Global variable not found");
if (false == ip->has_imm_reference) {
throw TErr(__LINE__, __FILE__,
"Want to use IMM as data ref but have no IMM reference");
}
uint64_t off = ip->get_reference(NativeInst::IMMRef);
// since globals are now a structure
// we cannot simply slice into them.
// Need to get ptr and then add integer displacement to ptr
if (ip->has_code_ref()) {
auto callback_fn = ArchAddCallbackDriver(
B->getParent()->getParent(), ip->get_reference(NativeInst::IMMRef));
auto addrInt = new llvm::PtrToIntInst(callback_fn,
llvm::Type::getIntNTy(C, width), "",
B);
return addrInt;
Value *globalGEPV[] =
{ ConstantInt::get(Type::getIntNTy(b->getContext(), width), 0),
ConstantInt::get(Type::getInt32Ty(b->getContext()), 0)};
Instruction *globalGEP =
GetElementPtrInst::Create(gData, globalGEPV, "", b);
Type *ty = Type::getIntNTy(b->getContext(), width);
Value *intVal = new PtrToIntInst(globalGEP, ty, "", b);
uint32_t addr_offset = off-baseGlobal;
int_adjusted = BinaryOperator::CreateAdd(intVal,
CONST_V<width>(b, addr_offset), "", b);
//then, assign this to the outer 'd' so that the rest of the
//logic picks up on that address instead of another address
} else if (addrIsInData(off, mod, baseGlobal, 0)) {
//we should be able to find a reference to this in global data
auto M = B->getParent()->getParent();
std::string sn = "data_0x" + to_string<VA>(baseGlobal, hex);
llvm::Value *int_adjusted = nullptr;
auto gData = M->getNamedGlobal(sn);
return int_adjusted;
} else {
throw TErr(__LINE__, __FILE__, "Address not in data");
return NULL;
}
//if we thought it was a global, we should be able to
//pin it to a global variable we made during module setup
if (gData == NULL)
throw TErr(__LINE__, __FILE__, "Global variable not found");
// since globals are now a structure
// we cannot simply slice into them.
// Need to get ptr and then add integer displacement to ptr
llvm::Value *globalGEPV[] = {llvm::ConstantInt::get(
llvm::Type::getIntNTy(C, width), 0), llvm::ConstantInt::get(
llvm::Type::getInt32Ty(C), 0)};
auto globalGEP = llvm::GetElementPtrInst::Create(gData, globalGEPV, "", B);
auto ty = llvm::Type::getIntNTy(C, width);
auto intVal = new llvm::PtrToIntInst(globalGEP, ty, "", B);
uint32_t addr_offset = off - baseGlobal;
int_adjusted = llvm::BinaryOperator::CreateAdd(
intVal, CONST_V<width>(B, addr_offset), "", B);
//then, assign this to the outer 'd' so that the rest of the
//logic picks up on that address instead of another address
return int_adjusted;
} else {
throw TErr(__LINE__, __FILE__, "Address not in data");
return NULL;
}
}
// Assume the instruction has a data reference, and
// return a computed pointer to that data reference
static inline llvm::Value* IMM_AS_DATA_REF(llvm::BasicBlock *b,
NativeModulePtr mod,
InstPtr ip)
{
llvm::Module *M = b->getParent()->getParent();
int regWidth = ArchPointerSize(M);
if(regWidth <= x86::REG_SIZE) {
return IMM_AS_DATA_REF<32>(b, mod, ip);
} else {
return IMM_AS_DATA_REF<64>(b, mod, ip);
}
static inline llvm::Value* IMM_AS_DATA_REF(llvm::BasicBlock *b,
NativeModulePtr mod,
NativeInstPtr ip) {
auto M = b->getParent()->getParent();
int regWidth = ArchPointerSize(M);
if (regWidth <= x86::REG_SIZE) {
return IMM_AS_DATA_REF<32>(b, mod, ip);
} else {
return IMM_AS_DATA_REF<64>(b, mod, ip);
}
}
inline llvm::PointerType *getVoidPtrType (llvm::LLVMContext & C) {
llvm::Type * Int8Type = llvm::IntegerType::getInt8Ty(C);
return llvm::PointerType::getUnqual(Int8Type);
inline llvm::PointerType *getVoidPtrType(llvm::LLVMContext & C) {
auto Int8Type = llvm::IntegerType::getInt8Ty(C);
return llvm::PointerType::getUnqual(Int8Type);
}
template <int width>
static inline Value *ADDR_NOREF_IMPL(NativeModulePtr natM, llvm::BasicBlock *b, int x, InstPtr ip, const llvm::MCInst &inst) {
template<int width>
static inline llvm::Value *ADDR_NOREF_IMPL(NativeModulePtr natM,
llvm::BasicBlock *b, int x,
NativeInstPtr ip,
const llvm::MCInst &inst) {
// Turns out this function name is a lie. This case can ref external data
llvm::Module *M = b->getParent()->getParent();
if(ip->has_external_ref()) {
llvm::Value *addrInt = getValueForExternal<width>(M, ip, b);
TASSERT(addrInt != NULL, "Could not get address for external");
return addrInt;
}
// Turns out this function name is a lie. This case can ref external data
auto M = b->getParent()->getParent();
if (ip->has_external_ref()) {
auto addrInt = getValueForExternal<width>(M, ip, b);
TASSERT(addrInt != NULL, "Could not get address for external");
return addrInt;
}
if(ArchPointerSize(M) == Pointer32) {
return x86::getAddrFromExpr(b, natM, inst.getOperand(x+0), inst.getOperand(x+1), inst.getOperand(x+2), inst.getOperand(x+3).getImm(), inst.getOperand(x+4), false);
} else {
return x86_64::getAddrFromExpr(b, natM, inst.getOperand(x+0), inst.getOperand(x+1), inst.getOperand(x+2), inst.getOperand(x+3).getImm(), inst.getOperand(x+4), false);
}
if (ArchPointerSize(M) == Pointer32) {
return x86::getAddrFromExpr(b, natM, inst.getOperand(x + 0),
inst.getOperand(x + 1), inst.getOperand(x + 2),
inst.getOperand(x + 3).getImm(),
inst.getOperand(x + 4), false);
} else {
return x86_64::getAddrFromExpr(b, natM, inst.getOperand(x + 0),
inst.getOperand(x + 1),
inst.getOperand(x + 2),
inst.getOperand(x + 3).getImm(),
inst.getOperand(x + 4), false);
}
}
+38 -59
View File
@@ -56,9 +56,9 @@ using namespace x86;
// currently used to turn non-conforming jump talbles
// into data sections
//
static void preprocessInstruction(NativeModulePtr natM, BasicBlock *&block,
InstPtr ip, MCInst &inst) {
static void PreProcessInst(TranslationContext &ctx, llvm::BasicBlock *&block) {
auto ip = ctx.natI;
auto &inst = ip->get_inst();
// only add data sections for non-conformant jump tables
//
// the conformant tables are handled in the instruction
@@ -67,46 +67,41 @@ static void preprocessInstruction(NativeModulePtr natM, BasicBlock *&block,
if ( !isConformantJumpInst(ip)) {
{
llvm::dbgs() << "WARNING: jump table but non-conformant instruction:\n";
llvm::dbgs() << to_string<VA>(ip->get_loc(), hex) << ": ";
llvm::dbgs() << to_string<VA>(ip->get_loc(), std::hex) << ": ";
llvm::dbgs() << inst << "\n";
VA tbl_va;
MCSJumpTablePtr jmptbl = ip->get_jump_table();
VA tbl_va = 0;
auto jmptbl = ip->get_jump_table();
bool ok = addJumpTableDataSection(natM, block->getParent()->getParent(),
tbl_va, *jmptbl);
bool ok = addJumpTableDataSection(ctx, tbl_va, *jmptbl);
TASSERT(ok, "Could not add jump table data section!\n");
uint32_t data_ref_va = static_cast<uint32_t>(tbl_va
+ 4 * jmptbl->getInitialEntry());
auto data_ref_va = static_cast<uint32_t>(tbl_va
+ (4 * jmptbl->getInitialEntry()));
ip->set_reference(Inst::MEMRef, data_ref_va);
ip->set_ref_type(Inst::MEMRef, Inst::CFGDataRef);
ip->set_reference(NativeInst::MEMRef, data_ref_va);
ip->set_ref_type(NativeInst::MEMRef, NativeInst::CFGDataRef);
}
}
}
// only add data references for unknown jump index table
// reads
else if (ip->has_jump_index_table() && inst.getOpcode() != X86::MOVZX32rm8) {
VA idx_va;
// only add data references for unknown jump index table reads
} else if (ip->has_jump_index_table() &&
inst.getOpcode() != llvm::X86::MOVZX32rm8) {
VA idx_va = 0;
JumpIndexTablePtr idxtbl = ip->get_jump_index_table();
bool ok = addJumpIndexTableDataSection(natM,
block->getParent()->getParent(),
idx_va, *idxtbl);
bool ok = addJumpIndexTableDataSection(ctx, idx_va, *idxtbl);
TASSERT(ok, "Could not add jump index table data section!\n");
uint32_t data_ref_va = static_cast<uint32_t>(idx_va
+ idxtbl->getInitialEntry());
ip->set_reference(Inst::MEMRef, data_ref_va);
ip->set_ref_type(Inst::MEMRef, Inst::CFGDataRef);
ip->set_reference(NativeInst::MEMRef, data_ref_va);
ip->set_ref_type(NativeInst::MEMRef, NativeInst::CFGDataRef);
}
}
// Take the supplied MCInst and turn it into a series of LLVM instructions.
@@ -135,56 +130,40 @@ static void preprocessInstruction(NativeModulePtr natM, BasicBlock *&block,
//
// The innermost is where most of the intelligent decisions happen.
//
InstTransResult liftInstrImpl(InstPtr ip, BasicBlock *&block, NativeBlockPtr nb,
Function *F, NativeFunctionPtr natF,
NativeModulePtr natM) {
MCInst inst = ip->get_inst();
InstTransResult LiftInstIntoBlockImpl(TranslationContext &ctx,
llvm::BasicBlock *&block) {
InstTransResult itr = ContinueBlock;
string outS;
raw_string_ostream strOut(outS);
MCInstPrinter *IP = nb->get_printer();
if (IP == NULL) {
throw TErr(__LINE__, __FILE__,
"No instruction printer supplied with native block");
}
// For conditional instructions, get the "true" and "false" targets.
// This will also look up the target for nonconditional jumps.
//string trueStrName = "block_0x" + to_string<VA>(ip->get_tr(), hex);
//string falseStrName = "block_0x" + to_string<VA>(ip->get_fa(), hex);
TranslationFuncPtr translationPtr;
auto &inst = ctx.natI->get_inst();
auto opcode = inst.getOpcode();
unsigned opcode = inst.getOpcode();
if (translationDispatchMap.find(opcode) != translationDispatchMap.end()) {
// Instruction translation defined.
translationPtr = translationDispatchMap[opcode];
preprocessInstruction(natM, block, ip, inst);
itr = translationPtr(natM, block, ip, inst);
if (translationDispatchMap.count(opcode)) {
auto translationPtr = translationDispatchMap[opcode];
PreProcessInst(ctx, block);
itr = translationPtr(ctx, block);
if (TranslateError == itr || TranslateErrorUnsupported == itr) {
errs() << "Error translating!";
IP->printInst( &inst, errs(), to_string<VA>(ip->get_loc(), hex));
errs() << "\n";
std::cerr << "Error translating instruction at " << std::hex
<< ctx.natI->get_loc() << std::endl;
}
} else {
// Instruction translation not defined.
errs() << "Unsupported opcode " << opcode << "!";
IP->printInst( &inst, errs(), to_string<VA>(ip->get_loc(), hex));
// Print out the unhandled opcode.
errs() << to_string<VA>(ip->get_loc(), hex) << " ";
errs() << strOut.str() << "\n";
errs() << inst.getOpcode() << "\n";
if (X86::REP_PREFIX != opcode && X86::REPNE_PREFIX != opcode) {
} else {
std::cerr << "Error translating instruction at " << std::hex
<< ctx.natI->get_loc() << "; unsupported opcode " << std::dec
<< opcode << std::endl;
if (llvm::X86::REP_PREFIX != opcode && llvm::X86::REPNE_PREFIX != opcode) {
itr = TranslateErrorUnsupported;
} else {
errs()
<< "Unsupported instruction is a rep/repne, trying to skip to next instr.\n";
std::cerr
<< "Unsupported instruction is a rep/repne, trying to skip to next instr."
<< std::endl;
}
}
//D(cout << __FUNCTION__ << " : " << opcode << "\n";
//cout.flush();)
return itr;
}
+3 -6
View File
@@ -26,9 +26,6 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
InstTransResult liftInstrImpl( InstPtr ip,
llvm::BasicBlock *&block,
NativeBlockPtr nb,
llvm::Function *F,
NativeFunctionPtr natF,
NativeModulePtr natM);
struct TranslationContext;
InstTransResult LiftInstIntoBlockImpl(TranslationContext &ctx,
llvm::BasicBlock *&block);
+19 -19
View File
@@ -45,7 +45,7 @@ static InstTransResult doNoop(BasicBlock *b) {
GENERIC_TRANSLATION(NOOP, doNoop(block))
template <int width>
static Value * doAddVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs)
static Value * doAddVV(NativeInstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs)
{
// Add src1 to the constant formed by src2.
Value *addRes = BinaryOperator::Create(Instruction::Add, rhs, lhs, "", b);
@@ -68,7 +68,7 @@ static Value * doAddVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs)
}
template <int width>
static InstTransResult doAddMI(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddMI(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &imm)
{
@@ -86,7 +86,7 @@ static InstTransResult doAddMI(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAddMV(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddMV(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
Value *rhs)
{
@@ -103,7 +103,7 @@ static InstTransResult doAddMV(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAddMR(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddMR(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &reg)
{
@@ -121,7 +121,7 @@ static InstTransResult doAddMR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAddRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst,
const MCOperand &src1,
const MCOperand &src2)
@@ -146,7 +146,7 @@ static InstTransResult doAddRI(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAddRM(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddRM(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &o1,
const MCOperand &o2)
@@ -171,7 +171,7 @@ static InstTransResult doAddRM(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAddRV(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddRV(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &o1,
const MCOperand &o2)
@@ -196,7 +196,7 @@ static InstTransResult doAddRV(InstPtr ip, BasicBlock *&b,
template <int width>
static InstTransResult doAddRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doAddRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst,
const MCOperand &o1,
const MCOperand &o2)
@@ -220,7 +220,7 @@ static InstTransResult doAddRR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static Value * doAdcVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *src)
static Value * doAdcVV(NativeInstPtr ip, BasicBlock *&b, Value *dst, Value *src)
{
Type *t;
@@ -259,7 +259,7 @@ static Value * doAdcVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *src)
}
template <int width>
static InstTransResult doAdcRV(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcRV(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &o1,
const MCOperand &o2)
@@ -281,7 +281,7 @@ static InstTransResult doAdcRV(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcI(InstPtr ip, BasicBlock *&b, const MCOperand &src)
static InstTransResult doAdcI(NativeInstPtr ip, BasicBlock *&b, const MCOperand &src)
{
TASSERT(src.isImm(), "");
@@ -330,7 +330,7 @@ static InstTransResult doAdcI(InstPtr ip, BasicBlock *&b, const MCOperand &src)
}
template <int width>
static InstTransResult doAdcMI(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcMI(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &src)
{
@@ -348,7 +348,7 @@ static InstTransResult doAdcMI(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcMV(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcMV(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
Value *rhs)
{
@@ -366,7 +366,7 @@ static InstTransResult doAdcMV(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcMI8(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcMI8(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &src)
{
@@ -389,7 +389,7 @@ static InstTransResult doAdcMI8(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcMR(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcMR(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &reg)
{
@@ -407,7 +407,7 @@ static InstTransResult doAdcMR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst,
const MCOperand &o1,
const MCOperand &o2)
@@ -427,7 +427,7 @@ static InstTransResult doAdcRI(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcRI8(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcRI8(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst,
const MCOperand &o1,
const MCOperand &o2)
@@ -452,7 +452,7 @@ static InstTransResult doAdcRI8(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcRM(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcRM(NativeInstPtr ip, BasicBlock *&b,
Value *addr,
const MCOperand &o1,
const MCOperand &o2)
@@ -477,7 +477,7 @@ static InstTransResult doAdcRM(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doAdcRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doAdcRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst,
const MCOperand &o1,
const MCOperand &o2)
File diff suppressed because it is too large Load Diff
+9 -3
View File
@@ -94,8 +94,11 @@ static InstTransResult doCMOV(
return ContinueBlock;
}
#define EMIT_CMOV_RM(width, condition) [] (NativeModulePtr natM, BasicBlock *&block, InstPtr ip, MCInst &inst)->InstTransResult {\
BasicBlock *b = block;\
#define EMIT_CMOV_RM(width, condition) [] (TranslationContext &ctx, BasicBlock *&block)->InstTransResult {\
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
auto natM = ctx.natM; \
llvm::BasicBlock *b = block;\
if( ip->has_mem_reference ) {\
return doCMOV<width>(block, OP(0), condition, M_READ<width>(ip, b, MEM_REFERENCE(2)));\
}else {\
@@ -103,7 +106,10 @@ static InstTransResult doCMOV(
}\
}
#define EMIT_CMOV_RR(width, condition) [] (NativeModulePtr natM, BasicBlock *&b, InstPtr ip, MCInst &inst)->InstTransResult {\
#define EMIT_CMOV_RR(width, condition) [] (TranslationContext &ctx, BasicBlock *&b)->InstTransResult {\
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
auto natM = ctx.natM; \
return doCMOV<width>(b, OP(0), condition, R_READ<width>(b, OP(2).getReg())); \
}
+14 -15
View File
@@ -35,12 +35,11 @@
#include "llvm/Support/Debug.h"
#define NASSERT(cond) TASSERT(cond, "")
#define INSTR_DEBUG(ip) llvm::dbgs() << __FUNCTION__ << "\tRepresentation: " << ip->printInst() << "\n"
using namespace llvm;
template<int width>
static InstTransResult doCmpRR(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
static InstTransResult doCmpRR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &lhs,
const MCOperand &rhs) {
NASSERT(lhs.isReg());
NASSERT(rhs.isReg());
@@ -54,7 +53,7 @@ static InstTransResult doCmpRR(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
}
template<int width>
static InstTransResult doCmpRI(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
static InstTransResult doCmpRI(NativeInstPtr ip, BasicBlock *&b, const MCOperand &lhs,
const MCOperand &rhs) {
NASSERT(lhs.isReg());
NASSERT(rhs.isImm());
@@ -68,7 +67,7 @@ static InstTransResult doCmpRI(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
}
template<int width>
static InstTransResult doCmpRV(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
static InstTransResult doCmpRV(NativeInstPtr ip, BasicBlock *&b, const MCOperand &lhs,
llvm::Value *rhs) {
NASSERT(lhs.isReg());
@@ -81,7 +80,7 @@ static InstTransResult doCmpRV(InstPtr ip, BasicBlock *&b, const MCOperand &lhs,
}
template<int width>
static InstTransResult doCmpMR(InstPtr ip, BasicBlock *&b, Value *mem,
static InstTransResult doCmpMR(NativeInstPtr ip, BasicBlock *&b, Value *mem,
const MCOperand &reg) {
NASSERT(reg.isReg());
NASSERT(mem!=NULL);
@@ -99,7 +98,7 @@ static InstTransResult doCmpMR(InstPtr ip, BasicBlock *&b, Value *mem,
}
template<int width>
static InstTransResult doCmpRM(InstPtr ip, BasicBlock *&b, const MCOperand &reg,
static InstTransResult doCmpRM(NativeInstPtr ip, BasicBlock *&b, const MCOperand &reg,
Value *mem) {
NASSERT(reg.isReg());
NASSERT(mem!=NULL);
@@ -117,7 +116,7 @@ static InstTransResult doCmpRM(InstPtr ip, BasicBlock *&b, const MCOperand &reg,
}
template<int width>
static InstTransResult doCmpMI(InstPtr ip, BasicBlock *&b, Value *r1,
static InstTransResult doCmpMI(NativeInstPtr ip, BasicBlock *&b, Value *r1,
const MCOperand &r2) {
NASSERT(r1 != NULL);
NASSERT(r2.isImm());
@@ -132,7 +131,7 @@ static InstTransResult doCmpMI(InstPtr ip, BasicBlock *&b, Value *r1,
}
template<int width>
static InstTransResult doCmpMV(InstPtr ip, BasicBlock *&b, Value *r1,
static InstTransResult doCmpMV(NativeInstPtr ip, BasicBlock *&b, Value *r1,
Value *rhs) {
NASSERT(r1 != NULL);
NASSERT(rhs != NULL);
@@ -146,7 +145,7 @@ static InstTransResult doCmpMV(InstPtr ip, BasicBlock *&b, Value *r1,
}
template<int width>
static void doTestVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
static void doTestVV(NativeInstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
Value *temp = BinaryOperator::CreateAnd(lhs, rhs, "", b);
@@ -177,7 +176,7 @@ static void doTestVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
}
template<int width>
static InstTransResult doTestMI(InstPtr ip, BasicBlock *&b, Value *lhs,
static InstTransResult doTestMI(NativeInstPtr ip, BasicBlock *&b, Value *lhs,
const MCOperand &rhs) {
NASSERT(lhs != NULL);
NASSERT(rhs.isImm());
@@ -189,7 +188,7 @@ static InstTransResult doTestMI(InstPtr ip, BasicBlock *&b, Value *lhs,
}
template<int width>
static InstTransResult doTestMV(InstPtr ip, BasicBlock *&b, Value *lhs,
static InstTransResult doTestMV(NativeInstPtr ip, BasicBlock *&b, Value *lhs,
Value *rhs) {
NASSERT(lhs != NULL);
NASSERT(rhs != NULL);
@@ -200,7 +199,7 @@ static InstTransResult doTestMV(InstPtr ip, BasicBlock *&b, Value *lhs,
}
template<int width>
static InstTransResult doTestRM(InstPtr ip, BasicBlock *&b,
static InstTransResult doTestRM(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &lhs, Value *rhs) {
NASSERT(rhs != NULL);
NASSERT(lhs.isReg());
@@ -212,7 +211,7 @@ static InstTransResult doTestRM(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doTestRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doTestRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &lhs, const MCOperand &rhs) {
NASSERT(lhs.isReg());
NASSERT(rhs.isReg());
@@ -224,7 +223,7 @@ static InstTransResult doTestRR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doTestRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doTestRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &lhs, const MCOperand &rhs) {
NASSERT(lhs.isReg());
NASSERT(rhs.isImm());
@@ -236,7 +235,7 @@ static InstTransResult doTestRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doTestRV(InstPtr ip, BasicBlock *&b,
static InstTransResult doTestRV(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &lhs, llvm::Value *rhs) {
NASSERT(lhs.isReg());
+1 -1
View File
@@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void CMPTEST_populateDispatchMap(DispatchMap &m);
template <int width>
void doCmpVV(InstPtr ip, llvm::BasicBlock *b, llvm::Value *lhs, llvm::Value *rhs) {
void doCmpVV(NativeInstPtr ip, llvm::BasicBlock *b, llvm::Value *lhs, llvm::Value *rhs) {
llvm::Value *subRes = llvm::BinaryOperator::Create(Instruction::Sub, lhs, rhs, "", b);
+6 -6
View File
@@ -37,7 +37,7 @@
#define NASSERT(cond) TASSERT(cond, "")
template<int width>
static InstTransResult doCmpxchgRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doCmpxchgRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dstReg,
const MCOperand &srcReg) {
NASSERT(dstReg.isReg());
@@ -101,7 +101,7 @@ static InstTransResult doCmpxchgRR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doCmpxchgRM(InstPtr ip, BasicBlock *&b, Value *dstAddr,
static InstTransResult doCmpxchgRM(NativeInstPtr ip, BasicBlock *&b, Value *dstAddr,
const MCOperand &srcReg) {
NASSERT(dstAddr != NULL);
NASSERT(srcReg.isReg());
@@ -180,7 +180,7 @@ static InstTransResult doCmpxchgRM(InstPtr ip, BasicBlock *&b, Value *dstAddr,
}
template<int width>
static InstTransResult doXaddRM(InstPtr ip, BasicBlock *&b,
static InstTransResult doXaddRM(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &srcReg, Value *dstAddr) {
NASSERT(srcReg.isReg());
NASSERT(dstAddr != NULL);
@@ -211,7 +211,7 @@ static InstTransResult doXaddRM(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doXaddRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doXaddRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dstReg,
const MCOperand &srcReg) {
NASSERT(dstReg.isReg());
@@ -243,7 +243,7 @@ static InstTransResult doXaddRR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doXchgRR(InstPtr ip, BasicBlock *&b, const MCOperand &o1,
static InstTransResult doXchgRR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &o1,
const MCOperand &o2) {
NASSERT(o1.isReg());
NASSERT(o2.isReg());
@@ -258,7 +258,7 @@ static InstTransResult doXchgRR(InstPtr ip, BasicBlock *&b, const MCOperand &o1,
}
template<int width>
static InstTransResult doXchgRM(InstPtr ip, BasicBlock *&b, const MCOperand &r,
static InstTransResult doXchgRM(NativeInstPtr ip, BasicBlock *&b, const MCOperand &r,
Value *mem) {
NASSERT(mem != NULL);
NASSERT(r.isReg());
+9 -9
View File
@@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace llvm;
template <int width>
static Value *doNegV(InstPtr ip, BasicBlock *&b, Value *v) {
static Value *doNegV(NativeInstPtr ip, BasicBlock *&b, Value *v) {
//compare dest to 0
Value *cmpRes =
new ICmpInst(*b, CmpInst::ICMP_NE, v, CONST_V<width>(b, 0));
@@ -57,7 +57,7 @@ static Value *doNegV(InstPtr ip, BasicBlock *&b, Value *v) {
}
template <int width>
static InstTransResult doNegM(InstPtr ip, BasicBlock *&b, Value *v) {
static InstTransResult doNegM(NativeInstPtr ip, BasicBlock *&b, Value *v) {
NASSERT(v != NULL);
Value *fromMem = M_READ<width>(ip, b, v);
@@ -68,7 +68,7 @@ static InstTransResult doNegM(InstPtr ip, BasicBlock *&b, Value *v) {
}
template <int width>
static InstTransResult doNegR(InstPtr ip, BasicBlock *&b,
static InstTransResult doNegR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst)
{
NASSERT(dst.isReg());
@@ -98,7 +98,7 @@ static InstTransResult doNegR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static Value *doIncV(InstPtr ip, BasicBlock *&b, Value *val) {
static Value *doIncV(NativeInstPtr ip, BasicBlock *&b, Value *val) {
//add by 1
Value *result = BinaryOperator::CreateAdd(val, CONST_V<width>(b, 1), "", b);
@@ -114,7 +114,7 @@ static Value *doIncV(InstPtr ip, BasicBlock *&b, Value *val) {
}
template <int width>
static InstTransResult doIncM(InstPtr ip, BasicBlock *&b,
static InstTransResult doIncM(NativeInstPtr ip, BasicBlock *&b,
Value *addr)
{
NASSERT(addr != NULL);
@@ -129,7 +129,7 @@ static InstTransResult doIncM(InstPtr ip, BasicBlock *&b,
}
template <int width>
static Value *doDecV(InstPtr ip, BasicBlock *&b, Value *val) {
static Value *doDecV(NativeInstPtr ip, BasicBlock *&b, Value *val) {
Value *result = BinaryOperator::CreateSub(val, CONST_V<width>(b, 1), "", b);
@@ -144,7 +144,7 @@ static Value *doDecV(InstPtr ip, BasicBlock *&b, Value *val) {
}
template <int width, int regWidth>
static InstTransResult doDecR(InstPtr ip, BasicBlock *&b,
static InstTransResult doDecR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst)
{
NASSERT(dst.isReg());
@@ -168,7 +168,7 @@ static InstTransResult doDecR(InstPtr ip, BasicBlock *&b,
}
template <int width, int regWidth>
static InstTransResult doDecM(InstPtr ip, BasicBlock *&b, Value *m) {
static InstTransResult doDecM(NativeInstPtr ip, BasicBlock *&b, Value *m) {
NASSERT(m != NULL);
Value *from_mem = M_READ<width>(ip, b, m);
@@ -230,7 +230,7 @@ GENERIC_TRANSLATION_REF(INC64m,
doIncM<64>(ip, block, MEM_REFERENCE(0)))
template <int width, int regWidth>
static InstTransResult doIncR(InstPtr ip, BasicBlock *&b,
static InstTransResult doIncR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst)
{
NASSERT(dst.isReg());
+195 -200
View File
@@ -1,31 +1,31 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "InstructionDispatch.h"
#include "toLLVM.h"
#include "X86.h"
@@ -38,228 +38,223 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define NASSERT(cond) TASSERT(cond, "")
using namespace llvm;
static Value *CMP(BasicBlock *&b, Value *x, Value *y) {
return new ICmpInst(*b, CmpInst::ICMP_EQ, x, y);
static llvm::Value *CMP(llvm::BasicBlock *&b, llvm::Value *x, llvm::Value *y) {
return new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, x, y);
}
static Value *AND(BasicBlock *&b, Value *x, Value *y) {
return BinaryOperator::Create(Instruction::And, x, y, "", b);
static llvm::Value *AND(llvm::BasicBlock *&b, llvm::Value *x, llvm::Value *y) {
return llvm::BinaryOperator::Create(llvm::Instruction::And, x, y, "", b);
}
static Value *OR(BasicBlock *&b, Value *x, Value *y) {
return BinaryOperator::Create(Instruction::Or, x, y, "", b);
static llvm::Value *OR(llvm::BasicBlock *&b, llvm::Value *x, llvm::Value *y) {
return llvm::BinaryOperator::Create(llvm::Instruction::Or, x, y, "", b);
}
//emit the LLVM statements that perform the test associated with each
//type of conditional jump
Value *emitTestCode(BasicBlock *&b, unsigned opCode) {
Value *emittedInsn = NULL;
#define ONE CONST_V<1>(b, 1)
#define ZERO CONST_V<1>(b, 0)
#define OF_F F_READ(b, OF)
#define CF_F F_READ(b, CF)
#define PF_F F_READ(b, PF)
#define AF_F F_READ(b, AF)
#define ZF_F F_READ(b, ZF)
#define SF_F F_READ(b, SF)
Value *emitTestCode(llvm::BasicBlock *&b, unsigned opCode) {
llvm::Value *emittedInsn = nullptr;
#define ONE CONST_V<1>(b, 1)
#define ZERO CONST_V<1>(b, 0)
#define OF_F F_READ(b, OF)
#define CF_F F_READ(b, CF)
#define PF_F F_READ(b, PF)
#define AF_F F_READ(b, AF)
#define ZF_F F_READ(b, ZF)
#define SF_F F_READ(b, SF)
switch(opCode) {
case X86::JO_4:
case X86::JO_1:
// OF == 1
emittedInsn = CMP(b, OF_F, ONE);
break;
switch (opCode) {
case llvm::X86::JO_4:
case llvm::X86::JO_1:
// OF == 1
emittedInsn = CMP(b, OF_F, ONE);
break;
case X86::JNO_4:
case X86::JNO_1:
// OF == 0
emittedInsn = CMP(b, OF_F, ZERO);
break;
case llvm::X86::JNO_4:
case llvm::X86::JNO_1:
// OF == 0
emittedInsn = CMP(b, OF_F, ZERO);
break;
case X86::JB_4:
case X86::JB_1:
// CF == 1
emittedInsn = CMP(b, CF_F, ONE);
break;
case llvm::X86::JB_4:
case llvm::X86::JB_1:
// CF == 1
emittedInsn = CMP(b, CF_F, ONE);
break;
case X86::JAE_4:
case X86::JAE_1:
// CF == 0
emittedInsn = CMP(b, CF_F, ZERO);
break;
case llvm::X86::JAE_4:
case llvm::X86::JAE_1:
// CF == 0
emittedInsn = CMP(b, CF_F, ZERO);
break;
case X86::JE_4:
case X86::JE_1:
//ZF == 1
emittedInsn = CMP(b, ZF_F, ONE);
break;
case llvm::X86::JE_4:
case llvm::X86::JE_1:
//ZF == 1
emittedInsn = CMP(b, ZF_F, ONE);
break;
case X86::JNE_4:
case X86::JNE_1:
//ZF == 0
emittedInsn = CMP(b, ZF_F, ZERO);
break;
case llvm::X86::JNE_4:
case llvm::X86::JNE_1:
//ZF == 0
emittedInsn = CMP(b, ZF_F, ZERO);
break;
case X86::JBE_4:
case X86::JBE_1:
//CF = 1 or ZF = 1
emittedInsn = OR(b, CMP(b, CF_F, ONE), CMP(b, ZF_F, ONE));
break;
case llvm::X86::JBE_4:
case llvm::X86::JBE_1:
//CF = 1 or ZF = 1
emittedInsn = OR(b, CMP(b, CF_F, ONE), CMP(b, ZF_F, ONE));
break;
case X86::JA_4:
case X86::JA_1:
//CF = 0 and ZF = 0
emittedInsn = AND(b, CMP(b, CF_F, ZERO), CMP(b, ZF_F, ZERO));
break;
case llvm::X86::JA_4:
case llvm::X86::JA_1:
//CF = 0 and ZF = 0
emittedInsn = AND(b, CMP(b, CF_F, ZERO), CMP(b, ZF_F, ZERO));
break;
case X86::JS_4:
case X86::JS_1:
//SF = 1
emittedInsn = CMP(b, SF_F, ONE);
break;
case llvm::X86::JS_4:
case llvm::X86::JS_1:
//SF = 1
emittedInsn = CMP(b, SF_F, ONE);
break;
case X86::JNS_4:
case X86::JNS_1:
//SF = 0
emittedInsn = CMP(b, SF_F, ZERO);
break;
case llvm::X86::JNS_4:
case llvm::X86::JNS_1:
//SF = 0
emittedInsn = CMP(b, SF_F, ZERO);
break;
case X86::JP_4:
case X86::JP_1:
//PF = 1
emittedInsn = CMP(b, PF_F, ONE);
break;
case llvm::X86::JP_4:
case llvm::X86::JP_1:
//PF = 1
emittedInsn = CMP(b, PF_F, ONE);
break;
case X86::JNP_4:
case X86::JNP_1:
//PF = 0
emittedInsn = CMP(b, PF_F, ZERO);
break;
case llvm::X86::JNP_4:
case llvm::X86::JNP_1:
//PF = 0
emittedInsn = CMP(b, PF_F, ZERO);
break;
case X86::JL_4:
case X86::JL_1:
//SF!=OF
emittedInsn = CMP(b, CMP(b, SF_F, OF_F), ZERO);
break;
case llvm::X86::JL_4:
case llvm::X86::JL_1:
//SF!=OF
emittedInsn = CMP(b, CMP(b, SF_F, OF_F), ZERO);
break;
case X86::JGE_4:
case X86::JGE_1:
//SF=OF
emittedInsn = CMP(b, SF_F, OF_F);
break;
case llvm::X86::JGE_4:
case llvm::X86::JGE_1:
//SF=OF
emittedInsn = CMP(b, SF_F, OF_F);
break;
case X86::JLE_4:
case X86::JLE_1:
//ZF=1 or SF != OF
emittedInsn = OR(b, CMP(b, ZF_F, ONE), CMP(b, CMP(b, SF_F, OF_F), ZERO));
break;
case llvm::X86::JLE_4:
case llvm::X86::JLE_1:
//ZF=1 or SF != OF
emittedInsn = OR(b, CMP(b, ZF_F, ONE), CMP(b, CMP(b, SF_F, OF_F), ZERO));
break;
case X86::JG_4:
case X86::JG_1:
//ZF=0 and SF=OF
emittedInsn = AND(b, CMP(b, ZF_F, ZERO), CMP(b, SF_F, OF_F));
break;
case llvm::X86::JG_4:
case llvm::X86::JG_1:
//ZF=0 and SF=OF
emittedInsn = AND(b, CMP(b, ZF_F, ZERO), CMP(b, SF_F, OF_F));
break;
case X86::JCXZ:
emittedInsn = CMP(b, R_READ<16>(b, X86::CX), CONST_V<16>(b, 0));
break;
case llvm::X86::JCXZ:
emittedInsn = CMP(b, R_READ<16>(b, X86::CX), CONST_V<16>(b, 0));
break;
case X86::JECXZ_32:
emittedInsn = CMP(b, R_READ<32>(b, X86::ECX), CONST_V<32>(b, 0));
break;
case llvm::X86::JECXZ_32:
emittedInsn = CMP(b, R_READ<32>(b, X86::ECX), CONST_V<32>(b, 0));
break;
default:
//case X86::JRCXZ:
throw TErr(__LINE__, __FILE__, "NIY");
break;
default:
//case llvm::X86::JRCXZ:
throw TErr(__LINE__, __FILE__, "NIY");
break;
}
#undef ONE
#undef ZERO
#undef OF_F
#undef CF_F
#undef PF_F
#undef AF_F
#undef ZF_F
#undef SF_F
#undef ONE
#undef ZERO
#undef OF_F
#undef CF_F
#undef PF_F
#undef AF_F
#undef ZF_F
#undef SF_F
NASSERT(emittedInsn != NULL );
NASSERT(emittedInsn != nullptr);
return emittedInsn;
return emittedInsn;
}
//emit a conditional branch
static InstTransResult doCondBranch(InstPtr ip, BasicBlock *&b,
BasicBlock *ifTrue,
BasicBlock *ifFalse,
Value *cond)
{
//we should have targets for this branch
NASSERT( ifTrue != NULL );
NASSERT( ifFalse != NULL );
NASSERT( cond != NULL );
static InstTransResult doCondBranch(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::BasicBlock *ifTrue,
llvm::BasicBlock *ifFalse,
llvm::Value *cond) {
//we should have targets for this branch
NASSERT(ifTrue != nullptr);
NASSERT(ifFalse != nullptr);
NASSERT(cond != nullptr);
//emit a branch on the condition
BranchInst::Create(ifTrue, ifFalse, cond, b);
//emit a branch on the condition
llvm::BranchInst::Create(ifTrue, ifFalse, cond, b);
return EndBlock;
return EndBlock;
}
static InstTransResult translate_Jcc(NativeModulePtr natM, BasicBlock *& block, InstPtr ip, MCInst &inst) {
static InstTransResult translate_Jcc(TranslationContext &ctx,
llvm::BasicBlock *&block) {
Function *F = block->getParent();
// llvm::dbgs() << __FUNCTION__ << "\tRepresentation: " << ip->printInst() << "\n";
auto F = block->getParent();
auto ip = ctx.natI;
auto &inst = ip->get_inst();
std::string trueStrName = "block_0x"+to_string<VA>(ip->get_tr(), std::hex);
std::string falseStrName = "block_0x"+to_string<VA>(ip->get_fa(), std::hex);
auto ifTrue = ctx.va_to_bb[ip->get_tr()];
auto ifFalse = ctx.va_to_bb[ip->get_fa()];
BasicBlock *ifTrue = bbFromStrName(trueStrName, F);
BasicBlock *ifFalse = bbFromStrName(falseStrName, F);
return doCondBranch(ip, block, ifTrue,
ifFalse,
emitTestCode(block, inst.getOpcode() ) );
return doCondBranch(ip, block, ifTrue, ifFalse,
emitTestCode(block, inst.getOpcode()));
}
void Jcc_populateDispatchMap(DispatchMap &m) {
//for conditional instructions, get the "true" and "false" targets
//this will also look up the target for nonconditional jumps
//for conditional instructions, get the "true" and "false" targets
//this will also look up the target for nonconditional jumps
m[X86::JBE_4] = translate_Jcc;
m[X86::JBE_1] = translate_Jcc;
m[X86::JA_4] = translate_Jcc;
m[X86::JA_1] = translate_Jcc;
m[X86::JS_4] = translate_Jcc;
m[X86::JS_1] = translate_Jcc;
m[X86::JNS_4] = translate_Jcc;
m[X86::JNS_1] = translate_Jcc;
m[X86::JP_4] = translate_Jcc;
m[X86::JP_1] = translate_Jcc;
m[X86::JNP_4] = translate_Jcc;
m[X86::JNP_1] = translate_Jcc;
m[X86::JL_4] = translate_Jcc;
m[X86::JL_1] = translate_Jcc;
m[X86::JGE_4] = translate_Jcc;
m[X86::JGE_1] = translate_Jcc;
m[X86::JG_4] = translate_Jcc;
m[X86::JG_1] = translate_Jcc;
m[X86::JCXZ] = translate_Jcc;
m[X86::JRCXZ] = translate_Jcc;
m[X86::JO_4] = translate_Jcc;
m[X86::JO_1] = translate_Jcc;
m[X86::JNO_4] = translate_Jcc;
m[X86::JNO_1] = translate_Jcc;
m[X86::JB_4] = translate_Jcc;
m[X86::JB_1] = translate_Jcc;
m[X86::JAE_4] = translate_Jcc;
m[X86::JAE_1] = translate_Jcc;
m[X86::JLE_4] = translate_Jcc;
m[X86::JLE_1] = translate_Jcc;
m[X86::JNE_4] = translate_Jcc;
m[X86::JNE_1] = translate_Jcc;
m[X86::JE_4] = translate_Jcc;
m[X86::JE_1] = translate_Jcc;
m[X86::JBE_4] = translate_Jcc;
m[X86::JBE_1] = translate_Jcc;
m[X86::JA_4] = translate_Jcc;
m[X86::JA_1] = translate_Jcc;
m[X86::JS_4] = translate_Jcc;
m[X86::JS_1] = translate_Jcc;
m[X86::JNS_4] = translate_Jcc;
m[X86::JNS_1] = translate_Jcc;
m[X86::JP_4] = translate_Jcc;
m[X86::JP_1] = translate_Jcc;
m[X86::JNP_4] = translate_Jcc;
m[X86::JNP_1] = translate_Jcc;
m[X86::JL_4] = translate_Jcc;
m[X86::JL_1] = translate_Jcc;
m[X86::JGE_4] = translate_Jcc;
m[X86::JGE_1] = translate_Jcc;
m[X86::JG_4] = translate_Jcc;
m[X86::JG_1] = translate_Jcc;
m[X86::JCXZ] = translate_Jcc;
m[X86::JRCXZ] = translate_Jcc;
m[X86::JO_4] = translate_Jcc;
m[X86::JO_1] = translate_Jcc;
m[X86::JNO_4] = translate_Jcc;
m[X86::JNO_1] = translate_Jcc;
m[X86::JB_4] = translate_Jcc;
m[X86::JB_1] = translate_Jcc;
m[X86::JAE_4] = translate_Jcc;
m[X86::JAE_1] = translate_Jcc;
m[X86::JLE_4] = translate_Jcc;
m[X86::JLE_1] = translate_Jcc;
m[X86::JNE_4] = translate_Jcc;
m[X86::JNE_1] = translate_Jcc;
m[X86::JE_4] = translate_Jcc;
m[X86::JE_1] = translate_Jcc;
}
File diff suppressed because it is too large Load Diff
+8 -11
View File
@@ -32,13 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace llvm;
#define INSTR_DEBUG(ip) llvm::dbgs() << __FUNCTION__ << "\tRepresentation: " << ip->printInst() << "\n"
//class INSTR_DEBUG;
void MOV_populateDispatchMap(DispatchMap &m);
template <int width, SystemArchType arch>
InstTransResult doMRMov(InstPtr ip, llvm::BasicBlock *&b,
InstTransResult doMRMov(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *dstAddr,
const llvm::MCOperand &src)
{
@@ -52,7 +49,7 @@ InstTransResult doMRMov(InstPtr ip, llvm::BasicBlock *&b,
}
template <int width>
InstTransResult doMRMovBE(InstPtr ip, llvm::BasicBlock *&b,
InstTransResult doMRMovBE(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *dstAddr,
const llvm::MCOperand &src)
{
@@ -125,7 +122,7 @@ InstTransResult doMRMovBE(InstPtr ip, llvm::BasicBlock *&b,
}
template <int width>
InstTransResult doMRMov(InstPtr ip, llvm::BasicBlock *&b,
InstTransResult doMRMov(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *dstAddr,
const llvm::MCOperand &src)
{
@@ -140,7 +137,7 @@ InstTransResult doMRMov(InstPtr ip, llvm::BasicBlock *&b,
template <int width, SystemArchType arch>
InstTransResult doRRMov(InstPtr ip, llvm::BasicBlock *b,
InstTransResult doRRMov(NativeInstPtr ip, llvm::BasicBlock *b,
const llvm::MCOperand &dst,
const llvm::MCOperand &src)
{
@@ -154,7 +151,7 @@ InstTransResult doRRMov(InstPtr ip, llvm::BasicBlock *b,
}
template <int width>
InstTransResult doRRMov(InstPtr ip, llvm::BasicBlock *b,
InstTransResult doRRMov(NativeInstPtr ip, llvm::BasicBlock *b,
const llvm::MCOperand &dst,
const llvm::MCOperand &src)
{
@@ -169,7 +166,7 @@ InstTransResult doRRMov(InstPtr ip, llvm::BasicBlock *b,
}
template <int width>
InstTransResult doRRMovD(InstPtr ip, llvm::BasicBlock *b,
InstTransResult doRRMovD(NativeInstPtr ip, llvm::BasicBlock *b,
const llvm::MCOperand &dst,
const llvm::MCOperand &src)
{
@@ -185,7 +182,7 @@ InstTransResult doRRMovD(InstPtr ip, llvm::BasicBlock *b,
template <int width>
InstTransResult doRMMovBE(InstPtr ip, llvm::BasicBlock *&b,
InstTransResult doRMMovBE(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *srcAddr,
const llvm::MCOperand &dst)
{
@@ -261,7 +258,7 @@ InstTransResult doRMMovBE(InstPtr ip, llvm::BasicBlock *&b,
template <int width>
InstTransResult doRMMov(InstPtr ip, llvm::BasicBlock *b,
InstTransResult doRMMov(NativeInstPtr ip, llvm::BasicBlock *b,
llvm::Value *srcAddr,
const llvm::MCOperand &dst)
{
+21 -21
View File
@@ -39,7 +39,7 @@ using namespace llvm;
using namespace std;
template<int width>
static void doMulV(InstPtr ip, BasicBlock *&b, Value *rhs) {
static void doMulV(NativeInstPtr ip, BasicBlock *&b, Value *rhs) {
// Handle the different source register depending on the bit width
Value *lhs;
@@ -101,7 +101,7 @@ static void doMulV(InstPtr ip, BasicBlock *&b, Value *rhs) {
}
template<int width>
static InstTransResult doMulR(InstPtr ip, BasicBlock *&b,
static InstTransResult doMulR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &src) {
NASSERT(src.isReg());
@@ -111,7 +111,7 @@ static InstTransResult doMulR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doMulM(InstPtr ip, BasicBlock *&b, Value *memAddr) {
static InstTransResult doMulM(NativeInstPtr ip, BasicBlock *&b, Value *memAddr) {
NASSERT(memAddr != NULL);
doMulV<width>(ip, b, M_READ<width>(ip, b, memAddr));
@@ -125,7 +125,7 @@ struct IMulRes {
};
template<int width>
static IMulRes doIMulVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
static IMulRes doIMulVV(NativeInstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
//model the semantics of the signed multiply
Value *a1 = lhs;
Value *a2 = rhs;
@@ -152,7 +152,7 @@ static IMulRes doIMulVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
}
template<int width>
static IMulRes doIMulV(InstPtr ip, BasicBlock *&b, Value *rhs) {
static IMulRes doIMulV(NativeInstPtr ip, BasicBlock *&b, Value *rhs) {
// Handle the different source register depending on the bit width
Value *lhs;
@@ -176,7 +176,7 @@ static IMulRes doIMulV(InstPtr ip, BasicBlock *&b, Value *rhs) {
}
template<int width>
static InstTransResult doIMulR(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &src) {
NASSERT(src.isReg());
@@ -215,7 +215,7 @@ static InstTransResult doIMulR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulM(InstPtr ip, BasicBlock *&b, Value *memAddr) {
static InstTransResult doIMulM(NativeInstPtr ip, BasicBlock *&b, Value *memAddr) {
NASSERT(memAddr != NULL);
auto imul_res = doIMulV<width>(ip, b, M_READ<width>(ip, b, memAddr));
@@ -250,7 +250,7 @@ static InstTransResult doIMulM(InstPtr ip, BasicBlock *&b, Value *memAddr) {
}
template<int width>
static InstTransResult doIMulRM(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRM(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &lhs,
Value *rhs) {
NASSERT(dst.isReg());
@@ -266,7 +266,7 @@ static InstTransResult doIMulRM(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulRR(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &lhs,
const MCOperand &rhs) {
NASSERT(dst.isReg());
@@ -282,13 +282,13 @@ static InstTransResult doIMulRR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static Value *doIMulVVV(InstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
static Value *doIMulVVV(NativeInstPtr ip, BasicBlock *&b, Value *lhs, Value *rhs) {
return doIMulVV<width>(ip, b, lhs, rhs).trunc;
}
template<int width>
static InstTransResult doIMulRMI(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRMI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, Value *lhs,
const MCOperand &rhs) {
NASSERT(dst.isReg());
@@ -304,7 +304,7 @@ static InstTransResult doIMulRMI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulRMV(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRMV(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, Value *lhs,
Value *rhs) {
NASSERT(dst.isReg());
@@ -318,7 +318,7 @@ static InstTransResult doIMulRMV(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulRRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &lhs,
const MCOperand &rhs) {
NASSERT(dst.isReg());
@@ -334,7 +334,7 @@ static InstTransResult doIMulRRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulRRV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doIMulRRV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &lhs, const MCOperand &dst) {
NASSERT(dst.isReg());
NASSERT(lhs.isReg());
@@ -347,7 +347,7 @@ static InstTransResult doIMulRRV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doIMulRMI8(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRMI8(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, Value *lhs,
const MCOperand &rhs) {
NASSERT(dst.isReg());
@@ -366,7 +366,7 @@ static InstTransResult doIMulRMI8(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doIMulRRI8(InstPtr ip, BasicBlock *&b,
static InstTransResult doIMulRRI8(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &lhs,
const MCOperand &rhs) {
NASSERT(dst.isReg());
@@ -385,7 +385,7 @@ static InstTransResult doIMulRRI8(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doDivV(InstPtr ip, BasicBlock *&b, Value *divisor,
static InstTransResult doDivV(NativeInstPtr ip, BasicBlock *&b, Value *divisor,
llvm::Instruction::BinaryOps whichdiv) {
//read in EDX and EAX
@@ -482,7 +482,7 @@ static InstTransResult doDivV(InstPtr ip, BasicBlock *&b, Value *divisor,
}
template <int width>
static InstTransResult doIDivR(InstPtr ip, BasicBlock *&b,
static InstTransResult doIDivR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &div)
{
NASSERT(div.isReg());
@@ -495,7 +495,7 @@ static InstTransResult doIDivR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doIDivM(InstPtr ip, BasicBlock *&b, Value *memLoc) {
static InstTransResult doIDivM(NativeInstPtr ip, BasicBlock *&b, Value *memLoc) {
NASSERT(memLoc != NULL);
Value *from_mem = M_READ<width>(ip, b, memLoc);
@@ -506,7 +506,7 @@ static InstTransResult doIDivM(InstPtr ip, BasicBlock *&b, Value *memLoc) {
}
template <int width>
static InstTransResult doDivR(InstPtr ip, BasicBlock *&b,
static InstTransResult doDivR(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &div)
{
NASSERT(div.isReg());
@@ -519,7 +519,7 @@ static InstTransResult doDivR(InstPtr ip, BasicBlock *&b,
}
template <int width>
static InstTransResult doDivM(InstPtr ip, BasicBlock *&b, Value *memLoc) {
static InstTransResult doDivM(NativeInstPtr ip, BasicBlock *&b, Value *memLoc) {
NASSERT(memLoc != NULL);
Value *from_mem = M_READ<width>(ip, b, memLoc);
+286 -285
View File
@@ -8,7 +8,8 @@
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
@@ -39,46 +40,40 @@
using namespace llvm;
static InstTransResult doNoop(BasicBlock *b) {
static InstTransResult doNoop(llvm::BasicBlock *b) {
//isn't this exciting
return ContinueBlock;
}
static InstTransResult doHlt(BasicBlock *b) {
static InstTransResult doHlt(llvm::BasicBlock *b) {
//isn't this exciting
llvm::dbgs()
<< "WARNING: Treating HLT as no-op, but HLT is normally privileged\n";
std::cerr << "WARNING: Treating HLT as no-op, but HLT is normally privileged"
<< std::endl;
return ContinueBlock;
}
static InstTransResult doInt3(BasicBlock *b) {
Module *M = b->getParent()->getParent();
static InstTransResult doInt3(llvm::BasicBlock *b) {
auto M = b->getParent()->getParent();
//emit an LLVM trap intrinsic
//this should be changed to a debugtrap intrinsic eventually
Function *trapIntrin = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapIntrin, "", b);
Value *unreachable = new UnreachableInst(b->getContext(), b);
auto trapIntrin = llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap);
llvm::CallInst::Create(trapIntrin, "", b);
(void) new llvm::UnreachableInst(b->getContext(), b);
return ContinueBlock;
}
static InstTransResult doTrap(BasicBlock *b) {
Module *M = b->getParent()->getParent();
Function *trapIntrin = Intrinsic::getDeclaration(M, Intrinsic::trap);
CallInst::Create(trapIntrin, "", b);
Value *unreachable = new UnreachableInst(b->getContext(), b);
static InstTransResult doTrap(llvm::BasicBlock *b) {
auto M = b->getParent()->getParent();
auto trapIntrin = Intrinsic::getDeclaration(M, llvm::Intrinsic::trap);
llvm::CallInst::Create(trapIntrin, "", b);
(void) new llvm::UnreachableInst(b->getContext(), b);
return ContinueBlock;
}
static InstTransResult doInt(BasicBlock *&b, const MCOperand &o) {
static InstTransResult doInt(llvm::BasicBlock *&b, const llvm::MCOperand &o) {
TASSERT(o.isImm(), "Operand not immediate");
Module *M = b->getParent()->getParent();
auto M = b->getParent()->getParent();
int interrupt_val = o.getImm();
auto os = SystemOS(M);
if (0x2e == interrupt_val && llvm::Triple::Win32 == os) {
@@ -89,25 +84,23 @@ static InstTransResult doInt(BasicBlock *&b, const MCOperand &o) {
TASSERT(false, "System call via interrupt is not supported!");
}
llvm::dbgs() << "WARNING: Treating INT " << interrupt_val << " as trap!\n";
std::cerr << "WARNING: Treating INT " << interrupt_val << " as trap!"
<< std::endl;
return doTrap(b);
}
static InstTransResult doCdq(BasicBlock *b) {
static InstTransResult doCdq(llvm::BasicBlock *b) {
// EDX <- SEXT(EAX)
//read EAX
Value *EAX_v = R_READ<32>(b, llvm::X86::EAX);
Value *sign_bit = CONST_V<32>(b, 1 << 31);
Value *test_bit = BinaryOperator::CreateAnd(EAX_v, sign_bit, "", b);
Value *is_zero = new ICmpInst( *b, CmpInst::ICMP_EQ, test_bit,
CONST_V<32>(b, 0));
Value *edx_val = SelectInst::Create(is_zero, CONST_V<32>(b, 0),
CONST_V<32>(b, 0xFFFFFFFF), "", b);
auto EAX_v = R_READ<32>(b, llvm::X86::EAX);
auto sign_bit = CONST_V<32>(b, 1ULL << 31U);
auto test_bit = llvm::BinaryOperator::CreateAnd(EAX_v, sign_bit, "", b);
auto is_zero = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, test_bit,
CONST_V<32>(b, 0));
auto edx_val = llvm::SelectInst::Create(is_zero, CONST_V<32>(b, 0),
CONST_V<32>(b, 0xFFFFFFFF), "", b);
//write this value to EDX
R_WRITE<32>(b, llvm::X86::EDX, edx_val);
@@ -116,72 +109,74 @@ static InstTransResult doCdq(BasicBlock *b) {
}
template<int width>
static InstTransResult doBswapR(InstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
static InstTransResult doBswapR(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &reg) {
TASSERT(reg.isReg(), "");
if (width != 32) {
throw TErr(__LINE__, __FILE__, "Width not supported");
}
Value *tmp = R_READ<width>(b, reg.getReg());
auto tmp = R_READ<width>(b, reg.getReg());
// Create the new bytes from the original value
Value *newByte1 = BinaryOperator::CreateShl(tmp, CONST_V<width>(b, 24), "",
b);
Value *newByte2 = BinaryOperator::CreateShl(
BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x0000FF00), "", b),
auto newByte1 = llvm::BinaryOperator::CreateShl(tmp, CONST_V<width>(b, 24),
"", b);
auto newByte2 = llvm::BinaryOperator::CreateShl(
llvm::BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x0000FF00), "",
b),
CONST_V<width>(b, 8), "", b);
Value *newByte3 = BinaryOperator::CreateLShr(
BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x00FF0000), "", b),
auto newByte3 = BinaryOperator::CreateLShr(
llvm::BinaryOperator::CreateAnd(tmp, CONST_V<width>(b, 0x00FF0000), "",
b),
CONST_V<width>(b, 8), "", b);
Value *newByte4 = BinaryOperator::CreateLShr(tmp, CONST_V<width>(b, 24), "",
b);
auto newByte4 = llvm::BinaryOperator::CreateLShr(tmp, CONST_V<width>(b, 24),
"", b);
// Add the bytes together to make the resulting DWORD
Value *res = BinaryOperator::CreateAdd(newByte1, newByte2, "", b);
res = BinaryOperator::CreateAdd(res, newByte3, "", b);
res = BinaryOperator::CreateAdd(res, newByte4, "", b);
llvm::Value *res = llvm::BinaryOperator::CreateAdd(newByte1, newByte2, "", b);
res = llvm::BinaryOperator::CreateAdd(res, newByte3, "", b);
res = llvm::BinaryOperator::CreateAdd(res, newByte4, "", b);
R_WRITE<width>(b, reg.getReg(), res);
return ContinueBlock;
}
static InstTransResult doLAHF(BasicBlock *b) {
static InstTransResult doLAHF(llvm::BasicBlock *b) {
//we need to create an 8-bit value out of the status
//flags, shift and OR them, and then write them into AH
Type *t = Type::getInt8Ty(b->getContext());
Value *cf = new ZExtInst(F_READ(b, CF), t, "", b);
Value *af = new ZExtInst(F_READ(b, AF), t, "", b);
Value *pf = new ZExtInst(F_READ(b, PF), t, "", b);
Value *zf = new ZExtInst(F_READ(b, ZF), t, "", b);
Value *sf = new ZExtInst(F_READ(b, SF), t, "", b);
auto t = llvm::Type::getInt8Ty(b->getContext());
auto cf = new llvm::ZExtInst(F_READ(b, CF), t, "", b);
auto af = new llvm::ZExtInst(F_READ(b, AF), t, "", b);
auto pf = new llvm::ZExtInst(F_READ(b, PF), t, "", b);
auto zf = new llvm::ZExtInst(F_READ(b, ZF), t, "", b);
auto sf = new llvm::ZExtInst(F_READ(b, SF), t, "", b);
//shift everything
Value *p_0 = cf;
Value *p_1 = BinaryOperator::CreateShl(CONST_V<8>(b, 1), CONST_V<8>(b, 1), "",
b);
Value *p_2 = BinaryOperator::CreateShl(pf, CONST_V<8>(b, 2), "", b);
Value *p_3 = BinaryOperator::CreateShl(CONST_V<8>(b, 0), CONST_V<8>(b, 3), "",
b);
Value *p_4 = BinaryOperator::CreateShl(af, CONST_V<8>(b, 4), "", b);
Value *p_5 = BinaryOperator::CreateShl(CONST_V<8>(b, 0), CONST_V<8>(b, 5), "",
b);
Value *p_6 = BinaryOperator::CreateShl(zf, CONST_V<8>(b, 6), "", b);
Value *p_7 = BinaryOperator::CreateShl(sf, CONST_V<8>(b, 7), "", b);
auto p_0 = cf;
auto p_1 = llvm::BinaryOperator::CreateShl(CONST_V<8>(b, 1), CONST_V<8>(b, 1),
"", b);
auto p_2 = llvm::BinaryOperator::CreateShl(pf, CONST_V<8>(b, 2), "", b);
auto p_3 = llvm::BinaryOperator::CreateShl(CONST_V<8>(b, 0), CONST_V<8>(b, 3),
"", b);
auto p_4 = llvm::BinaryOperator::CreateShl(af, CONST_V<8>(b, 4), "", b);
auto p_5 = llvm::BinaryOperator::CreateShl(CONST_V<8>(b, 0), CONST_V<8>(b, 5),
"", b);
auto p_6 = llvm::BinaryOperator::CreateShl(zf, CONST_V<8>(b, 6), "", b);
auto p_7 = llvm::BinaryOperator::CreateShl(sf, CONST_V<8>(b, 7), "", b);
//OR everything
Value *res = BinaryOperator::CreateOr(
BinaryOperator::CreateOr(
BinaryOperator::CreateOr(BinaryOperator::CreateOr(p_0, p_1, "", b),
p_2, "", b),
auto res = llvm::BinaryOperator::CreateOr(
llvm::BinaryOperator::CreateOr(
llvm::BinaryOperator::CreateOr(
llvm::BinaryOperator::CreateOr(p_0, p_1, "", b), p_2, "", b),
p_3, "", b),
BinaryOperator::CreateOr(
BinaryOperator::CreateOr(BinaryOperator::CreateOr(p_4, p_5, "", b),
p_6, "", b),
llvm::BinaryOperator::CreateOr(
llvm::BinaryOperator::CreateOr(
llvm::BinaryOperator::CreateOr(p_4, p_5, "", b), p_6, "", b),
p_7, "", b),
"", b);
@@ -190,117 +185,116 @@ static InstTransResult doLAHF(BasicBlock *b) {
return ContinueBlock;
}
static InstTransResult doStd(BasicBlock *b) {
static InstTransResult doStd(llvm::BasicBlock *b) {
F_SET(b, DF);
return ContinueBlock;
}
static InstTransResult doCld(BasicBlock *b) {
static InstTransResult doCld(llvm::BasicBlock *b) {
F_CLEAR(b, DF);
return ContinueBlock;
}
static InstTransResult doStc(BasicBlock *b) {
static InstTransResult doStc(llvm::BasicBlock *b) {
F_SET(b, CF);
return ContinueBlock;
}
static InstTransResult doClc(BasicBlock *b) {
static InstTransResult doClc(llvm::BasicBlock *b) {
F_CLEAR(b, CF);
return ContinueBlock;
}
template<int width>
static InstTransResult doLeaV(BasicBlock *&b, const MCOperand &dst,
Value *addrInt)
{
static InstTransResult doLeaV(llvm::BasicBlock *&b, const llvm::MCOperand &dst,
llvm::Value *addrInt) {
//write the address into the register
R_WRITE<width>(b, dst.getReg(), addrInt);
return ContinueBlock;
}
template<int width>
static InstTransResult doLea(InstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &dst) {
static InstTransResult doLea(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *addr, const llvm::MCOperand &dst) {
// LEA <r>, <expr>
TASSERT(addr != NULL, "");
TASSERT(dst.isReg(), "");
//addr is an address, so, convert it to an integer value to write
Type *ty = Type::getIntNTy(b->getContext(), width);
Value *addrInt = addr;
auto ty = llvm::Type::getIntNTy(b->getContext(), width);
auto addrInt = addr;
if (addr->getType()->isPointerTy()) {
addrInt = new PtrToIntInst(addr, ty, "", b);
addrInt = new llvm::PtrToIntInst(addr, ty, "", b);
}
return doLeaV<width>(b, dst, addrInt);
}
static InstTransResult doRdtsc(BasicBlock *b) {
static InstTransResult doRdtsc(llvm::BasicBlock *b) {
/* write out a call to the RDTSC intrinsic */
Module *M = b->getParent()->getParent();
auto M = b->getParent()->getParent();
auto &C = M->getContext();
//emit an LLVM trap intrinsic
//this should be changed to a debugtrap intrinsic eventually
Function *rcc = Intrinsic::getDeclaration(M, Intrinsic::readcyclecounter);
CallInst::Create(rcc, "", b);
auto rcc = llvm::Intrinsic::getDeclaration(M,
llvm::Intrinsic::readcyclecounter);
auto ret = llvm::CallInst::Create(rcc, "", b);
auto Int32Ty = llvm::Type::getInt32Ty(C);
auto low = new llvm::TruncInst(ret, Int32Ty, "", b);
auto high = new llvm::TruncInst(
llvm::BinaryOperator::Create(llvm::Instruction::LShr, ret,
llvm::ConstantInt::get(Int32Ty, 32), "", b),
Int32Ty, "", b);
R_WRITE<32>(b, X86::EDX, high);
R_WRITE<32>(b, X86::EAX, low);
return ContinueBlock;
}
static InstTransResult doAAA(BasicBlock *b) {
static InstTransResult doAAA(llvm::BasicBlock *b) {
Function *F = b->getParent();
auto F = b->getParent();
auto &C = F->getContext();
//trueBlock for when ((AL & 0x0F > 9) || (AF == 1)); falseblock otherwise
BasicBlock *trueBlock = BasicBlock::Create(F->getContext(), "", F);
BasicBlock *falseBlock = BasicBlock::Create(F->getContext(), "", F);
BasicBlock *endBlock = BasicBlock::Create(F->getContext(), "", F);
auto trueBlock = llvm::BasicBlock::Create(C, "", F);
auto falseBlock = llvm::BasicBlock::Create(C, "", F);
auto endBlock = llvm::BasicBlock::Create(C, "", F);
Value *al;
Value *af;
llvm::Value *al = nullptr;
llvm::Value *af = nullptr;
al = R_READ<8>(b, llvm::X86::AL);
af = F_READ(b, AF);
// AL & 0x0F
Value *andRes = BinaryOperator::CreateAnd(al, CONST_V<8>(b, 0x0F), "", b);
auto andRes = llvm::BinaryOperator::CreateAnd(al, CONST_V<8>(b, 0x0F), "", b);
// ((AL & 0x0F) > 9)?
Value *testRes = new ICmpInst( *b, CmpInst::ICMP_UGT, andRes,
CONST_V<8>(b, 9));
auto testRes = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_UGT, andRes,
CONST_V<8>(b, 9));
Value *orRes = BinaryOperator::CreateOr(testRes, af, "", b);
auto orRes = llvm::BinaryOperator::CreateOr(testRes, af, "", b);
BranchInst::Create(trueBlock, falseBlock, orRes, b);
llvm::BranchInst::Create(trueBlock, falseBlock, orRes, b);
//True Block Statements
Value *alRes = BinaryOperator::CreateAdd(al, CONST_V<8>(trueBlock, 6), "",
trueBlock);
llvm::Value *alRes = llvm::BinaryOperator::CreateAdd(al,
CONST_V<8>(trueBlock, 6),
"", trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AL, alRes);
Value *ahRes = BinaryOperator::CreateAdd(R_READ<8>(trueBlock, llvm::X86::AH),
CONST_V<8>(trueBlock, 1), "",
trueBlock);
auto ahRes = llvm::BinaryOperator::CreateAdd(
R_READ<8>(trueBlock, llvm::X86::AH), CONST_V<8>(trueBlock, 1), "",
trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AH, ahRes);
F_SET(trueBlock, AF);
F_SET(trueBlock, CF);
alRes = BinaryOperator::CreateAnd(alRes, CONST_V<8>(trueBlock, 0x0F), "",
trueBlock);
alRes = llvm::BinaryOperator::CreateAnd(alRes, CONST_V<8>(trueBlock, 0x0F),
"", trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AL, alRes);
BranchInst::Create(endBlock, trueBlock);
llvm::BranchInst::Create(endBlock, trueBlock);
//False Block Statements
F_CLEAR(falseBlock, AF);
@@ -310,7 +304,7 @@ static InstTransResult doAAA(BasicBlock *b) {
falseBlock);
R_WRITE<8>(falseBlock, llvm::X86::AL, alRes);
BranchInst::Create(endBlock, falseBlock);
llvm::BranchInst::Create(endBlock, falseBlock);
F_ZAP(endBlock, OF);
F_ZAP(endBlock, SF);
@@ -323,49 +317,53 @@ static InstTransResult doAAA(BasicBlock *b) {
return ContinueBlock;
}
static InstTransResult doAAS(BasicBlock *b) {
static InstTransResult doAAS(llvm::BasicBlock *b) {
auto F = b->getParent();
auto &C = F->getContext();
Function *F = b->getParent();
//trueBlock for when ((AL & 0x0F > 9) || (AF == 1)); falseblock otherwise
BasicBlock *trueBlock = BasicBlock::Create(F->getContext(), "", F);
BasicBlock *falseBlock = BasicBlock::Create(F->getContext(), "", F);
BasicBlock *endBlock = BasicBlock::Create(F->getContext(), "", F);
auto trueBlock = llvm::BasicBlock::Create(C, "", F);
auto falseBlock = llvm::BasicBlock::Create(C, "", F);
auto endBlock = llvm::BasicBlock::Create(C, "", F);
Value *al;
Value *af;
llvm::Value *al = nullptr;
llvm::Value *af = nullptr;
al = R_READ<8>(b, llvm::X86::AL);
af = F_READ(b, AF);
// AL & 0x0F
Value *andRes = BinaryOperator::CreateAnd(al, CONST_V<8>(b, 0x0F), "", b);
llvm::Value *andRes = llvm::BinaryOperator::CreateAnd(al, CONST_V<8>(b, 0x0F),
"", b);
// ((AL & 0x0F) > 9)?
Value *testRes = new ICmpInst( *b, CmpInst::ICMP_UGT, andRes,
CONST_V<8>(b, 9));
llvm::Value *testRes = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_UGT,
andRes, CONST_V<8>(b, 9));
Value *orRes = BinaryOperator::CreateOr(testRes, af, "", b);
llvm::Value *orRes = llvm::BinaryOperator::CreateOr(testRes, af, "", b);
BranchInst::Create(trueBlock, falseBlock, orRes, b);
llvm::BranchInst::Create(trueBlock, falseBlock, orRes, b);
//True Block Statements
Value *alRes = BinaryOperator::CreateSub(al, CONST_V<8>(trueBlock, 6), "",
trueBlock);
llvm::Value *alRes = llvm::BinaryOperator::CreateSub(al,
CONST_V<8>(trueBlock, 6),
"", trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AL, alRes);
Value *ahRes = BinaryOperator::CreateSub(R_READ<8>(trueBlock, llvm::X86::AH),
CONST_V<8>(trueBlock, 1), "",
trueBlock);
llvm::Value *ahRes = llvm::BinaryOperator::CreateSub(
R_READ<8>(trueBlock, llvm::X86::AH), CONST_V<8>(trueBlock, 1), "",
trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AH, ahRes);
F_SET(trueBlock, AF);
F_SET(trueBlock, CF);
alRes = BinaryOperator::CreateAnd(alRes, CONST_V<8>(trueBlock, 0x0F), "",
trueBlock);
alRes = llvm::BinaryOperator::CreateAnd(alRes, CONST_V<8>(trueBlock, 0x0F),
"", trueBlock);
R_WRITE<8>(trueBlock, llvm::X86::AL, alRes);
BranchInst::Create(endBlock, trueBlock);
llvm::BranchInst::Create(endBlock, trueBlock);
//False Block Statements
F_CLEAR(falseBlock, AF);
@@ -375,7 +373,7 @@ static InstTransResult doAAS(BasicBlock *b) {
falseBlock);
R_WRITE<8>(falseBlock, llvm::X86::AL, alRes);
BranchInst::Create(endBlock, falseBlock);
llvm::BranchInst::Create(endBlock, falseBlock);
F_ZAP(endBlock, OF);
F_ZAP(endBlock, SF);
@@ -388,16 +386,16 @@ static InstTransResult doAAS(BasicBlock *b) {
return ContinueBlock;
}
static InstTransResult doAAM(BasicBlock *b) {
static InstTransResult doAAM(llvm::BasicBlock *b) {
Value *al;
llvm::Value *al = nullptr;
al = R_READ<8>(b, llvm::X86::AL);
Value *res = BinaryOperator::Create(Instruction::SDiv, al,
CONST_V<8>(b, 0x0A), "", b);
Value *mod = BinaryOperator::Create(Instruction::SRem, al,
CONST_V<8>(b, 0x0A), "", b);
llvm::Value *res = llvm::BinaryOperator::Create(llvm::Instruction::SDiv, al,
CONST_V<8>(b, 0x0A), "", b);
llvm::Value *mod = llvm::BinaryOperator::Create(llvm::Instruction::SRem, al,
CONST_V<8>(b, 0x0A), "", b);
R_WRITE<8>(b, llvm::X86::AL, mod);
R_WRITE<8>(b, llvm::X86::AH, res);
@@ -412,18 +410,18 @@ static InstTransResult doAAM(BasicBlock *b) {
return ContinueBlock;
}
static InstTransResult doAAD(BasicBlock *b) {
static InstTransResult doAAD(llvm::BasicBlock *b) {
Value *al;
Value *ah;
llvm::Value *al = nullptr;
llvm::Value *ah = nullptr;
al = R_READ<8>(b, llvm::X86::AL);
ah = R_READ<8>(b, llvm::X86::AH);
Value *tmp = BinaryOperator::Create(Instruction::Mul, ah, CONST_V<8>(b, 0x0A),
"", b);
tmp = BinaryOperator::CreateAdd(tmp, al, "", b);
tmp = BinaryOperator::CreateAnd(tmp, CONST_V<8>(b, 0xFF), "", b);
llvm::Value *tmp = llvm::BinaryOperator::Create(llvm::Instruction::Mul, ah,
CONST_V<8>(b, 0x0A), "", b);
tmp = llvm::BinaryOperator::CreateAdd(tmp, al, "", b);
tmp = llvm::BinaryOperator::CreateAnd(tmp, CONST_V<8>(b, 0xFF), "", b);
R_WRITE<8>(b, llvm::X86::AL, tmp);
R_WRITE<8>(b, llvm::X86::AH, CONST_V<8>(b, 0x00));
@@ -439,23 +437,24 @@ static InstTransResult doAAD(BasicBlock *b) {
}
template<int width>
static InstTransResult doCwd(BasicBlock *b) {
static InstTransResult doCwd(llvm::BasicBlock *b) {
// read ax or eax
Value *ax_val = R_READ<width>(b, llvm::X86::EAX);
llvm::Value *ax_val = R_READ<width>(b, llvm::X86::EAX);
// sign extend to twice width
Type *dt = Type::getIntNTy(b->getContext(), width * 2);
Value *tmp = new SExtInst(ax_val, dt, "", b);
auto dt = llvm::Type::getIntNTy(b->getContext(), width * 2);
auto tmp = new llvm::SExtInst(ax_val, dt, "", b);
// rotate leftmost bits into rightmost
Type *t = Type::getIntNTy(b->getContext(), width);
Value *res_sh = BinaryOperator::Create(Instruction::LShr, tmp,
CONST_V<width * 2>(b, width), "", b);
auto t = llvm::Type::getIntNTy(b->getContext(), width);
auto res_sh = llvm::BinaryOperator::Create(llvm::Instruction::LShr, tmp,
CONST_V<width * 2>(b, width), "",
b);
// original rightmost
Value *wrAX = new TruncInst(tmp, t, "", b);
auto wrAX = new llvm::TruncInst(tmp, t, "", b);
// original leftmost
Value *wrDX = new TruncInst(res_sh, t, "", b);
auto wrDX = new llvm::TruncInst(res_sh, t, "", b);
switch (width) {
case 16:
R_WRITE<width>(b, llvm::X86::DX, wrDX);
@@ -477,9 +476,9 @@ static InstTransResult doCwd(BasicBlock *b) {
}
static InstTransResult translate_SAHF(NativeModulePtr natM, BasicBlock *&block,
InstPtr ip, MCInst &inst) {
Value *ah_val = R_READ<8>(block, llvm::X86::AH);
static InstTransResult translate_SAHF(TranslationContext &ctx,
llvm::BasicBlock *&block) {
auto ah_val = R_READ<8>(block, llvm::X86::AH);
SHR_SET_FLAG<8, 1>(block, ah_val, CF, 0);
// bit 1 is reserved
@@ -494,8 +493,8 @@ static InstTransResult translate_SAHF(NativeModulePtr natM, BasicBlock *&block,
}
template<int width>
static InstTransResult doBtmi(InstPtr ip, BasicBlock *&b, Value *base,
const MCOperand &index) {
static InstTransResult doBtmi(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *base, const llvm::MCOperand &index) {
TASSERT(index.isImm(), "Operand must be an immediate");
int imm = index.getImm();
@@ -506,54 +505,53 @@ static InstTransResult doBtmi(InstPtr ip, BasicBlock *&b, Value *base,
whichbit *= -1;
}
Value *addrInt = base;
auto addrInt = base;
if (base->getType()->isPointerTy()) {
addrInt = new PtrToIntInst(base,
llvm::Type::getIntNTy(b->getContext(), width),
"", b);
addrInt = new llvm::PtrToIntInst(
base, llvm::Type::getIntNTy(b->getContext(), width), "", b);
}
// pick which byte we need to bit test
Value *new_base = BinaryOperator::Create(Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt), "",
b);
auto new_base = llvm::BinaryOperator::Create(llvm::Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt),
"", b);
Value *base_val = M_READ<8>(ip, b, new_base);
auto base_val = M_READ<8>(ip, b, new_base);
SHR_SET_FLAG_V<8, 1>(b, base_val, CF, CONST_V<8>(b, whichbit));
return ContinueBlock;
}
template<int width>
static InstTransResult doBtri(BasicBlock *&b, const MCOperand &base,
const MCOperand &index) {
static InstTransResult doBtri(llvm::BasicBlock *&b, const llvm::MCOperand &base,
const llvm::MCOperand &index) {
TASSERT(base.isReg(), "Operand must be an immediate");
TASSERT(index.isImm(), "Operand must be an immediate");
unsigned whichbit = index.getImm();
whichbit %= width;
Value *base_val = R_READ<width>(b, base.getReg());
auto base_val = R_READ<width>(b, base.getReg());
SHR_SET_FLAG_V<width, 1>(b, base_val, CF, CONST_V<width>(b, whichbit));
return ContinueBlock;
}
template<int width>
static InstTransResult doBtrr(BasicBlock *&b, const MCOperand &base,
const MCOperand &index) {
static InstTransResult doBtrr(llvm::BasicBlock *&b, const llvm::MCOperand &base,
const llvm::MCOperand &index) {
TASSERT(base.isReg(), "operand must be register");
TASSERT(index.isReg(), "operand must be register");
Value *base_val = R_READ<width>(b, base.getReg());
Value *index_val = R_READ<width>(b, index.getReg());
auto base_val = R_READ<width>(b, base.getReg());
auto index_val = R_READ<width>(b, index.getReg());
// modulo the index by register size
Value *index_mod = BinaryOperator::CreateURem(index_val,
CONST_V<width>(b, width), "",
b);
auto index_mod = llvm::BinaryOperator::CreateURem(index_val,
CONST_V<width>(b, width),
"", b);
SHR_SET_FLAG_V<width, 1>(b, base_val, CF, index_mod);
@@ -561,27 +559,30 @@ static InstTransResult doBtrr(BasicBlock *&b, const MCOperand &base,
}
template<int width>
static InstTransResult doBTSri(BasicBlock *&b, const MCOperand &base,
const MCOperand &index) {
static InstTransResult doBTSri(llvm::BasicBlock *&b,
const llvm::MCOperand &base,
const llvm::MCOperand &index) {
TASSERT(base.isReg(), "Operand must be an immediate");
TASSERT(index.isImm(), "Operand must be an immediate");
unsigned whichbit = index.getImm();
whichbit %= width;
Value *base_val = R_READ<width>(b, base.getReg());
auto base_val = R_READ<width>(b, base.getReg());
SHR_SET_FLAG_V<width, 1>(b, base_val, CF, CONST_V<width>(b, whichbit));
auto new_base_val = BinaryOperator::Create(
Instruction::Or, base_val, CONST_V<width>(b, 1ULL << whichbit), "", b);
auto new_base_val = llvm::BinaryOperator::Create(
llvm::Instruction::Or, base_val, CONST_V<width>(b, 1ULL << whichbit), "",
b);
R_WRITE<width>(b, base.getReg(), new_base_val);
return ContinueBlock;
}
template<int width>
static InstTransResult doBTSmi(InstPtr ip, BasicBlock *&b, Value *base,
const MCOperand &index) {
static InstTransResult doBTSmi(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *base,
const llvm::MCOperand &index) {
TASSERT(index.isImm(), "Operand must be an immediate");
int imm = index.getImm();
@@ -592,33 +593,34 @@ static InstTransResult doBTSmi(InstPtr ip, BasicBlock *&b, Value *base,
whichbit *= -1;
}
Value *addrInt = base;
auto addrInt = base;
if (base->getType()->isPointerTy()) {
addrInt = new PtrToIntInst(base,
llvm::Type::getIntNTy(b->getContext(), width),
"", b);
addrInt = new llvm::PtrToIntInst(
base, llvm::Type::getIntNTy(b->getContext(), width), "", b);
}
// pick which byte we need to bit test
Value *new_base = BinaryOperator::Create(Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt), "",
b);
auto new_base = llvm::BinaryOperator::Create(llvm::Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt),
"", b);
Value *base_val = M_READ<8>(ip, b, new_base);
auto base_val = M_READ<8>(ip, b, new_base);
SHR_SET_FLAG_V<8, 1>(b, base_val, CF, CONST_V<8>(b, whichbit));
auto new_base_val = BinaryOperator::Create(Instruction::Or, base_val,
CONST_V<8>(b, 1 << whichbit), "",
b);
auto new_base_val = llvm::BinaryOperator::Create(llvm::Instruction::Or,
base_val,
CONST_V<8>(b, 1 << whichbit),
"", b);
M_WRITE<8>(ip, b, new_base, new_base_val);
return ContinueBlock;
}
template<int width>
static InstTransResult doBTRmi(InstPtr ip, BasicBlock *&b, Value *base,
const MCOperand &index) {
static InstTransResult doBTRmi(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *base,
const llvm::MCOperand &index) {
TASSERT(index.isImm(), "Operand must be an immediate");
int imm = index.getImm();
@@ -629,25 +631,24 @@ static InstTransResult doBTRmi(InstPtr ip, BasicBlock *&b, Value *base,
whichbit *= -1;
}
Value *addrInt = base;
auto addrInt = base;
if (base->getType()->isPointerTy()) {
addrInt = new PtrToIntInst(base,
llvm::Type::getIntNTy(b->getContext(), width),
"", b);
addrInt = new llvm::PtrToIntInst(
base, llvm::Type::getIntNTy(b->getContext(), width), "", b);
}
// pick which byte we need to bit test
Value *new_base = BinaryOperator::Create(Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt), "",
b);
auto new_base = llvm::BinaryOperator::Create(llvm::Instruction::Add, addrInt,
CONST_V<width>(b, bytes_offt),
"", b);
Value *base_val = M_READ<8>(ip, b, new_base);
auto base_val = M_READ<8>(ip, b, new_base);
SHR_SET_FLAG_V<8, 1>(b, base_val, CF, CONST_V<8>(b, whichbit));
auto new_base_val = BinaryOperator::Create(Instruction::And, base_val,
CONST_V<8>(b, ~(1ULL << whichbit)),
"", b);
auto new_base_val = llvm::BinaryOperator::Create(
llvm::Instruction::And, base_val, CONST_V<8>(b, ~(1ULL << whichbit)), "",
b);
M_WRITE<8>(ip, b, new_base, new_base_val);
@@ -655,38 +656,38 @@ static InstTransResult doBTRmi(InstPtr ip, BasicBlock *&b, Value *base,
}
template<int width>
static InstTransResult doBsrr(BasicBlock *&b, const MCOperand &dst,
const MCOperand &src) {
static InstTransResult doBsrr(llvm::BasicBlock *&b, const llvm::MCOperand &dst,
const llvm::MCOperand &src) {
TASSERT(dst.isReg(), "operand must be register");
TASSERT(src.isReg(), "operand must be register");
Value *src_val = R_READ<width>(b, src.getReg());
auto src_val = R_READ<width>(b, src.getReg());
Type *s[1] = {Type::getIntNTy(b->getContext(), width)};
Function *ctlzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::ctlz, s);
llvm::Type *s[] = {llvm::Type::getIntNTy(b->getContext(), width)};
auto ctlzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::ctlz, s);
TASSERT(ctlzFn != NULL, "Could not find ctlz intrinsic");
vector<Value*> ctlzArgs;
std::vector<llvm::Value *> ctlzArgs;
ctlzArgs.push_back(src_val);
ctlzArgs.push_back(CONST_V<1>(b, 0));
Value *ctlz = CallInst::Create(ctlzFn, ctlzArgs, "", b);
auto ctlz = llvm::CallInst::Create(ctlzFn, ctlzArgs, "", b);
Value *index_of_first_1 = BinaryOperator::CreateSub(CONST_V<width>(b, width),
ctlz, "", b);
auto index_of_first_1 = llvm::BinaryOperator::CreateSub(
CONST_V<width>(b, width), ctlz, "", b);
Value *is_zero = new ICmpInst( *b, CmpInst::ICMP_EQ, CONST_V<width>(b, 0),
index_of_first_1);
auto is_zero = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ,
CONST_V<width>(b, 0), index_of_first_1);
F_WRITE(b, ZF, is_zero);
Value *fix_index = BinaryOperator::CreateSub(index_of_first_1,
CONST_V<width>(b, 1), "", b);
auto fix_index = llvm::BinaryOperator::CreateSub(index_of_first_1,
CONST_V<width>(b, 1), "", b);
// See if we write to register
Value *save_index = SelectInst::Create(is_zero, // check if the source was zero
auto save_index = llvm::SelectInst::Create(is_zero, // check if the source was zero
src_val, // if it was, do not change contents
fix_index, // if it was not, set index
"", b);
@@ -697,31 +698,32 @@ static InstTransResult doBsrr(BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doBsfrm(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
Value *memAddr) {
static InstTransResult doBsfrm(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &dst,
llvm::Value *memAddr) {
TASSERT(dst.isReg(), "operand must be register");
Value *src_val = M_READ<width>(ip, b, memAddr);
auto src_val = M_READ<width>(ip, b, memAddr);
Type *s[1] = {Type::getIntNTy(b->getContext(), width)};
Function *cttzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::cttz, s);
llvm::Type *s[] = {llvm::Type::getIntNTy(b->getContext(), width)};
auto cttzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::cttz, s);
TASSERT(cttzFn != NULL, "Could not find cttz intrinsic");
vector<Value*> cttzArgs;
std::vector<llvm::Value *> cttzArgs;
cttzArgs.push_back(src_val);
cttzArgs.push_back(CONST_V<1>(b, 0));
Value *cttz = CallInst::Create(cttzFn, cttzArgs, "", b);
auto cttz = llvm::CallInst::Create(cttzFn, cttzArgs, "", b);
Value *is_zero = new ICmpInst( *b, CmpInst::ICMP_EQ, CONST_V<width>(b, width),
cttz);
auto is_zero = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ,
CONST_V<width>(b, width), cttz);
F_WRITE(b, ZF, is_zero);
// See if we write to register
Value *save_index = SelectInst::Create(is_zero, // check if the source was zero
auto save_index = llvm::SelectInst::Create(is_zero, // check if the source was zero
src_val, // if it was, do not change contents
cttz, // if it was not, set index
"", b);
@@ -732,32 +734,32 @@ static InstTransResult doBsfrm(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doBsfr(BasicBlock *&b, const MCOperand &dst,
const MCOperand &src) {
static InstTransResult doBsfr(llvm::BasicBlock *&b, const llvm::MCOperand &dst,
const llvm::MCOperand &src) {
TASSERT(dst.isReg(), "operand must be register");
TASSERT(src.isReg(), "operand must be register");
Value *src_val = R_READ<width>(b, src.getReg());
auto src_val = R_READ<width>(b, src.getReg());
Type *s[1] = {Type::getIntNTy(b->getContext(), width)};
Function *cttzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::cttz, s);
llvm::Type *s[] = {llvm::Type::getIntNTy(b->getContext(), width)};
auto cttzFn = Intrinsic::getDeclaration(b->getParent()->getParent(),
Intrinsic::cttz, s);
TASSERT(cttzFn != NULL, "Could not find cttz intrinsic");
vector<Value*> cttzArgs;
std::vector<llvm::Value *> cttzArgs;
cttzArgs.push_back(src_val);
cttzArgs.push_back(CONST_V<1>(b, 0));
Value *cttz = CallInst::Create(cttzFn, cttzArgs, "", b);
auto cttz = llvm::CallInst::Create(cttzFn, cttzArgs, "", b);
Value *is_zero = new ICmpInst( *b, CmpInst::ICMP_EQ, CONST_V<width>(b, width),
cttz);
auto is_zero = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ,
CONST_V<width>(b, width), cttz);
F_WRITE(b, ZF, is_zero);
// See if we write to register
Value *save_index = SelectInst::Create(is_zero, // check if the source was zero
auto save_index = llvm::SelectInst::Create(is_zero, // check if the source was zero
src_val, // if it was, do not change contents
cttz, // if it was not, set index
"", b);
@@ -786,24 +788,27 @@ GENERIC_TRANSLATION_REF(LEA16r, doLea<16>(ip, block, ADDR_NOREF(1), OP(0)),
doLea<16>(ip, block, MEM_REFERENCE(1), OP(0)))
template<int width>
static InstTransResult doLeaRef(NativeModulePtr natM, BasicBlock *&block,
InstPtr ip, MCInst &inst) {
static InstTransResult doLeaRef(TranslationContext &ctx,
llvm::BasicBlock *&block) {
InstTransResult ret;
Function *F = block->getParent();
auto F = block->getParent();
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto natM = ctx.natM;
if (ip->has_code_ref()) {
Inst::CFGOpType optype;
NativeInst::CFGOpType optype;
if (ip->has_mem_reference) {
optype = Inst::MEMRef;
optype = NativeInst::MEMRef;
} else if (ip->has_imm_reference) {
optype = Inst::IMMRef;
optype = NativeInst::IMMRef;
} else {
throw TErr(__LINE__, __FILE__, "Have code ref but no reference");
}
Value *callback_fn = ArchAddCallbackDriver(block->getParent()->getParent(),
ip->get_reference(optype));
Value *addrInt = new PtrToIntInst(
auto callback_fn = ArchAddCallbackDriver(block->getParent()->getParent(),
ip->get_reference(optype));
auto addrInt = new llvm::PtrToIntInst(
callback_fn, llvm::Type::getIntNTy(block->getContext(), width), "",
block);
ret = doLeaV<width>(block, OP(0), addrInt);
@@ -817,29 +822,26 @@ static InstTransResult doLeaRef(NativeModulePtr natM, BasicBlock *&block,
}
return ret;
}
static InstTransResult translate_LEA32r(NativeModulePtr natM,
BasicBlock *&block, InstPtr ip,
MCInst &inst) {
return doLeaRef<32>(natM, block, ip, inst);
static InstTransResult translate_LEA32r(TranslationContext &ctx,
llvm::BasicBlock *&block) {
return doLeaRef<32>(ctx, block);
}
static InstTransResult translate_LEA64r(NativeModulePtr natM,
BasicBlock *&block, InstPtr ip,
MCInst &inst) {
return doLeaRef<64>(natM, block, ip, inst);
static InstTransResult translate_LEA64r(TranslationContext &ctx,
llvm::BasicBlock *&block) {
return doLeaRef<64>(ctx, block);
}
static InstTransResult translate_LEA64_32r(NativeModulePtr natM,
BasicBlock *&block, InstPtr ip,
MCInst &inst) {
return doLeaRef<32>(natM, block, ip, inst);
static InstTransResult translate_LEA64_32r(TranslationContext &ctx,
llvm::BasicBlock *&block) {
return doLeaRef<32>(ctx, block);
}
static InstTransResult translate_CPUID32(NativeModulePtr natM,
BasicBlock *&block, InstPtr ip,
MCInst &inst) {
Value *eax = R_READ<32>(block, llvm::X86::EAX);
Value *ecx = R_READ<32>(block, llvm::X86::ECX);
static InstTransResult translate_CPUID32(TranslationContext &ctx,
llvm::BasicBlock *&block) {
auto eax = R_READ<32>(block, llvm::X86::EAX);
auto ecx = R_READ<32>(block, llvm::X86::ECX);
CREATE_BLOCK(b0, block);
CREATE_BLOCK(b1, block);
@@ -862,8 +864,7 @@ static InstTransResult translate_CPUID32(NativeModulePtr natM,
CREATE_BLOCK(eax11_b1, block_b11);
CREATE_BLOCK(eax11_bdefault, block_b11);
llvm::SwitchInst *si = llvm::SwitchInst::Create(eax, block_bdefault, 7,
block);
auto si = llvm::SwitchInst::Create(eax, block_bdefault, 7, block);
// 32-bit CPUID values taken by sampling from a live CPU
+218 -270
View File
@@ -1,31 +1,32 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "InstructionDispatch.h"
#include "toLLVM.h"
#include "X86.h"
@@ -33,261 +34,222 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "x86Helpers.h"
#include "x86Instrs_SETcc.h"
using namespace llvm;
static llvm::Value *doSetaV(NativeInstPtr ip, llvm::BasicBlock *&b) {
static Value *doSetaV(InstPtr ip, BasicBlock *&b)
{
// set 1 if CF==0 && ZF==0
// else, set 0
auto cf_val = F_READ(b, CF);
auto zf_val = F_READ(b, ZF);
// set 1 if CF==0 && ZF==0
// else, set 0
Value *cf_val = F_READ(b, CF);
Value *zf_val = F_READ(b, ZF);
// cf|zf == 0 iff cf == 0 && zf == 0
auto f_or = llvm::BinaryOperator::CreateOr(cf_val, zf_val, "", b);
// cf|zf == 0 iff cf == 0 && zf == 0
Value *f_or =
BinaryOperator::CreateOr(cf_val, zf_val, "", b);
// to_set will be 1 iff cf == 0 && zf == 0
auto to_set = llvm::BinaryOperator::CreateNot(f_or, "", b);
// to_set will be 1 iff cf == 0 && zf == 0
Value *to_set = BinaryOperator::CreateNot(f_or, "", b);
// zero extend to desired width
Value *ext_to_set = new ZExtInst(to_set, Type::getIntNTy(b->getContext(), 8), "", b);
return ext_to_set;
// zero extend to desired width
return new llvm::ZExtInst(to_set, llvm::Type::getIntNTy(b->getContext(), 8),
"", b);
}
static Value *doSetbV(InstPtr ip, BasicBlock *&b)
{
// setb == set if cf == 1
// essentially, read CF
Value *cf_val = F_READ(b, CF);
static llvm::Value *doSetbV(NativeInstPtr ip, llvm::BasicBlock *&b) {
// setb == set if cf == 1
// essentially, read CF
auto cf_val = F_READ(b, CF);
// zero extend to desired width
Value *ext_to_set = new ZExtInst(cf_val, Type::getIntNTy(b->getContext(), 8), "", b);
return ext_to_set;
// zero extend to desired width
return new llvm::ZExtInst(cf_val, llvm::Type::getIntNTy(b->getContext(), 8),
"", b);
}
static Value *doSetsV(InstPtr ip, BasicBlock *&b)
{
// sets == set if sf == 1
// essentially, read SF
Value *sf_val = F_READ(b, SF);
static llvm::Value *doSetsV(NativeInstPtr ip, llvm::BasicBlock *&b) {
// sets == set if sf == 1
// essentially, read SF
auto sf_val = F_READ(b, SF);
// zero extend to desired width
Value *ext_to_set = new ZExtInst(sf_val, Type::getIntNTy(b->getContext(), 8), "", b);
return ext_to_set;
// zero extend to desired width
return new llvm::ZExtInst(sf_val, llvm::Type::getIntNTy(b->getContext(), 8),
"", b);
}
// set if CF==0
static Value *doSetaeV(InstPtr ip, BasicBlock *&b)
{
//read CF
Value *cf_val = F_READ(b, CF);
static llvm::Value *doSetaeV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read CF
auto cf_val = F_READ(b, CF);
//compare to 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, cf_val, CONST_V<1>(b,0));
//compare to 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, cf_val,
CONST_V<1>(b, 0));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
static Value *doSetneV(InstPtr ip, BasicBlock *&b)
{
//read ZF
Value *zf_val = F_READ(b, ZF);
static llvm::Value *doSetneV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read ZF
auto zf_val = F_READ(b, ZF);
//compare to 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, zf_val, CONST_V<1>(b,0));
//compare to 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, zf_val,
CONST_V<1>(b, 0));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
static Value *doSeteV(InstPtr ip, BasicBlock *&b)
{
//read ZF
Value *zf_val = F_READ(b, ZF);
static llvm::Value *doSeteV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read ZF
auto zf_val = F_READ(b, ZF);
//compare to not 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_NE, zf_val, CONST_V<1>(b,0));
//compare to not 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_NE, zf_val,
CONST_V<1>(b, 0));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// setge: of == sf
static Value *doSetgeV(InstPtr ip, BasicBlock *&b)
{
Value *sf_val = F_READ(b, SF);
Value *of_val = F_READ(b, OF);
static llvm::Value *doSetgeV(NativeInstPtr ip, llvm::BasicBlock *&b) {
auto sf_val = F_READ(b, SF);
auto of_val = F_READ(b, OF);
//compare of == sf
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, sf_val, of_val);
//compare of == sf
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, sf_val,
of_val);
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// setg: of == sf && ZF==0
static Value *doSetgV(InstPtr ip, BasicBlock *&b)
{
Value *sf_val = F_READ(b, SF);
Value *of_val = F_READ(b, OF);
Value *zf_val = F_READ(b, ZF);
static llvm::Value *doSetgV(NativeInstPtr ip, llvm::BasicBlock *&b) {
auto sf_val = F_READ(b, SF);
auto of_val = F_READ(b, OF);
auto zf_val = F_READ(b, ZF);
//compare of == sf
Value *cmp0_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, sf_val, of_val);
//compare of == sf
auto cmp0_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, sf_val,
of_val);
// if ZF == 0, NOT ZF == 1
Value *not_zf = BinaryOperator::CreateNot(zf_val, "", b);
// if ZF == 0, NOT ZF == 1
auto not_zf = llvm::BinaryOperator::CreateNot(zf_val, "", b);
// final result:
// (sf==of) & (not zf)
Value *cmp_res =
BinaryOperator::CreateAnd(cmp0_res, not_zf, "", b);
// final result:
// (sf==of) & (not zf)
auto cmp_res = llvm::BinaryOperator::CreateAnd(cmp0_res, not_zf, "", b);
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// setle: of != sf || ZF==1
static Value *doSetleV(InstPtr ip, BasicBlock *&b)
{
Value *sf_val = F_READ(b, SF);
Value *of_val = F_READ(b, OF);
Value *zf_val = F_READ(b, ZF);
static llvm::Value *doSetleV(NativeInstPtr ip, llvm::BasicBlock *&b) {
auto sf_val = F_READ(b, SF);
auto of_val = F_READ(b, OF);
auto zf_val = F_READ(b, ZF);
//compare of == sf
Value *cmp0_res =
new ICmpInst(*b, CmpInst::ICMP_NE, sf_val, of_val);
//compare of == sf
auto cmp0_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_NE, sf_val,
of_val);
// final result:
// (sf!=of) | (zf)
Value *cmp_res =
BinaryOperator::CreateOr(cmp0_res, zf_val, "", b);
// final result:
// (sf!=of) | (zf)
auto cmp_res = llvm::BinaryOperator::CreateOr(cmp0_res, zf_val, "", b);
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// setge: of != sf
static Value *doSetlV(InstPtr ip, BasicBlock *&b)
{
Value *sf_val = F_READ(b, SF);
Value *of_val = F_READ(b, OF);
static llvm::Value *doSetlV(NativeInstPtr ip, llvm::BasicBlock *&b) {
auto sf_val = F_READ(b, SF);
auto of_val = F_READ(b, OF);
//compare of != sf
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_NE, sf_val, of_val);
//compare of != sf
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_NE, sf_val,
of_val);
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
//setbe: cf==1 or zf==1
static Value *doSetbeV(InstPtr ip, BasicBlock *&b)
{
Value *cf_val = F_READ(b, CF);
Value *zf_val = F_READ(b, ZF);
static llvm::Value *doSetbeV(NativeInstPtr ip, llvm::BasicBlock *&b) {
auto cf_val = F_READ(b, CF);
auto zf_val = F_READ(b, ZF);
// final result:
// result = cf | zf
Value *cmp_res =
BinaryOperator::CreateOr(cf_val, zf_val, "", b);
// final result:
// result = cf | zf
auto cmp_res = llvm::BinaryOperator::CreateOr(cf_val, zf_val, "", b);
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// set if pf == 0
static Value *doSetnpV(InstPtr ip, BasicBlock *&b)
{
//read PF
Value *pf_val = F_READ(b, PF);
static llvm::Value *doSetnpV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read PF
auto pf_val = F_READ(b, PF);
//compare to 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, pf_val, CONST_V<1>(b,0));
//compare to 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, pf_val,
CONST_V<1>(b, 0));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// set if pf == 1
static Value *doSetpV(InstPtr ip, BasicBlock *&b)
{
//read PF
Value *pf_val = F_READ(b, PF);
static llvm::Value *doSetpV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read PF
auto pf_val = F_READ(b, PF);
//compare to 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, pf_val, CONST_V<1>(b,1));
//compare to 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, pf_val,
CONST_V<1>(b, 1));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// set if sf == 0
static Value *doSetnsV(InstPtr ip, BasicBlock *&b)
{
//read SF
Value *sf_val = F_READ(b, SF);
static llvm::Value *doSetnsV(NativeInstPtr ip, llvm::BasicBlock *&b) {
//read SF
auto sf_val = F_READ(b, SF);
//compare to 0
Value *cmp_res =
new ICmpInst(*b, CmpInst::ICMP_EQ, sf_val, CONST_V<1>(b,0));
//compare to 0
auto cmp_res = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, sf_val,
CONST_V<1>(b, 0));
//extend result to 8 bits
Value *res = new ZExtInst(cmp_res, Type::getInt8Ty(b->getContext()), "", b);
return res;
//extend result to 8 bits
return new llvm::ZExtInst(cmp_res, llvm::Type::getInt8Ty(b->getContext()), "",
b);
}
// SETcc always operate on 8bit quantities
#define DO_SETCC_OP_REG(NAME) static InstTransResult do ## NAME ## R(InstPtr ip, BasicBlock *&b, const MCOperand &reg) \
#define DO_SETCC_OP_REG(NAME) static InstTransResult do ## NAME ## R(NativeInstPtr ip, llvm::BasicBlock *&b, const llvm::MCOperand &reg) \
{ \
TASSERT(reg.isReg(), "");\
Value *val_to_set = do ## NAME ## V(ip, b); \
auto val_to_set = do ## NAME ## V(ip, b); \
R_WRITE<8>(b, reg.getReg(), val_to_set); \
return ContinueBlock; \
}
#define DO_SETCC_OP_MEM(NAME) static InstTransResult do ## NAME ## M(InstPtr ip, BasicBlock *&b, Value *addr) \
#define DO_SETCC_OP_MEM(NAME) static InstTransResult do ## NAME ## M(NativeInstPtr ip, llvm::BasicBlock *&b, llvm::Value *addr) \
{ \
TASSERT(addr != NULL, ""); \
Value *val_to_set = do ## NAME ## V(ip ,b); \
auto val_to_set = do ## NAME ## V(ip ,b); \
M_WRITE<8>(ip, b, addr, val_to_set); \
return ContinueBlock; \
}
@@ -321,95 +283,81 @@ DO_SETCC_OP_MEM(Setns)
DO_SETCC_OP_REG(Setp)
DO_SETCC_OP_MEM(Setp)
GENERIC_TRANSLATION_REF(SETAm,
doSetaM(ip, block, ADDR_NOREF(0)),
doSetaM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETAm, doSetaM(ip, block, ADDR_NOREF(0)),
doSetaM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETAr, doSetaR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETBm,
doSetbM(ip, block, ADDR_NOREF(0)),
doSetbM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETBm, doSetbM(ip, block, ADDR_NOREF(0)),
doSetbM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETBr, doSetbR(ip, block, OP(0)))
GENERIC_TRANSLATION(SETNEr, doSetneR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETNEm,
doSetneM(ip, block, ADDR_NOREF(0)),
doSetneM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETNEm, doSetneM(ip, block, ADDR_NOREF(0)),
doSetneM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETEr, doSeteR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETEm,
doSeteM(ip, block, ADDR_NOREF(0)),
doSeteM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETEm, doSeteM(ip, block, ADDR_NOREF(0)),
doSeteM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETGEr, doSetgeR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETGEm,
doSetgeM(ip, block, ADDR_NOREF(0)),
doSetgeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETGEm, doSetgeM(ip, block, ADDR_NOREF(0)),
doSetgeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETGr, doSetgR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETGm,
doSetgM(ip, block, ADDR_NOREF(0)),
doSetgM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETGm, doSetgM(ip, block, ADDR_NOREF(0)),
doSetgM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETLr, doSetlR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETLm,
doSetlM(ip, block, ADDR_NOREF(0)),
doSetlM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETLm, doSetlM(ip, block, ADDR_NOREF(0)),
doSetlM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETLEr, doSetleR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETLEm,
doSetleM(ip, block, ADDR_NOREF(0)),
doSetleM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETLEm, doSetleM(ip, block, ADDR_NOREF(0)),
doSetleM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETSr, doSetsR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETSm,
doSetsM(ip, block, ADDR_NOREF(0)),
doSetsM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETSm, doSetsM(ip, block, ADDR_NOREF(0)),
doSetsM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETAEr, doSetaeR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETAEm,
doSetaeM(ip, block, ADDR_NOREF(0)),
doSetaeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETAEm, doSetaeM(ip, block, ADDR_NOREF(0)),
doSetaeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETBEr, doSetbeR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETBEm,
doSetbeM(ip, block, ADDR_NOREF(0)),
doSetbeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETBEm, doSetbeM(ip, block, ADDR_NOREF(0)),
doSetbeM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETNPr, doSetnpR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETNPm,
doSetnpM(ip, block, ADDR_NOREF(0)),
doSetnpM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETNPm, doSetnpM(ip, block, ADDR_NOREF(0)),
doSetnpM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETNSr, doSetnsR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETNSm,
doSetnsM(ip, block, ADDR_NOREF(0)),
doSetnsM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETNSm, doSetnsM(ip, block, ADDR_NOREF(0)),
doSetnsM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION(SETPr, doSetpR(ip, block, OP(0)))
GENERIC_TRANSLATION_REF(SETPm,
doSetpM(ip, block, ADDR_NOREF(0)),
doSetpM(ip, block, MEM_REFERENCE(0)))
GENERIC_TRANSLATION_REF(SETPm, doSetpM(ip, block, ADDR_NOREF(0)),
doSetpM(ip, block, MEM_REFERENCE(0)))
void SETcc_populateDispatchMap(DispatchMap &m) {
m[X86::SETAm] = translate_SETAm;
m[X86::SETAr] = translate_SETAr;
m[X86::SETBm] = translate_SETBm;
m[X86::SETBr] = translate_SETBr;
m[X86::SETNEr] = translate_SETNEr;
m[X86::SETNEm] = translate_SETNEm;
m[X86::SETEr] = translate_SETEr;
m[X86::SETEm] = translate_SETEm;
m[X86::SETGEr] = translate_SETGEr;
m[X86::SETGEm] = translate_SETGEm;
m[X86::SETLr] = translate_SETLr;
m[X86::SETLm] = translate_SETLm;
m[X86::SETLEr] = translate_SETLEr;
m[X86::SETLEm] = translate_SETLEm;
m[X86::SETGr] = translate_SETGr;
m[X86::SETGm] = translate_SETGm;
m[X86::SETSr] = translate_SETSr;
m[X86::SETSm] = translate_SETSm;
m[X86::SETAm] = translate_SETAm;
m[X86::SETAr] = translate_SETAr;
m[X86::SETBm] = translate_SETBm;
m[X86::SETBr] = translate_SETBr;
m[X86::SETNEr] = translate_SETNEr;
m[X86::SETNEm] = translate_SETNEm;
m[X86::SETEr] = translate_SETEr;
m[X86::SETEm] = translate_SETEm;
m[X86::SETGEr] = translate_SETGEr;
m[X86::SETGEm] = translate_SETGEm;
m[X86::SETLr] = translate_SETLr;
m[X86::SETLm] = translate_SETLm;
m[X86::SETLEr] = translate_SETLEr;
m[X86::SETLEm] = translate_SETLEm;
m[X86::SETGr] = translate_SETGr;
m[X86::SETGm] = translate_SETGm;
m[X86::SETSr] = translate_SETSr;
m[X86::SETSm] = translate_SETSm;
m[X86::SETAEr] = translate_SETAEr;
m[X86::SETAEm] = translate_SETAEm;
m[X86::SETAEr] = translate_SETAEr;
m[X86::SETAEm] = translate_SETAEm;
m[X86::SETBEr] = translate_SETBEr;
m[X86::SETBEm] = translate_SETBEm;
m[X86::SETBEr] = translate_SETBEr;
m[X86::SETBEm] = translate_SETBEm;
m[X86::SETNPr] = translate_SETNPr;
m[X86::SETNPm] = translate_SETNPm;
m[X86::SETNPr] = translate_SETNPr;
m[X86::SETNPm] = translate_SETNPm;
m[X86::SETPr] = translate_SETPr;
m[X86::SETPm] = translate_SETPm;
m[X86::SETPr] = translate_SETPr;
m[X86::SETPm] = translate_SETPm;
m[X86::SETNSr] = translate_SETNSr;
m[X86::SETNSm] = translate_SETNSm;
m[X86::SETNSr] = translate_SETNSr;
m[X86::SETNSm] = translate_SETNSm;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+65 -65
View File
@@ -49,7 +49,7 @@ static Value *getBit(BasicBlock *b, Value *val, int which) {
}
template<int width, Instruction::BinaryOps shift_op>
static Value *doShiftOp(InstPtr ip, BasicBlock *b, Value *src, Value *count) {
static Value *doShiftOp(NativeInstPtr ip, BasicBlock *b, Value *src, Value *count) {
// get the masked count variable
int count_max = (width == 64) ? 63 : 31;
@@ -172,12 +172,12 @@ static Value *doShiftOp(InstPtr ip, BasicBlock *b, Value *src, Value *count) {
}
Value *doShrVV32(BasicBlock *&b, Value *src, Value *count) {
return doShiftOp<32, Instruction::LShr>(InstPtr((Inst*) (nullptr)), b, src,
return doShiftOp<32, Instruction::LShr>(NativeInstPtr((NativeInst*) (nullptr)), b, src,
count);
}
template<int width>
static Value *doShldVV(InstPtr ip, BasicBlock *&b, Value* addr,
static Value *doShldVV(NativeInstPtr ip, BasicBlock *&b, Value* addr,
unsigned srcReg1,
//unsigned shiftBy)
Value* shiftBy) {
@@ -217,7 +217,7 @@ static Value *doShldVV(InstPtr ip, BasicBlock *&b, Value* addr,
}
template<int width>
static Value *doShldRV(InstPtr ip, BasicBlock *&b, unsigned dstReg,
static Value *doShldRV(NativeInstPtr ip, BasicBlock *&b, unsigned dstReg,
unsigned srcReg1, Value* shiftBy) {
Value *from_left = R_READ<width>(b, dstReg);
Value *reg_val = doShldVV<width>(ip, b, from_left, srcReg1, shiftBy);
@@ -227,7 +227,7 @@ static Value *doShldRV(InstPtr ip, BasicBlock *&b, unsigned dstReg,
}
template<int width>
static Value *doShldMV(InstPtr ip, BasicBlock *&b, Value *addr,
static Value *doShldMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
unsigned srcReg1, Value *shiftBy) {
Value *from_left = M_READ<width>(ip, b, addr);
Value *mem_val = doShldVV<width>(ip, b, from_left, srcReg1, shiftBy);
@@ -237,7 +237,7 @@ static Value *doShldMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static Value *doShrdVV(InstPtr ip, BasicBlock *&b, unsigned dstReg,
static Value *doShrdVV(NativeInstPtr ip, BasicBlock *&b, unsigned dstReg,
unsigned srcReg1,
//unsigned shiftBy)
Value* shiftBy) {
@@ -280,11 +280,11 @@ static Value *doShrdVV(InstPtr ip, BasicBlock *&b, unsigned dstReg,
Value *ShrdVV32(BasicBlock *&b, unsigned dstReg, unsigned srcReg1,
Value* shiftBy) {
return doShrdVV<32>(InstPtr((Inst*) (NULL)), b, dstReg, srcReg1, shiftBy);
return doShrdVV<32>(NativeInstPtr((NativeInst*) (NULL)), b, dstReg, srcReg1, shiftBy);
}
template<int width>
static InstTransResult doShrdRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doShrdRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &src1,
const MCOperand &src2) {
TASSERT(src2.isImm(), "");
@@ -298,7 +298,7 @@ static InstTransResult doShrdRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShldRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doShldRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &src1,
const MCOperand &src2) {
TASSERT(src2.isImm(), "");
@@ -322,7 +322,7 @@ static Value *getShifyByValueFromCLRegister(BasicBlock *&b) {
}
template<int width>
static InstTransResult doShldRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doShldRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &src1) {
TASSERT(src1.isReg(), "");
TASSERT(dst.isReg(), "");
@@ -334,7 +334,7 @@ static InstTransResult doShldRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShldMCL(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doShldMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &src1) {
TASSERT(src1.isReg(), "");
@@ -345,7 +345,7 @@ static InstTransResult doShldMCL(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doShrdRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doShrdRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst, const MCOperand &src1) {
TASSERT(src1.isReg(), "");
TASSERT(dst.isReg(), "");
@@ -357,7 +357,7 @@ static InstTransResult doShrdRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShrRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doShrRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &src1, const MCOperand &src2,
const MCOperand &dst) {
TASSERT(src1.isReg(), "");
@@ -375,7 +375,7 @@ static InstTransResult doShrRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShrR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doShrR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -390,7 +390,7 @@ static InstTransResult doShrR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShrRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doShrRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -405,7 +405,7 @@ static InstTransResult doShrRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShrMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doShrMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -421,7 +421,7 @@ static InstTransResult doShrMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doShrMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doShrMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -436,7 +436,7 @@ static InstTransResult doShrMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doShrM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doShrM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -450,7 +450,7 @@ static InstTransResult doShrM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doShrMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doShrMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -464,7 +464,7 @@ static InstTransResult doShrMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doShlRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doShlRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &src1, const MCOperand &src2,
const MCOperand &dst) {
TASSERT(src1.isReg(), "");
@@ -482,7 +482,7 @@ static InstTransResult doShlRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShlR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doShlR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -497,7 +497,7 @@ static InstTransResult doShlR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShlRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doShlRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -512,7 +512,7 @@ static InstTransResult doShlRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doShlMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doShlMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -528,7 +528,7 @@ static InstTransResult doShlMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doShlMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doShlMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -543,7 +543,7 @@ static InstTransResult doShlMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doShlM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doShlM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -557,7 +557,7 @@ static InstTransResult doShlM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doShlMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doShlMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -571,7 +571,7 @@ static InstTransResult doShlMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doSarRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doSarRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &src1, const MCOperand &src2,
const MCOperand &dst) {
TASSERT(src1.isReg(), "");
@@ -589,7 +589,7 @@ static InstTransResult doSarRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doSarR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doSarR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -604,7 +604,7 @@ static InstTransResult doSarR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doSarRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doSarRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -619,7 +619,7 @@ static InstTransResult doSarRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doSarMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doSarMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -635,7 +635,7 @@ static InstTransResult doSarMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doSarMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doSarMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -650,7 +650,7 @@ static InstTransResult doSarMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doSarM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doSarM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -664,7 +664,7 @@ static InstTransResult doSarM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doSarMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doSarMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
Value *dst = M_READ<width>(ip, b, addr);
@@ -678,7 +678,7 @@ static InstTransResult doSarMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static Value *doRclVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
static Value *doRclVV(NativeInstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
Function *F = b->getParent();
//create basic blocks to define the branching behavior
@@ -803,7 +803,7 @@ static Value *doRclVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
}
template<int width>
static InstTransResult doRclM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRclM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -818,7 +818,7 @@ static InstTransResult doRclM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRclMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRclMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &count) {
TASSERT(addr != NULL, "");
@@ -835,7 +835,7 @@ static InstTransResult doRclMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRclMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRclMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
@@ -851,7 +851,7 @@ static InstTransResult doRclMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRclMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRclMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -866,7 +866,7 @@ static InstTransResult doRclMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRclR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doRclR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -882,7 +882,7 @@ static InstTransResult doRclR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRclRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doRclRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst1, const MCOperand &reg,
const MCOperand &count) {
@@ -901,7 +901,7 @@ static InstTransResult doRclRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRclRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doRclRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -917,7 +917,7 @@ static InstTransResult doRclRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static Value *doRcrVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
static Value *doRcrVV(NativeInstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
Function *F = b->getParent();
//create basic blocks to define the branching behavior
@@ -1045,7 +1045,7 @@ static Value *doRcrVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
}
template<int width>
static InstTransResult doRcrM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRcrM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1060,7 +1060,7 @@ static InstTransResult doRcrM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRcrMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRcrMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &count) {
TASSERT(addr != NULL, "");
@@ -1077,7 +1077,7 @@ static InstTransResult doRcrMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRcrMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRcrMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
@@ -1093,7 +1093,7 @@ static InstTransResult doRcrMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRcrMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRcrMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1108,7 +1108,7 @@ static InstTransResult doRcrMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRcrR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doRcrR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -1124,7 +1124,7 @@ static InstTransResult doRcrR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRcrRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doRcrRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst1, const MCOperand &reg,
const MCOperand &count) {
@@ -1143,7 +1143,7 @@ static InstTransResult doRcrRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRcrRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doRcrRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -1159,7 +1159,7 @@ static InstTransResult doRcrRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static Value *doRolVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
static Value *doRolVV(NativeInstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
Function *F = b->getParent();
//create basic blocks to define the branching behavior
@@ -1259,7 +1259,7 @@ static Value *doRolVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
}
template<int width>
static InstTransResult doRolM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRolM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1274,7 +1274,7 @@ static InstTransResult doRolM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRolMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRolMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &count) {
TASSERT(addr != NULL, "");
@@ -1291,7 +1291,7 @@ static InstTransResult doRolMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRolMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRolMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
@@ -1307,7 +1307,7 @@ static InstTransResult doRolMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRolMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRolMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1322,7 +1322,7 @@ static InstTransResult doRolMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRolR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doRolR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -1338,7 +1338,7 @@ static InstTransResult doRolR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRolRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doRolRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst1, const MCOperand &reg,
const MCOperand &count) {
@@ -1357,7 +1357,7 @@ static InstTransResult doRolRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRolRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doRolRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -1373,7 +1373,7 @@ static InstTransResult doRolRCL(InstPtr ip, BasicBlock *&b,
}
template<int width>
static Value *doRorVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
static Value *doRorVV(NativeInstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
Function *F = b->getParent();
//create basic blocks to define the branching behavior
@@ -1478,7 +1478,7 @@ static Value *doRorVV(InstPtr ip, BasicBlock *&b, Value *dst, Value *count) {
}
template<int width>
static InstTransResult doRorM1(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRorM1(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1493,7 +1493,7 @@ static InstTransResult doRorM1(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRorMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRorMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &count) {
TASSERT(addr != NULL, "");
@@ -1510,7 +1510,7 @@ static InstTransResult doRorMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRorMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doRorMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
@@ -1526,7 +1526,7 @@ static InstTransResult doRorMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doRorMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
static InstTransResult doRorMCL(NativeInstPtr ip, BasicBlock *&b, Value *addr) {
TASSERT(addr != NULL, "");
@@ -1542,7 +1542,7 @@ static InstTransResult doRorMCL(InstPtr ip, BasicBlock *&b, Value *addr) {
}
template<int width>
static InstTransResult doRorR1(InstPtr ip, BasicBlock *&b,
static InstTransResult doRorR1(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
@@ -1558,7 +1558,7 @@ static InstTransResult doRorR1(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRorRI(InstPtr ip, BasicBlock *&b,
static InstTransResult doRorRI(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &dst1, const MCOperand &reg,
const MCOperand &count) {
@@ -1577,7 +1577,7 @@ static InstTransResult doRorRI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doRorRCL(InstPtr ip, BasicBlock *&b,
static InstTransResult doRorRCL(NativeInstPtr ip, BasicBlock *&b,
const MCOperand &reg) {
TASSERT(reg.isReg(), "");
+284 -265
View File
@@ -41,68 +41,65 @@
#define NASSERT(cond) TASSERT(cond, "")
using namespace llvm;
template<int width>
static void doPushVT(InstPtr ip, BasicBlock *&b, Value *v) {
static void doPushVT(NativeInstPtr ip, llvm::BasicBlock *&b, llvm::Value *v) {
//ESP <- ESP - 4
//Memory[ESP] = v
if (ArchPointerSize(b->getParent()->getParent())) {
Value *oldESP = R_READ<32>(b, X86::ESP);
Value *newESP = BinaryOperator::CreateSub(oldESP,
CONST_V<32>(b, (width / 8)), "",
b);
auto oldESP = R_READ<32>(b, llvm::X86::ESP);
auto newESP = llvm::BinaryOperator::CreateSub(oldESP,
CONST_V<32>(b, (width / 8)),
"", b);
Value *intVal = CastInst::CreatePointerCast(
v, Type::getInt32Ty(b->getContext()), "", b);
auto intVal = llvm::CastInst::CreatePointerCast(
v, llvm::Type::getInt32Ty(b->getContext()), "", b);
M_WRITE_0<width>(b, newESP, intVal);
R_WRITE<32>(b, X86::ESP, newESP);
R_WRITE<32>(b, llvm::X86::ESP, newESP);
} else {
Value *oldESP = R_READ<64>(b, X86::RSP);
Value *newESP = BinaryOperator::CreateSub(oldESP,
CONST_V<64>(b, (width / 8)), "",
b);
Value *intVal = CastInst::CreatePointerCast(
v, Type::getInt64Ty(b->getContext()), "", b);
auto oldESP = R_READ<64>(b, llvm::X86::RSP);
auto newESP = llvm::BinaryOperator::CreateSub(oldESP,
CONST_V<64>(b, (width / 8)),
"", b);
auto intVal = llvm::CastInst::CreatePointerCast(
v, llvm::Type::getInt64Ty(b->getContext()), "", b);
M_WRITE_0<width>(b, newESP, intVal);
R_WRITE<64>(b, X86::RSP, newESP);
R_WRITE<64>(b, llvm::X86::RSP, newESP);
}
return;
}
template<int width>
static void doPushV(InstPtr ip, BasicBlock *&b, Value *v) {
static void doPushV(NativeInstPtr ip, llvm::BasicBlock *&b, llvm::Value *v) {
//ESP <- ESP - 4
//Memory[ESP] = v
llvm::Module *M = b->getParent()->getParent();
auto M = b->getParent()->getParent();
if (ArchPointerSize(M) == Pointer32) {
Value *oldESP = x86::R_READ<32>(b, X86::ESP);
Value *newESP = BinaryOperator::CreateSub(oldESP,
CONST_V<32>(b, (width / 8)), "",
b);
auto oldESP = x86::R_READ<32>(b, llvm::X86::ESP);
auto newESP = llvm::BinaryOperator::CreateSub(oldESP,
CONST_V<32>(b, (width / 8)),
"", b);
M_WRITE_0<width>(b, newESP, v);
x86::R_WRITE<32>(b, X86::ESP, newESP);
x86::R_WRITE<32>(b, llvm::X86::ESP, newESP);
} else {
Value *oldRSP = x86_64::R_READ<64>(b, X86::RSP);
Value *newRSP = BinaryOperator::CreateSub(oldRSP,
CONST_V<64>(b, (width / 8)), "",
b);
auto oldRSP = x86_64::R_READ<64>(b, llvm::X86::RSP);
auto newRSP = llvm::BinaryOperator::CreateSub(oldRSP,
CONST_V<64>(b, (width / 8)),
"", b);
M_WRITE_0<width>(b, newRSP, v);
x86_64::R_WRITE<64>(b, X86::RSP, newRSP);
x86_64::R_WRITE<64>(b, llvm::X86::RSP, newRSP);
}
return;
}
template<int width>
static InstTransResult doPushAV(InstPtr ip, BasicBlock *b) {
static InstTransResult doPushAV(NativeInstPtr ip, llvm::BasicBlock *b) {
// Temp := (ESP);
// Push(EAX);
// Push(ECX);
@@ -112,94 +109,95 @@ static InstTransResult doPushAV(InstPtr ip, BasicBlock *b) {
// Push(EBP);
// Push(ESI);
// Push(EDI);
Value *Temp = R_READ<width>(b, X86::ESP);
auto Temp = R_READ<width>(b, llvm::X86::ESP);
doPushV<width>(ip, b, R_READ<width>(b, X86::EAX));
doPushV<width>(ip, b, R_READ<width>(b, X86::ECX));
doPushV<width>(ip, b, R_READ<width>(b, X86::EDX));
doPushV<width>(ip, b, R_READ<width>(b, X86::EBX));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::EAX));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::ECX));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::EDX));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::EBX));
doPushV<width>(ip, b, Temp);
doPushV<width>(ip, b, R_READ<width>(b, X86::EBP));
doPushV<width>(ip, b, R_READ<width>(b, X86::ESI));
doPushV<width>(ip, b, R_READ<width>(b, X86::EDI));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::EBP));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::ESI));
doPushV<width>(ip, b, R_READ<width>(b, llvm::X86::EDI));
return ContinueBlock;
}
namespace x86 {
static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
const MCOperand &frameSize,
const MCOperand &nestingLevel) {
Function *F = b->getParent();
static InstTransResult doEnter(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &frameSize,
const llvm::MCOperand &nestingLevel) {
auto F = b->getParent();
NASSERT(frameSize.isImm());
NASSERT(nestingLevel.isImm());
Value *vFrameSize = CONST_V<32>(b, frameSize.getImm());
Value *vNestingLevel = CONST_V<32>(b, nestingLevel.getImm());
auto vFrameSize = CONST_V<32>(b, frameSize.getImm());
auto vNestingLevel = CONST_V<32>(b, nestingLevel.getImm());
//Push EBP
doPushV<32>(ip, b, x86::R_READ<32>(b, X86::EBP));
doPushV<32>(ip, b, x86::R_READ<32>(b, llvm::X86::EBP));
//set FrameTemp equal to the current value in ESP
Value *frameTemp = x86::R_READ<32>(b, X86::ESP);
auto frameTemp = x86::R_READ<32>(b, llvm::X86::ESP);
//we'll need some blocks for -
// * the loop header
// * the loop body
// * the end of the loop
BasicBlock *loopHeader = BasicBlock::Create(b->getContext(), "loopHeader", F);
BasicBlock *loopBody = BasicBlock::Create(b->getContext(), "loopBody", F);
BasicBlock *loopEnd = BasicBlock::Create(b->getContext(), "loopEnd", F);
BasicBlock *cont = BasicBlock::Create(b->getContext(), "continue", F);
BasicBlock *preLoop = BasicBlock::Create(b->getContext(), "preLoop", F);
BasicBlock *loopSetup = BasicBlock::Create(b->getContext(), "loopSetup", F);
auto &C = b->getContext();
auto loopHeader = llvm::BasicBlock::Create(C, "loopHeader", F);
auto loopBody = llvm::BasicBlock::Create(C, "loopBody", F);
auto loopEnd = llvm::BasicBlock::Create(C, "loopEnd", F);
auto cont = llvm::BasicBlock::Create(C, "continue", F);
auto preLoop = llvm::BasicBlock::Create(C, "preLoop", F);
auto loopSetup = llvm::BasicBlock::Create(C, "loopSetup", F);
//test to see if NestingLevel is 0
Value *isNestZ = new ICmpInst( *b, CmpInst::ICMP_EQ, vNestingLevel,
CONST_V<32>(b, 0));
BranchInst::Create(cont, preLoop, isNestZ, b);
auto isNestZ = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, vNestingLevel,
CONST_V<32>(b, 0));
llvm::BranchInst::Create(cont, preLoop, isNestZ, b);
//test to see if NestingLevel is greater than 1
Value *testRes = new ICmpInst( *preLoop, CmpInst::ICMP_UGT, vNestingLevel,
CONST_V<32>(b, 1));
BranchInst::Create(loopSetup, loopEnd, testRes, preLoop);
auto testRes = new llvm::ICmpInst( *preLoop, llvm::CmpInst::ICMP_UGT,
vNestingLevel, CONST_V<32>(b, 1));
llvm::BranchInst::Create(loopSetup, loopEnd, testRes, preLoop);
//initialize i to 1
Value *i_init = CONST_V<32>(loopSetup, 1);
BranchInst::Create(loopHeader, loopSetup);
auto i_init = CONST_V<32>(loopSetup, 1);
llvm::BranchInst::Create(loopHeader, loopSetup);
//the counter is a PHI instruction
PHINode *i = PHINode::Create(Type::getInt32Ty(F->getContext()), 2, "",
loopHeader);
auto i = llvm::PHINode::Create(llvm::Type::getInt32Ty(F->getContext()), 2, "",
loopHeader);
i->addIncoming(i_init, loopSetup);
//test and see if we should leave
Value *leaveLoop = new ICmpInst( *loopHeader, CmpInst::ICMP_ULT, i,
vNestingLevel);
auto leaveLoop = new llvm::ICmpInst( *loopHeader, llvm::CmpInst::ICMP_ULT, i,
vNestingLevel);
BranchInst::Create(loopBody, loopEnd, leaveLoop, loopHeader);
//subtract 4 from EBP
Value *oEBP = x86::R_READ<32>(loopBody, X86::EBP);
Value *nEBP = BinaryOperator::CreateSub(oEBP, CONST_V<32>(loopBody, 4), "",
loopBody);
x86::R_WRITE<32>(loopBody, X86::EBP, nEBP);
auto oEBP = x86::R_READ<32>(loopBody, llvm::X86::EBP);
auto nEBP = llvm::BinaryOperator::CreateSub(oEBP, CONST_V<32>(loopBody, 4),
"", loopBody);
x86::R_WRITE<32>(loopBody, llvm::X86::EBP, nEBP);
doPushV<32>(ip, loopBody, nEBP);
//add to the counter
Value *i_inc = BinaryOperator::CreateAdd(i, CONST_V<32>(loopBody, 1), "",
loopBody);
auto i_inc = BinaryOperator::CreateAdd(i, CONST_V<32>(loopBody, 1), "",
loopBody);
i->addIncoming(i_inc, loopBody);
BranchInst::Create(loopHeader, loopBody);
llvm::BranchInst::Create(loopHeader, loopBody);
//now at the end of the loop, push the frame temp
doPushV<32>(ip, loopEnd, frameTemp);
BranchInst::Create(cont, loopEnd);
llvm::BranchInst::Create(cont, loopEnd);
//write the frame temp into EBP
x86::R_WRITE<32>(cont, X86::EBP, frameTemp);
x86::R_WRITE<32>(cont, llvm::X86::EBP, frameTemp);
//Subtract the size from ESP
Value *oESP = x86::R_READ<32>(cont, X86::ESP);
Value *nESP = BinaryOperator::CreateSub(oESP, vFrameSize, "", cont);
x86::R_WRITE<32>(cont, X86::ESP, nESP);
auto oESP = x86::R_READ<32>(cont, llvm::X86::ESP);
auto nESP = llvm::BinaryOperator::CreateSub(oESP, vFrameSize, "", cont);
x86::R_WRITE<32>(cont, llvm::X86::ESP, nESP);
//update our caller to use the 'continue' block as the place to continue
//sticking instructions
@@ -210,80 +208,81 @@ static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
}
namespace x86_64 {
static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
const MCOperand &frameSize,
const MCOperand &nestingLevel) {
Function *F = b->getParent();
static InstTransResult doEnter(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &frameSize,
const llvm::MCOperand &nestingLevel) {
auto F = b->getParent();
NASSERT(frameSize.isImm());
NASSERT(nestingLevel.isImm());
Value *vFrameSize = CONST_V<64>(b, frameSize.getImm());
Value *vNestingLevel = CONST_V<64>(b, nestingLevel.getImm());
auto vFrameSize = CONST_V<64>(b, frameSize.getImm());
auto vNestingLevel = CONST_V<64>(b, nestingLevel.getImm());
//Push EBP
doPushV<64>(ip, b, R_READ<64>(b, X86::RBP));
doPushV<64>(ip, b, R_READ<64>(b, llvm::X86::RBP));
//set FrameTemp equal to the current value in ESP
Value *frameTemp = R_READ<64>(b, X86::RSP);
auto frameTemp = R_READ<64>(b, llvm::X86::RSP);
//we'll need some blocks for -
// * the loop header
// * the loop body
// * the end of the loop
BasicBlock *loopHeader = BasicBlock::Create(b->getContext(), "loopHeader", F);
BasicBlock *loopBody = BasicBlock::Create(b->getContext(), "loopBody", F);
BasicBlock *loopEnd = BasicBlock::Create(b->getContext(), "loopEnd", F);
BasicBlock *cont = BasicBlock::Create(b->getContext(), "continue", F);
BasicBlock *preLoop = BasicBlock::Create(b->getContext(), "preLoop", F);
BasicBlock *loopSetup = BasicBlock::Create(b->getContext(), "loopSetup", F);
auto &C = b->getContext();
auto loopHeader = llvm::BasicBlock::Create(C, "loopHeader", F);
auto loopBody = llvm::BasicBlock::Create(C, "loopBody", F);
auto loopEnd = llvm::BasicBlock::Create(C, "loopEnd", F);
auto cont = llvm::BasicBlock::Create(C, "continue", F);
auto preLoop = llvm::BasicBlock::Create(C, "preLoop", F);
auto loopSetup = llvm::BasicBlock::Create(C, "loopSetup", F);
//test to see if NestingLevel is 0
Value *isNestZ = new ICmpInst( *b, CmpInst::ICMP_EQ, vNestingLevel,
CONST_V<64>(b, 0));
auto isNestZ = new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_EQ, vNestingLevel,
CONST_V<64>(b, 0));
BranchInst::Create(cont, preLoop, isNestZ, b);
llvm::BranchInst::Create(cont, preLoop, isNestZ, b);
//test to see if NestingLevel is greater than 1
Value *testRes = new ICmpInst( *preLoop, CmpInst::ICMP_UGT, vNestingLevel,
CONST_V<64>(b, 1));
BranchInst::Create(loopSetup, loopEnd, testRes, preLoop);
auto testRes = new llvm::ICmpInst( *preLoop, llvm::CmpInst::ICMP_UGT,
vNestingLevel, CONST_V<64>(b, 1));
llvm::BranchInst::Create(loopSetup, loopEnd, testRes, preLoop);
//initialize i to 1
Value *i_init = CONST_V<64>(loopSetup, 1);
BranchInst::Create(loopHeader, loopSetup);
auto i_init = CONST_V<64>(loopSetup, 1);
llvm::BranchInst::Create(loopHeader, loopSetup);
//the counter is a PHI instruction
PHINode *i = PHINode::Create(Type::getInt64Ty(F->getContext()), 2, "",
loopHeader);
auto i = llvm::PHINode::Create(llvm::Type::getInt64Ty(F->getContext()), 2, "",
loopHeader);
i->addIncoming(i_init, loopSetup);
//test and see if we should leave
Value *leaveLoop = new ICmpInst( *loopHeader, CmpInst::ICMP_ULT, i,
vNestingLevel);
BranchInst::Create(loopBody, loopEnd, leaveLoop, loopHeader);
auto leaveLoop = new llvm::ICmpInst( *loopHeader, llvm::CmpInst::ICMP_ULT, i,
vNestingLevel);
llvm::BranchInst::Create(loopBody, loopEnd, leaveLoop, loopHeader);
//subtract 8 from EBP
Value *oEBP = R_READ<64>(loopBody, X86::RBP);
Value *nEBP = BinaryOperator::CreateSub(oEBP, CONST_V<64>(loopBody, 8), "",
loopBody);
R_WRITE<64>(loopBody, X86::RBP, nEBP);
auto oEBP = R_READ<64>(loopBody, llvm::X86::RBP);
auto nEBP = llvm::BinaryOperator::CreateSub(oEBP, CONST_V<64>(loopBody, 8),
"", loopBody);
R_WRITE<64>(loopBody, llvm::X86::RBP, nEBP);
doPushV<64>(ip, loopBody, nEBP);
//add to the counter
Value *i_inc = BinaryOperator::CreateAdd(i, CONST_V<64>(loopBody, 1), "",
loopBody);
auto i_inc = llvm::BinaryOperator::CreateAdd(i, CONST_V<64>(loopBody, 1), "",
loopBody);
i->addIncoming(i_inc, loopBody);
BranchInst::Create(loopHeader, loopBody);
llvm::BranchInst::Create(loopHeader, loopBody);
//now at the end of the loop, push the frame temp
doPushV<64>(ip, loopEnd, frameTemp);
BranchInst::Create(cont, loopEnd);
llvm::BranchInst::Create(cont, loopEnd);
//write the frame temp into EBP
R_WRITE<64>(cont, X86::RBP, frameTemp);
R_WRITE<64>(cont, llvm::X86::RBP, frameTemp);
//Subtract the size from ESP
Value *oESP = R_READ<64>(cont, X86::RSP);
Value *nESP = BinaryOperator::CreateSub(oESP, vFrameSize, "", cont);
R_WRITE<64>(cont, X86::RSP, nESP);
auto oESP = R_READ<64>(cont, llvm::X86::RSP);
auto nESP = llvm::BinaryOperator::CreateSub(oESP, vFrameSize, "", cont);
R_WRITE<64>(cont, llvm::X86::RSP, nESP);
//update our caller to use the 'continue' block as the place to continue
//sticking instructions
b = cont;
@@ -292,10 +291,10 @@ static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
}
}
static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
const MCOperand &frameSize,
const MCOperand &nestingLevel) {
llvm::Module *M = b->getParent()->getParent();
static InstTransResult doEnter(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &frameSize,
const llvm::MCOperand &nestingLevel) {
auto M = b->getParent()->getParent();
if (ArchPointerSize(M) == Pointer32) {
return x86::doEnter(ip, b, frameSize, nestingLevel);
} else {
@@ -303,127 +302,128 @@ static InstTransResult doEnter(InstPtr ip, BasicBlock *&b,
}
}
static InstTransResult doLeave(InstPtr ip, BasicBlock *b) {
static InstTransResult doLeave(NativeInstPtr ip, llvm::BasicBlock *b) {
// LEAVE
llvm::Module *M = b->getParent()->getParent();
auto M = b->getParent()->getParent();
if (ArchPointerSize(M) == Pointer32) {
// read EBP
Value *link_pointer = x86::R_READ<32>(b, X86::EBP);
Value *base_pointer = M_READ<32>(ip, b, link_pointer);
R_WRITE<32>(b, X86::EBP, base_pointer);
auto link_pointer = x86::R_READ<32>(b, llvm::X86::EBP);
auto base_pointer = M_READ<32>(ip, b, link_pointer);
R_WRITE<32>(b, llvm::X86::EBP, base_pointer);
//write this to ESP
R_WRITE<32>(
b,
X86::ESP,
llvm::BinaryOperator::Create(Instruction::Add, link_pointer,
llvm::X86::ESP,
llvm::BinaryOperator::Create(llvm::Instruction::Add, link_pointer,
CONST_V<32>(b, 4), "", b));
} else {
Value *link_pointer = x86::R_READ<64>(b, X86::RBP);
Value *base_pointer = M_READ<64>(ip, b, link_pointer);
R_WRITE<64>(b, X86::RBP, base_pointer);
auto link_pointer = x86::R_READ<64>(b, llvm::X86::RBP);
auto base_pointer = M_READ<64>(ip, b, link_pointer);
R_WRITE<64>(b, llvm::X86::RBP, base_pointer);
//write this to ESP
R_WRITE<64>(
b,
X86::RSP,
llvm::BinaryOperator::Create(Instruction::Add, link_pointer,
llvm::X86::RSP,
llvm::BinaryOperator::Create(llvm::Instruction::Add, link_pointer,
CONST_V<64>(b, 8), "", b));
}
return ContinueBlock;
}
static InstTransResult doLeave64(InstPtr ip, BasicBlock *b) {
static InstTransResult doLeave64(NativeInstPtr ip, llvm::BasicBlock *b) {
// LEAVE
// read RBP
Value *vRBP = x86_64::R_READ<64>(b, X86::RBP);
auto vRBP = x86_64::R_READ<64>(b, llvm::X86::RBP);
//write this to RSP
x86_64::R_WRITE<64>(b, X86::RSP, vRBP);
x86_64::R_WRITE<64>(b, llvm::X86::RSP, vRBP);
//do a pop into EBP
//read from memory at the top of the stack
Value *vRSP = x86_64::R_READ<64>(b, X86::RSP);
Value *atTop = M_READ<64>(ip, b, vRSP);
auto vRSP = x86_64::R_READ<64>(b, llvm::X86::RSP);
auto atTop = M_READ<64>(ip, b, vRSP);
//write this value into EBP
x86_64::R_WRITE<64>(b, X86::RBP, atTop);
x86_64::R_WRITE<64>(b, llvm::X86::RBP, atTop);
//add 8 to the stack pointer
Value *updt = BinaryOperator::CreateAdd(vRSP, CONST_V<64>(b, 8), "", b);
x86_64::R_WRITE<64>(b, X86::RSP, updt);
auto updt = llvm::BinaryOperator::CreateAdd(vRSP, CONST_V<64>(b, 8), "", b);
x86_64::R_WRITE<64>(b, llvm::X86::RSP, updt);
return ContinueBlock;
}
template<int width>
static InstTransResult doPopR(InstPtr ip, BasicBlock *&b,
const MCOperand &dst) {
static InstTransResult doPopR(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &dst) {
NASSERT(dst.isReg());
llvm::Module *M = b->getParent()->getParent();
auto M = b->getParent()->getParent();
//read the stack pointer
Value *oldRSP;
llvm::Value *oldRSP = nullptr;
if (ArchPointerSize(M) == Pointer32) {
oldRSP = x86::R_READ<32>(b, X86::ESP);
oldRSP = x86::R_READ<32>(b, llvm::X86::ESP);
} else {
oldRSP = x86_64::R_READ<64>(b, X86::RSP);
oldRSP = x86_64::R_READ<64>(b, llvm::X86::RSP);
}
//read the value from the memory at the stack pointer address
Value *m = M_READ_0<width>(b, oldRSP);
auto m = M_READ_0<width>(b, oldRSP);
//write that value into dst
R_WRITE<width>(b, dst.getReg(), m);
//add to the stack pointer
if (ArchPointerSize(M) == Pointer32) {
Value *newESP = BinaryOperator::CreateAdd(oldRSP,
CONST_V<32>(b, (width / 8)), "",
b);
auto newESP = llvm::BinaryOperator::CreateAdd(oldRSP,
CONST_V<32>(b, (width / 8)),
"", b);
//update the stack pointer register
x86::R_WRITE<32>(b, X86::ESP, newESP);
x86::R_WRITE<32>(b, llvm::X86::ESP, newESP);
} else {
Value *newRSP = BinaryOperator::CreateAdd(oldRSP,
CONST_V<64>(b, (width / 8)), "",
b);
auto newRSP = llvm::BinaryOperator::CreateAdd(oldRSP,
CONST_V<64>(b, (width / 8)),
"", b);
//update the stack pointer register
x86_64::R_WRITE<64>(b, X86::RSP, newRSP);
x86_64::R_WRITE<64>(b, llvm::X86::RSP, newRSP);
}
return ContinueBlock;
}
template<int width>
static InstTransResult doPopD(BasicBlock *b) {
static llvm::Value *doPopV(llvm::BasicBlock *b) {
//read the stack pointer
Value *oldESP = R_READ<width>(b, X86::ESP);
auto xsp = 32 == width ? llvm::X86::ESP : llvm::X86::RSP;
auto oldESP = R_READ<width>(b, xsp);
//read the value from the memory at the stack pointer address,
//and throw it away
Value *m = M_READ_0<width>(b, oldESP);
NASSERT(m != NULL);
auto m = INTERNAL_M_READ(width, 0, b, oldESP);
NASSERT(m != nullptr);
//add to the stack pointer
Value *newESP = BinaryOperator::CreateAdd(oldESP,
CONST_V<width>(b, (width / 8)), "",
b);
auto newESP = llvm::BinaryOperator::CreateAdd(oldESP,
CONST_V<width>(b, (width / 8)),
"", b);
//update the stack pointer register
R_WRITE<width>(b, X86::ESP, newESP);
R_WRITE<width>(b, xsp, newESP);
return ContinueBlock;
return m;
}
template<int width>
static InstTransResult doPopAV(InstPtr ip, BasicBlock *b) {
static InstTransResult doPopAV(NativeInstPtr ip, llvm::BasicBlock *b) {
// EDI := Pop();
// ESI := Pop();
// EBP := Pop();
@@ -433,26 +433,26 @@ static InstTransResult doPopAV(InstPtr ip, BasicBlock *b) {
// ECX := Pop();
// EAX := Pop();
doPopR<width>(ip, b, MCOperand::CreateReg(X86::EDI));
doPopR<width>(ip, b, MCOperand::CreateReg(X86::ESI));
doPopR<width>(ip, b, MCOperand::CreateReg(X86::EBP));
doPopD<width>(b);
doPopR<width>(ip, b, MCOperand::CreateReg(X86::EBX));
doPopR<width>(ip, b, MCOperand::CreateReg(X86::EDX));
doPopR<width>(ip, b, MCOperand::CreateReg(X86::ECX));
doPopR<width>(ip, b, MCOperand::CreateReg(X86::EAX));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::EDI));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::ESI));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::EBP));
doPopV<width>(b);
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::EBX));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::EDX));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::ECX));
doPopR<width>(ip, b, llvm::MCOperand::CreateReg(llvm::X86::EAX));
return ContinueBlock;
}
template<int width>
static InstTransResult doPushR(InstPtr ip, BasicBlock *&b,
const MCOperand &src) {
static InstTransResult doPushR(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &src) {
//PUSH <r>
NASSERT(src.isReg());
//first, read from <r> into a temp
Value *TMP = R_READ<width>(b, src.getReg());
auto TMP = R_READ<width>(b, src.getReg());
doPushV<width>(ip, b, TMP);
@@ -460,26 +460,28 @@ static InstTransResult doPushR(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doPushI(InstPtr ip, BasicBlock *&b,
const MCOperand &src) {
static InstTransResult doPushI(NativeInstPtr ip, llvm::BasicBlock *&b,
const llvm::MCOperand &src) {
// PUSH <imm>
NASSERT(src.isImm());
Value *OrigIMM = CONST_V<width>(b, src.getImm());
auto OrigIMM = CONST_V<width>(b, src.getImm());
// PUSHi32 and PUSHi16 will never be extended
// in IA32
Value *SExt_Val = OrigIMM;
llvm::Value *SExt_Val = OrigIMM;
// PUSHi8 is extended to operand size, which is 32
if (width == 8) {
SExt_Val = new SExtInst(OrigIMM, Type::getInt32Ty(b->getContext()), "", b);
SExt_Val = new llvm::SExtInst(OrigIMM,
llvm::Type::getInt32Ty(b->getContext()), "",
b);
doPushV<32>(ip, b, SExt_Val);
} else {
if (width == 32 && ip->has_ext_call_target()) {
std::string target = ip->get_ext_call_target()->getSymbolName();
Module *M = b->getParent()->getParent();
Function *externFunction = M->getFunction(target);
NASSERT(externFunction != NULL);
auto M = b->getParent()->getParent();
auto externFunction = M->getFunction(target);
NASSERT(externFunction != nullptr);
doPushVT<width>(ip, b, externFunction);
} else {
doPushV<width>(ip, b, SExt_Val);
@@ -490,46 +492,53 @@ static InstTransResult doPushI(InstPtr ip, BasicBlock *&b,
}
template<int width>
static InstTransResult doPopM(InstPtr ip, BasicBlock *&b, Value *addr) {
NASSERT(addr != NULL);
static InstTransResult doPopM(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *addr) {
NASSERT(addr != nullptr);
auto xsp = 32 == width ? llvm::X86::ESP : llvm::X86::RSP;
//read the stack pointer
Value *oldESP = R_READ<32>(b, X86::ESP);
auto oldESP = R_READ<width>(b, xsp);
//read the value from the memory at the stack pointer address
Value *m = M_READ_0<width>(b, oldESP);
auto m = M_READ_0<width>(b, oldESP);
//write that value into dst
M_WRITE<width>(ip, b, addr, m);
//add to the stack pointer
Value *newESP = BinaryOperator::CreateAdd(oldESP, CONST_V<32>(b, (width / 8)),
"", b);
auto newESP = llvm::BinaryOperator::CreateAdd(oldESP,
CONST_V<width>(b, (width / 8)),
"", b);
//update the stack pointer register
R_WRITE<32>(b, X86::ESP, newESP);
R_WRITE<32>(b, xsp, newESP);
return ContinueBlock;
}
template<int width>
static InstTransResult doPushRMM(InstPtr ip, BasicBlock *&b, Value *addr) {
NASSERT(addr != NULL);
static InstTransResult doPushRMM(NativeInstPtr ip, llvm::BasicBlock *&b,
llvm::Value *addr) {
NASSERT(addr != nullptr);
Value *fromMem = M_READ<width>(ip, b, addr);
auto fromMem = M_READ<width>(ip, b, addr);
doPushV<width>(ip, b, fromMem);
return ContinueBlock;
}
static InstTransResult translate_PUSH32rmm(NativeModulePtr natM,
BasicBlock *& block, InstPtr ip,
MCInst &inst) {
static InstTransResult translate_PUSH32rmm(TranslationContext &ctx,
llvm::BasicBlock *&block) {
InstTransResult ret;
Function *F = block->getParent();
auto natM = ctx.natM;
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto F = block->getParent();
if (ip->has_external_ref()) {
Value *addrInt = getValueForExternal<32>(F->getParent(), ip, block);
TASSERT(addrInt != NULL, "Could not get address for external");
auto addrInt = getValueForExternal<32>(F->getParent(), ip, block);
TASSERT(addrInt != nullptr, "Could not get address for external");
doPushV<32>(ip, block, addrInt);
return ContinueBlock;
} else if (ip->has_mem_reference) {
@@ -540,14 +549,17 @@ static InstTransResult translate_PUSH32rmm(NativeModulePtr natM,
return ret;
}
static InstTransResult translate_PUSH64rmm(NativeModulePtr natM,
BasicBlock *& block, InstPtr ip,
MCInst &inst) {
static InstTransResult translate_PUSH64rmm(TranslationContext &ctx,
llvm::BasicBlock *&block) {
InstTransResult ret;
Function *F = block->getParent();
auto natM = ctx.natM;
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto F = block->getParent();
if (ip->has_external_ref()) {
Value *addrInt = getValueForExternal<64>(F->getParent(), ip, block);
TASSERT(addrInt != NULL, "Could not get address for external");
auto addrInt = getValueForExternal<64>(F->getParent(), ip, block);
TASSERT(addrInt != nullptr, "Could not get address for external");
doPushV<64>(ip, block, addrInt);
return ContinueBlock;
} else if (ip->has_mem_reference) {
@@ -558,26 +570,31 @@ static InstTransResult translate_PUSH64rmm(NativeModulePtr natM,
return ret;
}
static InstTransResult translate_PUSHi32(NativeModulePtr natM,
BasicBlock *&block, InstPtr ip,
MCInst &inst) {
static InstTransResult translate_PUSHi32(TranslationContext &ctx,
llvm::BasicBlock *&block) {
InstTransResult ret;
Function *F = block->getParent();
auto natM = ctx.natM;
auto ip = ctx.natI;
auto &inst = ip->get_inst();
auto F = block->getParent();
if (ip->has_code_ref()) {
Value *callback_fn = ArchAddCallbackDriver(
block->getParent()->getParent(), ip->get_reference(Inst::IMMRef));
Value *addrInt = new PtrToIntInst(
callback_fn, llvm::Type::getInt32Ty(block->getContext()), "", block);
auto callback_fn = ArchAddCallbackDriver(
block->getParent()->getParent(), ip->get_reference(NativeInst::IMMRef));
auto addrInt = new PtrToIntInst(callback_fn,
llvm::Type::getInt32Ty(block->getContext()),
"", block);
doPushV<32>(ip, block, addrInt);
ret = ContinueBlock;
} else if (ip->has_imm_reference) {
Module *M = F->getParent();
Value *ref = IMM_AS_DATA_REF(block, natM, ip);
auto M = F->getParent();
auto ref = IMM_AS_DATA_REF(block, natM, ip);
// this may fail catastrophically, but we can only push those 32-bits
// or we break the stack
if (Pointer64 == ArchPointerSize(M)) {
ref = new llvm::TruncInst(ref, llvm::Type::getInt32Ty(block->getContext()), "", block);
ref = new llvm::TruncInst(ref,
llvm::Type::getInt32Ty(block->getContext()), "",
block);
}
doPushV<32>(ip, block, ref);
@@ -589,29 +606,28 @@ static InstTransResult translate_PUSHi32(NativeModulePtr natM,
}
#define EMIT_SHL_OR(destval, inval, shiftcount) do {\
Value *tmp = BinaryOperator::CreateShl(inval, CONST_V<width>(b, shiftcount), "", b); \
destval = BinaryOperator::CreateOr(destval, tmp, "", b); \
auto tmp = llvm::BinaryOperator::CreateShl(inval, CONST_V<width>(b, shiftcount), "", b); \
destval = llvm::BinaryOperator::CreateOr(destval, tmp, "", b); \
} while (0)
#define EMIT_SHR_AND(destval, inval, shiftcount) do {\
Value *tmp = BinaryOperator::CreateLShr(inval, CONST_V<width>(b, shiftcount), "", b); \
destval = BinaryOperator::CreateAnd(destval, tmp, "", b); \
auto tmp = llvm::BinaryOperator::CreateLShr(inval, CONST_V<width>(b, shiftcount), "", b); \
destval = llvm::BinaryOperator::CreateAnd(destval, tmp, "", b); \
} while (0)
template<int width>
static Value * checkIfBitSet(Value *field, int bit, BasicBlock *b) {
static llvm::Value *checkIfBitSet(llvm::Value *field, int bit,
llvm::BasicBlock *b) {
Value *tmp = BinaryOperator::CreateAnd(field, CONST_V<width>(b, 1 << bit), "",
b);
Value *res = new ICmpInst( *b, CmpInst::ICMP_NE, tmp, CONST_V<width>(b, 0));
return res;
auto tmp = llvm::BinaryOperator::CreateAnd(field, CONST_V<width>(b, 1 << bit),
"", b);
return new llvm::ICmpInst( *b, llvm::CmpInst::ICMP_NE, tmp,
CONST_V<width>(b, 0));
}
template<int width>
static InstTransResult doPopF(InstPtr ip, BasicBlock *b) {
Value *newFlags = R_READ<width>(b, X86::ESP);
doPopD<width>(b);
static InstTransResult doPopF(NativeInstPtr ip, llvm::BasicBlock *b) {
auto newFlags = doPopV<width>(b);
// bit 0: CF
F_WRITE(b, CF, checkIfBitSet<width>(newFlags, 0, b));
@@ -638,24 +654,24 @@ static InstTransResult doPopF(InstPtr ip, BasicBlock *b) {
}
template<int width>
static InstTransResult doPushF(InstPtr ip, BasicBlock *b) {
static InstTransResult doPushF(NativeInstPtr ip, llvm::BasicBlock *b) {
// put eflags into one value.
//
Type *toT = Type::getIntNTy(b->getContext(), width);
Type *toT = llvm::Type::getIntNTy(b->getContext(), width);
Value *cf = new ZExtInst(F_READ(b, CF), toT, "", b);
Value *pf = new ZExtInst(F_READ(b, PF), toT, "", b);
Value *af = new ZExtInst(F_READ(b, AF), toT, "", b);
Value *zf = new ZExtInst(F_READ(b, ZF), toT, "", b);
Value *sf = new ZExtInst(F_READ(b, SF), toT, "", b);
Value *df = new ZExtInst(F_READ(b, DF), toT, "", b);
Value *of = new ZExtInst(F_READ(b, OF), toT, "", b);
Value *cf = new llvm::ZExtInst(F_READ(b, CF), toT, "", b);
Value *pf = new llvm::ZExtInst(F_READ(b, PF), toT, "", b);
Value *af = new llvm::ZExtInst(F_READ(b, AF), toT, "", b);
Value *zf = new llvm::ZExtInst(F_READ(b, ZF), toT, "", b);
Value *sf = new llvm::ZExtInst(F_READ(b, SF), toT, "", b);
Value *df = new llvm::ZExtInst(F_READ(b, DF), toT, "", b);
Value *of = new llvm::ZExtInst(F_READ(b, OF), toT, "", b);
Value *eflags_base = CONST_V<width>(b, 0x202);
// bit 0: CF
Value *cur_flags = BinaryOperator::CreateOr(eflags_base, cf, "", b);
Value *cur_flags = llvm::BinaryOperator::CreateOr(eflags_base, cf, "", b);
// bit 1: 1 (reserved)
// bit 2: PF
EMIT_SHL_OR(cur_flags, pf, 2);
@@ -708,32 +724,35 @@ GENERIC_TRANSLATION_REF(PUSHi16, doPushI<16>(ip, block, OP(0)),
doPushV<16>(ip, block, MEM_REFERENCE(0) ))
GENERIC_TRANSLATION_REF(POP32rmm, doPopM<32>(ip, block, ADDR_NOREF(0)),
doPopM<32>(ip, block, MEM_REFERENCE(0)));
GENERIC_TRANSLATION_REF(POP64rmm, doPopM<64>(ip, block, ADDR_NOREF(0)),
doPopM<32>(ip, block, MEM_REFERENCE(0)));
void Stack_populateDispatchMap(DispatchMap &m) {
m[X86::ENTER] = translate_ENTER;
m[X86::LEAVE] = translate_LEAVE;
m[X86::LEAVE64] = translate_LEAVE64;
m[X86::POP16r] = translate_POP16r;
m[X86::POP32r] = translate_POP32r;
m[X86::PUSH16r] = translate_PUSH16r;
m[X86::PUSH32r] = translate_PUSH32r;
m[X86::PUSH32i8] = translate_PUSHi8;
m[X86::PUSHi16] = translate_PUSHi16;
m[X86::PUSHi32] = translate_PUSHi32;
m[X86::PUSH32rmm] = translate_PUSH32rmm;
m[X86::POPA32] = translate_POPA32;
m[X86::PUSHA32] = translate_PUSHA32;
m[X86::PUSHF32] = translate_PUSHF32;
m[X86::PUSHF64] = translate_PUSHF64;
m[X86::POP32rmm] = translate_POP32rmm;
m[llvm::X86::ENTER] = translate_ENTER;
m[llvm::X86::LEAVE] = translate_LEAVE;
m[llvm::X86::LEAVE64] = translate_LEAVE64;
m[llvm::X86::POP16r] = translate_POP16r;
m[llvm::X86::POP32r] = translate_POP32r;
m[llvm::X86::PUSH16r] = translate_PUSH16r;
m[llvm::X86::PUSH32r] = translate_PUSH32r;
m[llvm::X86::PUSH32i8] = translate_PUSHi8;
m[llvm::X86::PUSHi16] = translate_PUSHi16;
m[llvm::X86::PUSHi32] = translate_PUSHi32;
m[llvm::X86::PUSH32rmm] = translate_PUSH32rmm;
m[llvm::X86::POPA32] = translate_POPA32;
m[llvm::X86::PUSHA32] = translate_PUSHA32;
m[llvm::X86::PUSHF32] = translate_PUSHF32;
m[llvm::X86::PUSHF64] = translate_PUSHF64;
m[llvm::X86::POP32rmm] = translate_POP32rmm;
m[X86::PUSH64r] = translate_PUSH64r;
m[X86::PUSH64rmr] = translate_PUSH64r; // TODO(pag): Is this right??
m[X86::PUSH64rmm] = translate_PUSH64rmm;
m[X86::PUSH64i8] = translate_PUSHi8;
m[X86::PUSH64i32] = translate_PUSHi32;
m[llvm::X86::PUSH64r] = translate_PUSH64r;
m[llvm::X86::PUSH64rmr] = translate_PUSH64r; // TODO(pag): Is this right??
m[llvm::X86::PUSH64rmm] = translate_PUSH64rmm;
m[llvm::X86::PUSH64i8] = translate_PUSHi8;
m[llvm::X86::PUSH64i32] = translate_PUSHi32;
m[X86::POP64r] = translate_POP64r;
m[X86::POPF64] = translate_POPF64;
m[X86::POPF32] = translate_POPF32;
m[llvm::X86::POP64r] = translate_POP64r;
m[llvm::X86::POP64rmm] = translate_POP64rmm;
m[llvm::X86::POPF64] = translate_POPF64;
m[llvm::X86::POPF32] = translate_POPF32;
}
+25 -21
View File
@@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "x86Instrs_String.h"
template<int width, int regWidth>
static BasicBlock *doCmpsV(BasicBlock *pred) {
static llvm::BasicBlock *doCmpsV(llvm::BasicBlock *pred) {
auto lhsRegVal = R_READ<regWidth>(pred, llvm::X86::RSI);
auto lhsFromMem = M_READ_0<width>(pred, lhsRegVal);
@@ -518,13 +518,13 @@ static InstTransResult doRepMovs(llvm::BasicBlock *&b) {
}
template<int width>
static InstTransResult doMovs(llvm::BasicBlock *&b, InstPtr ip) {
static InstTransResult doMovs(llvm::BasicBlock *&b, NativeInstPtr ip) {
//we will just kind of paste a new block into the end
//here so that we have less duplicated logic
llvm::Module *M = b->getParent()->getParent();
int bitWidth = ArchPointerSize(M);
Inst::Prefix pfx = ip->get_prefix();
if (pfx == Inst::RepPrefix) {
NativeInst::Prefix pfx = ip->get_prefix();
if (pfx == NativeInst::RepPrefix) {
if (bitWidth == Pointer32) {
doRepMovs<width, x86::REG_SIZE>(b);
} else {
@@ -547,18 +547,18 @@ static InstTransResult doRepStos(llvm::BasicBlock *&b) {
}
template <int width>
static InstTransResult doStos(llvm::BasicBlock *&b, InstPtr ip) {
static InstTransResult doStos(llvm::BasicBlock *&b, NativeInstPtr ip) {
auto M = b->getParent()->getParent();
auto bitWidth = ArchPointerSize(M);
Inst::Prefix pfx = ip->get_prefix();
NativeInst::Prefix pfx = ip->get_prefix();
if (bitWidth == Pointer32) {
if (pfx == Inst::RepPrefix) {
if (pfx == NativeInst::RepPrefix) {
doRepStos<width, x86::REG_SIZE>(b);
} else {
b = doStosV<width, x86::REG_SIZE>(b);
}
} else {
if (pfx == Inst::RepPrefix) {
if (pfx == NativeInst::RepPrefix) {
doRepStos<width, x86_64::REG_SIZE>(b);
} else {
b = doStosV<width, x86_64::REG_SIZE>(b);
@@ -592,18 +592,20 @@ GENERIC_TRANSLATION(REP_STOSQ_64, (doRepStos<64, 64>(block)))
#define SCAS_TRANSLATION(NAME, WIDTH) \
static InstTransResult translate_ ## NAME ( \
NativeModulePtr natM, llvm::BasicBlock *& block, \
InstPtr ip, llvm::MCInst &inst) {\
TranslationContext &ctx, llvm::BasicBlock *&block) {\
auto natM = ctx.natM; \
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
InstTransResult ret = TranslateError;\
Inst::Prefix pfx = ip->get_prefix();\
switch(pfx) { \
case Inst::NoPrefix: \
NativeInst::Prefix pfx = ip->get_prefix();\
switch (pfx) { \
case NativeInst::NoPrefix: \
throw TErr(__LINE__, __FILE__, "NIY"); \
break; \
case Inst::RepPrefix: \
case NativeInst::RepPrefix: \
throw TErr(__LINE__, __FILE__, "NIY"); \
break; \
case Inst::RepNePrefix: \
case NativeInst::RepNePrefix: \
ret = doRepNeScas<WIDTH>(block); \
break; \
default: \
@@ -614,19 +616,21 @@ GENERIC_TRANSLATION(REP_STOSQ_64, (doRepStos<64, 64>(block)))
#define CMPS_TRANSLATION(NAME, WIDTH) \
static InstTransResult translate_ ## NAME ( \
NativeModulePtr natM, llvm::BasicBlock *&block, \
InstPtr ip, llvm::MCInst &inst) {\
TranslationContext &ctx, llvm::BasicBlock *&block) {\
auto natM = ctx.natM; \
auto ip = ctx.natI; \
auto &inst = ip->get_inst(); \
InstTransResult ret;\
Inst::Prefix pfx = ip->get_prefix();\
NativeInst::Prefix pfx = ip->get_prefix();\
switch(pfx) { \
case Inst::NoPrefix: \
case NativeInst::NoPrefix: \
block = doCmps<WIDTH>(block); \
ret = ContinueBlock; \
break; \
case Inst::RepPrefix: \
case NativeInst::RepPrefix: \
ret = doRepeCmps<WIDTH>(block); \
break; \
case Inst::RepNePrefix: \
case NativeInst::RepNePrefix: \
ret = doRepNeCmps<WIDTH>(block); \
break; \
default: \
+27 -27
View File
@@ -58,12 +58,12 @@ Value *doAndVV32(BasicBlock *&b, Value *o1, Value *o2) {
}
template<int width>
static Value * doAndVV(InstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
static Value * doAndVV(NativeInstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
return doAndVV<width>(b, o1, o2);
}
template<int width>
static InstTransResult doAndMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doAndMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -79,7 +79,7 @@ static InstTransResult doAndMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doAndMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doAndMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -94,7 +94,7 @@ static InstTransResult doAndMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doAndMR(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doAndMR(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &src) {
TASSERT(addr != NULL, "");
TASSERT(src.isReg(), "");
@@ -110,7 +110,7 @@ static InstTransResult doAndMR(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doAndRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doAndRI(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -125,7 +125,7 @@ static InstTransResult doAndRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doAndRV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doAndRV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(o2.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -138,7 +138,7 @@ static InstTransResult doAndRV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doAndRM(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doAndRM(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &o1, const MCOperand &dst) {
TASSERT(dst.isReg(), "");
TASSERT(addr != NULL, "");
@@ -153,7 +153,7 @@ static InstTransResult doAndRM(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doAndRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doAndRR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -168,7 +168,7 @@ static InstTransResult doAndRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static Value * doNotV(InstPtr ip, BasicBlock *&b, Value *v) {
static Value * doNotV(NativeInstPtr ip, BasicBlock *&b, Value *v) {
TASSERT(v != NULL, "");
Value *highest = NULL;
@@ -200,7 +200,7 @@ static Value * doNotV(InstPtr ip, BasicBlock *&b, Value *v) {
}
template<int width>
static InstTransResult doNotM(InstPtr ip, BasicBlock *&b, Value *a) {
static InstTransResult doNotM(NativeInstPtr ip, BasicBlock *&b, Value *a) {
TASSERT(a != NULL, "");
Value *m = M_READ<width>(ip, b, a);
@@ -213,7 +213,7 @@ static InstTransResult doNotM(InstPtr ip, BasicBlock *&b, Value *a) {
}
template<int width>
static InstTransResult doNotR(InstPtr ip, BasicBlock *&b, const MCOperand &o) {
static InstTransResult doNotR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &o) {
TASSERT(o.isReg(), "");
Value *r = R_READ<width>(b, o.getReg());
@@ -226,7 +226,7 @@ static InstTransResult doNotR(InstPtr ip, BasicBlock *&b, const MCOperand &o) {
}
template<int width>
static Value * doOrVV(InstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
static Value * doOrVV(NativeInstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
// Do the operation.
Value *result = BinaryOperator::Create(Instruction::Or, o1, o2, "", b);
@@ -242,7 +242,7 @@ static Value * doOrVV(InstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
}
template<int width>
static InstTransResult doOrMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doOrMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -258,7 +258,7 @@ static InstTransResult doOrMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doOrMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doOrMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -273,7 +273,7 @@ static InstTransResult doOrMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doOrMR(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doOrMR(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &src) {
TASSERT(addr != NULL, "");
TASSERT(src.isReg(), "");
@@ -289,7 +289,7 @@ static InstTransResult doOrMR(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doOrRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doOrRI(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -304,7 +304,7 @@ static InstTransResult doOrRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doOrRV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doOrRV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(o2.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -317,7 +317,7 @@ static InstTransResult doOrRV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doOrRM(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doOrRM(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &o1, const MCOperand &dst) {
TASSERT(addr != NULL, "");
TASSERT(o1.isReg(), "");
@@ -332,7 +332,7 @@ static InstTransResult doOrRM(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doOrRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doOrRR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -347,7 +347,7 @@ static InstTransResult doOrRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static Value * doXorVV(InstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
static Value * doXorVV(NativeInstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
Value *xoredVal = BinaryOperator::Create(Instruction::Xor, o1, o2, "", b);
// Clear CF and OF.
@@ -366,7 +366,7 @@ static Value * doXorVV(InstPtr ip, BasicBlock *&b, Value *o1, Value *o2) {
}
template<int width>
static InstTransResult doXorMI(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doXorMI(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &imm) {
TASSERT(addr != NULL, "");
TASSERT(imm.isImm(), "");
@@ -381,7 +381,7 @@ static InstTransResult doXorMI(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doXorMV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doXorMV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
Value *rhs) {
TASSERT(addr != NULL, "");
TASSERT(rhs != NULL, "");
@@ -395,7 +395,7 @@ static InstTransResult doXorMV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doXorMR(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doXorMR(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &reg) {
TASSERT(addr != NULL, "");
TASSERT(reg.isReg(), "");
@@ -409,7 +409,7 @@ static InstTransResult doXorMR(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doXorRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doXorRI(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
@@ -424,7 +424,7 @@ static InstTransResult doXorRI(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doXorRV(InstPtr ip, BasicBlock *&b, Value *addr,
static InstTransResult doXorRV(NativeInstPtr ip, BasicBlock *&b, Value *addr,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(o1.isReg(), "");
TASSERT(o2.isReg(), "");
@@ -437,7 +437,7 @@ static InstTransResult doXorRV(InstPtr ip, BasicBlock *&b, Value *addr,
}
template<int width>
static InstTransResult doXorRM(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doXorRM(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &src1, Value *mem) {
TASSERT(mem != NULL, "");
TASSERT(dst.isReg(), "");
@@ -452,7 +452,7 @@ static InstTransResult doXorRM(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
}
template<int width>
static InstTransResult doXorRR(InstPtr ip, BasicBlock *&b, const MCOperand &dst,
static InstTransResult doXorRR(NativeInstPtr ip, BasicBlock *&b, const MCOperand &dst,
const MCOperand &o1, const MCOperand &o2) {
TASSERT(dst.isReg(), "");
TASSERT(o1.isReg(), "");
File diff suppressed because it is too large Load Diff
-52
View File
@@ -1,52 +0,0 @@
//===-- .h ---------------------------------------------------===//
//
// THE PROJECT
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#ifndef _BMO_H
#define _BMO_H
#include "llvm/Support/MemoryBuffer.h"
#include <boost/cstdint.hpp>
class BaseBufferMemoryObject : public llvm::MemoryObject {
private:
std::vector<uint8_t> Bytes;
uint64_t Base;
public:
BaseBufferMemoryObject( std::vector<uint8_t> bytes,
uint64_t baseAddr) :
Bytes(bytes), Base(baseAddr) {
return;
}
uint64_t getBase() const { return this->Base; }
uint64_t getExtent() const { return this->Bytes.size()+this->Base; }
int readByte(uint64_t addr, uint8_t *byte) const {
if (addr >= this->getBase() )
{
if(addr < this->getExtent())
{
*byte = this->Bytes[addr-this->Base];
return 0;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
};
#endif
+4 -5
View File
@@ -4,17 +4,16 @@
#include <exception>
#include <iostream>
#include <sstream>
#include <boost/exception/to_string.hpp>
class LErr : public std::exception {
private:
std::string message;
public:
LErr(unsigned int line, const char *file, std::string message) {
this->message = "Generic error: Line: " +
boost::to_string<unsigned int>(line) + "\n" +
"File: " + std::string(file) + "\n" +
message;
std::stringstream ss;
ss << "Generic error: Line: " << line << "\n"
<< "File: " << file << "\n" << message;
this->message = ss.str();
}
virtual ~LErr(void) throw() { }
+99 -104
View File
@@ -1,31 +1,32 @@
/*
Copyright (c) 2014, Trail of Bits
All rights reserved.
Copyright (c) 2014, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of Trail of Bits nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "peToCFG.h"
#include "X86.h"
#include <LExcn.h>
@@ -33,113 +34,107 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "llvm/Support/Debug.h"
using namespace std;
using namespace boost;
using namespace llvm;
LLVMByteDecoder::LLVMByteDecoder(const std::string &triple,
const llvm::Target *target_)
: STI(target_->createMCSubtargetInfo(triple, "", "")),
MRI(target_->createMCRegInfo(triple)),
AsmInfo(target_->createMCAsmInfo(*MRI, triple)),
Ctx(new llvm::MCContext(AsmInfo, MRI, nullptr)),
DisAsm(target_->createMCDisassembler( *this->STI, *Ctx)),
TT(triple),
target(target_) {}
InstPtr LLVMByteDecoder::getInstFromBuff(VA addr, llvm::MemoryObject *bmo) {
InstPtr inst;
llvm::MCInst mcInst;
::uint64_t insLen;
VA nextVA = addr;
::uint32_t arch_type;
NativeInstPtr LLVMByteDecoder::getInstFromBuff(VA addr, llvm::MemoryObject *bmo) {
NativeInstPtr inst;
llvm::MCInst mcInst;
uint64_t insLen;
VA nextVA = addr;
uint32_t arch_type;
uint8_t prefixes[0x100] = {0};
llvm::MCDisassembler::DecodeStatus s;
llvm::MCDisassembler::DecodeStatus s;
bool have_prefix = true;
size_t bmo_size = bmo->getExtent() - bmo->getBase();
while(have_prefix)
{
insLen = 0;
s = DisAsm->getInstruction( mcInst,
insLen,
*bmo,
((::uint64_t)nextVA),
llvm::nulls(),
llvm::nulls());
while (have_prefix) {
insLen = 0;
s = DisAsm->getInstruction(mcInst, insLen, *bmo, ((uint64_t) nextVA),
llvm::nulls(), llvm::nulls());
if(s == llvm::MCDisassembler::Success && bmo_size > 1)
{
switch(mcInst.getOpcode()) {
case llvm::X86::REP_PREFIX:
prefixes[0xF3] = 1;
break;
case llvm::X86::REPNE_PREFIX:
prefixes[0xF2] = 1;
break;
case llvm::X86::LOCK_PREFIX:
prefixes[0xF0] = 1;
break;
default:
have_prefix = false;
}
} else {
if (s == llvm::MCDisassembler::Success && bmo_size > 1) {
switch (mcInst.getOpcode()) {
case llvm::X86::REP_PREFIX:
prefixes[0xF3] = 1;
break;
case llvm::X86::REPNE_PREFIX:
prefixes[0xF2] = 1;
break;
case llvm::X86::LOCK_PREFIX:
prefixes[0xF0] = 1;
break;
default:
have_prefix = false;
break;
}
if(have_prefix) {
nextVA += 1;
} else {
for(int i = 0; i < 0x100; i++) {
if(prefixes[i] == 1) {
mcInst.prefixPresent[i] = 1;
}
}
break;
// set prefixes
} else {
have_prefix = false;
break;
}
if (have_prefix) {
nextVA += 1;
} else {
for (int i = 0; i < 0x100; i++) {
if (prefixes[i] == 1) {
mcInst.prefixPresent[i] = 1;
}
}
break;
// set prefixes
}
}
Inst::Prefix pfx = Inst::NoPrefix;
if(s == llvm::MCDisassembler::Success) {
NativeInst::Prefix pfx = NativeInst::NoPrefix;
if (s == llvm::MCDisassembler::Success) {
if( mcInst.getOpcode() == llvm::X86::MOVSL && mcInst.hasPrefix(0xF3) ) {
mcInst.setOpcode(llvm::X86::REP_MOVSD_32);
} else if( mcInst.hasPrefix(0xF2) ) {
pfx = Inst::RepNePrefix;
} else if( mcInst.hasPrefix(0xF3) ) {
pfx = Inst::RepPrefix;
} else if ( mcInst.hasPrefix(0x64) ) {
pfx = Inst::FSPrefix;
} else if ( mcInst.hasPrefix(0x64) ) {
pfx = Inst::GSPrefix;
if (mcInst.getOpcode() == llvm::X86::MOVSL && mcInst.hasPrefix(0xF3)) {
mcInst.setOpcode(llvm::X86::REP_MOVSD_32);
} else if (mcInst.hasPrefix(0xF2)) {
pfx = NativeInst::RepNePrefix;
} else if (mcInst.hasPrefix(0xF3)) {
pfx = NativeInst::RepPrefix;
} else if (mcInst.hasPrefix(0x64)) {
pfx = NativeInst::FSPrefix;
} else if (mcInst.hasPrefix(0x64)) {
pfx = NativeInst::GSPrefix;
}
string outS;
llvm::raw_string_ostream osOut(outS);
MCOperand oper;
MCOperand oper;
this->IP->printInst(&mcInst, osOut, "");
vector<uint8_t> bytes;
//store the bytes from the MO in the inst
for(unsigned int i = 0; i < insLen; i++) {
std::vector<uint8_t> bytes;
//store the bytes from the MO in the inst
for (unsigned int i = 0; i < insLen; i++) {
uint8_t b;
int k = bmo->readByte(addr+i, &b);
int k = bmo->readByte(addr + i, &b);
LASSERT(k == 0, "Failed to read data when decoder could");
bytes.push_back(b);
}
inst = InstPtr(new Inst( addr,
insLen,
mcInst,
osOut.str(),
pfx,
bytes));
}
inst = NativeInstPtr(new NativeInst(addr, insLen, mcInst, pfx, bytes));
for (unsigned i = 0; i < mcInst.getNumOperands(); ++i) {
const MCOperand &Op = mcInst.getOperand(i);
for (auto i = 0U; i < mcInst.getNumOperands(); ++i) {
const MCOperand &Op = mcInst.getOperand(i);
if (Op.isReg() && Op.getReg() == X86::RIP)
inst->set_rip_relative(i);
if (Op.isReg() && Op.getReg() == X86::RIP) {
inst->set_rip_relative(i);
}
}
//ask if this is a jmp, and figure out what the true / false follows are
switch(mcInst.getOpcode()) {
switch (mcInst.getOpcode()) {
case X86::JMP32m:
case X86::JMP32r:
case X86::JMP64m:
@@ -158,7 +153,7 @@ InstPtr LLVMByteDecoder::getInstFromBuff(VA addr, llvm::MemoryObject *bmo) {
case X86::JMP_4:
case X86::JMP_1:
oper = mcInst.getOperand(0);
if(oper.isImm()) {
if (oper.isImm()) {
nextVA += oper.getImm() + insLen;
inst->set_tr(nextVA);
} else {
@@ -211,8 +206,8 @@ InstPtr LLVMByteDecoder::getInstFromBuff(VA addr, llvm::MemoryObject *bmo) {
}
} else {
string s = to_string<VA>(addr, hex);
throw LErr(__LINE__, __FILE__, "Failed to decode address 0x"+s);
string s = to_string<VA>(addr, hex);
throw LErr(__LINE__, __FILE__, "Failed to decode address 0x" + s);
}
return inst;
+34 -140
View File
@@ -1,31 +1,31 @@
/*
Copyright (c) 2013, Trail of Bits
All rights reserved.
Copyright (c) 2013, Trail of Bits
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _INST_FE_H
#define _INST_FE_H
@@ -39,125 +39,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "X86TargetMachine.h"
class LLVMByteDecoder {
private:
const llvm::MCSubtargetInfo *STI;
const llvm::MCAsmInfo *AsmInfo;
llvm::MCInstPrinter *IP;
const llvm::MCDisassembler *DisAsm;
llvm::Triple *TT;
const llvm::Target *target;
private:
const llvm::MCSubtargetInfo * const STI;
llvm::MCRegisterInfo * const MRI;
const llvm::MCAsmInfo * const AsmInfo;
llvm::MCContext * const Ctx;
const llvm::MCDisassembler * const DisAsm;
const llvm::Triple TT;
const llvm::Target * const target;
public:
LLVMByteDecoder(void)
{
this->target = NULL;
llvm::MCRegisterInfo *MRI = NULL;
const llvm::MCInstrInfo *MCII = NULL;
public:
LLVMByteDecoder(const std::string &triple,
const llvm::Target *target_);
for(llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(),
e = llvm::TargetRegistry::end();
it != e;
++it)
{
const llvm::Target &t = *it;
if(std::string(t.getName()) == "x86") {
target= &t;
break;
}
}
LASSERT( target != NULL, "target != NULL" );
TT = new llvm::Triple();
TT->setArch(llvm::Triple::x86);
TT->setVendor(llvm::Triple::UnknownVendor);
TT->setOS(llvm::Triple::UnknownOS);
this->STI = target->createMCSubtargetInfo( "i386-unknown-unknown", "", "");
MRI = target->createMCRegInfo("i386-unknown-unknown");
this->AsmInfo = target->createMCAsmInfo(*MRI, "i386-unknown-unknown");
LASSERT( this->STI, "this->STI" );
LASSERT( this->AsmInfo, "this->AsmInfo" );
//get an inst printer
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
MCII = target->createMCInstrInfo();
this->IP = target->createMCInstPrinter(AsmPrinterVariant,
*AsmInfo,
*MCII,
*MRI,
*STI);
LASSERT( this->IP, "this->IP" );
llvm::MCContext *Ctx = new llvm::MCContext(AsmInfo, MRI, nullptr);
this->DisAsm = target->createMCDisassembler(*this->STI, *Ctx );
LASSERT( this->DisAsm, "this->DisAsm" );
return;
}
LLVMByteDecoder(std::string T)
{
this->target = NULL;
llvm::MCRegisterInfo *MRI = NULL;
const llvm::MCInstrInfo *MCII = NULL;
TT = new llvm::Triple();
for(llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(),
e = llvm::TargetRegistry::end();
it != e;
++it)
{
const llvm::Target &t = *it;
if(!T.compare(t.getName())) {
target= &t;
break;
}
}
LASSERT( target != NULL, "target != NULL" );
TT->setVendor(llvm::Triple::UnknownVendor);
TT->setOS(llvm::Triple::UnknownOS);
if(0 == T.compare("x86-64")) {
TT->setArch(llvm::Triple::x86_64);
} else {
TT->setArch(llvm::Triple::x86);
}
std::cout << " TT " <<target->getName() <<" : " << TT->str() << " \n";
this->STI = target->createMCSubtargetInfo( TT->getTriple(), "", "");
MRI = target->createMCRegInfo(TT->getTriple());
this->AsmInfo = target->createMCAsmInfo(*MRI, TT->getTriple());
std::cout.flush();
LASSERT( this->STI, "this->STI" );
LASSERT( this->AsmInfo, "this->AsmInfo" );
//get an inst printer
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
MCII = target->createMCInstrInfo();
this->IP = target->createMCInstPrinter(AsmPrinterVariant,
*AsmInfo,
*MCII,
*MRI,
*STI);
LASSERT( this->IP, "this->IP" );
llvm::MCContext *Ctx = new llvm::MCContext(AsmInfo, MRI, nullptr);
this->DisAsm = target->createMCDisassembler(*this->STI, *Ctx );
LASSERT( this->DisAsm, "this->DisAsm" );
return;
}
llvm::MCInstPrinter *getPrinter(void) { return this->IP; }
InstPtr getInstFromBuff(VA, llvm::MemoryObject *);
NativeInstPtr getInstFromBuff(VA, llvm::MemoryObject *);
};
#endif
File diff suppressed because it is too large Load Diff
+181 -616
View File
@@ -54,31 +54,19 @@
#include <stack>
#include <set>
#include <map>
#include <memory>
#include <list>
#include <unordered_map>
#include <stdio.h>
#include <assert.h>
#include <cstdio>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/program_options/config.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/adjacency_matrix.hpp>
typedef boost::adjacency_matrix<boost::directedS> CFG;
typedef uint64_t FuncID;
typedef uint64_t VA;
class Inst;
typedef boost::shared_ptr<Inst> InstPtr;
class NativeInst;
typedef NativeInst *NativeInstPtr;
#include <BaseBMO.h>
@@ -90,36 +78,29 @@ typedef boost::shared_ptr<Inst> InstPtr;
class MCSJumpTable;
class JumpIndexTable;
class MCSOffsetTable;
typedef boost::shared_ptr<ExternalCodeRef> ExternalCodeRefPtr;
typedef boost::shared_ptr<ExternalDataRef> ExternalDataRefPtr;
typedef boost::shared_ptr<MCSJumpTable> MCSJumpTablePtr;
typedef boost::shared_ptr<JumpIndexTable> JumpIndexTablePtr;
typedef boost::shared_ptr<MCSOffsetTable> MCSOffsetTablePtr;
typedef ExternalCodeRef *ExternalCodeRefPtr;
typedef ExternalDataRef *ExternalDataRefPtr;
typedef MCSJumpTable *MCSJumpTablePtr;
typedef JumpIndexTable *JumpIndexTablePtr;
typedef MCSOffsetTable *MCSOffsetTablePtr;
class BufferMemoryObject : public llvm::MemoryObject {
private:
std::vector<uint8_t> Bytes;
const std::vector<uint8_t> bytes;
const uint64_t base_addr;
public:
BufferMemoryObject(const uint8_t *bytes, uint64_t length) {
for (unsigned int i = 0; i < length; i++) {
this->Bytes.push_back(bytes[i]);
}
return;
}
BufferMemoryObject(const uint8_t *bytes_, uint64_t length);
BufferMemoryObject(const std::vector<uint8_t> &bytes_,
uint64_t base_addr_);
BufferMemoryObject(const std::vector<uint8_t> &bytes_);
uint64_t getBase() const {
return 0;
}
uint64_t getExtent() const {
return this->Bytes.size();
}
virtual ~BufferMemoryObject(void);
int readByte(uint64_t addr, uint8_t *byte) const {
if (addr > this->getExtent())
return -1;
*byte = this->Bytes[addr];
return 0;
}
uint64_t getBase(void) const override;
uint64_t getExtent(void) const override;
int readByte(uint64_t addr, uint8_t *byte) const override;
};
/* we're going to make some assumptions about external calls:
@@ -130,7 +111,7 @@ class BufferMemoryObject : public llvm::MemoryObject {
assign that value to the EAX register
*/
class Inst {
class NativeInst {
public:
enum Prefix {
NoPrefix,
@@ -156,8 +137,7 @@ class Inst {
VA tgtIfTrue;
VA tgtIfFalse;
VA loc;
llvm::MCInst NativeInst;
std::string instRep;
llvm::MCInst decoded_inst;
ExternalCodeRefPtr extCallTgt;
ExternalDataRefPtr extDataRef;
@@ -201,460 +181,165 @@ class Inst {
bool hasRIP;
public:
VA offset_table;
std::vector<uint8_t> get_bytes(void) {
return this->instBytes;
}
std::string printInst(void) {
return this->instRep;
}
bool terminator(void) {
return this->is_terminator;
}
void set_terminator(void) {
this->is_terminator = true;
}
const std::vector<uint8_t> &get_bytes(void) const;
void set_system_call_number(int cn) {
this->system_call_number = cn;
}
int get_system_call_number() {
return this->system_call_number;
}
bool has_system_call_number() {
return this->system_call_number != -1;
}
bool terminator(void) const;
void set_terminator(void);
void set_local_noreturn() {
this->local_noreturn = true;
}
void set_system_call_number(int cn);
int get_system_call_number(void) const;
bool has_system_call_number(void) const;
bool has_local_noreturn() {
return this->local_noreturn;
}
void set_local_noreturn(void);
bool has_local_noreturn(void) const;
uint8_t get_reloc_offset(CFGOpType op) {
if (op == MEMRef) {
return this->mem_reloc_offset;
} else if (op == IMMRef) {
return this->imm_reloc_offset;
} else {
return -1;
}
}
uint8_t get_reloc_offset(CFGOpType op) const;
void set_reloc_offset(CFGOpType op, uint8_t ro);
void set_reloc_offset(CFGOpType op, uint8_t ro) {
if (op == MEMRef) {
this->mem_reloc_offset = ro;
} else if (op == IMMRef) {
this->imm_reloc_offset = ro;
} else {
//
}
}
void set_reference(CFGOpType op, uint64_t ref) {
if (op == MEMRef) {
this->mem_reference = ref;
this->has_mem_reference = true;
} else if (op == IMMRef) {
this->imm_reference = ref;
this->has_imm_reference = true;
} else {
// void
}
}
void set_ref_type(CFGOpType op, CFGRefType rt) {
if (op == MEMRef) {
this->mem_ref_type = rt;
} else if (op == IMMRef) {
this->imm_ref_type = rt;
} else {
// void
}
}
void set_reference(CFGOpType op, uint64_t ref);
uint64_t get_reference(CFGOpType op) const;
bool has_reference(CFGOpType op) const;
void set_ref_type(CFGOpType op, CFGRefType rt);
CFGRefType get_ref_type(CFGOpType op) const;
void set_ref_reloc_type(CFGOpType op, uint64_t ref, uint64_t ro,
CFGRefType rt) {
const char *ops = op == MEMRef ? "MEM" : "IMM";
const char *rts = rt == CFGCodeRef ? "CODE" : "DATA";
CFGRefType rt);
std::cout << __FUNCTION__ << ": Adding ref: " << ops << ", to: "
<< std::hex << ref << ", ro: " << ro << ", rt: " << rts
<< std::endl;
this->set_reference(op, ref);
this->set_reloc_offset(op, ro);
this->set_ref_type(op, rt);
}
bool has_code_ref(void) const;
bool has_reference(CFGOpType op) {
if (op == MEMRef) {
return this->has_mem_reference;
} else if (op == IMMRef) {
return this->has_imm_reference;
} else {
return false;
}
}
bool get_is_call_external(void) const;
void set_is_call_external(void);
uint64_t get_reference(CFGOpType op) {
if (op == MEMRef) {
return this->mem_reference;
} else if (op == IMMRef) {
return this->imm_reference;
} else {
return -1;
}
}
llvm::MCInst &get_inst(void);
void set_inst(const llvm::MCInst &i);
CFGRefType get_ref_type(CFGOpType op) {
if (op == MEMRef) {
return this->mem_ref_type;
} else if (op == IMMRef) {
return this->imm_ref_type;
} else {
//TODO throw exception?
//return -1;
return this->mem_ref_type;
}
}
VA get_loc(void) const;
bool has_code_ref() {
if (this->has_mem_reference && this->mem_ref_type == CFGCodeRef) {
return true;
}
void set_tr(VA a);
void set_fa(VA a);
if (this->has_imm_reference && this->imm_ref_type == CFGCodeRef) {
return true;
}
VA get_tr(void) const;
VA get_fa(void) const;
return false;
}
uint8_t get_len(void) const;
bool get_is_call_external(void) {
return this->is_call_external;
}
void set_is_call_external(void) {
this->is_call_external = true;
}
void set_call_tgt(VA addr);
bool has_call_tgt(void) const;
VA get_call_tgt(int index) const;
llvm::MCInst get_inst(void) {
return this->NativeInst;
}
void set_inst(const llvm::MCInst &i) {
this->NativeInst = i;
}
void set_inst_rep(std::string s) {
this->instRep = s;
}
void set_ext_call_target(ExternalCodeRefPtr t);
ExternalCodeRefPtr get_ext_call_target(void) const;
bool has_ext_call_target(void) const;
VA get_loc(void) {
return this->loc;
}
void set_ext_data_ref(ExternalDataRefPtr t);
ExternalDataRefPtr get_ext_data_ref(void) const;
bool has_ext_data_ref(void) const;
void set_tr(VA a) {
this->tgtIfTrue = a;
}
void set_fa(VA a) {
this->tgtIfFalse = a;
}
bool has_external_ref(void) const;
VA get_tr(void) {
return this->tgtIfTrue;
}
VA get_fa(void) {
return this->tgtIfFalse;
}
uint8_t get_len(void) {
return this->len;
}
void set_call_tgt(VA addr) {
this->targets.push_back(addr);
return;
}
bool has_call_tgt() {
return !this->targets.empty();
}
VA get_call_tgt(int index) {
return this->targets.at(index);
}
void set_ext_call_target(ExternalCodeRefPtr t) {
this->extCallTgt = t;
this->ext_call_target = true;
return;
}
void set_ext_data_ref(ExternalDataRefPtr t) {
this->extDataRef = t;
this->ext_data_ref = true;
return;
}
bool has_ext_data_ref(void) {
return this->ext_data_ref;
}
bool has_ext_call_target(void) {
return this->ext_call_target;
}
bool has_external_ref(void) {
return this->has_ext_call_target() || this->has_ext_data_ref();
}
bool has_rip_relative(void) {
return this->hasRIP;
}
VA get_rip_relative(void) {
return this->rip_target;
}
void set_rip_relative(unsigned i) {
const llvm::MCOperand &base = NativeInst.getOperand(i + 0);
const llvm::MCOperand &scale = NativeInst.getOperand(i + 1);
const llvm::MCOperand &index = NativeInst.getOperand(i + 2);
const llvm::MCOperand &disp = NativeInst.getOperand(i + 3);
rip_target = loc + len + disp.getImm();
//const
this->hasRIP = true;
}
bool has_rip_relative(void) const;
VA get_rip_relative(void) const;
void set_rip_relative(unsigned i);
// accessors for JumpTable
void set_jump_table(MCSJumpTablePtr p) {
this->jump_table = true;
this->jumpTable = p;
}
MCSJumpTablePtr get_jump_table(void) {
return this->jumpTable;
}
bool has_jump_table(void) {
return this->jump_table;
}
void set_jump_table(MCSJumpTablePtr p);
MCSJumpTablePtr get_jump_table(void) const;
bool has_jump_table(void) const;
// accessors for JumpIndexTable
void set_jump_index_table(JumpIndexTablePtr p) {
this->jump_index_table = true;
this->jumpIndexTable = p;
}
JumpIndexTablePtr get_jump_index_table(void) {
return this->jumpIndexTable;
}
bool has_jump_index_table(void) {
return this->jump_index_table;
}
void set_jump_index_table(JumpIndexTablePtr p);
JumpIndexTablePtr get_jump_index_table(void) const;
bool has_jump_index_table(void) const;
Prefix get_prefix(void) {
return this->pfx;
}
unsigned int get_addr_space(void) {
Prefix get_prefix(void) const;
unsigned int get_addr_space(void) const;
unsigned int get_opcode(void) const;
switch (this->pfx) {
case GSPrefix:
return 256;
case FSPrefix:
return 257;
default:
return 0;
}
}
unsigned int get_opcode(void) {
return this->NativeInst.getOpcode();
}
ExternalCodeRefPtr get_ext_call_target(void) {
return this->extCallTgt;
}
ExternalDataRefPtr get_ext_data_ref(void) {
return this->extDataRef;
}
Inst(VA v, uint8_t l, const llvm::MCInst &inst, std::string instR, Prefix k,
std::vector<uint8_t> bytes)
: instBytes(bytes),
tgtIfTrue(0),
tgtIfFalse(0),
loc(v),
NativeInst(inst),
instRep(instR),
pfx(k),
ext_call_target(false),
is_call_external(false),
is_terminator(false),
imm_reloc_offset(0),
imm_reference(0),
imm_ref_type(CFGDataRef),
has_imm_reference(false),
mem_reloc_offset(0),
mem_reference(0),
mem_ref_type(CFGDataRef),
has_mem_reference(false),
len(l),
jump_table(false),
jump_index_table(false),
ext_data_ref(false),
arch(0),
system_call_number( -1),
local_noreturn(false),
hasRIP(false),
rip_target(0),
offset_table( -1) {
}
NativeInst(VA v, uint8_t l, const llvm::MCInst &inst, Prefix k,
const std::vector<uint8_t> &bytes);
};
class NativeBlock {
private:
//a list of instructions
VA baseAddr;
std::list<InstPtr> instructions;
std::list<NativeInstPtr> instructions;
std::list<VA> follows;
llvm::MCInstPrinter *MyPrinter;
public:
NativeBlock(VA, llvm::MCInstPrinter *);
void add_inst(InstPtr);
VA get_base(void) {
return this->baseAddr;
}
void add_follow(VA f) {
this->follows.push_back(f);
}
std::list<VA> &get_follows(void) {
return this->follows;
}
std::string print_block(void);
explicit NativeBlock(VA);
void add_inst(NativeInstPtr);
VA get_base(void);
void add_follow(VA f);
std::list<VA> &get_follows(void);
std::string get_name(void);
const std::list<InstPtr> &get_insts(void) {
return this->instructions;
}
llvm::MCInstPrinter *get_printer(void) {
return this->MyPrinter;
}
uint32_t get_size(void) {
uint32_t blockLen = 0;
const std::list<NativeInstPtr> &get_insts(void);
for (std::list<InstPtr>::iterator i = this->instructions.begin();
i != this->instructions.end(); ++i) {
InstPtr inst = *i;
blockLen += inst->get_len();
}
return blockLen;
}
private:
NativeBlock(void) = delete;
};
typedef boost::shared_ptr<NativeBlock> NativeBlockPtr;
typedef NativeBlock *NativeBlockPtr;
class NativeFunction {
public:
NativeFunction(VA b)
: funcEntryVA(b),
nextBlockID(0),
graph(nullptr) {
}
explicit NativeFunction(VA b)
: funcEntryVA(b) {}
NativeFunction(VA b, const std::string &sym)
: funcEntryVA(b),
funcSymName(sym),
nextBlockID(0),
graph(nullptr) {
}
funcSymName(sym) {}
void add_block(NativeBlockPtr);
VA get_start(void) {
return this->funcEntryVA;
}
uint64_t num_blocks(void) {
return this->IDtoBlock.size();
}
NativeBlockPtr block_from_id(uint64_t);
VA get_start(void);
uint64_t num_blocks(void);
NativeBlockPtr block_from_base(VA);
uint64_t entry_block_id() const;
void compute_graph(void);
const CFG &get_cfg(void) {
return *this->graph;
}
const std::map<VA, NativeBlockPtr> &get_blocks(void) const;
std::string get_name(void);
const std::string &get_symbol_name(void);
private:
//a graph of blocks
CFG *graph;
//a map of block bases to block IDs
std::map<VA, uint64_t> baseToID;
//a map of block IDs to blocks
std::map<uint64_t, NativeBlockPtr> IDtoBlock;
NativeFunction(void) = delete;
// Use a `std::map` to keep the blocks in their original order.
std::map<VA, NativeBlockPtr> blocks;
//addr of function entry point
VA funcEntryVA;
std::string funcSymName;
//next available block ID
uint64_t nextBlockID;
};
typedef boost::shared_ptr<NativeBlock> NativeBlockPtr;
typedef boost::shared_ptr<NativeFunction> NativeFunctionPtr;
typedef NativeBlock *NativeBlockPtr;
typedef NativeFunction *NativeFunctionPtr;
class DataSectionEntry {
public:
DataSectionEntry(uint64_t base, const std::vector<uint8_t>& b)
: base(base),
bytes(b),
is_symbol(false) {
//empty
}
DataSectionEntry(uint64_t base, const std::vector<uint8_t> &b);
DataSectionEntry(uint64_t base, const std::string &sname);
DataSectionEntry(uint64_t base, const std::string &sname,
uint64_t symbol_size);
DataSectionEntry(uint64_t base, const std::string& sname)
: base(base),
sym_name(sname),
is_symbol(true) {
uint64_t getBase(void) const;
this->bytes.push_back(0x0);
this->bytes.push_back(0x0);
this->bytes.push_back(0x0);
this->bytes.push_back(0x0);
}
uint64_t getSize(void) const;
DataSectionEntry(uint64_t base, const std::string& sname,
uint64_t symbol_size)
: base(base),
sym_name(sname),
is_symbol(true) {
// initialize bytes to null
for (unsigned int i = 0; i < symbol_size; i++) {
this->bytes.push_back(0x0);
}
}
const std::vector<uint8_t> &getBytes(void) const;
uint64_t getBase() const {
return this->base;
}
uint64_t getSize() const {
return this->bytes.size();
}
std::vector<uint8_t> getBytes() const {
return this->bytes;
}
bool getSymbol(std::string &sname) const;
bool getSymbol(std::string &sname) const {
if (this->is_symbol) {
sname = this->sym_name;
return true;
} else {
return false;
}
}
virtual ~DataSectionEntry() {
}
;
virtual ~DataSectionEntry(void);
protected:
uint64_t base;
std::vector<uint8_t> bytes;
bool is_symbol;
std::string sym_name;
private:
DataSectionEntry(void) = delete;
};
class DataSection {
@@ -666,205 +351,99 @@ class DataSection {
public:
static const uint64_t NO_BASE = (uint64_t) ( -1);
DataSection()
: base(NO_BASE),
read_only(false) {
}
DataSection(void);
virtual ~DataSection(void);
virtual ~DataSection() {
}
;
void setReadOnly(bool isro);
bool isReadOnly(void) const;
uint64_t getBase(void) const;
const std::list<DataSectionEntry> &getEntries(void) const;
void addEntry(const DataSectionEntry &dse);
uint64_t getSize(void) const;
std::vector<uint8_t> getBytes(void) const;
};
void setReadOnly(bool isro) {
this->read_only = isro;
}
bool isReadOnly() const {
return this->read_only;
}
uint64_t getBase() const {
return this->base;
}
class NativeEntrySymbol {
private:
const std::string name;
const VA addr;
bool has_extra;
int num_args;
bool does_return;
ExternalCodeRef::CallingConvention calling_conv;
std::list<DataSectionEntry>& getEntries() {
return this->entries;
}
public:
NativeEntrySymbol(const std::string &name_, VA addr_);
explicit NativeEntrySymbol(VA addr_);
void addEntry(const DataSectionEntry &dse) {
this->entries.push_back(dse);
if (this->base == NO_BASE || this->base > dse.getBase()) {
this->base = dse.getBase();
}
}
const std::string &getName(void) const;
VA getAddr(void) const;
bool hasExtra(void) const;
void setExtra(int argc_, bool does_ret,
ExternalCodeRef::CallingConvention conv);
int getArgc(void) const;
bool doesReturn(void) const;
ExternalCodeRef::CallingConvention getConv(void) const;
uint64_t getSize() const {
uint64_t size_sum = 0;
for (std::list<DataSectionEntry>::const_iterator itr = entries.begin();
itr != entries.end(); itr++) {
size_sum += itr->getSize();
}
return size_sum;
}
std::vector<uint8_t> getBytes() const {
std::vector<uint8_t> all_bytes;
for (std::list<DataSectionEntry>::const_iterator itr = entries.begin();
itr != entries.end(); itr++) {
std::vector<uint8_t> vec = itr->getBytes();
all_bytes.insert(all_bytes.end(), vec.begin(), vec.end());
}
return all_bytes;
}
private:
NativeEntrySymbol(void) = delete;
};
class NativeModule {
public:
class EntrySymbol {
private:
std::string name;
VA addr;
bool has_extra;
int argc;
bool does_return;
ExternalCodeRef::CallingConvention cconv;
NativeModule(const std::string &module_name_,
const std::unordered_map<VA, NativeFunctionPtr> &funcs_,
const std::string &triple_,
const llvm::Target *target_);
public:
EntrySymbol(const std::string &name, VA addr)
: name(name),
addr(addr),
has_extra(false),
argc(0),
does_return(false),
cconv(ExternalCodeRef::CallerCleanup) {
}
void add_func(NativeFunctionPtr f);
const std::unordered_map<VA, NativeFunctionPtr> &get_funcs(void) const;
EntrySymbol(VA addr)
: addr(addr),
has_extra(false),
argc(0),
does_return(false),
cconv(ExternalCodeRef::CallerCleanup) {
this->name = "sub_" + to_string<VA>(this->addr, std::hex);
}
const std::string& getName() const {
return this->name;
}
VA getAddr() const {
return this->addr;
}
bool hasExtra() const {
return this->has_extra;
}
int getArgc() const {
return this->argc;
}
bool doesReturn() const {
return this->does_return;
}
ExternalCodeRef::CallingConvention getConv() const {
return this->cconv;
}
void setExtra(int argc, bool does_ret,
ExternalCodeRef::CallingConvention conv) {
this->argc = argc;
this->does_return = does_ret;
this->cconv = conv;
this->has_extra = true;
}
};
NativeModule(std::string, std::list<NativeFunctionPtr>,
llvm::MCInstPrinter *);
void add_func(NativeFunctionPtr f) {
this->funcs.push_back(f);
}
const std::list<NativeFunctionPtr> &get_funcs(void) {
return this->funcs;
}
CFG get_cfg(void) {
return this->callGraph;
}
std::string printModule(void);
std::string name(void) {
return this->nameStr;
}
llvm::MCInstPrinter *get_printer(void) {
return this->MyPrinter;
}
const std::string &name(void) const;
//add a data section from a COFF object
void addDataSection(VA, std::vector<uint8_t> &);
void addDataSection(const DataSection &d);
std::list<DataSection> &getData(void) {
return this->dataSecs;
}
const std::list<DataSection> &getData(void) const;
//add an external reference
void addExtCall(ExternalCodeRefPtr p) {
this->extCalls.push_back(p);
return;
}
const std::list<ExternalCodeRefPtr> &getExtCalls(void) {
return this->extCalls;
}
void addExtCall(ExternalCodeRefPtr p);
const std::list<ExternalCodeRefPtr> &getExtCalls(void) const;
//external data ref
void addExtDataRef(ExternalDataRefPtr p) {
this->extData.push_back(p);
return;
}
const std::list<ExternalDataRefPtr> &getExtDataRefs(void) {
return this->extData;
}
void addExtDataRef(ExternalDataRefPtr p);
std::vector<EntrySymbol> entries;
const std::list<ExternalDataRefPtr> &getExtDataRefs(void) const;
const std::vector<EntrySymbol> &getEntryPoints() const {
return this->entries;
}
void addEntryPoint(const EntrySymbol& ep) {
this->entries.push_back(ep);
}
const std::vector<NativeEntrySymbol> &getEntryPoints(void) const;
void setTarget(const llvm::Target *T) {
this->target = T;
}
void addEntryPoint(const NativeEntrySymbol &ep);
void setTargetTriple(const std::string &triple) {
this->triple = llvm::Triple(triple);
}
bool is64Bit(void) const;
bool is64Bit(void) {
if (std::string(target->getName()) == "x86-64") {
return true;
}
return false;
}
void addOffsetTables(const std::list<MCSOffsetTablePtr> &tables);
void addOffsetTables(const std::list<MCSOffsetTablePtr> & tables);
std::vector<NativeEntrySymbol> entries;
private:
std::list<NativeFunctionPtr> funcs;
std::map<FuncID, NativeFunctionPtr> IDtoFunc;
CFG callGraph;
FuncID nextID;
std::string nameStr;
llvm::MCInstPrinter *MyPrinter;
const llvm::Target *target;
llvm::Triple triple;
NativeModule(void) = delete;
std::list<DataSection> dataSecs;
std::list<ExternalCodeRefPtr> extCalls;
std::list<ExternalDataRefPtr> extData;
std::unordered_map<VA, NativeFunctionPtr> funcs;
const std::string module_name;
const llvm::Target * const target;
const llvm::Triple triple;
std::list<DataSection> data_sections;
std::list<ExternalCodeRefPtr> external_code_refs;
std::list<ExternalDataRefPtr> external_data_refs;
public:
std::unordered_map<VA, MCSOffsetTablePtr> offsetTables;
std::unordered_map<VA, MCSOffsetTablePtr> offset_tables;
};
typedef boost::shared_ptr<NativeModule> NativeModulePtr;
typedef NativeModule *NativeModulePtr;
enum ModuleInputFormat {
COFFObject,
@@ -873,22 +452,8 @@ enum ModuleInputFormat {
ProtoBuff
};
const llvm::Target *findDisTarget(std::string);
NativeModulePtr readModule(std::string, ModuleInputFormat, std::list<VA>,
const llvm::Target*);
// used in testSemantics.cpp via funcFromBuff
NativeBlockPtr blockFromBuff(VA, BufferMemoryObject &,
const llvm::MCDisassembler *,
llvm::MCInstPrinter *);
// used in testSemantics.cpp
NativeFunctionPtr funcFromBuff(VA, BufferMemoryObject &,
const llvm::MCDisassembler *,
llvm::MCInstPrinter *);
void addExterns(std::list<NativeFunctionPtr>, NativeModulePtr);
std::string dumpProtoBuf(NativeModulePtr);
NativeModulePtr ReadProtoBuf(const std::string &file_name,
const std::string &triple,
const llvm::Target *target);
#endif
+2 -2
View File
@@ -11,8 +11,8 @@ then
echo "Using IDA to recover CFG"
${BIN_DESCEND_PATH}/bin_descend_wrapper.py -march=x86 -entry-symbol=shiftit -i=demo_test16.o >> /dev/null
else
echo "Using bin_descend to recover CFG"
${BIN_DESCEND_PATH}/bin_descend -d -march=x86 -entry-symbol=shiftit -i=demo_test16.o
echo "Please install IDA to recover the control flow graph; bin_descend is now deprecated"
exit 1
fi
${CFG_TO_BC_PATH}/cfg_to_bc -mtriple=i686-pc-linux-gnu -i demo_test16.cfg -entrypoint=shiftit -o demo_test16.bc
+8 -13
View File
@@ -2,25 +2,20 @@
source env.sh
rm -f demo17 demo17.bc demo17.cfg demo17_opt.bc demo17_out.exe
rm -f demo_test17.cfg demo_driver17.o demo_test17.o demo_test17_mine.o demo_driver17.exe
${CC} -ggdb -m32 -o demo17 demo17.c
${CC} -ggdb -m32 -c -o demo_test17.o demo17.c
if [ -e "${IDA_PATH}/idaq" ]
then
echo "Using IDA to recover CFG"
IDALOG=logfile_demo17.txt
${BIN_DESCEND_PATH}/bin_descend_wrapper.py -d -func-map=${STD_DEFS}/linux.txt -i=demo17 -entry-symbol=main >> /dev/null
${BIN_DESCEND_PATH}/bin_descend_wrapper.py -march=x86 -entry-symbol=main -i=demo_test17.o >> /dev/null
else
echo "Using bin_descend to recover CFG"
${BIN_DESCEND_PATH}/bin_descend -d -march=x86 -func-map=${STD_DEFS}/linux.txt -i=demo17 -entry-symbol=main
echo "Please install IDA to recover the control flow graph; bin_descend is now deprecated"
exit 1
fi
${CFG_TO_BC_PATH}/cfg_to_bc -mtriple=i686-pc-linux-gnu -i demo17.cfg -driver=mcsema_main,main,2,return,C -o demo17.bc
${LLVM_PATH}/opt -O3 -o demo17_opt.bc demo17.bc
${LLVM_PATH}/llvm-link ${RUNTIME_PATH}/linux_i386_callback.bc demo17_opt.bc > demo17_linked.bc
${LLVM_PATH}/llc -filetype=obj -o demo17.o demo17_linked.bc
${CFG_TO_BC_PATH}/cfg_to_bc -mtriple=i686-pc-linux-gnu -i demo_test17.cfg -entrypoint=main -o demo_test17.bc
clang-3.5 -O3 -m32 -o demo_driver17.exe ../../drivers/ELF_32_linux.S demo_test17.bc
${CC} -m32 -ggdb -o demo17_out.exe driver_demo17.c demo17.o
./demo17_out.exe
./demo_driver17.exe
-12
View File
@@ -1,12 +0,0 @@
#include <stdlib.h>
extern int mcsema_main(int argc, const char *argv[]);
extern void* __mcsema_create_alt_stack(size_t stack_size);
extern void* __mcsema_free_alt_stack(size_t stack_size);
int main(int argc, const char *argv[]) {
__mcsema_create_alt_stack(4096*2);
int rv = mcsema_main(argc, argv);
__mcsema_free_alt_stack(4096*2);
return rv;
}
+2 -2
View File
@@ -5,8 +5,8 @@ IDA_PATH=$(<./IDA_PATH.linux)
GET_CFG_PY=${BIN_DESCEND_PATH}/get_cfg.py
STD_DEFS=$(<./STD_DEFS.linux)
RUNTIME_PATH=$(<./RUNTIME_PATH.linux)
CC=clang
CXX=clang++
CC=clang-3.5
CXX=clang++-3.5
export TVHEADLESS=1
export IDALOG=/dev/null
export IDA_PATH
-5
View File
@@ -1,5 +0,0 @@
if("${TARGET}" STREQUAL "X86_64")
add_subdirectory(x86_64)
else()
add_subdirectory(x86)
endif("${TARGET}" STREQUAL "X86_64")
-3
View File
@@ -1,3 +0,0 @@
add_subdirectory(valTool)
add_subdirectory(valTest)
add_subdirectory(testSemantics)
@@ -1,46 +0,0 @@
find_package(Nasm REQUIRED)
include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../peToCFG
${CMAKE_CURRENT_SOURCE_DIR}/../../../cfgToLLVM
${CMAKE_CURRENT_SOURCE_DIR}/../../../../llvm-3.5/utils/unittest/googletest/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../../llvm-3.5/lib/Target/X86
${CMAKE_CURRENT_BINARY_DIR}/../../../../llvm-3.5/lib/Target/X86)
SET_SOURCE_FILES_PROPERTIES( "${CMAKE_CURRENT_SOURCE_DIR}/testSemantics.auto.cpp"
PROPERTIES
GENERATED true
)
add_custom_target(testSemantics.auto.cpp ALL
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/../testgen.py" -tstmpl "${CMAKE_CURRENT_SOURCE_DIR}/testSemantics.template" -tsout "${CMAKE_CURRENT_SOURCE_DIR}/testSemantics.auto.cpp" -testfiles "${CMAKE_CURRENT_SOURCE_DIR}/../tests" -nasm "${NASM_EXECUTABLE}"
COMMENT Generating semantics tests
)
add_executable(testSemantics "${CMAKE_CURRENT_SOURCE_DIR}/testSemantics.auto.cpp" )
add_dependencies(testSemantics testSemantics.auto.cpp )
link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../../lib)
target_link_libraries(testSemantics peToCFG cfgToLLVM
LLVMInterpreter LLVMipo LLVMInstrumentation
LLVMX86CodeGen LLVMJIT LLVMBitReader LLVMBitWriter LLVMMCDisassembler gtest
gtest_main LLVMX86Disassembler LLVMX86AsmParser LLVMX86CodeGen
LLVMSelectionDAG LLVMAsmPrinter LLVMX86Desc LLVMX86Info LLVMObjCARCOpts
LLVMX86AsmPrinter LLVMX86Utils ${Boost_LIBRARIES} libprotobuf)
IF(UNIX)
find_library(DL_LIB dl)
target_link_libraries(testSemantics ${DL_LIB})
endif(UNIX)
add_dependencies(testSemantics peToCFG bitreader asmparser bitwriter instrumentation scalaropts ipo pin_validator gtest tests.out)
IF(APPLE)
SET_TARGET_PROPERTIES(testSemantics PROPERTIES LINK_FLAGS "-pagezero_size 1000")
endif(APPLE)
if(UNIX)
add_custom_target(run_testSemantics ALL
COMMAND cd ${CMAKE_CURRENT_BINARY_DIR}/../valTest && ../testSemantics/testSemantics || echo # this echo shouldn't be here. It lets the build continue
DEPENDS testSemantics testSemantics.auto.cpp
)
endif(UNIX)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-339
View File
@@ -1,339 +0,0 @@
import sys
import collections
import itertools
import os
import glob
import subprocess
import tempfile
import re
import argparse
#for debugging, use the pretty-printer
import pprint
argparser = argparse.ArgumentParser()
argparser.add_argument('-tstmpl', type=argparse.FileType('rb', 0), help="testSemantics template", required=True)
argparser.add_argument('-taout', type=argparse.FileType('wb', 0), help="assembly output for PIN", required=False)
argparser.add_argument('-tsout', type=argparse.FileType('wb', 0), help="testSemantics.cpp output", required=False)
argparser.add_argument('-testfiles', help="directory containing test files", required=True)
argparser.add_argument('-nasm', help="path to nasm executable", required=True)
args = argparser.parse_args()
if not (args.taout or args.tsout):
sys.stderr.write("Either -taout or -tsout is required!\n")
sys.exit(-1)
#TEST_FILES_PATH = os.path.join("..","validator", "valTest", "tests")
#NASM_PATH = os.path.join("..","validator","valTest", "nasm", "nasm.exe")
EXPECTED_LINES = ["BITS 32", ";TEST_FILE_META_BEGIN"]
META_END_MARKER = ";TEST_FILE_META_END"
TEST_NUMBER = 0x300
PREPARED_TESTS = collections.OrderedDict()
#OUTPUT_TESTSEMANTICS = "testSemantics.auto.cpp"
#OUTPUT_TEST_ASM = "test_a.auto.asm"
BEGIN_RECORDING_TOKEN = ";TEST_BEGIN_RECORDING"
END_RECORDING_TOKEN = ";TEST_END_RECORDING"
RCONST = 0x18230000
RECORDED_ASM_RE = re.compile(";TEST_(BEGIN|END)_RECORDING")
TEST_DECLARATION = """
NEW_TEST("{test_name}", {test_number:#x});
"""
TEST_IGNOREFLAGS_DECLARATION = """
NEW_TEST_IGNOREFLAGS("{test_name}", {test_number:#x}, {test_ignoreflags});
"""
TEST_DEFINITION = """
{test_type}(ModuleTest, {test_name}) {{
uint8_t byteArr[] = {{ {test_bytes} }};
IN_OUT_TEST("{test_name}", byteArr);
}}
"""
def compile_asm(test_name, test_file):
tmphandle_bin,tmpfile_bin = tempfile.mkstemp(suffix=".bin")
tmphandle_asm,tmpfile_asm = tempfile.mkstemp(suffix=".asm")
os.close(tmphandle_bin)
os.close(tmphandle_asm)
orig_asm = open(test_file, 'rb').read()
# get only the asm between ;TEST_BEGIN_RECORDING and ;TEST_END_RECORDING
orig_parts = RECORDED_ASM_RE.split(orig_asm)
semantics_asm = orig_parts[2]
#save it to a separate file for compilation
with open(tmpfile_asm, 'wb') as asmfile:
asmfile.write("BITS 32\n")
asmfile.write(semantics_asm)
try:
subprocess.check_call([args.nasm, "-f", "bin", "-o", tmpfile_bin, tmpfile_asm])
except subprocess.CalledProcessError as e:
sys.stderr.write("Could not assemble test {}, original source file: {}\n".format(test_name, test_file))
sys.stderr.write("Error was: {}\n".format(e))
os.unlink(tmpfile_bin)
os.unlink(tmpfile_asm)
sys.exit(-1)
with open(tmpfile_bin, 'rb') as binfile:
bindata = binfile.read()
#clean up tmpfiles
os.unlink(tmpfile_bin)
os.unlink(tmpfile_asm)
# transform to c-style hex (0x##)
bindata = ", ".join([hex(ord(x)) for x in bindata])
return bindata
def parse_metadata(test_name, test_file):
global EXPECTED_LINES
meta_values = {}
lines = open(test_file, 'r').readlines()
lines = [l.strip() for l in lines]
# do a quick sanity check on ASM files in the directory
for i in range(2):
if lines[i].upper() != EXPECTED_LINES[i]:
sys.stderr.write("Failed to parse {}. Looking for {}, got {}\n".format(test_file, EXPECTED_LINES[i], lines[i] ))
sys.exit(-1)
#parse metadata; it should be in the form of
#;KEY=VALUE
# the keys are lowercased and values are uppercased
for i in xrange(2, len(lines)-2):
if lines[i] == META_END_MARKER:
break
try:
vname, vval = lines[i].split('=')
vname = vname[1:]
except:
sys.stderr.write("Could not parse {}; line: {}.\nExpected KEY=VALUE\n".format(test_file, lines[i]))
sys.exit(-1)
meta_values[vname.lower()] = vval.upper()
#get the asm that will go into the automatically
# generated test_a.auto.asm. That file is by PIN
# to generate ground truth for semantics tests
all_but_bits_line = "\n".join(lines[1:])
all_but_bits_line = all_but_bits_line.replace(
BEGIN_RECORDING_TOKEN, "mov esi, {:#x}".format(RCONST+TEST_NUMBER))
all_but_bits_line = all_but_bits_line.replace(
END_RECORDING_TOKEN, "mov esi, {:#x}".format(RCONST+TEST_NUMBER))
meta_values['test_asm'] = all_but_bits_line
return meta_values
def prepare_from_file(test_name, test_file):
#read metadata
meta_dict = parse_metadata(test_name, test_file)
#get the hex bytes that go into testSemantics.auto.cpp
hexbytes = compile_asm(test_name, test_file)
meta_dict['test_bytes'] = hexbytes
# see if we are using an ignoreflags or a normal declaration
# this is determined by the value of TEST_IGNOREFLAGS metadata entry
if meta_dict['test_ignoreflags'] == "":
meta_dict['test_declaration'] = TEST_DECLARATION
else:
meta_dict['test_declaration'] = TEST_IGNOREFLAGS_DECLARATION
return meta_dict
def prepare_tests():
global TEST_NUMBER
# assume every .asm file in the tests directory is a test
asm_files = glob.glob( os.path.join(args.testfiles,"*.asm") )
# test names are the file name without .asm
test_names = map(lambda x: os.path.basename(x)[:-4], asm_files)
sys.stderr.write( "Found {} tests:\n".format(len(test_names)) )
pprint.pprint(test_names, stream=sys.stderr)
# fill out the test dictionary with a test name and an increasing
# test number. Should be filled out in alphabetical order, or
# whichever way glob.glob() returns files
for test,testfile in zip(sorted(test_names), sorted(asm_files)):
sys.stderr.write("processing: {}\n".format(test))
PREPARED_TESTS[test] = {}
td = PREPARED_TESTS[test]
td['test_number'] = TEST_NUMBER
td['test_name'] = test
# fill out:
# test_bytes
# test_declaration
# test_type
td.update(prepare_from_file(test, testfile))
TEST_NUMBER += 1
def gen_declarations():
declarations = ""
for test in PREPARED_TESTS.itervalues():
declarations += test['test_declaration'].format(**test)
return declarations
def gen_definitions():
declarations = ""
for test in PREPARED_TESTS.itervalues():
declarations += TEST_DEFINITION.format(**test)
return declarations
def gen_asm():
asm = ""
for tname,test in PREPARED_TESTS.iteritems():
asm += """\n"""
asm += " ;TEST: " + tname + "\n"
asm += " " + test['test_asm'] + "\n"
asm += """
; pre-test clear to zeros
mov eax, 0
mov ecx, 0
mov edx, 0
mov ebx, 0
mov esi, 0
mov edi, 0
; end pre-test clear
; restore stack
mov esp, dword [internal_saveregs+0x10]
mov ebp, dword [internal_saveregs+0x14]
; add some stack slack
sub esp, 0x100
mov eax, dword [internal_saveregs+0x20]
push eax
POPFD
FLDZ ;ST0
FLDZ ;ST1
FLDZ ;ST2
FLDZ ;ST3
FLDZ ;ST4
FLDZ ;ST5
FLDZ ;ST6
FLDZ ;ST7
FNINIT
"""
return asm
if __name__ == "__main__":
prepare_tests()
decs = "// Begin Declarations\n"
decs += gen_declarations()
decs += "// End Declarations\n"
defs = "// Begin Definitions\n"
defs += gen_definitions()
defs += "// End Definitions\n"
data = None
# create test_a.auto.asm
test_asm = """BITS 32
section .text
global doTest
doTest:
mov dword [internal_saveregs+0x00], eax
mov dword [internal_saveregs+0x04], ecx
mov dword [internal_saveregs+0x08], edx
mov dword [internal_saveregs+0x0c], ebx
mov dword [internal_saveregs+0x10], esp
mov dword [internal_saveregs+0x14], ebp
mov dword [internal_saveregs+0x18], esi
mov dword [internal_saveregs+0x1c], edi
push eax
PUSHFD
pop eax
mov dword [internal_saveregs+0x20], eax
pop eax
FNSAVE [internal_savefpu_precall]
mov eax, 0
mov ecx, 0
mov edx, 0
mov ebx, 0
mov esi, 0
mov edi, 0
sub esp, 0x100
mov eax, dword [internal_saveregs+0x20]
push eax
POPFD
FLDZ ;ST0
FLDZ ;ST1
FLDZ ;ST2
FLDZ ;ST3
FLDZ ;ST4
FLDZ ;ST5
FLDZ ;ST6
FLDZ ;ST7
FNINIT
"""
test_asm += gen_asm()
test_asm += """
mov eax, dword [internal_saveregs+0x00]
mov ecx, dword [internal_saveregs+0x04]
mov edx, dword [internal_saveregs+0x08]
mov ebx, dword [internal_saveregs+0x0c]
mov esp, dword [internal_saveregs+0x10]
mov ebp, dword [internal_saveregs+0x14]
mov esi, dword [internal_saveregs+0x18]
mov edi, dword [internal_saveregs+0x1c]
push dword [internal_saveregs+0x20]
POPFD
FRSTOR [internal_savefpu_precall]
RET
SECTION .bss
internal_saveregs: RESD 10
internal_savefpu: RESB 108
internal_savefpu_precall: RESB 108
"""
# populate testSemantics.auto.cpp
data = args.tstmpl.read()
args.tstmpl.close()
data = data.replace(r'/*%DECLARATIONS*%/', decs)
data = data.replace(r'/*%DEFINITIONS%*/', defs)
if data == None:
sys.stderr.write("Error: Could not open template file: {}\n".format(TEMPLATE_FILE))
sys.exit(-1)
else:
if args.tsout:
args.tsout.write(data)
args.tsout.close()
if args.taout:
args.taout.write(test_asm)
args.taout.close()
-14
View File
@@ -1,14 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; AAA
mov al, 0x45
add al, 0x23
;enable tracing
;TEST_BEGIN_RECORDING
aaa
;disable tracing
;TEST_END_RECORDING
-13
View File
@@ -1,13 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=FLAG_AF|FLAG_OF|FLAG_CF
;TEST_FILE_META_END
; AAD8i8
mov ax, 0x70
;TEST_BEGIN_RECORDING
aad 0xa
;TEST_END_RECORDING
mov bl, 0x3
div bl
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=FLAG_AF|FLAG_OF|FLAG_CF
;TEST_FILE_META_END
; AAM8i8
mov al, 0x22
mov bl, 0x6
;TEST_BEGIN_RECORDING
aam 0xa
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=FLAG_PF
;TEST_FILE_META_END
; AAS
mov al, 0x45
sub al, 0x23
;TEST_BEGIN_RECORDING
aas
;TEST_END_RECORDING
-15
View File
@@ -1,15 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; set up st0 to be -1
lea edi, [esp-04]
mov dword [edi], 0xbf800000
fld dword [edi]
;TEST_BEGIN_RECORDING
FABS
mov edi, 0
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC16i16
mov ax, 0x55
;TEST_BEGIN_RECORDING
adc ax, 0xeee
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; Adc16RI
mov ax, 0xf012
;TEST_BEGIN_RECORDING
adc ax, 0x1234
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC16rr
mov cx, 0xabc
mov dx, 0xdef
;TEST_BEGIN_RECORDING
adc cx, dx
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC32i32
mov eax, 0x778
;TEST_BEGIN_RECORDING
adc eax, 0x6fffffff
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC32ri
mov ebx, 0x6789
;TEST_BEGIN_RECORDING
adc ebx, 0x44444
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; Adc32RR
mov eax, 0x1234abcd
mov edx, 0x2345bcde
;TEST_BEGIN_RECORDING
adc eax, edx
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC8i8
mov al, 0xbb
;TEST_BEGIN_RECORDING
adc al, 0x5
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC8ri
mov ah, 0xaa
;TEST_BEGIN_RECORDING
adc ah, 0x3
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADC8rr
mov ch, 0xc
mov dh, 0x10
;TEST_BEGIN_RECORDING
adc ch, dh
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD16i16
mov ax, 0x4
;TEST_BEGIN_RECORDING
add ax, 0xeeee
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD16ri
mov bx, 0x4
;TEST_BEGIN_RECORDING
add bx, 0x444
;TEST_END_RECORDING
-14
View File
@@ -1,14 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD16rm
;TEST_BEGIN_RECORDING
lea eax, [esp-0x10]
mov DWORD [eax], 0x1000
mov bx, 0x2
add bx, [eax]
mov eax, [eax]
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD16rr
mov cx, 0x4
mov dx, 0x5
;TEST_BEGIN_RECORDING
add cx, dx
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD32i32
mov eax, 0x4
;TEST_BEGIN_RECORDING
add eax, 0x6fffffff
;TEST_END_RECORDING
-15
View File
@@ -1,15 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD32mr
;TEST_BEGIN_RECORDING
lea edi, [esp-0x4]
mov DWORD [edi], 0x8
mov eax, 0x36
add [edi], eax
mov eax, [edi]
mov edi, 0x0
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; Add32RI
mov eax, 0x2
;TEST_BEGIN_RECORDING
add eax, 0x11111
;TEST_END_RECORDING
-14
View File
@@ -1,14 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; Add32RR
xor eax, eax
inc eax
mov eax, 0x1
mov ebx, 0x2
;TEST_BEGIN_RECORDING
add eax, ebx
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD8i8
mov al, 0x4
;TEST_BEGIN_RECORDING
add al, 0x5
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD8ri
mov ah, 0x20
;TEST_BEGIN_RECORDING
add ah, 0x3
;TEST_END_RECORDING
-12
View File
@@ -1,12 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; ADD8rr
mov ch, 0x2
mov dh, 0x3
;TEST_BEGIN_RECORDING
add ch, dh
;TEST_END_RECORDING
-22
View File
@@ -1,22 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; convert 1 to a double precision float and store in xmm0
mov ecx, 1
cvtsi2sd xmm0, ecx
;TEST_BEGIN_RECORDING
; load 2.5 (in double precision float form)
lea ecx, [esp-8]
mov DWORD [ecx], 0
mov DWORD [ecx+4], 0x40040000
addsd xmm0, [ecx]
mov ecx, [ecx]
;TEST_END_RECORDING
xor ecx, ecx
cvtsi2sd xmm0, ecx
-21
View File
@@ -1,21 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; convert 1 to a double precision float and store in xmm0
mov ecx, 1
cvtsi2sd xmm0, ecx
; convert 2 to a double precision float and store in xmm1
mov ecx, 2
cvtsi2sd xmm1, ecx
;TEST_BEGIN_RECORDING
addsd xmm0, xmm1
;TEST_END_RECORDING
xor ecx, ecx
cvtsi2sd xmm0, ecx
cvtsi2sd xmm1, ecx
-21
View File
@@ -1,21 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; convert 1 to a double precision float and store in xmm0
mov ecx, 1
cvtsi2ss xmm0, ecx
;TEST_BEGIN_RECORDING
; load 1.5 (in double precision float form)
lea ecx, [esp-4]
mov DWORD [ecx], 0x3fc00000
addss xmm0, [ecx]
mov ecx, [ecx]
;TEST_END_RECORDING
xor ecx, ecx
cvtsi2sd xmm0, ecx
-21
View File
@@ -1,21 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; convert 3 to a double precision float and store in xmm0
mov ecx, 3
cvtsi2ss xmm0, ecx
; convert 1 to a double precision float and store in xmm1
mov ecx, 1
cvtsi2ss xmm1, ecx
;TEST_BEGIN_RECORDING
addss xmm0, xmm1
;TEST_END_RECORDING
xor ecx, ecx
cvtsi2sd xmm0, ecx
cvtsi2sd xmm1, ecx
-17
View File
@@ -1,17 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; set up st0 to be 3.141593
lea edi, [esp-04]
mov dword [edi], 0x40490fdb
fld dword [edi]
;TEST_BEGIN_RECORDING
lea edi, [esp-04]
mov dword [edi], 0x40490fdb
FADD dword [edi]
mov edi, 0
;TEST_END_RECORDING
-16
View File
@@ -1,16 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; set up st0 to be 1.0
FLD1
;TEST_BEGIN_RECORDING
lea edi, [esp-08]
; 3.1415926 or there about
mov dword [edi+00], 0x54442d18
mov dword [edi+04], 0x400921fb
FADD qword [edi]
mov edi, 0
;TEST_END_RECORDING
-13
View File
@@ -1,13 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; set up st0 and st1 to be pi
FLDPI
FLDPI
;TEST_BEGIN_RECORDING
FADD st0, st1
;TEST_END_RECORDING
-13
View File
@@ -1,13 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=
;TEST_FILE_META_END
; set up st0 and st1 to be pi
FLDPI
FLDPI
;TEST_BEGIN_RECORDING
FADD st1, st0
;TEST_END_RECORDING
-11
View File
@@ -1,11 +0,0 @@
BITS 32
;TEST_FILE_META_BEGIN
;TEST_TYPE=TEST_F
;TEST_IGNOREFLAGS=FLAG_AF
;TEST_FILE_META_END
; AND16i16
mov ax, 0x7
;TEST_BEGIN_RECORDING
and ax, 0xeeee
;TEST_END_RECORDING

Some files were not shown because too many files have changed in this diff Show More