Mark Wielaard faac41
commit 434c7524413a8a47ae40e4b141f5821eabc506b7
Mark Wielaard faac41
Author: iraisr <iraisr@a5019735-40e9-0310-863c-91ae7b9d1cf9>
Mark Wielaard faac41
Date:   Fri Dec 4 13:14:10 2015 +0000
Mark Wielaard faac41
Mark Wielaard faac41
    Dwarf line info reader now correctly interprets 'is_stmt' register
Mark Wielaard faac41
    
Mark Wielaard faac41
    Line numbers should correctly reflect all instructions belonging to a source line,
Mark Wielaard faac41
    regardless of is_stmt value. Previously only instructions covered by
Mark Wielaard faac41
    'is_stmt = 1' were attributed to a source line.
Mark Wielaard faac41
    
Mark Wielaard faac41
    Fixes BZ#356044
Mark Wielaard faac41
    
Mark Wielaard faac41
    
Mark Wielaard faac41
    git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15741 a5019735-40e9-0310-863c-91ae7b9d1cf9
Mark Wielaard faac41
Mark Wielaard faac41
diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
Mark Wielaard faac41
index 88d49e9..a95bb3d 100644
Mark Wielaard faac41
--- a/coregrind/m_debuginfo/readdwarf.c
Mark Wielaard faac41
+++ b/coregrind/m_debuginfo/readdwarf.c
Mark Wielaard faac41
@@ -91,7 +91,6 @@ typedef struct
Mark Wielaard faac41
   ULong  li_header_length;
Mark Wielaard faac41
   UChar  li_min_insn_length;
Mark Wielaard faac41
   UChar  li_max_ops_per_insn;
Mark Wielaard faac41
-  UChar  li_default_is_stmt;
Mark Wielaard faac41
   Int    li_line_base;
Mark Wielaard faac41
   UChar  li_line_range;
Mark Wielaard faac41
   UChar  li_opcode_base;
Mark Wielaard faac41
@@ -150,7 +149,6 @@ typedef struct
Mark Wielaard faac41
   UInt  file;
Mark Wielaard faac41
   UInt  line;
Mark Wielaard faac41
   UInt  column;
Mark Wielaard faac41
-  Int   is_stmt;
Mark Wielaard faac41
   Int   basic_block;
Mark Wielaard faac41
   UChar end_sequence;
Mark Wielaard faac41
 } LineSMR;
Mark Wielaard faac41
@@ -230,7 +228,7 @@ ULong read_initial_length_field ( DiCursor p_img, /*OUT*/Bool* is64 )
Mark Wielaard faac41
 static LineSMR state_machine_regs;
Mark Wielaard faac41
 
Mark Wielaard faac41
 static 
Mark Wielaard faac41
-void reset_state_machine ( Int is_stmt )
Mark Wielaard faac41
+void reset_state_machine ( void )
Mark Wielaard faac41
 {
Mark Wielaard faac41
    if (0) VG_(printf)("smr.a := %p (reset)\n", NULL );
Mark Wielaard faac41
    state_machine_regs.last_address = 0;
Mark Wielaard faac41
@@ -240,7 +238,6 @@ void reset_state_machine ( Int is_stmt )
Mark Wielaard faac41
    state_machine_regs.file = 1;
Mark Wielaard faac41
    state_machine_regs.line = 1;
Mark Wielaard faac41
    state_machine_regs.column = 0;
Mark Wielaard faac41
-   state_machine_regs.is_stmt = is_stmt;
Mark Wielaard faac41
    state_machine_regs.basic_block = 0;
Mark Wielaard faac41
    state_machine_regs.end_sequence = 0;
Mark Wielaard faac41
 }
Mark Wielaard faac41
@@ -253,7 +250,7 @@ void reset_state_machine ( Int is_stmt )
Mark Wielaard faac41
 static 
