--- binutils.orig/gas/dw2gencfi.c 2022-09-08 13:54:05.539276706 +0100 +++ binutils-2.35.2/gas/dw2gencfi.c 2022-09-08 14:05:56.128016840 +0100 @@ -2054,6 +2054,64 @@ output_fde (struct fde_entry *fde, struc symbol_set_value_now (end_address); } +/* Allow these insns to be put in the initial sequence of a CIE. + If J is non-NULL, then compare I and J insns for a match. */ + +static inline bfd_boolean +initial_cie_insn (const struct cfi_insn_data *i, const struct cfi_insn_data *j) +{ + if (j && i->insn != j->insn) + return FALSE; + + switch (i->insn) + { + case DW_CFA_offset: + case DW_CFA_def_cfa: + case DW_CFA_val_offset: + if (j) + { + if (i->u.ri.reg != j->u.ri.reg) + return FALSE; + if (i->u.ri.offset != j->u.ri.offset) + return FALSE; + } + break; + + case DW_CFA_register: + if (j) + { + if (i->u.rr.reg1 != j->u.rr.reg1) + return FALSE; + if (i->u.rr.reg2 != j->u.rr.reg2) + return FALSE; + } + break; + + case DW_CFA_def_cfa_register: + case DW_CFA_restore: + case DW_CFA_undefined: + case DW_CFA_same_value: + if (j) + { + if (i->u.r != j->u.r) + return FALSE; + } + break; + + case DW_CFA_def_cfa_offset: + if (j) + { + if (i->u.i != j->u.i) + return FALSE; + } + break; + + default: + return FALSE; + } + return TRUE; +} + static struct cie_entry * select_cie_for_fde (struct fde_entry *fde, bfd_boolean eh_frame, struct cfi_insn_data **pfirst, int align) @@ -2099,71 +2157,15 @@ select_cie_for_fde (struct fde_entry *fd i != cie->last && j != NULL; i = i->next, j = j->next) { - if (i->insn != j->insn) - goto fail; - switch (i->insn) - { - case DW_CFA_advance_loc: - case DW_CFA_remember_state: - /* We reached the first advance/remember in the FDE, - but did not reach the end of the CIE list. */ - goto fail; - - case DW_CFA_offset: - case DW_CFA_def_cfa: - if (i->u.ri.reg != j->u.ri.reg) - goto fail; - if (i->u.ri.offset != j->u.ri.offset) - goto fail; - break; - - case DW_CFA_register: - if (i->u.rr.reg1 != j->u.rr.reg1) - goto fail; - if (i->u.rr.reg2 != j->u.rr.reg2) - goto fail; - break; - - case DW_CFA_def_cfa_register: - case DW_CFA_restore: - case DW_CFA_undefined: - case DW_CFA_same_value: - if (i->u.r != j->u.r) - goto fail; - break; - - case DW_CFA_def_cfa_offset: - if (i->u.i != j->u.i) - goto fail; - break; - - case CFI_escape: - case CFI_val_encoded_addr: - case CFI_label: - /* Don't bother matching these for now. */ - goto fail; - - default: - abort (); - } + if (!initial_cie_insn (i, j)) + break; } - /* Success if we reached the end of the CIE list, and we've either - run out of FDE entries or we've encountered an advance, - remember, or escape. */ - if (i == cie->last - && (!j - || j->insn == DW_CFA_advance_loc - || j->insn == DW_CFA_remember_state - || j->insn == CFI_escape - || j->insn == CFI_val_encoded_addr - || j->insn == CFI_label)) + if (i == cie->last) { *pfirst = j; return cie; } - - fail:; } cie = XNEW (struct cie_entry); @@ -2181,11 +2183,7 @@ select_cie_for_fde (struct fde_entry *fd #endif for (i = cie->first; i ; i = i->next) - if (i->insn == DW_CFA_advance_loc - || i->insn == DW_CFA_remember_state - || i->insn == CFI_escape - || i->insn == CFI_val_encoded_addr - || i->insn == CFI_label) + if (!initial_cie_insn (i, NULL)) break; cie->last = i;