[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