[llvm-dev] Get segfault with ModulePass

George Burgess IV via llvm-dev llvm-dev at lists.llvm.org
Sat Jun 10 17:16:36 PDT 2017


Hi,

Have you tried building LLVM with assertions enabled? Assertions are
often a good way to catch API misuses, but they aren't on by default
for release builds.

FWIW, StringRefs aren't guaranteed to be nul-terminated. They support
a similar comparison API as std::strings, though, so things like
`user->getOpcodeName() == "<Invalid operator>"` should just work™.

George

On Fri, Jun 9, 2017 at 4:54 PM, Gerion Entrup via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> Hi,
>
> don't know if this is the right list. Please post a better place,
> otherwise.
>
> I'm currently writing a LLVM ModulePass and ran into strange segfaults or
> endless loops within LLVM. My main question is, if this is a programming error
> or API misuse from me or a LLVM bug?
>
> Here is some minimal code, that triggers the bug:
> ----------------
>         class DebugPass : public ModulePass {
>         public:
>                 static char ID;
>                 DebugPass() : ModulePass(ID) {}
>
>                 virtual bool runOnModule(Module &M) override {
>                         DILocation* loc;
>                         for (auto &F : M) {
>                                 for (auto &B : F) {
>                                         for (auto &I : B) {
>                                                 errs() << "op_code: " << I.getOpcodeName() << '\n';
>                                                 loc = I.getDebugLoc();
>                                                 if (loc != nullptr) {
>                                                         errs() << "file: " << loc->getFilename() << '\n';
>                                                 }
>                                                 for (const auto& use : I.uses()) {
>                                                         if (const CallInst* c = dyn_cast<CallInst>(use.getUser())) {
>                                                                 const Function* f = c->getCalledFunction();
>                                                                 if (f != nullptr) {
>                                                                         for (unsigned i = 0; i < c->getNumArgOperands(); ++i) {
>                                                                                 const Use& u = c->getArgOperandUse(i);
>                                                                                 if (u.operator->() == &I) {
>                                                                                         Function::const_arg_iterator ai = f->arg_begin();
>                                                                                         std::advance(ai, i);
>                                                                                         for (const auto& use : ai->uses()) {
>                                                                                                 errs() << "next one\n";
>                                                                                                 if (const Instruction* user = dyn_cast<Instruction>(use.getUser())) {
>                                                                                                         errs() << "op_code2: " << user->getOpcodeName() << '\n';
>                                                                                                         //if (std::strcmp("<Invalid operator> ", user->getOpcodeName()) == 0) {
>                                                                                                         //      continue;
>                                                                                                         //}
>                                                                                                         loc = user->getDebugLoc();
>                                                                                                         if (loc != nullptr) {
>                                                                                                                 errs() << "file: " << loc->getFilename() << '\n';
>                                                                                                         }
>                                                                                                 }
>                                                                                                 if (const Instruction* user = dyn_cast<Instruction>(use.operator->())) {
>                                                                                                         errs() << "op_code3: " << user->getOpcodeName() << '\n';
>                                                                                                         loc = user->getDebugLoc();
>                                                                                                         if (loc != nullptr) {
>                                                                                                                 errs() << "file: " << loc->getFilename() << '\n';
>                                                                                                         }
>                                                                                                 }
>                                                                                         }
>                                                                                         errs() << "loop end\n";
>                                                                                         break;
>                                                                                 }
>                                                                         }
>                                                                 }
>                                                         }
>                                                 }
>                                         }
>                                 }
>                         }
>                         return false;
>                 }
>         };
> ------------------
>
> The segfault backtrace is this one:
> ----------------
> ...
> op_code: phi
> next one
> op_code2: <Invalid operator>
> #0 0x00007fa7135446b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/lib64/llvm/4/bin/../lib64/libLLVMSupport.so.4+0xe56b8)
> #1 0x00007fa71354258e llvm::sys::RunSignalHandlers() (/usr/lib64/llvm/4/bin/../lib64/libLLVMSupport.so.4+0xe358e)
> #2 0x00007fa71354280c (/usr/lib64/llvm/4/bin/../lib64/libLLVMSupport.so.4+0xe380c)
> #3 0x00007fa711210170 (/lib64/libc.so.6+0x33170)
> #4 0x00007fa709a06bf0 llvm::MDOperand::get() const /usr/lib/llvm/4/include/llvm/IR/Metadata.h:690:0
> #5 0x00007fa709a06c0e llvm::MDOperand::operator llvm::Metadata*() const /usr/lib/llvm/4/include/llvm/IR/Metadata.h:691:0
> #6 0x00007fa709a074d7 llvm::DILocation::getRawScope() const /usr/lib/llvm/4/include/llvm/IR/DebugInfoMetadata.h:1336:0
> #7 0x00007fa709a07486 llvm::DILocation::getScope() const /usr/lib/llvm/4/include/llvm/IR/DebugInfoMetadata.h:1274:0
> #8 0x00007fa709a074a8 llvm::DILocation::getFilename() const /usr/lib/llvm/4/include/llvm/IR/DebugInfoMetadata.h:1280:0
> #9 0x00007fa709a062e2 (anonymous namespace)::DebugPass::runOnModule(llvm::Module&) /home/gerion/sourcecode/debug-pass/debugpass/DebugPass.cpp:50:0
> ...
> ----------------
>
> If I filter out the invalid operators I get an endless loop (the outcommented
> lines).
>
> To get this running, I have used the gremlin-pass-skeleton I found on
> Github [1] together with the modification for modules here [2].
>
> I load the pass with:
> clang ... -g -Xclang load -Xclang /path/to/my/pass sourcefile.c
>
> I've tested the pass with the FFmpeg sources (and a modified configure).
> The error happens in af_aformat.c [3].
>
> The meaning of the code is to get first an instruction, and if this
> instruction is used as an argument in some function extract the instructions,
> that uses the argument inside of the function body.
>
> Can somebody help me, to find another way to achive the (argument-)connection
> between the instructions? And is the segfault a LLVM bug?
>
>
> Regards,
> Gerion
>
> [1] https://github.com/sampsyo/llvm-pass-skeleton
> [2] https://github.com/sampsyo/llvm-pass-skeleton/issues/7
> [3] https://github.com/FFmpeg/FFmpeg/blob/master/libavfilter/af_aformat.c
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list