Skip to content

Commit

Permalink
Initial Rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
fundamental committed Aug 9, 2014
0 parents commit 9428861
Show file tree
Hide file tree
Showing 16 changed files with 584 additions and 0 deletions.
31 changes: 31 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Realtime Function Static Analysis
---------------------------------

Pass 1
~~~~~~

Generate Function List and Annotations
Perhaps annotate rtosc ports somehow

Code 1.5
~~~~~~~~

Merge in blacklist/whitelist information

Pass 2
~~~~~~

Populate the MultiGraph

Function->Function
:source location with source function

Code 2.5
~~~~~~~~

Perform same graph operations to determine problematic sequences

Pass 3
~~~~~~

Gather more information about source if needed
207 changes: 207 additions & 0 deletions run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
require 'optparse'
require 'ostruct'
require 'set'
require 'yaml'
require 'pp'


#Modifies mapa s.t. it includes the mapb info
def merge_maps(mapa, mapb)
mapb.each do |key, val|
if(mapa.has_key? key)
mapa[key].concat val
else
mapa[key] = val
end
end
end


options = OpenStruct.new
options.whitelist = []
options.blacklist = []
options.unmangled = OpenStruct.new
options.unmangled.whitelist = []
options.unmangled.blacklist = []
options.root = "./"
options.dir = []
options.recursive = false

OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options] FILE"

opts.on("-w", "--whitelist FILE",
"Define a Mangled Whitelist File") do |list|
options.whitelist << list
end

opts.on("-b", "--blacklist FILE",
"Define a Mangled Blacklist File") do |list|
options.blacklist << list
end

#opts.on("-W", "--unmangled-whitelist FILE",
# "Define an Unmangled Whitelist File") do |list|
# options.unmangled.whitelist << list
#end

#opts.on("-B", "--unmangled-blacklist FILE",
# "Define an Unmangled Blacklist File") do |list|
# options.unmangled.blacklist << list
#end

#opts.on("-s", "--search DIR",
# "Search Within the Defined Directory") do |dir|
# options.dirs << dir
#end

opts.on("-r", "--recursive DIR",
"Enable Recursive Search Mode") do |dir|
options.recursive = true
options.root = dir
end
end.parse!

#If there are unmangled files, then mangle them and add them to the end of the
#mangled lists

#For each one of the bitcode files, run the pass based preprocessor
if(!options.recursive)
$stderr.puts "This Program Must Process Input Recursively At this time"
exit 1
end
files = `find #{options.root} -type f | grep -e "\\.bc$"`.split
#p files
callgraph = Hash.new
function_props = Hash.new

files.each do |f|
p "running #{f} file..."
`opt -load ./src/libfoo.so --dummy1 < #{f} > /dev/null 2> sfpv_output.txt`
#puts File.read("sfpv_output.txt")
ncallgraph = YAML.load_file "sfpv_output.txt"


`opt -load ./src/libfoo.so --dummy2 < #{f} > /dev/null 2> sfpv_output.txt`
#puts File.read("sfpv_output.txt")
nfunc = YAML.load_file "sfpv_output.txt"

if(ncallgraph)
merge_maps(callgraph, ncallgraph)
end
if(nfunc)
merge_maps(function_props, nfunc)
end
end

symbol_list = Set.new
callgraph.each do |key,val|
symbol_list << key
val.each do |x|
symbol_list << x
end
end

demangled_symbols = Hash.new
symbol_list.each do |x|
demangled_symbols[x] = `echo '#{x}' | c++filt`
end
pp demangled_symbols


reason_user_w = "The Function Was Declared Realtime By A Whitelist"
reason_user_b = "The Function Was Declared NonRealtime By A Blacklist"
reason_code_w = "The Function Was Declared Realtime By A Code Annotation"
reason_code_b = "The Function Was Declared NonRealtime By A Code Annotation"
reason_deduced = "The Function Was Deduced To Need To Be RealTime As It Was Called By A Realtime Function"
reason_none = "No Deduction has occured"
reason_nocode = "No Code Or Annotations, So The Function is Assumed Unsafe"

class DeductionChain
attr_accessor :deduction_source, :reason, :realtime_p, :non_realtime_p, :has_body_p, :contradicted_p, :contradicted_by

def initialize
@deduction_source = nil
@reason = "No Deduction has occured"
@realtime_p = false
@non_realtime_p = false
@has_body_p = false
@contradicted_p = false
@contradicted_by = Set.new
end
end

property_list = Hash.new
symbol_list.each do |x|
property_list[x] = DeductionChain.new
end

#Add information about finding source
callgraph.each do |key,value|
property_list[key].has_body_p = true
end

#Add Anything That's On the function_props list
function_props.each do |key, value|
if(property_list.include? key)
if(value.include? 'realtime')
property_list[key].realtime_p = true
property_list[key].reason = reason_code_w
elsif(value.include? 'non-realtime')
property_list[key].non_realtime_p = true
property_list[key].reason = reason_code_b
end
end
end

