Hi,
exception handling is currently broken in all languages for Darwin at -O2 on
the mainline because of what appears to be a bug in either the assembler or
the system unwinder. The problem occurs when the compiler decides to split a
function into hot & cold parts and the cold part is active wrt EH; in this
case, the compiler generates a FDE for each part (the Darwin port doesn't use
the CFI assembler directives) and the second FDE looks like:
.set L$set$24,LEFDE3-LASFDE3
.long L$set$24 # FDE Length
LASFDE3:
.long LASFDE3-EH_frame1 # FDE CIE offset
.quad LCOLDB1-. # FDE initial location
.set L$set$25,LCOLDE1-LCOLDB1
.quad L$set$25 # FDE address range
.byte 0x8 # uleb128 0x8; Augmentation size
.quad LLSDAC5-. # Language Specific Data Area
.byte 0x1 # DW_CFA_set_loc
.quad LCFI1-.
.byte 0xe # DW_CFA_def_cfa_offset
.byte 0x10 # uleb128 0x10
.byte 0x83 # DW_CFA_offset, column 0x3
.byte 0x2 # uleb128 0x2
Note the DW_CFA_set_loc operation: it's the only case where the compiler emits
it (DW_CFA_advance_loc4 is usually emitted) and is the source of the problem,
since it appears that the PC-relative relocation is not applied to the operand
of the DW_CFA_set_loc (unlike to the 2 other cases in the FDE).
This DW_CFA_set_loc instruction is emitted by add_cfis_to_fde for the second
FDE generated for the cold part of a function but doesn't seem necessary any
more, since there is a label (LCOLDB1) to be used now (this can also be seen
on Linux with the -fno-dwarf2-cfi-asm option).
Bootstrapped/regtested on x86-64/Linux by me and various versions of Darwin by
Iain, Dominique and myself. OK for the mainline?
2017-09-18 Eric Botcazou <ebotca...@adacore.com>
PR target/81361
* dwarf2cfi.c (add_cfis_to_fde): Do not generate DW_CFA_set_loc
after switching to a new text section.
--
Eric Botcazou
Index: dwarf2cfi.c
===================================================================
--- dwarf2cfi.c (revision 252749)
+++ dwarf2cfi.c (working copy)
@@ -2209,20 +2209,13 @@ add_cfis_to_fde (void)
{
dw_fde_ref fde = cfun->fde;
rtx_insn *insn, *next;
- /* We always start with a function_begin label. */
- bool first = false;
for (insn = get_insns (); insn; insn = next)
{
next = NEXT_INSN (insn);
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
- {
- fde->dw_fde_switch_cfi_index = vec_safe_length (fde->dw_fde_cfi);
- /* Don't attempt to advance_loc4 between labels
- in different sections. */
- first = true;
- }
+ fde->dw_fde_switch_cfi_index = vec_safe_length (fde->dw_fde_cfi);
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI)
{
@@ -2247,8 +2240,7 @@ add_cfis_to_fde (void)
/* Set the location counter to the new label. */
xcfi = new_cfi ();
- xcfi->dw_cfi_opc = (first ? DW_CFA_set_loc
- : DW_CFA_advance_loc4);
+ xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
vec_safe_push (fde->dw_fde_cfi, xcfi);
@@ -2263,7 +2255,6 @@ add_cfis_to_fde (void)
insn = NEXT_INSN (insn);
}
while (insn != next);
- first = false;
}
}
}