[llvm-dev] Get segfault with ModulePass

Gerion Entrup via llvm-dev llvm-dev at lists.llvm.org
Fri Jun 9 16:54:04 PDT 2017


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


More information about the llvm-dev mailing list