Mark Wielaard faac41
 void process_extended_line_op( struct _DebugInfo* di,
Mark Wielaard faac41
                                XArray* fndn_ix_xa,
Mark Wielaard faac41
-                               DiCursor* data, Int is_stmt)
Mark Wielaard faac41
+                               DiCursor* data )
Mark Wielaard faac41
 {
Mark Wielaard faac41
    UInt len = step_leb128U(data);
Mark Wielaard faac41
    if (len == 0) {
Mark Wielaard faac41
@@ -275,19 +272,17 @@ void process_extended_line_op( struct _DebugInfo* di,
Mark Wielaard faac41
             reset_state_machine below */
Mark Wielaard faac41
          state_machine_regs.end_sequence = 1; 
Mark Wielaard faac41
 
Mark Wielaard faac41
-         if (state_machine_regs.is_stmt) {
Mark Wielaard faac41
-            if (state_machine_regs.last_address) {
Mark Wielaard faac41
-               ML_(addLineInfo) (
Mark Wielaard faac41
-                  di,
Mark Wielaard faac41
-                  safe_fndn_ix (fndn_ix_xa,
Mark Wielaard faac41
-                                state_machine_regs.last_file),
Mark Wielaard faac41
-                  di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
-                  di->text_debug_bias + state_machine_regs.address, 
Mark Wielaard faac41
-                  state_machine_regs.last_line, 0
Mark Wielaard faac41
-               );
Mark Wielaard faac41
-            }
Mark Wielaard faac41
+         if (state_machine_regs.last_address) {
Mark Wielaard faac41
+            ML_(addLineInfo)(
Mark Wielaard faac41
+               di,
Mark Wielaard faac41
+               safe_fndn_ix(fndn_ix_xa,
Mark Wielaard faac41
+                            state_machine_regs.last_file),
Mark Wielaard faac41
+               di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
+               di->text_debug_bias + state_machine_regs.address, 
Mark Wielaard faac41
+               state_machine_regs.last_line, 0
Mark Wielaard faac41
+            );
Mark Wielaard faac41
          }
Mark Wielaard faac41
-         reset_state_machine (is_stmt);
Mark Wielaard faac41
+         reset_state_machine();
Mark Wielaard faac41
          if (di->ddump_line)
Mark Wielaard faac41
             VG_(printf)("  Extended opcode %d: End of Sequence\n\n", 
Mark Wielaard faac41
                         (Int)op_code);
Mark Wielaard faac41
@@ -446,29 +441,9 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
Mark Wielaard faac41
       info.li_max_ops_per_insn = 1;
Mark Wielaard faac41
    }
Mark Wielaard faac41
 
Mark Wielaard faac41
-   info.li_default_is_stmt = ML_(cur_step_UChar)(&external);
Mark Wielaard faac41
-   if (di->ddump_line)
Mark Wielaard faac41
-      VG_(printf)("  Initial value of 'is_stmt':  %d\n", 
Mark Wielaard faac41
-                  (Int)info.li_default_is_stmt);
Mark Wielaard faac41
-
Mark Wielaard faac41
-   /* Josef Weidendorfer (20021021) writes:
Mark Wielaard faac41
-
Mark Wielaard faac41
-      It seems to me that the Intel Fortran compiler generates bad
Mark Wielaard faac41
-      DWARF2 line info code: It sets "is_stmt" of the state machine in
Mark Wielaard faac41
-      the line info reader to be always false. Thus, there is never
Mark Wielaard faac41
-      a statement boundary generated and therefore never an instruction
Mark Wielaard faac41
-      range/line number mapping generated for valgrind.
Mark Wielaard faac41
-
Mark Wielaard faac41
-      Please have a look at the DWARF2 specification, Ch. 6.2
Mark Wielaard faac41
-      (x86.ddj.com/ftp/manuals/tools/dwarf.pdf).  Perhaps I understand
Mark Wielaard faac41
-      this wrong, but I don't think so.
Mark Wielaard faac41
-
Mark Wielaard faac41
-      I just had a look at the GDB DWARF2 reader...  They completely
Mark Wielaard faac41
-      ignore "is_stmt" when recording line info ;-) That's the reason
Mark Wielaard faac41
-      "objdump -S" works on files from the intel fortran compiler.
Mark Wielaard faac41
-
Mark Wielaard faac41
-      Therefore: */
Mark Wielaard faac41
-   info.li_default_is_stmt = True; 
Mark Wielaard faac41
+   /* Register is_stmt is not tracked as we are interested only
Mark Wielaard faac41
+      in pc -> line info mapping and not other debugger features. */
Mark Wielaard faac41
+   /* default_is_stmt = */ ML_(cur_step_UChar)(&external);
Mark Wielaard faac41
 
Mark Wielaard faac41
    /* JRS: changed (UInt*) to (UChar*) */
Mark Wielaard faac41
    info.li_line_base = ML_(cur_step_UChar)(&external);
Mark Wielaard faac41
@@ -495,7 +470,7 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
Mark Wielaard faac41
    DiCursor end_of_sequence
Mark Wielaard faac41
      = ML_(cur_plus)(data, info.li_length + (is64 ? 12 : 4));
Mark Wielaard faac41
 
Mark Wielaard faac41
-   reset_state_machine (info.li_default_is_stmt);
Mark Wielaard faac41
+   reset_state_machine();
Mark Wielaard faac41
 
Mark Wielaard faac41
    /* Read the contents of the Opcodes table.  */
Mark Wielaard faac41
    DiCursor standard_opcodes = external;
Mark Wielaard faac41
@@ -632,55 +607,49 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
Mark Wielaard faac41
                         (Int)op_code, advAddr, state_machine_regs.address,
Mark Wielaard faac41
                         (Int)adv, (Int)state_machine_regs.line );
Mark Wielaard faac41
 
Mark Wielaard faac41
-         if (state_machine_regs.is_stmt) {
Mark Wielaard faac41
-            /* only add a statement if there was a previous boundary */
Mark Wielaard faac41
-            if (state_machine_regs.last_address) {
Mark Wielaard faac41
-               ML_(addLineInfo)(
Mark Wielaard faac41
-                  di,
Mark Wielaard faac41
-                  safe_fndn_ix (fndn_ix_xa,
Mark Wielaard faac41
-                                state_machine_regs.last_file),
Mark Wielaard faac41
-                  di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
-                  di->text_debug_bias + state_machine_regs.address, 
Mark Wielaard faac41
-                  state_machine_regs.last_line, 
Mark Wielaard faac41
-                  0
Mark Wielaard faac41
-               );
Mark Wielaard faac41
-            }
Mark Wielaard faac41
-            state_machine_regs.last_address = state_machine_regs.address;
Mark Wielaard faac41
-            state_machine_regs.last_file = state_machine_regs.file;
Mark Wielaard faac41
-            state_machine_regs.last_line = state_machine_regs.line;
Mark Wielaard faac41
+         /* only add a statement if there was a previous boundary */
Mark Wielaard faac41
+         if (state_machine_regs.last_address) {
Mark Wielaard faac41
+            ML_(addLineInfo)(
Mark Wielaard faac41
+               di,
Mark Wielaard faac41
+               safe_fndn_ix(fndn_ix_xa,
Mark Wielaard faac41
+                            state_machine_regs.last_file),
Mark Wielaard faac41
+               di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
+               di->text_debug_bias + state_machine_regs.address, 
Mark Wielaard faac41
+               state_machine_regs.last_line, 
Mark Wielaard faac41
+               0
Mark Wielaard faac41
+            );
Mark Wielaard faac41
          }
Mark Wielaard faac41
+         state_machine_regs.last_address = state_machine_regs.address;
Mark Wielaard faac41
+         state_machine_regs.last_file = state_machine_regs.file;
Mark Wielaard faac41
+         state_machine_regs.last_line = state_machine_regs.line;
Mark Wielaard faac41
       }
Mark Wielaard faac41
 
Mark Wielaard faac41
       else { /* ! (op_code >= info.li_opcode_base) */
Mark Wielaard faac41
 
Mark Wielaard faac41
       switch (op_code) {
Mark Wielaard faac41
          case DW_LNS_extended_op:
Mark Wielaard faac41
-            process_extended_line_op (
Mark Wielaard faac41
-                       di, fndn_ix_xa,
Mark Wielaard faac41
-                       &data, info.li_default_is_stmt);
Mark Wielaard faac41
+            process_extended_line_op(di, fndn_ix_xa, &data);
Mark Wielaard faac41
             break;
Mark Wielaard faac41
 
Mark Wielaard faac41
          case DW_LNS_copy:
Mark Wielaard faac41
             if (0) VG_(printf)("1002: di->o %#lx, smr.a %#lx\n",
Mark Wielaard faac41
                                (UWord)di->text_debug_bias,
Mark Wielaard faac41
                                state_machine_regs.address );
Mark Wielaard faac41
-            if (state_machine_regs.is_stmt) {
Mark Wielaard faac41
-               /* only add a statement if there was a previous boundary */
Mark Wielaard faac41
-               if (state_machine_regs.last_address) {
Mark Wielaard faac41
-                  ML_(addLineInfo)(
Mark Wielaard faac41
-                     di,
Mark Wielaard faac41
-                     safe_fndn_ix (fndn_ix_xa,
Mark Wielaard faac41
-                                   state_machine_regs.last_file), 
Mark Wielaard faac41
-                     di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
-                     di->text_debug_bias + state_machine_regs.address,
Mark Wielaard faac41
-                     state_machine_regs.last_line, 
Mark Wielaard faac41
-                     0
Mark Wielaard faac41
-                  );
Mark Wielaard faac41
-               }
Mark Wielaard faac41
-               state_machine_regs.last_address = state_machine_regs.address;
Mark Wielaard faac41
-               state_machine_regs.last_file = state_machine_regs.file;
Mark Wielaard faac41
-               state_machine_regs.last_line = state_machine_regs.line;
Mark Wielaard faac41
+            /* only add a statement if there was a previous boundary */
Mark Wielaard faac41
+            if (state_machine_regs.last_address) {
Mark Wielaard faac41
+               ML_(addLineInfo)(
Mark Wielaard faac41
+                  di,
Mark Wielaard faac41
+                  safe_fndn_ix(fndn_ix_xa,
Mark Wielaard faac41
+                               state_machine_regs.last_file), 
Mark Wielaard faac41
+                  di->text_debug_bias + state_machine_regs.last_address, 
Mark Wielaard faac41
+                  di->text_debug_bias + state_machine_regs.address,
Mark Wielaard faac41
+                  state_machine_regs.last_line, 
Mark Wielaard faac41
+                  0
Mark Wielaard faac41
+               );
Mark Wielaard faac41
             }
Mark Wielaard faac41
+            state_machine_regs.last_address = state_machine_regs.address;
Mark Wielaard faac41
+            state_machine_regs.last_file = state_machine_regs.file;
Mark Wielaard faac41
+            state_machine_regs.last_line = state_machine_regs.line;
Mark Wielaard faac41
             state_machine_regs.basic_block = 0; /* JRS added */
Mark Wielaard faac41
             if (di->ddump_line)
Mark Wielaard faac41
                VG_(printf)("  Copy\n");
Mark Wielaard faac41
@@ -719,9 +688,6 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
Mark Wielaard faac41
             break;
Mark Wielaard faac41
          }
Mark Wielaard faac41
          case DW_LNS_negate_stmt: {
Mark Wielaard faac41
-            Int adv = state_machine_regs.is_stmt;
Mark Wielaard faac41
-            adv = ! adv;
Mark Wielaard faac41
-            state_machine_regs.is_stmt = adv;
Mark Wielaard faac41
             if (di->ddump_line)
Mark Wielaard faac41
                VG_(printf)("  DWARF2-line: negate_stmt\n");
Mark Wielaard faac41
             break;
Mark Wielaard faac41
diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
Mark Wielaard faac41
index 7b2e26a..e6a9856 100644
Mark Wielaard faac41
--- a/coregrind/m_debuginfo/storage.c
Mark Wielaard faac41
+++ b/coregrind/m_debuginfo/storage.c
Mark Wielaard faac41
@@ -419,6 +419,21 @@ static void addLoc ( struct _DebugInfo* di, DiLoc* loc, UInt fndn_ix )
Mark Wielaard faac41
    /* Zero-sized locs should have been ignored earlier */
Mark Wielaard faac41
    vg_assert(loc->size > 0);
Mark Wielaard faac41
 
Mark Wielaard faac41
+   /* Check if the last entry has adjacent range for the same line. */
Mark Wielaard faac41
+   if (di->loctab_used > 0) {
Mark Wielaard faac41
+      DiLoc *previous = &di->loctab[di->loctab_used - 1];
Mark Wielaard faac41
+      if ((previous->lineno == loc->lineno)
Mark Wielaard faac41
+          && (previous->addr + previous->size == loc->addr)) {
Mark Wielaard faac41
+         if (0)
Mark Wielaard faac41
+            VG_(printf)("Merging previous: addr %#lx, size %d, line %d, "
Mark Wielaard faac41
+                        "with current: addr %#lx, size %d, line %d.\n",
Mark Wielaard faac41
+                        previous->addr, previous->size, previous->lineno,
Mark Wielaard faac41
+                        loc->addr, loc->size, loc->lineno);
Mark Wielaard faac41
+         previous->size += loc->size;
Mark Wielaard faac41
+         return;
Mark Wielaard faac41
+      }
Mark Wielaard faac41
+   }
Mark Wielaard faac41
+
Mark Wielaard faac41
    if (di->loctab_used == di->loctab_size) {
Mark Wielaard faac41
       UInt   new_sz;
Mark Wielaard faac41
       DiLoc* new_loctab;