https://sourceware.org/bugzilla/show_bug.cgi?id=34872

            Bug ID: 34872
           Summary: readelf -wl: DW_LNS_const_add_pc ignores
                    maximum_operations_per_instruction
           Product: binutils
           Version: 2.48 (HEAD)
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: martin.mirchev at u dot nus.edu
  Target Milestone: ---

In display_debug_lines_raw() (readelf -wl / objdump --dwarf=rawline),
the DW_LNS_const_add_pc case tests

        if (linfo.li_max_ops_per_insn)

where every other address-advancing opcode in both the raw and the
decoded line printers tests "== 1".  li_max_ops_per_insn is never 0 at
this point (it is forced to 1 for DWARF < 4 and rejected when 0), so the
VLIW branch is dead: with maximum_operations_per_instruction > 1 the
raw dump advances the address by the whole operation advance and never
updates op_index.  readelf's own -wL (display_debug_lines_decoded, which
has "== 1") and elfutils get it right.

t.s (attached) is a DWARF 4 line program with
maximum_operations_per_instruction = 2 and min_inst_length = 1:
DW_LNS_const_add_pc, DW_LNS_copy, DW_LNE_end_sequence.  The operation
advance is (255 - 13) / 14 = 17, i.e. address 8, op_index 1.

$ gcc -c t.s -o t.o
$ readelf -wl t.o | grep Advance
  [0x00000025]  Advance PC by constant 17 to 0x11
$ readelf -wL t.o | grep t.c
t.c                                        1                 0x8[1]            
  x
t.c                                        -                 0x8[1]
$ eu-readelf --debug-dump=line t.o | grep 'by constant'
 [    25] advance address by constant 8 to 0x8, op_index to 1

t-control.s is the same with maximum_operations_per_instruction = 1;
there all three agree on 0x11.

Fix (patch attached, against master 0164fa7b33f):

--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -6311,7 +6311,7 @@ display_debug_lines_raw (struct dwarf_section *  section,

                  case DW_LNS_const_add_pc:
                    uladv = ((255 - linfo.li_opcode_base) /
linfo.li_line_range);
-                   if (linfo.li_max_ops_per_insn)
+                   if (linfo.li_max_ops_per_insn == 1)
                      {
                        uladv *= linfo.li_min_insn_length;
                        state_machine_regs.address += uladv;

With the patch, readelf -wl t.o prints
  [0x00000025]  Advance PC by constant 17 to 0x8[1]
and t-control.o is unchanged.  readelf -a -W --debug-dump=rawline,decodedline
output is byte-identical before and after the patch for 784 ELF files
(/usr/bin, system shared libraries, separate debug files, and the
binutils/bfd/libiberty objects of the build), all of which have
maximum_operations_per_instruction = 1.  I could not run the DejaGnu
testsuite here.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified
manually; the patch was manually reviewed.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to