2017-02-10 35 views
1

Cソースファイルからデータ構造を解析して取得するための最良のソリューションは何か不思議でした。私が持っていると仮定:データ構造を解析するCLANG/LLVM

typedef int M_Int; 
typedef float* P_Float; 

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

構造体Fooの両方の変数ap_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") 

代わりに内蔵型のtypedefを用いて宣言されているC構造体のフィールドと一致します。 bind()コールは、コールバックがASTノードにアクセスできるようにします。ここではそのrun()方法フィールド宣言の基になる型を取得しますコールバックです:これはクランツールに入れて構築されると

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 

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

を実行すると、

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を生成しますCode Analysis and Refactoring Examples with Clang Tools project(apps/TypedefFinder.ccを参照)に完全な実例のアプリケーションを載せてください。

関連する問題