1
votes

I need to identify virtual function call sites in my LLVM pass, as well as identify possible candidate functions which may be called at run time.

class B
{
   virtual void F() { // do something }
};

class D : public B
{
 void F() { // do something else }
};

B* d = new D();
d->F();

For example for the given hierarchy and call of F, identify both B::F and D::F as a possible candidates.

While looking for a solution, I came across Clang CFI (Control flow integration), where they said they are identifying if a virtual table pointer is a valid one by checking if it is in a set of candidate virtual table pointers. Thus I assume there is a way to get this information about inheritance hierarchy. But I was not able to find anything how to get this done in llvm.

So does anyone have an idea how this could be done?

1

1 Answers

1
votes

With help of llvm developers I found a way to solve my problem, and thought to share it here, in case if someone will need it.

There is a transformation pass -wholeprogramdevirt in llvm, which is doing pretty much what I wanted to achieve. It identifies virtual call sites and candidate callees in a module, then tries to devirtualize these calls if possible. For example if a virtual function is implemented only in one class of hierarchy, an indirect call to this function will be replaced with direct call of the implemented function.

class B
{
virtual void F() { // do something }
};

class D : public B {};

B* d = new D();
d->F();

So for this case indirect call of F, is going to be replaced with direct call of B::F. The WholeProgramDevirt pass uses type metadata and llvm type checking intrinsic functions to identify virtual call sites and candidate callees.

First you’ll need to get bitcode with clang’s -fwhole-program-vtables flag enabled. This will generate corresponding intrinsic functions for virtual call sites. Those intrinsic functions are llvm.type.test, llvm.checked.load and llvm.assume. Then using these intrinsics whole program devirtualizer finds virtual call sites and for each of them candidate callees.

For my case, I don’t need to do transformations, so I implement this as an analysis pass and collect the results for further uses.