]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
readelf: Fix advance_pc to use op_addr_advance, not just op_advance.
authorMark Wielaard <mark@klomp.org>
Mon, 16 Apr 2018 08:25:35 +0000 (10:25 +0200)
committerMark Wielaard <mark@klomp.org>
Mon, 16 Apr 2018 08:25:35 +0000 (10:25 +0200)
Found by John Mellor-Crummey.

The reason this bug wasn't found earlier is because gcc fixes
minimum_instr_len and max_ops_per_instr to 1 for all architectures
(in theory max_ops_per_instr could be overridden, but I didn't find
any architecture that does). And op_index always seems zero (it looks
like it is really only for special VLWI architectures).

So in all cases I saw it means that:

op_addr_advance = minimum_instr_len * ((op_index + op_advance)
                                       / max_ops_per_instr)
                = 1 * ((0 + op_advance) / 1)
                = op_advance

Completely masking the bug.

The libdw dwarf_getsrclines.c implementation does get this right.
Because it doesn't care about the data representation and so does
the calculation directly.

Signed-off-by: Mark Wielaard <mark@klomp.org>
src/ChangeLog
src/readelf.c

index 068c87b94fcb4d6fc9227f981454195f359e0a92..2d525e6d60abb1ce8b797baf840ffaf0208597ed 100644 (file)
@@ -1,3 +1,8 @@
+2018-04-16  Mark Wielaard  <mark@klomp.org>
+
+       * readelf.c (print_debug_line_section). In advance_pc, advance
+       using op_addr_advance, not op_advance.
+
 2018-04-14  Mark Wielaard  <mark@klomp.org>
 
        * readelf.c (attr_callback): Only show errors when not silent.
index 8c0ef6ca83163625693577f143d47c9b8afc9a11..45fc82657b8104a54f6352f6cf7462dd440c3a39 100644 (file)
@@ -6971,7 +6971,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       {
        op_addr_advance = minimum_instr_len * ((op_index + op_advance)
                                               / max_ops_per_instr);
-       address += op_advance;
+       address += op_addr_advance;
        show_op_index = (op_index > 0 ||
                         (op_index + op_advance) % max_ops_per_instr > 0);
        op_index = (op_index + op_advance) % max_ops_per_instr;