From: Mark Wielaard Date: Thu, 7 Dec 2017 15:31:54 +0000 (+0100) Subject: readelf: Handle DW_OP_call2 and DW_OP_call4 correctly. X-Git-Tag: elfutils-0.171~97 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57b7f381e167356fa47d58c18bbc2e856f75ee16;p=thirdparty%2Felfutils.git readelf: Handle DW_OP_call2 and DW_OP_call4 correctly. DW_OP_call2 and DW_OP_call4 didn't correctly advance the data pointer. This caused print_ops to produce garbage operands. Also format the arguments as DIE offsets. That makes it easier to follow the call to the actual dwarf_procedure DIE. Testcase from https://sourceware.org/bugzilla/show_bug.cgi?id=22532 The testcase only checks the eu-readelf output is correct for the byte_size attribute. But it might be interesting to write a full expression parser to check the actual sizes. [ 3e] structure_type name (strp) "pck__rec" byte_size (exprloc) [ 0] push_object_address [ 1] deref_size 1 [ 3] call4 [ 95] [ 8] plus_uconst 7 [ 10] const1s -4 [ 12] and [ 95] dwarf_procedure location (exprloc) [ 0] dup [ 1] lit1 [ 2] ne [ 3] bra 10 [ 6] lit4 [ 7] skip 31 [ 10] dup [ 11] lit4 [ 12] ne [ 13] bra 20 [ 16] lit0 [ 17] skip 31 [ 20] dup [ 21] lit3 [ 22] eq [ 23] bra 30 [ 26] lit0 [ 27] skip 31 [ 30] lit4 [ 31] swap [ 32] drop The "answer" depends on the Discr value (first byte at object address), and is rounded up to 4 or 8 bytes. Signed-off-by: Mark Wielaard --- diff --git a/src/ChangeLog b/src/ChangeLog index eed8569de..8935022be 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2017-12-07 Mark Wielaard + + * readelf.c (print_ops): Update data pointer and print arguments + to DW_OP_call2 and DW_OP_call4 as DIE offsets. + 2017-11-29 Mark Wielaard * readelf.c (argp_options): Add "section-groups", 'g'. diff --git a/src/readelf.c b/src/readelf.c index 357c73e3f..ed21ef7ac 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4324,19 +4324,21 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call2: NEED (2); - printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n", + printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n", indent, "", (uintmax_t) offset, op_name, read_2ubyte_unaligned (dbg, data)); CONSUME (2); + data += 2; offset += 3; break; case DW_OP_call4: NEED (4); - printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n", + printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n", indent, "", (uintmax_t) offset, op_name, read_4ubyte_unaligned (dbg, data)); CONSUME (4); + data += 4; offset += 5; break; diff --git a/tests/ChangeLog b/tests/ChangeLog index cb0c977ff..fe6335944 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2017-12-07 Mark Wielaard + + * run-readelf-variant.sh: New test. + * testfile-ada-variant.bz2: New testfile. + * Makefile.am (TESTS): Add run-readelf-variant.sh. + (EXTRA_DISTS): Add run-readelf-variant.sh and + testfile-ada-variant.bz2. + 2017-11-29 Mark Wielaard * run-readelf-loc.sh: Adjust expected loc list output. diff --git a/tests/Makefile.am b/tests/Makefile.am index d5020547a..fca00727f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -110,6 +110,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \ run-test-archive64.sh run-readelf-vmcoreinfo.sh \ run-readelf-mixed-corenote.sh run-dwfllines.sh \ + run-readelf-variant.sh \ run-dwfl-report-elf-align.sh run-addr2line-test.sh \ run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \ run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \ @@ -264,6 +265,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfilebazdynppc64.bz2 testfilebazmdbppc64.bz2 \ testfilebazminppc64.bz2 testfilebazminppc64_pl.bz2 \ testfilebazminppc64_plr.bz2 testfilebaztabppc64.bz2 \ + run-readelf-variant.sh testfile-ada-variant.bz2 \ run-dwflsyms.sh \ run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \ run-low_high_pc.sh testfile_low_high_pc.bz2 \ diff --git a/tests/run-readelf-variant.sh b/tests/run-readelf-variant.sh new file mode 100755 index 000000000..dcc0d5e16 --- /dev/null +++ b/tests/run-readelf-variant.sh @@ -0,0 +1,89 @@ +#! /bin/sh +# Copyright (C) 2017 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 + +# Tests exprloc for an Ada record variants byte_size. + +# = pck.ads +# +# with System; +# +# package Pck is +# +# type One_To_Five is range 1 .. 5; +# +# type Rec (Discr : One_To_Five) is +# record +# case Discr is +# when 1 => Field1 : Integer; +# when 4 => null; +# when 3 => Field3 : Boolean; +# when 5 => null; +# when others => null; +# end case; +# end record; +# +# procedure Do_Nothing (A : System.Address); +# +# end Pck; + +# = pck.adb +# +# package body Pck is +# +# procedure Do_Nothing (A : System.Address) is +# begin +# null; +# end Do_Nothing; +# +# end Pck; + +# = foo.adb +# +# with Pck; use Pck; +# +# procedure Foo is +# +# R : Rec (1); +# +# begin +# Do_Nothing (R'Address); +# end Foo; + +# gnatmake -g -fgnat-encodings=minimal foo.adb -cargs + +testfiles testfile-ada-variant + +tempfiles testfile.temp testfile2.temp + +testrun ${abs_top_builddir}/src/readelf --debug-dump=info \ + testfile-ada-variant > testfile.temp + +grep -A6 byte_size testfile.temp | grep -A6 exprloc > testfile2.temp + +diff -u testfile2.temp - <