2017-04-24 1 views
1

Ich muss virtuelle Funktionsaufrufe in meinem LLVM-Durchlauf identifizieren sowie mögliche Kandidatenfunktionen identifizieren, die zur Laufzeit aufgerufen werden können.Identifizieren von virtuellen Anruforten in llvm

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

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

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

beispielsweise für die gegebene Hierarchie und Aufruf von F, identifizieren sowohl B :: F und D :: F als mögliche Kandidaten. Während ich nach einer Lösung suchte, stieß ich auf Clang CFI (Kontrollflussintegration), wo sie sagten, dass sie identifizieren, ob ein virtueller Tabellenzeiger ein gültiger ist, indem sie überprüft, ob sie in einer Menge von möglichen virtuellen Tabellenzeigern enthalten ist. Daher nehme ich an, dass es eine Möglichkeit gibt, diese Informationen über die Vererbungshierarchie zu erhalten. Aber ich konnte nichts finden, wie man das in llvm machen könnte.

Hat also jemand eine Idee, wie das gemacht werden könnte?

Antwort

1

Mit Hilfe von llvm-Entwicklern habe ich einen Weg gefunden, mein Problem zu lösen, und dachte, es hier zu teilen, falls jemand es brauchen sollte.

Es gibt eine Transformation pass -wholeprogramdevirt in llvm, die ziemlich genau das tut, was ich erreichen wollte. Er identifiziert virtuelle Call-Sites und Kandidaten-Calles in einem Modul und versucht, diese Calls nach Möglichkeit zu devirtualisieren. Wenn beispielsweise eine virtuelle Funktion nur in einer Hierarchieklasse implementiert ist, wird ein indirekter Aufruf dieser Funktion durch den direkten Aufruf der implementierten Funktion ersetzt.

Also für diesen Fall indirekten Aufruf von F, wird mit direktem Aufruf von B :: F ersetzt werden. Der WholeProgramDevirt-Pass verwendet Typmetadaten und llvm-Typ, der die systeminternen Funktionen überprüft, um virtuelle Call-Sites und Kandidaten-Calles zu identifizieren.

Zunächst müssen Sie den Bitcode mit dem Flag clanning -fwhole-program-vtables aktivieren. Dies erzeugt entsprechende intrinsische Funktionen für virtuelle Rufstellen. Diese intrinsischen Funktionen sind llvm.type.test, llvm.checked.load und llvm.assume. Mit diesen Intrinsics findet das gesamte Programm Devirtualizer virtuelle Call-Sites und für jeden von ihnen Kandidaten Calles.

Für meinen Fall muss ich keine Transformationen durchführen, daher implementiere ich dies als Analysepass und sammle die Ergebnisse für weitere Verwendungen.