summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_highpc.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2012-04-27 13:00:50 +0200
committerMark Wielaard <[email protected]>2012-04-28 15:02:28 +0200
commit547972539ecbe8668e89d891d86cef10f0302fd5 (patch)
treeac41ac0a8ba48e00038a9b8de5b252e33e841b9e /libdw/dwarf_highpc.c
parentbdad8e39aede889dbac95944a07eaebdebe4ad89 (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.c29
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)