[Bug gold/23482] New: Identical code folding can break C++ exception handling invariants

2018-08-03 Thread oremanj at gmail dot com
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


[Bug gold/23482] Identical code folding can break C++ exception handling invariants

2018-08-03 Thread oremanj at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=23482

--- Comment #1 from Joshua Oreman  ---
Created attachment 11162
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11162&action=edit
Reproducer for reported issue

-- 
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


[Bug gold/21066] icf folds template functions with different exception handling semantics

2018-08-10 Thread oremanj at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=21066

--- Comment #4 from Joshua Oreman  ---
As I pointed out in PR 23482, hot/cold function splitting (the new gcc
-freorder-blocks-and-partition optimization) can make this an issue even
without any LSDA at all. Seems a full fix will need to consider the CIE/FDE
contents that are relevant to the function as well.

Example uses asm for clarity, but I can obtain analogous issues using
gcc-produced code, as demonstrated on the above PR.

$ g++ -o t.nofold t.cc -fuse-ld=gold
$ g++ -o t.fold t.cc -fuse-ld=gold -Wl,--icf=safe
$ ./t.nofold
caught 1: 42
caught 2: 42
$ ./t.fold
caught 1: 42
terminate called after throwing an instance of 'int'
Aborted (core dumped)
$ cat t.cc

extern "C" int printf(const char *fmt, ...);

void throw_it() { throw 42; }
extern void call_1(void(*)());
extern void call_2(void(*)());

asm(R"(
.section .text._Z6call_1PFvvE,"ax",@progbits
.globl _Z6call_1PFvvE
.type _Z6call_1PFvvE, @function
_Z6call_1PFvvE:
.cfi_startproc
pushq   %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
jmp _Z6call_1PFvvE.cold
.cfi_endproc

.section .text.unlikely._Z6call_1PFvvE,"ax",@progbits
.type _Z6call_1PFvvE.cold, @function
_Z6call_1PFvvE.cold:
.cfi_startproc
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
call*%rdi
.cfi_endproc

.section .text._Z6call_2PFvvE,"ax",@progbits
.globl _Z6call_2PFvvE
.type _Z6call_2PFvvE, @function
_Z6call_2PFvvE:
.cfi_startproc
subq$24, %rsp
.cfi_def_cfa_offset 32
jmp _Z6call_2PFvvE.cold
.cfi_endproc

.section .text.unlikely._Z6call_2PFvvE,"ax",@progbits
.type _Z6call_2PFvvE.cold, @function
_Z6call_2PFvvE.cold:
.cfi_startproc
.cfi_def_cfa_offset 32
call*%rdi
.cfi_endproc
)");

int main() {
try {
call_1(throw_it);
} catch (int val) {
printf("caught 1: %d\n", val);
}
try {
call_2(throw_it);
} catch (int val) {
printf("caught 2: %d\n", val);
}
}

-- 
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


[Bug gold/21066] icf folds template functions with different exception handling semantics

2018-09-26 Thread oremanj at gmail dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=21066

--- Comment #5 from Joshua Oreman  ---
Created attachment 11278
  --> https://sourceware.org/bugzilla/attachment.cgi?id=11278&action=edit
Proposed fix

I believe this patch fixes all the issues described in this thread. I also
submitted it to the mailing list:
https://sourceware.org/ml/binutils/2018-09/msg00346.html

-- 
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