Skip to content

Commit a363dca

Browse files
author
Kaipeng Zeng
authored
Merge pull request #36 from Bins94/master
Attach static analysis code and kernel instrument code
2 parents ffbfaf5 + c63bb30 commit a363dca

File tree

11 files changed

+1153
-2
lines changed

11 files changed

+1153
-2
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#include <llvm/IR/Module.h>
2+
#include <llvm/IRReader/IRReader.h>
3+
#include <llvm/IR/LLVMContext.h>
4+
#include <llvm/Support/SourceMgr.h>
5+
#include <llvm/Support/raw_ostream.h>
6+
#include <llvm/IR/InstrTypes.h>
7+
#include <llvm/IR/Instructions.h>
8+
#include <llvm/Analysis/CmpInstAnalysis.h>
9+
#include <llvm/IR/DebugLoc.h>
10+
#include "llvm/IR/DebugInfo.h"
11+
#include "llvm/IR/DIBuilder.h"
12+
#include "llvm/IR/Function.h"
13+
#include <llvm/IR/DebugInfoMetadata.h>
14+
#include <llvm/IR/CFG.h>
15+
#include <llvm/IR/Metadata.h>
16+
#include <llvm/Analysis/CallGraph.h>
17+
18+
#include <string>
19+
#include <iostream>
20+
#include <sstream>
21+
#include <fstream>
22+
#include <sys/types.h>
23+
#include <dirent.h>
24+
#include <vector>
25+
26+
#include "log.h"
27+
28+
29+
using namespace std;
30+
using namespace llvm;
31+
32+
33+
std::vector<std::string> readFuncList(std::string funcListPath);
34+
std::vector<std::string> getIRList(std::string IRDirPath);
35+
std::map<std::string, int> FuncComplexity;
36+
37+
void getCalledFunc(CallGraph *CG, const Function *f, int blockNum, int level, std::vector<std::string> *funcList, std::string rootFunc);
38+
void writeToNewFuncList(std::vector<std::string> funcList, std::string oldPath);
39+
40+
int main(int argc, const char *argv[]) {
41+
if (argc < 2 || argv[1] == nullptr) {
42+
outs() << "./extern_func functions_list ir_dir\n";
43+
return 1;
44+
}
45+
std::string FuncListPath = argv[1];
46+
std::string IRDirPath = argv[2];
47+
48+
std::vector<std::string> IRList = getIRList(IRDirPath);
49+
std::vector<std::string> funcList = readFuncList(FuncListPath);
50+
std::vector<std::string> extFuncList;
51+
52+
for (std::string ir : IRList) {
53+
LLVMContext ctx;
54+
SMDiagnostic err;
55+
std::unique_ptr<Module> mod = parseIRFile(ir, err, ctx);
56+
if (mod == nullptr) {
57+
outs() << FAIL << "Failed to open ir file: " << ir << "\n" << RESET;
58+
continue;
59+
}
60+
Module *constMod = mod.get();
61+
CallGraph CG(*constMod);
62+
for (std::string fn : funcList) {
63+
const Function *func = constMod->getFunction(fn);
64+
if (func == nullptr || func->size() < 1)
65+
continue;
66+
FuncComplexity[fn] = func->size();
67+
outs() << "Function: " << fn << " was found\n";
68+
if (func->size() < 20)
69+
getCalledFunc(&CG, func, 7, 3, &extFuncList, fn);
70+
}
71+
}
72+
73+
/* Show the sum blocks of enable functions of a root function */
74+
outs() << "Extended function:\n";
75+
for (auto &i : FuncComplexity) {
76+
outs() << "Function: " << i.first << " with " << i.second << " blocks\n";
77+
}
78+
79+
for (std::string f : extFuncList) {
80+
bool found = false;
81+
for (std::string ff : funcList) {
82+
if (f == ff) {
83+
found = true;
84+
break;
85+
}
86+
}
87+
if (found)
88+
continue;
89+
funcList.push_back(f);
90+
}
91+
/* Create a FuncListPath.new file for extended functions list */
92+
writeToNewFuncList(funcList, FuncListPath);
93+
}
94+
95+
std::vector<std::string> readFuncList(std::string funcListPath) {
96+
fstream funcListFile(funcListPath);
97+
std::vector<std::string> funcList;
98+
std::string fn = "";
99+
if (!funcListFile.is_open()) {
100+
outs() << FAIL << "Failed to open init function list\n" << RESET;
101+
return funcList;
102+
}
103+
while (getline(funcListFile, fn)) {
104+
if(fn != "")
105+
funcList.push_back(fn);
106+
}
107+
return funcList;
108+
}
109+
110+
std::vector<std::string> getIRList(std::string IRDirPath) {
111+
std::vector<std::string> ret;
112+
struct dirent *entry;
113+
DIR *dir = opendir(IRDirPath.c_str());
114+
if (dir == NULL) {
115+
return ret;
116+
}
117+
while ((entry = readdir(dir)) != NULL) {
118+
ret.push_back(IRDirPath + "/" + entry->d_name);
119+
}
120+
closedir(dir);
121+
return ret;
122+
}
123+
124+
/* Recursively get the called functions, use blockNum and level limit functions */
125+
void getCalledFunc(CallGraph *CG, const Function *f, int blockNum, int level, std::vector<std::string> *funcList, std::string rootFunc) {
126+
const CallGraphNode *n = (*CG)[f];
127+
if (level < 1)
128+
return;
129+
if (n == nullptr) {
130+
outs() << FAIL << "Failed to get call graph node\n" << RESET;
131+
return;
132+
}
133+
for (auto i : *n) {
134+
Function *calledFunc = i.second->getFunction();
135+
if (calledFunc != nullptr) {
136+
/* Skip the instument function */
137+
if (calledFunc->getName().find("saniti") != std::string::npos)
138+
continue;
139+
if (calledFunc->getName().find("asan") != std::string::npos)
140+
continue;
141+
if (calledFunc->size() > blockNum) {
142+
funcList->push_back(calledFunc->getName());
143+
outs() << "Add function " << calledFunc->getName() << " to root " << rootFunc << " at level " << level << "\n";
144+
/* Calculate the sum of blocks from root function to every called functions */
145+
FuncComplexity[rootFunc] += calledFunc->size();
146+
}
147+
/* Recursive call with a depth level */
148+
getCalledFunc(CG, calledFunc, blockNum, level - 1, funcList, rootFunc);
149+
}
150+
}
151+
return;
152+
}
153+
154+
void writeToNewFuncList(std::vector<std::string> funcList, std::string oldPath) {
155+
ofstream newFuncList;
156+
newFuncList.open(oldPath + ".new");
157+
for (std::string f : funcList) {
158+
newFuncList << f << "\n";
159+
}
160+
newFuncList.close();
161+
162+
}

