mirror of
https://github.com/lifting-bits/mcsema
synced 2026-06-08 15:31:09 +00:00
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:
+12
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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> §ions)`: 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
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 §ion_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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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
@@ -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> §ions = 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 §ions = 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
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ®)
|
||||
{
|
||||
@@ -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 ®)
|
||||
{
|
||||
@@ -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
@@ -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())); \
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ®) {
|
||||
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 ®,
|
||||
static InstTransResult doCmpRM(NativeInstPtr ip, BasicBlock *&b, const MCOperand ®,
|
||||
Value *mem) {
|
||||
NASSERT(reg.isReg());
|
||||
NASSERT(mem!=NULL);
|
||||
@@ -117,7 +116,7 @@ static InstTransResult doCmpRM(InstPtr ip, BasicBlock *&b, const MCOperand ®,
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+647
-659
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ®) {
|
||||
static InstTransResult doBswapR(NativeInstPtr ip, llvm::BasicBlock *&b,
|
||||
const llvm::MCOperand ®) {
|
||||
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
|
||||
|
||||
|
||||
@@ -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 ®) \
|
||||
#define DO_SETCC_OP_REG(NAME) static InstTransResult do ## NAME ## R(NativeInstPtr ip, llvm::BasicBlock *&b, const llvm::MCOperand ®) \
|
||||
{ \
|
||||
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;
|
||||
}
|
||||
|
||||
+2886
-2999
File diff suppressed because it is too large
Load Diff
+395
-490
File diff suppressed because it is too large
Load Diff
@@ -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 ®) {
|
||||
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 ®) {
|
||||
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 ®) {
|
||||
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 ®) {
|
||||
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 ®) {
|
||||
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 ®) {
|
||||
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 ®) {
|
||||
|
||||
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 ®,
|
||||
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 ®) {
|
||||
|
||||
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 ®) {
|
||||
|
||||
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 ®,
|
||||
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 ®) {
|
||||
|
||||
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 ®) {
|
||||
|
||||
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 ®,
|
||||
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 ®) {
|
||||
|
||||
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 ®) {
|
||||
|
||||
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 ®,
|
||||
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 ®) {
|
||||
|
||||
TASSERT(reg.isReg(), "");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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: \
|
||||
|
||||
@@ -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 ®) {
|
||||
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(), "");
|
||||
|
||||
+515
-544
File diff suppressed because it is too large
Load Diff
@@ -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,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() { }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+753
-726
File diff suppressed because it is too large
Load Diff
+181
-616
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
if("${TARGET}" STREQUAL "X86_64")
|
||||
add_subdirectory(x86_64)
|
||||
else()
|
||||
add_subdirectory(x86)
|
||||
endif("${TARGET}" STREQUAL "X86_64")
|
||||
@@ -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
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user