Program compiled with Clang -pg and -O crashes with SEGFAULT

Hi,

I am trying to compile a simple program with Clang 3.3 on Linux and used -pg and -O2 option. The program would crash with segfault. Interestingly if I compile it with -pg option only it works. Do you have any idea why it crashes? And any workaround?

$ cat myprog.c
int main() {
    return 0;
}

$ clang -v -pg -O2 myprog.c
clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
"/usr/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -disable-free -disable-llvm-verifier -main-file-name myprog.c -mrelocation-model static -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.22 -momit-leaf-frame-pointer -v -resource-dir /usr/bin/../lib/clang/3.3 -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/clang/3.3/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir /home/vagrant/work/c++ -ferror-limit 19 -fmessage-length 204 -pg -mstackrealign -fobjc-runtime=gcc -fobjc-default-synthesize-properties -fdiagnostics-show-option -fcolor-diagnostics -backend-option -vectorize-loops -o /tmp/myprog-oJBSKs.o -x c myprog.c
clang -cc1 version 3.3 based upon LLVM 3.3 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/bin/../lib/clang/3.3/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
"/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/gcrt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. -L/lib -L/usr/lib /tmp/myprog-oJBSKs.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o

Running this program it would give me stack trace:
Program received signal SIGSEGV, Segmentation fault.
mcount () at ../sysdeps/x86_64/_mcount.S:46
46 ../sysdeps/x86_64/_mcount.S: No such file or directory.
(gdb) bt
#0 mcount () at ../sysdeps/x86_64/_mcount.S:46
#1 0x00007ffff7dd6568 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x0000000000000000 in ?? ()

If I compare the assembly code with and without optimization, the only difference seems to be that the optimized version removed some register preservation ops before calling mcount().

-pg version, which works:

Hi Qiao,

Hi,

I am trying to compile a simple program with Clang 3.3 on Linux and used -pg and -O2 option. The program would crash with segfault. Interestingly if I compile it with -pg option only it works. Do you have any idea why it crashes? And any workaround?

$ cat myprog.c
int main() {
     return 0;
}

$ clang -v -pg -O2 myprog.c

if you compile with -fno-omit-frame-pointer, the crash goes away, right?

clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
  "/usr/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -disable-free -disable-llvm-verifier -main-file-name myprog.c -mrelocation-model static -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.22 -momit-leaf-frame-pointer -v -resource-dir /usr/bin/../lib/clang/3.3 -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/clang/3.3/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir /home/vagrant/work/c++ -ferror-limit 19 -fmessage-length 204 -pg -mstackrealign -fobjc-runtime=gcc -fobjc-default-synthesize-properties -fdiagnostics-show-option -fcolor-diagnostics -backend-option -vectorize-loops -o /tmp/myprog-oJBSKs.o -x c myprog.c
clang -cc1 version 3.3 based upon LLVM 3.3 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
  /usr/local/include
  /usr/bin/../lib/clang/3.3/include
  /usr/include/x86_64-linux-gnu
  /usr/include
End of search list.
  "/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/gcrt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. -L/lib -L/usr/lib /tmp/myprog-oJBSKs.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o

Running this program it would give me stack trace:
Program received signal SIGSEGV, Segmentation fault.
mcount () at ../sysdeps/x86_64/_mcount.S:46
46 ../sysdeps/x86_64/_mcount.S: No such file or directory.
(gdb) bt
#0 mcount () at ../sysdeps/x86_64/_mcount.S:46
#1 0x00007ffff7dd6568 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x0000000000000000 in ?? ()

Here you see that it crashes inside mcount. I think mcount walks up the call
stack in order to generate a call graph. Since it crashes when there is no
frame pointer it seems like this is an mcount bug, and it should really be
updated to one of the more modern methods that doesn't require a frame pointer.

If I compare the assembly code with and without optimization, the only difference seems to be that the optimized version removed some register preservation ops before calling mcount().

-pg version, which works:
----------------------------------------
main: # @main
  .cfi_startproc
# BB#0:
  pushq %rbp

^ frame pointer

.Ltmp2:
  .cfi_def_cfa_offset 16
.Ltmp3:
  .cfi_offset %rbp, -16
  movq %rsp, %rbp
.Ltmp4:
  .cfi_def_cfa_register %rbp
  subq $16, %rsp
  callq mcount
  movl $0, %eax
  movl $0, -4(%rbp)
  addq $16, %rsp
  popq %rbp
  ret

-pg -O2 version, which crashes:
--------------------------------------------
main: # @main
  .cfi_startproc
# BB#0:
  pushq %rax
.Ltmp1:
  .cfi_def_cfa_offset 16

^ no frame pointer

Ciao, Duncan.

Duncan,

Yes, that is exactly the issue. It no longer crashes with -fno-omit-frame-pointer. Thanks a lot.
--Qiao