cbd5319db8
Resolves: #2121123
156 lines
3.6 KiB
Diff
156 lines
3.6 KiB
Diff
--- 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;
|