From: Mark Wielaard Date: Fri, 27 Apr 2012 11:00:50 +0000 (+0200) Subject: dwarf_highpc: Handle DW_AT_high_pc being a constant offset from DW_AT_low_pc. X-Git-Tag: elfutils-0.154~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=547972539ecbe8668e89d891d86cef10f0302fd5;p=platform%2Fupstream%2Felfutils.git dwarf_highpc: Handle DW_AT_high_pc being a constant offset from DW_AT_low_pc. --- diff --git a/NEWS b/NEWS index aa660a8..d41f045 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Version 0.154 + +libdw: dwarf_highpc function now handles DWARF 4 DW_AT_high_pc constant form. + Version 0.153 libdw: Support reading .zdebug_* DWARF sections compressed via zlib. diff --git a/libdw/ChangeLog b/libdw/ChangeLog index f96c0d1..3ff83e4 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2012-04-27 Mark Wielaard + + * libdw/dwarf_highpc.c (dwarf_highpc): Handle DW_AT_high_pc being + a constant offset from DW_AT_low_pc. + 2012-03-19 Tom Tromey * libdw_findcu.c (findcu_cb): Move earlier. diff --git a/libdw/dwarf_highpc.c b/libdw/dwarf_highpc.c index c88e072..4e7c3f6 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 , 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) diff --git a/tests/ChangeLog b/tests/ChangeLog index ffe61d5..abc7340 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2012-04-27 Mark Wielaard + + * Makefile.am (TESTS): Add run-low_high_pc.sh + (EXTRA_DIST): Add run-low_high_pc.sh and testfile_low_high_pc.bz2 + (noinst_PROGRAMS): Add low_high_pc. + (low_high_pc_LDADD): New variable. + * low_high_pc.c: New test. + 2012-04-26 Mark Wielaard * Makefile.am (EXTRA_DIST): Remove run-show-ciefde.sh. diff --git a/tests/Makefile.am b/tests/Makefile.am index 835cc7a..61247e4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -58,7 +58,7 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-addr-sect dwfl-bug-report early-offscn \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ - alldts md5-sha1-test typeiter + alldts md5-sha1-test typeiter low_high_pc asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -87,7 +87,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-early-offscn.sh run-dwarf-getmacros.sh \ run-test-flag-nobits.sh run-prelink-addr-test.sh \ run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh \ - run-readelf-d.sh run-unstrip-n.sh + run-readelf-d.sh run-unstrip-n.sh run-low_high_pc.sh if !STANDALONE noinst_PROGRAMS += msg_tst md5-sha1-test @@ -164,7 +164,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile56.bz2 testfile57.bz2 testfile58.bz2 \ run-typeiter.sh testfile59.bz2 \ run-readelf-d.sh testlib_dynseg.so.bz2 \ - run-unstrip-n.sh testcore-rtlib.bz2 + run-unstrip-n.sh testcore-rtlib.bz2 \ + run-low_high_pc.sh testfile_low_high_pc.bz2 installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \ bindir=$(DESTDIR)$(bindir) \ @@ -262,6 +263,7 @@ rerequest_tag_LDADD = $(libdw) $(libmudflap) alldts_LDADD = $(libebl) $(libelf) $(libmudflap) md5_sha1_test_LDADD = $(libeu) typeiter_LDADD = $(libdw) $(libelf) $(libmudflap) +low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap) if GCOV check: check-am coverage diff --git a/tests/low_high_pc.c b/tests/low_high_pc.c new file mode 100644 index 0000000..3054046 --- /dev/null +++ b/tests/low_high_pc.c @@ -0,0 +1,114 @@ +/* Test program for dwarf_lowpc and dwarf_highpc + Copyright (C) 2012 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#include +#include +#include +#include ELFUTILS_HEADER(dwfl) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct args +{ + Dwfl *dwfl; + Dwarf_Die *cu; + Dwarf_Addr dwbias; + char **argv; + const char *file; +}; + +static struct args *args; + +static void +fail(Dwarf_Off off, const char *name, const char *msg) +{ + printf("%s: [%lx] '%s' %s\n", args->file, off, name, msg); + exit(-1); +} + +static int +handle_die (Dwarf_Die *die, void *arg) +{ + args = arg; + Dwarf_Off off = dwarf_dieoffset (die); + + const char *name = dwarf_diename (die); + if (name == NULL) + fail (off, "", "die without a name"); + + Dwarf_Addr lowpc = 0; + Dwarf_Addr highpc = 0; + if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc)) + fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails"); + if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc)) + fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails"); + + if (dwarf_hasattr (die, DW_AT_low_pc) + && dwarf_hasattr (die, DW_AT_high_pc) + && highpc <= lowpc) + { + printf("lowpc: %lx, highpc: %lx\n", lowpc, highpc); + fail (off, name, "highpc <= lowpc"); + } + + return 0; +} + + +int +main (int argc, char *argv[]) +{ + int remaining; + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + struct args a = { .dwfl = NULL, .cu = NULL }; + + (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, + &a.dwfl); + assert (a.dwfl != NULL); + a.argv = &argv[remaining]; + + int result = 0; + + while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL) + { + a.file = dwarf_diename (a.cu); + handle_die (a.cu, &a); + dwarf_getfuncs (a.cu, &handle_die, &a, 0); + } + + dwfl_end (a.dwfl); + + return result; +} diff --git a/tests/run-low_high_pc.sh b/tests/run-low_high_pc.sh new file mode 100755 index 0000000..8d891f1 --- /dev/null +++ b/tests/run-low_high_pc.sh @@ -0,0 +1,42 @@ +#! /bin/sh +# Copyright (C) 2005 Red Hat, Inc. +# This file is part of Red Hat elfutils. +# +# Red Hat elfutils is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; version 2 of the License. +# +# Red Hat elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Red Hat elfutils; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +# +# Red Hat elfutils is an included package of the Open Invention Network. +# An included package of the Open Invention Network is a package for which +# Open Invention Network licensees cross-license their patents. No patent +# license is granted, either expressly or impliedly, by designation as an +# included package. Should you wish to participate in the Open Invention +# Network licensing program, please visit www.openinventionnetwork.com +# . + +. $srcdir/test-subr.sh + +# int +# main (int argc, char **argv) +# { +# return 0; +# } +# gcc -g -o main main.c +testfiles testfile_low_high_pc + +testrun ./low_high_pc -e ./testfile_low_high_pc +testrun ./low_high_pc -e ./low_high_pc +testrun ./low_high_pc -e ../src/strip +testrun ./low_high_pc -e ../src/strip.o +testrun ./low_high_pc -e ../libelf/libelf.so + +exit 0 diff --git a/tests/testfile_low_high_pc.bz2 b/tests/testfile_low_high_pc.bz2 new file mode 100755 index 0000000..f20814a Binary files /dev/null and b/tests/testfile_low_high_pc.bz2 differ