C++ 如何调试LLVM3.2插件断言错误

C++ 如何调试LLVM3.2插件断言错误,c++,llvm,clang,C++,Llvm,Clang,我正在将为LLVM 2.9编写的LLVM插件(LLFI)移植到最新版本的LLVM/Clang 使用启用断言的LLVM3.2版本测试插件时,我遇到以下错误: opt: /home/kzvr/ubc/llfi/llvm3/llvmsrc/lib/IR/Instructions.cpp:281: void llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, const llvm::Twine&):

我正在将为LLVM 2.9编写的LLVM插件(LLFI)移植到最新版本的LLVM/Clang

使用启用断言的LLVM3.2版本测试插件时,我遇到以下错误:

opt: /home/kzvr/ubc/llfi/llvm3/llvmsrc/lib/IR/Instructions.cpp:281: 
 void llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, 
 const llvm::Twine&): Assertion `(i >= FTy->getNumParams() || 
 FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad
 signature!"' failed.
0  opt             0x00000000017931a6 llvm::sys::PrintStackTrace(_IO_FILE*) + 38
1  opt             0x0000000001793423
2  opt             0x0000000001792e7b
3  libpthread.so.0 0x00007f0c0279fff0
4  libc.so.6       0x00007f0c018a91b5 gsignal + 53
5  libc.so.6       0x00007f0c018abfc0 abort + 384
6  libc.so.6       0x00007f0c018a2301 __assert_fail + 241
7  opt             0x00000000016e78c4 llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine const&) + 402
8  LLFI.so         0x00007f0c0165adcb
9  LLFI.so         0x00007f0c0165aa83
10 LLFI.so         0x00007f0c016581c5
11 opt             0x000000000171c02c llvm::FPPassManager::doFinalization(llvm::Module&) + 88
12 opt             0x000000000171c449 llvm::MPPassManager::runOnModule(llvm::Module&) + 1013
13 opt             0x000000000171c8a6 llvm::PassManagerImpl::run(llvm::Module&) + 254
14 opt             0x000000000171cc01 llvm::PassManager::run(llvm::Module&) + 39
15 opt             0x000000000087a089 main + 5591
16 libc.so.6       0x00007f0c01895c8d __libc_start_main + 253
17 opt             0x000000000086bf59
opt:/home/kzvr/ubc/llfi/llvm3/llvmsrc/lib/IR/Instructions.cpp:281:
void llvm::CallInst::init(llvm::Value*,llvm::ArrayRef,
const llvm::Twine&):断言`(i>=FTy->getNumParams()||
FTy->getParamType(i)==Args[i]->getType())&&“使用错误的
签名!“失败。
0 opt 0x00000000017931a6 llvm::sys::PrintStackTrace(_IO_文件*)+38
1选择0x0000000001793423
2选择0x0000000001792e7b
3 libpthread.so.0 0x00007f0c0279fff0
4 libc.so.6 0x00007f0c018a91b5 gsignal+53
5 libc.so.6 0x00007f0c018abfc0中止+384
6 libc.so.6 0x00007f0c018a2301断言失败+241
7 opt 0x00000000016e78c4 llvm::CallInst::init(llvm::Value*,llvm::ArrayRef,llvm::Twine const&)+402
8 LLFI.so 0x00007f0c0165adcb
9 LLFI.so 0x00007f0c0165aa83
10 LLFI.so 0x00007f0c016581c5
11 opt 0x000000000171c02c llvm::FPPassManager::doFinalization(llvm::Module&)+88
12 opt 0x000000000171c449 llvm::MPPassManager::runOnModule(llvm::Module&)+1013
13 opt 0x000000000171c8a6 llvm::PassManagerImpl::run(llvm::Module&)+254
14 opt 0x000000000171cc01 llvm::PassManager::run(llvm::Module&)+39
15选项0x000000000087a089主+5591
16 libc.so.6 0x00007f0c01895c8d\u libc\u start\u main+253
17选择0x000000000086bf59
在插件代码中,我有许多对llvm::CallInst::Create的调用,基于上述内容,我认为至少有一个调用执行不正确。它们几乎都是这样的:

