From 8f65940dd1ba4a5d305a9efa4d44a5af15518af1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 21 Apr 2010 08:57:37 +0200 Subject: [PATCH] dwarf2out.c (output_call_frame_info): For dw_cie_version >= 4 add also address size and segment size fields into CIE... * dwarf2out.c (output_call_frame_info): For dw_cie_version >= 4 add also address size and segment size fields into CIE header. * unwind-dw2.c (extract_cie_info): Handle CIE version 4, as long as address size is the same as sizeof (void *) and segment size is 0. * unwind-dw2-fde.c (get_cie_encoding): Likewise. If address size or segment size is unexpected, return DW_EH_PE_omit. (classify_object_over_fdes): If get_cie_encoding returned DW_EH_PE_omit, return -1. (init_object): If classify_object_over_fdes returned -1, pretend there were no FDEs at all. From-SVN: r158589 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/dwarf2out.c | 5 +++++ gcc/unwind-dw2-fde.c | 34 ++++++++++++++++++++++++++++++---- gcc/unwind-dw2.c | 11 ++++++++++- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4348d3d1331..6f875d4b32e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2010-04-21 Jakub Jelinek + + * dwarf2out.c (output_call_frame_info): For dw_cie_version + >= 4 add also address size and segment size fields into CIE + header. + + * unwind-dw2.c (extract_cie_info): Handle CIE version 4, as + long as address size is the same as sizeof (void *) and + segment size is 0. + * unwind-dw2-fde.c (get_cie_encoding): Likewise. If + address size or segment size is unexpected, return DW_EH_PE_omit. + (classify_object_over_fdes): If get_cie_encoding returned + DW_EH_PE_omit, return -1. + (init_object): If classify_object_over_fdes returned -1, + pretend there were no FDEs at all. + 2010-04-21 Uros Bizjak * config/i386/i386.md (bswap2): Macroize expander from diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index cfacf96a62b..21a3f75f855 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3771,6 +3771,11 @@ output_call_frame_info (int for_eh) } dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); + if (dw_cie_version >= 4) + { + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "CIE Address Size"); + dw2_asm_output_data (1, 0, "CIE Segment Size"); + } dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT, "CIE Data Alignment Factor"); diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c index 60535cfd780..93d427165c4 100644 --- a/gcc/unwind-dw2-fde.c +++ b/gcc/unwind-dw2-fde.c @@ -1,6 +1,6 @@ /* Subroutines needed for unwinding stack frames for exception handling. */ /* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, - 2009 Free Software Foundation, Inc. + 2009, 2010 Free Software Foundation, Inc. Contributed by Jason Merrill . This file is part of GCC. @@ -265,10 +265,18 @@ get_cie_encoding (const struct dwarf_cie *cie) _sleb128_t stmp; aug = cie->augmentation; + p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */ + if (__builtin_expect (cie->version >= 4, 0)) + { + if (p[0] != sizeof (void *) || p[1] != 0) + return DW_EH_PE_omit; /* We are not prepared to handle unexpected + address sizes or segment selectors. */ + p += 2; /* Skip address size and segment size. */ + } + if (aug[0] != 'z') return DW_EH_PE_absptr; - p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */ p = read_uleb128 (p, &utmp); /* Skip code alignment. */ p = read_sleb128 (p, &stmp); /* Skip data alignment. */ if (cie->version == 1) /* Skip return address column. */ @@ -614,6 +622,8 @@ classify_object_over_fdes (struct object *ob, const fde *this_fde) { last_cie = this_cie; encoding = get_cie_encoding (this_cie); + if (encoding == DW_EH_PE_omit) + return -1; base = base_from_object (encoding, ob); if (ob->s.b.encoding == DW_EH_PE_omit) ob->s.b.encoding = encoding; @@ -723,10 +733,26 @@ init_object (struct object* ob) { fde **p = ob->u.array; for (count = 0; *p; ++p) - count += classify_object_over_fdes (ob, *p); + { + size_t cur_count = classify_object_over_fdes (ob, *p); + if (cur_count == (size_t) -1) + goto unhandled_fdes; + count += cur_count; + } } else - count = classify_object_over_fdes (ob, ob->u.single); + { + count = classify_object_over_fdes (ob, ob->u.single); + if (count == (size_t) -1) + { + static const fde terminator; + unhandled_fdes: + ob->s.i = 0; + ob->s.b.encoding = DW_EH_PE_omit; + ob->u.single = &terminator; + return; + } + } /* The count field we have in the main struct object is somewhat limited, but should suffice for virtually all cases. If the diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 3cf3189bb4f..65d639d4301 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -356,7 +356,16 @@ extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context, aug += 2; } - /* Immediately following the augmentation are the code and + /* After the augmentation resp. pointer for "eh" augmentation + follows for CIE version >= 4 address size byte and + segment size byte. */ + if (__builtin_expect (cie->version >= 4, 0)) + { + if (p[0] != sizeof (void *) || p[1] != 0) + return NULL; + p += 2; + } + /* Immediately following this are the code and data alignment and return address column. */ p = read_uleb128 (p, &utmp); fs->code_align = (_Unwind_Word)utmp;