2017-04-24 8 views
1

내 LLVM 패스에서 가상 함수 호출 사이트를 식별하고 런타임에 호출 할 수있는 가능한 후보 함수를 식별해야합니다.llvm의 가상 호출 사이트 식별

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

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

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

는 F의 소정의 계층과 통화 예를 들어, 가능한 후보로서 모두 B : F 및 D : F를 식별한다.

해결책을 찾고있는 동안 Clang CFI (제어 흐름 통합)를 통해 가상 테이블 포인터가 후보 가상 테이블 포인터 집합에 있는지 확인하여 가상 테이블 포인터가 유효한 것인지 식별합니다. 따라서 상속 계층 구조에 대한 정보를 얻는 방법이 있다고 가정합니다. 그러나 나는 이것을 llvm에서하는 방법을 찾을 수 없었다.

그렇다면이 작업을 수행하는 방법에 대해 누구나 알고 있습니까?

답변

1

llvm 개발자의 도움으로 문제를 해결할 수있는 방법을 찾았습니다. 누군가가 필요로 할 경우를 대비하여 여기에서 공유 할 생각이었습니다.

llvm에는 변환 통과 -wholeprogramdevirt가 있습니다. 이는 달성하고 싶은 것을 수행하고 있습니다. 모듈에서 가상 호출 사이트 및 후보 호출 수신자를 식별 한 다음 가능한 경우 이러한 호출을 가상화하려고 시도합니다. 예를 들어 가상 함수가 한 계층의 계층에서만 구현되는 경우이 함수에 대한 간접 호출은 구현 된 함수의 직접 호출로 바뀝니다.

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

class D : public B {}; 

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

이 경우 F의 간접 호출은 B :: F의 직접 호출로 바뀝니다. WholeProgramDevirt 패스는 유형 메타 데이터 및 llvm 유형 확인 내장 함수를 사용하여 가상 호출 사이트 및 후보 호출 수신자를 식별합니다.

먼저 clang의 -fwhole-program-vtables 플래그를 사용하여 비트 코드를 가져와야합니다. 이것은 가상 호출 사이트에 상응하는 내장 함수를 생성합니다. 이러한 내장 함수는 llvm.type.test, llvm.checked.load 및 llvm.assume입니다. 그런 다음 이러한 내장 함수를 사용하여 전체 프로그램 devirtualizer는 가상 호출 사이트와 후보 호출 수신자 각각을 찾습니다.

필자의 경우 변환을 수행 할 필요가 없으므로이를 분석 단계로 구현하고 이후 사용을 위해 결과를 수집합니다.