Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
JackyMa | 143b727f41 | 2 years ago |
JackyMa | ee181732f0 | 2 years ago |
JackyMa | a001ff6fed | 2 years ago |
JackyMa | 42fb856148 | 2 years ago |
JackyMa | b46a40452f | 2 years ago |
JackyMa | e91e42364b | 2 years ago |
JackyMa | 7f801de04b | 2 years ago |
JackyMa | 078201c4e5 | 2 years ago |
JackyMa | fa7d46141b | 2 years ago |
JackyMa | 6dbf02b5ba | 2 years ago |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/dse.iml" filepath="$PROJECT_DIR$/.idea/dse.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,39 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
find_package(LLVM 14 REQUIRED CONFIG)
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
|
||||
include(HandleLLVMOptions)
|
||||
include(AddLLVM)
|
||||
|
||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||
|
||||
set(Z3_DIR $ENV{Z3_DIR})
|
||||
get_filename_component(Z3_DIR ${Z3_DIR} ABSOLUTE)
|
||||
set(Z3_CXX_INCLUDE_DIRS ${Z3_DIR}/include)
|
||||
set(Z3_LIBRARIES ${Z3_DIR}/lib/libz3.so)
|
||||
message(STATUS "Z3_DIR: ${Z3_DIR}")
|
||||
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
include_directories(${LLVM_INCLUDE_DIRS} include)
|
||||
include_directories(${Z3_CXX_INCLUDE_DIRS})
|
||||
link_directories(${LLVM_LIBRARY_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${Z3_LIBRARIES})
|
||||
|
||||
add_executable(dse
|
||||
src/DSE.cpp
|
||||
src/Strategy.cpp
|
||||
)
|
||||
|
||||
add_llvm_library(InstrumentPass MODULE
|
||||
src/Instrument.cpp
|
||||
)
|
||||
|
||||
llvm_map_components_to_libnames(llvm_libs support core irreader)
|
||||
|
||||
target_link_libraries(dse ${llvm_libs} ${Z3_LIBRARIES})
|
||||
|
||||
add_library(runtime MODULE
|
||||
src/SymbolicInterpreter.cpp
|
||||
src/Runtime.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(runtime ${llvm_libs} ${Z3_LIBRARIES})
|
@ -0,0 +1,3 @@
|
||||
void __DSE_Input__(int *x, int ID);
|
||||
|
||||
#define DSE_Input(x) __DSE_Input__(&x, __COUNTER__)
|
@ -0,0 +1,4 @@
|
||||
#include "z3++.h"
|
||||
|
||||
void recordBranches(z3::expr_vector &OldVec);
|
||||
void searchStrategy(z3::expr_vector &OldVec);
|
@ -0,0 +1,62 @@
|
||||
#ifndef SYMBOLIC_INTERPRETER_H
|
||||
#define SYMBOLIC_INTERPRETER_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "z3++.h"
|
||||
|
||||
/// 结果输出目录
|
||||
static const char *FormulaFile = "formula.smt2";
|
||||
/// 输入读取目录
|
||||
static const char *InputFile = "input.txt";
|
||||
/// 日志:记录 Path Condition
|
||||
static const char *LogFile = "log.txt";
|
||||
/// 目前不清楚
|
||||
static const char *BranchFile = "branch.txt";
|
||||
|
||||
class Address {
|
||||
public:
|
||||
enum Ty { Memory, Register };
|
||||
Address(int *Ptr) : Type(Memory), Addr((uintptr_t)Ptr) {}
|
||||
Address(int ID) : Type(Register), Addr(ID) {}
|
||||
Address(z3::expr &R)
|
||||
: Type(Register), Addr(std::stoi(R.to_string().substr(1))) {}
|
||||
|
||||
bool operator<(const Address &RHS) const {
|
||||
return (Type < RHS.Type) || (Type == RHS.Type && Addr < RHS.Addr);
|
||||
}
|
||||
friend std::ostream &operator<<(std::ostream &OS, const Address &SE);
|
||||
|
||||
private:
|
||||
Ty Type;
|
||||
uintptr_t Addr;
|
||||
};
|
||||
|
||||
using MemoryTy = std::map<Address, z3::expr>;
|
||||
|
||||
class SymbolicInterpreter {
|
||||
public:
|
||||
int NewInput(int *Ptr, int ID);
|
||||
MemoryTy &getMemory() { return Mem; }
|
||||
std::map<int, int> &getInputs() { return Inputs; }
|
||||
z3::context &getContext() { return Ctx; }
|
||||
std::stack<z3::expr> &getStack() { return Stack; }
|
||||
std::vector<std::pair<int, z3::expr>> &getPathCondition() {
|
||||
return PathCondition;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryTy Mem;
|
||||
/// Inputs: <RegisteredId, Value>
|
||||
std::map<int, int> Inputs;
|
||||
int NumOfInputs = 0;
|
||||
std::stack<z3::expr> Stack;
|
||||
std::vector<std::pair<int, z3::expr>> PathCondition;
|
||||
|
||||
z3::context Ctx;
|
||||
};
|
||||
|
||||
#endif // SYMBOLIC_INTERPRETER_H
|
@ -0,0 +1,149 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
|
||||
#include "SymbolicInterpreter.h"
|
||||
|
||||
#define ADD 13 /// +
|
||||
#define SUB 15 /// -
|
||||
#define MUL 17 /// *
|
||||
#define SDIV 20 /// /
|
||||
#define SREM 23 /// %
|
||||
|
||||
#define ICMP_EQ 32 ///< equal
|
||||
#define ICMP_NE 33 ///< not equal
|
||||
#define ICMP_SGT 38 ///< signed greater than
|
||||
#define ICMP_SGE 39 ///< signed greater or equal
|
||||
#define ICMP_SLT 40 ///< signed less than
|
||||
#define ICMP_SLE 41 ///< signed less or equal
|
||||
#define ICMP_UGT 34 ///< unsigned greater than
|
||||
#define ICMP_UGE 35 ///< unsigned greater or equal
|
||||
#define ICMP_ULT 36 ///< unsigned less than
|
||||
#define ICMP_ULE 37 ///< unsigned less or equal
|
||||
|
||||
extern SymbolicInterpreter SI;
|
||||
using namespace z3;
|
||||
using namespace std;
|
||||
/**
|
||||
* Implement your transfer functions.
|
||||
*/
|
||||
|
||||
/// DSE_Alloca(getRegisterId(%x),%x)
|
||||
/// Reg(%x) => 0x1000
|
||||
extern "C" void __DSE_Alloca__(int R, int *Ptr) {
|
||||
expr e = SI.getContext().int_val(*Ptr);
|
||||
auto address = Address(R);
|
||||
SI.getMemory().insert(make_pair(address, e));
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Store__(int *X) {
|
||||
expr e = SI.getStack().top();
|
||||
SI.getStack().pop();
|
||||
if(e.to_string().at(0) == 'R'){
|
||||
e = SI.getMemory().at(e);
|
||||
}
|
||||
auto address = Address(X);
|
||||
SI.getMemory().insert(make_pair(address, e));
|
||||
SI.getMemory().at(address) = e;
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Load__(int Y, int *X) {
|
||||
expr e = SI.getMemory().at(Address(X));
|
||||
auto address = Address(Y);
|
||||
SI.getMemory().insert(make_pair(address, e));
|
||||
SI.getMemory().at(address) = e;
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Label__(int RID, int BID, int label){
|
||||
expr el = SI.getMemory().at(Address(RID));
|
||||
auto address = Address(BID);
|
||||
expr t = SI.getContext().bool_val(true);
|
||||
expr f = SI.getContext().bool_val(false);
|
||||
if(label){
|
||||
SI.getMemory().insert(make_pair(address, el == t));
|
||||
SI.getMemory().at(address) = (el == t);
|
||||
} else{
|
||||
SI.getMemory().insert(make_pair(address, el == f));
|
||||
SI.getMemory().at(address) = (el == f);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Loop__(int Type){
|
||||
expr type = SI.getContext().int_val(Type);
|
||||
SI.getStack().push(type);
|
||||
}
|
||||
|
||||
extern "C" void __DSE_ICmp__(int R, int Op) {
|
||||
expr el = SI.getStack().top();
|
||||
SI.getStack().pop();
|
||||
expr er = SI.getStack().top();
|
||||
SI.getStack().pop();
|
||||
if(el.to_string().at(0) == 'R'){
|
||||
el = SI.getMemory().at(el);
|
||||
}
|
||||
if(er.to_string().at(0) == 'R'){
|
||||
er = SI.getMemory().at(er);
|
||||
}
|
||||
expr res = el == er;
|
||||
switch (Op) {
|
||||
case ICMP_EQ:
|
||||
res = el == er;
|
||||
break;
|
||||
case ICMP_NE:
|
||||
res = el != er;
|
||||
break;
|
||||
case ICMP_SLT:
|
||||
res = el < er;
|
||||
break;
|
||||
case ICMP_SLE:
|
||||
res = el <= er;
|
||||
break;
|
||||
case ICMP_SGT:
|
||||
res = el > er;
|
||||
break;
|
||||
case ICMP_SGE:
|
||||
res = el >= er;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto address = Address(R);
|
||||
SI.getMemory().insert(make_pair(address, res));
|
||||
SI.getMemory().at(address) = res;
|
||||
}
|
||||
|
||||
extern "C" void __DSE_BinOp__(int R, int Op) {
|
||||
expr el = SI.getStack().top();
|
||||
SI.getStack().pop();
|
||||
expr er = SI.getStack().top();
|
||||
SI.getStack().pop();
|
||||
if(el.to_string().at(0) == 'R'){
|
||||
el = SI.getMemory().at(el);
|
||||
}
|
||||
if(er.to_string().at(0) == 'R'){
|
||||
er = SI.getMemory().at(er);
|
||||
}
|
||||
expr res = el + er;
|
||||
switch (Op) {
|
||||
case ADD:
|
||||
res = el + er;
|
||||
break;
|
||||
case SUB:
|
||||
res = el - er;
|
||||
break;
|
||||
case MUL:
|
||||
res = el * er;
|
||||
break;
|
||||
case SDIV:
|
||||
res = el / er;
|
||||
break;
|
||||
case SREM:
|
||||
res = el % er;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto address = Address(R);
|
||||
SI.getMemory().insert(make_pair(address, res));
|
||||
SI.getMemory().at(address) = res;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
#include "Strategy.h"
|
||||
#include <iostream>
|
||||
|
||||
static const char *NOT = "not";
|
||||
std::vector<std::string> Branches;
|
||||
/**
|
||||
* Implement your search strategy.
|
||||
*/
|
||||
|
||||
void recordBranches(z3::expr_vector &OldVec){
|
||||
for (auto && E : OldVec) {
|
||||
if(E.to_string().find('X') == std::string::npos){
|
||||
continue;
|
||||
}
|
||||
if(std::find(Branches.begin(), Branches.end(),E.to_string()) == Branches.end()){
|
||||
Branches.push_back(E.to_string().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void searchStrategy(z3::expr_vector &OldVec) {
|
||||
int i = OldVec.size()-1;
|
||||
if(i<0){
|
||||
return;
|
||||
}
|
||||
auto e = OldVec[i];
|
||||
if(e.to_string().find('X') == std::string::npos){
|
||||
OldVec.pop_back();
|
||||
searchStrategy(OldVec);
|
||||
return;
|
||||
}
|
||||
if(e.to_string().substr(1, 3) != NOT){
|
||||
std::string newExpr = e.to_string();
|
||||
if(newExpr.find("false") != std::string::npos){
|
||||
newExpr = newExpr.replace(newExpr.end()-6, newExpr.end()-1,"true");
|
||||
} else{
|
||||
newExpr = newExpr.replace(newExpr.end()-5, newExpr.end()-1,"false");
|
||||
}
|
||||
if(std::find(Branches.begin(), Branches.end(), newExpr) == Branches.end()){
|
||||
OldVec.pop_back();
|
||||
OldVec.push_back(not e);
|
||||
} else{
|
||||
OldVec.pop_back();
|
||||
searchStrategy(OldVec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
OldVec.pop_back();
|
||||
searchStrategy(OldVec);
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
#include "SymbolicInterpreter.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
|
||||
std::ostream &operator<<(std::ostream &OS, const Address &A) {
|
||||
if (A.Type == A.Memory) {
|
||||
OS << A.Addr;
|
||||
} else {
|
||||
OS << "R" << A.Addr;
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
int SymbolicInterpreter::NewInput(int *Ptr, int ID) {
|
||||
int Ret = 0;
|
||||
if (Inputs.find(ID) != Inputs.end()) {
|
||||
Ret = Inputs[ID];
|
||||
} else {
|
||||
Ret = std::rand();
|
||||
Inputs[ID] = Ret;
|
||||
}
|
||||
Address X(Ptr);
|
||||
std::string InputName = "X" + std::to_string(NumOfInputs);
|
||||
z3::expr SE = Ctx.int_const(InputName.c_str());
|
||||
/// Type(Mem) : MemoryTy = std::map<Address, z3::expr>
|
||||
Mem.insert(std::make_pair(X, SE));
|
||||
NumOfInputs++;
|
||||
return Ret;
|
||||
}
|
||||
|
||||
SymbolicInterpreter SI;
|
||||
|
||||
void print(std::ostream &OS) {
|
||||
OS << "=== Inputs ===" << std::endl;
|
||||
int Idx = 0;
|
||||
for (auto &E : SI.getInputs()) {
|
||||
OS << "X" << E.first << " : " << E.second << std::endl;
|
||||
}
|
||||
OS << std::endl;
|
||||
OS << "=== Symbolic Memory ===" << std::endl;
|
||||
for (auto &E : SI.getMemory()) {
|
||||
OS << E.first << " : " << E.second << std::endl;
|
||||
}
|
||||
OS << std::endl;
|
||||
|
||||
OS << "=== Path Condition ===" << std::endl;
|
||||
for (auto &E : SI.getPathCondition()) {
|
||||
std::string BID = "B" + std::to_string(E.first);
|
||||
OS << BID << " : " << E.second << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Exit__() {
|
||||
z3::solver Solver(SI.getContext());
|
||||
std::ofstream Branch(BranchFile);
|
||||
for (auto &E : SI.getPathCondition()) {
|
||||
std::string BID = "B" + std::to_string(E.first);
|
||||
Solver.add(E.second);
|
||||
Branch << E.second << "\n";
|
||||
}
|
||||
std::ofstream Smt2(FormulaFile);
|
||||
Smt2 << Solver.to_smt2();
|
||||
std::ofstream Log(LogFile);
|
||||
print(Log);
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Init__() {
|
||||
std::srand(std::time(nullptr));
|
||||
std::string Line;
|
||||
std::ifstream Input(InputFile);
|
||||
if (Input.is_open()) {
|
||||
while (getline(Input, Line)) {
|
||||
int ID = std::stoi(Line.substr(1, Line.find(",")));
|
||||
int Val = std::stoi(Line.substr(Line.find(",") + 1));
|
||||
SI.getInputs()[ID] = Val;
|
||||
}
|
||||
}
|
||||
std::atexit(__DSE_Exit__);
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Input__(int *X, int ID) {
|
||||
/// 地址 *X 的值变为 (int)SI.NewInput(X, ID)
|
||||
/// Inputs<0, V0> => %x = V0
|
||||
*X = (int)SI.NewInput(X, ID);
|
||||
}
|
||||
|
||||
/// 这里我按照自己的逻辑改了框架
|
||||
extern "C" void __DSE_Branch__(int RID, int BID) {
|
||||
if(SI.getStack().top().to_string() == "0"){
|
||||
SI.getStack().pop();
|
||||
return;
|
||||
}
|
||||
MemoryTy &Mem = SI.getMemory();
|
||||
Address Addr(RID);
|
||||
/// (Addr(RID), SE)
|
||||
z3::expr SE = Mem.at(Addr);
|
||||
SI.getPathCondition().push_back(std::make_pair(BID, SE));
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Const__(int X) {
|
||||
z3::expr SE = SI.getContext().int_val(X);
|
||||
SI.getStack().push(SE);
|
||||
}
|
||||
|
||||
extern "C" void __DSE_Register__(int X) {
|
||||
std::string Name = "R" + std::to_string(X);
|
||||
z3::expr SE = SI.getContext().int_const(Name.c_str());
|
||||
SI.getStack().push(SE);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
.PRECIOUS: %.ll %.instrumented.ll
|
||||
#-Instrument
|
||||
TARGETS=simple0 simple1 simple2 branch0 branch1 branch2 infeasable
|
||||
|
||||
all: ${TARGETS}
|
||||
|
||||
%: %.c
|
||||
clang -emit-llvm -S -fno-discard-value-names -c -o $@.ll $<
|
||||
opt -enable-new-pm=0 -load ../build/InstrumentPass.so -Instrument -S $*.ll -o $*.instrumented.ll
|
||||
clang -o $@ -L${PWD}/../build -lruntime $*.instrumented.ll
|
||||
|
||||
clean:
|
||||
rm -f *.ll *.out *.err *.smt2 input.txt branch.txt ${TARGETS}
|
@ -0,0 +1,26 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x;
|
||||
DSE_Input(x);
|
||||
int y;
|
||||
DSE_Input(y);
|
||||
int z;
|
||||
DSE_Input(z);
|
||||
|
||||
if (x == 1) {
|
||||
if (y == z) {
|
||||
x = x / (y-z);
|
||||
}
|
||||
} else {
|
||||
if(x == 0){
|
||||
x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x;
|
||||
DSE_Input(x);
|
||||
int y;
|
||||
DSE_Input(y);
|
||||
int z;
|
||||
DSE_Input(z);
|
||||
|
||||
if (x == y && y == z) {
|
||||
x = x / (y-z);
|
||||
}
|
||||
else{
|
||||
x = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x;
|
||||
DSE_Input(x);
|
||||
int y;
|
||||
DSE_Input(y);
|
||||
int z;
|
||||
DSE_Input(z);
|
||||
|
||||
|
||||
if (x > y && y > z && z == 0) {
|
||||
x = x / z;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x;
|
||||
DSE_Input(x);
|
||||
|
||||
//c is a product of two primes
|
||||
int c = 1022;
|
||||
|
||||
int y = 1;
|
||||
|
||||
for(int i=0; i<x; i++){
|
||||
y *= 2;
|
||||
}
|
||||
|
||||
if (y % c == 2) {
|
||||
x = x / (c-c);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x = 1;
|
||||
int y = x;
|
||||
int z = 9;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x;
|
||||
DSE_Input(x);
|
||||
int y;
|
||||
DSE_Input(y);
|
||||
int z = (x*y) + (y/x) - (x+y);
|
||||
x = z;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/Runtime.h"
|
||||
|
||||
int main() {
|
||||
int x; DSE_Input(x);
|
||||
int y = x + 1;
|
||||
x = y;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in new issue