Search code examples
clangllvmosx-elcapitan

Usage of FunctionPass over ModulePass when creating LLVM passes


I've seen quite a numerous amount of examples that go over creating functions passes (e.g. Brandon Holt and Adrian Sampson), but I am curious as to the difficulty in creating a module pass to do these very similar problems. I've tried to implement a module pass to display the global variable names using this example and llvm source code to understand how you have to iterate through members.

I am using a source compiled version of LLVM, and using the example from the above links to add the pass, and then running:

$ clang -Xclang -load -Xclang build/Skeleton/libSkeletonPass.so something.c

Which then returns this gibberish. However, if I implement a functionPass and just use Auto to determine the type to be initialized it's very straight forward and works. Am I just going about printing the global variables the wrong way?

This is a pastebin of the error output from the terminal. link

Skeleton.cpp

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;

namespace {
  // Helper method for converting the name of a LLVM type to a string
  static std::string LLVMTypeAsString(const Type *T) {
    std::string TypeName;
    raw_string_ostream N(TypeName);
    T->print(N);
    return N.str();
  }

  struct SkeletonPass : public ModulePass {
    static char ID;
    SkeletonPass() : ModulePass(ID) {}

    virtual bool runOnModule(Module &M) {

      for (Module::const_global_iterator GI = M.global_begin(), 
                                 GE = M.global_end(); GI != GE; ++GI) {
          errs() << "Found global named: " << GI->getName() 
                  << "\tType: " << LLVMTypeAsString(GI->getType()) << "!\n";
      }

      return false;
    }
  };
}

char SkeletonPass::ID = 0;

// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder &,
                         legacy::PassManagerBase &PM) {
  PM.add(new SkeletonPass());
}
static RegisterStandardPasses
  RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
                 registerSkeletonPass);

something.c

int value0 = 5;

int main(int argc, char const *argv[])
{
    int value = 4;
    value += 1;
    return 0;
}

Solution

  • I was able to figure this out after some extensive github searching. Here is the answer from which I was following a tutorial to help others who may be curious how to implement a Module Pass.