2017-02-10 10 views
1

C 소스 파일에서 데이터 구조를 구문 분석하고 얻으려면 최상의 솔루션이 무엇인지 궁금합니다. 내가 가지고 있다고 가정하자 :구문 분석 데이터 구조 clang/LLVM

typedef int M_Int; 
typedef float* P_Float; 

typedef struct Foo { 
    M_Int a; 
    P_Float p_f; 
} Foo; 

이 두 변수 a 및 구조체 Foop_f의 프리미티브를 얻기 위해 데이터 구조를 전개하는 가장 좋은 방법은 무엇입니까?

매우 간단한 예제로 AST를 파싱하는 것이 가장 좋은 방법 일 수 있지만 코드가 복잡해지면 IR 코드로 좀 더 낮은 수준의 방법으로 작업하는 것이 더 좋을까요?

답변

0

llvm 디버그 정보를 사용하여 필요한 정보를 얻을 수 있습니다. -g 옵션을 사용하여 C 코드를 컴파일하면 모든 정보가 포함 된 디버그 정보가 생성됩니다. llvm debuginfo에 대한 이해는 대부분 자신의 구조 및 액세스 방법에 대한 많은 문서가 없기 때문에 까다 롭습니다. 여기에 몇 가지 링크가 있습니다 :

1) http://llvm.org/docs/SourceLevelDebugging.html

2) 저는 여기에있는 디버그 정보를 사용하고 있어요 프로젝트에 대한 링크입니다. 많은 문서가 없지만 debuginfo 클래스의 사용법을 보는 것이 유용 할 수 있으므로이 방법은 유용하지 않을 수 있습니다. 우리는 C 함수의 모든 포인터 매개 변수 (구조 매개 변수의 경우 필드 이름 포함)에 대한 필드 이름을 얻으려고합니다. debuginfo 액세스와 관련된 모든 코드는 다음 파일에 있습니다. https://github.com/jiten-thakkar/DataStructureAnalysis/blob/dsa_llvm3.8/lib/dsaGenerator/DSAGenerator.cpp

0

AST는 기본 수준을 찾기에 적합합니다. Clang은 libtooling과 함께 사용되는 AST Matchers 및 Callbacks를 사용하여이 프로세스를 자동화하고 확장 할 수 있습니다. 예를 들어, AST의 정규 조합

fieldDecl(hasType(tyoedefType().bind("typedef"))).bind("field") 

대신의 타입 정의로 선언 된 C 구조체의 필드와 일치합니다 내장 타입입니다. bind() 호출은 AST 노드를 콜백에 액세스 가능하게 만듭니다.

typedef-report Foo.h -- # Note two dashes 

실행이되면

virtual void run(clang::ast_matchers::MatchFinder::MatchResult const & result) override 
{ 
    using namespace clang; 
    FieldDecl * f_decl = 
     const_cast<FieldDecl *>(result.Nodes.getNodeAs<FieldDecl>("field")); 
    TypedefType * tt = const_cast<TypedefType *>(
     result.Nodes.getNodeAs<TypedefType>("typedef")); 
    if(f_decl && tt) { 
    QualType ut = tt->getDecl()->getUnderlyingType(); 
    TypedefNameDecl * tnd = tt->getDecl(); 

    std::string struct_name = f_decl->getParent()->getNameAsString(); 
    std::string fld_name = f_decl->getNameAsString(); 
    std::string ut_name = ut.getAsString(); 
    std::string tnd_name = tnd->getNameAsString(); 

    std::cout << "Struct '" << struct_name << "' declares field '" 
       << fld_name << " with typedef name = '" << tnd_name << "'" 
       << ", underlying type = '" << ut_name << "'" << std::endl; 
    } 
    else { 
    // error handling 
    } 
    return; 
} // run 

연타 도구에 넣어 내장되어

Struct 'Foo' declares field 'a' with typedef name = 'M_Int', underlying type = 'int' 
Struct 'Foo' declares field 'p_f' with typedef name = 'P_Float', underlying type = 'float *' 

I을 생산 : 여기에 그 run() 방법 필드 선언의 기본 형식을 가져옵니다 콜백입니다 Code Analysis and Refactoring Examples with Clang Tools project (앱/TypedefFinder.cc 참조)에 전체 작동 예제 앱을 게시하십시오.