From: Mark Wielaard Date: Wed, 27 Jun 2018 12:41:22 +0000 (+0200) Subject: libdw: Allow .debug_frame only Dwarf. X-Git-Tag: elfutils-0.173~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7a83bf05734e2c20d621678d0f3214475404c55;p=thirdparty%2Felfutils.git libdw: Allow .debug_frame only Dwarf. .debug_frame is useful independent from the other .debug sections. Add a simplified variant of the addrcfi testcase dwarfcfi. dwarfcfi only uses dwarf_frame calls and no dwfl helpers. Signed-off-by: Mark Wielaard --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 0ae12724e..1e86e6825 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2018-06-27 Mark Wielaard + + * dwarf_begin_elf.c (check_section): Allow a single .debug_frame + section. + 2018-06-26 Mark Wielaard * libdw.h (dwarf_getscn_info): Remove. diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index e1542c750..184a6dc95 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -209,7 +209,8 @@ valid_p (Dwarf *result) Require at least one section that can be read "standalone". */ if (likely (result != NULL) && unlikely (result->sectiondata[IDX_debug_info] == NULL - && result->sectiondata[IDX_debug_line] == NULL)) + && result->sectiondata[IDX_debug_line] == NULL + && result->sectiondata[IDX_debug_frame] == NULL)) { Dwarf_Sig8_Hash_free (&result->sig8_hash); __libdw_seterrno (DWARF_E_NO_DWARF); diff --git a/tests/ChangeLog b/tests/ChangeLog index d66041032..35a5d7eea 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,20 @@ +2018-06-27 Mark Wielaard + + * dwarf_cfi.c: New file. + * run-dwarfcfi.sh: New test. + * testfile11-debugframe.bz2: New testfile. + * testfile12-debugframe.bz2: Likewise. + * testfileaarch64-debugframe.bz2: Likewise. + * testfilearm-debugframe.bz2: Likewise. + * testfileppc32-debugframe.bz2: Likewise. + * testfileppc64-debugframe.bz2: Likewise. + * Makefile.am (check_PROGRAMS): Add dwarfcfi. + (TESTS): Add run-dwarfcfi.sh. + (EXTRA_DIST): Add run-dwarfcfi.sh, testfile11-debugframe.bz2, + testfile12-debugframe.bz2, testfileaarch64-debugframe.bz2, + testfilearm-debugframe.bz2, testfileppc32-debugframe.bz2 and + testfileppc64-debugframe.bz2. + 2018-06-23 Mark Wielaard * varlocs.c (print_expr): Take a new depth argument. Check it isn't diff --git a/tests/Makefile.am b/tests/Makefile.am index 7b29fd834..47e555516 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -46,6 +46,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \ dwfl-addr-sect dwfl-bug-report early-offscn \ dwfl-bug-getmodules dwarf-getmacros dwarf-ranges addrcfi \ + dwarfcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ alldts typeiter typeiter2 low_high_pc \ test-elf_cntl_gelf_getshdr dwflsyms dwfllines \ @@ -95,6 +96,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \ run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \ run-find-prologues.sh run-allregs.sh run-addrcfi.sh \ + run-dwarfcfi.sh \ run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \ run-readelf-const-values.sh \ run-varlocs-self.sh run-exprlocs-self.sh \ @@ -205,7 +207,10 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \ run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \ run-readelf-const-values.sh testfile-const-values.debug.bz2 \ - run-addrcfi.sh \ + run-addrcfi.sh run-dwarfcfi.sh \ + testfile11-debugframe.bz2 testfile12-debugframe.bz2 \ + testfileaarch64-debugframe.bz2 testfilearm-debugframe.bz2 \ + testfileppc32-debugframe.bz2 testfileppc64-debugframe.bz2 \ run-varlocs-self.sh run-exprlocs-self.sh \ run-find-prologues.sh run-allregs.sh run-native-test.sh \ run-addrname-test.sh run-dwfl-bug-offline-rel.sh \ @@ -506,6 +511,7 @@ dwarf_getmacros_LDADD = $(libdw) dwarf_ranges_LDADD = $(libdw) dwarf_getstring_LDADD = $(libdw) addrcfi_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD) -ldl +dwarfcfi_LDADD = $(libdw) $(libelf) test_flag_nobits_LDADD = $(libelf) rerequest_tag_LDADD = $(libdw) alldts_LDADD = $(libdw) $(libelf) diff --git a/tests/dwarfcfi.c b/tests/dwarfcfi.c new file mode 100644 index 000000000..db4a36ffc --- /dev/null +++ b/tests/dwarfcfi.c @@ -0,0 +1,175 @@ +/* Test program for DWARF (.debug_frame) CFI handling. + Copyright (C) 2009-2010, 2013, 2015, 2018 Red Hat, Inc. + This file is part of elfutils. + + This file 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; either version 3 of the License, or + (at your option) any later version. + + 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 this program. If not, see . */ + +#include +#include +#include +#include +#include ELFUTILS_HEADER(dw) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libdw/known-dwarf.h" + +static const char * +op_name (unsigned int code) +{ + static const char *const known[] = + { +#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME, + DWARF_ALL_KNOWN_DW_OP +#undef DWARF_ONE_KNOWN_DW_OP + }; + + if (likely (code < sizeof (known) / sizeof (known[0]))) + return known[code]; + + return NULL; +} + +static void +print_detail (int result, const Dwarf_Op *ops, size_t nops) +{ + if (result < 0) + printf ("indeterminate (%s)\n", dwarf_errmsg (-1)); + else if (nops == 0) + printf ("%s\n", ops == NULL ? "same_value" : "undefined"); + else + { + printf ("%s expression:", result == 0 ? "location" : "value"); + for (size_t i = 0; i < nops; ++i) + { + printf (" %s", op_name(ops[i].atom)); + if (ops[i].number2 == 0) + { + if (ops[i].atom == DW_OP_addr) + printf ("(%#" PRIx64 ")", ops[i].number); + else if (ops[i].number != 0) + printf ("(%" PRId64 ")", ops[i].number); + } + else + printf ("(%" PRId64 ",%" PRId64 ")", + ops[i].number, ops[i].number2); + } + puts (""); + } +} + +static int +handle_address (Dwarf_CFI *cfi, GElf_Addr pc) +{ + Dwarf_Frame *frame; + int result = dwarf_cfi_addrframe (cfi, pc, &frame); + if (result != 0) + { + printf ("dwarf_cfi_addrframe: %s\n", dwarf_errmsg (-1)); + return 1; + } + + Dwarf_Addr start = pc; + Dwarf_Addr end = pc; + bool signalp; + int ra_regno = dwarf_frame_info (frame, &start, &end, &signalp); + + printf ("%#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n", + pc, start, end); + + if (ra_regno < 0) + printf ("\treturn address register unavailable (%s)\n", + dwarf_errmsg (-1)); + else + printf ("\treturn address in reg%u%s\n", + ra_regno, signalp ? " (signal frame)" : ""); + + // Point cfa_ops to dummy to match print_detail expectations. + // (nops == 0 && cfa_ops != NULL => "undefined") + Dwarf_Op dummy; + Dwarf_Op *cfa_ops = &dummy; + size_t cfa_nops; + result = dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops); + + printf ("\tCFA "); + print_detail (result, cfa_ops, cfa_nops); + + // Print the location of the first 10 (DWARF nr) registers + for (int r = 0; r < 10; r++) + { + Dwarf_Op ops_mem[3]; + Dwarf_Op *ops; + size_t nops; + printf ("\treg%d: ", r); + int reg_result = dwarf_frame_register (frame, r, ops_mem, &ops, &nops); + print_detail (reg_result, ops, nops); + result |= reg_result; + } + + free (frame); + return result; +} + +int +main (int argc, char *argv[]) +{ + if (argc <= 2) + error (EXIT_FAILURE, 0, "need file name argument and addresses"); + + int fd = open (argv[1], O_RDONLY); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open input file `%s'", argv[1]); + + elf_version (EV_CURRENT); + + Elf *elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s", + elf_errmsg (-1)); + + Dwarf *dwarf = dwarf_begin_elf (elf, DWARF_C_READ, NULL); + if (dwarf == NULL) + error (EXIT_FAILURE, 0, "cannot create DWARF descriptor: %s", + dwarf_errmsg (-1)); + + Dwarf_CFI *cfi = dwarf_getcfi (dwarf); + if (cfi == NULL) + error (EXIT_FAILURE, 0, "cannot get DWARF CFI from .dwarf_frame: %s", + dwarf_errmsg (-1)); + + int result = 0; + int args = 2; + do + { + char *endp; + uintmax_t addr = strtoumax (argv[args], &endp, 0); + if (endp != argv[args]) + result |= handle_address (cfi, addr); + else + result = 1; + } + while (args++ < argc - 1); + + dwarf_end (dwarf); + elf_end (elf); + + return result; +} diff --git a/tests/run-dwarfcfi.sh b/tests/run-dwarfcfi.sh new file mode 100755 index 000000000..98fa171da --- /dev/null +++ b/tests/run-dwarfcfi.sh @@ -0,0 +1,133 @@ +#! /bin/sh +# Test for dwarf_getcfi. +# Copyright (C) 2018 Red Hat, Inc. +# This file is part of elfutils. +# +# This file 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; either version 3 of the License, or +# (at your option) any later version. +# +# 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 this program. If not, see . + +. $srcdir/test-subr.sh + +# Test files come from run-addrcfi with all sections stripped except +# the .debug_frame. +# for i in +# eu-strip -f $i-debugframe $i +# eu-strip -g --remove-comment --keep-section=.debug_frame $i-debugframe +# done +testfiles testfile11-debugframe testfile12-debugframe +testfiles testfileaarch64-debugframe +testfiles testfilearm-debugframe +testfiles testfileppc32-debugframe +testfiles testfileppc64-debugframe + +testfiles testfile11-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfile11-debugframe 0x080489b8 <<\EOF +0x80489b8 => [0x80489b8, 0x80489b9): + return address in reg8 + CFA location expression: bregx(4,4) + reg0: undefined + reg1: undefined + reg2: undefined + reg3: same_value + reg4: location expression: call_frame_cfa stack_value + reg5: same_value + reg6: same_value + reg7: same_value + reg8: location expression: call_frame_cfa plus_uconst(-4) + reg9: undefined +EOF + +testfiles testfile12-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfile12-debugframe 0x00000000000009d0 <<\EOF +0x9d0 => [0x9d0, 0x9d1): + return address in reg16 + CFA location expression: bregx(7,8) + reg0: same_value + reg1: undefined + reg2: undefined + reg3: undefined + reg4: undefined + reg5: undefined + reg6: same_value + reg7: location expression: call_frame_cfa stack_value + reg8: undefined + reg9: undefined +EOF + +testfiles testfileppc32-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfileppc32-debugframe 0x100004c0 <<\EOF +0x100004c0 => [0x100004c0, 0x100004d0): + return address in reg65 + CFA location expression: bregx(1) + reg0: undefined + reg1: location expression: call_frame_cfa stack_value + reg2: same_value + reg3: undefined + reg4: undefined + reg5: undefined + reg6: undefined + reg7: undefined + reg8: undefined + reg9: undefined +EOF + +testfiles testfileppc64-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfileppc64-debugframe 0x00000000100005b0 <<\EOF +0x100005b0 => [0x100005b0, 0x100005d0): + return address in reg65 + CFA location expression: bregx(1) + reg0: undefined + reg1: location expression: call_frame_cfa stack_value + reg2: same_value + reg3: undefined + reg4: undefined + reg5: undefined + reg6: undefined + reg7: undefined + reg8: undefined + reg9: undefined +EOF + +testfiles testfilearm-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfilearm-debugframe 0x00008510 <<\EOF +0x8510 => [0x8510, 0x8524): + return address in reg14 + CFA location expression: bregx(13) + reg0: undefined + reg1: undefined + reg2: undefined + reg3: undefined + reg4: same_value + reg5: same_value + reg6: same_value + reg7: same_value + reg8: same_value + reg9: undefined +EOF + +testfiles testfileaarch64-debugframe +testrun_compare ${abs_builddir}/dwarfcfi testfileaarch64-debugframe 0x400550 <<\EOF +0x400550 => [0x400550, 0x400568): + return address in reg30 + CFA location expression: bregx(31) + reg0: undefined + reg1: undefined + reg2: undefined + reg3: undefined + reg4: undefined + reg5: undefined + reg6: undefined + reg7: undefined + reg8: undefined + reg9: undefined +EOF diff --git a/tests/testfile11-debugframe.bz2 b/tests/testfile11-debugframe.bz2 new file mode 100644 index 000000000..5c07d16a0 Binary files /dev/null and b/tests/testfile11-debugframe.bz2 differ diff --git a/tests/testfile12-debugframe.bz2 b/tests/testfile12-debugframe.bz2 new file mode 100644 index 000000000..b8cc19c3c Binary files /dev/null and b/tests/testfile12-debugframe.bz2 differ diff --git a/tests/testfileaarch64-debugframe.bz2 b/tests/testfileaarch64-debugframe.bz2 new file mode 100755 index 000000000..e77494a10 Binary files /dev/null and b/tests/testfileaarch64-debugframe.bz2 differ diff --git a/tests/testfilearm-debugframe.bz2 b/tests/testfilearm-debugframe.bz2 new file mode 100755 index 000000000..51ce2d371 Binary files /dev/null and b/tests/testfilearm-debugframe.bz2 differ diff --git a/tests/testfileppc32-debugframe.bz2 b/tests/testfileppc32-debugframe.bz2 new file mode 100755 index 000000000..b6ae4ea67 Binary files /dev/null and b/tests/testfileppc32-debugframe.bz2 differ diff --git a/tests/testfileppc64-debugframe.bz2 b/tests/testfileppc64-debugframe.bz2 new file mode 100755 index 000000000..85c80ac66 Binary files /dev/null and b/tests/testfileppc64-debugframe.bz2 differ