diff options
| author | Mark Wielaard <[email protected]> | 2012-04-27 13:00:50 +0200 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2012-04-28 15:02:28 +0200 |
| commit | 547972539ecbe8668e89d891d86cef10f0302fd5 (patch) | |
| tree | ac41ac0a8ba48e00038a9b8de5b252e33e841b9e /libdw/dwarf_highpc.c | |
| parent | bdad8e39aede889dbac95944a07eaebdebe4ad89 (diff) | |
dwarf_highpc: Handle DW_AT_high_pc being a constant offset from DW_AT_low_pc.
Diffstat (limited to 'libdw/dwarf_highpc.c')
| -rw-r--r-- | libdw/dwarf_highpc.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/libdw/dwarf_highpc.c b/libdw/dwarf_highpc.c index c88e0721..4e7c3f6e 100644 --- a/libdw/dwarf_highpc.c +++ b/libdw/dwarf_highpc.c @@ -1,5 +1,5 @@ /* Return high PC attribute of DIE. - Copyright (C) 2003, 2005 Red Hat, Inc. + Copyright (C) 2003, 2005, 2012 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <[email protected]>, 2003. @@ -61,10 +61,29 @@ dwarf_highpc (die, return_addr) Dwarf_Die *die; Dwarf_Addr *return_addr; { - Dwarf_Attribute attr_mem; + Dwarf_Attribute attr_high_mem; + Dwarf_Attribute *attr_high = INTUSE(dwarf_attr) (die, DW_AT_high_pc, + &attr_high_mem); + if (attr_high == NULL) + return -1; - return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_high_pc, - &attr_mem), - return_addr); + if (attr_high->form == DW_FORM_addr) + return INTUSE(dwarf_formaddr) (attr_high, return_addr); + + /* DWARF 4 allows high_pc to be a constant offset from low_pc. */ + Dwarf_Attribute attr_low_mem; + if (INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_low_pc, + &attr_low_mem), + return_addr) == 0) + { + Dwarf_Word uval; + if (INTUSE(dwarf_formudata) (attr_high, &uval) == 0) + { + *return_addr += uval; + return 0; + } + __libdw_seterrno (DWARF_E_NO_ADDR); + } + return -1; } INTDEF(dwarf_highpc) |
