2017-07-25 42 views
1

我有一個簡單的LLVM通道,用於重命名當前翻譯單元中定義的每個函數(即所有預處理步驟發生後所涉及的源文件 - 請參閱here)。我的通行證如下:如何鏈接兩個LLVM位碼模塊?

#include <vector> 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <sstream> 

#include "llvm/Pass.h" 
#include "llvm/IR/Function.h" 
#include "llvm/Support/raw_ostream.h" 
#include "llvm/ADT/STLExtras.h" 
#include "llvm/ADT/SmallString.h" 
#include "llvm/IR/DerivedTypes.h" 
#include "llvm/IR/Module.h" 
#include "llvm/IR/Type.h" 
#include "llvm/IR/TypeFinder.h" 
#include "llvm/Transforms/IPO.h" 
#include "llvm/IR/Argument.h" 
#include "llvm/IR/GlobalValue.h" 

using namespace llvm; 

namespace { 

    struct FunctionRename : public ModulePass { 
    static char ID; // Pass identification 
    FunctionRename() : ModulePass(ID) {} 

    bool runOnModule(Module &M) override { 
     // Rename all functions 
     for (auto &F : M) { 
     StringRef Name = F.getName(); 
     // Leave library functions alone because their presence or absence 
     // could affect the behaviour of other passes. 
     if (F.isDeclaration()) 
      continue; 
     F.setLinkage(GlobalValue::LinkOnceAnyLinkage); 
     F.setName(Name + "_renamed"); 
     } 
     return true; 
    } 
    }; 
} 

char FunctionRename::ID = 0; 
static RegisterPass<FunctionRename> X("functionrename", "Function Rename Pass"); 
// ===-------------------------------------------------------==// 
// 
// Function Renamer - Renames all functions 
// 

運行後傳過來一個位碼文件,file.bc,我將結果輸出到一個新文件file_renamed.bc,如下

opt -load /path/to/libFunctionRenamePass.so -functionrename <file.bc> file_renamed.bc

然後我試圖鏈接這兩個文件如下

llvm-link file.bc file_renamed.bc -o file_linked.bc

但是,我仍然得到C++源文件(從中生成初始位代碼文件)涉及構造函數和析構函數的符號衝突。我的期望是,線

F.setLinkage(GlobalValue::LinkOnceAnyLinkage)

將防止發生在file.bcfile_renamed.bc定義的任何符號的符號衝突。

我在做什麼錯?

+0

你能提供你收到錯誤的實際文字嗎? – jvstech

回答

0

我的完整的解決方案如下:

#include <vector> 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <sstream> 

#include "llvm/Pass.h" 
#include "llvm/IR/Function.h" 
#include "llvm/Support/raw_ostream.h" 
#include "llvm/ADT/STLExtras.h" 
#include "llvm/ADT/SmallString.h" 
#include "llvm/IR/DerivedTypes.h" 
#include "llvm/IR/Module.h" 
#include "llvm/IR/Type.h" 
#include "llvm/IR/TypeFinder.h" 
#include "llvm/Transforms/IPO.h" 
#include "llvm/IR/Argument.h" 
#include "llvm/IR/GlobalValue.h" 
#include "llvm/IR/Metadata.h" 

using namespace llvm; 

namespace { 

    struct FunctionRename : public ModulePass { 
    static char ID; // Pass identification 
    FunctionRename() : ModulePass(ID) {} 

    bool runOnModule(Module &M) override { 

     for (auto it = M.global_begin(); it != M.global_end(); ++it) 
     { 
     GlobalVariable& gv = *it; 
     if (!gv.isDeclaration()) 
      gv.setLinkage(GlobalValue::LinkerPrivateLinkage); 
     } 

     for (auto it = M.alias_begin(); it != M.alias_end(); ++it) 
     { 
     GlobalAlias& ga = *it; 
     if (!ga.isDeclaration()) 
      ga.setLinkage(GlobalValue::LinkerPrivateLinkage); 
     } 

     // Rename all functions 
     for (auto &F : M) { 
     StringRef Name = F.getName(); 
     // Leave library functions alone because their presence or absence 
     // could affect the behaviour of other passes. 
     if (F.isDeclaration()) 
      continue; 
     F.setLinkage(GlobalValue::WeakAnyLinkage); 
     F.setName(Name + "_renamed"); 
     } 
     return true; 
    } 
    }; 
} 

char FunctionRename::ID = 0; 
static RegisterPass<FunctionRename> X("functionrename", "Function Rename Pass"); 
// ===-------------------------------------------------------==// 
// 
// Function Renamer - Renames all functions 
// 

在循環處理功能,for(auto &F : M) { ... },我更喜歡使用WeakAnyLinkage而不是LinkOnceAnyLinkage,原因如下。

LinkOnceAnyLinkage的全局 - 顧名思義 - 在鏈接發生時與其他相同名稱的符號合併,並且允許丟棄具有該鏈接的未引用的全局變量。

具有WeakAnyLinkage的全局變量與LinkOnceAnyLinkage共享全局變量的語義,但可以不放棄具有WeakAnyLinkage的未引用全局變量。

此外,在處理全局變量和別名的兩個循環中,我使用LinkerPrivateLinkage,因爲我不希望file_renamed.bc中的全局變量可由該模塊外部的任何對象訪問。

此外,處理別名的循環對於避免與完整對象構造函數和析構函數相關的符號衝突(即:根據Itanium C++ ABI的C1和D1析構函數)是必需的(至少在我的環境中)。

1

當我試圖在樣本位碼文件運行代碼,LLVM的鏈接步驟失敗由於全局變量:

ERROR: Linking globals named 'my_global': symbol multiply defined! 

添加第二個循環的RunOnModule例程來處理全局變量後, llvm-link成功,然後代碼最終鏈接。

for (auto git = M.global_begin(), get = M.global_end(); git != get; ++git) 
{ 
    GlobalValue* gv = &*git; 
    gv->setLinkage(GlobalValue::LinkOnceAnyLinkage); 
} 

但是,我對構造函數的C++代碼進行了簡單的測試,不管是否有這種變化。