Showing preview only (813K chars total). Download the full file or copy to clipboard to get everything.
Repository: Boyan-MILANOV/ropgenerator
Branch: master
Commit: a9cbff211c17
Files: 58
Total size: 783.6 KB
Directory structure:
gitextract_uvwwhzll/
├── Dockerfile
├── Makefile
├── README.md
├── bin/
│ └── .gitignore
├── bindings/
│ ├── py_arch.cpp
│ ├── py_module.cpp
│ ├── py_ropchain.cpp
│ ├── py_ropium.cpp
│ ├── python_bindings.hpp
│ └── utils.cpp
├── cli-tool/
│ └── ropium
├── libropium/
│ ├── arch/
│ │ ├── arch.cpp
│ │ ├── archX86.cpp
│ │ └── disassembler.cpp
│ ├── compiler/
│ │ ├── compiler.cpp
│ │ ├── il.cpp
│ │ ├── strategy_graph.cpp
│ │ ├── strategy_rules.cpp
│ │ └── systems.cpp
│ ├── database/
│ │ └── database.cpp
│ ├── dependencies/
│ │ └── murmur3/
│ │ ├── murmur3.c
│ │ └── murmur3.h
│ ├── include/
│ │ ├── arch.hpp
│ │ ├── assertion.hpp
│ │ ├── compiler.hpp
│ │ ├── constraint.hpp
│ │ ├── database.hpp
│ │ ├── disassembler.hpp
│ │ ├── exception.hpp
│ │ ├── expression.hpp
│ │ ├── il.hpp
│ │ ├── ir.hpp
│ │ ├── ropchain.hpp
│ │ ├── ropium.hpp
│ │ ├── simplification.hpp
│ │ ├── strategy.hpp
│ │ ├── symbolic.hpp
│ │ ├── systems.hpp
│ │ └── utils.hpp
│ ├── ir/
│ │ └── ir.cpp
│ ├── ropchain/
│ │ ├── assertion.cpp
│ │ ├── constraint.cpp
│ │ ├── gadget.cpp
│ │ └── ropchain.cpp
│ ├── symbolic/
│ │ ├── expression.cpp
│ │ ├── simplification.cpp
│ │ └── symbolic.cpp
│ └── utils/
│ └── utils.cpp
└── tests/
├── ressources/
│ └── gadgets.txt
├── test_all.cpp
├── test_compiler.cpp
├── test_database.cpp
├── test_expression.cpp
├── test_gadgets.cpp
├── test_il.cpp
├── test_ir.cpp
├── test_simplification.cpp
└── test_strategy.cpp
================================================
FILE CONTENTS
================================================
================================================
FILE: Dockerfile
================================================
FROM python:3.7.3-slim-stretch
RUN pip3 install prompt_toolkit==2.0.9 \
# https://github.com/lief-project/packages/raw/lief-master-latest/pylief-0.9.0.dev.zip \
capstone \
https://github.com/JonathanSalwan/ROPgadget/archive/v5.9.zip \
&& apt-get update && apt-get install -y --no-install-recommends \
# g++ \
libmagic1 \
make \
libcapstone-dev \
&& rm -rf /var/lib/apt/lists/* /root/.cache
COPY . ropium/
# At the expense of a larger image size, recompilation of ropium can be
# performed without reinstalling g++ (and thus without an active internet
# connection) by uncommenting the previous g++ installation and removing the
# apt-get commands of the following RUN
RUN apt-get update && apt-get install -y --no-install-recommends g++ \
&& cd ropium && make && make test && make install \
&& cd .. && rm -rf ropium \
&& apt-get -y remove g++ \
&& apt-get purge -y --autoremove \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["ropium"]
================================================
FILE: Makefile
================================================
CC = gcc
CXX = g++
OUTDIR = ./bin
LIB_FILE = libropium.so
LIB_HEADER_FILE = ropium.hpp
BINDINGS_FILE = ropium.so
## Basic default flags
CFLAGS ?=
CXXFLAGS ?=
CXXFLAGS ?=
LDFLAGS ?=
LDLIBS ?=
LDLIBS += -lcapstone
## Flags for debug mode
DEBUG ?= 0
ifeq ($(DEBUG), 1)
CFLAGS += -g -O0
CXXFLAGS += -g -O0
LDFLAGS += -g
else
CFLAGS += -O2
CXXFLAGS += -O2 -Wno-narrowing
endif
## Bindings
BINDINGS ?= 1
ifeq ($(BINDINGS), 1)
CXXFLAGS += `python3-config --cflags` -DPYTHON_BINDINGS -Ibindings/python
BINDINGS_DIR = ./bindings
BINDINGS_SRCS = $(wildcard $(BINDINGS_DIR)/*.cpp)
BINDINGS_OBJS = $(BINDINGS_SRCS:.cpp=.o)
BINDINGS_RULE = bindings
LDLIBS += `python3-config --libs`
else
BINDINGS_RULE =
endif
SRCDIR=./libropium
## Final C++ flags
CXXFLAGS += -std=c++11 -fpermissive -fPIC -I $(SRCDIR)/include -I $(SRCDIR)/dependencies/murmur3 -Wno-write-strings -Wno-sign-compare -Wno-reorder
# Source files
SRCS=$(wildcard $(SRCDIR)/symbolic/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/ir/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/arch/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/ropchain/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/utils/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/database/*.cpp)
SRCS+=$(wildcard $(SRCDIR)/compiler/*.cpp)
OBJS=$(SRCS:.cpp=.o)
TESTDIR = ./tests
TESTSRCS = $(wildcard $(TESTDIR)/*.cpp)
TESTOBJS = $(TESTSRCS:.cpp=.o)
DEPDIR = $(SRCDIR)/dependencies
DEPSRCS = $(DEPDIR)/murmur3/murmur3.c
DEPOBJS = $(DEPSRCS:.c=.o)
INCLUDEDIR = $(SRCDIR)/include
# Compile lib and tests
all: lib tests $(BINDINGS_RULE)
# librop
lib: $(OBJS) $(DEPOBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(OUTDIR)/$(LIB_FILE) -shared $(OBJS) $(DEPOBJS) $(LDLIBS)
# unit tests
tests: $(TESTOBJS) $(OBJS) $(DEPOBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(OUTDIR)/tests $(TESTOBJS) $(OBJS) $(DEPOBJS) $(LDLIBS)
# bindings
bindings: $(BINDINGS_OBJS) $(OBJS) $(DEPOBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(OUTDIR)/$(BINDINGS_FILE) -shared $(BINDINGS_OBJS) $(OBJS) $(DEPOBJS) $(LDLIBS)
# generic
%.o : %.cpp
$(CXX) $(CXXFLAGS) $(LDFLAGS) -c $< -o $@ $(LDLIBS)
%.o : %.c
$(CC) $(CFLAGS) $(LDFLAGS) -c $< -o $@ $(LDLIBS)
# Installation (assuming Linux system)
# If prefix not set, set default
ifeq ($(PREFIX),)
PREFIX = /usr
endif
INSTALL_MESSAGE_RULE=
# Check if lib and binding files exist
ifneq (,$(wildcard ./bin/$(LIB_FILE)))
INSTALL_LIB_RULE=install_lib
INSTALL_MESSAGE_RULE=print_install_message
else
INSTALL_LIB_RULE=
endif
ifneq (,$(wildcard ./bin/$(BINDINGS_FILE)))
INSTALL_BINDINGS_RULE=install_bindings
PYTHONDIR=$(shell python3 -m site --user-site)/
INSTALL_MESSAGE_RULE=print_install_message
else
INSTALL_BINDINGS_RULE=
endif
# make install command
install: $(INSTALL_LIB_RULE) $(INSTALL_BINDINGS_RULE) install_cli_tool $(INSTALL_MESSAGE_RULE)
install_lib:
install -d $(DESTDIR)$(PREFIX)/lib/
install -D $(OUTDIR)/$(LIB_FILE) $(DESTDIR)$(PREFIX)/lib/
install -d $(DESTDIR)$(PREFIX)/include/
install -D $(INCLUDEDIR)/$(LIB_HEADER_FILE) $(DESTDIR)$(PREFIX)/include/
install_bindings:
install -d $(PYTHONDIR)
install -D $(OUTDIR)/$(BINDINGS_FILE) $(PYTHONDIR)
install_cli_tool:
install -d $(DESTDIR)$(PREFIX)/bin/
install -D cli-tool/ropium $(DESTDIR)$(PREFIX)/bin/
print_install_message:
@echo "\nROPium was successfully installed."
# make test command
test:
$(OUTDIR)/tests
# cleaning
cleanall: clean
clean:
rm -f $(OBJS)
rm -f $(DEPOBJS)
rm -f $(TESTOBJS)
rm -f $(BINDINGS_OBJS)
rm -f `find . -type f -name "*.gch"`
rm -f $(OUTDIR)/*
================================================
FILE: README.md
================================================
<p align="center" >
<img width=50% src="/ressources/ropium_logo.png"/><br /><br /><br />
</p>
# About
**ROPium** (ex-ROPGenerator) is a library/tool that makes ROP-exploits easy. It automatically extracts and analyses gadgets from binaries and
lets you find ROP-chains with semantic queries. ROPium supports *X86* and *X64* architectures, soon to be
extended with *ARM*.
Key features:
- **Effortless**: ROPium works out-of-the-box with a smooth Command Line Interface
- **Python API**: It is easy to integrate ROPium in script thanks to its python API
- **Automatic chaining**: ROPium automatically combines gadgets to create complex ROP-chains
- **Advanced features**: ROPium supports function calls for various ABIs, syscalls, ...
- **Semantic queries**: ROPium queries are quick and convenient to write : ``rax=rbx+8``, ``[rdi+0x20]=rax``, ``rsi=[rbx+16]``, ``0x08040212(1, 2, rax)``, ``[0xdeadbeaf] = "/bin/sh\x00"``, ``sys_execve(0xdeadbeef, 0, 0)``, ``sys_0x1(0)``, ``...``
# Content
- [About](#about)
- [Installation](#installation)
- [Getting started](#getting-started)
- [CLI tool](#cli-tool)
- [Python API](#python-api)
- [Docker](#docker)
- [Contact](#contact)
- [Licence](#licence)
- [Special thanks](#special-thanks)
# Installation
First install the [Capstone](https://github.com/aquynh/capstone) disassembly framework:
sudo apt-get install libcapstone-dev
You also need the latest [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) release:
git clone https://github.com/JonathanSalwan/ROPgadget && cd ROPgadget
python setup.py install --user
To use the CLI tool, install [prompt_toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit):
pip3 install prompt_toolkit
Finally install **ROPium**:
git clone https://github.com/Boyan-MILANOV/ropium && cd ropium
make
make test
sudo make install
# Getting started
### CLI tool
Thanks to a Command-Line-Interface wrapper, you can use ROPium interactively to quickly build ropchains:
<p align="center">
<img src="/ressources/ropium.gif" width="800" align="middle">
</p>
### Python API
Do you need to integrate ropchains directly in your scripts ? Good news, ROPium has a python API !
Loading a binary and finding ropchains:
```Python
from ropium import *
rop = ROPium(ARCH.X64)
rop.load('/lib/x86_64-linux-gnu/libc-2.27.so')
chain = rop.compile('rbx = [rax + 0x20]')
```
Dumping a ropchain in various formats:
```Python
>>> print( chain.dump() )
0x000000000009a851 (sub rax, 0x10; ret)
0x0000000000130018 (mov rax, qword ptr [rax + 0x30]; ret)
0x0000000000052240 (push rax; pop rbx; ret)
>>> print(chain.dump('python'))
from struct import pack
off = 0x0
p = ''
p += pack('<Q', 0x000000000009a851+off) # sub rax, 0x10; ret
p += pack('<Q', 0x0000000000130018+off) # mov rax, qword ptr [rax + 0x30]; ret
p += pack('<Q', 0x0000000000052240+off) # push rax; pop rbx; ret
>>> print(chain.dump('raw'))
b'Q\xa8\t\x00\x00\x00\x00\x00\x18\x00\x13\x00\x00\x00\x00\x00@"\x05\x00\x00\x00\x00\x00'
```
Set constraints on ropchains:
```Python
# Bytes that should not appear in the ropchain
rop.bad_bytes = [0x00, 0x0a, 0x0b]
# Register that should not be clobbered by the ropchain
rop.keep_regs = ['rsi', 'rdx']
# Enable/Forbid ropchain to dereference registers that might hold invalid addresses
# Safe mode is 'True' by default
rop.safe_mem = False
# Specify which ABI you want to use when calling functions
rop.abi = ABI.X86_CDECL
# Specify which system to target when doing syscalls
rop.os = OS.LINUX
```
# Docker
If needed you can run ROPium in a docker container. The container can be generated from the *Dockerfile* as
follows:
```bash
# Create your docker image (this will take time!)
docker build . --tag ropium
# Run the image in interactive mode, bind mounting the file to analyze
docker run --rm -it -v /FULL/HOST/PATH/FILE:/tmp/FILE:ro ropium
(ropium)> load -a X86 /tmp/FILE
```
The actual image is around 200 MB based on a Debian Stretch with a Python 3.7.3 installed.
# Contact
**Boyan MILANOV** - boyan.milanov (at) hotmail (dot) fr
# Licence
ROPium is provided under the MIT licence.
# Special thanks
Contributors:
- Docker container support: [migounette](https://github.com/migounette), [clslgrnc](https://github.com/clslgrnc)
ROPium uses the following awesome projects:
- [capstone](https://github.com/aquynh/capstone) : Disassembly Framework
- [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) : Gadget extractor
- [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) : Python CLI interface library
================================================
FILE: bin/.gitignore
================================================
# Ignore everything in this directory
*
# Except this file
!.gitignore
================================================
FILE: bindings/py_arch.cpp
================================================
#include "python_bindings.hpp"
#include "arch.hpp"
#include "compiler.hpp"
void init_arch(PyObject* module){
/* ARCH enum */
PyObject* arch_enum = PyDict_New();
PyDict_SetItemString(arch_enum, "X86", PyLong_FromLong((int)ArchType::X86));
PyDict_SetItemString(arch_enum, "X64", PyLong_FromLong((int)ArchType::X64));
PyDict_SetItemString(arch_enum, "ARM32", PyLong_FromLong((int)ArchType::ARM32));
PyDict_SetItemString(arch_enum, "ARM64", PyLong_FromLong((int)ArchType::ARM64));
PyObject* arch_class = create_class(PyUnicode_FromString("ARCH"), PyTuple_New(0), arch_enum);
PyModule_AddObject(module, "ARCH", arch_class);
/* OS enum */
PyObject* os_enum = PyDict_New();
PyDict_SetItemString(os_enum, "LINUX", PyLong_FromLong((int)System::LINUX));
PyDict_SetItemString(os_enum, "WINDOWS", PyLong_FromLong((int)System::WINDOWS));
PyDict_SetItemString(os_enum, "NONE", PyLong_FromLong((int)System::NONE));
PyObject* os_class = create_class(PyUnicode_FromString("OS"), PyTuple_New(0), os_enum);
PyModule_AddObject(module, "OS", os_class);
/* ABI enum */
PyObject* abi_enum = PyDict_New();
PyDict_SetItemString(abi_enum, "X86_CDECL", PyLong_FromLong((int)ABI::X86_CDECL));
PyDict_SetItemString(abi_enum, "X86_STDCALL", PyLong_FromLong((int)ABI::X86_STDCALL));
PyDict_SetItemString(abi_enum, "X64_SYSTEM_V", PyLong_FromLong((int)ABI::X64_SYSTEM_V));
PyDict_SetItemString(abi_enum, "X64_MS", PyLong_FromLong((int)ABI::X64_MS));
PyDict_SetItemString(abi_enum, "NONE", PyLong_FromLong((int)ABI::NONE));
PyObject* abi_class = create_class(PyUnicode_FromString("ABI"), PyTuple_New(0), abi_enum);
PyModule_AddObject(module, "ABI", abi_class);
/* X86 registers enum */
PyObject* x86_enum = PyDict_New();
PyDict_SetItemString(x86_enum, "EAX", PyLong_FromLong(X86_EAX));
PyDict_SetItemString(x86_enum, "EBX", PyLong_FromLong(X86_EBX));
PyDict_SetItemString(x86_enum, "ECX", PyLong_FromLong(X86_ECX));
PyDict_SetItemString(x86_enum, "EDX", PyLong_FromLong(X86_EDX));
PyDict_SetItemString(x86_enum, "EDI", PyLong_FromLong(X86_EDI));
PyDict_SetItemString(x86_enum, "ESI", PyLong_FromLong(X86_ESI));
PyDict_SetItemString(x86_enum, "EBP", PyLong_FromLong(X86_EBP));
PyDict_SetItemString(x86_enum, "ESP", PyLong_FromLong(X86_ESP));
PyDict_SetItemString(x86_enum, "EIP", PyLong_FromLong(X86_EIP));
PyDict_SetItemString(x86_enum, "CS", PyLong_FromLong(X86_CS));
PyDict_SetItemString(x86_enum, "DS", PyLong_FromLong(X86_DS));
PyDict_SetItemString(x86_enum, "ES", PyLong_FromLong(X86_ES));
PyDict_SetItemString(x86_enum, "FS", PyLong_FromLong(X86_FS));
PyDict_SetItemString(x86_enum, "GS", PyLong_FromLong(X86_GS));
PyDict_SetItemString(x86_enum, "SS", PyLong_FromLong(X86_SS));
PyDict_SetItemString(x86_enum, "CF", PyLong_FromLong(X86_CF));
PyDict_SetItemString(x86_enum, "PF", PyLong_FromLong(X86_PF));
PyDict_SetItemString(x86_enum, "AF", PyLong_FromLong(X86_AF));
PyDict_SetItemString(x86_enum, "ZF", PyLong_FromLong(X86_ZF));
PyDict_SetItemString(x86_enum, "SF", PyLong_FromLong(X86_SF));
PyDict_SetItemString(x86_enum, "TF", PyLong_FromLong(X86_TF));
PyDict_SetItemString(x86_enum, "IF", PyLong_FromLong(X86_IF));
PyDict_SetItemString(x86_enum, "DF", PyLong_FromLong(X86_DF));
PyDict_SetItemString(x86_enum, "OF", PyLong_FromLong(X86_OF));
PyDict_SetItemString(x86_enum, "IOPL", PyLong_FromLong(X86_IOPL));
PyDict_SetItemString(x86_enum, "NT", PyLong_FromLong(X86_NT));
PyDict_SetItemString(x86_enum, "RF", PyLong_FromLong(X86_RF));
PyDict_SetItemString(x86_enum, "VM", PyLong_FromLong(X86_VM));
PyDict_SetItemString(x86_enum, "AC", PyLong_FromLong(X86_AC));
PyDict_SetItemString(x86_enum, "VIF", PyLong_FromLong(X86_VIF));
PyDict_SetItemString(x86_enum, "VIP", PyLong_FromLong(X86_VIP));
PyDict_SetItemString(x86_enum, "ID", PyLong_FromLong(X86_ID));
PyDict_SetItemString(x86_enum, "TSC", PyLong_FromLong(X86_TSC));
PyDict_SetItemString(x86_enum, "NB_REGS", PyLong_FromLong(X86_NB_REGS));
PyObject* x86_class = create_class(PyUnicode_FromString("X86"), PyTuple_New(0), arch_enum);
PyModule_AddObject(module, "X86", x86_class);
/* X64 registers enum */
PyObject* x64_enum = PyDict_New();
PyDict_SetItemString(x64_enum, "RAX", PyLong_FromLong(X64_RAX));
PyDict_SetItemString(x64_enum, "RBX", PyLong_FromLong(X64_RBX));
PyDict_SetItemString(x64_enum, "RCX", PyLong_FromLong(X64_RCX));
PyDict_SetItemString(x64_enum, "RDX", PyLong_FromLong(X64_RDX));
PyDict_SetItemString(x64_enum, "RDI", PyLong_FromLong(X64_RDI));
PyDict_SetItemString(x64_enum, "RSI", PyLong_FromLong(X64_RSI));
PyDict_SetItemString(x64_enum, "RBP", PyLong_FromLong(X64_RBP));
PyDict_SetItemString(x64_enum, "RSP", PyLong_FromLong(X64_RSP));
PyDict_SetItemString(x64_enum, "RIP", PyLong_FromLong(X64_RIP));
PyDict_SetItemString(x64_enum, "R8", PyLong_FromLong(X64_R8));
PyDict_SetItemString(x64_enum, "R9", PyLong_FromLong(X64_R9));
PyDict_SetItemString(x64_enum, "R10", PyLong_FromLong(X64_R10));
PyDict_SetItemString(x64_enum, "R11", PyLong_FromLong(X64_R11));
PyDict_SetItemString(x64_enum, "R12", PyLong_FromLong(X64_R12));
PyDict_SetItemString(x64_enum, "R13", PyLong_FromLong(X64_R13));
PyDict_SetItemString(x64_enum, "R14", PyLong_FromLong(X64_R14));
PyDict_SetItemString(x64_enum, "R15", PyLong_FromLong(X64_R15));
PyDict_SetItemString(x64_enum, "CS", PyLong_FromLong(X64_CS));
PyDict_SetItemString(x64_enum, "DS", PyLong_FromLong(X64_DS));
PyDict_SetItemString(x64_enum, "ES", PyLong_FromLong(X64_ES));
PyDict_SetItemString(x64_enum, "FS", PyLong_FromLong(X64_FS));
PyDict_SetItemString(x64_enum, "GS", PyLong_FromLong(X64_GS));
PyDict_SetItemString(x64_enum, "SS", PyLong_FromLong(X64_SS));
PyDict_SetItemString(x64_enum, "CF", PyLong_FromLong(X64_CF));
PyDict_SetItemString(x64_enum, "PF", PyLong_FromLong(X64_PF));
PyDict_SetItemString(x64_enum, "AF", PyLong_FromLong(X64_AF));
PyDict_SetItemString(x64_enum, "ZF", PyLong_FromLong(X64_ZF));
PyDict_SetItemString(x64_enum, "SF", PyLong_FromLong(X64_SF));
PyDict_SetItemString(x64_enum, "TF", PyLong_FromLong(X64_TF));
PyDict_SetItemString(x64_enum, "IF", PyLong_FromLong(X64_IF));
PyDict_SetItemString(x64_enum, "DF", PyLong_FromLong(X64_DF));
PyDict_SetItemString(x64_enum, "OF", PyLong_FromLong(X64_OF));
PyDict_SetItemString(x64_enum, "IOPL", PyLong_FromLong(X64_IOPL));
PyDict_SetItemString(x64_enum, "NT", PyLong_FromLong(X64_NT));
PyDict_SetItemString(x64_enum, "RF", PyLong_FromLong(X64_RF));
PyDict_SetItemString(x64_enum, "VM", PyLong_FromLong(X64_VM));
PyDict_SetItemString(x64_enum, "AC", PyLong_FromLong(X64_AC));
PyDict_SetItemString(x64_enum, "VIF", PyLong_FromLong(X64_VIF));
PyDict_SetItemString(x64_enum, "VIP", PyLong_FromLong(X64_VIP));
PyDict_SetItemString(x64_enum, "ID", PyLong_FromLong(X64_ID));
PyDict_SetItemString(x64_enum, "TSC", PyLong_FromLong(X64_TSC));
PyDict_SetItemString(x64_enum, "NB_REGS", PyLong_FromLong(X64_NB_REGS));
PyObject* x64_class = create_class(PyUnicode_FromString("X64"), PyTuple_New(0), arch_enum);
PyModule_AddObject(module, "X64", x64_class);
};
================================================
FILE: bindings/py_module.cpp
================================================
#include "Python.h"
#include "python_bindings.hpp"
/* Module methods */
PyMethodDef module_methods[] = {
{"ROPium", (PyCFunction)ropium_ROPium, METH_VARARGS, "Create a new ROPium instance"},
{NULL}
};
/* Module information */
PyModuleDef ropium_module_def = {
PyModuleDef_HEAD_INIT,
"ropium",
nullptr,
-1, // m_size
module_methods, // m_methods
nullptr, // m_slots
nullptr, // m_traverse
nullptr, // m_clear
nullptr // m_free
};
PyMODINIT_FUNC PyInit_ropium(){
Py_Initialize();
PyObject* module = PyModule_Create(&ropium_module_def);
init_arch(module);
init_ropchain(module);
return module;
}
================================================
FILE: bindings/py_ropchain.cpp
================================================
#include "python_bindings.hpp"
#include <cstdio>
/* -------------------------------------
* ROPChain object
* ------------------------------------ */
static void ropchain_dealloc(PyObject* self){
delete ((ropchain_Object*)self)->ropchain; ((ropchain_Object*)self)->ropchain = nullptr;
Py_TYPE(self)->tp_free((PyObject *)self);
};
static PyObject* ropchain_str(PyObject* self){
stringstream ss;
ss << *(as_ropchain_object(self).ropchain);
return PyUnicode_FromString(ss.str().c_str());
};
static int ropchain_print(PyObject* self){
std::cout << *(as_ropchain_object(self).ropchain);
return 0;
};
static PyObject* ropchain_repr(PyObject* self){
return ropchain_str(self);
};
static PyObject* ropchain_dump(PyObject* self, PyObject* args, PyObject* keywords){
char* arg = "pretty"; // Default
string fmt;
stringstream ss;
int color = 1;
vector<uint8_t> raw;
PyObject* res;
char* tab = "";
char* keywd[] = {"", "tab", "color", NULL};
if( ! PyArg_ParseTupleAndKeywords(args, keywords, "|ssp", keywd, &arg, &tab, &color)){
return NULL;
}
fmt = string(arg);
if(!color){
disable_colors();
}
if( fmt == "pretty" ){
as_ropchain_object(self).ropchain->print_pretty(ss, string(tab));
res = PyUnicode_FromString(ss.str().c_str());
}else if( fmt == "python" ){
as_ropchain_object(self).ropchain->print_python(ss, string(tab));
res = PyUnicode_FromString(ss.str().c_str());
}else if( fmt == "raw" ){
as_ropchain_object(self).ropchain->dump_raw(raw);
// Translate vector into python bytes
res = PyBytes_FromStringAndSize((char*)raw.data(), raw.size());
}else
return PyErr_Format(PyExc_ValueError, "Unknown dump format: %s", arg);
enable_colors();
if( res == NULL ){
return PyErr_Format(PyExc_RuntimeError, "%s", "Failed to dump ropchain");
}
return res;
}
static PyMethodDef ropchain_methods[] = {
{"dump", (PyCFunction)ropchain_dump, METH_VARARGS | METH_KEYWORDS, "dump(fmt='pretty', tab='', color=True) \nDump the ropchain in various formats. Available formats: 'pretty', 'python', 'raw'"},
{NULL, NULL, 0, NULL}
};
static PyMemberDef ropchain_members[] = {
{NULL}
};
static PyNumberMethods ropchain_operators; // Empty PyNumberMethods, will be filled in the init function
/* Type description for python Expr objects */
PyTypeObject ropchain_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"ropchain", /* tp_name */
sizeof(ropchain_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)ropchain_dealloc, /* tp_dealloc */
(printfunc)ropchain_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
ropchain_repr, /* tp_repr */
&ropchain_operators, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
ropchain_str, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"ROPChain object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
ropchain_methods, /* tp_methods */
ropchain_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
PyObject* get_ropchain_Type(){
return (PyObject*)&ropchain_Type;
};
/* Constructor */
PyObject* Pyropchain_FromROPChain(ROPChain* chain){
ropchain_Object* object;
// Create object
PyType_Ready(&ropchain_Type);
object = PyObject_New(ropchain_Object, &ropchain_Type);
if( object != nullptr ){
object->ropchain = chain;
}
return (PyObject*)object;
}
// Adding two ropchains
/* Number methods & Various Constructors */
static PyObject* ropchain_nb_add(PyObject* self, PyObject *other){
if( ! PyObject_IsInstance(other, (PyObject*)&(ropchain_Type))){
return PyErr_Format(PyExc_TypeError, "Mismatching types for operator '+'");
}
ROPChain * rop = new ROPChain(as_ropchain_object(self).ropchain->arch);
rop->add_chain(*(as_ropchain_object(self).ropchain));
rop->add_chain(*(as_ropchain_object(other).ropchain));
return Pyropchain_FromROPChain(rop);
}
/* -------------------------------------
* Init function
* ------------------------------------ */
void init_ropchain(PyObject* module){
/* Add number operators to ropchain */
ropchain_operators.nb_add = ropchain_nb_add;
}
================================================
FILE: bindings/py_ropium.cpp
================================================
#include "python_bindings.hpp"
#include <cstdio>
#include <fstream>
/* -------------------------------------
* ROPium object
* ------------------------------------ */
static void ROPium_dealloc(PyObject* self){
delete ((ROPium_Object*)self)->compiler; ((ROPium_Object*)self)->compiler = nullptr;
delete ((ROPium_Object*)self)->arch; ((ROPium_Object*)self)->arch = nullptr;
delete ((ROPium_Object*)self)->gadget_db; ((ROPium_Object*)self)->gadget_db = nullptr;
delete ((ROPium_Object*)self)->constraint; ((ROPium_Object*)self)->constraint = nullptr;
Py_TYPE(self)->tp_free((PyObject *)self);
};
static PyObject* ROPium_load(PyObject* self, PyObject* args){
const char* filename;
int filename_len;
int filenum = 0;
stringstream ss;
string gadget_file;
string ropgadget_tmp_file;
int max_filenum = 0x7fffffff;
vector<RawGadget>* raw = nullptr;
if( ! PyArg_ParseTuple(args, "s#", &filename, &filename_len) ){
return NULL;
}
// Get available file to dump gadgets
for( filenum = 0; filenum < max_filenum; filenum++){
ss.str("");
ss << ".ropium_raw_gadgets." << filenum;
gadget_file = ss.str();
// Test if file exists
std::ifstream fin(gadget_file);
if( !fin ){
break; // File doesn't exist
}else{
fin.close(); // Try next filenum
}
}
if( filenum == max_filenum ){
return PyErr_Format(PyExc_RuntimeError, "Couldn't create new file where to dump gadgets");
}
ss.str("");
ss << ".ropgadget_output." << filenum,
ropgadget_tmp_file = ss.str();
try{
// Try to load binary and get gadgets using ROPgadget for now
if( ! ropgadget_to_file(gadget_file, ropgadget_tmp_file, filename)){
return PyErr_Format(PyExc_RuntimeError, "Couldn't analyse binary with ROPgadget");
}
raw = raw_gadgets_from_file(gadget_file);
as_ropium_object(self).gadget_db->analyse_raw_gadgets(*raw, as_ropium_object(self).arch);
delete raw; raw = nullptr;
remove(gadget_file.c_str());
remove(ropgadget_tmp_file.c_str());
}catch(runtime_exception& e){
return PyErr_Format(PyExc_RuntimeError, "%s", e.what());
}
Py_RETURN_NONE;
};
static PyObject* ROPium_compile(PyObject* self, PyObject* args){
const char* query;
int query_len;
ROPChain* ropchain;
if( ! PyArg_ParseTuple(args, "s#", &query, &query_len) ){
return NULL;
}
try{
ropchain = as_ropium_object(self).compiler->compile( string(query, query_len),
as_ropium_object(self).constraint, as_ropium_object(self).abi, as_ropium_object(self).system);
if( ropchain ){
return Pyropchain_FromROPChain(ropchain);
}
}catch(il_exception& e){
return PyErr_Format(PyExc_ValueError, "%s", e.what());
}catch(runtime_exception& e){
return PyErr_Format(PyExc_RuntimeError, "%s", e.what());
}catch(compiler_exception& e){
return PyErr_Format(PyExc_RuntimeError, "%s", e.what());
}
Py_RETURN_NONE;
};
static PyMethodDef ROPium_methods[] = {
{"load", (PyCFunction)ROPium_load, METH_VARARGS, "load(<filename>) \nLoad and analyse gadgets from a binary"},
{"compile", (PyCFunction)ROPium_compile, METH_VARARGS, "compile(<query>) \nCompile a semantic query into a ropchain"},
{NULL, NULL, 0, NULL}
};
// Get/Set Attributes
static PyObject* ROPium_get_bad_bytes(PyObject* self, void* closure){
PyObject* list;
list = PyList_New(0);
if( list == NULL ){
return PyErr_Format(PyExc_RuntimeError, "%s", "Failed to create new python list");
}
// Add bad bytes to list
for (int i = 0; i < 0x100; i++){
if( !as_ropium_object(self).constraint->bad_bytes.is_valid_byte(i) ){
if( PyList_Append(list, PyLong_FromLong(i)) == -1){
return PyErr_Format(PyExc_RuntimeError, "%s", "Failed to add bad byte to python list");
}
}
}
return list;
}
static int ROPium_set_bad_bytes(PyObject* self, PyObject* list, void* closure){
PyObject *item;
Py_ssize_t size;
if( ! PyList_Check(list)){
PyErr_SetString(PyExc_RuntimeError, "Expected a list of integers");
return -1;
}
size = PyList_Size(list);
// Clear previous bad bytes
as_ropium_object(self).constraint->bad_bytes.clear();
// Add new bad bytes
for( int i = 0; i < size; i++){
item = PyList_GetItem(list, i);
if( item == NULL ){
PyErr_SetString(PyExc_RuntimeError, "Error getting item in supplied list");
return -1;
}
if( ! PyLong_Check(item) || PyLong_AsUnsignedLong(item) > 0xff ){
PyErr_SetString(PyExc_ValueError, "Bad bytes list has incorrect element(s)");
return -1;
}
// Add bad byte
as_ropium_object(self).constraint->bad_bytes.add_bad_byte(PyLong_AsUnsignedLong(item));
}
return 0;
}
static PyObject* ROPium_get_safe_mem(PyObject* self, void* closure){
if( as_ropium_object(self).constraint->mem_safety.is_enforced())
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static int ROPium_set_safe_mem(PyObject* self, PyObject* val, void* closure){
if( ! PyBool_Check(val)){
PyErr_SetString(PyExc_RuntimeError, "Excepted a boolean value");
return -1;
}
if( val == Py_True ){
as_ropium_object(self).constraint->mem_safety.force_safe();
}else{
as_ropium_object(self).constraint->mem_safety.enable_unsafe();
}
return 0;
}
static PyObject* ROPium_get_keep_regs(PyObject* self, void* closure){
PyObject* list;
list = PyList_New(0);
if( list == NULL ){
return PyErr_Format(PyExc_RuntimeError, "%s", "Failed to create new python list");
}
// Add bad bytes to list
for (int i = 0; i < as_ropium_object(self).arch->nb_regs; i++){
if( as_ropium_object(self).constraint->keep_regs.is_kept(i) ){
if( PyList_Append(list, PyUnicode_FromString( as_ropium_object(self).arch->reg_name(i).c_str())) == -1){
return PyErr_Format(PyExc_RuntimeError, "%s", "Failed to add register name to python list");
}
}
}
return list;
}
static int ROPium_set_keep_regs(PyObject* self, PyObject* list, void* closure){
PyObject *item;
Py_ssize_t size;
string name;
int reg_num;
if( ! PyList_Check(list)){
PyErr_SetString(PyExc_RuntimeError, "Expected a list of str");
return -1;
}
size = PyList_Size(list);
// Clear previous regs
as_ropium_object(self).constraint->keep_regs.clear();
// Add new regs
for( int i = 0; i < size; i++){
item = PyList_GetItem(list, i);
if( item == NULL ){
PyErr_SetString(PyExc_RuntimeError, "Error getting item in supplied list");
return -1;
}
if( ! PyUnicode_Check(item) ){
PyErr_SetString(PyExc_ValueError, "Registers must be specified as strings: 'eax', 'ebx', ...");
return -1;
}
name = string((char*)PyUnicode_DATA(item));
try{
reg_num = as_ropium_object(self).arch->reg_num(name);
}catch(runtime_exception& e){
PyErr_Format(PyExc_ValueError, "Invalid register: %s", name.c_str());
return -1;
}
// Add keep reg
as_ropium_object(self).constraint->keep_regs.add_keep_reg(reg_num);
}
return 0;
}
static PyObject* ROPium_get_arch(PyObject* self, void* closure){
return PyLong_FromLong((int)(as_ropium_object(self).arch->type));
}
static PyObject* ROPium_get_abi(PyObject* self, void* closure){
return PyLong_FromLong((int)(as_ropium_object(self).abi));
}
static int ROPium_set_abi(PyObject* self, PyObject* val, void* closure){
int abi;
if( ! PyLong_Check(val)){
PyErr_SetString(PyExc_RuntimeError, "Argument should be a ABI.* enum value");
return -1;
}
abi = PyLong_AsLong(val);
as_ropium_object(self).abi = (ABI)abi;
return 0;
}
static PyObject* ROPium_get_os(PyObject* self, void* closure){
return PyLong_FromLong((int)(as_ropium_object(self).system));
}
static int ROPium_set_os(PyObject* self, PyObject* val, void* closure){
int system;
if( ! PyLong_Check(val)){
PyErr_SetString(PyExc_RuntimeError, "Argument should be a OS.* enum value");
return -1;
}
system = PyLong_AsLong(val);
as_ropium_object(self).system = (System)system;
return 0;
}
static PyGetSetDef ROPium_getset[] = {
{"bad_bytes", ROPium_get_bad_bytes, ROPium_set_bad_bytes, "Bad bytes that must not occur in the ropchains", NULL},
{"keep_regs", ROPium_get_keep_regs, ROPium_set_keep_regs, "Registers that should not be clobbered by the ropchains", NULL},
{"safe_mem", ROPium_get_safe_mem, ROPium_set_safe_mem, "Indicates whether ropchains can contain gadgets that perform potentially unsafe register dereferencing", NULL},
{"arch", ROPium_get_arch, NULL, "Architecture type", NULL},
{"abi", ROPium_get_abi, ROPium_set_abi, "ABI to use when calling functions", NULL},
{"os", ROPium_get_os, ROPium_set_os, "OS to target when doing syscalls", NULL},
{NULL}
};
static PyMemberDef ROPium_members[] = {
{NULL}
};
/* Type description for python Expr objects */
PyTypeObject ROPium_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"ROPium", /* tp_name */
sizeof(ROPium_Object), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)ROPium_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"ROPium: automatic ropchain finder", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
ROPium_methods, /* tp_methods */
ROPium_members, /* tp_members */
ROPium_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
PyObject* get_ROPium_Type(){
return (PyObject*)&ROPium_Type;
};
/* Constructor */
PyObject* ropium_ROPium(PyObject* self, PyObject* args){
ROPium_Object* object;
int arch;
// Parse arguments
if( ! PyArg_ParseTuple(args, "i", &arch) ){
return NULL;
}
// Create object
try{
PyType_Ready(&ROPium_Type);
object = PyObject_New(ROPium_Object, &ROPium_Type);
if( object != nullptr ){
// Set constraint
object->constraint = new Constraint();
// Set architecture
switch ( (ArchType)arch){
case ArchType::X86: as_ropium_object(object).arch = new ArchX86(); break;
case ArchType::X64: as_ropium_object(object).arch = new ArchX64(); break;
default: return PyErr_Format(PyExc_ValueError, "This architecture isn't supported yet");
}
// Set gadget db
as_ropium_object(object).gadget_db = new GadgetDB();
// Set compiler
as_ropium_object(object).compiler = new ROPCompiler(object->arch, (object->gadget_db));
as_ropium_object(object).abi = ABI::NONE;
as_ropium_object(object).system = System::NONE;
}
}catch(runtime_exception& e){
return PyErr_Format(PyExc_RuntimeError, "%s", e.what());
}
return (PyObject*)object;
}
================================================
FILE: bindings/python_bindings.hpp
================================================
#ifndef PYTHON_BINDINGS_INCLUDE_H
#define PYTHON_BINDINGS_INCLUDE_H
#include "Python.h"
#include "structmember.h"
#include "exception.hpp"
#include "arch.hpp"
#include "database.hpp"
#include "compiler.hpp"
#include "systems.hpp"
/* -------------------------------------------------
* Utils
* ------------------------------------------------- */
PyObject* create_class(PyObject* name, PyObject* bases, PyObject* dict);
/* --------------------------------------------------
* Arch
* -------------------------------------------------- */
void init_arch(PyObject* module);
/* --------------------------------------------------
* Ropium
* -------------------------------------------------- */
typedef struct{
PyObject_HEAD
Arch* arch;
GadgetDB* gadget_db;
ROPCompiler* compiler;
Constraint* constraint;
ABI abi;
System system;
} ROPium_Object;
PyObject* get_ROPium_Type();
PyObject* ropium_ROPium(PyObject* self, PyObject* args);
#define as_ropium_object(x) (*((ROPium_Object*)x))
/* --------------------------------------------------
* ROPChain
* -------------------------------------------------- */
void init_ropchain(PyObject* module);
typedef struct{
PyObject_HEAD
ROPChain* ropchain;
} ropchain_Object;
PyObject* get_ropchain_Type();
PyObject* Pyropchain_FromROPChain(ROPChain* chain);
#define as_ropchain_object(x) (*((ropchain_Object*)x))
#endif
================================================
FILE: bindings/utils.cpp
================================================
#include "python_bindings.hpp"
PyObject* create_class(PyObject* name, PyObject* bases, PyObject* dict){
PyObject* res = PyObject_CallFunctionObjArgs((PyObject*)&PyType_Type, name, bases, dict, NULL);
Py_CLEAR(name);
Py_CLEAR(bases);
Py_CLEAR(dict);
return res;
}
================================================
FILE: cli-tool/ropium
================================================
#!/usr/bin/env python3
from ropium import *
from prompt_toolkit import PromptSession, ANSI
import os
# Colors and util functions
MAIN_COLOR_ANSI = '\033[92m' # Default color
ERROR_COLOR_ANSI = '\033[91m'
BOLD_COLOR_ANSI = '\033[1m'
WARNING_COLOR_ANSI = '\033[93m'
SPECIAL_COLOR_ANSI = '\033[93m'
END_COLOR_ANSI = '\033[0m'
def str_bold(msg):
return BOLD_COLOR_ANSI + msg + END_COLOR_ANSI
def str_error(msg):
return ERROR_COLOR_ANSI + msg + END_COLOR_ANSI
def str_main(msg):
return MAIN_COLOR_ANSI + msg + END_COLOR_ANSI
def str_warning(msg):
return WARNING_COLOR_ANSI + msg + END_COLOR_ANSI
def str_special(msg):
return SPECIAL_COLOR_ANSI + msg + END_COLOR_ANSI
def error(msg, skip=False):
if skip:
print('')
print("\t[" + str_bold(str_error("!")) + "] " + msg)
def info(msg):
print("\t[" + str_main("+") + "] " + msg)
def warning(msg, skip=False):
if skip:
print('')
print("\t[" + str_bold(str_warning("!")) + "] " + msg)
compiler = None
bad_bytes = []
keep_regs = []
safe_mem = True
abi = ABI.NONE
system = OS.NONE
start_msg = "\n" + str_bold("ROPium") + " - v3.2\n"
# Commands
CMD_HELP = "help"
CMD_LOAD = "load"
CMD_FIND = "find"
CMD_BADBYTES = "badbytes"
CMD_KEEPREGS = "keepregs"
CMD_ABI = "abi"
CMD_OS = "os"
CMD_SAFEMEM = "safemem"
CMD_EXIT = "exit"
# Arch correspondance
str_to_arch = {"X86":ARCH.X86, "X64":ARCH.X64}
# Main function
def main():
print(start_msg)
finish = False
promptSession = PromptSession(ANSI(u"("+ str_main(u"ropium") +u")> "))
while( not finish ):
try:
user_input = promptSession.prompt()
args = user_input.split()
argslen = len(args)
if( argslen > 0 ):
command = args[0]
else:
command = None
continue
if( command == CMD_LOAD ):
try:
load(args[1:])
except LoadException as e:
error(str(e), skip=True)
elif( command == CMD_EXIT ):
finish = True
elif( command == CMD_HELP ):
if len(args) > 1:
if args[1] == "load":
print(load_help)
elif args[1] == "find":
print(find_help)
elif args[1] == "badbytes":
print(badbytes_help)
elif args[1] == "keepregs":
print(keepregs_help)
elif args[1] == "safemem":
print(safemem_help)
elif args[1] == "abi":
print(abi_help)
else:
print(main_help)
else:
print(main_help)
elif( command == CMD_FIND ):
try:
find(args[1:])
except FindException as e:
error(str(e), skip=True)
elif( command == CMD_BADBYTES ):
try:
badbytes(args[1:])
except ContextException as e:
error(str(e), skip=True)
elif( command == CMD_KEEPREGS ):
try:
keepregs(args[1:])
except ContextException as e:
error(str(e), skip=True)
elif( command == CMD_SAFEMEM ):
try:
safemem(args[1:])
except ContextException as e:
error(str(e), skip=True)
elif( command == CMD_ABI ):
try:
cmd_abi(args[1:])
except ContextException as e:
error(str(e), skip=True)
elif( command == CMD_OS ):
try:
cmd_os(args[1:])
except ContextException as e:
error(str(e), skip=True)
else:
error(f"Unknown command '{command}' (type 'help' for help)", skip=True)
print('')
except KeyboardInterrupt:
pass
except EOFError:
finish = True
print('Thanks for using ROPium !')
return
# Load command
class LoadException(Exception):
pass
def load(args):
global compiler
OPTIONS_ARCH = ['-a', '--arch']
OPTIONS_HELP = ['-h', '--help']
seen_arch = False
seen_filename = False
arch = None
filenames = []
compiler_was_none = False
# Parse arguments
if not args:
print(load_help)
return
i = 0
while i < len(args):
if args[i] in OPTIONS_ARCH:
if seen_arch:
raise LoadException(f"Option '{args[i]}' can be used only one time")
seen_arch = True
if( i+1 == len(args)):
raise LoadException(f"Missing argument after {args[i]}")
else:
arch = args[i+1]
i += 2
elif args[i] in OPTIONS_HELP:
print(load_help)
return
else:
filenames.append(args[i])
i += 1
# Check arguments
if not filenames:
raise LoadException("Missing filename")
if not arch and not compiler:
raise LoadException("Missing architecture")
if arch and (arch not in str_to_arch):
raise LoadException(f"Unsupported architecture: {arch}")
# Instanciate compiler if not already
if compiler is None:
compiler = ROPium(str_to_arch[arch])
compiler_was_none = True
elif compiler and arch and (str_to_arch[arch] != compiler.arch):
raise LoadException(f"Already working on a different architecture than '{arch}'")
loaded_at_least_one = False
print('') # So it's moar pretty
for f in filenames:
# Test if the file exists
if not os.path.isfile(f):
warning(f"Skipped: {f} (file doesn't exist)")
else:
compiler.load(f)
info(f"Loaded: {f}")
loaded_at_least_one = True
if compiler_was_none and not loaded_at_least_one:
compiler = None
# Find command
class FindException(Exception):
pass
def find(args):
global compiler
global bad_bytes
global keep_regs
global safemem
global abi
global system
if not compiler:
raise FindException("You must load a binary before finding ropchains")
query = "".join(args)
compiler.bad_bytes = bad_bytes
compiler.keep_regs = keep_regs
compiler.safe_mem = safe_mem
compiler.abi = abi
compiler.os = system
try:
ropchain = compiler.compile(query)
except ValueError as e:
raise FindException(str(e))
except RuntimeError as e:
raise FindException(str(e))
if ropchain:
print('')
print(ropchain.dump(tab="\t"))
else:
print("\n\tNo ROPChain found.")
# Badbytes command
class ContextException(Exception):
pass
def badbytes(args):
global compiler
if not args:
print(badbytes_help)
return
subcommand = args[0]
if subcommand == "set":
set_badbytes(args[1:])
elif subcommand == "reset":
reset_badbytes(args[1:])
else:
raise ContextException(f"Unsupported action '{subcommand}'")
def str_to_byte(s):
try:
return int(s, 10)
except:
try:
return int(s, 16)
except:
return None
def set_badbytes(args):
global bad_bytes
new_bad = []
for arg in args:
bad = str_to_byte(arg)
if bad is None or bad > 0xff:
raise ContextException(f"'{arg}' is not a valid byte")
new_bad.append(bad)
bad_bytes = new_bad
def reset_badbytes(args):
global bad_bytes
bad_bytes = []
# Keppregs command
def keepregs(args):
global compiler
if not args:
print(keepregs_help)
return
subcommand = args[0]
if subcommand == "set":
set_keepregs(args[1:])
elif subcommand == "reset":
reset_keepregs(args[1:])
else:
raise ContextException(f"Unsupported action '{subcommand}'")
reg_map = {
"eax":X86.EAX,
"ebx":X86.EBX,
"ecx":X86.ECX,
"edx":X86.EDX,
"esi":X86.ESI,
"edi":X86.EDI,
"esp":X86.ESP,
"ebp":X86.EBP,
"eip":X86.EIP,
"rax":X64.RAX,
"rbx":X64.RBX,
"rcx":X64.RBX,
"rdx":X64.RDX,
"rdi":X64.RDI,
"rsi":X64.RSI,
"rsp":X64.RSP,
"rbp":X64.RBP,
"rip":X64.RIP,
"r8":X64.R8,
"r9":X64.R9,
"r10":X64.R10,
"r11":X64.R11,
"r12":X64.R12,
"r13":X64.R13,
"r14":X64.R14,
"r15":X64.R15
}
def str_to_reg(s):
if s in reg_map:
return reg_map[s]
else:
return None
def set_keepregs(args):
global keep_regs
new_keep = []
for arg in args:
reg = str_to_reg(arg)
if reg is None:
raise ContextException(f"Register '{arg}' is not supported for 'keepregs'")
new_keep.append(arg)
keep_regs = new_keep
def reset_keepregs(args):
global keep_regs
keep_regs = []
# safemem command
def safemem(args):
global compiler
global safe_mem
if not args:
print(safemem_help)
return
subcommand = args[0]
if subcommand == "set":
safe_mem = True
elif subcommand == "unset":
safe_mem = False
else:
raise ContextException(f"Unsupported action '{subcommand}'")
if len(args) > 1:
args_str = ' '.join(args[1:])
warning(f"Extra arguments ignored: '{args_str}'", skip=True)
# ABI Command
str_to_abi = {
"X86_CDECL":ABI.X86_CDECL,
"X86_STDCALL":ABI.X86_STDCALL,
"X64_SYSTEM_V":ABI.X64_SYSTEM_V,
"X64_MS":ABI.X64_MS
}
def cmd_abi(args):
global compiler
if not args:
print(abi_help)
return
subcommand = args[0]
if subcommand == "set":
set_abi(args[1:])
else:
raise ContextException(f"Unsupported action '{subcommand}'")
def set_abi(args):
global abi
if not args:
raise ContextException(f"Missing ABI argument")
if args[0] not in str_to_abi:
raise ContextException(f"Unsupported ABI: '{args[0]}'")
else:
abi = str_to_abi[args[0]]
if len(args) > 1:
extra_args = ' '.join(args[1:])
warning(f"Extra arguments ignored: '{extra_args}'", skip=True)
# OS Command
str_to_os = {
"LINUX":OS.LINUX,
"WINDOWS":OS.WINDOWS
}
def cmd_os(args):
global compiler
if not args:
print(os_help)
return
subcommand = args[0]
if subcommand == "set":
set_os(args[1:])
else:
raise ContextException(f"Unsupported action '{subcommand}'")
def set_os(args):
global system
if not args:
raise ContextException(f"Missing OS argument")
if args[0] not in str_to_os:
raise ContextException(f"Unsupported Operating System: '{args[0]}'")
else:
system = str_to_os[args[0]]
if len(args) > 1:
extra_args = ' '.join(args[1:])
warning(f"Extra arguments ignored: '{extra_args}'", skip=True)
# Help strings
main_help = str_main(str_bold('\n\tMain Commands'))
main_help += str_special("\n\t(For more info about a command type 'help <cmd>')")
main_help += '\n\n\t' + str_bold(CMD_LOAD) + ': \t\tload gadgets from a binary file'
main_help += '\n\t' + str_bold(CMD_FIND) + ': \t\tFind ropchains using semantic queries'
main_help += '\n\n\t' + str_bold(CMD_BADBYTES) + ': \tSet bad bytes to be avoided in ropchains'
main_help += '\n\t' + str_bold(CMD_KEEPREGS) + ': \tSet registers that must not be clobbered'
main_help += '\n\t' + str_bold(CMD_SAFEMEM) + ': \tEnable/Disable the use of unsafe gadgets'
main_help += '\n\t' + str_bold(CMD_ABI) + ': \t\tSpecify the ABI to use when calling functions'
main_help += '\n\t' + str_bold(CMD_OS) + ': \t\tSpecify the OS to target when doing syscalls'
main_help += '\n\n\t' + str_bold(CMD_HELP) + ': \t\tshow this help'
main_help += '\n\t' + str_bold(CMD_EXIT) + ': \t\texit ROPium'
load_help = str_main(str_bold("\n\t'load' Command"))
load_help += str_special("\n\t(Load gadgets from a binary file)")
load_help += "\n\n\t"+str_bold("Usage")+":\tload [OPTIONS] <filename> [<filename> ...]"
load_help += "\n\n\t"+str_bold("Options")+":"
load_help += str_special("\n\t\t-a,--arch <arch>")+" architecture to use for gadget" +"\n\t\t\t\t disassembly/analysis"
load_help += "\n\n\t"+str_bold("Supported achitectures")+": "+', '.join([str_special(s) for s in str_to_arch])
load_help += "\n\n\t"+str_bold("Examples")+":\n\t\tload -a X86 /bin/bash \n\t\tload -a X64 ../my_binary1 ../my_binary2 "
find_help = str_main(str_bold("\n\t'find' Command"))
find_help += str_special("\n\t(Automatically find ropchains)")
find_help += "\n\n\t"+str_bold("Usage")+":\tfind <query>"
find_help += "\n\n\t"+str_bold("Query examples")+":\n"
find_help += "\n\t eax = 0x42"
find_help += "\n\t eax = ebx"
find_help += "\n\t eax = ebx ^ 3"
find_help += "\n\t eax = ebx & ecx"
find_help += "\n\t eax = [ebx + 16] "
find_help += "\n\t eax = [0x12345678] "
find_help += "\n\t eax += [ebx + 16]"
find_help += "\n\t eax *= [0x12345678]"
find_help += "\n\t [eax - 8] = ebx"
find_help += "\n\t [eax - 8] = 0x42"
find_help += "\n\t [eax - 8] &= ebx"
find_help += "\n\t [eax - 8] &= 0x42"
find_help += "\n\t [0x12345678] = ebx"
find_help += "\n\t [0x12345678] = 0x42"
find_help += "\n\t [0x12345678] &= ebx"
find_help += "\n\t [0x12345678] &= 0x42"
find_help += "\n\t [0x12345678] = '/bin/sh\x00'"
find_help += "\n\t 0x08040120()"
find_help += "\n\t 0x08040120(1, 2, 3, 4)"
find_help += "\n\t sys_execve(0x1234, 0, 0) [syscall by name]"
find_help += "\n\t sys_0xb(0x1234, 0, 0) [syscall by num]"
badbytes_help = str_main(str_bold("\n\t'badbytes' Command"))
badbytes_help += str_special("\n\t(Set bad bytes to avoid in ropchains)")
badbytes_help += "\n\n\t"+str_bold("Usage")+":\tbadbytes set BYTE [BYTE ...]"+"\n\t\tbadbytes reset"
badbytes_help += "\n\n\t"+str_bold("Example")+": badbytes set 0 0xa 0xb 255"
keepregs_help = str_main(str_bold("\n\t'keepregs' Command"))
keepregs_help += str_special("\n\t(Set registers that must not be clobbered)")
keepregs_help += "\n\n\t"+str_bold("Usage")+":\tkeepregs set REG [REG ...]"+"\n\t\tkeepregs reset"
keepregs_help += "\n\n\t"+str_bold("Example")+": keepregs set rsi rbp"
safemem_help = str_main(str_bold("\n\t'safemem' Command"))
safemem_help += str_special("\n\t(Enable/Disable the use of gadgets that dereference" +
"\n\tregisters holding unknown values and thus might"+ "\n\tcause a crash)")
safemem_help += "\n\n\t"+str_bold("Usage")+":\tsafemem set (disable unsafe gadgets)"+"\n\t\tsafemem unset (enable unsafe gadgets)"
abi_help = str_main(str_bold("\n\t'abi' Command"))
abi_help += str_special("\n\t(Set ABI to use when calling functions)")
abi_help += "\n\n\t"+str_bold("Usage")+":\tabi set <ABI>"
abi_help += "\n\n\t"+str_bold("Supported ABIs")+": "+', '.join([str_special(s) for s in str_to_abi])
os_help = str_main(str_bold("\n\t'os' Command"))
os_help += str_special("\n\t(Set OS to target when doing syscalls)")
os_help += "\n\n\t"+str_bold("Usage")+":\tos set <operating system>"
os_help += "\n\n\t"+str_bold("Supported systems")+": "+', '.join([str_special(s) for s in str_to_os])
if __name__ == "__main__":
main()
================================================
FILE: libropium/arch/arch.cpp
================================================
#include "arch.hpp"
#include <iostream>
Arch::Arch(ArchType _type, int _bits, int _octets, int _nb, CPUMode _mode, Disassembler* _disasm):
type(_type), bits(_bits), octets(_octets), nb_regs(_nb), mode(_mode), disasm(_disasm){}
Arch::~Arch(){
delete disasm;
disasm = nullptr;
}
================================================
FILE: libropium/arch/archX86.cpp
================================================
#include "expression.hpp"
#include "arch.hpp"
#include "disassembler.hpp"
#include "exception.hpp"
#include "ir.hpp"
#include <cstring>
#include <sstream>
#include <capstone/capstone.h>
#include <capstone/x86.h>
#include <iostream>
using std::stringstream;
/* ===================================
* ArchX86
* ================================== */
ArchX86::ArchX86(): Arch(ArchType::X86, 32, 4, X86_NB_REGS, CPUMode::X86, new DisassemblerX86(CPUMode::X86)){
}
string ArchX86::reg_name(reg_t num){
switch(num){
case X86_EAX: return "eax";
case X86_EBX: return "ebx";
case X86_ECX: return "ecx";
case X86_EDX: return "edx";
case X86_EDI: return "edi";
case X86_ESI: return "esi";
case X86_EBP: return "ebp";
case X86_ESP: return "esp";
case X86_EIP: return "eip";
case X86_CS: return "cs";
case X86_DS: return "ds";
case X86_ES: return "es";
case X86_FS: return "fs";
case X86_GS: return "gs";
case X86_SS: return "ss";
case X86_CF: return "cf";
case X86_PF: return "pf";
case X86_AF: return "af";
case X86_ZF: return "zf";
case X86_SF: return "sf";
case X86_TF: return "tf";
case X86_IF: return "if";
case X86_DF: return "df";
case X86_OF: return "of";
case X86_IOPL: return "iopl";
case X86_VM: return "vm";
case X86_NT: return "nt";
case X86_RF: return "rf";
case X86_AC: return "ac";
case X86_VIP: return "vip";
case X86_VIF: return "vif";
case X86_ID: return "id";
case X86_TSC: return "tsc";
default:
throw runtime_exception("ArchX86::reg_name() got unknown reg num");
}
}
reg_t ArchX86::reg_num(string name){
if( !name.compare("eax")) return X86_EAX;
else if( !name.compare("ebx")) return X86_EBX;
else if( !name.compare("ecx")) return X86_ECX;
else if( !name.compare("edx")) return X86_EDX;
else if( !name.compare("edi")) return X86_EDI;
else if( !name.compare("esi")) return X86_ESI;
else if( !name.compare("ebp")) return X86_EBP;
else if( !name.compare("esp")) return X86_ESP;
else if( !name.compare("eip")) return X86_EIP;
else if( !name.compare("cs")) return X86_CS;
else if( !name.compare("ds")) return X86_DS;
else if( !name.compare("es")) return X86_ES;
else if( !name.compare("fs")) return X86_FS;
else if( !name.compare("gs")) return X86_GS;
else if( !name.compare("ss")) return X86_SS;
else if( !name.compare("cf")) return X86_CF;
else if( !name.compare("pf")) return X86_PF;
else if( !name.compare("af")) return X86_AF;
else if( !name.compare("zf")) return X86_ZF;
else if( !name.compare("sf")) return X86_SF;
else if( !name.compare("tf")) return X86_TF;
else if( !name.compare("if")) return X86_IF;
else if( !name.compare("df")) return X86_DF;
else if( !name.compare("of")) return X86_OF;
else if( !name.compare("iopl")) return X86_IOPL;
else if( !name.compare("vm")) return X86_VM;
else if( !name.compare("nt")) return X86_NT;
else if( !name.compare("rf")) return X86_RF;
else if( !name.compare("ac")) return X86_AC;
else if( !name.compare("vip")) return X86_VIP;
else if( !name.compare("vif")) return X86_VIF;
else if( !name.compare("id")) return X86_ID;
else if( !name.compare("tsc")) return X86_TSC;
else throw runtime_exception(QuickFmt () << "ArchX86::reg_num() got unknown reg name: " << name >> QuickFmt::to_str);
}
bool ArchX86::is_valid_reg(string& name){
return ( !name.compare("eax"))
|| (!name.compare("ebx"))
|| (!name.compare("ecx"))
|| (!name.compare("edx"))
|| (!name.compare("edi"))
|| (!name.compare("esi"))
|| (!name.compare("ebp"))
|| (!name.compare("esp"))
|| (!name.compare("eip"))
|| (!name.compare("cs"))
|| (!name.compare("ds"))
|| (!name.compare("es"))
|| (!name.compare("fs"))
|| (!name.compare("gs"))
|| (!name.compare("ss"))
|| (!name.compare("cf"))
|| (!name.compare("pf"))
|| (!name.compare("af"))
|| (!name.compare("zf"))
|| (!name.compare("sf"))
|| (!name.compare("tf"))
|| (!name.compare("if"))
|| (!name.compare("df"))
|| (!name.compare("of"))
|| (!name.compare("iopl"))
|| (!name.compare("vm"))
|| (!name.compare("nt"))
|| (!name.compare("rf"))
|| (!name.compare("ac"))
|| (!name.compare("vip"))
|| (!name.compare("vif"))
|| (!name.compare("id"))
|| (!name.compare("tsc"));
}
reg_t ArchX86::sp(){
return X86_ESP;
}
reg_t ArchX86::pc(){
return X86_EIP;
}
reg_t ArchX86::tsc(){
return X86_TSC;
}
/* ===================================
* ArchX64
* ================================== */
ArchX64::ArchX64(): Arch(ArchType::X64, 64, 8, X64_NB_REGS, CPUMode::X64, new DisassemblerX86(CPUMode::X64)){
}
string ArchX64::reg_name(reg_t num){
switch(num){
case X64_RAX: return "rax";
case X64_RBX: return "rbx";
case X64_RCX: return "rcx";
case X64_RDX: return "rdx";
case X64_RDI: return "rdi";
case X64_RSI: return "rsi";
case X64_RBP: return "rbp";
case X64_RSP: return "rsp";
case X64_RIP: return "rip";
case X64_R8: return "r8";
case X64_R9: return "r9";
case X64_R10: return "r10";
case X64_R11: return "r11";
case X64_R12: return "r12";
case X64_R13: return "r13";
case X64_R14: return "r14";
case X64_R15: return "r15";
case X64_CS: return "cs";
case X64_DS: return "ds";
case X64_ES: return "es";
case X64_FS: return "fs";
case X64_GS: return "gs";
case X64_SS: return "ss";
case X64_CF: return "cf";
case X64_PF: return "pf";
case X64_AF: return "af";
case X64_ZF: return "zf";
case X64_SF: return "sf";
case X64_TF: return "tf";
case X64_IF: return "if";
case X64_DF: return "df";
case X64_OF: return "of";
case X64_IOPL: return "iopl";
case X64_VM: return "vm";
case X64_NT: return "nt";
case X64_RF: return "rf";
case X64_AC: return "ac";
case X64_VIP: return "vip";
case X64_VIF: return "vif";
case X64_ID: return "id";
case X64_TSC: return "tsc";
default:
throw runtime_exception("ArchX64::reg_name() got unknown reg num");
}
}
reg_t ArchX64::reg_num(string name){
if( !name.compare("rax")) return X64_RAX;
else if( !name.compare("rbx")) return X64_RBX;
else if( !name.compare("rcx")) return X64_RCX;
else if( !name.compare("rdx")) return X64_RDX;
else if( !name.compare("rdi")) return X64_RDI;
else if( !name.compare("rsi")) return X64_RSI;
else if( !name.compare("rbp")) return X64_RBP;
else if( !name.compare("rsp")) return X64_RSP;
else if( !name.compare("rip")) return X64_RIP;
else if( !name.compare("r8")) return X64_R8;
else if( !name.compare("r9")) return X64_R9;
else if( !name.compare("r10")) return X64_R10;
else if( !name.compare("r11")) return X64_R11;
else if( !name.compare("r12")) return X64_R12;
else if( !name.compare("r13")) return X64_R13;
else if( !name.compare("r14")) return X64_R14;
else if( !name.compare("r15")) return X64_R15;
else if( !name.compare("cs")) return X64_CS;
else if( !name.compare("ds")) return X64_DS;
else if( !name.compare("es")) return X64_ES;
else if( !name.compare("fs")) return X64_FS;
else if( !name.compare("gs")) return X64_GS;
else if( !name.compare("ss")) return X64_SS;
else if( !name.compare("cf")) return X64_CF;
else if( !name.compare("pf")) return X64_PF;
else if( !name.compare("af")) return X64_AF;
else if( !name.compare("zf")) return X64_ZF;
else if( !name.compare("sf")) return X64_SF;
else if( !name.compare("tf")) return X64_TF;
else if( !name.compare("if")) return X64_IF;
else if( !name.compare("df")) return X64_DF;
else if( !name.compare("of")) return X64_OF;
else if( !name.compare("iopl")) return X64_IOPL;
else if( !name.compare("vm")) return X64_VM;
else if( !name.compare("nt")) return X64_NT;
else if( !name.compare("rf")) return X64_RF;
else if( !name.compare("ac")) return X64_AC;
else if( !name.compare("vip")) return X64_VIP;
else if( !name.compare("vif")) return X64_VIF;
else if( !name.compare("id")) return X64_ID;
else if( !name.compare("tsc")) return X64_TSC;
else throw runtime_exception(QuickFmt () << "ArchX86::reg_num() got unknown reg name: " << name >> QuickFmt::to_str);
}
bool ArchX64::is_valid_reg(string& name){
return (!name.compare("rax"))
|| (!name.compare("rbx"))
|| (!name.compare("rcx"))
|| (!name.compare("rdx"))
|| (!name.compare("rdi"))
|| (!name.compare("rsi"))
|| (!name.compare("rbp"))
|| (!name.compare("rsp"))
|| (!name.compare("rip"))
|| (!name.compare("r8"))
|| (!name.compare("r9"))
|| (!name.compare("r10"))
|| (!name.compare("r11"))
|| (!name.compare("r12"))
|| (!name.compare("r13"))
|| (!name.compare("r14"))
|| (!name.compare("r15"))
|| (!name.compare("cs"))
|| (!name.compare("ds"))
|| (!name.compare("es"))
|| (!name.compare("fs"))
|| (!name.compare("gs"))
|| (!name.compare("ss"))
|| (!name.compare("cf"))
|| (!name.compare("pf"))
|| (!name.compare("af"))
|| (!name.compare("zf"))
|| (!name.compare("sf"))
|| (!name.compare("tf"))
|| (!name.compare("if"))
|| (!name.compare("df"))
|| (!name.compare("of"))
|| (!name.compare("iopl"))
|| (!name.compare("vm"))
|| (!name.compare("nt"))
|| (!name.compare("rf"))
|| (!name.compare("ac"))
|| (!name.compare("vip"))
|| (!name.compare("vif"))
|| (!name.compare("id"))
|| (!name.compare("tsc"));
}
reg_t ArchX64::sp(){
return X64_RSP;
}
reg_t ArchX64::pc(){
return X64_RIP;
}
reg_t ArchX64::tsc(){
return X64_TSC;
}
/* ===================================
* X86 & X64 Disassembler
* ================================== */
DisassemblerX86::DisassemblerX86(CPUMode mode){
_mode = mode;
if( mode == CPUMode::X86 ){
cs_open(CS_ARCH_X86, CS_MODE_32, &_handle);
}else if( mode == CPUMode::X64 ){
cs_open(CS_ARCH_X86, CS_MODE_64, &_handle);
}else{
throw runtime_exception("DisassemblerX86: got unsupported mode");
}
// Ask for detailed instructions
cs_option(_handle, CS_OPT_DETAIL, CS_OPT_ON);
// allocate memory cache for 1 instruction, to be used by cs_disasm_iter later.
// (will be freed in destructor)
_insn = cs_malloc(_handle);
}
inline IROperand x86_32_reg_translate(x86_reg reg){
switch(reg){
case X86_REG_AL: return IROperand(IROperandType::VAR, X86_EAX, 7, 0);
case X86_REG_AH: return IROperand(IROperandType::VAR, X86_EAX, 15, 8);
case X86_REG_AX: return IROperand(IROperandType::VAR, X86_EAX, 15, 0);
case X86_REG_EAX: return IROperand(IROperandType::VAR, X86_EAX, 31, 0);
case X86_REG_BL: return IROperand(IROperandType::VAR, X86_EBX, 7, 0);
case X86_REG_BH: return IROperand(IROperandType::VAR, X86_EBX, 15, 8);
case X86_REG_BX: return IROperand(IROperandType::VAR, X86_EBX, 15, 0);
case X86_REG_EBX: return IROperand(IROperandType::VAR, X86_EBX , 31, 0);
case X86_REG_CL: return IROperand(IROperandType::VAR, X86_ECX, 7, 0);
case X86_REG_CH: return IROperand(IROperandType::VAR, X86_ECX, 15, 8);
case X86_REG_CX: return IROperand(IROperandType::VAR, X86_ECX, 15, 0);
case X86_REG_ECX: return IROperand(IROperandType::VAR, X86_ECX, 31, 0);
case X86_REG_DL: return IROperand(IROperandType::VAR, X86_EDX, 7, 0);
case X86_REG_DH: return IROperand(IROperandType::VAR, X86_EDX, 15, 8);
case X86_REG_DX: return IROperand(IROperandType::VAR, X86_EDX, 15, 0);
case X86_REG_EDX: return IROperand(IROperandType::VAR, X86_EDX, 31, 0);
case X86_REG_DI: return IROperand(IROperandType::VAR, X86_EDI, 15, 0);
case X86_REG_EDI: return IROperand(IROperandType::VAR, X86_EDI, 31, 0);
case X86_REG_SI: return IROperand(IROperandType::VAR, X86_ESI, 15, 0);
case X86_REG_ESI: return IROperand(IROperandType::VAR, X86_ESI, 31, 0);
case X86_REG_BP: return IROperand(IROperandType::VAR, X86_EBP, 15, 0);
case X86_REG_EBP: return IROperand(IROperandType::VAR, X86_EBP, 31, 0);
case X86_REG_SP: return IROperand(IROperandType::VAR, X86_ESP, 15, 0);
case X86_REG_ESP: return IROperand(IROperandType::VAR, X86_ESP, 31, 0);
case X86_REG_IP: return IROperand(IROperandType::VAR, X86_EIP, 15, 0);
case X86_REG_EIP: return IROperand(IROperandType::VAR, X86_EIP, 31, 0);
case X86_REG_CS: return IROperand(IROperandType::VAR, X86_CS, 31, 0);
case X86_REG_DS: return IROperand(IROperandType::VAR, X86_DS, 31, 0);
case X86_REG_ES: return IROperand(IROperandType::VAR, X86_ES, 31, 0);
case X86_REG_GS: return IROperand(IROperandType::VAR, X86_GS, 31, 0);
case X86_REG_FS: return IROperand(IROperandType::VAR, X86_FS, 31, 0);
case X86_REG_SS: return IROperand(IROperandType::VAR, X86_SS, 31, 0);
default: throw runtime_exception( QuickFmt() <<
"Disassembler X86: unknown capstone register " << reg
>> QuickFmt::to_str);
}
}
inline IROperand x86_64_reg_translate(x86_reg reg){
switch(reg){
case X86_REG_AL: return IROperand(IROperandType::VAR, X64_RAX, 7, 0);
case X86_REG_AH: return IROperand(IROperandType::VAR, X64_RAX, 15, 8);
case X86_REG_AX: return IROperand(IROperandType::VAR, X64_RAX, 15, 0);
case X86_REG_EAX: return IROperand(IROperandType::VAR, X64_RAX, 31, 0);
case X86_REG_RAX: return IROperand(IROperandType::VAR, X64_RAX, 63, 0);
case X86_REG_BL: return IROperand(IROperandType::VAR, X64_RBX, 7, 0);
case X86_REG_BH: return IROperand(IROperandType::VAR, X64_RBX, 15, 8);
case X86_REG_BX: return IROperand(IROperandType::VAR, X64_RBX, 15, 0);
case X86_REG_EBX: return IROperand(IROperandType::VAR, X64_RBX , 31, 0);
case X86_REG_RBX: return IROperand(IROperandType::VAR, X64_RBX , 63, 0);
case X86_REG_CL: return IROperand(IROperandType::VAR, X64_RCX, 7, 0);
case X86_REG_CH: return IROperand(IROperandType::VAR, X64_RCX, 15, 8);
case X86_REG_CX: return IROperand(IROperandType::VAR, X64_RCX, 15, 0);
case X86_REG_ECX: return IROperand(IROperandType::VAR, X64_RCX, 31, 0);
case X86_REG_RCX: return IROperand(IROperandType::VAR, X64_RCX, 63, 0);
case X86_REG_DL: return IROperand(IROperandType::VAR, X64_RDX, 7, 0);
case X86_REG_DH: return IROperand(IROperandType::VAR, X64_RDX, 15, 8);
case X86_REG_DX: return IROperand(IROperandType::VAR, X64_RDX, 15, 0);
case X86_REG_EDX: return IROperand(IROperandType::VAR, X64_RDX, 31, 0);
case X86_REG_RDX: return IROperand(IROperandType::VAR, X64_RDX, 63, 0);
case X86_REG_DI: return IROperand(IROperandType::VAR, X64_RDI, 15, 0);
case X86_REG_EDI: return IROperand(IROperandType::VAR, X64_RDI, 31, 0);
case X86_REG_RDI: return IROperand(IROperandType::VAR, X64_RDI, 63, 0);
case X86_REG_SI: return IROperand(IROperandType::VAR, X64_RSI, 15, 0);
case X86_REG_ESI: return IROperand(IROperandType::VAR, X64_RSI, 31, 0);
case X86_REG_RSI: return IROperand(IROperandType::VAR, X64_RSI, 63, 0);
case X86_REG_BP: return IROperand(IROperandType::VAR, X64_RBP, 15, 0);
case X86_REG_EBP: return IROperand(IROperandType::VAR, X64_RBP, 31, 0);
case X86_REG_RBP: return IROperand(IROperandType::VAR, X64_RBP, 63, 0);
case X86_REG_SP: return IROperand(IROperandType::VAR, X64_RSP, 15, 0);
case X86_REG_ESP: return IROperand(IROperandType::VAR, X64_RSP, 31, 0);
case X86_REG_RSP: return IROperand(IROperandType::VAR, X64_RSP, 63, 0);
case X86_REG_IP: return IROperand(IROperandType::VAR, X64_RIP, 15, 0);
case X86_REG_EIP: return IROperand(IROperandType::VAR, X64_RIP, 31, 0);
case X86_REG_RIP: return IROperand(IROperandType::VAR, X64_RIP, 63, 0);
case X86_REG_R8: return IROperand(IROperandType::VAR, X64_R8, 63, 0);
case X86_REG_R8B: return IROperand(IROperandType::VAR, X64_R8, 7, 0);
case X86_REG_R8D: return IROperand(IROperandType::VAR, X64_R8, 31, 0);
case X86_REG_R8W: return IROperand(IROperandType::VAR, X64_R8, 15, 0);
case X86_REG_R9: return IROperand(IROperandType::VAR, X64_R9, 63, 0);
case X86_REG_R9B: return IROperand(IROperandType::VAR, X64_R9, 7, 0);
case X86_REG_R9D: return IROperand(IROperandType::VAR, X64_R9, 31, 0);
case X86_REG_R9W: return IROperand(IROperandType::VAR, X64_R9, 15, 0);
case X86_REG_R10: return IROperand(IROperandType::VAR, X64_R10, 63, 0);
case X86_REG_R10B: return IROperand(IROperandType::VAR, X64_R10, 7, 0);
case X86_REG_R10D: return IROperand(IROperandType::VAR, X64_R10, 31, 0);
case X86_REG_R10W: return IROperand(IROperandType::VAR, X64_R10, 15, 0);
case X86_REG_R11: return IROperand(IROperandType::VAR, X64_R11, 63, 0);
case X86_REG_R11B: return IROperand(IROperandType::VAR, X64_R11, 7, 0);
case X86_REG_R11D: return IROperand(IROperandType::VAR, X64_R11, 31, 0);
case X86_REG_R11W: return IROperand(IROperandType::VAR, X64_R11, 15, 0);
case X86_REG_R12: return IROperand(IROperandType::VAR, X64_R12, 63, 0);
case X86_REG_R12B: return IROperand(IROperandType::VAR, X64_R12, 7, 0);
case X86_REG_R12D: return IROperand(IROperandType::VAR, X64_R12, 31, 0);
case X86_REG_R12W: return IROperand(IROperandType::VAR, X64_R12, 15, 0);
case X86_REG_R13: return IROperand(IROperandType::VAR, X64_R13, 63, 0);
case X86_REG_R13B: return IROperand(IROperandType::VAR, X64_R13, 7, 0);
case X86_REG_R13D: return IROperand(IROperandType::VAR, X64_R13, 31, 0);
case X86_REG_R13W: return IROperand(IROperandType::VAR, X64_R13, 15, 0);
case X86_REG_R14: return IROperand(IROperandType::VAR, X64_R14, 63, 0);
case X86_REG_R14B: return IROperand(IROperandType::VAR, X64_R14, 7, 0);
case X86_REG_R14D: return IROperand(IROperandType::VAR, X64_R14, 31, 0);
case X86_REG_R14W: return IROperand(IROperandType::VAR, X64_R14, 15, 0);
case X86_REG_R15: return IROperand(IROperandType::VAR, X64_R15, 63, 0);
case X86_REG_R15B: return IROperand(IROperandType::VAR, X64_R15, 7, 0);
case X86_REG_R15D: return IROperand(IROperandType::VAR, X64_R15, 31, 0);
case X86_REG_R15W: return IROperand(IROperandType::VAR, X64_R15, 15, 0);
case X86_REG_CS: return IROperand(IROperandType::VAR, X64_CS, 63, 0);
case X86_REG_DS: return IROperand(IROperandType::VAR, X64_DS, 63, 0);
case X86_REG_ES: return IROperand(IROperandType::VAR, X64_ES, 63, 0);
case X86_REG_GS: return IROperand(IROperandType::VAR, X64_GS, 63, 0);
case X86_REG_FS: return IROperand(IROperandType::VAR, X64_FS, 63, 0);
case X86_REG_SS: return IROperand(IROperandType::VAR, X64_SS, 63, 0);
default: throw runtime_exception( QuickFmt() <<
"Disassembler X86: unknown capstone register " << reg
>> QuickFmt::to_str);
}
}
inline IROperand x86_reg_translate(CPUMode mode, x86_reg reg){
if( mode == CPUMode::X86 ){
return x86_32_reg_translate(reg);
}else{
return x86_64_reg_translate(reg);
}
}
inline IROperand x86_arg_extract(IROperand& arg, exprsize_t high, exprsize_t low){
switch(arg.type){
case IROperandType::CST: return IROperand(IROperandType::CST, arg.cst(), high, low);
case IROperandType::VAR: return IROperand(IROperandType::VAR, arg.var(), high, low);
case IROperandType::TMP: return IROperand(IROperandType::TMP, arg.tmp(), high, low);
case IROperandType::NONE: return IROperand();
default: throw runtime_exception("x86_arg_extract(): got unknown IROperandType!");
}
}
/* Translate capstone argument to IR argument
* Arguments:
* mode - the current CPU mode for registers translation
* addr - the address of the instruction being translated
* arg - the capstone operand
* block/bblkid - block and basicblockid where to add instructions if needed
* tmp_var_count - the counter of the tmp variables used in the current IRBlock
* load_mem - if TRUE then load memory operands (dereference), else only return the operand (pointer)
*/
inline IROperand x86_arg_translate(CPUMode mode, addr_t addr, cs_x86_op* arg, IRBlock* block, IRBasicBlockId bblkid, int& tmp_vars_count, bool load_mem=false){
IROperand base, index, res, disp, segment;
exprsize_t size = arg->size*8, addr_size = 0, reg_size = (mode==CPUMode::X86)? 32:64;
try{
switch(arg->type){
/* Register */
case X86_OP_REG:
return x86_reg_translate(mode, arg->reg);
/* Immediate */
case X86_OP_IMM:
return IROperand(IROperandType::CST, arg->imm, size-1, 0);
/* Memory */
case X86_OP_MEM:
// Arg = segment + base + (index*scale) + disp
// Get index*scale
if( arg->mem.index != X86_OP_INVALID ){
index = x86_reg_translate(mode, (x86_reg)arg->mem.index);
if( arg->mem.scale != 1 ){
block->add_instr(bblkid, IRInstruction(IROperation::MUL, ir_tmp(tmp_vars_count++, index.size-1, 0),
ir_cst(arg->mem.scale, index.size-1, 0), index, addr));
index = ir_tmp(tmp_vars_count-1, index.size-1, 0);
}
addr_size = index.size;
}
// Get base
if( arg->mem.base != X86_OP_INVALID ){
base = x86_reg_translate(mode, (x86_reg)arg->mem.base);
// If too small adjust
if( base.size < index.size ){
block->add_instr(bblkid, ir_mov(ir_tmp(tmp_vars_count++, index.size-1, 0), ir_cst(0, index.size-1, 0), addr));
block->add_instr(bblkid, ir_mov(ir_tmp(tmp_vars_count-1, base.size-1, 0), base, addr));
base = ir_tmp(tmp_vars_count-1, base.size-1, 0);
}
addr_size = base.size;
}else{
//base = ir_cst(0, index.size-1, 0);
base = ir_none();
//throw runtime_exception("Disassembler X86: didn't expect X86_OP_INVALID base for mem operand in capstone");
}
// Get displacement
if( addr_size == 0 )
addr_size = reg_size;
if( arg->mem.disp != 0 ){
disp = IROperand(IROperandType::CST, arg->mem.disp, addr_size-1, 0);
}else{
disp = ir_none();
}
// Get segment selector (here we consider that the segment selector symbolic register holds the address
// of the segment, not the index in the GDT
if( arg->mem.segment != X86_OP_INVALID ){
segment = x86_reg_translate(mode, (x86_reg)arg->mem.segment);
// If too big, adjust
if( segment.size > addr_size ){
block->add_instr(bblkid, ir_mov(ir_tmp(tmp_vars_count++, addr_size-1, 0), x86_arg_extract(segment, addr_size-1, 0), addr));
segment = ir_tmp(tmp_vars_count-1, addr_size-1, 0);
}
}else{
segment = ir_none();
}
// === Build the operand now ===
// Add base and index if any
if( !index.is_none() ){
if( !base.is_none() ){
block->add_instr(bblkid, ir_add(ir_tmp(tmp_vars_count++, index.size-1, 0), base, index, addr));
res = IROperand(IROperandType::TMP, tmp_vars_count-1, index.size-1, 0);
}else{
res = index;
}
}else if(!base.is_none()){
res = base;
}else{
res = ir_none();
}
// Add displacement if any
if( !disp.is_none() ){
if( !res.is_none()){
block->add_instr(bblkid, ir_add( ir_tmp(tmp_vars_count++, res.size-1, 0), disp, res, addr));
res = IROperand(IROperandType::TMP, tmp_vars_count-1, res.size-1, 0);
}else{
res = disp;
}
}
// Add segment if any
if( !segment.is_none() ){
if( !res.is_none() ){
block->add_instr(bblkid, ir_add( ir_tmp(tmp_vars_count++, res.size-1, 0), segment, res, addr));
res = IROperand(IROperandType::TMP, tmp_vars_count-1, res.size-1, 0);
}else{
res = segment;
}
}
// Check res
if( res.is_none() ){
throw symbolic_exception("Got IR_NONE memory operand");
}
// Do load memory if requested
if( load_mem ){
block->add_instr(bblkid, IRInstruction(IROperation::LDM,
IROperand(IROperandType::TMP, tmp_vars_count++, size-1 , 0), res, addr));
res = IROperand(IROperandType::TMP, tmp_vars_count-1, size-1, 0);
}
return res;
default:
throw runtime_exception(QuickFmt() << "Disassembler X86: at addr: 0x" << std::hex
<< addr << " :got unknown capstone operand type" >> QuickFmt::to_str);
}
}catch(runtime_exception& e){
throw runtime_exception(QuickFmt() << "Disassembler X86: error at addr: 0x" << std::hex
<< addr << " :" + string(e.what()) >> QuickFmt::to_str);
}
throw runtime_exception(QuickFmt() << "Disassembler X86: at addr: 0x" << std::hex << addr << " :couldn't translate operand"
>> QuickFmt::to_str);
}
/* Translate a 32bits assignments to a 64bits assignment where the upper
* 32 bits are cleared. For the bits to be cleared, the following conditions
* must be fulfilled:
* - mode is CPUMOde::X64
* - destination is a register (IROperandType::VAR)
* - destination is 32 bits */
inline void x86_adjust_reg_assign(CPUMode mode, addr_t addr, IRBlock* block, IRBasicBlockId bblkid, int& tmp_vars_count, IROperand dest, IROperand val){
IROperand res;
if( mode != CPUMode::X64 || dest.size != 32 || dest.type != IROperandType::VAR){
// No need to adjust, to assign result to destination
block->add_instr(bblkid, ir_mov(dest, val, addr));
return;
}
// Need to clear upper bits
block->add_instr(bblkid, ir_concat(ir_var(dest.var(), 63, 0), ir_cst(0, 63-val.size, 0), val, addr));
}
/* ========================================= */
inline IROperand x86_get_pc(CPUMode mode ){
if( mode == CPUMode::X86 )
return ir_var(X86_EIP, 31, 0 );
else if( mode == CPUMode::X64 )
return ir_var(X64_RIP, 63, 0 );
else
throw runtime_exception("x86_get_pc(): got unknown CPUMode!");
}
inline IROperand x86_get_tsc(CPUMode mode ){
if( mode == CPUMode::X86 )
return ir_var(X86_TSC, 63, 0 );
else if( mode == CPUMode::X64 )
return ir_var(X64_TSC, 63, 0 );
else
throw runtime_exception("x86_get_pc(): got unknown CPUMode!");
}
inline void x86_set_zf(CPUMode mode, IROperand& arg, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid){
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz(ir_var(X86_ZF, 31, 0), arg, ir_cst(1, 31, 0), addr));
else
block->add_instr(bblkid, ir_bisz(ir_var(X64_ZF, 63, 0), arg , ir_cst(1, 63, 0), addr));
}
inline void x86_add_set_cf(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
IROperand msb0 = x86_arg_extract(op0, op0.high, op0.high),
msb1 = x86_arg_extract(op1, op1.high, op1.high),
msb2 = x86_arg_extract(res, res.high, res.high),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp2 = ir_tmp(tmp_var_count++, 0, 0 );
// cf -> higher bits of both operands are already 1
block->add_instr(bblkid, ir_and(tmp0, msb0, msb1, addr));
// or they are 1 and 0 and result has MSB 0
block->add_instr(bblkid, ir_xor(tmp1, msb0, msb1, addr));
block->add_instr(bblkid, ir_not(tmp2, msb2, addr));
block->add_instr(bblkid, ir_and(tmp2, tmp1, tmp2, addr));
block->add_instr(bblkid, ir_or(tmp2, tmp0, tmp2, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz( ir_var(X86_CF, 31, 0),tmp2, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz( ir_var(X64_CF, 63, 0),tmp2, ir_cst(0, 63, 0), addr));
}
inline void x86_add_set_of(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
IROperand msb0 = x86_arg_extract(op0, op0.high, op0.high),
msb1 = x86_arg_extract(op1, op1.high, op1.high),
msb2 = x86_arg_extract(res, res.high, res.high),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 );
// of -> msb of both operands have the same MSB but result
// has different
block->add_instr(bblkid, ir_xor(tmp0, msb0, msb1, addr));
block->add_instr(bblkid, ir_not(tmp0, tmp0, addr));
block->add_instr(bblkid, ir_xor(tmp1, msb0, msb2, addr));
block->add_instr(bblkid, ir_and(tmp1, tmp0, tmp1, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz(ir_var(X86_OF, 31, 0), tmp1, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz(ir_var(X64_OF, 63, 0), tmp1, ir_cst(0, 63, 0), addr));
}
inline void x86_sub_set_cf(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
IROperand msb0 = x86_arg_extract(op0, op0.high, op0.high),
msb1 = x86_arg_extract(op1, op1.high, op1.high),
msb2 = x86_arg_extract(res, res.high, res.high),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 );
// cf <- (~msb0&msb1) | (msb1&msb2) | (~msb0&msb2)
block->add_instr(bblkid, ir_not(tmp0, msb0, addr));
block->add_instr(bblkid, ir_and(tmp0, tmp0, msb1, addr));
block->add_instr(bblkid, ir_and(tmp1, msb1, msb2, addr));
block->add_instr(bblkid, ir_or(tmp1, tmp0, tmp1, addr));
block->add_instr(bblkid, ir_not(tmp0, msb0, addr));
block->add_instr(bblkid, ir_and(tmp0, tmp0, msb2, addr));
block->add_instr(bblkid, ir_or(tmp1, tmp1, tmp0, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz( ir_var(X86_CF, 31, 0),tmp1, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz( ir_var(X64_CF, 63, 0),tmp1, ir_cst(0, 63, 0), addr));
}
inline void x86_sub_set_af(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
/* Like cf but for bit 3 */
IROperand msb0 = x86_arg_extract(op0, 3, 3),
msb1 = x86_arg_extract(op1, 3, 3),
msb2 = x86_arg_extract(res, 3, 3),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 );
// cf <- (~msb0&msb1) | (msb1&msb2) | (~msb0&msb2)
block->add_instr(bblkid, ir_not(tmp0, msb0, addr));
block->add_instr(bblkid, ir_and(tmp0, tmp0, msb1, addr));
block->add_instr(bblkid, ir_and(tmp1, msb1, msb2, addr));
block->add_instr(bblkid, ir_or(tmp1, tmp0, tmp1, addr));
block->add_instr(bblkid, ir_not(tmp0, msb0, addr));
block->add_instr(bblkid, ir_and(tmp0, tmp0, msb2, addr));
block->add_instr(bblkid, ir_or(tmp1, tmp1, tmp0, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz( ir_var(X86_AF, 31, 0),tmp1, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz( ir_var(X64_AF, 63, 0),tmp1, ir_cst(0, 63, 0), addr));
}
inline void x86_sub_set_of(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
IROperand msb0 = x86_arg_extract(op0, op0.high, op0.high),
msb1 = x86_arg_extract(op1, op1.high, op1.high),
msb2 = x86_arg_extract(res, res.high, res.high),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 );
// of -> msb of both operands have different MSB and result
// has the same as second operand
block->add_instr(bblkid, ir_xor(tmp0, msb0, msb1, addr));
block->add_instr(bblkid, ir_xor(tmp1, msb1, msb2, addr));
block->add_instr(bblkid, ir_not(tmp1, tmp1, addr));
block->add_instr(bblkid, ir_and(tmp1, tmp0, tmp1, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz(ir_var(X86_OF, 31, 0), tmp1, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz(ir_var(X64_OF, 63, 0), tmp1, ir_cst(0, 63, 0), addr));
}
inline void x86_set_sf(CPUMode mode, IROperand& arg, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid){
IROperand sf = mode == CPUMode::X86 ? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
block->add_instr(bblkid, ir_bisz(sf, x86_arg_extract(arg, arg.high, arg.high), ir_cst(0, sf.high, 0), addr));
}
inline void x86_add_set_af(CPUMode mode, IROperand op0, IROperand op1, IROperand res, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
// Basically like cf but for bits 3
IROperand msb0 = x86_arg_extract(op0, 3, 3),
msb1 = x86_arg_extract(op1, 3, 3),
msb2 = x86_arg_extract(res, 3, 3),
tmp0 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp1 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp2 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp3 = ir_tmp(tmp_var_count++, 0, 0 ),
tmp4 = ir_tmp(tmp_var_count++, 0, 0 );
// cf -> higher bits of both operands are already 1
block->add_instr(bblkid, ir_and(tmp0, msb0, msb1, addr));
// or they are 1 and 0 and result has MSB 0
block->add_instr(bblkid, ir_xor(tmp1, msb0, msb1, addr));
block->add_instr(bblkid, ir_not(tmp2, msb2, addr));
block->add_instr(bblkid, ir_and(tmp3, tmp1, tmp2, addr));
block->add_instr(bblkid, ir_or(tmp4, tmp0, tmp3, addr));
if( mode == CPUMode::X86 )
block->add_instr(bblkid, ir_bisz( ir_var(X86_AF, 31, 0),tmp4, ir_cst(0, 31, 0), addr));
else if( mode == CPUMode::X64 )
block->add_instr(bblkid, ir_bisz( ir_var(X64_AF, 63, 0),tmp4, ir_cst(0, 63, 0), addr));
}
inline void x86_set_pf(CPUMode mode, IROperand arg, addr_t addr, IRBlock* block, IRBasicBlockId bblkid, int& tmp_var_count){
// pf number of bits that are equal to zero in the least significant byte
// of the result of an operation -> xor all and set flag if zero
IROperand tmp = ir_tmp(tmp_var_count++, 0, 0 );
block->add_instr(bblkid, ir_mov(tmp, x86_arg_extract(arg, 0, 0), addr));
for( int i = 1; i < 8; i++){
block->add_instr(bblkid, ir_xor(tmp, tmp, x86_arg_extract(arg, i, i), addr));
}
if( mode == CPUMode::X86 ){
block->add_instr(bblkid, ir_bisz(ir_var(X86_PF, 31, 0), tmp, ir_cst(1, 31, 0), addr));
}else if( mode == CPUMode::X64 ){
block->add_instr(bblkid, ir_bisz(ir_var(X64_PF, 63, 0), tmp, ir_cst(1, 31, 0), addr));
}
}
/* =====================
* Instruction prefixes
* =====================
*/
IRBasicBlockId _x86_init_prefix(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid){
IRBasicBlockId start;
if( instr->detail->x86.prefix[0] != X86_PREFIX_REP &&
instr->detail->x86.prefix[0] != X86_PREFIX_REPNE ){
return -1;
}
start = block->new_bblock();
block->add_instr(bblkid, ir_bcc(ir_cst(1, 31, 0), ir_cst(start, 31, 0), ir_none(), addr));
bblkid = block->new_bblock();
return start;
}
bool inline _accepts_repe_prefix(cs_insn* instr){
return instr->id == X86_INS_CMPSB ||
instr->id == X86_INS_CMPSW ||
instr->id == X86_INS_CMPSD ||
instr->id == X86_INS_CMPSQ ||
instr->id == X86_INS_SCASB ||
instr->id == X86_INS_SCASW ||
instr->id == X86_INS_SCASD ||
instr->id == X86_INS_SCASQ;
}
bool inline _accepts_rep_prefix(cs_insn* instr){
return instr->id == X86_INS_INSB ||
instr->id == X86_INS_INSW ||
instr->id == X86_INS_INSD ||
instr->id == X86_INS_MOVSB ||
instr->id == X86_INS_MOVSW ||
instr->id == X86_INS_MOVSD ||
instr->id == X86_INS_MOVSQ ||
instr->id == X86_INS_OUTSB ||
instr->id == X86_INS_OUTSW ||
instr->id == X86_INS_OUTSD ||
instr->id == X86_INS_LODSB ||
instr->id == X86_INS_LODSW ||
instr->id == X86_INS_LODSD ||
instr->id == X86_INS_LODSQ ||
instr->id == X86_INS_STOSB ||
instr->id == X86_INS_STOSW ||
instr->id == X86_INS_STOSD ||
instr->id == X86_INS_STOSQ;
}
/* Wraps an instruction block with a REP prefix
* Parameters:
* start - the basic block where to test the terminating condition. The instruction semantics start at start+1
* last - the current last bblock of the instruction
*
*/
inline void _x86_end_prefix(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId start, IRBasicBlockId& last, int& tmp_var_count){
IROperand cx = (mode == CPUMode::X86)? ir_var(X86_ECX, 31, 0): ir_var(X64_RCX, 63, 0);
IROperand zf = (mode == CPUMode::X86)? ir_var(X86_ZF, 31, 0): ir_var(X64_ZF, 63, 0);
IROperand tmp;
IRBasicBlockId end;
if( instr->detail->x86.prefix[0] != X86_PREFIX_REP &&
instr->detail->x86.prefix[0] != X86_PREFIX_REPNE ){
return;
}
/* Add loop and cx decrement at the end of the instruction */
block->add_instr(last, ir_sub(cx, cx, ir_cst(1, cx.size-1, 0), addr));
block->add_instr(last, ir_bcc(ir_cst(1, 31, 0), ir_cst(start, 31, 0), ir_none(), addr));
/* Add REP test in the beginning */
end = block->new_bblock();
if( instr->detail->x86.prefix[0] == X86_PREFIX_REP && _accepts_rep_prefix(instr) ){
block->add_instr(start, ir_bcc(cx, ir_cst(start+1, 31, 0), ir_cst(end, 31, 0), addr));
}else if( instr->detail->x86.prefix[0] == X86_PREFIX_REP && _accepts_repe_prefix(instr) ){
tmp = ir_tmp(tmp_var_count++, 0, 0);
block->add_instr(start, ir_bisz(tmp, cx, ir_cst(0, 0, 0), addr));
block->add_instr(start, ir_and(tmp, tmp, x86_arg_extract(zf, 0, 0), addr));
block->add_instr(start, ir_bcc(tmp, ir_cst(start+1, 31, 0), ir_cst(end, 31, 0), addr));
}else if( instr->detail->x86.prefix[0] == X86_PREFIX_REPNE ){
tmp = ir_tmp(tmp_var_count++, 0, 0);
block->add_instr(start, ir_bisz(tmp, cx, ir_cst(1, 0, 0), addr));
block->add_instr(start, ir_or(tmp, tmp, x86_arg_extract(zf, 0, 0), addr));
block->add_instr(start, ir_bcc(tmp, ir_cst(end, 31, 0), ir_cst(start+1, 31, 0), addr));
}
last = end; // Update last basic block
}
/* ========================================= */
/* Instructions translation */
inline void x86_aaa_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand af, eax, cf, tmp0, tmp1, pc;
if( mode == CPUMode::X86 ){
eax = ir_var(X86_EAX, 31, 0);
af = ir_var(X86_AF, 31, 0);
cf = ir_var(X86_CF, 31, 0);
}else if( mode == CPUMode::X64 ){
throw illegal_instruction_exception("X86 AAA instruction is valid only in 32-bit mode");
}
tmp0 = ir_tmp(tmp_var_count++, af.size-1, 0), // Get the size from any register
tmp1 = ir_tmp(tmp_var_count++, af.size-1, 0);
/* If 4 LSB are > 9 or if AF is set then adjust the unpacked BCD values */
// (4 LSB) > 9
block->add_instr(bblkid, ir_bisz(tmp0, x86_arg_extract(eax, 3, 3), ir_cst(0, eax.size,0), addr));
block->add_instr(bblkid, ir_bisz(tmp1, x86_arg_extract(eax, 2, 1), ir_cst(0, eax.size,0), addr));
block->add_instr(bblkid, ir_and(tmp1, tmp1, tmp0, addr));
// AF
block->add_instr(bblkid, ir_or(tmp1, af, tmp1, addr));
// Branch depending on condition
block->add_instr(bblkid, ir_bcc(tmp1, ir_cst(bblkid+1, 31,0), ir_cst(bblkid+2, 31, 0), addr));
// 1°) Branch 1 - Do the adjust
bblkid = block->new_bblock();
// AL <- AL + 6
block->add_instr(bblkid, ir_add(x86_arg_extract(eax, 7, 0), x86_arg_extract(eax, 7, 0), ir_cst(6, 7, 0), addr));
// AH ++
block->add_instr(bblkid, ir_add(x86_arg_extract(eax, 15, 8), x86_arg_extract(eax, 15, 8), ir_cst(1, 7, 0), addr));
// CF <- 1 , AF <- 1
block->add_instr(bblkid, ir_mov(af, ir_cst(1, af.size-1, 0), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(1, af.size-1, 0), addr));
// Jump to common end
block->add_instr(bblkid, ir_bcc(ir_cst(1, 0, 0), ir_cst(bblkid+2, 31, 0), ir_none(), addr));
// 2°) Branch 2 - Just reset flags
bblkid = block->new_bblock();
block->add_instr(bblkid, ir_mov(af, ir_cst(0, af.size-1, 0), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(0, af.size-1, 0), addr));
// Jump to common end
block->add_instr(bblkid, ir_bcc(ir_cst(1, 0, 0), ir_cst(bblkid+1, 31, 0), ir_none(), addr));
// 3°) Common end - Keep only 4 LSB of AL
bblkid = block->new_bblock();
block->add_instr(bblkid, ir_and(x86_arg_extract(eax, 7, 0), x86_arg_extract(eax, 7, 0), ir_cst(0xf, 7, 0), addr));
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_aad_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, imm, al, pc;
if( mode != CPUMode::X86 ){
throw illegal_instruction_exception("X86 AAD instruction is valid only in 32-bit mode");
}
tmp0 = ir_tmp(tmp_var_count++, 7, 0), // Get the size from any register
imm = ir_cst(0xa, 7, 0); // 2 byte of the encoded instruction always 0xA for AAD
al = ir_var(X86_EAX, 7,0);
// AL <- (AL + (AH ∗ imm8)) & 0xFF;
// AH <- 0
block->add_instr(bblkid, ir_mul(tmp0, ir_var(X86_EAX, 15, 8), imm, addr));
block->add_instr(bblkid, ir_add(al, al, tmp0, addr));
block->add_instr(bblkid, ir_mov(ir_var(X86_EAX, 15, 8), ir_cst(0, 7, 0), addr));
// Set flags : SF, ZF, PF
x86_set_sf(mode, al, addr, block, bblkid);
x86_set_zf(mode, al, addr, block, bblkid);
x86_set_pf(mode, al, addr, block, bblkid, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_aam_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, imm, al, pc;
if( mode != CPUMode::X86 ){
throw illegal_instruction_exception("X86 AAM instruction is valid only in 32-bit mode");
}
tmp0 = ir_tmp(tmp_var_count++, 7, 0), // Get the size from any register
imm = ir_cst(0xa, 7, 0); // 2 byte of the encoded instruction always 0xA for AAM
al = ir_var(X86_EAX, 7,0);
// AH <- AL / 10
// AL <- AL % 10
block->add_instr(bblkid, ir_mov(tmp0, al, addr));
block->add_instr(bblkid, ir_div(ir_var(X86_EAX, 15, 8), tmp0, imm, addr));
block->add_instr(bblkid, ir_mod(al, tmp0, imm, addr));
// Set flags : SF, ZF, PF
x86_set_sf(mode, al, addr, block, bblkid);
x86_set_zf(mode, al, addr, block, bblkid);
x86_set_pf(mode, al, addr, block, bblkid, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_aas_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand af, eax, cf, tmp0, tmp1, pc;
if( mode == CPUMode::X86 ){
eax = ir_var(X86_EAX, 31, 0);
af = ir_var(X86_AF, 31, 0);
cf = ir_var(X86_CF, 31, 0);
}else if( mode == CPUMode::X64 ){
throw illegal_instruction_exception("X86 AAS instruction is valid only in 32-bit mode");
}
tmp0 = ir_tmp(tmp_var_count++, af.size-1, 0), // Get the size from any register
tmp1 = ir_tmp(tmp_var_count++, af.size-1, 0);
/* If 4 LSB are > 9 or if AF is set then adjust the unpacked BCD values */
// (4 LSB) > 9
block->add_instr(bblkid, ir_bisz(tmp0, x86_arg_extract(eax, 3, 3), ir_cst(0, eax.size,0), addr));
block->add_instr(bblkid, ir_bisz(tmp1, x86_arg_extract(eax, 2, 1), ir_cst(0, eax.size,0), addr));
block->add_instr(bblkid, ir_and(tmp1, tmp1, tmp0, addr));
// AF
block->add_instr(bblkid, ir_or(tmp1, af, tmp1, addr));
// Branch depending on condition
block->add_instr(bblkid, ir_bcc(tmp1, ir_cst(bblkid+1, 31,0), ir_cst(bblkid+2, 31, 0), addr));
// 1°) Branch 1 - Do the adjust
bblkid = block->new_bblock();
// AL <- AL - 6
block->add_instr(bblkid, ir_sub(x86_arg_extract(eax, 7, 0), x86_arg_extract(eax, 7, 0), ir_cst(6, 7, 0), addr));
// AH
block->add_instr(bblkid, ir_sub(x86_arg_extract(eax, 15, 8), x86_arg_extract(eax, 15, 8), ir_cst(1, 7, 0), addr));
// CF <- 1 , AF <- 1
block->add_instr(bblkid, ir_mov(af, ir_cst(1, af.size-1, 0), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(1, af.size-1, 0), addr));
// Jump to common end
block->add_instr(bblkid, ir_bcc(ir_cst(1, 0, 0), ir_cst(bblkid+2, 31, 0), ir_none(), addr));
// 2°) Branch 2 - Just reset flags
bblkid = block->new_bblock();
block->add_instr(bblkid, ir_mov(af, ir_cst(0, af.size-1, 0), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(0, af.size-1, 0), addr));
// Jump to common end
block->add_instr(bblkid, ir_bcc(ir_cst(1, 0, 0), ir_cst(bblkid+1, 31, 0), ir_none(), addr));
// 3°) Common end - Keep only 4 LSB of AL
bblkid = block->new_bblock();
block->add_instr(bblkid, ir_and(x86_arg_extract(eax, 7, 0), x86_arg_extract(eax, 7, 0), ir_cst(0xf, 7, 0), addr));
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_adc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, prev_cf, pc;
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
}else{
op0 = dest;
}
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
res = ir_tmp(tmp_var_count++, (instr->detail->x86.operands[0].size*8)-1, 0);
if( mode == CPUMode::X86 )
prev_cf = ir_var(X86_CF, res.size-1, 0);
else if( mode == CPUMode::X64 )
prev_cf = ir_var(X64_CF, res.size-1, 0);
/* Do the add */
block->add_instr(bblkid, ir_add(res, op0, op1, addr));
block->add_instr(bblkid, ir_add(res, res, prev_cf, addr));
/* Update flags */
x86_set_zf(mode, res, addr, block, bblkid);
x86_add_set_cf(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_add_set_af(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_add_set_of(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_set_sf(mode, res, addr, block, bblkid);
x86_set_pf(mode, res, addr, block, bblkid, tmp_var_count);
/* Finally assign the result to the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, res, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_adcx_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, prev_cf, pc;
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
}else{
op0 = dest;
}
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
res = ir_tmp(tmp_var_count++, (instr->detail->x86.operands[0].size*8)-1, 0);
if( mode == CPUMode::X86 )
prev_cf = ir_var(X86_CF, res.size-1, 0);
else if( mode == CPUMode::X64 )
prev_cf = ir_var(X64_CF, res.size-1, 0);
/* Do the add */
block->add_instr(bblkid, ir_add(res, op0, op1, addr));
block->add_instr(bblkid, ir_add(res, res, prev_cf, addr));
/* Update flags */
x86_add_set_cf(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
/* Finally assign the result to the destination */
/* ADCX destination is always a general purpose reg */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_add_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, pc;
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
}else{
op0 = dest;
}
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
/* Do the add */
res = ir_tmp(tmp_var_count++, (instr->detail->x86.operands[0].size*8)-1, 0);
block->add_instr(bblkid, ir_add(res, op0, op1, addr));
/* Update flags */
x86_set_zf(mode, res, addr, block, bblkid);
x86_add_set_cf(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_add_set_af(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_add_set_of(mode, op0, op1, res, addr, block, bblkid, tmp_var_count);
x86_set_sf(mode, res, addr, block, bblkid);
x86_set_pf(mode, res, addr, block, bblkid, tmp_var_count);
/* Finally assign the result to the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, res, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_and_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, of, cf, pc;
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
}else{
op0 = dest;
}
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
/* Do the and */
res = ir_tmp(tmp_var_count++, (instr->detail->x86.operands[0].size*8)-1, 0);
block->add_instr(bblkid, ir_and(res, op0, op1, addr));
/* Update flags: SF, ZF, PF */
x86_set_zf(mode, res, addr, block, bblkid);
x86_set_sf(mode, res, addr, block, bblkid);
x86_set_pf(mode, res, addr, block, bblkid, tmp_var_count);
/* OF and CF cleared */
block->add_instr(bblkid, ir_mov(of, ir_cst(0, of.high, of.low), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(0, cf.high, cf.low), addr));
/* Finally assign the result to the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, res, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_andn_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, of, cf, pc;
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[2]), block, bblkid, tmp_var_count, true);
/* Do the not then the and */
res = ir_tmp(tmp_var_count++, (instr->detail->x86.operands[0].size*8)-1, 0);
block->add_instr(bblkid, ir_not(res, op0, addr));
block->add_instr(bblkid, ir_and(res, res, op1, addr));
/* Update flags: SF, ZF */
x86_set_zf(mode, res, addr, block, bblkid);
x86_set_sf(mode, res, addr, block, bblkid);
/* OF and CF cleared */
block->add_instr(bblkid, ir_mov(of, ir_cst(0, of.high, of.low), addr));
block->add_instr(bblkid, ir_mov(cf, ir_cst(0, cf.high, cf.low), addr));
/* Finally assign the result to the destination */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_blsi_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, of, cf, pc;
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
/* Do the not then the and */
res = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_neg(res, op0, addr));
block->add_instr(bblkid, ir_and(res, res, op0, addr));
/* Update flags: SF, ZF */
x86_set_zf(mode, res, addr, block, bblkid);
x86_set_sf(mode, res, addr, block, bblkid);
/* CF set if op0 is source is not zero */
block->add_instr(bblkid, ir_bisz(cf, op0, ir_cst(0, cf.size-1, 0), addr));
/* OF cleared */
block->add_instr(bblkid, ir_mov(of, ir_cst(0, of.high, of.low), addr));
/* Finally assign the result to the destination */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_blsmsk_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, of, cf, zf, pc;
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
zf = (mode == CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
/* res <- (op0-1) XOR op0 */
res = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_sub(res, op0, ir_cst(1, op0.size-1, 0), addr));
block->add_instr(bblkid, ir_xor(res, res, op0, addr));
/* Update flags: SF */
x86_set_sf(mode, res, addr, block, bblkid);
/* CF set if op0 is source is zero */
block->add_instr(bblkid, ir_bisz(cf, op0, ir_cst(1, cf.size-1, 0), addr));
/* OF and ZF cleared */
block->add_instr(bblkid, ir_mov(of, ir_cst(0, of.high, of.low), addr));
block->add_instr(bblkid, ir_mov(zf, ir_cst(0, of.high, of.low), addr));
/* Finally assign the result to the destination */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_blsr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, op1, dest, res, of, cf, zf, pc;
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
zf = (mode == CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
/* res <- (op0-1) AND op0 */
res = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_sub(res, op0, ir_cst(1, op0.size-1, 0), addr));
block->add_instr(bblkid, ir_and(res, res, op0, addr));
/* Update flags: SF, ZF */
x86_set_sf(mode, res, addr, block, bblkid);
x86_set_zf(mode, res, addr, block, bblkid);
/* CF set if op0 is source is zero */
block->add_instr(bblkid, ir_bisz(cf, op0, ir_cst(1, cf.size-1, 0), addr));
/* OF cleared */
block->add_instr(bblkid, ir_mov(of, ir_cst(0, of.high, of.low), addr));
/* Finally assign the result to the destination */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_bsf_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, op0, counter, tmp0, zf, pc;
IRBasicBlockId loop_test, loop_body, loop_exit, op_is_zero, op_not_zero, end;
zf = (mode == CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
op_not_zero = block->new_bblock();
loop_test = block->new_bblock();
loop_body = block->new_bblock();
loop_exit = block->new_bblock();
op_is_zero = block->new_bblock();
end = block->new_bblock();
// Update PC first because then we don't know what branch we take
pc = x86_get_pc(mode);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// op0 == 0 ??
block->add_instr(bblkid, ir_bcc(op0, ir_cst(op_not_zero, 31, 0), ir_cst(op_is_zero, 31, 0), addr));
// 1°) Branch1 : op_not_zero
counter = ir_tmp(tmp_var_count++, dest.size-1, 0);
tmp0 = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(op_not_zero, ir_mov(counter, ir_cst(0, counter.size-1, 0), addr)); // counter <- 0
block->add_instr(op_not_zero, ir_bcc(ir_cst(1, 31, 0) , ir_cst(loop_test, 31, 0), ir_none(), addr));
// loop test: while ( op0[i] == 0 )
block->add_instr(loop_test, ir_shr(tmp0, op0, counter, addr));
block->add_instr(loop_test, ir_bcc(x86_arg_extract(tmp0,0,0) , ir_cst(loop_exit, 31, 0), ir_cst(loop_body, 31, 0), addr));
// loop body: counter = counter + 1
block->add_instr(loop_body, ir_add(counter, counter, ir_cst(1, counter.size-1, 0), addr));
block->add_instr(loop_body, ir_bcc(ir_cst(1, 31, 0) , ir_cst(loop_test, 31, 0), ir_none(), addr));
// loop exit: dest <- counter and ZF <- 0
x86_adjust_reg_assign(mode, addr, block, loop_exit, tmp_var_count, dest, counter);
x86_set_zf(mode, op0, addr, block, loop_exit );
block->add_instr(loop_exit, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// 2°) Branch2: op_is_zero
// ZF <- 1
block->add_instr(op_is_zero, ir_mov(zf, ir_cst(1, zf.size-1, 0), addr));
block->add_instr(op_is_zero, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_bsr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, op0, counter, tmp0, zf, pc;
IRBasicBlockId loop_test, loop_body, loop_exit, op_is_zero, op_not_zero, end;
zf = (mode == CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
op_not_zero = block->new_bblock();
loop_test = block->new_bblock();
loop_body = block->new_bblock();
loop_exit = block->new_bblock();
op_is_zero = block->new_bblock();
end = block->new_bblock();
// Update PC first because then we don't know what branch we take
pc = x86_get_pc(mode);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// op0 == 0 ??
block->add_instr(bblkid, ir_bcc(op0, ir_cst(op_not_zero, 31, 0), ir_cst(op_is_zero, 31, 0), addr));
// 1°) Branch1 : op_not_zero
counter = ir_tmp(tmp_var_count++, dest.size-1, 0);
tmp0 = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(op_not_zero, ir_mov(counter, ir_cst((dest.size-1), counter.size-1, 0), addr)); // counter <- sizeof(op0)-1
block->add_instr(op_not_zero, ir_bcc(ir_cst(1, 31, 0) , ir_cst(loop_test, 31, 0), ir_none(), addr));
// loop test: while ( op0[i] == 0 )
block->add_instr(loop_test, ir_shr(tmp0, op0, counter, addr));
block->add_instr(loop_test, ir_bcc(x86_arg_extract(tmp0,0,0) , ir_cst(loop_exit, 31, 0), ir_cst(loop_body, 31, 0), addr));
// loop body: counter = counter - 1
block->add_instr(loop_body, ir_sub(counter, counter, ir_cst(1, counter.size-1, 0), addr));
block->add_instr(loop_body, ir_bcc(ir_cst(1, 31, 0) , ir_cst(loop_test, 31, 0), ir_none(), addr));
// loop exit: dest <- counter and ZF <- 0
x86_adjust_reg_assign(mode, addr, block, loop_exit, tmp_var_count, dest, counter);
x86_set_zf(mode, op0, addr, block, loop_exit );
block->add_instr(loop_exit, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// 2°) Branch2: op0 == 0
// ZF <- 1
block->add_instr(op_is_zero, ir_mov(zf, ir_cst(1, zf.size-1, 0), addr));
block->add_instr(op_is_zero, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_bswap_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, pc, res;
/* Get operand */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
if( dest.size == 64 ){
res = ir_tmp(tmp_var_count++, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 7, 0);
tmp1 = ir_tmp(tmp_var_count++, 7, 0);
tmp2 = ir_tmp(tmp_var_count++, 7, 0);
tmp3 = ir_tmp(tmp_var_count++, 7, 0);
tmp4 = ir_tmp(tmp_var_count++, 7, 0);
tmp5 = ir_tmp(tmp_var_count++, 7, 0);
tmp6 = ir_tmp(tmp_var_count++, 7, 0);
tmp7 = ir_tmp(tmp_var_count++, 7, 0);
block->add_instr(bblkid, ir_mov(tmp0, x86_arg_extract(dest, 7, 0), addr));
block->add_instr(bblkid, ir_mov(tmp1, x86_arg_extract(dest, 15, 8), addr));
block->add_instr(bblkid, ir_mov(tmp2, x86_arg_extract(dest, 23, 16), addr));
block->add_instr(bblkid, ir_mov(tmp3, x86_arg_extract(dest, 31, 24), addr));
block->add_instr(bblkid, ir_mov(tmp4, x86_arg_extract(dest, 39,32), addr));
block->add_instr(bblkid, ir_mov(tmp5, x86_arg_extract(dest, 47, 40), addr));
block->add_instr(bblkid, ir_mov(tmp6, x86_arg_extract(dest, 55, 48), addr));
block->add_instr(bblkid, ir_mov(tmp7, x86_arg_extract(dest, 63, 56), addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 63, 56), tmp0, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 55, 48), tmp1, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 47, 40), tmp2, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 39, 32), tmp3, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 31, 24), tmp4, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 23, 16), tmp5, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 15, 8), tmp6, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 7, 0), tmp7, addr));
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
}else if( dest.size == 32 ){
res = ir_tmp(tmp_var_count++, 31, 0);
tmp0 = ir_tmp(tmp_var_count++, 7, 0);
tmp1 = ir_tmp(tmp_var_count++, 7, 0);
tmp2 = ir_tmp(tmp_var_count++, 7, 0);
tmp3 = ir_tmp(tmp_var_count++, 7, 0);
block->add_instr(bblkid, ir_mov(tmp0, x86_arg_extract(dest, 7, 0), addr));
block->add_instr(bblkid, ir_mov(tmp1, x86_arg_extract(dest, 15, 8), addr));
block->add_instr(bblkid, ir_mov(tmp2, x86_arg_extract(dest, 23, 16), addr));
block->add_instr(bblkid, ir_mov(tmp3, x86_arg_extract(dest, 31, 24), addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 31, 24), tmp0, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 23, 16), tmp1, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 15, 8), tmp2, addr));
block->add_instr(bblkid, ir_mov(x86_arg_extract(res, 7, 0), tmp3, addr));
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, res);
}else{
throw runtime_exception("X86 BSWAP translation: accepts operands of size 32 or 64 only");
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
}
inline void x86_bt_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand base, off, cf, pc, tmp0;
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
base = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
off = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
tmp0 = ir_tmp(tmp_var_count++, base.size-1, 0);
/* cf <- bit(base, off % {16/32/64}) */
block->add_instr(bblkid, ir_mod(tmp0, off, ir_cst(base.size, off.size-1, 0), addr));
block->add_instr(bblkid, ir_shr(tmp0, base, tmp0, addr));
block->add_instr(bblkid, ir_bisz(cf, x86_arg_extract(tmp0,0,0), ir_cst(0, cf.size-1, 0), addr));
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_btc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, base, off, cf, pc, tmp0, tmp1;
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
base = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
off = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
tmp0 = ir_tmp(tmp_var_count++, base.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, base.size-1, 0);
/* cf <- bit(base, off % {16/32/64}) */
block->add_instr(bblkid, ir_mod(tmp0, off, ir_cst(base.size, off.size-1, 0), addr));
block->add_instr(bblkid, ir_shr(tmp1, base, tmp0, addr));
block->add_instr(bblkid, ir_bisz(cf, x86_arg_extract(tmp1,0,0), ir_cst(0, cf.size-1, 0), addr));
/* invert bit(base, off % ... )*/
block->add_instr(bblkid, ir_shl(tmp1, ir_cst(1, tmp0.size-1, 0), tmp0, addr));
block->add_instr(bblkid, ir_xor(tmp1, base, tmp1, addr));
/* Set the bit in the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, tmp1, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, tmp1);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_btr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, base, off, cf, pc, tmp0, tmp1;
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
base = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
off = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
tmp0 = ir_tmp(tmp_var_count++, base.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, base.size-1, 0);
/* cf <- bit(base, off % {16/32/64}) */
block->add_instr(bblkid, ir_mod(tmp0, off, ir_cst(base.size, off.size-1, 0), addr));
block->add_instr(bblkid, ir_shr(tmp1, base, tmp0, addr));
block->add_instr(bblkid, ir_bisz(cf, x86_arg_extract(tmp1,0,0), ir_cst(0, cf.size-1, 0), addr));
/* bit(base, off % ... ) <- 0 */
block->add_instr(bblkid, ir_shl(tmp1, ir_cst(1, tmp0.size-1, 0), tmp0, addr));
block->add_instr(bblkid, ir_not(tmp1, tmp1, addr));
block->add_instr(bblkid, ir_and(tmp1, base, tmp1, addr));
/* Set the bit in the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, tmp1, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, tmp1);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_bts_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, base, off, cf, pc, tmp0, tmp1;
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
base = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
off = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
tmp0 = ir_tmp(tmp_var_count++, base.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, base.size-1, 0);
/* cf <- bit(base, off % {16/32/64}) */
block->add_instr(bblkid, ir_mod(tmp0, off, ir_cst(base.size, off.size-1, 0), addr));
block->add_instr(bblkid, ir_shr(tmp1, base, tmp0, addr));
block->add_instr(bblkid, ir_bisz(cf, x86_arg_extract(tmp1,0,0), ir_cst(0, cf.size-1, 0), addr));
/* bit(base, off % ... ) <- 1 */
block->add_instr(bblkid, ir_shl(tmp1, ir_cst(1, tmp0.size-1, 0), tmp0, addr));
block->add_instr(bblkid, ir_or(tmp1, base, tmp1, addr));
/* Set the bit in the destination */
/* If the add is written in memory */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, tmp1, addr));
/* Else direct register assign */
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, tmp1);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_bzhi_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand dest, op0, op1, cf, of, pc, index, tmp0, tmp1, opsize, res;
IRBasicBlockId index_too_big = block->new_bblock(),
index_ok = block->new_bblock(),
end = block->new_bblock();
/* Get operands */
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[2]), block, bblkid, tmp_var_count, true);
index = ir_tmp(tmp_var_count++, dest.size-1, 0);
tmp0 = ir_tmp(tmp_var_count++, dest.size-1, 0);
res = ir_tmp(tmp_var_count++, dest.size-1, 0);
/* index <- op1[7:0]
* dest <- op0
* dest[size(dest)-1:index] <- 0
* cf = 1 iff index > size(dest)-1
*/
// Get index
block->add_instr(bblkid, ir_mov(index, op1, addr));
block->add_instr(bblkid, ir_and(index, index, ir_cst(0xff, index.size-1, 0), addr));
// Compare index and size operands
opsize = ir_cst(dest.size, dest.size-1, 0);
block->add_instr(bblkid, ir_sub(tmp0, opsize, ir_cst(1, opsize.size-1, 0), addr));
block->add_instr(bblkid, ir_sub(tmp0, tmp0, index, addr));
block->add_instr(bblkid, ir_bcc(x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1),
ir_cst(index_too_big, 31, 0),
ir_cst(index_ok, 31, 0),
addr));
// 1°) Index > size operands -1
block->add_instr(index_too_big, ir_mov(cf, ir_cst(1, cf.size-1, 0), addr));
block->add_instr(index_too_big, ir_mov(res, op0, addr));
x86_adjust_reg_assign(mode, addr, block, index_too_big, tmp_var_count, dest, res);
block->add_instr(index_too_big, ir_bcc(ir_cst(1, 31, 0), ir_cst(end, 31, 0), ir_none(), addr));
// 2°) Index < size operands
tmp1 = ir_tmp(tmp_var_count++, dest.size-1, 0);
block->add_instr(index_ok, ir_mov(cf, ir_cst(0, cf.size-1, 0), addr ));
// Get mask size(dest)-1 .. index
block->add_instr(index_ok, ir_shl(tmp0, ir_cst(1, index.size-1, 0), index, addr));
block->add_instr(index_ok, ir_neg(tmp1, tmp0, addr));
block->add_instr(index_ok, ir_or(tmp1, tmp1, tmp0, addr));
block->add_instr(index_ok, ir_not(tmp1, tmp1, addr));
// Mask res
block->add_instr(index_ok, ir_mov(res, dest, addr));
block->add_instr(index_ok, ir_and(res, op0, tmp1, addr));
x86_adjust_reg_assign(mode, addr, block, index_ok, tmp_var_count, dest, res);
block->add_instr(index_ok, ir_bcc(ir_cst(1, 31, 0), ir_cst(end, 31, 0), ir_none(), addr));
// 3° ) Common end: set flags and pc
// OF cleared
block->add_instr(end, ir_mov(of, ir_cst(0, of.size-1, 0), addr ));
// Set zf, cf
x86_set_sf(mode, res, addr, block, end);
x86_set_zf(mode, res, addr, block, end);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(end, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
bblkid = end;
return;
}
inline void x86_call_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand op0, sp, pc;
/* Increment program counter first because
* the call is maybe relative to EIP/RIP */
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.high, 0), addr));
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
sp = (mode == CPUMode::X86)? ir_var(X86_ESP, 31, 0): ir_var(X64_RSP, 63, 0);
/* Get and push next instruction address */
block->add_instr(bblkid, ir_sub(sp, sp, ir_cst(pc.size/8, pc.size-1, 0), addr));
block->add_instr(bblkid, ir_stm(sp, pc, addr));
/* Jump to called address */
block->add_instr(bblkid, ir_jcc(ir_cst(1, pc.size-1, 0), op0, ir_none(), addr));
return;
}
inline void x86_cbw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg, pc;
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg = (mode==CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* ax <- sign_extend(al) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg, 7, 7), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
block->add_instr(ext1, ir_mov(x86_arg_extract(reg, 15, 8), ir_cst(0xff, 7, 0), addr));
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
block->add_instr(ext0, ir_mov(x86_arg_extract(reg, 15, 8), ir_cst(0x0, 7, 0), addr));
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cdq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg_a, reg_d, pc, cst0, cst1;
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg_a = (mode==CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
reg_d = (mode==CPUMode::X86)? ir_var(X86_EDX, 31, 0) : ir_var(X64_RDX, 63, 0);
reg_d = x86_arg_extract(reg_d, 31, 0);
cst1 = ir_cst(0xffffffff, 31, 0);
cst0 = ir_cst(0, 31, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* edx <- replicate(eax[31]) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg_a, 31, 31), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
x86_adjust_reg_assign(mode, addr, block, ext1, tmp_var_count, reg_d, cst1);
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
x86_adjust_reg_assign(mode, addr, block, ext0, tmp_var_count, reg_d, cst0);
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cdqe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg, pc;
if( mode == CPUMode::X86 ){
throw runtime_exception("CDQE: invalid instruction in X86 mode");
}
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg = ir_var(X64_RAX, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* rax <- sign_extend(eax) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg, 31, 31), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
block->add_instr(ext1, ir_mov(x86_arg_extract(reg, 63, 32), ir_cst(0xffffffff, 31, 0), addr));
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
block->add_instr(ext0, ir_mov(x86_arg_extract(reg, 63, 32), ir_cst(0x0, 31, 0), addr));
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_clc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, pc;
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// cf <- 0
block->add_instr(bblkid, ir_mov(cf, ir_cst(0x0, cf.size-1, 0), addr));
return;
}
inline void x86_cld_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand df, pc;
df = (mode==CPUMode::X86)? ir_var(X86_DF, 31, 0) : ir_var(X64_DF, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// df <- 0
block->add_instr(bblkid, ir_mov(df, ir_cst(0x0, df.size-1, 0), addr));
return;
}
inline void x86_cli_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand if_flag, pc;
if_flag = (mode==CPUMode::X86)? ir_var(X86_IF, 31, 0) : ir_var(X64_IF, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// if_flag <- 0
block->add_instr(bblkid, ir_mov(if_flag, ir_cst(0x0, if_flag.size-1, 0), addr));
return;
}
inline void x86_cmc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, pc;
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// complement cf
block->add_instr(bblkid, ir_xor(cf, cf, ir_cst(0x1, cf.size-1, 0), addr));
return;
}
inline void x86_cmova_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, zf, pc, tmp0, tmp1, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
tmp1 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if CF = 0 and ZF = 0
block->add_instr(bblkid, ir_not(tmp0, cf, addr));
block->add_instr(bblkid, ir_not(tmp1, zf, addr));
block->add_instr(bblkid, ir_and(tmp1, tmp1, tmp0, addr));
block->add_instr(bblkid, ir_bcc(tmp1, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovae_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if CF = 0
block->add_instr(bblkid, ir_bcc(cf, ir_cst(dont_mov,31, 0), ir_cst(do_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if CF = 1
block->add_instr(bblkid, ir_bcc(cf, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovbe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand cf, zf, pc, tmp0, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
cf = (mode==CPUMode::X86)? ir_var(X86_CF, 31, 0) : ir_var(X64_CF, 63, 0);
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if CF = 1 or ZF = 1
block->add_instr(bblkid, ir_or(tmp0, cf, zf, addr));
block->add_instr(bblkid, ir_bcc(tmp0, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmove_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand zf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if zf = 1
block->add_instr(bblkid, ir_bcc(zf, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, of, zf, pc, tmp0, tmp1, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
tmp1 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if ZF = 0 and OF = SF
block->add_instr(bblkid, ir_xor(tmp0, sf, of, addr));
block->add_instr(bblkid, ir_not(tmp0, tmp0, addr));
block->add_instr(bblkid, ir_not(tmp1, zf, addr));
block->add_instr(bblkid, ir_and(tmp1, tmp1, tmp0, addr));
block->add_instr(bblkid, ir_bcc(tmp1, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovge_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, of, zf, pc, tmp0, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if OF = SF
block->add_instr(bblkid, ir_xor(tmp0, sf, of, addr));
block->add_instr(bblkid, ir_not(tmp0, tmp0, addr));
block->add_instr(bblkid, ir_bcc(tmp0, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovl_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, of, zf, pc, tmp0, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if OF != SF
block->add_instr(bblkid, ir_xor(tmp0, sf, of, addr));
block->add_instr(bblkid, ir_bcc(tmp0, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovle_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, of, zf, pc, tmp0, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
tmp0 = ir_tmp(tmp_var_count++, 0, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if ZF = 1 or OF != SF
block->add_instr(bblkid, ir_xor(tmp0, sf, of, addr));
block->add_instr(bblkid, ir_or(tmp0, x86_arg_extract(zf, 0, 0), tmp0, addr));
block->add_instr(bblkid, ir_bcc(tmp0, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovne_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand zf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
zf = (mode==CPUMode::X86)? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if ZF = 0
block->add_instr(bblkid, ir_bcc(zf, ir_cst(dont_mov,31, 0), ir_cst(do_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovno_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand of, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if OF = 0
block->add_instr(bblkid, ir_bcc(of, ir_cst(dont_mov,31, 0), ir_cst(do_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovnp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
pf = (mode==CPUMode::X86)? ir_var(X86_PF, 31, 0) : ir_var(X64_PF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if PF = 0
block->add_instr(bblkid, ir_bcc(pf, ir_cst(dont_mov,31, 0), ir_cst(do_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovns_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if SF = 0
block->add_instr(bblkid, ir_bcc(sf, ir_cst(dont_mov,31, 0), ir_cst(do_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovo_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand of, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
of = (mode==CPUMode::X86)? ir_var(X86_OF, 31, 0) : ir_var(X64_OF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if OF = 1
block->add_instr(bblkid, ir_bcc(of, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
pf = (mode==CPUMode::X86)? ir_var(X86_PF, 31, 0) : ir_var(X64_PF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if OF = 1
block->add_instr(bblkid, ir_bcc(pf, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmovs_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand sf, pc, op0, op1;
IRBasicBlockId do_mov = block->new_bblock(),
dont_mov = block->new_bblock(),
end = block->new_bblock();
sf = (mode==CPUMode::X86)? ir_var(X86_SF, 31, 0) : ir_var(X64_SF, 63, 0);
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
// test if SF = 1
block->add_instr(bblkid, ir_bcc(sf, ir_cst(do_mov,31, 0), ir_cst(dont_mov, 31, 0), addr));
// do mov
x86_adjust_reg_assign(mode, addr, block, do_mov, tmp_var_count, op0, op1);
block->add_instr(do_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// dont mov - do nothing
/* but still assign op0 to itself if 64 bits (because in 64 bits, the instruction
* clears the upper bits when operands are 32 bits, even when the condition
* is false */
if( mode == CPUMode::X64 && op0.size == 32 ){
x86_adjust_reg_assign(mode, addr, block, dont_mov, tmp_var_count, op0, op0);
}
block->add_instr(dont_mov, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cmp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, op0, op1, tmp;
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
// Check if op1 is a imm and needs sign extend
if( op1.size < op0.size && op1.is_cst()){
op1 = ir_cst(cst_sign_extend(op1.size, op1.cst()), op0.size-1, 0);
}
// tmp <- op0 - op1
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_sub(tmp, op0, op1, addr));
// Update flags
x86_set_pf( mode, tmp, addr, block, bblkid, tmp_var_count );
x86_set_zf( mode, tmp, addr, block, bblkid );
x86_set_sf( mode, tmp, addr, block, bblkid );
x86_sub_set_of( mode, op0, op1, tmp, addr, block, bblkid, tmp_var_count );
x86_sub_set_cf( mode, op0, op1, tmp, addr, block, bblkid, tmp_var_count );
x86_sub_set_af( mode, op0, op1, tmp, addr, block, bblkid, tmp_var_count );
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_cmpsb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, tmp0, tmp1, tmp2, si, di, df;
IRBasicBlockId inc, dec, end, prefix_start;
/* Get operands */
si = (mode == CPUMode::X86) ? ir_var(X86_ESI, 31, 0) : ir_var(X64_RSI, 63, 0);
di = (mode == CPUMode::X86) ? ir_var(X86_EDI, 31, 0) : ir_var(X64_RDI, 63, 0);
df = (mode == CPUMode::X86) ? ir_var(X86_DF, 31, 0) : ir_var(X64_DF, 63, 0);
prefix_start = _x86_init_prefix(mode, instr, addr, block, bblkid);
inc = block->new_bblock();
dec = block->new_bblock();
end = block->new_bblock();
/* Read bytes from memory and compare them */
tmp0 = ir_tmp(tmp_var_count++, 7, 0);
tmp1 = ir_tmp(tmp_var_count++, 7, 0);
tmp2 = ir_tmp(tmp_var_count++, 7, 0);
block->add_instr(bblkid, ir_ldm(tmp0, si, addr));
block->add_instr(bblkid, ir_ldm(tmp1, di, addr));
block->add_instr(bblkid, ir_sub(tmp2, tmp0, tmp1, addr));
// Update flags
x86_set_pf( mode, tmp2, addr, block, bblkid, tmp_var_count );
x86_set_zf( mode, tmp2, addr, block, bblkid );
x86_set_sf( mode, tmp2, addr, block, bblkid );
x86_sub_set_of( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_cf( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_af( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
// Increment or decrement ESI/EDI according to DF
block->add_instr(bblkid, ir_bcc(df, ir_cst(dec, 31, 0), ir_cst(inc, 31, 0), addr));
block->add_instr(inc, ir_add(si, si, ir_cst(1, si.size-1, 0), addr));
block->add_instr(inc, ir_add(di, di, ir_cst(1, di.size-1, 0), addr));
block->add_instr(inc, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
block->add_instr(dec, ir_sub(si, si, ir_cst(1, si.size-1, 0), addr));
block->add_instr(dec, ir_sub(di, di, ir_cst(1, di.size-1, 0), addr));
block->add_instr(dec, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
/* Add prefix if any */
_x86_end_prefix(mode, instr, addr, block, prefix_start, end, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(end, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
bblkid = end;
return;
}
inline void x86_cmpsd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, tmp0, tmp1, tmp2, si, di, df;
IRBasicBlockId inc, dec, end, prefix_start;
/* Get operands */
si = (mode == CPUMode::X86) ? ir_var(X86_ESI, 31, 0) : ir_var(X64_RSI, 63, 0);
di = (mode == CPUMode::X86) ? ir_var(X86_EDI, 31, 0) : ir_var(X64_RDI, 63, 0);
df = (mode == CPUMode::X86) ? ir_var(X86_DF, 31, 0) : ir_var(X64_DF, 63, 0);
prefix_start = _x86_init_prefix(mode, instr, addr, block, bblkid);
inc = block->new_bblock();
dec = block->new_bblock();
end = block->new_bblock();
/* Read dwords from memory and compare them */
tmp0 = ir_tmp(tmp_var_count++, 31, 0);
tmp1 = ir_tmp(tmp_var_count++, 31, 0);
tmp2 = ir_tmp(tmp_var_count++, 31, 0);
block->add_instr(bblkid, ir_ldm(tmp0, si, addr));
block->add_instr(bblkid, ir_ldm(tmp1, di, addr));
block->add_instr(bblkid, ir_sub(tmp2, tmp0, tmp1, addr));
// Update flags
x86_set_pf( mode, tmp2, addr, block, bblkid, tmp_var_count );
x86_set_zf( mode, tmp2, addr, block, bblkid );
x86_set_sf( mode, tmp2, addr, block, bblkid );
x86_sub_set_of( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_cf( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_af( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
// Increment or decrement ESI/EDI according to DF
block->add_instr(bblkid, ir_bcc(df, ir_cst(dec, 31, 0), ir_cst(inc, 31, 0), addr));
block->add_instr(inc, ir_add(si, si, ir_cst(4, si.size-1, 0), addr));
block->add_instr(inc, ir_add(di, di, ir_cst(4, di.size-1, 0), addr));
block->add_instr(inc, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
block->add_instr(dec, ir_sub(si, si, ir_cst(4, si.size-1, 0), addr));
block->add_instr(dec, ir_sub(di, di, ir_cst(4, di.size-1, 0), addr));
block->add_instr(dec, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
/* Add prefix if any */
_x86_end_prefix(mode, instr, addr, block, prefix_start, end, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(end, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
bblkid = end;
return;
}
inline void x86_cmpsq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, tmp0, tmp1, tmp2, si, di, df;
IRBasicBlockId inc, dec, end, prefix_start;
if( mode == CPUMode::X86 ){
throw runtime_exception("CMPSQ: instruction is invalid in X86 mode");
}
/* Get operands */
si = ir_var(X64_RSI, 63, 0);
di = ir_var(X64_RDI, 63, 0);
df = ir_var(X64_DF, 63, 0);
prefix_start = _x86_init_prefix(mode, instr, addr, block, bblkid);
inc = block->new_bblock();
dec = block->new_bblock();
end = block->new_bblock();
/* Read words from memory and compare them */
tmp0 = ir_tmp(tmp_var_count++, 63, 0);
tmp1 = ir_tmp(tmp_var_count++, 63, 0);
tmp2 = ir_tmp(tmp_var_count++, 63, 0);
block->add_instr(bblkid, ir_ldm(tmp0, si, addr));
block->add_instr(bblkid, ir_ldm(tmp1, di, addr));
block->add_instr(bblkid, ir_sub(tmp2, tmp0, tmp1, addr));
// Update flags
x86_set_pf( mode, tmp2, addr, block, bblkid, tmp_var_count );
x86_set_zf( mode, tmp2, addr, block, bblkid );
x86_set_sf( mode, tmp2, addr, block, bblkid );
x86_sub_set_of( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_cf( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_af( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
// Increment or decrement ESI/EDI according to DF
block->add_instr(bblkid, ir_bcc(df, ir_cst(dec, 31, 0), ir_cst(inc, 31, 0), addr));
block->add_instr(inc, ir_add(si, si, ir_cst(8, si.size-1, 0), addr));
block->add_instr(inc, ir_add(di, di, ir_cst(8, di.size-1, 0), addr));
block->add_instr(inc, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
block->add_instr(dec, ir_sub(si, si, ir_cst(8, si.size-1, 0), addr));
block->add_instr(dec, ir_sub(di, di, ir_cst(8, di.size-1, 0), addr));
block->add_instr(dec, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
/* Add prefix if any */
_x86_end_prefix(mode, instr, addr, block, prefix_start, end, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(end, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
bblkid = end;
return;
}
inline void x86_cmpsw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, tmp0, tmp1, tmp2, si, di, df;
IRBasicBlockId inc, dec, end, prefix_start;
/* Get operands */
si = (mode == CPUMode::X86) ? ir_var(X86_ESI, 31, 0) : ir_var(X64_RSI, 63, 0);
di = (mode == CPUMode::X86) ? ir_var(X86_EDI, 31, 0) : ir_var(X64_RDI, 63, 0);
df = (mode == CPUMode::X86) ? ir_var(X86_DF, 31, 0) : ir_var(X64_DF, 63, 0);
prefix_start = _x86_init_prefix(mode, instr, addr, block, bblkid);
inc = block->new_bblock();
dec = block->new_bblock();
end = block->new_bblock();
/* Read words from memory and compare them */
tmp0 = ir_tmp(tmp_var_count++, 15, 0);
tmp1 = ir_tmp(tmp_var_count++, 15, 0);
tmp2 = ir_tmp(tmp_var_count++, 15, 0);
block->add_instr(bblkid, ir_ldm(tmp0, si, addr));
block->add_instr(bblkid, ir_ldm(tmp1, di, addr));
block->add_instr(bblkid, ir_sub(tmp2, tmp0, tmp1, addr));
// Update flags
x86_set_pf( mode, tmp2, addr, block, bblkid, tmp_var_count );
x86_set_zf( mode, tmp2, addr, block, bblkid );
x86_set_sf( mode, tmp2, addr, block, bblkid );
x86_sub_set_of( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_cf( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
x86_sub_set_af( mode, tmp0, tmp1, tmp2, addr, block, bblkid, tmp_var_count );
// Increment or decrement ESI/EDI according to DF
block->add_instr(bblkid, ir_bcc(df, ir_cst(dec, 31, 0), ir_cst(inc, 31, 0), addr));
block->add_instr(inc, ir_add(si, si, ir_cst(2, si.size-1, 0), addr));
block->add_instr(inc, ir_add(di, di, ir_cst(2, di.size-1, 0), addr));
block->add_instr(inc, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
block->add_instr(dec, ir_sub(si, si, ir_cst(2, si.size-1, 0), addr));
block->add_instr(dec, ir_sub(di, di, ir_cst(2, di.size-1, 0), addr));
block->add_instr(dec, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
/* Add prefix if any */
_x86_end_prefix(mode, instr, addr, block, prefix_start, end, tmp_var_count);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(end, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
bblkid = end;
return;
}
inline void x86_cmpxchg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, dest, op0, op1, ax, zf, tmp;
IRBasicBlockId eq, neq, end;
eq = block->new_bblock();
neq = block->new_bblock();
end = block->new_bblock();
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
ax = (mode == CPUMode::X86) ? ir_var(X86_EAX, op0.size-1, 0) : ir_var(X64_RAX, op0.size-1, 0);
zf = (mode == CPUMode::X86) ? ir_var(X86_ZF, 31, 0) : ir_var(X64_ZF, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* Compare op0 and op1 */
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_sub(tmp, ax, op0, addr ));
/* Set flags */
x86_set_pf(mode, tmp, addr, block, bblkid, tmp_var_count);
x86_set_sf(mode, tmp, addr, block, bblkid );
x86_set_zf(mode, tmp, addr, block, bblkid );
x86_sub_set_af(mode, ax, op0, tmp, addr, block, bblkid, tmp_var_count);
x86_sub_set_cf(mode, ax, op0, tmp, addr, block, bblkid, tmp_var_count);
x86_sub_set_of(mode, ax, op0, tmp, addr, block, bblkid, tmp_var_count);
/* Exchange values depending on zf */
block->add_instr(bblkid, ir_bcc(zf, ir_cst(eq, 31, 0), ir_cst(neq, 31, 0), addr));
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(eq, ir_stm(op0, op1, addr));
}else{
x86_adjust_reg_assign(mode, addr, block, eq, tmp_var_count, op0, op1);
}
block->add_instr(eq, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
x86_adjust_reg_assign(mode, addr, block, neq, tmp_var_count, ax, op0);
block->add_instr(neq, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cpuid_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid, int& tmp_var_count){
IRBasicBlockId leaf_0 = block->new_bblock(),
end = block->new_bblock();
IROperand eax = (mode == CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
IROperand ebx = (mode == CPUMode::X86)? ir_var(X86_EBX, 31, 0) : ir_var(X64_RBX, 63, 0);
IROperand ecx = (mode == CPUMode::X86)? ir_var(X86_ECX, 31, 0) : ir_var(X64_RCX, 63, 0);
IROperand edx = (mode == CPUMode::X86)? ir_var(X86_EDX, 31, 0) : ir_var(X64_RDX, 63, 0);
/* Test eax to know what cpuid leaf is requested */
block->add_instr(bblkid, ir_bcc(eax, ir_cst(end, 31, 0), ir_cst(leaf_0, 31, 0), addr));
/* Leaf 0
* Return the CPU's manufacturer ID string in ebx, edx and ecx
* Set EAX to the higher supported leaf */
// Set registers to "GenuineIntel"
x86_adjust_reg_assign(mode, addr, block, leaf_0, tmp_var_count, ebx, ir_cst(0x756e6547, 31, 0));
x86_adjust_reg_assign(mode, addr, block, leaf_0, tmp_var_count, edx, ir_cst(0x49656e69, 31, 0));
x86_adjust_reg_assign(mode, addr, block, leaf_0, tmp_var_count, ecx, ir_cst(0x6c65746e, 31, 0));
// Set eax to 0 because other leafs are not supported yet
x86_adjust_reg_assign(mode, addr, block, leaf_0, tmp_var_count, eax, ir_cst(0, 31, 0));
block->add_instr(leaf_0, ir_bcc(ir_cst(1, 31, 0), ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cqo_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg_a, reg_d, pc, cst0, cst1;
if( mode == CPUMode::X86 ){
throw runtime_exception("CQO: invalid instruction in X86 mode");
}
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg_a = ir_var(X64_RAX, 63, 0);
reg_d = ir_var(X64_RDX, 63, 0);
cst1 = ir_cst(0xffffffffffffffff, 63, 0);
cst0 = ir_cst(0, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* edx <- replicate(eax[63]) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg_a, 63, 63), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
x86_adjust_reg_assign(mode, addr, block, ext1, tmp_var_count, reg_d, cst1);
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
x86_adjust_reg_assign(mode, addr, block, ext0, tmp_var_count, reg_d, cst0);
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cwd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg_a, reg_d, pc;
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg_a = (mode==CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
reg_d = (mode==CPUMode::X86)? ir_var(X86_EDX, 31, 0) : ir_var(X64_RDX, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* dx <- replicate(ax[15]) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg_a, 15, 15), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
block->add_instr(ext1, ir_mov(x86_arg_extract(reg_d, 15, 0), ir_cst(0xffff, 15, 0), addr));
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
block->add_instr(ext0, ir_mov(x86_arg_extract(reg_d, 15, 0), ir_cst(0x0, 15, 0), addr));
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_cwde_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand tmp0, reg, pc;
IRBasicBlockId ext0 = block->new_bblock(),
ext1 = block->new_bblock(),
end = block->new_bblock();
reg = (mode==CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* eax <- sign_extend(ax) */
block->add_instr(bblkid, ir_bcc(x86_arg_extract(reg, 15, 15), ir_cst(ext1, 31, 0), ir_cst(ext0, 31, 0), addr));
// extend 1
if( mode == CPUMode::X64 ){ // zero higher bits
block->add_instr(ext1, ir_mov(x86_arg_extract(reg, 63, 32), ir_cst(0, 31, 0), addr));
}
block->add_instr(ext1, ir_mov(x86_arg_extract(reg, 31, 16), ir_cst(0xffff, 15, 0), addr));
block->add_instr(ext1, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
// extend 0
if( mode == CPUMode::X64 ){ // zero higher bits
block->add_instr(ext0, ir_mov(x86_arg_extract(reg, 63, 32), ir_cst(0, 31, 0), addr));
}
block->add_instr(ext0, ir_mov(x86_arg_extract(reg, 31, 16), ir_cst(0x0, 15, 0), addr));
block->add_instr(ext0, ir_bcc(ir_cst(1, 31, 0) , ir_cst(end, 31, 0), ir_none(), addr));
bblkid = end;
return;
}
inline void x86_dec_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, dest, op0, tmp;
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
/* Decrement op0 */
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_sub(tmp, op0, ir_cst(1, op0.size-1, 0), addr ));
/* Set flags (except CF) */
x86_set_pf(mode, tmp, addr, block, bblkid, tmp_var_count);
x86_set_sf(mode, tmp, addr, block, bblkid );
x86_set_zf(mode, tmp, addr, block, bblkid );
x86_sub_set_af(mode, op0, ir_cst(1, op0.size-1, 0), tmp, addr, block, bblkid, tmp_var_count);
x86_sub_set_of(mode, op0, ir_cst(1, op0.size-1, 0), tmp, addr, block, bblkid, tmp_var_count);
/* Store result */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, tmp, addr));
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, tmp);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_div_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, op0, dividend, remainder, tmp, ax, dx, tmp_dividend, tmp_remainder;
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
ax = (mode == CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
dx = (mode == CPUMode::X86)? ir_var(X86_EDX, 31, 0) : ir_var(X64_RDX, 63, 0);
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp_dividend = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp_remainder = ir_tmp(tmp_var_count++, op0.size-1, 0);
if( op0.size == 8 ){
dividend = x86_arg_extract(ax, 7, 0);
remainder = x86_arg_extract(ax, 15, 8);
}else{
dividend = x86_arg_extract(ax, op0.size-1, 0);
remainder = x86_arg_extract(dx, op0.size-1, 0);
}
/* Do the div */
block->add_instr(bblkid, ir_mov(tmp, x86_arg_extract(ax, op0.size-1, 0), addr));
block->add_instr(bblkid, ir_div(tmp_dividend, tmp , op0, addr ));
block->add_instr(bblkid, ir_mod(tmp_remainder, tmp , op0, addr ));
/* Assign results to registers */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dividend, tmp_dividend);
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, remainder, tmp_remainder);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_idiv_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, op0, ax, dx, tmp, dividend, remainder, tmp_dividend, tmp_remainder;
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
ax = (mode == CPUMode::X86)? ir_var(X86_EAX, 31, 0) : ir_var(X64_RAX, 63, 0);
dx = (mode == CPUMode::X86)? ir_var(X86_EDX, 31, 0) : ir_var(X64_RDX, 63, 0);
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp_dividend = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp_remainder = ir_tmp(tmp_var_count++, op0.size-1, 0);
if( op0.size == 8 ){
dividend = x86_arg_extract(ax, 7, 0);
remainder = x86_arg_extract(ax, 15, 8);
}else{
dividend = x86_arg_extract(ax, op0.size-1, 0);
remainder = x86_arg_extract(dx, op0.size-1, 0);
}
/* Quotient in *ax, remainder in *dx */
block->add_instr(bblkid, ir_mov(tmp, x86_arg_extract(ax, op0.size-1, 0), addr));
block->add_instr(bblkid, ir_sdiv(tmp_dividend, tmp , op0, addr ));
block->add_instr(bblkid, ir_smod(tmp_remainder, tmp , op0, addr ));
/* Assign results to registers */
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dividend, tmp_dividend);
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, remainder, tmp_remainder);
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_imul_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, op0, op1, op2, lower, higher, tmp0, tmp1, ax, tmp2, tmp3, tmp4, cf, of;
cf = (mode == CPUMode::X86)? ir_var(X86_CF, 31, 0): ir_var(X64_CF, 63, 0);
of = (mode == CPUMode::X86)? ir_var(X86_OF, 31, 0): ir_var(X64_OF, 63, 0);
/* One-operand form */
if( instr->detail->x86.op_count == 1 ){
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
ax = (mode == CPUMode::X86)? ir_var(X86_EAX, op0.size-1, 0): ir_var(X64_RAX, op0.size-1, 0);
if( op0.size == 8 ){
lower = (mode == CPUMode::X86)? ir_var(X86_EAX, 7, 0): ir_var(X64_RAX, 7, 0);
higher = (mode == CPUMode::X86)? ir_var(X86_EAX, 15, 8): ir_var(X64_RAX, 15, 8);
}else{
lower = (mode == CPUMode::X86)? ir_var(X86_EAX, op0.size-1, 0): ir_var(X64_RAX, op0.size-1, 0);
higher = (mode == CPUMode::X86)? ir_var(X86_EDX, op0.size-1, 0): ir_var(X64_RDX, op0.size-1, 0);
}
tmp0 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp2 = ir_tmp(tmp_var_count++, 0, 0);
tmp3 = ir_tmp(tmp_var_count++, 0, 0);
/* Do the multiplication */
block->add_instr(bblkid, ir_smull(tmp0, ax, op0, addr));
block->add_instr(bblkid, ir_smulh(tmp1, ax, op0, addr));
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, lower, tmp0);
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, higher, tmp1);
/* Set OF and CF iff the higher:lower != signextend(lower)
* SO we do
* higher==0 && lower[n-1] == 0
* OR higher==0xfff.... && lower[n-1] == 1 */
block->add_instr(bblkid, ir_bisz(tmp2, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_not(tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_and(tmp2, tmp2, tmp3, addr));
block->add_instr(bblkid, ir_not(tmp1, tmp1, addr));
block->add_instr(bblkid, ir_bisz(tmp3, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_and(tmp3, tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_or(tmp3, tmp3, tmp2, addr));
block->add_instr(bblkid, ir_bisz(cf, tmp3, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_bisz(of, tmp3, ir_cst(1, 0, 0), addr));
/* Two-operands form */
}else if( instr->detail->x86.op_count == 2){
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
tmp0 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp2 = ir_tmp(tmp_var_count++, 0, 0);
tmp3 = ir_tmp(tmp_var_count++, 0, 0);
/* Do the multiplication */
block->add_instr(bblkid, ir_smull(tmp0, op0, op1, addr));
block->add_instr(bblkid, ir_smulh(tmp1, op0, op1, addr));
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, op0, tmp0);
/* Set OF and CF iff the higher:lower != signextend(lower)
* SO we do
* higher==0 && lower[n-1] == 0
* OR higher==0xfff.... && lower[n-1] == 1 */
block->add_instr(bblkid, ir_bisz(tmp2, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_not(tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_and(tmp2, tmp2, tmp3, addr));
block->add_instr(bblkid, ir_not(tmp1, tmp1, addr));
block->add_instr(bblkid, ir_bisz(tmp3, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_and(tmp3, tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_or(tmp3, tmp3, tmp2, addr));
block->add_instr(bblkid, ir_bisz(cf, tmp3, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_bisz(of, tmp3, ir_cst(1, 0, 0), addr));
/* Three-operands form */
}else{
/* Get operands */
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
op1 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[1]), block, bblkid, tmp_var_count, true);
op2 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[2]), block, bblkid, tmp_var_count, true);
if( op2.size == 8 )
op2 = ir_cst(op2.cst(), op1.size-1, 0); // Already sign extended in IROperand() constructor
tmp0 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp1 = ir_tmp(tmp_var_count++, op0.size-1, 0);
tmp2 = ir_tmp(tmp_var_count++, 0, 0);
tmp3 = ir_tmp(tmp_var_count++, 0, 0);
/* Do the multiplication */
block->add_instr(bblkid, ir_smull(tmp0, op1, op2, addr));
block->add_instr(bblkid, ir_smulh(tmp1, op1, op2, addr));
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, op0, tmp0);
/* Set OF and CF iff the higher:lower != signextend(lower)
* SO we do
* higher==0 && lower[n-1] == 0
* OR higher==0xfff.... && lower[n-1] == 1 */
block->add_instr(bblkid, ir_bisz(tmp2, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_not(tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_and(tmp2, tmp2, tmp3, addr));
block->add_instr(bblkid, ir_not(tmp1, tmp1, addr));
block->add_instr(bblkid, ir_bisz(tmp3, tmp1, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_and(tmp3, tmp3, x86_arg_extract(tmp0, tmp0.size-1, tmp0.size-1), addr));
block->add_instr(bblkid, ir_or(tmp3, tmp3, tmp2, addr));
block->add_instr(bblkid, ir_bisz(cf, tmp3, ir_cst(1, 0, 0), addr));
block->add_instr(bblkid, ir_bisz(of, tmp3, ir_cst(1, 0, 0), addr));
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_inc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, dest, op0, tmp;
/* Get operands */
dest = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
op0 = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count, true);
/* Increment op0 */
tmp = ir_tmp(tmp_var_count++, op0.size-1, 0);
block->add_instr(bblkid, ir_add(tmp, op0, ir_cst(1, op0.size-1, 0), addr ));
/* Set flags (except CF) */
x86_set_pf(mode, tmp, addr, block, bblkid, tmp_var_count);
x86_set_sf(mode, tmp, addr, block, bblkid );
x86_set_zf(mode, tmp, addr, block, bblkid );
x86_sub_set_af(mode, op0, ir_cst(1, op0.size-1, 0), tmp, addr, block, bblkid, tmp_var_count);
x86_sub_set_of(mode, op0, ir_cst(1, op0.size-1, 0), tmp, addr, block, bblkid, tmp_var_count);
/* Store result */
if( instr->detail->x86.operands[0].type == X86_OP_MEM ){
block->add_instr(bblkid, ir_stm(dest, tmp, addr));
}else{
x86_adjust_reg_assign(mode, addr, block, bblkid, tmp_var_count, dest, tmp);
}
// Update PC
pc = x86_get_pc(mode);
block->add_instr(bblkid, ir_add(pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
return;
}
inline void x86_int_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, num, next_pc;
/* Get operands */
pc = x86_get_pc(mode);
next_pc = ir_tmp(tmp_var_count++, pc.size-1, 0);
block->add_instr(bblkid, ir_add(next_pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
num = x86_arg_translate(mode, addr, &(instr->detail->x86.operands[0]), block, bblkid, tmp_var_count);
/* Create interrupt */
block->add_instr(bblkid, ir_int(num, next_pc, addr));
return;
}
inline void x86_int3_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock* block, IRBasicBlockId& bblkid , int& tmp_var_count){
IROperand pc, num, next_pc;
/* Get operands */
pc = x86_get_pc(mode);
next_pc = ir_tmp(tmp_var_count++, pc.size-1, 0);
block->add_instr(bblkid, ir_add(next_pc, pc, ir_cst(instr->size, pc.size-1, 0), addr));
/* Create interrupt 3 */
block->add_instr(bblkid, ir_int(ir_cst(3,
gitextract_uvwwhzll/
├── Dockerfile
├── Makefile
├── README.md
├── bin/
│ └── .gitignore
├── bindings/
│ ├── py_arch.cpp
│ ├── py_module.cpp
│ ├── py_ropchain.cpp
│ ├── py_ropium.cpp
│ ├── python_bindings.hpp
│ └── utils.cpp
├── cli-tool/
│ └── ropium
├── libropium/
│ ├── arch/
│ │ ├── arch.cpp
│ │ ├── archX86.cpp
│ │ └── disassembler.cpp
│ ├── compiler/
│ │ ├── compiler.cpp
│ │ ├── il.cpp
│ │ ├── strategy_graph.cpp
│ │ ├── strategy_rules.cpp
│ │ └── systems.cpp
│ ├── database/
│ │ └── database.cpp
│ ├── dependencies/
│ │ └── murmur3/
│ │ ├── murmur3.c
│ │ └── murmur3.h
│ ├── include/
│ │ ├── arch.hpp
│ │ ├── assertion.hpp
│ │ ├── compiler.hpp
│ │ ├── constraint.hpp
│ │ ├── database.hpp
│ │ ├── disassembler.hpp
│ │ ├── exception.hpp
│ │ ├── expression.hpp
│ │ ├── il.hpp
│ │ ├── ir.hpp
│ │ ├── ropchain.hpp
│ │ ├── ropium.hpp
│ │ ├── simplification.hpp
│ │ ├── strategy.hpp
│ │ ├── symbolic.hpp
│ │ ├── systems.hpp
│ │ └── utils.hpp
│ ├── ir/
│ │ └── ir.cpp
│ ├── ropchain/
│ │ ├── assertion.cpp
│ │ ├── constraint.cpp
│ │ ├── gadget.cpp
│ │ └── ropchain.cpp
│ ├── symbolic/
│ │ ├── expression.cpp
│ │ ├── simplification.cpp
│ │ └── symbolic.cpp
│ └── utils/
│ └── utils.cpp
└── tests/
├── ressources/
│ └── gadgets.txt
├── test_all.cpp
├── test_compiler.cpp
├── test_database.cpp
├── test_expression.cpp
├── test_gadgets.cpp
├── test_il.cpp
├── test_ir.cpp
├── test_simplification.cpp
└── test_strategy.cpp
SYMBOL INDEX (733 symbols across 45 files)
FILE: bindings/py_arch.cpp
function init_arch (line 5) | void init_arch(PyObject* module){
FILE: bindings/py_module.cpp
function PyMODINIT_FUNC (line 23) | PyMODINIT_FUNC PyInit_ropium(){
FILE: bindings/py_ropchain.cpp
function ropchain_dealloc (line 8) | static void ropchain_dealloc(PyObject* self){
function PyObject (line 13) | static PyObject* ropchain_str(PyObject* self){
function ropchain_print (line 19) | static int ropchain_print(PyObject* self){
function PyObject (line 24) | static PyObject* ropchain_repr(PyObject* self){
function PyObject (line 28) | static PyObject* ropchain_dump(PyObject* self, PyObject* args, PyObject*...
function PyObject (line 124) | PyObject* get_ropchain_Type(){
function PyObject (line 129) | PyObject* Pyropchain_FromROPChain(ROPChain* chain){
function PyObject (line 143) | static PyObject* ropchain_nb_add(PyObject* self, PyObject *other){
function init_ropchain (line 156) | void init_ropchain(PyObject* module){
FILE: bindings/py_ropium.cpp
function ROPium_dealloc (line 9) | static void ROPium_dealloc(PyObject* self){
function PyObject (line 17) | static PyObject* ROPium_load(PyObject* self, PyObject* args){
function PyObject (line 71) | static PyObject* ROPium_compile(PyObject* self, PyObject* args){
function PyObject (line 104) | static PyObject* ROPium_get_bad_bytes(PyObject* self, void* closure){
function ROPium_set_bad_bytes (line 122) | static int ROPium_set_bad_bytes(PyObject* self, PyObject* list, void* cl...
function PyObject (line 154) | static PyObject* ROPium_get_safe_mem(PyObject* self, void* closure){
function ROPium_set_safe_mem (line 162) | static int ROPium_set_safe_mem(PyObject* self, PyObject* val, void* clos...
function PyObject (line 178) | static PyObject* ROPium_get_keep_regs(PyObject* self, void* closure){
function ROPium_set_keep_regs (line 196) | static int ROPium_set_keep_regs(PyObject* self, PyObject* list, void* cl...
function PyObject (line 237) | static PyObject* ROPium_get_arch(PyObject* self, void* closure){
function PyObject (line 241) | static PyObject* ROPium_get_abi(PyObject* self, void* closure){
function ROPium_set_abi (line 245) | static int ROPium_set_abi(PyObject* self, PyObject* val, void* closure){
function PyObject (line 259) | static PyObject* ROPium_get_os(PyObject* self, void* closure){
function ROPium_set_os (line 263) | static int ROPium_set_os(PyObject* self, PyObject* val, void* closure){
function PyObject (line 336) | PyObject* get_ROPium_Type(){
function PyObject (line 341) | PyObject* ropium_ROPium(PyObject* self, PyObject* args){
FILE: bindings/utils.cpp
function PyObject (line 3) | PyObject* create_class(PyObject* name, PyObject* bases, PyObject* dict){
FILE: libropium/arch/archX86.cpp
function string (line 20) | string ArchX86::reg_name(reg_t num){
function reg_t (line 60) | reg_t ArchX86::reg_num(string name){
function reg_t (line 133) | reg_t ArchX86::sp(){
function reg_t (line 137) | reg_t ArchX86::pc(){
function reg_t (line 141) | reg_t ArchX86::tsc(){
function string (line 152) | string ArchX64::reg_name(reg_t num){
function reg_t (line 200) | reg_t ArchX64::reg_num(string name){
function reg_t (line 289) | reg_t ArchX64::sp(){
function reg_t (line 293) | reg_t ArchX64::pc(){
function reg_t (line 297) | reg_t ArchX64::tsc(){
function IROperand (line 320) | inline IROperand x86_32_reg_translate(x86_reg reg){
function IROperand (line 360) | inline IROperand x86_64_reg_translate(x86_reg reg){
function IROperand (line 441) | inline IROperand x86_reg_translate(CPUMode mode, x86_reg reg){
function IROperand (line 449) | inline IROperand x86_arg_extract(IROperand& arg, exprsize_t high, exprsi...
function IROperand (line 468) | inline IROperand x86_arg_translate(CPUMode mode, addr_t addr, cs_x86_op*...
function x86_adjust_reg_assign (line 593) | inline void x86_adjust_reg_assign(CPUMode mode, addr_t addr, IRBlock* bl...
function IROperand (line 605) | inline IROperand x86_get_pc(CPUMode mode ){
function IROperand (line 614) | inline IROperand x86_get_tsc(CPUMode mode ){
function x86_set_zf (line 623) | inline void x86_set_zf(CPUMode mode, IROperand& arg, addr_t addr, IRBloc...
function x86_add_set_cf (line 630) | inline void x86_add_set_cf(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_add_set_of (line 651) | inline void x86_add_set_of(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_sub_set_cf (line 670) | inline void x86_sub_set_cf(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_sub_set_af (line 691) | inline void x86_sub_set_af(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_sub_set_of (line 713) | inline void x86_sub_set_of(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_set_sf (line 732) | inline void x86_set_sf(CPUMode mode, IROperand& arg, addr_t addr, IRBloc...
function x86_add_set_af (line 737) | inline void x86_add_set_af(CPUMode mode, IROperand op0, IROperand op1, I...
function x86_set_pf (line 761) | inline void x86_set_pf(CPUMode mode, IROperand arg, addr_t addr, IRBlock...
function IRBasicBlockId (line 782) | IRBasicBlockId _x86_init_prefix(CPUMode mode, cs_insn* instr, addr_t add...
function _accepts_repe_prefix (line 794) | bool inline _accepts_repe_prefix(cs_insn* instr){
function _accepts_rep_prefix (line 805) | bool inline _accepts_rep_prefix(cs_insn* instr){
function _x86_end_prefix (line 833) | inline void _x86_end_prefix(CPUMode mode, cs_insn* instr, addr_t addr, I...
function x86_aaa_d (line 872) | inline void x86_aaa_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_aad_d (line 922) | inline void x86_aad_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_aam_d (line 947) | inline void x86_aam_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_aas_d (line 973) | inline void x86_aas_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_adc_d (line 1023) | inline void x86_adc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_adcx_d (line 1066) | inline void x86_adcx_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_add_d (line 1099) | inline void x86_add_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_and_d (line 1137) | inline void x86_and_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_andn_d (line 1177) | inline void x86_andn_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_blsi_d (line 1207) | inline void x86_blsi_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_blsmsk_d (line 1237) | inline void x86_blsmsk_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_blsr_d (line 1268) | inline void x86_blsr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_bsf_d (line 1299) | inline void x86_bsf_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_bsr_d (line 1346) | inline void x86_bsr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_bswap_d (line 1393) | inline void x86_bswap_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_bt_d (line 1449) | inline void x86_bt_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_btc_d (line 1469) | inline void x86_btc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_btr_d (line 1503) | inline void x86_btr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_bts_d (line 1538) | inline void x86_bts_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_bzhi_d (line 1572) | inline void x86_bzhi_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_call_d (line 1637) | inline void x86_call_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_cbw_d (line 1659) | inline void x86_cbw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cdq_d (line 1682) | inline void x86_cdq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cdqe_d (line 1710) | inline void x86_cdqe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_clc_d (line 1737) | inline void x86_clc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cld_d (line 1748) | inline void x86_cld_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cli_d (line 1759) | inline void x86_cli_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cmc_d (line 1770) | inline void x86_cmc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cmova_d (line 1781) | inline void x86_cmova_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovae_d (line 1819) | inline void x86_cmovae_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovb_d (line 1851) | inline void x86_cmovb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovbe_d (line 1883) | inline void x86_cmovbe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmove_d (line 1918) | inline void x86_cmove_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovg_d (line 1950) | inline void x86_cmovg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovge_d (line 1990) | inline void x86_cmovge_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovl_d (line 2026) | inline void x86_cmovl_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovle_d (line 2061) | inline void x86_cmovle_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovne_d (line 2098) | inline void x86_cmovne_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovno_d (line 2130) | inline void x86_cmovno_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovnp_d (line 2163) | inline void x86_cmovnp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovns_d (line 2195) | inline void x86_cmovns_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_cmovo_d (line 2228) | inline void x86_cmovo_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovp_d (line 2260) | inline void x86_cmovp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmovs_d (line 2292) | inline void x86_cmovs_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmp_d (line 2324) | inline void x86_cmp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cmpsb_d (line 2353) | inline void x86_cmpsb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmpsd_d (line 2406) | inline void x86_cmpsd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmpsq_d (line 2459) | inline void x86_cmpsq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmpsw_d (line 2516) | inline void x86_cmpsw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cmpxchg_d (line 2569) | inline void x86_cmpxchg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRB...
function x86_cpuid_d (line 2614) | inline void x86_cpuid_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_cqo_d (line 2640) | inline void x86_cqo_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cwd_d (line 2671) | inline void x86_cwd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_cwde_d (line 2695) | inline void x86_cwde_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_dec_d (line 2724) | inline void x86_dec_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_div_d (line 2757) | inline void x86_div_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_idiv_d (line 2790) | inline void x86_idiv_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_imul_d (line 2824) | inline void x86_imul_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_inc_d (line 2940) | inline void x86_inc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_int_d (line 2972) | inline void x86_int_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_int3_d (line 2986) | inline void x86_int3_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_leave_d (line 2999) | inline void x86_leave_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_ja_d (line 3019) | inline void x86_ja_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jae_d (line 3037) | inline void x86_jae_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jb_d (line 3050) | inline void x86_jb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jbe_d (line 3063) | inline void x86_jbe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jcxz_d (line 3081) | inline void x86_jcxz_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_je_d (line 3097) | inline void x86_je_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jecxz_d (line 3110) | inline void x86_jecxz_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_jg_d (line 3123) | inline void x86_jg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jge_d (line 3143) | inline void x86_jge_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jl_d (line 3161) | inline void x86_jl_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jle_d (line 3179) | inline void x86_jle_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jmp_d (line 3199) | inline void x86_jmp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jne_d (line 3212) | inline void x86_jne_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jno_d (line 3225) | inline void x86_jno_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jnp_d (line 3238) | inline void x86_jnp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jns_d (line 3251) | inline void x86_jns_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_jo_d (line 3264) | inline void x86_jo_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jp_d (line 3277) | inline void x86_jp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_jrcxz_d (line 3291) | inline void x86_jrcxz_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_js_d (line 3309) | inline void x86_js_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_lahf_d (line 3323) | inline void x86_lahf_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_lea_d (line 3350) | inline void x86_lea_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_lodsb_d (line 3373) | inline void x86_lodsb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_lodsd_d (line 3407) | inline void x86_lodsd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_lodsq_d (line 3443) | inline void x86_lodsq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_lodsw_d (line 3477) | inline void x86_lodsw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_mov_d (line 3511) | inline void x86_mov_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_movsb_d (line 3530) | inline void x86_movsb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_movsd_d (line 3568) | inline void x86_movsd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_movsq_d (line 3606) | inline void x86_movsq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_movsw_d (line 3644) | inline void x86_movsw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_movsx_d (line 3682) | inline void x86_movsx_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_movsxd_d (line 3713) | inline void x86_movsxd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_movzx_d (line 3749) | inline void x86_movzx_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_mul_d (line 3768) | inline void x86_mul_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_neg_d (line 3808) | inline void x86_neg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_nop_d (line 3844) | inline void x86_nop_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_not_d (line 3854) | inline void x86_not_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_or_d (line 3879) | inline void x86_or_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock*...
function x86_pop_d (line 3918) | inline void x86_pop_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_popad_d (line 3946) | inline void x86_popad_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_push_d (line 4000) | inline void x86_push_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_pushad_d (line 4020) | inline void x86_pushad_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBl...
function x86_rcl_d (line 4079) | inline void x86_rcl_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_rcr_d (line 4153) | inline void x86_rcr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_rdtsc_d (line 4227) | inline void x86_rdtsc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_ret_d (line 4242) | inline void x86_ret_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_rol_d (line 4266) | inline void x86_rol_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_ror_d (line 4332) | inline void x86_ror_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_sal_d (line 4400) | inline void x86_sal_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_sar_d (line 4458) | inline void x86_sar_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_scasb_d (line 4533) | inline void x86_scasb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_scasd_d (line 4580) | inline void x86_scasd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_scasq_d (line 4627) | inline void x86_scasq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_scasw_d (line 4674) | inline void x86_scasw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_seta_d (line 4721) | inline void x86_seta_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setae_d (line 4761) | inline void x86_setae_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setb_d (line 4795) | inline void x86_setb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setbe_d (line 4829) | inline void x86_setbe_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_sete_d (line 4867) | inline void x86_sete_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setg_d (line 4901) | inline void x86_setg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setge_d (line 4944) | inline void x86_setge_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setl_d (line 4982) | inline void x86_setl_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setle_d (line 5020) | inline void x86_setle_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setne_d (line 5061) | inline void x86_setne_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setno_d (line 5095) | inline void x86_setno_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setnp_d (line 5129) | inline void x86_setnp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_setns_d (line 5163) | inline void x86_setns_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_seto_d (line 5197) | inline void x86_seto_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_setp_d (line 5231) | inline void x86_setp_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_sets_d (line 5265) | inline void x86_sets_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_shr_d (line 5299) | inline void x86_shr_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_stc_d (line 5359) | inline void x86_stc_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_std_d (line 5375) | inline void x86_std_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_sti_d (line 5391) | inline void x86_sti_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_stosb_d (line 5407) | inline void x86_stosb_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_stosd_d (line 5439) | inline void x86_stosd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_stosq_d (line 5470) | inline void x86_stosq_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_stosw_d (line 5501) | inline void x86_stosw_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlo...
function x86_sub_d (line 5532) | inline void x86_sub_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function x86_syscall_d (line 5566) | inline void x86_syscall_d(CPUMode mode, cs_insn* instr, addr_t addr, IRB...
function x86_sysenter_d (line 5584) | inline void x86_sysenter_d(CPUMode mode, cs_insn* instr, addr_t addr, IR...
function x86_test_d (line 5602) | inline void x86_test_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_xadd_d (line 5629) | inline void x86_xadd_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_xchg_d (line 5666) | inline void x86_xchg_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBloc...
function x86_xor_d (line 5694) | inline void x86_xor_d(CPUMode mode, cs_insn* instr, addr_t addr, IRBlock...
function IRBlock (line 5742) | IRBlock* DisassemblerX86::disasm_block(addr_t addr, code_t code, size_t ...
FILE: libropium/compiler/compiler.cpp
function ROPChain (line 24) | ROPChain* CompilerTask::compile(Arch* arch, GadgetDB* db, Constraint* co...
function ROPChain (line 130) | ROPChain* ROPCompiler::compile(string program, Constraint* constraint, A...
function ROPChain (line 160) | ROPChain* ROPCompiler::process_simple(vector<ILInstruction>& ins, Constr...
function ROPChain (line 187) | ROPChain* ROPCompiler::process_complex(vector<ILInstruction>& ins, Const...
function _is_empty_line (line 231) | bool _is_empty_line(string& s){
function _permutation_contains (line 261) | bool _permutation_contains(vector<int>& perm1, vector<int>& perm2){
function _record_failed_permutation (line 276) | void _record_failed_permutation(list<vector<int>>& failed_perms, vector<...
function _is_failed_permutation (line 284) | bool _is_failed_permutation(list<vector<int>>& failed_perms, vector<int>...
function ROPChain (line 294) | ROPChain* ROPCompiler::_set_registers_permutation( vector<ILInstruction>...
function ROPChain (line 349) | ROPChain* ROPCompiler::_set_multiple_registers(vector<ILInstruction>& in...
function ROPChain (line 495) | ROPChain* ROPCompiler::_compile_x64_system_v_call(ILInstruction& instr, ...
function ROPChain (line 603) | ROPChain* ROPCompiler::_compile_x64_ms_call(ILInstruction& instr, Constr...
function ROPChain (line 711) | ROPChain* ROPCompiler::_compile_x86_linux_syscall(ILInstruction& instr, ...
function ROPChain (line 778) | ROPChain* ROPCompiler::_compile_x64_linux_syscall(ILInstruction& instr, ...
function _string_to_integers (line 846) | bool _string_to_integers(vector<cst_t>& integers, string& str, int arch_...
function _cst_store_cst_to_strategy (line 877) | bool _cst_store_cst_to_strategy(StrategyGraph& graph, ILInstruction& ins...
function _preprocess_cst_store_string (line 920) | bool _preprocess_cst_store_string(vector<ILInstruction>& dst, ILInstruct...
FILE: libropium/compiler/il.cpp
function _skip_whitespace (line 11) | void _skip_whitespace(string& str, int& idx){
function _parse_end (line 17) | bool _parse_end(string& str, int& idx){
function _parse_il_cst (line 26) | bool _parse_il_cst(Arch& arch, vector<cst_t>& args, string& str, int& idx){
function _parse_il_reg (line 76) | bool _parse_il_reg(Arch& arch, vector<cst_t>& args, string& str, int& idx){
function _parse_il_string (line 104) | bool _parse_il_string( string& res, string& str, int& idx){
function _parse_il_affect (line 165) | bool _parse_il_affect(string& str, int& idx){
function _parse_il_mem_start (line 176) | bool _parse_il_mem_start(string& str, int& idx){
function _parse_il_mem_end (line 187) | bool _parse_il_mem_end(string& str, int& idx){
function _parse_il_function_args_list (line 198) | bool _parse_il_function_args_list(Arch& arch, vector<cst_t>& args, vecto...
function _parse_il_function_args (line 220) | bool _parse_il_function_args(Arch& arch, vector<cst_t>& args, vector<int...
function _parse_il_syscall_name (line 241) | bool _parse_il_syscall_name( string& name, string& str, int& idx){
function _parse_il_single_syscall (line 269) | bool _parse_il_single_syscall(Arch& arch, ILInstruction* instr, string& ...
function _parse_il_syscall_num (line 288) | bool _parse_il_syscall_num( Arch& arch, int& num, string& str, int& idx){
function _parse_il_reg_and_offset (line 313) | bool _parse_il_reg_and_offset(Arch& arch, vector<cst_t>& args, string& s...
function _parse_il_binop (line 345) | bool _parse_il_binop(vector<cst_t>& args, string& str, int& idx){
function _parse_il_unop (line 375) | bool _parse_il_unop(vector<cst_t>& args, string& str, int& idx){
function _parse_il_mov_reg (line 390) | bool _parse_il_mov_reg(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_mov_cst (line 405) | bool _parse_il_mov_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_amov_cst (line 420) | bool _parse_il_amov_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_amov_reg (line 437) | bool _parse_il_amov_reg(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_load (line 454) | bool _parse_il_load(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_aload (line 471) | bool _parse_il_aload(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_load_cst (line 489) | bool _parse_il_load_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_aload_cst (line 506) | bool _parse_il_aload_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_store (line 524) | bool _parse_il_store(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_astore (line 541) | bool _parse_il_astore(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_cst_store (line 559) | bool _parse_il_cst_store(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_cst_astore (line 576) | bool _parse_il_cst_astore(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_store_cst (line 594) | bool _parse_il_store_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_astore_cst (line 611) | bool _parse_il_astore_cst(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_cst_store_cst (line 629) | bool _parse_il_cst_store_cst(Arch& arch, ILInstruction* instr, string& s...
function _parse_il_cst_astore_cst (line 646) | bool _parse_il_cst_astore_cst(Arch& arch, ILInstruction* instr, string& ...
function _parse_il_cst_store_string (line 665) | bool _parse_il_cst_store_string(Arch& arch, ILInstruction* instr, string...
function _parse_il_function (line 684) | bool _parse_il_function(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_syscall_by_name (line 702) | bool _parse_il_syscall_by_name(Arch& arch, ILInstruction* instr, string&...
function _parse_il_syscall_by_num (line 721) | bool _parse_il_syscall_by_num(Arch& arch, ILInstruction* instr, string& ...
function _parse_il_syscall (line 740) | bool _parse_il_syscall(Arch& arch, ILInstruction* instr, string& str){
function _parse_il_instruction (line 746) | bool _parse_il_instruction(Arch& arch, ILInstruction* instr, string& str){
FILE: libropium/compiler/strategy_graph.cpp
function constraint_branch_type (line 33) | bool constraint_branch_type(Node* node, StrategyGraph* graph, Arch* arch){
function addr_t (line 322) | addr_t _get_valid_gadget_address(Gadget* gadget, Arch* arch, Constraint*...
function node_t (line 365) | node_t StrategyGraph::new_node(GadgetType t){
function string (line 380) | string StrategyGraph::new_name(string base){
function _redirect_param_dep (line 386) | bool _redirect_param_dep(ParamDep& dep, node_t curr_node, param_t curr_p...
function _redirect_param_deps (line 395) | void _redirect_param_deps(Param& param, Node& curr_node, param_t curr_pa...
function PossibleGadgets (line 768) | PossibleGadgets* StrategyGraph::_get_possible_gadgets(GadgetDB& db, node...
function ROPChain (line 1088) | ROPChain* StrategyGraph::get_ropchain(Arch* arch, Constraint* constraint){
function StrategyGraph (line 1165) | StrategyGraph* StrategyGraph::copy(){
function ostream (line 1176) | ostream& operator<<(ostream& os, Param& param){
function ostream (line 1193) | ostream& operator<<(ostream& os, Node& node){
function ostream (line 1230) | ostream& operator<<(ostream& os, StrategyGraph& graph){
FILE: libropium/compiler/systems.cpp
function SyscallDef (line 105) | SyscallDef* get_syscall_def(ArchType arch, System sys, string name){
FILE: libropium/database/database.cpp
function find_insert_index (line 5) | int find_insert_index(vector<Gadget*>& gadget_list, Gadget* gadget){
function find_insert_index_possible_gadgets (line 23) | int find_insert_index_possible_gadgets(PossibleGadgets* possible, Gadget...
function gadget_t (line 40) | gadget_t GadgetDB::add(Gadget* gadget, Arch* arch){
function Gadget (line 263) | Gadget* GadgetDB::get(gadget_t gadget_num){
function PossibleGadgets (line 315) | PossibleGadgets* GadgetDB::get_possible_mov_reg(reg_t dst_reg, reg_t src...
function PossibleGadgets (line 319) | PossibleGadgets* GadgetDB::get_possible_amov_reg(reg_t dst_reg, reg_t sr...
function PossibleGadgets (line 323) | PossibleGadgets* GadgetDB::get_possible_mov_cst(reg_t dst_reg, cst_t src...
function PossibleGadgets (line 327) | PossibleGadgets* GadgetDB::get_possible_amov_cst(reg_t dst_reg, reg_t sr...
function PossibleGadgets (line 331) | PossibleGadgets* GadgetDB::get_possible_load(reg_t dst_reg, reg_t src_ad...
function PossibleGadgets (line 335) | PossibleGadgets* GadgetDB::get_possible_aload(reg_t dst_reg, Op op, reg_...
function PossibleGadgets (line 339) | PossibleGadgets* GadgetDB::get_possible_store(reg_t dst_addr_reg, cst_t ...
function PossibleGadgets (line 343) | PossibleGadgets* GadgetDB::get_possible_astore(reg_t dst_addr_reg, cst_t...
FILE: libropium/dependencies/murmur3/murmur3.c
function FORCE_INLINE (line 21) | static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
function FORCE_INLINE (line 26) | static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
function FORCE_INLINE (line 45) | static FORCE_INLINE uint32_t fmix32 ( uint32_t h )
function FORCE_INLINE (line 58) | static FORCE_INLINE uint64_t fmix64 ( uint64_t k )
function MurmurHash3_x86_32 (line 71) | void MurmurHash3_x86_32 ( const void * key, int len,
function MurmurHash3_x86_128 (line 128) | void MurmurHash3_x86_128 ( const void * key, const int len,
function MurmurHash3_x64_128 (line 234) | void MurmurHash3_x64_128 ( const void * key, const int len,
FILE: libropium/include/arch.hpp
class Disassembler (line 12) | class Disassembler
type CPUMode (line 20) | enum class CPUMode{
type ArchType (line 30) | enum class ArchType{
class Arch (line 55) | class Arch{
class ArchNone (line 74) | class ArchNone: public Arch{
method ArchNone (line 76) | ArchNone(): Arch(ArchType::NONE, 32, 4, 20, CPUMode::NONE, (Disassembl...
method string (line 77) | string reg_name(reg_t num){return "reg" + to_string(num);}
method reg_t (line 78) | reg_t reg_num(string name){return 0;}
method is_valid_reg (line 79) | bool is_valid_reg(string& name){return false;}
method reg_t (line 80) | reg_t sp(){return 19;}
method reg_t (line 81) | reg_t pc(){return 18;}
method reg_t (line 82) | reg_t tsc(){return 17;}
class ArchX86 (line 128) | class ArchX86: public Arch{
class ArchX64 (line 191) | class ArchX64: public Arch{
FILE: libropium/include/assertion.hpp
class ValidPointers (line 8) | class ValidPointers{
class Assertion (line 17) | class Assertion{
FILE: libropium/include/compiler.hpp
type ABI (line 13) | enum class ABI{
class CompilerTask (line 42) | class CompilerTask{
class ROPCompiler (line 64) | class ROPCompiler{
FILE: libropium/include/constraint.hpp
class BadBytes (line 9) | class BadBytes{
class KeepRegs (line 22) | class KeepRegs{
class MemSafety (line 32) | class MemSafety{
class Constraint (line 45) | class Constraint{
FILE: libropium/include/database.hpp
type GadgetType (line 24) | enum class GadgetType{
class PossibleGadgets (line 50) | class PossibleGadgets{
method size (line 53) | int size(){return gadgets.size();}
method cst_t (line 55) | cst_t get_param(int i, int p){return gadgets[i].first[p];}
method PossibleGadgets (line 56) | PossibleGadgets(){}
method PossibleGadgets (line 57) | PossibleGadgets(const PossibleGadgets& other){
class BaseDB (line 68) | class BaseDB{
method add (line 73) | void add(K key, Gadget* gadget){
method _check_key_match (line 94) | bool _check_key_match(const K& key1, const K& key2, bool* param_is_fre...
method PossibleGadgets (line 104) | PossibleGadgets* get_possible(K key, bool* param_is_free, int nb_params){
method clear (line 118) | void clear(){
class GadgetDB (line 126) | class GadgetDB{
FILE: libropium/include/disassembler.hpp
type CPUMode (line 12) | enum class CPUMode
class IRBlock (line 13) | class IRBlock
class Disassembler (line 26) | class Disassembler{
class DisassemblerX86 (line 37) | class DisassemblerX86: public Disassembler{
FILE: libropium/include/exception.hpp
class QuickFmt (line 11) | class QuickFmt{
method QuickFmt (line 13) | QuickFmt() {}
method QuickFmt (line 17) | QuickFmt & operator << (const Type & value)
method str (line 23) | std::string str() const { return stream_.str(); }
type ConvertToString (line 26) | enum ConvertToString
class runtime_exception (line 42) | class runtime_exception: public std::exception {
method runtime_exception (line 45) | explicit runtime_exception(string msg): _msg(msg){}
class expression_exception (line 52) | class expression_exception: public std::exception {
method expression_exception (line 55) | explicit expression_exception(string msg): _msg(msg){}
class ir_exception (line 61) | class ir_exception: public std::exception {
method ir_exception (line 64) | explicit ir_exception(string msg): _msg(msg){}
class il_exception (line 68) | class il_exception: public std::exception {
method il_exception (line 71) | explicit il_exception(string msg): _msg(msg){}
class compiler_exception (line 75) | class compiler_exception: public std::exception {
method compiler_exception (line 78) | explicit compiler_exception(string msg): _msg(msg){}
class strategy_exception (line 82) | class strategy_exception: public std::exception {
method strategy_exception (line 85) | explicit strategy_exception(string msg): _msg(msg){}
class symbolic_exception (line 90) | class symbolic_exception: public std::exception {
method symbolic_exception (line 93) | explicit symbolic_exception(string msg): _msg(msg){}
class unsupported_instruction_exception (line 99) | class unsupported_instruction_exception: public std::exception {
method unsupported_instruction_exception (line 102) | explicit unsupported_instruction_exception(string msg): _msg(msg){}
class illegal_instruction_exception (line 108) | class illegal_instruction_exception: public std::exception {
method illegal_instruction_exception (line 111) | explicit illegal_instruction_exception(string msg): _msg(msg){}
class test_exception (line 118) | class test_exception : public std::exception {
FILE: libropium/include/expression.hpp
type ExprType (line 42) | enum class ExprType {
type Op (line 64) | enum class Op {
class ExprObject (line 94) | class ExprObject
method hash_t (line 122) | virtual hash_t hash(){throw runtime_exception("Called virtual function...
method cst_t (line 123) | virtual cst_t cst(){throw runtime_exception("Called virtual function i...
method string (line 124) | virtual const string& name(){throw runtime_exception("Called virtual f...
method replace_name (line 125) | virtual void replace_name(string& new_name){throw runtime_exception("C...
method Op (line 126) | virtual Op op(){throw runtime_exception("Called virtual function in Ex...
method cst_t (line 127) | virtual cst_t mode(){throw runtime_exception("Called virtual function ...
method print (line 128) | virtual void print(ostream& out){out << "???";}
method reg (line 129) | virtual int reg(){throw runtime_exception("Called virtual function in ...
method is_reg (line 134) | virtual bool is_reg(int reg){return false;}
method Expr (line 157) | virtual Expr copy(){throw runtime_exception("Called virtual function i...
class VarContext (line 95) | class VarContext
class ExprObject (line 99) | class ExprObject{
method hash_t (line 122) | virtual hash_t hash(){throw runtime_exception("Called virtual function...
method cst_t (line 123) | virtual cst_t cst(){throw runtime_exception("Called virtual function i...
method string (line 124) | virtual const string& name(){throw runtime_exception("Called virtual f...
method replace_name (line 125) | virtual void replace_name(string& new_name){throw runtime_exception("C...
method Op (line 126) | virtual Op op(){throw runtime_exception("Called virtual function in Ex...
method cst_t (line 127) | virtual cst_t mode(){throw runtime_exception("Called virtual function ...
method print (line 128) | virtual void print(ostream& out){out << "???";}
method reg (line 129) | virtual int reg(){throw runtime_exception("Called virtual function in ...
method is_reg (line 134) | virtual bool is_reg(int reg){return false;}
method Expr (line 157) | virtual Expr copy(){throw runtime_exception("Called virtual function i...
class ExprCst (line 161) | class ExprCst: public ExprObject{
class ExprVar (line 172) | class ExprVar: public ExprObject{
class ExprMem (line 187) | class ExprMem: public ExprObject{
class ExprUnop (line 196) | class ExprUnop: public ExprObject{
class ExprBinop (line 208) | class ExprBinop: public ExprObject{
class ExprExtract (line 223) | class ExprExtract: public ExprObject{
class ExprConcat (line 232) | class ExprConcat: public ExprObject{
class ExprBisz (line 241) | class ExprBisz: public ExprObject{
class ExprUnknown (line 252) | class ExprUnknown: public ExprObject{
class VarContext (line 374) | class VarContext{
FILE: libropium/include/il.hpp
type ILInstructionType (line 18) | enum class ILInstructionType{
class ILInstruction (line 70) | class ILInstruction{
FILE: libropium/include/ir.hpp
type IROperation (line 27) | enum class IROperation{
type IROperandType (line 80) | enum class IROperandType{
class IROperand (line 87) | class IROperand{
class IRInstruction (line 118) | class IRInstruction{
class IRContext (line 172) | class IRContext{
class MemContext (line 189) | class MemContext{
class IRBlock (line 220) | class IRBlock{
FILE: libropium/include/ropchain.hpp
type BranchType (line 14) | enum class BranchType{
class Gadget (line 23) | class Gadget{
type ROPItemType (line 53) | enum class ROPItemType{
class ROPItem (line 59) | class ROPItem{
method ROPItem (line 67) | ROPItem(addr_t a, Gadget* g, string m=""):type(ROPItemType::GADGET), a...
method ROPItem (line 68) | ROPItem(ROPItemType t, cst_t v, string m=""):type(t), value(v), msg(m)...
class ROPChain (line 71) | class ROPChain{
FILE: libropium/include/simplification.hpp
class ExprSimplifier (line 10) | class ExprSimplifier
class ExprSimplifier (line 17) | class ExprSimplifier{
FILE: libropium/include/strategy.hpp
type ParamType (line 20) | enum class ParamType{
type ParamDep (line 27) | struct ParamDep{
class Param (line 32) | class Param{
method Param (line 44) | Param():type(ParamType::NONE), name(""), value(-1), expr(nullptr), is_...
method add_dep (line 46) | void add_dep(node_t n, param_t p){
method depends_on (line 55) | bool depends_on(node_t n){
method make_reg (line 64) | void make_reg(int reg, bool fixed=true){
method make_reg (line 74) | void make_reg(node_t dn, int dpt){
method make_cst (line 85) | void make_cst(cst_t val, string n, bool fixed=true){
method make_cst (line 96) | void make_cst(node_t dn, int dpt, Expr e, string n){
method make_op (line 108) | void make_op(Op op){
method is_dependent (line 117) | bool is_dependent(){return !is_fixed && !deps.empty();}
method is_free (line 118) | bool is_free(){return !is_dependent() && !is_fixed;}
method is_cst (line 119) | bool is_cst(){return type == ParamType::CST;}
method is_reg (line 120) | bool is_reg(){return type == ParamType::REG;}
type EdgeSet (line 126) | struct EdgeSet{
class UniqueNameGenerator (line 131) | class UniqueNameGenerator{
method UniqueNameGenerator (line 135) | UniqueNameGenerator():n(0){}
method string (line 136) | string new_name(string& name){
class Node (line 330) | class Node
class NodeValidPointers (line 332) | class NodeValidPointers{
class NodeAssertion (line 340) | class NodeAssertion{
class Node (line 349) | class Node
class StrategyGraph (line 350) | class StrategyGraph
class Node (line 356) | class Node{
class InterferencePoint (line 423) | class InterferencePoint {
method InterferencePoint (line 428) | InterferencePoint(node_t i, node_t s, node_t e):interfering_node(i), s...
class StrategyGraph (line 432) | class StrategyGraph{
FILE: libropium/include/symbolic.hpp
class Semantics (line 14) | class Semantics{
class SymbolicEngine (line 28) | class SymbolicEngine{
FILE: libropium/include/systems.hpp
type System (line 9) | enum class System{
class SyscallDef (line 16) | class SyscallDef{
method SyscallDef (line 21) | SyscallDef(string n, cst_t sysn, int nb):name(n), nb_args(nb), num(sys...
FILE: libropium/include/utils.hpp
class RawGadget (line 13) | class RawGadget{
method RawGadget (line 15) | RawGadget(){}
method RawGadget (line 16) | RawGadget(string r, uint64_t a):raw(r), addr(a){}
type std (line 30) | namespace std{
function hash_combine (line 40) | inline void hash_combine(std::size_t& seed, T const& v)
type HashValueImpl (line 47) | struct HashValueImpl
method apply (line 49) | static void apply(size_t& seed, Tuple const& tuple)
type HashValueImpl<Tuple,0> (line 57) | struct HashValueImpl<Tuple,0>
method apply (line 59) | static void apply(size_t& seed, Tuple const& tuple)
type hash<std::tuple<TT...>> (line 67) | struct hash<std::tuple<TT...>>
type indices (line 83) | struct indices {
type build_indices (line 88) | struct build_indices {
type build_indices<0> (line 93) | struct build_indices<0> {
function make_indices (line 101) | constexpr
function to_array (line 107) | std::array<
function tuple_to_array (line 118) | auto tuple_to_array(Tuple&& tuple)
function tuple_to_vector (line 125) | vector<cst_t> tuple_to_vector(Tuple&& tuple)
FILE: libropium/ir/ir.cpp
function iroperation_is_assignment (line 9) | bool iroperation_is_assignment(IROperation& op){
function iroperation_is_memory (line 30) | bool iroperation_is_memory(IROperation& op){
function ostream (line 34) | ostream& operator<<(ostream& os, IROperation& op){
function cst_t (line 77) | cst_t IROperand::cst(){ return _val; }
function IRVar (line 78) | IRVar IROperand::var(){ return (IRVar)_val;}
function IRVar (line 79) | IRVar IROperand::tmp(){return (IRVar)_val;}
function ostream (line 81) | ostream& operator<<(ostream& os, IROperand& op){
function IROperand (line 93) | IROperand ir_cst(cst_t val, exprsize_t high, exprsize_t low){
function IROperand (line 96) | IROperand ir_var(cst_t num, exprsize_t high, exprsize_t low){
function IROperand (line 99) | IROperand ir_tmp(cst_t num, exprsize_t high, exprsize_t low){
function IROperand (line 102) | IROperand ir_none(){
function ostream (line 273) | ostream& operator<<(ostream& os, IRInstruction& ins){
function IRInstruction (line 292) | IRInstruction ir_add(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 295) | IRInstruction ir_sub(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 298) | IRInstruction ir_mul(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 301) | IRInstruction ir_mulh(IROperand dst, IROperand src1, IROperand src2, add...
function IRInstruction (line 304) | IRInstruction ir_smull(IROperand dst, IROperand src1, IROperand src2, ad...
function IRInstruction (line 307) | IRInstruction ir_smulh(IROperand dst, IROperand src1, IROperand src2, ad...
function IRInstruction (line 310) | IRInstruction ir_div(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 313) | IRInstruction ir_sdiv(IROperand dst, IROperand src1, IROperand src2, add...
function IRInstruction (line 316) | IRInstruction ir_and(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 319) | IRInstruction ir_or(IROperand dst, IROperand src1, IROperand src2, addr_...
function IRInstruction (line 322) | IRInstruction ir_xor(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 325) | IRInstruction ir_shl(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 328) | IRInstruction ir_shr(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 331) | IRInstruction ir_mod(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 334) | IRInstruction ir_smod(IROperand dst, IROperand src1, IROperand src2, add...
function IRInstruction (line 337) | IRInstruction ir_neg(IROperand dst, IROperand src1, addr_t addr){
function IRInstruction (line 340) | IRInstruction ir_not(IROperand dst, IROperand src1, addr_t addr){
function IRInstruction (line 343) | IRInstruction ir_ldm(IROperand dst, IROperand src1, addr_t addr){
function IRInstruction (line 346) | IRInstruction ir_stm(IROperand dst, IROperand src1, addr_t addr){
function IRInstruction (line 349) | IRInstruction ir_mov(IROperand dst, IROperand src1, addr_t addr){
function IRInstruction (line 352) | IRInstruction ir_bcc(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 355) | IRInstruction ir_jcc(IROperand dst, IROperand src1, IROperand src2, addr...
function IRInstruction (line 358) | IRInstruction ir_bisz(IROperand dst, IROperand src1, IROperand src2, add...
function IRInstruction (line 361) | IRInstruction ir_concat(IROperand dst, IROperand src1, IROperand src2, a...
function IRInstruction (line 364) | IRInstruction ir_int(IROperand num, IROperand ret, addr_t addr){
function IRInstruction (line 367) | IRInstruction ir_syscall(IROperand type, IROperand ret, addr_t addr){
function Expr (line 389) | Expr IRContext::get(IRVar num){
function ostream (line 396) | ostream& operator<<(ostream& os, IRContext& ctx){
function Expr (line 422) | Expr MemContext::read(Expr addr, int octets){
function ostream (line 442) | ostream& operator<<(ostream& os, MemContext& ctx){
function IRBasicBlockId (line 469) | IRBasicBlockId IRBlock::new_bblock(){
function IRBasicBlock (line 474) | IRBasicBlock& IRBlock::get_bblock(IRBasicBlockId id){
function ostream (line 486) | ostream& operator<<(ostream& os, IRBlock& blk){
FILE: libropium/ropchain/constraint.cpp
function addr_t (line 28) | addr_t BadBytes::get_valid_padding(int nb_bytes){
function addr_t (line 47) | addr_t BadBytes::get_valid_address(Gadget* gadget, int arch_bytes){
FILE: libropium/ropchain/gadget.cpp
function ostream (line 30) | ostream& operator<<(ostream& os, Gadget& g){
FILE: libropium/ropchain/ropchain.cpp
function append_value_to_bytes (line 87) | void append_value_to_bytes(vector<uint8_t>& bytes, addr_t val, int nb_oc...
function ostream (line 109) | ostream& operator<<(ostream& os, ROPChain& ropchain){
FILE: libropium/symbolic/expression.cpp
function prepare_hash_with_i64 (line 37) | inline int prepare_hash_with_i64(uint8_t* hash_in, int64_t val, int inde...
function prepare_hash_with_str (line 42) | inline int prepare_hash_with_str(uint8_t* hash_in, const string& str, in...
function prepare_hash_with_i32 (line 47) | inline int prepare_hash_with_i32(uint8_t* hash_in, int32_t val, int inde...
function prepare_hash_with_op (line 52) | inline int prepare_hash_with_op(uint8_t* hash_in, Op op, int index=0){
function hash_t (line 57) | hash_t exprhash(void* hash_in, int len, uint32_t seed){
function cst_t (line 76) | cst_t ExprObject::concretize(VarContext* ctx ){throw runtime_exception("...
function hash_t (line 148) | hash_t ExprCst::hash(){
function cst_t (line 156) | cst_t ExprCst::cst(){ return _cst; }
function cst_t (line 157) | cst_t ExprCst::concretize(VarContext* ctx){return _cst;}
function Expr (line 159) | Expr ExprCst::copy(){
function hash_t (line 170) | hash_t ExprVar::hash(){
function cst_t (line 183) | cst_t ExprVar::concretize(VarContext* ctx){
function string (line 195) | const string& ExprVar::name(){ return _name; }
function Expr (line 198) | Expr ExprVar::copy(){
function hash_t (line 206) | hash_t ExprMem::hash(){
function cst_t (line 214) | cst_t ExprMem::concretize(VarContext* ctx){
function Expr (line 221) | Expr ExprMem::copy(){
function hash_t (line 229) | hash_t ExprUnop::hash(){
function Op (line 237) | Op ExprUnop::op(){ return _op;}
function cst_t (line 250) | cst_t ExprUnop::concretize(VarContext* ctx){
function Expr (line 267) | Expr ExprUnop::copy(){
function hash_t (line 279) | hash_t ExprBinop::hash(){
function Op (line 289) | Op ExprBinop::op(){ return _op;}
function cst_t (line 336) | cst_t ExprBinop::concretize(VarContext* ctx){
function Expr (line 378) | Expr ExprBinop::copy(){
function hash_t (line 397) | hash_t ExprExtract::hash(){
function cst_t (line 417) | cst_t ExprExtract::concretize(VarContext* ctx){
function Expr (line 439) | Expr ExprExtract::copy(){
function hash_t (line 448) | hash_t ExprConcat::hash(){
function cst_t (line 466) | cst_t ExprConcat::concretize(VarContext* ctx){
function Expr (line 483) | Expr ExprConcat::copy(){
function hash_t (line 495) | hash_t ExprBisz::hash(){
function cst_t (line 505) | cst_t ExprBisz::mode(){return _mode;}
function cst_t (line 519) | cst_t ExprBisz::concretize(VarContext* ctx){
function Expr (line 532) | Expr ExprBisz::copy(){
function hash_t (line 538) | hash_t ExprUnknown::hash(){
function cst_t (line 550) | cst_t ExprUnknown::concretize(VarContext* ctx){
function Expr (line 558) | Expr exprcst(exprsize_t size, cst_t cst){
function Expr (line 561) | Expr exprvar(exprsize_t size, string name, int num){
function Expr (line 564) | Expr exprmem(exprsize_t size, Expr addr){
function Expr (line 567) | Expr exprbinop(Op op, Expr left, Expr right){
function Expr (line 570) | Expr exprunop(Op op, Expr arg){
function Expr (line 573) | Expr extract(Expr arg, unsigned long higher, unsigned long lower){
function Expr (line 576) | Expr extract(Expr arg, Expr higher, Expr lower){
function Expr (line 579) | Expr concat(Expr upper, Expr lower){
function Expr (line 582) | Expr exprunknown(exprsize_t size){
function Expr (line 586) | Expr operator+(Expr left, Expr right){
function Expr (line 589) | Expr operator+(Expr left, cst_t right ){
function Expr (line 592) | Expr operator+(cst_t left, Expr right){
function Expr (line 596) | Expr operator-(Expr left, Expr right){
function Expr (line 600) | Expr operator-(Expr left, cst_t right ){
function Expr (line 603) | Expr operator-(cst_t left, Expr right){
function Expr (line 607) | Expr operator*(Expr left, Expr right){
function Expr (line 610) | Expr operator*(Expr left, cst_t right ){
function Expr (line 613) | Expr operator*(cst_t left, Expr right){
function Expr (line 617) | Expr operator/(Expr left, Expr right){
function Expr (line 620) | Expr operator/(Expr left, cst_t right ){
function Expr (line 623) | Expr operator/(cst_t left, Expr right){
function Expr (line 627) | Expr operator&(Expr left, Expr right){
function Expr (line 630) | Expr operator&(Expr left, cst_t right ){
function Expr (line 633) | Expr operator&(cst_t left, Expr right){
function Expr (line 637) | Expr operator|(Expr left, Expr right){
function Expr (line 640) | Expr operator|(Expr left, cst_t right ){
function Expr (line 643) | Expr operator|(cst_t left, Expr right){
function Expr (line 647) | Expr operator^(Expr left, Expr right){
function Expr (line 650) | Expr operator^(Expr left, cst_t right ){
function Expr (line 653) | Expr operator^(cst_t left, Expr right){
function Expr (line 657) | Expr operator%(Expr left, Expr right){
function Expr (line 660) | Expr operator%(Expr left, cst_t right ){
function Expr (line 663) | Expr operator%(cst_t left, Expr right){
function Expr (line 667) | Expr operator<<(Expr left, Expr right){
function Expr (line 670) | Expr operator<<(Expr left, cst_t right ){
function Expr (line 673) | Expr operator<<(cst_t left, Expr right){
function Expr (line 677) | Expr operator>>(Expr left, Expr right){
function Expr (line 680) | Expr operator>>(Expr left, cst_t right ){
function Expr (line 683) | Expr operator>>(cst_t left, Expr right){
function Expr (line 687) | Expr shl(Expr arg, Expr shift){
function Expr (line 690) | Expr shl(Expr arg, cst_t shift){
function Expr (line 693) | Expr shl(cst_t arg, Expr shift){
function Expr (line 697) | Expr shr(Expr arg, Expr shift){
function Expr (line 700) | Expr shr(Expr arg, cst_t shift){
function Expr (line 703) | Expr shr(cst_t arg, Expr shift){
function Expr (line 707) | Expr sdiv(Expr left, Expr right){
function Expr (line 710) | Expr sdiv(Expr left, cst_t right){
function Expr (line 713) | Expr sdiv(cst_t left, Expr right){
function Expr (line 717) | Expr smod(Expr left, Expr right){
function Expr (line 720) | Expr smod(Expr left, cst_t right){
function Expr (line 723) | Expr smod(cst_t left, Expr right){
function Expr (line 727) | Expr mulh(Expr left, Expr right){
function Expr (line 730) | Expr mulh(Expr left, cst_t right){
function Expr (line 733) | Expr mulh(cst_t left, Expr right){
function Expr (line 737) | Expr smull(Expr left, Expr right){
function Expr (line 740) | Expr smull(Expr left, cst_t right){
function Expr (line 743) | Expr smull(cst_t left, Expr right){
function Expr (line 747) | Expr smulh(Expr left, Expr right){
function Expr (line 750) | Expr smulh(Expr left, cst_t right){
function Expr (line 753) | Expr smulh(cst_t left, Expr right){
function Expr (line 758) | Expr operator~(Expr arg){
function Expr (line 761) | Expr operator-(Expr arg){
function Expr (line 764) | Expr bisz(exprsize_t size, Expr cond, cst_t mode){
function ostream (line 769) | ostream& operator<<(ostream& os, Expr e){
function string (line 774) | string op_to_str(Op op){
function Expr (line 815) | Expr build_associative_from_args(Expr e, Op op, vector<Expr>& new_args){
function Expr (line 861) | Expr build_left_associative_from_args(Expr e, Op op, vector<Expr>& new_a...
function Expr (line 892) | Expr expr_canonize(Expr e){
function op_is_symetric (line 946) | bool op_is_symetric(Op op){
function op_is_associative (line 951) | bool op_is_associative(Op op){
function op_is_left_associative (line 956) | bool op_is_left_associative(Op op){
function op_is_multiplication (line 960) | bool op_is_multiplication(Op op){
function op_is_distributive_over (line 964) | bool op_is_distributive_over(Op op1, Op op2){
function cst_t (line 984) | cst_t cst_sign_trunc(exprsize_t size, cst_t val){
function cst_t (line 990) | cst_t cst_mask(exprsize_t size){
function cst_t (line 996) | cst_t cst_sign_extend(exprsize_t size, cst_t c){
function cst_t (line 1019) | cst_t VarContext::get(const string& name){
function ostream (line 1039) | ostream& operator<<(ostream& os, VarContext& c){
FILE: libropium/symbolic/simplification.cpp
function Expr (line 23) | Expr ExprSimplifier::run_simplifiers(Expr e){
function Expr (line 37) | Expr ExprSimplifier::simplify(Expr e){
function ExprSimplifier (line 79) | ExprSimplifier* NewDefaultExprSimplifier(){
function Expr (line 101) | Expr es_constant_folding(Expr e){
function Expr (line 181) | Expr es_neutral_elements(Expr e){
function Expr (line 212) | Expr es_absorbing_elements(Expr e){
function Expr (line 234) | Expr es_arithmetic_properties(Expr e){
function Expr (line 259) | Expr es_involution(Expr e){
function Expr (line 268) | Expr es_extract_patterns(Expr e){
function Expr (line 296) | Expr es_basic_transform(Expr e){
function Expr (line 336) | Expr es_logical_properties(Expr e){
function Expr (line 364) | Expr es_concat_patterns(Expr e){
function Expr (line 397) | Expr es_arithmetic_factorize(Expr e){
function Expr (line 455) | Expr es_generic_factorize(Expr e){
function Expr (line 482) | Expr es_generic_distribute(Expr e){
function Expr (line 506) | Expr es_deep_associative(Expr e, ExprSimplifier& s){
FILE: libropium/symbolic/symbolic.cpp
function ostream (line 32) | ostream& operator<<(ostream& os, Semantics& s){
function Expr (line 56) | Expr _reduce_rvalue(Expr e, exprsize_t high, exprsize_t low ){
function Expr (line 63) | Expr _expand_lvalue(Expr current, Expr e, exprsize_t high, exprsize_t low){
function _set_tmp_var (line 76) | inline void _set_tmp_var(int num, Expr e, int high, int low, vector<Expr...
function Expr (line 100) | Expr _get_operand(IROperand& arg, IRContext* irctx, vector<Expr>& tmp_va...
function _update_dereferenced_regs (line 116) | void _update_dereferenced_regs(bool* deref, Expr e){
function Semantics (line 140) | Semantics* SymbolicEngine::execute_block(IRBlock* block){
FILE: libropium/utils/utils.cpp
function split (line 71) | void split(const std::string& str, vector<string>& cont, char delim = ' ')
function ropgadget_to_file (line 83) | bool ropgadget_to_file(string out, string ropgadget_out, string bin){
function string (line 150) | string str_bold(string s){
function string (line 154) | string str_special(string s){
function string (line 158) | string value_to_hex_str(int octets, addr_t addr){
function disable_colors (line 167) | void disable_colors(){
function enable_colors (line 176) | void enable_colors(){
type sigaction (line 188) | struct sigaction
type sigaction (line 189) | struct sigaction
function ropium_sigint_handler (line 192) | void ropium_sigint_handler(int s){
function set_sigint_handler (line 196) | void set_sigint_handler(){
function unset_signint_handler (line 204) | void unset_signint_handler(){
function is_pending_sigint (line 208) | bool is_pending_sigint(){
function notify_sigint_handled (line 212) | void notify_sigint_handled(){
FILE: tests/test_all.cpp
function main (line 20) | int main(int argc, char ** argv){
FILE: tests/test_compiler.cpp
type test (line 14) | namespace test{
type compiler (line 15) | namespace compiler{
function _assert_ropchain (line 16) | unsigned int _assert_ropchain(ROPChain* ropchain, const string& msg){
function _assert_no_ropchain (line 25) | unsigned int _assert_no_ropchain(ROPChain* ropchain, const string& m...
function direct_match (line 33) | unsigned int direct_match(){
function indirect_match (line 97) | unsigned int indirect_match(){
function store_string (line 164) | unsigned int store_string(){
function incorrect_match (line 201) | unsigned int incorrect_match(){
function function_call_x86 (line 234) | unsigned int function_call_x86(){
function function_call_x64 (line 274) | unsigned int function_call_x64(){
function syscall_x86 (line 332) | unsigned int syscall_x86(){
function syscall_x64 (line 369) | unsigned int syscall_x64(){
function test_compiler (line 408) | void test_compiler(){
FILE: tests/test_database.cpp
type test (line 16) | namespace test{
type database (line 17) | namespace database{
function _assert (line 18) | unsigned int _assert(bool val, const string& msg){
function base_db (line 26) | unsigned int base_db(){
function _assert_db (line 44) | unsigned int _assert_db(addr_t addr, const vector<Gadget*>& list){
function classification (line 53) | unsigned int classification(){
function classification_x64 (line 106) | unsigned int classification_x64(){
function test_database (line 128) | void test_database(){
FILE: tests/test_expression.cpp
type test (line 14) | namespace test{
type expression (line 15) | namespace expression{
function basic (line 17) | unsigned int basic(){
function _assert_hash_eq (line 32) | unsigned int _assert_hash_eq(Expr e1, Expr e2){
function _assert_hash_neq (line 40) | unsigned int _assert_hash_neq(Expr e1, Expr e2){
function hashing (line 47) | unsigned hashing(){
function _assert_canonize_eq (line 81) | unsigned int _assert_canonize_eq(Expr e1, Expr e2 ){
function _assert_canonize_neq (line 90) | unsigned int _assert_canonize_neq(Expr e1, Expr e2 ){
function canonize (line 99) | unsigned int canonize(){
function _assert (line 137) | unsigned int _assert(bool val, const string& msg){
function concretization (line 146) | unsigned int concretization(){
function change_varctx (line 231) | unsigned int change_varctx(){
function test_expression (line 273) | void test_expression(){
FILE: tests/test_gadgets.cpp
type test (line 13) | namespace test{
type gadgets (line 14) | namespace gadgets{
function _assert (line 15) | unsigned int _assert(bool val, const string& msg){
function basic (line 23) | unsigned int basic(){
function test_gadgets (line 40) | void test_gadgets(){
FILE: tests/test_il.cpp
type test (line 15) | namespace test{
type il (line 16) | namespace il{
function _assert (line 17) | unsigned int _assert(bool val, const string& msg){
function il_parser (line 25) | unsigned int il_parser(){
function il_parser64 (line 364) | unsigned int il_parser64(){
function test_il (line 405) | void test_il(){
FILE: tests/test_ir.cpp
type test (line 13) | namespace test{
type ir (line 14) | namespace ir{
function _assert (line 15) | unsigned int _assert(bool val, const string& msg){
function ir_context (line 23) | unsigned int ir_context(){
function test_ir (line 46) | void test_ir(){
FILE: tests/test_simplification.cpp
type test (line 14) | namespace test{
type simplification (line 15) | namespace simplification{
function _assert_simplify (line 16) | unsigned int _assert_simplify(Expr e1, Expr e2, ExprSimplifier& simp){
function _assert (line 27) | unsigned int _assert(bool val, const string& msg){
function basic (line 35) | unsigned int basic(ExprSimplifier& s){
function const_folding (line 40) | unsigned int const_folding(ExprSimplifier& s){
function neutral_elems (line 68) | unsigned int neutral_elems(ExprSimplifier& s){
function absorbing_elems (line 81) | unsigned int absorbing_elems(ExprSimplifier& s){
function arithmetic_properties (line 91) | unsigned int arithmetic_properties(ExprSimplifier& s){
function involution (line 116) | unsigned int involution(ExprSimplifier& s){
function extract_patterns (line 123) | unsigned int extract_patterns(ExprSimplifier& s){
function basic_transform (line 135) | unsigned int basic_transform(ExprSimplifier& s){
function logical_properties (line 149) | unsigned int logical_properties(ExprSimplifier& s){
function concat_patterns (line 164) | unsigned int concat_patterns(ExprSimplifier& s){
function advanced (line 188) | unsigned int advanced(ExprSimplifier& s){
function test_simplification (line 226) | void test_simplification(){
FILE: tests/test_strategy.cpp
type test (line 16) | namespace test{
type strategy (line 17) | namespace strategy{
function _assert (line 20) | unsigned int _assert(bool val, const string& msg){
function _assert_ropchain (line 28) | unsigned int _assert_ropchain(ROPChain* ropchain, const string& msg){
function basic (line 37) | unsigned int basic(){
function rules (line 59) | unsigned int rules(){
function test_generic_adjust_jmp (line 171) | unsigned int test_generic_adjust_jmp(){
function test_adjust_load (line 204) | unsigned int test_adjust_load(){
function test_generic_src_transitivity (line 248) | unsigned int test_generic_src_transitivity(){
function test_adjust_store (line 290) | unsigned int test_adjust_store(){
function test_cst_pop (line 355) | unsigned int test_cst_pop(){
function test_x64_syscall (line 387) | unsigned int test_x64_syscall(){
function test_strategy (line 447) | void test_strategy(){
Condensed preview — 58 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (830K chars).
[
{
"path": "Dockerfile",
"chars": 974,
"preview": "FROM python:3.7.3-slim-stretch\n\nRUN pip3 install prompt_toolkit==2.0.9 \\\n#\t\thttps://github.com/lief-project/packages/raw"
},
{
"path": "Makefile",
"chars": 3461,
"preview": "CC = gcc\nCXX = g++\n\nOUTDIR = ./bin\nLIB_FILE = libropium.so\nLIB_HEADER_FILE = ropium.hpp\nBINDINGS_FILE = ropium.so\n\n## Ba"
},
{
"path": "README.md",
"chars": 4645,
"preview": "\n\n<p align=\"center\" >\n<img width=50% src=\"/ressources/ropium_logo.png\"/><br /><br /><br />\n</p>\n\n# About\n**ROPium** (ex-"
},
{
"path": "bin/.gitignore",
"chars": 71,
"preview": "# Ignore everything in this directory\n*\n# Except this file\n!.gitignore\n"
},
{
"path": "bindings/py_arch.cpp",
"chars": 7348,
"preview": "#include \"python_bindings.hpp\"\n#include \"arch.hpp\"\n#include \"compiler.hpp\"\n\nvoid init_arch(PyObject* module){\n /* ARC"
},
{
"path": "bindings/py_module.cpp",
"chars": 675,
"preview": "#include \"Python.h\"\n#include \"python_bindings.hpp\"\n\n/* Module methods */\nPyMethodDef module_methods[] = {\n {\"ROPium\","
},
{
"path": "bindings/py_ropchain.cpp",
"chars": 6030,
"preview": "#include \"python_bindings.hpp\"\n#include <cstdio>\n\n/* -------------------------------------\n * ROPChain object\n "
},
{
"path": "bindings/py_ropium.cpp",
"chars": 13221,
"preview": "#include \"python_bindings.hpp\"\n#include <cstdio>\n#include <fstream>\n\n/* -------------------------------------\n * "
},
{
"path": "bindings/python_bindings.hpp",
"chars": 1485,
"preview": "#ifndef PYTHON_BINDINGS_INCLUDE_H\n#define PYTHON_BINDINGS_INCLUDE_H\n\n#include \"Python.h\"\n#include \"structmember.h\"\n#incl"
},
{
"path": "bindings/utils.cpp",
"chars": 284,
"preview": "#include \"python_bindings.hpp\"\n\nPyObject* create_class(PyObject* name, PyObject* bases, PyObject* dict){\n PyObject* r"
},
{
"path": "cli-tool/ropium",
"chars": 15436,
"preview": "#!/usr/bin/env python3\nfrom ropium import *\nfrom prompt_toolkit import PromptSession, ANSI\nimport os\n\n# Colors and util "
},
{
"path": "libropium/arch/arch.cpp",
"chars": 297,
"preview": "#include \"arch.hpp\"\n#include <iostream>\n\n\nArch::Arch(ArchType _type, int _bits, int _octets, int _nb, CPUMode _mode, Dis"
},
{
"path": "libropium/arch/archX86.cpp",
"chars": 289179,
"preview": "#include \"expression.hpp\"\n#include \"arch.hpp\"\n#include \"disassembler.hpp\"\n#include \"exception.hpp\"\n#include \"ir.hpp\"\n#in"
},
{
"path": "libropium/arch/disassembler.cpp",
"chars": 162,
"preview": "#include \"disassembler.hpp\"\n#include <iostream>\n\nDisassembler::~Disassembler(){\n cs_free(_insn, 1);\n _insn"
},
{
"path": "libropium/compiler/compiler.cpp",
"chars": 57729,
"preview": "#include \"compiler.hpp\"\n#include \"exception.hpp\"\n#include \"il.hpp\"\n#include <algorithm>\n\n\n/* ============= Compiler Task"
},
{
"path": "libropium/compiler/il.cpp",
"chars": 21391,
"preview": "#include \"il.hpp\"\n#include <string>\n#include <cctype>\n#include \"exception.hpp\"\n#include <iostream>\n\nusing std::string;\n\n"
},
{
"path": "libropium/compiler/strategy_graph.cpp",
"chars": 50326,
"preview": "#include \"strategy.hpp\"\n#include \"expression.hpp\"\n#include \"exception.hpp\"\n#include <algorithm>\n\n/* =============== Nod"
},
{
"path": "libropium/compiler/strategy_rules.cpp",
"chars": 20755,
"preview": "#include \"strategy.hpp\"\n#include \"expression.hpp\"\n#include \"exception.hpp\"\n#include <algorithm>\n\n/* =============== Stra"
},
{
"path": "libropium/compiler/systems.cpp",
"chars": 4035,
"preview": "#include \"systems.hpp\"\n#include <vector>\n\nusing std::vector;\n\n// Supported syscalls\nvector<SyscallDef> linux_x86_syscall"
},
{
"path": "libropium/database/database.cpp",
"chars": 14698,
"preview": "#include \"database.hpp\"\n#include \"exception.hpp\"\n#include <iostream>\n\nint find_insert_index(vector<Gadget*>& gadget_list"
},
{
"path": "libropium/dependencies/murmur3/murmur3.c",
"chars": 7532,
"preview": "//-----------------------------------------------------------------------------\n// MurmurHash3 was written by Austin App"
},
{
"path": "libropium/dependencies/murmur3/murmur3.h",
"chars": 792,
"preview": "//-----------------------------------------------------------------------------\n// MurmurHash3 was written by Austin App"
},
{
"path": "libropium/include/arch.hpp",
"chars": 4821,
"preview": "#ifndef ARCH_H\n#define ARCH_H\n\n#include <cstdint>\n#include <string>\n#include <capstone/capstone.h>\n\nusing std::string;\nu"
},
{
"path": "libropium/include/assertion.hpp",
"chars": 343,
"preview": "#ifndef ASSERTION_H\n#define ASSERTION_H\n\n#include \"ropchain.hpp\"\n#include \"arch.hpp\"\n#include <algorithm>\n\nclass ValidPo"
},
{
"path": "libropium/include/compiler.hpp",
"chars": 3682,
"preview": "#ifndef ROP_COMPILER_H\n#define ROP_COMPILER_H\n\n#include \"strategy.hpp\"\n#include \"il.hpp\"\n#include \"database.hpp\"\n#includ"
},
{
"path": "libropium/include/constraint.hpp",
"chars": 1329,
"preview": "#ifndef CONSTRAINT_H\n#define CONSTRAINT_H\n\n#include \"ropchain.hpp\"\n#include \"arch.hpp\"\n#include \"assertion.hpp\"\n#include"
},
{
"path": "libropium/include/database.hpp",
"chars": 6477,
"preview": "#ifndef DATABASE_H\n#define DATABASE_H\n\n#include <iostream>\n#include <tuple>\n#include <unordered_map>\n#include \"utils.hpp"
},
{
"path": "libropium/include/disassembler.hpp",
"chars": 1039,
"preview": "#ifndef DISASSEMBLER_H\n#define DISASSEMBLER_H\n\n#include \"arch.hpp\"\n#include \"ir.hpp\"\n#include <cstdint>\n\n/* Types aliasi"
},
{
"path": "libropium/include/exception.hpp",
"chars": 3025,
"preview": "#ifndef EXCEPTION_H\n#define EXCEPTION_H\n\n#include <sstream>\n#include <string>\n#include <exception>\n\nusing std::string;\n\n"
},
{
"path": "libropium/include/expression.hpp",
"chars": 10775,
"preview": "#ifndef EXPRESSION_H\n#define EXPRESSION_H\n\n#include <cstdint>\n#include <string>\n#include <vector>\n#include <memory>\n#inc"
},
{
"path": "libropium/include/il.hpp",
"chars": 2585,
"preview": "#ifndef IL_HPP\n#define IL_HPP\n\n#include \"arch.hpp\"\n\n/* IL - Intermediate Language\n ==========================\n \n The"
},
{
"path": "libropium/include/ir.hpp",
"chars": 7860,
"preview": "#ifndef IR_H\n#define IR_H\n\n#include <vector>\n#include <unordered_map>\n#include \"expression.hpp\"\n#include \"simplification"
},
{
"path": "libropium/include/ropchain.hpp",
"chars": 2031,
"preview": "#ifndef ROPCHAIN_H\n#define ROPCHAIN_H\n\n#include \"symbolic.hpp\"\n#include \"arch.hpp\"\n#include \"utils.hpp\"\n#include <string"
},
{
"path": "libropium/include/ropium.hpp",
"chars": 398,
"preview": "#ifndef ROPIUM_H\n#define ROPIUM_H\n\n#include \"expression.hpp\"\n#include \"simplification.hpp\"\n#include \"arch.hpp\"\n#include "
},
{
"path": "libropium/include/simplification.hpp",
"chars": 1287,
"preview": "#ifndef SIMPLIFICATION_H\n#define SIMPLIFICATION_H\n\n#include \"expression.hpp\"\n#include <vector>\n\nusing std::vector; \n\n/* "
},
{
"path": "libropium/include/strategy.hpp",
"chars": 14769,
"preview": "#ifndef STRATEGY_H\n#define STRATEGY_H\n\n#include \"database.hpp\"\n#include \"expression.hpp\"\n#include \"constraint.hpp\"\n#incl"
},
{
"path": "libropium/include/symbolic.hpp",
"chars": 647,
"preview": "#ifndef SYMBOLIC_H\n#define SYMBOLIC_H\n\n#include \"ir.hpp\"\n#include \"expression.hpp\"\n#include \"simplification.hpp\"\n#includ"
},
{
"path": "libropium/include/systems.hpp",
"chars": 452,
"preview": "#ifndef SYSTEMS_H\n#define SYSTEMS_H\n\n#include <string>\n#include \"arch.hpp\"\n\nusing std::string;\n\nenum class System{\n L"
},
{
"path": "libropium/include/utils.hpp",
"chars": 4176,
"preview": "#ifndef UTILS_H\n#define UTILS_H\n\n#include <string>\n#include <cstdint>\n#include <vector>\n#include \"expression.hpp\"\n\nusing"
},
{
"path": "libropium/ir/ir.cpp",
"chars": 17965,
"preview": "#include \"ir.hpp\"\n#include \"exception.hpp\"\n#include <iostream>\n#include <cassert>\n#include <cstring>\n#include <algorithm"
},
{
"path": "libropium/ropchain/assertion.cpp",
"chars": 353,
"preview": "#include \"assertion.hpp\"\n#include <algorithm>\n\n\nvoid ValidPointers::add_valid_pointer(int reg){\n _regs.push_back(reg)"
},
{
"path": "libropium/ropchain/constraint.cpp",
"chars": 3479,
"preview": "#include \"constraint.hpp\"\n#include <cstring>\n#include <iostream>\n\n/* =============== Bad Bytes ================= */\n\nvoi"
},
{
"path": "libropium/ropchain/gadget.cpp",
"chars": 957,
"preview": "#include \"ropchain.hpp\"\n#include <unordered_map>\n#include <iostream>\n#include <cstring>\n\nusing std::unordered_map;\n\nGadg"
},
{
"path": "libropium/ropchain/ropchain.cpp",
"chars": 3957,
"preview": "#include \"ropchain.hpp\"\n#include \"utils.hpp\"\n#include <iostream>\n#include <sstream>\n\n\nROPChain::ROPChain(Arch* a):arch(a"
},
{
"path": "libropium/symbolic/expression.cpp",
"chars": 35906,
"preview": "#include \"expression.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <cstring>\n#include \"murmur3.h\"\n#include <"
},
{
"path": "libropium/symbolic/simplification.cpp",
"chars": 23558,
"preview": "#include \"simplification.hpp\"\n#include \"expression.hpp\"\n#include \"exception.hpp\"\n#include <iostream>\n#include <algorithm"
},
{
"path": "libropium/symbolic/symbolic.cpp",
"chars": 14982,
"preview": "#include \"symbolic.hpp\"\n#include \"exception.hpp\"\n#include \"simplification.hpp\"\n#include <cassert>\n#include <vector>\n#inc"
},
{
"path": "libropium/utils/utils.cpp",
"chars": 5960,
"preview": "#include \"utils.hpp\"\n#include \"exception.hpp\"\n#include <iostream>\n#include <fstream>\n#include <cstdio>\n#include <memory>"
},
{
"path": "tests/ressources/gadgets.txt",
"chars": 37,
"preview": "0xaaaaaaa$505BFFE3\n0x12345678$89D8C3\n"
},
{
"path": "tests/test_all.cpp",
"chars": 2243,
"preview": "#include \"exception.hpp\"\n#include <string>\n#include <cstring>\n#include <iostream>\n#include <exception>\n\nusing std::cout;"
},
{
"path": "tests/test_compiler.cpp",
"chars": 21926,
"preview": "#include \"compiler.hpp\"\n#include \"arch.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <iostream>\n#include <st"
},
{
"path": "tests/test_database.cpp",
"chars": 6174,
"preview": "#include \"database.hpp\"\n#include \"exception.hpp\"\n#include <string>\n#include <sstream>\n#include <tuple>\n#include <iostrea"
},
{
"path": "tests/test_expression.cpp",
"chars": 15565,
"preview": "#include \"expression.hpp\"\n#include \"simplification.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <iostream>\n"
},
{
"path": "tests/test_gadgets.cpp",
"chars": 1339,
"preview": "#include \"database.hpp\"\n#include \"exception.hpp\"\n#include <string>\n#include <sstream>\n#include <tuple>\n#include <iostrea"
},
{
"path": "tests/test_il.cpp",
"chars": 26997,
"preview": "#include \"il.hpp\"\n#include \"arch.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <iostream>\n#include <string>\n"
},
{
"path": "tests/test_ir.cpp",
"chars": 1738,
"preview": "#include \"ir.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <iostream>\n#include <string>\n#include <sstream>\n#"
},
{
"path": "tests/test_simplification.cpp",
"chars": 12486,
"preview": "#include \"expression.hpp\"\n#include \"simplification.hpp\"\n#include \"exception.hpp\"\n#include <cassert>\n#include <iostream>\n"
},
{
"path": "tests/test_strategy.cpp",
"chars": 20525,
"preview": "#include \"strategy.hpp\"\n#include \"compiler.hpp\"\n#include \"il.hpp\"\n#include \"exception.hpp\"\n#include \"utils.hpp\"\n#include"
}
]
About this extraction
This page contains the full source code of the Boyan-MILANOV/ropgenerator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 58 files (783.6 KB), approximately 242.8k tokens, and a symbol index with 733 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.