I can't build a working Valgrind using clang-2.9, whereas I could using clang-2.8. I think this is due to an idiom recognition pass in LLVM spotting a loop that can be turned into a call to memset(). Here's the deal: Valgrind tool executables (the big files "valgrind-amd64-darwin", etc) are statically linked and completely freestanding; we do not link in any of libc nor libgcc. That means we have our own mini-libc. The reasons for this aren't relevant here. So for example we have our own memset (omitting the vectorised loops): void* vgPlain_memset ( void *destV, Int c, SizeT sz ) { Char* d = (Char*)destV; while (sz >= 1) { d[0] = c; d++; sz--; } return destV; } When built by gcc, gcc would sometimes insert calls to memset() for whatever reason. Since we are completely freestanding, these cause the link to fail, so we insert a hook that routes through to the above function: void* memset(void *s, int c, SizeT n) { return vgPlain_memset(s,c,n); } With gcc that all works fine. But clang comes along, recognises the vgPlain_memset loop as a memset idiom, and converts it into a call to memset(). Infinite recursion leading to segfault. Bah! Below is the assembly for vgPlain_memset. Note the absence of a loop, plus the call to memset(). This is happening at -O2 and -O. I have to back off to -O0 to stop it happening. That's obviously undesirable. How can I selectively disable this idiom recognition pass? 000000003802f9b0 <vgPlain_memset>: 3802f9b0: 53 push %rbx 3802f9b1: 48 85 d2 test %rdx,%rdx 3802f9b4: 48 89 fb mov %rdi,%rbx 3802f9b7: 74 0c je 3802f9c5 <vgPlain_memset+0x15> 3802f9b9: 40 0f b6 f6 movzbl %sil,%esi 3802f9bd: 48 89 df mov %rbx,%rdi 3802f9c0: e8 3b 50 00 00 callq 38034a00 <memset> 3802f9c5: 48 89 d8 mov %rbx,%rax 3802f9c8: 5b pop %rbx 3802f9c9: c3 retq
Hi Julian, Building with -fno-builtin or -ffree-standing should disable it. Does this work for you? -Chris
-ffreestanding that is.
(In reply to comment #2) > -ffreestanding that is. Wow, that's quick :) -ffreestanding produces something that works. Thanks! I didn't test -fno-builtin on the assumption that it removes all the __builtin_blah stuff, and we rely on some of that.
Great, happy to help. This should work with GCC also, FWIW.