static_analysis_tools/IRParser/info.h

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#include <string>
2+
#include <unordered_map>
3+
4+
using namespace std;
5+
6+
class sanCallInfo {
7+
private:
8+
std::string rawInst;
9+
unsigned blockID;
10+
unsigned address;
11+
public:
12+
sanCallInfo(std::string rawI, unsigned bID) {
13+
rawInst = rawI;
14+
blockID = bID;
15+
}
16+
sanCallInfo(){};
17+
void AttachAddress(unsigned addr) {
18+
address = addr;
19+
}
20+
unsigned getBlockID() {
21+
return blockID;
22+
}
23+
std::string getAsLine() {
24+
return std::to_string(address) + ": " + rawInst;
25+
}
26+
unsigned getAddress() {
27+
return address;
28+
}
29+
};
30+
31+
class blockInfo {
32+
private:
33+
unsigned blockID;
34+
std::string blockName;
35+
std::string funcName;
36+
unsigned long count;
37+
38+
std::vector<sanCallInfo> sanCalls;
39+
std::vector<unsigned> succBlock;
40+
std::vector<unsigned> predBlock;
41+
42+
public:
43+
blockInfo(unsigned bID, std::string bName, std::string fName, unsigned cnt) {
44+
blockID = bID;
45+
blockName = bName;
46+
funcName = fName;
47+
count = cnt;
48+
}
49+
50+
blockInfo(){};
51+
52+
unsigned getBlockID() {
53+
return blockID;
54+
}
55+
56+
void addSuccBlock(unsigned bID) {
57+
for (unsigned i : succBlock) {
58+
if (i == bID)
59+
return;
60+
}
61+
succBlock.push_back(bID);
62+
}
63+
64+
void addPredBlock(unsigned bID) {
65+
for (unsigned i : predBlock) {
66+
if (i == bID)
67+
return;
68+
}
69+
predBlock.push_back(bID);
70+
}
71+
72+
void addSanCall(sanCallInfo sc) {
73+
sanCalls.push_back(sc);
74+
}
75+
76+
std::vector<sanCallInfo> getSanCalls() {
77+
return sanCalls;
78+
}
79+
80+
unsigned getForwardEdgeNum() {
81+
/* We use this method to get the weight of this block */
82+
//return count;
83+
return succBlock.size();
84+
}
85+
86+
std::string getAsJson() {
87+
std::string ret = "";
88+
ret += "{\n";
89+
ret += "Function: \"" + funcName + "\",\n";
90+
ret += "Block: \"" + blockName + "\",\n";
91+
ret += "BlockID: " + std::to_string(blockID) + ",\n";
92+
ret += "Count: " + std::to_string(count) + ",\n";
93+
ret += "Predblocks: [";
94+
for (unsigned b : predBlock)
95+
ret += std::to_string(b) + ", ";
96+
ret += "],\n";
97+
ret += "Succblocks: [";
98+
for (unsigned b : succBlock)
99+
ret += std::to_string(b) + ", ";
100+
ret += "],\n";
101+
ret += "SanitizerCall: [\n";
102+
for (sanCallInfo sc : sanCalls) {
103+
ret += "\t" + sc.getAsLine() + ",\n";
104+
}
105+
ret += "\t],\n";
106+
ret += "}\n";
107+
return ret;
108+
}
109+
};
110+
111+
class gepInfo {
112+
private:
113+
std::string structName;
114+
std::string fieldName;
115+
unsigned bitWidth;
116+
unsigned count;
117+
unsigned ID;
118+
119+
unsigned hash(string s) {
120+
std::hash<std::string> hashFunc;
121+
return hashFunc(s);
122+
}
123+
124+
std::string stripNum(std::string name) {
125+
size_t len = name.size();
126+
char tmp[len];
127+
strncpy(tmp, name.c_str(), len);
128+
if (len < 1)
129+
return name;
130+
/* llvm will add suffix to variable name, we have to strip away*/
131+
while ((tmp[len-1] <= '9' && tmp[len-1] >= '0' && len > 1)
132+
|| (tmp[len-1] == 'i' && tmp[len-2] == '.' && len > 2)
133+
|| (tmp[len-1] == '.' && len > 1)) {
134+
if (tmp[len-1] == 'i' && tmp[len-2] == '.') {
135+
tmp[len-1] = 0;
136+
tmp[len-2] = 0;
137+
len -= 2;
138+
continue;
139+
}
140+
tmp[len-1] = 0;
141+
len--;
142+
}
143+
name = name.substr(0, len);
144+
return name;
145+
}
146+
147+
public:
148+
gepInfo(std::string srtName, std::string fName, unsigned bitWid) {
149+
structName = srtName;
150+
fieldName = fName;
151+
bitWidth = bitWid;
152+
ID = hash(getStructName());
153+
count = 0;
154+
}
155+
156+
gepInfo(){};
157+
158+
std::string getStructName() {
159+
return stripNum(structName) + "->" + stripNum(fieldName);
160+
}
161+
162+
void incCount() {count++;}
163+
164+
/* We use this method to get the weight of a kernel state */
165+
unsigned getCount() {return count;}
166+
167+
unsigned getGEPointerID() {return ID;}
168+
169+
std::string getAsJson() {
170+
std::string ret;
171+
ret += "{\n";
172+
ret += "\tName: " + structName + "->" + fieldName + ",\n";
173+
ret += "\tBitWidth: " + std::to_string(bitWidth) + ",\n";
174+
ret += "\tID: " + std::to_string(ID) + "\n";
175+
ret += "}\n";
176+
return ret;
177+
}
178+
};

0 commit comments

Comments
 (0)