Skip to content

Commit

Permalink
Fix Vtable Mapping For Diamond Inheritance
Browse files Browse the repository at this point in the history
Fixes #22
  • Loading branch information
fundamental committed Dec 6, 2016
1 parent 04ae2b7 commit e308005
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 12 deletions.
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,14 @@ add_test(namespace-disambiguation
${SRC}/test/namespaces.cpp)
set_property(TEST namespace-disambiguation PROPERTY PASS_REGULAR_EXPRESSION
"Total of 2 error")

#Test virtual inheritance combined with diamond graph structures
add_test(diamond
${RUBY} ${CMAKE_SOURCE_DIR}/test/run-test.rb
${CMAKE_SOURCE_DIR}/stoat
${CMAKE_BINARY_DIR}/libstoat.so
${CLANGPP}
${CMAKE_SOURCE_DIR}/data/whitelist.txt
${CMAKE_SOURCE_DIR}/data/blacklist.txt
nil
${SRC}/test/diamond-inherit.cpp)
2 changes: 1 addition & 1 deletion lib/callgraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def add_subclass_calls(classes, vtables)
iter += 1
end
end
currently_processed = offset-1
#currently_processed = offset-1
end
end
end
Expand Down
53 changes: 42 additions & 11 deletions src/llvm-passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ struct ExtractClassHierarchy : public FunctionPass {
if(auto cast = dyn_cast<BitCastInst>(getelm->getOperand(0))) {
if(auto load = dyn_cast<LoadInst>(cast->getOperand(0))) {
if(this_ptr == dyn_cast<Instruction>(load->getOperand(0))) {
//getelm->dump();
if(!dyn_cast<ConstantInt>(getelm->getOperand(1)))
return "";
unsigned off = dyn_cast<ConstantInt>(getelm->getOperand(1))->getZExtValue()/8;
Expand All @@ -412,14 +411,26 @@ struct ExtractClassHierarchy : public FunctionPass {
std::string s = ss.str();
//fprintf(stderr, "name = %s\n", s.c_str());
int l = s.length();
if(s.substr(0,6) == "%class")
return s.substr(7, l-8)+"+"+to_s(off);
if(s.substr(0,7) == "%\"class")
return s.substr(8, l-10)+"+"+to_s(off);
if(s.substr(0,7) == "%struct")
return ss.str().substr(8, l-9)+"+"+to_s(off);
if(s.substr(0,8) == "%\"struct")
return s.substr(9, l-11)+"+"+to_s(off);
//if(off) {
if(s.substr(0,6) == "%class")
return s.substr(7, l-8)+"+"+to_s(off);
if(s.substr(0,7) == "%\"class")
return s.substr(8, l-10)+"+"+to_s(off);
if(s.substr(0,7) == "%struct")
return ss.str().substr(8, l-9)+"+"+to_s(off);
if(s.substr(0,8) == "%\"struct")
return s.substr(9, l-11)+"+"+to_s(off);
//} else {
// if(s.substr(0,6) == "%class")
// return s.substr(7, l-8);
// if(s.substr(0,7) == "%\"class")
// return s.substr(8, l-10);
// if(s.substr(0,7) == "%struct")
// return ss.str().substr(8, l-9);
// if(s.substr(0,8) == "%\"struct")
// return s.substr(9, l-11);
//}

}
}
}
Expand All @@ -445,6 +456,8 @@ struct ExtractClassHierarchy : public FunctionPass {
//later there is a load of this %this.addr
//if this load is cast into anything other than i8***, then that's a
//super class
//fprintf(stderr, "%s : %s : %s\n", name.c_str(), fullname.c_str(), alias.c_str());
//Fn.dump();

std::vector<string> class_list;
Instruction *this_ptr = NULL;
Expand Down Expand Up @@ -553,6 +566,7 @@ struct ExtractVtables : public ModulePass {
{
auto op = v->getOperand(i);
char *fname = NULL;
//op->dump();
if(!dyn_cast<ConstantPointerNull>(op)) {
Function *function = NULL;
auto alias = dyn_cast<GlobalAlias>(op->getOperand(0));
Expand All @@ -566,12 +580,29 @@ struct ExtractVtables : public ModulePass {
}
if(fname && strlen(fname) == 0)
fname = NULL;

if(dyn_cast<ConstantPointerNull>(op)) {
ii += 1;
continue;
}

if(!fname) {
int variant_id = 0;
if(op->getNumOperands())
if(auto n = dyn_cast<ConstantInt>(op->getOperand(0)))
if(op->getNumOperands()) {
if(auto n = dyn_cast<ConstantInt>(op->getOperand(0))) {
if(n->getSExtValue() <= 1) {
continue;
}
variant_id = -n->getZExtValue()/8;
if(variant_id == -1) {
ii++;
continue;
}
} else {
ii++;
continue;
}
}
fprintf(stderr, "%s.variant%d:\n", name, variant_id);//++variant);
i++;
ii+=2;
Expand Down
50 changes: 50 additions & 0 deletions test/diamond-confuse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
class A
{
public:
A(){}
virtual ~A(){}
virtual void method_b(void) = 0;
virtual void method_c(void) = 0;
virtual void method_d(void) = 0;
};

class B:virtual public A
{
public:
B(){};
virtual ~B(){};
virtual void method_b(void) {}
virtual void method_c(void) {}
};

class C:virtual public A
{
public:
C(){}
virtual ~C(){}
virtual void method_b(void) {}
virtual void method_c(void) {}
virtual void method_d(void) {}
};

class D:virtual public B
{
public:
D(){}
virtual ~D(){}
virtual void method_d(void) {}
C c;
};

void dummy()
{
D d;
}

void test(A *a) __attribute__((annotate("realtime")))
{
a->method_b();
a->method_c();
a->method_d();
}

46 changes: 46 additions & 0 deletions test/diamond-inherit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class A
{
public:
A(){}
virtual ~A(){}
virtual void method_b(void) = 0;
virtual void method_c(void) = 0;
virtual void method_d(void) = 0;
};

class B:virtual public A
{
public:
B(){};
virtual ~B(){};
virtual void method_b(void) {}
};

class C:virtual public A
{
public:
C(){}
virtual ~C(){}
virtual void method_c(void) {}
};

class D:virtual public B, virtual public C
{
public:
D(){}
virtual ~D(){}
virtual void method_d(void) {}
};

void dummy()
{
D d;
}

void test(A *a) __attribute__((annotate("realtime")))
{
a->method_b();
a->method_c();
a->method_d();
}

0 comments on commit e308005

Please sign in to comment.