aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-04-14 09:23:12 +0930
committerAlan Modra <amodra@gmail.com>2021-04-14 09:37:41 +0930
commitd20eb46617fc6170e144f80dcbaffbc3f4ff6090 (patch)
tree42547a6eaa39f4ddfb90bbd2b84a80ada9e36537
parentc48a248e3358ea11e9d1946c50b4bd548cccf939 (diff)
downloadgdb-d20eb46617fc6170e144f80dcbaffbc3f4ff6090.zip
gdb-d20eb46617fc6170e144f80dcbaffbc3f4ff6090.tar.gz
gdb-d20eb46617fc6170e144f80dcbaffbc3f4ff6090.tar.bz2
Re: PR27723, Internal error in select_cie_for_fde
Let's make sure what we allow in the CIE initial instructions and what select_cie_for_fde compares for a match is always in sync. Also correct the previous patch that allowed DW_CFA_GNU_window_save to be part of the CIE initial instructions, which was likely a mistake. PR 27723 * dw2gencfi.c (initial_cie_insn): New function, extracted from.. (select_cie_for_fde): ..here. Simplify.
-rw-r--r--gas/ChangeLog6
-rw-r--r--gas/dw2gencfi.c129
2 files changed, 67 insertions, 68 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 07e5581..10127cc 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,6 +1,12 @@
2021-04-14 Alan Modra <amodra@gmail.com>
PR 27723
+ * dw2gencfi.c (initial_cie_insn): New function, extracted from..
+ (select_cie_for_fde): ..here. Simplify.
+
+2021-04-14 Alan Modra <amodra@gmail.com>
+
+ PR 27723
* dw2gencfi.c (select_cie_for_fde): Handle DW_CFA_val_offset,
DW_CFA_GNU_window_save and DW_CFA_restore_state.
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index ffaef52..c065614 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -2043,6 +2043,63 @@ output_fde (struct fde_entry *fde, struct cie_entry *cie,
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 bool
+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, bool eh_frame,
struct cfi_insn_data **pfirst, int align)
@@ -2088,75 +2145,15 @@ select_cie_for_fde (struct fde_entry *fde, bool eh_frame,
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:
- case DW_CFA_val_offset:
- 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:
- case DW_CFA_restore_state:
- case DW_CFA_GNU_window_save:
- /* 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 == DW_CFA_GNU_window_save
- || 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);
@@ -2174,11 +2171,7 @@ select_cie_for_fde (struct fde_entry *fde, bool eh_frame,
#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;