ArrayRef<Value*> arrayArgs(args);
Instruction* callInst = CallInst::Create( injectFunc, arrayArgs, fiName, insertInst);
ArrayRef-arrayArgs(args);
指令*callInst=callInst::Create(injectFunc、arrayArgs、fiName、insertInst);
其中args是std::vector,injectFunc是llvm::Constant*,fiName是std::string,insertInst是llvm::指令*

问题是,作为一个LLVM新手,我不知道如何从这一点上缩小我的错误搜索范围。所以我有几个问题:

  • 如何找到导致CallInst::init断言失败的调用CallInst::Create
  • 说明CallInst类正确用法的文档在哪里?谷歌搜索会自动生成源代码文档,我已经仔细研究过了,但毫无用处
  • 该插件的2.9版和3.2版(就CallInst而言)之间的唯一区别是,将传递std::vector迭代器替换为传递从std::vector构造的ArrayRef到CallInst::create。我是否从向量构造ArrayRef不正确

  • 提前谢谢你的帮助,我希望这个问题不要太模糊

    关于如何调试LLVM断言错误的最佳技巧(标题中的问题)是阅读断言的代码:)

    消息“调用具有错误签名的函数!”-有点含糊不清,但是查看实际的断言条件(失败),您可以看到问题是什么:

    i >= FTy->getNumParams() ||  FTy->getParamType(i) == Args[i]->getType()
    
    因此,您要么提供了太多的参数,要么其中一个参数的类型与函数期望的类型不同。您还可以查看断言位置Instructions.cpp第281行,以查看上下文的周围代码

    为了解决这个问题,我首先要看看函数类型到底是什么(一种简单的方法就是在函数或函数类型上调用
    ->dump()
    ,它会将其打印到stdout)。然后,我将这些类型与我发送给CallInst的类型进行比较(
    ->dump()
    也将在那里工作)。另外,根据预期的参数数量验证参数数量

    关于你剩下的问题:

  • 为什么不使用标准编程实践来定位错误行?
    • e、 注释掉一些行,或者在行之间添加打印,或者只是启动一个调试器,看看哪一行失败
  • 查看源代码(包括实现和注释)通常是我找到如何使用这些函数的首选方法。在任何情况下,您的使用似乎都很好
  • 您没有不正确地从向量构造ArrayRef,只是冗余:存在从std::Vector到ArrayRef的隐式转换,因此您可以将
    args
    向量作为第二个参数传递。但是,您的用法是正确的,这不是断言失败的原因

  • 关于如何调试LLVM断言错误(标题中的问题)的最佳提示是阅读断言代码:)

    消息“调用具有错误签名的函数!”-有点含糊不清,但是查看实际的断言条件(失败),您可以看到问题是什么:

    i >= FTy->getNumParams() ||  FTy->getParamType(i) == Args[i]->getType()
    
    因此,您要么提供了太多的参数,要么其中一个参数的类型与函数期望的类型不同。您还可以查看断言位置Instructions.cpp第281行,以查看上下文的周围代码

    为了解决这个问题,我首先要看看函数类型到底是什么(一种简单的方法就是在函数或函数类型上调用
    ->dump()
    ,它会将其打印到stdout)。然后,我将这些类型与我发送给CallInst的类型进行比较(
    ->dump()
    也将在那里工作)。另外,根据预期的参数数量验证参数数量

    关于你剩下的问题:

  • 为什么不使用标准编程实践来定位错误行?
    • e、 注释掉一些行,或者在行之间添加打印,或者只是启动一个调试器,看看哪一行失败
  • 查看源代码(包括实现和注释)通常是我找到如何使用这些函数的首选方法。无论如何,你的