https://sourceware.org/bugzilla/show_bug.cgi?id=23482
Bug ID: 23482 Summary: Identical code folding can break C++ exception handling invariants Product: binutils Version: 2.32 (HEAD) Status: UNCONFIRMED Severity: normal Priority: P2 Component: gold Assignee: ccoutant at gmail dot com Reporter: oremanj at gmail dot com CC: ian at airs dot com Target Milestone: --- Recent versions of GCC at reasonable optimization levels will automatically split predicted-rarely-taken portions of a function into a separate "funcname.cold" symbol, which goes in a different executable section so as to improve locality of frequently-used code. (This happens on GCC 8 at -O2 or higher; the specific flag is -freorder-blocks-and-partition.) Suppose that two functions with different stack frame layouts happen to have identical .cold fragments split off, the .cold fragment throws an exception (common due to GCC considering exception throwing unlikely), and identical code folding is enabled with eg --icf=safe. Then the one merged .cold fragment can only be associated with one unwinding state, so at least one of the functions will crash or otherwise misbehave when it throws. I previously reported this to GCC (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86854) and they claim it's gold's bug: "the eh/unwind information from GCC is correct for the landing location but --icf=safe does not take into account the difference in landing locations before merging them". The attached tarball contains three small C++ source files that reproduce the issue when compiled and linked together using GCC 8, as well as the assembly and object files produced by that compilation, plus the resulting working (without --icf=safe) and failing (with --icf=safe) binaries. The issue was observed on an x86_64 Linux system with gold 1.14 from binutils 2.29.1, and is also seen on a gold built from latest sources today. Binaries produced using: $ gold --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt{1,i}.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/x86_64-linux-gnu t{1,2,m}.o -lstdc++ -lgcc_s -lgcc -lc /usr/lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o -o t.nofold $ gold --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt{1,i}.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/x86_64-linux-gnu t{1,2,m}.o -lstdc++ -lgcc_s -lgcc -lc /usr/lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o -o t.fold --icf=safe Demonstration: $ ./t.nofold caught 1 caught 2 $ ./t.fold caught 1 Segmentation fault (core dumped) -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils