From: Roland McGrath Date: Tue, 27 Apr 2010 01:45:36 +0000 (-0700) Subject: libdw: Record ill-specified CFA rule and diagnose in dwarf_frame_cfa, not immediately... X-Git-Tag: elfutils-0.147~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3b10ac0ade6aae156b76884421eb82985b4e9be8;p=thirdparty%2Felfutils.git libdw: Record ill-specified CFA rule and diagnose in dwarf_frame_cfa, not immediately at decode time. --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 50fba721c..a6e845724 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,10 @@ 2010-04-26 Roland McGrath + * cfi.h (struct Dwarf_Frame_s): Add cfa_invalid alternative in cfa_rule. + * cfi.c (execute_cfi): Set that instead of doing cfi_assert for + DW_CFA_def_cfa_{offset*,register} when a non-offset rule is in force. + * dwarf_frame_cfa.c (dwarf_frame_cfa): Handle cfa_invalid. + * dwarf_getlocation.c (__libdw_intern_expression): Take new arg CFAP. Prepend DW_OP_call_frame_cfa if true. (getlocation): Update caller. diff --git a/libdw/cfi.c b/libdw/cfi.c index 5936659a7..3cb378b6d 100644 --- a/libdw/cfi.c +++ b/libdw/cfi.c @@ -117,6 +117,12 @@ execute_cfi (Dwarf_CFI *cache, return true; } + inline void require_cfa_offset (void) + { + if (unlikely (fs->cfa_rule != cfa_offset)) + fs->cfa_rule = cfa_invalid; + } + #define register_rule(regno, r_rule, r_value) do { \ if (unlikely (! enough_registers (regno))) \ goto out; \ @@ -177,7 +183,7 @@ execute_cfi (Dwarf_CFI *cache, case DW_CFA_def_cfa_register: get_uleb128 (regno, program); - cfi_assert (fs->cfa_rule == cfa_offset); + require_cfa_offset (); fs->cfa_val_reg = regno; continue; @@ -190,7 +196,7 @@ execute_cfi (Dwarf_CFI *cache, case DW_CFA_def_cfa_offset: get_uleb128 (offset, program); def_cfa_offset: - cfi_assert (fs->cfa_rule == cfa_offset); + require_cfa_offset (); fs->cfa_val_offset = offset; continue; diff --git a/libdw/cfi.h b/libdw/cfi.h index 64f3f1574..e04e76ddb 100644 --- a/libdw/cfi.h +++ b/libdw/cfi.h @@ -1,5 +1,5 @@ /* Internal definitions for libdw CFI interpreter. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -191,8 +191,11 @@ struct Dwarf_Frame_s which has the return_address_register and signal_frame flag. */ struct dwarf_fde *fde; - /* The CFA is unknown, is R+N, or is computed by a DWARF expression. */ - enum { cfa_undefined, cfa_offset, cfa_expr } cfa_rule; + /* The CFA is unknown, is R+N, or is computed by a DWARF expression. + A bogon in the CFI can indicate an invalid/incalculable rule. + We store that as cfa_invalid rather than barfing when processing it, + so callers can ignore the bogon unless they really need that CFA. */ + enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule; union { Dwarf_Op offset; diff --git a/libdw/dwarf_frame_cfa.c b/libdw/dwarf_frame_cfa.c index 03c5fbd24..0ba26b2fd 100644 --- a/libdw/dwarf_frame_cfa.c +++ b/libdw/dwarf_frame_cfa.c @@ -88,6 +88,11 @@ dwarf_frame_cfa (fs, ops, nops) ops, nops, IDX_debug_frame); break; + case cfa_invalid: + __libdw_seterrno (DWARF_E_INVALID_CFI); + result = -1; + break; + default: abort (); }