Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to link two LLVM bitcode modules?

I have a simple LLVM pass that renames every function defined within the current translation unit (i.e: the source file in question, after all preprocessing steps have taken place - see here). My pass is as follows:

#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
//

After running the pass over a bitcode file, file.bc, I output the result to a new file file_renamed.bc, as follows

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

I then attempt to link the two files as follows

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

However, I still get symbol clashes for C++ source files (from which the initial bitcode file is generated) where constructors and destructors are involved. My expectation was that the line

F.setLinkage(GlobalValue::LinkOnceAnyLinkage)

would prevent symbol clashes occurring for any symbols defined in file.bc and file_renamed.bc.

What am I doing wrong?

like image 383
UnchartedWaters Avatar asked May 26 '26 13:05

UnchartedWaters


1 Answers

When I tried running your code on a sample bitcode file, the llvm-link step failed due to the global variables:

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

After adding a second loop to the RunOnModule routine to process the global variables, llvm-link succeeds and then the code ultimately linked.

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

However, my simple test of C++ code with constructors worked both with and without this change.

like image 166
Brian Avatar answered May 28 '26 02:05

Brian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!