zpa*_*ack 5 c c++ linker llvm clang
我正在使用clang/llvm以编程方式编译和链接C源代码.我发现llvm链接器似乎没有报告模块中存在未解析的外部因为错误的事实.
我有以下代码(原谅长度,但这确实是最低要求):
int CompileAndLink()
{
llvm::InitializeNativeTarget();
std::string code = "int UnresolvedFunction();\n"
"int main() { return UnresolvedFunction(); }";
clang::DiagnosticOptions diagnosticOptions;
clang::TextDiagnosticPrinter tdp( llvm::outs(), diagnosticOptions );
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs( new clang::DiagnosticIDs );
clang::Diagnostic diag( diagIDs, &tdp, false );
clang::FileSystemOptions fsOptions;
clang::FileManager fm( fsOptions );
clang::SourceManager sm( diag, fm );
clang::HeaderSearch hs( fm );
clang::TargetOptions targetOptions;
targetOptions.Triple = llvm::sys::getHostTriple();
clang::TargetInfo* ti = clang::TargetInfo::CreateTargetInfo( diag, targetOptions );
clang::HeaderSearchOptions headerSearchOptions;
clang::LangOptions langOptions;
clang::ApplyHeaderSearchOptions( hs, headerSearchOptions, langOptions, ti->getTriple() );
clang::PreprocessorOptions ppo;
clang::Preprocessor pp( diag, langOptions, *ti, sm, hs );
clang::FrontendOptions frontendOptions;
clang::InitializePreprocessor( pp, ppo, headerSearchOptions, frontendOptions );
pp.getBuiltinInfo().InitializeBuiltins( pp.getIdentifierTable(), langOptions );
llvm::MemoryBuffer* sourceBuffer = llvm::MemoryBuffer::getMemBufferCopy( code );
sm.createMainFileIDForMemBuffer( sourceBuffer );
clang::Builtin::Context bic( *ti );
clang::ASTContext astc( langOptions, sm, *ti,
pp.getIdentifierTable(),
pp.getSelectorTable(),
bic,
0 );
llvm::LLVMContext lc;
clang::CodeGenOptions codeGenOptions;
llvm::OwningPtr<clang::CodeGenerator> cg;
cg.reset( clang::CreateLLVMCodeGen( diag, "clang_test", codeGenOptions, lc ) );
if( cg == NULL ) {
printf( "could not create CodeGenerator\n" );
return -1;
}
clang::ParseAST( pp, cg.get(), astc );
if( tdp.getNumErrors() ) {
printf( "error parsing AST\n" );
return -2;
}
llvm::Module* new_module = cg->ReleaseModule();
if( !new_module ) {
printf( "error generating code\n" );
return -2;
}
llvm::Linker linker( "clang_test", "clang_test", lc, llvm::Linker::Verbose );
std::string error;
if( linker.LinkInModule( new_module, &error ) || !error.empty() ) {
printf( "link error\n" );
return -3;
}
llvm::Module* composite_module = linker.getModule();
if( composite_module == NULL ) {
printf( "link error\n" );
return -3;
}
llvm::ExecutionEngine *pEngine = llvm::ExecutionEngine::create( composite_module,
false,
&error );
if( !error.empty() || pEngine == NULL ) {
printf( "error creating ExecutionEngine\n" );
return -4;
}
llvm::Function* f = composite_module->getFunction( "main" );
if( f == NULL ) {
printf( "couldn't find main function\n" );
return -5;
}
// This will abort with the message:
// LLVM ERROR: Program used external function 'UnresolvedFunction' which could not be resolved!
std::vector<llvm::GenericValue> params;
llvm::GenericValue result = pEngine->runFunction( f, params );
printf( "function main returned %llu\n", result.IntVal.getZExtValue() );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我们在结尾附近调用runFunction之前,没有任何错误发生,这会产生错误"LLVM错误:程序使用的外部函数'UnresolvedFunction'无法解决!" 在流产之前.
我有点期望LinkInModule或getModule失败并出现一些错误,但事实并非如此.我的问题是:有没有办法确定模块是否有未解析的外部,以免在尝试执行代码时崩溃和烧毁?我已经花了很长一段时间来浏览llvm源码,到目前为止还找不到我想要的东西.
我在Mac OS X(x86_64)上使用llvm/clang 2.9,如果这很重要的话.
编辑:我发现了一个GetAllUndefinedSymbols在llvm源代码中调用的私有函数(llvm-2.9/lib/Linker/LinkArchives.cpp),这似乎是我想做的.我想我希望有一个实际的API,我错过了什么?
IIRC,没有人要求过这样的 API,所以不存在。无论如何,我不完全确定您会使用这样的 API 做什么...任何重要的程序都会引用任何 .bc 文件中未定义的符号,例如malloc.
如果您确实想检查,类似以下内容应该有效:
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (I->isDeclaration())
UndefGlobals.insert(&*I);
for (Module::global_iterator I = M->global_begin(),
E = M->global_end();
I != E; ++I)
if (I->isDeclaration())
UndefGlobals.insert(&*I);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1963 次 |
| 最近记录: |