You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
3.6 KiB
155 lines
3.6 KiB
--- 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;
|
|
|