2011-06-22 27 views
5

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?

+0

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

Trả lời

2

IIRC, chưa ai từng yêu cầu API như vậy, vì vậy không tồn tại. Tôi không hoàn toàn chắc chắn những gì bạn sẽ làm với API như vậy, dù sao ... bất kỳ chương trình không tầm thường nào sẽ tham chiếu các biểu tượng không được định nghĩa trong bất kỳ tệp .bc nào, như malloc.

Nếu bạn thực sự muốn kiểm tra, một cái gì đó như sau nên làm việc:

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); 
+0

Những gì tôi đang cố gắng làm là chạy một số mã trong JIT, mà không cần phải hủy bỏ nó nếu có các phần bên ngoài chưa được giải quyết. Mã của bạn không hoạt động (mặc dù, như @Anton chỉ ra, một số thứ được giải quyết một cách kỳ diệu bởi JIT, dẫn đến kết quả dương tính giả). – zpasternack

2

LLVM mối liên kết được sử dụng để liên kết các module. Cho rằng nó hoàn toàn hợp lệ cho Module để có các khai báo bên ngoài, không có lỗi nào. Vì vậy, tùy thuộc vào bạn để quyết định xem bạn có cần phải báo lỗi trong tình huống như vậy hay không (ví dụ: một số hàm bên ngoài ví dụ: chức năng thư viện C trong một số situtation có thể được JIT giải quyết tự động)

Vì vậy, mã của servn là những gì bạn phải làm ở đây.

+0

Đủ công bằng, cảm ơn! – zpasternack

+0

Anton, bạn có biết ở đâu/như thế nào JIT tìm kiếm danh sách phụ thuộc tự động giải quyết của nó? là có một nơi tôi có thể thêm một phụ thuộc chưa được giải quyết có thể được tìm kiếm? – lurscher

+0

Chỉ cần thông qua dlopen'ing nhị phân chính. Nhìn vào lớp DynamicLibrary để biết thêm thông tin –

Các vấn đề liên quan