Crash due to using a new Transformation Pass

Hello,

I am new to llvm, I have written an llvm pass to insert a call to a specific function after each call Instruction.
This is the crash backtrace I got and I don’t understand the problem. (the code of the pass is included here if that might help)

Thank you in advance.


Stack dump:
0. Program arguments: opt-15 -load-pass-plugin lib/libInstrumentCall.so --passes=instr-call instrumentcall.ll
#0 0x00007fcdb0f35451 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/llvm-15/bin/../lib/libLLVM-15.so.1+0xf04451)
[#1](https://github.com/llvm/llvm-project/pull/1) 0x00007fcdb0f3318e llvm::sys::RunSignalHandlers() (/usr/lib/llvm-15/bin/../lib/libLLVM-15.so.1+0xf0218e)
[#2](https://github.com/llvm/llvm-project/pull/2) 0x00007fcdb0f35976 (/usr/lib/llvm-15/bin/../lib/libLLVM-15.so.1+0xf04976)
[#3](https://github.com/llvm/llvm-project/pull/3) 0x00007fcdafb0a520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
[#4](https://github.com/llvm/llvm-project/pull/4) 0x00007fcdb10c8340 llvm::Value::getName() const (/usr/lib/llvm-15/bin/../lib/libLLVM-15.so.1+0x1097340)
[#5](https://github.com/llvm/llvm-project/pull/5) 0x00007fcdad9ccb6c InstrumentCall::runOnModule(llvm::Module&) /home/ss/llvm-tutor/lib/InstrumentCall.cpp:74:82
[#6](https://github.com/llvm/llvm-project/pull/6) 0x00007fcdad9cce0e InstrumentCall::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) /home/ss/llvm-tutor/lib/InstrumentCall.cpp:97:30
[#7](https://github.com/llvm/llvm-project/pull/7) 0x00007fcdad9d4723 llvm::detail::PassModel<llvm::Module, InstrumentCall, llvm::PreservedAnalyses, llvm::AnalysisManagerllvm::Module>::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) /usr/include/llvm-15/llvm/IR/PassManagerInternal.h:89:3
[#8](https://github.com/llvm/llvm-project/pull/8) 0x00007fcdb10a61b9 llvm::PassManager<llvm::Module, llvm::AnalysisManagerllvm::Module>::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (/usr/lib/llvm-15/bin/../lib/libLLVM-15.so.1+0x10751b9)
[#9](https://github.com/llvm/llvm-project/pull/9) 0x0000562c08da8f37 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRefllvm::StringRef, llvm::ArrayRefllvm::PassPlugin, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool) (/usr/lib/llvm-15/bin/opt+0x22f37)
[#10](https://github.com/llvm/llvm-project/pull/10) 0x0000562c08dbac04 main (/usr/lib/llvm-15/bin/opt+0x34c04)
[#11](https://github.com/llvm/llvm-project/pull/11) 0x00007fcdafaf1d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
[#12](https://github.com/llvm/llvm-project/pull/12) 0x00007fcdafaf1e40 call_init ./csu/../csu/libc-start.c:128:20
[#13](https://github.com/llvm/llvm-project/pull/13) 0x00007fcdafaf1e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
[#14](https://github.com/llvm/llvm-project/pull/14) 0x0000562c08da1905 _start (/usr/lib/llvm-15/bin/opt+0x1b905)
Segmentation fault (core dumped)

This is the code for my llvm pass :slight_smile:

#include "InstrumentCall.h"
#include "instrumentcall.c"


#include "llvm/IR/IRBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"

using namespace llvm;

#define DEBUG_TYPE "instr-call"

//-----------------------------------------------------------------------------
// InstrumentCall implementation
//-----------------------------------------------------------------------------
bool InstrumentCall::runOnModule(Module &M) {
  bool Instrumented = false;
  auto &CTX = M.getContext();
  // STEP 1: Inject the declaration of the function to call
  // -------------------------------------------------------
  
  llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(CTX),       // return type
					false       // is varg function
				 );
  // STEP 2: Chose where to inject the instrumentation
  // -------------------------------------------------
  auto InstFunc = M.getOrInsertFunction("instrumentcall", FT);
  //auto InstFunc = Function::Create(FT, Function::ExternalLinkage, "instrumentcall", M);
    
  for (auto &F : M) {
    for(auto &B:F){ 
      for(auto &I:B){
        
        if(I.isTerminator()){
          //errs() << "Instruction: "<< I << "\n";
          if(I.getOpcodeName()=="ret")
            errs() << "Opcode: "<< I.getOpcodeName() << "\n";
        }
        if(dyn_cast<CallInst>(&I)){
          //errs() << "Instruction: "<< I << "\n";
          //errs() << "Opcode: "<< I.getOpcodeName() << "\n";
          StringRef called = dyn_cast<CallInst>(&I)->getCalledFunction()->getName();
          errs() << "Called Function: "<< called << "\n";
          // error in the IRBuilder constructor
          if(!called.contains("instrumentcall"))
          {
            IRBuilder<> builder(&B);
            builder.SetInsertPoint(I.getNextNode());
            builder.CreateCall(InstFunc);
            
            //Instruction *newInst = CallInst::Create(InstFunc, "");
            //B.getInstList().insert(((Instruction*)&I)->getIterator(), newInst);    
            Instrumented = true;
          }
        
        }
      }
    }
  }
  return Instrumented;
}

PreservedAnalyses InstrumentCall::run(llvm::Module &M,
                                       llvm::ModuleAnalysisManager &) {
  bool Changed =  runOnModule(M);

  return (Changed ? llvm::PreservedAnalyses::none()
                  : llvm::PreservedAnalyses::all());
}



//-----------------------------------------------------------------------------
// New PM Registration
//-----------------------------------------------------------------------------
llvm::PassPluginLibraryInfo getInstrumentCallPluginInfo() {
  return {LLVM_PLUGIN_API_VERSION, "instr-call", LLVM_VERSION_STRING,
          [](PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](StringRef Name, ModulePassManager &MPM,
                   ArrayRef<PassBuilder::PipelineElement>) {
                  if (Name == "instr-call") {
                    MPM.addPass(InstrumentCall());
                    return true;
                  }
                  return false;
                });
          }};
}

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
  return getInstrumentCallPluginInfo();
}

You’re modifying a block while using a range loop over it, which typically works poorly. You may want to try using make_early_inc_range

Thank you for your response. I added that but I still have the same issue.
Could it be because the function I am trying to call contains an in line assembly ?

I also have another issue where after I run the pass I can’t find the modifications on the input file !! Does anyone have an idea why?

Thank you in advance.

Yes. For inline asm the call target isn’t a function and getCalledFunction will return null

1 Like

Oh I didn’t know that thank you !! if it’s not a Function what would you recommend I use instead of getCalledFunction ?

Depends what you’re doing with it? Everything is a wrapper around getCalledOperand with type checks

I see !! Well, actually for now I am just attempting to insert function calls. The function I am trying to call is written in assembly.