解析数据结构clang/LLVM
我想知道从C源文件解析和获取数据结构的最佳解决方案是什么。假设我有:解析数据结构clang/LLVM,clang,llvm,llvm-clang,llvm-ir,Clang,Llvm,Llvm Clang,Llvm Ir,我想知道从C源文件解析和获取数据结构的最佳解决方案是什么。假设我有: typedef int M_Int; typedef float* P_Float; typedef struct Foo { M_Int a; P_Float p_f; } Foo; 为了获得structFoo的变量a和p\f的原语,展开数据结构的最佳方式是什么 对于非常简单的示例,解析AST可能是最好的方法,但是当代码变得更复杂时,也许最好以更低级的方式使用IR代码?您可以使用llvm debug info获取
typedef int M_Int;
typedef float* P_Float;
typedef struct Foo {
M_Int a;
P_Float p_f;
} Foo;
为了获得structFoo
的变量a
和p\f
的原语,展开数据结构的最佳方式是什么
对于非常简单的示例,解析AST可能是最好的方法,但是当代码变得更复杂时,也许最好以更低级的方式使用IR代码?您可以使用llvm debug info获取所需的信息。如果使用
-g
选项编译C代码,它将生成包含所有信息的调试信息。理解llvm debuginfo非常棘手,因为没有太多关于它们的结构和如何访问它们的文档。以下是一些链接:
(一)
2) 下面是我正在处理的一个使用调试信息的项目的链接。这可能不会太有用,因为没有太多文档,但是查看debuginfo类的用法可能会很有用。我们试图为C函数的所有指针参数(包括结构参数的字段名)获取字段名。与debuginfo访问相关的所有代码都在这个文件中:您可以使用llvm debug info获取所需的信息。如果使用
-g
选项编译C代码,它将生成包含所有信息的调试信息。理解llvm debuginfo非常棘手,因为没有太多关于它们的结构和如何访问它们的文档。以下是一些链接:
(一)
2) 下面是我正在处理的一个使用调试信息的项目的链接。这可能不会太有用,因为没有太多文档,但是查看debuginfo类的用法可能会很有用。我们试图为C函数的所有指针参数(包括结构参数的字段名)获取字段名。与debuginfo访问相关的所有代码都在这个文件中:要查找底层类型,AST是一个很好的工作级别。Clang可以使用AST匹配器和回调(与libtooling结合使用)来自动化和扩展此过程。例如,AST匹配器组合
fieldDecl( hasType( tyoedefType().bind("typedef") ) ).bind("field")
将匹配C结构中使用typedef而不是内置类型声明的字段。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
产生
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 *'
我在a中提供了一个完整的工作示例应用程序(请参阅apps/typedefinder.cc)。要查找底层类型,AST是一个很好的工作级别。Clang可以使用AST匹配器和回调(与libtooling结合使用)来自动化和扩展此过程。例如,AST匹配器组合
fieldDecl( hasType( tyoedefType().bind("typedef") ) ).bind("field")
将匹配C结构中使用typedef而不是内置类型声明的字段。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
产生
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 *'
我将一个完整的工作示例应用程序放在一个文件夹中(请参阅apps/typedefinder.cc)