Tôi đang sử dụng lệnh clang/llvm để lập trình và liên kết các bit của nguồn C. Tôi thấy rằng các liên kết llvm dường như không báo cáo thực tế là các phần bên ngoài chưa được giải quyết tồn tại trong một mô-đun như là một lỗi.Sử dụng llvm :: Trình liên kết để tìm kiếm bên ngoài chưa được giải quyết một cách có lập trình
Tôi đã đoạn mã sau (tha thứ cho chiều dài, nhưng điều này thực sự là tối thiểu bắt buộc):
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;
}
Không có lỗi xảy ra bất cứ nơi nào cho đến khi chúng ta gọi là runFunction gần cuối, mang đến cho các lỗi "ERROR LLVM : Chương trình được sử dụng chức năng bên ngoài 'UnresolvedFunction' mà không thể được giải quyết! " trước khi hủy bỏ.
Tôi mong đợi LinkInModule hoặc getModule không thành công với một số lỗi, nhưng đây không phải là trường hợp. Câu hỏi của tôi là: có cách nào để xác định rằng một mô-đun có các phần bên ngoài chưa được giải quyết, để không bị sập và ghi khi cố thực thi mã? Tôi đã say mê thông qua các nguồn llvm trong một thời gian, và cho đến nay không thể tìm thấy những gì tôi đang tìm kiếm.
Tôi đang sử dụng llvm/clang 2.9 trên Mac OS X (x86_64), nếu điều đó quan trọng.
Chỉnh sửa: Tôi đã tìm thấy hàm riêng tư được gọi là GetAllUndefinedSymbols
trong các nguồn llvm (llvm-2.9/lib/Linker/LinkArchives.cpp), dường như làm những gì tôi muốn. Tôi đoán tôi đã hy vọng có một API thực tế cho điều này, một cái gì đó tôi bị mất?
Tôi đã làm nhiều hơn hoặc ít hơn như @servn được đề xuất, đây là biến thể trên mã trong GetAllUndefinedSybols. – zpasternack