#Add no source stuff
property_list.each do |key, value|
if(!value.has_body_p && !value.realtime_p && !value.non_realtime_p)
value.non_realtime_p = true
value.reason = reason_nocode
end
end

#Perform Deductions
do_stuff = true
while do_stuff
do_stuff = false
property_list.each do |key, value|
if(!value.contradicted_p)
if(value.realtime_p() && callgraph.include?(key))
callgraph[key].each do |x|
if(property_list[x].non_realtime_p)
value.contradicted_p = true
value.contradicted_by << x
do_stuff = true
elsif(!property_list[x].realtime_p)
property_list[x].realtime_p = true
property_list[x].deduction_source = key
property_list[x].reason = reason_deduced
do_stuff = true
end
end
end
end
end
end



#pp symbol_list
#pp callgraph
#puts "\n\n\n\n\n"
#pp function_props
#pp property_list

property_list.each do |key, value|
if(value.contradicted_p)
pp key
pp value
puts "\n\n\n"
end
end


#p options
#p ARGV
101 changes: 101 additions & 0 deletions src/pass1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <llvm/Analysis/CallGraph.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Pass.h>

using namespace llvm;
using std::string;

namespace {
struct DummyPass : public FunctionPass {
static char ID; // Pass ID, replacement for typeid
DummyPass() : FunctionPass(ID) {}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}

bool runOnFunction(Function &Fn) override {
//Fn.dump();
//auto attr = Fn.getAttributes();
//attr.dump();
std::vector<string> v;
//Fn.dump();
for(auto &bb:Fn) {
for(auto &i:bb) {
if(i.getOpcode() == Instruction::Call) {
auto call = dyn_cast<CallInst>(&i);
auto fn2 = call->getCalledFunction();
if(!fn2)
continue;
auto s = fn2->getName().str();
if(s == "llvm.dbg.value")
continue;
if(fn2)
v.push_back(s);
}
}
}
if(!v.empty()) {
fprintf(stderr, "%s :\n", Fn.getName().str().c_str());
for(auto x:v)
fprintf(stderr, " - %s\n", x.c_str());
}
return false;
}
};

struct DummyPass2 : public ModulePass {
static char ID; // Pass ID, replacement for typeid
DummyPass2() : ModulePass(ID) {}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}

void handleNested(Value *v)
{
if(auto o = dyn_cast<Function>(v))
{
fprintf(stderr, "%s :\n", o->getName().str().c_str());
} else if(auto s = dyn_cast<GlobalVariable>(v)) {
fprintf(stderr, " - %s\n", dyn_cast<ConstantDataArray>(s->getOperand(0))->getAsString().str().c_str());
} else
fprintf(stderr, "We have a dinosaur\n");


}

bool runOnModule(Module &m) override {
auto g = m.getNamedGlobal("llvm.global.annotations");
if(g) {
auto gg = dyn_cast<ConstantArray>(g->getOperand(0));
auto ggg = gg->getOperand(0);
unsigned ops = ggg->getNumOperands();
if(ops > 2)
ops = 2;
for(unsigned i=0; i<ops; ++i) {
auto op = ggg->getOperand(i);
if(auto o = dyn_cast<ConstantExpr>(op))
{
//fprintf(stderr, "Case 1[");
//o->getOperand(0)->dump();;
//fprintf(stderr, "]\n");
handleNested(o->getOperand(0));

}
//fprintf(stderr,"\n");
}
//fprintf(stderr, "I found it\n");
}
return false;
}
};
}

char DummyPass::ID = 0;
char DummyPass2::ID = 0;
static RegisterPass<DummyPass> P1("dummy1", "do nothin");
static RegisterPass<DummyPass2> P2("dummy2", "do nothin");
5 changes: 5 additions & 0 deletions test/cpp-new-detection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void foo()
{
int *x = new int;
delete x;
}
31 changes: 31 additions & 0 deletions test/function-pointer-call.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#define REALTIME __attribute__((annotate("realtime")))
#define NREALTIME __attribute__((annotate("!realtime")))

typedef int (*callback_t)(int, void*);

void make_realtime(callback_t REALTIME call, void*)
{
}

void NREALTIME malloc_of_doooooooooom();

class Runner
{
public:
int process(int, void*)
{
malloc_of_doooooooooom();
return 1;
}

static int _process(int i, void* data)
{
Runner *ptr = (Runner*)(data);
return ptr->process(i,data);
}
};

int main()
{
make_realtime(Runner::_process, new Runner);
}
8 changes: 8 additions & 0 deletions test/function-pointer-resolution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
int x();



int main()
{
return 0;
}
Loading

0 comments on commit 9428861

Please sign in to comment.