-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
050ea3c
commit 0d60276
Showing
11 changed files
with
500 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
LLBIN=/usr/lib/llvm-4.0/bin | ||
LLVM_CONFIG=$(LLBIN)/llvm-config | ||
LDIS=$(LLBIN)/llvm-dis | ||
CPP=$(LLBIN)/clang++ | ||
CC=$(LLBIN)/clang | ||
LLC=$(LLBIN)/llc | ||
OPTB=$(LLBIN)/opt | ||
|
||
#QUIET:=@ | ||
QUIET:= | ||
|
||
SRC_DIR?=$(PWD)/src | ||
BOD=build/obj | ||
|
||
LDFLAGS+=$(shell $(LLVM_CONFIG) --ldflags) | ||
COMMON_FLAGS=-Wall -Wextra -g | ||
CXXFLAGS+=$(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags) | ||
CPPFLAGS+=$(shell $(LLVM_CONFIG) --cppflags) -std=c++11 -I$(SRC_DIR) | ||
LOADABLE_MODULE_OPTIONS=-shared | ||
LIBS=$(shell $(LLVM_CONFIG) --libs) | ||
|
||
PASS=libSingleOut.so | ||
PASS_OBJECTS=SingleOutPass.o \ | ||
NoCallFunctionSieve.o \ | ||
PossiblyCheck.o \ | ||
SeahornBodyRock.o | ||
|
||
default: prep $(PASS) | ||
|
||
prep: | ||
$(QUIET)mkdir -p build/obj | ||
$(QUIET)mkdir -p build/lib | ||
|
||
define builditdood | ||
$(QUIET)$(CPP) -o $(BOD)/$(1)/$(@F) -c $(CPPFLAGS) $(CXXFLAGS) $< | ||
endef | ||
|
||
%.o: %.cpp | ||
@echo "Compiling $*.cpp" | ||
$(call builditdood,.) | ||
|
||
$(PASS) : $(PASS_OBJECTS) | ||
@echo "Linking $@" | ||
$(QUIET)$(CPP) -o build/lib/$@ $(LOADABLE_MODULE_OPTIONS) $(CXXFLAGS) $(LDFLAGS) ${addprefix $(BOD)/,$^} | ||
|
||
clean: | ||
$(QUIET)rm -rf build | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Removes all functions in module with no CallInst or | ||
* InvokeInst instruction. | ||
* | ||
* more lame arr code | ||
*/ | ||
#include "llvm/IR/Module.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/CallSite.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
#include "llvm/Support/CommandLine.h" | ||
|
||
#include <set> | ||
#include <algorithm> | ||
|
||
using namespace llvm; | ||
|
||
#include "NoCallFunctionSieve.h" | ||
|
||
cl::opt<bool> NCFVerbose("no-call-sieve-verbose", cl::desc("verbose yo"), | ||
cl::init(false)); | ||
|
||
cl::opt<unsigned> NCCallLevel("no-call-sieve-level", cl::desc("level"), | ||
cl::init(0)); | ||
|
||
cl::opt<bool> NCGreaterThan("no-call-greater", cl::desc("fns with counts > n"), | ||
cl::init(false)); | ||
|
||
static inline std::vector<std::string> | ||
do_union(std::vector<std::string> keepDecl, std::vector<std::string> calledSet) | ||
{ | ||
std::vector<std::string> d; | ||
std::set_union(keepDecl.begin(), keepDecl.end(), calledSet.begin(), | ||
calledSet.end(), std::back_inserter(d)); | ||
return d; | ||
} | ||
|
||
bool | ||
NoCallFunctionSievePass::runOnModule(Module &M) | ||
{ | ||
std::vector<Function *> removeThese; | ||
bool modified = false; | ||
|
||
std::vector<std::string> keepDecl; | ||
|
||
|
||
for (Function &F : M) { | ||
Function *pF = &F; | ||
std::set<std::string> calledSet; | ||
bool keep = true; | ||
|
||
for (BasicBlock &B : F) { | ||
for (Instruction &I : B) { | ||
if (isa<CallInst>(I) || isa<InvokeInst>(I)) { | ||
CallSite cs(&I); | ||
calledSet.insert(cs.getCalledFunction()->getName().str()); | ||
} | ||
} | ||
} | ||
if (!((NCGreaterThan == false && calledSet.size() == NCCallLevel) || \ | ||
(NCGreaterThan == true && calledSet.size() > NCCallLevel))) { | ||
removeThese.push_back(pF); | ||
continue; | ||
} | ||
std::vector<std::string> calledV; | ||
std::copy(calledSet.begin(), calledSet.end(), std::back_inserter(calledV)); | ||
keepDecl = do_union(keepDecl, calledV); | ||
} | ||
for (auto fi = removeThese.begin(); fi != removeThese.end(); ++fi) { | ||
Function *pF = *fi; | ||
std::string remName = pF->getName().str(); | ||
bool keepIt = false; | ||
for (auto k = keepDecl.begin(); k != keepDecl.end(); ++k) { | ||
std::string s = *k; | ||
if (remName == s) { | ||
keepIt = true; | ||
break; | ||
} | ||
} | ||
if (keepIt) { | ||
pF->deleteBody(); | ||
} else { | ||
pF->eraseFromParent(); | ||
} | ||
} | ||
return modified; | ||
} | ||
|
||
char NoCallFunctionSievePass::ID = 0; | ||
static RegisterPass<NoCallFunctionSievePass> X("no-call-sieve", "no call sieve"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#ifndef _NOCALLFUNCTIONSIEVEPASS_H | ||
#define _NOCALLFUNCTIONSIEVEPASS_H | ||
|
||
struct NoCallFunctionSievePass : ModulePass { | ||
static char ID; | ||
NoCallFunctionSievePass() : ModulePass(ID) {} | ||
virtual bool runOnModule(Module &); | ||
}; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
#!/usr/bin/python | ||
|
||
# There are hardcoded paths... sorry :( | ||
|
||
# target app dir | ||
|
||
import sys | ||
import os | ||
import fnmatch | ||
import json | ||
import subprocess | ||
|
||
def main(): | ||
# By configuration, os.getcwd() gives us the Module dir | ||
modDir = os.getcwd() | ||
|
||
# Find all the android_gradle_build.json files | ||
agb = [] | ||
for root, dns, fns in os.walk(modDir): | ||
for fn in fnmatch.filter(fns, 'android_gradle_build.json'): | ||
agb.append(os.path.join(root, fn)) | ||
|
||
if len(agb) == 0: | ||
print "Failed to find any android_gradle_build.json file to work with." | ||
print "You may need to build your project first, or fix the config of tool" | ||
sys.exit(1) | ||
|
||
|
||
jpath = agb[0] | ||
with open(jpath, "r") as joh: | ||
job = json.load(joh) | ||
cfext = [] | ||
try: | ||
cfext = job["cFileExtensions"] | ||
except: | ||
pass | ||
cppfext = [] | ||
try: | ||
cppfext = job["cppFileExtensions"] | ||
except: | ||
pass | ||
|
||
firstchain = job["toolchains"].keys()[0] | ||
# clang = job["toolchains"][firstchain]["cCompilerExecutable"] | ||
# clangpp = job["toolchains"][firstchain]["cppCompilerExecutable"] | ||
|
||
clang = '/usr/lib/llvm-4.0/bin/clang' | ||
clangpp = '/usr/lib/llvm-4.0/bin/clang++' | ||
opt_bin = '/usr/lib/llvm-4.0/bin/opt' | ||
|
||
|
||
for libs in job["libraries"].keys(): | ||
jf = job["libraries"][libs]["files"] | ||
for fi in jf: | ||
comp = None | ||
if fi["src"].split(".")[-1] in cfext: | ||
comp = clang | ||
elif fi["src"].split(".")[-1] in cppfext: | ||
comp = clangpp | ||
else: | ||
print "Failed to get compiler for {}".format(fi["src"]) | ||
sys.exit(1) | ||
|
||
args = [comp] | ||
args.extend(fi["flags"].split(" ")) | ||
args.append("-emit-llvm") | ||
args.append("-o") | ||
args.append("poschk.bc") | ||
args.append(fi["src"]) | ||
subprocess.check_output(args) | ||
subprocess.check_output([opt_bin, | ||
"-load", | ||
"/home/areiter/SingleOut/build/lib/libSingleOut.so", | ||
"-possibly-check", | ||
"-o", | ||
"/dev/null", | ||
os.path.join(modDir, "poschk.bc")]) | ||
|
||
sys.exit(0) | ||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* not even prototype front end to finding functions that some static | ||
* analysis thinks should have some assume/assert compile time DbC | ||
* checks. | ||
* | ||
* more lame arr code | ||
*/ | ||
#include "llvm/IR/Module.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/BasicBlock.h" | ||
#include "llvm/IR/CFG.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
#include "llvm/Support/CommandLine.h" | ||
|
||
#include <set> | ||
|
||
using namespace llvm; | ||
|
||
#include "PossiblyCheck.h" | ||
|
||
bool | ||
PossiblyCheck::scCheckAll(Function *F) | ||
{ | ||
return true; | ||
} | ||
|
||
bool | ||
PossiblyCheck::scCheckNone(Function *F) | ||
{ | ||
return false; | ||
} | ||
|
||
bool | ||
PossiblyCheck::scCheckCyclo(Function *F) | ||
{ | ||
/* | ||
* For a function in well-formed IR, there should be only | ||
* 1 connected component. | ||
* | ||
* M = E - N + 2C; | ||
* | ||
*/ | ||
unsigned nEdges = 0; // E | ||
unsigned nNodes = 0; // N | ||
unsigned nConnectedComponents = 1; // C | ||
|
||
nNodes = std::distance(F->begin(), F->end()); | ||
for (BasicBlock &BB : *F) { | ||
BasicBlock *b = &BB; | ||
nEdges += std::distance(succ_begin(b), succ_end(b)); | ||
} | ||
unsigned v = (nEdges - nNodes + (2 * nConnectedComponents)); | ||
|
||
/* Make tunable */ | ||
#define ARBITRARY_CCBAR 10 | ||
if (v > 10) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
bool | ||
PossiblyCheck::runOnModule(Module &M) | ||
{ | ||
|
||
for (Function &F : M) { | ||
if (F.isIntrinsic() || F.isDeclaration() || F.hasName() == false) { | ||
continue; | ||
} | ||
std::string Fname = F.getName().str(); | ||
errs() << Fname << ":\n"; | ||
for (auto ci = shouldCheckMap.begin(); ci != shouldCheckMap.end(); | ||
++ci) { | ||
std::string scName = ci->first; | ||
errs() << " Running check test: " << scName << " "; | ||
shouldCheck scFunc = ci->second; | ||
if (scFunc(&F) == true) { | ||
errs() << "(SHOULD CHECK)\n"; | ||
} else { | ||
errs() << "(NO COMMENT)\n"; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
char PossiblyCheck::ID = 0; | ||
static RegisterPass<PossiblyCheck> X("possibly-check", "Possibly add DbC checks"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef _POSSIBLYCHECK_H | ||
#define _POSSIBLYCHECK_H | ||
|
||
#include <map> | ||
|
||
typedef bool (*shouldCheck)(llvm::Function *); | ||
|
||
struct PossiblyCheck : ModulePass { | ||
static char ID; | ||
PossiblyCheck() : ModulePass(ID) {} | ||
virtual bool runOnModule(Module &); | ||
|
||
private: | ||
|
||
// Worth breaking out; this is just a hack to make go. | ||
static bool scCheckAll(Function *); | ||
static bool scCheckNone(Function *); | ||
static bool scCheckCyclo(Function *); | ||
std::map<std::string, shouldCheck> shouldCheckMap = { | ||
std::make_pair("check all", scCheckAll), | ||
std::make_pair("check none", scCheckNone), | ||
std::make_pair("check by cyclo-complexity", scCheckCyclo) | ||
}; | ||
}; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
|
||
## Toys | ||
|
||
Just thinking of ways to insert pre/post condition type stuff into code | ||
after the fact. You'd like to have them in prior to implementation, but | ||
say you want or have to add such annotations on a code base that's already | ||
there. One way to think of going about that process is to look at varying | ||
levels of where functions are defined, depth-wise, by how many unique functions | ||
they call. | ||
So, looking at functions that have 0 call instructions, 1 call instructions, | ||
..., >k call instructions lumped. This may or may not be useful for you | ||
depending on goals. | ||
|
||
Aside from the above, these are mostly just for-fun, so not likely worth | ||
your while, but putting here so they are available. They modify the | ||
module instead of trying to create a new module with the stuff in it. | ||
|
||
### Couple of issues | ||
|
||
- Not yet handling other references to functions (eg, pthread_create(.,.,&function,.)) | ||
- Probably just awful in general. Could benefit from lambda |
Oops, something went wrong.