-
Notifications
You must be signed in to change notification settings - Fork 7
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
0 parents
commit 9428861
Showing
16 changed files
with
584 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,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 |
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,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 |
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,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"); |
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,5 @@ | ||
void foo() | ||
{ | ||
int *x = new int; | ||
delete x; | ||
} |
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,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); | ||
} |
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,8 @@ | ||
int x(); | ||
|
||
|
||
|
||
int main() | ||
{ | ||
return 0; | ||
} |
Oops, something went wrong.