Fix: flt.lttng-utils.debug-info: Error in src line reporting
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Thu, 28 Mar 2019 22:20:52 +0000 (18:20 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 2 May 2019 04:09:19 +0000 (00:09 -0400)
Issue
=====
A `debug-info` component does not print the `src` field of a tracepoint
properly when tracepoint is within a for loop.

  #include "tp.h"
  int main(int argc, char *argv[])
  {
      tracepoint(my_app, empty);
      for(int i = 0; i < 1; i++) {
          tracepoint(my_app, empty);
      }
      return 0;
  }

The problem derives from the DWARF information generated by the
compiler. The compiler may place the DWARF content of the for loop in
`DW_TAG_lexical_block` which the current `debug-info` design doesn't
expect.

Here is a summarized version of DWARF tree containing the first
tracepoint in the code above:
  DW_TAG_subprogram
    DW_TAG_inlined_subroutine
      /* tracepoint callsite info */

Here is a summarized version of the DWARF tree containing the tracepoint
in the for loop:
  DW_TAG_subprogram
    DW_TAG_lexical_block
      DW_TAG_inlined_subroutine
       /* tracepoint callsite info */

The current implementation doesn't expect the presence of a
`DW_TAG_lexical_block` entry as child of the `DW_TAG_inlined_subroutine`
entry and won't look any further down that branch to find the source
information for the current tracepoint. This results in the component
not finding the line number for such callsite and thus leaving the `src`
field empty. Also, on some occasions, the `src` field would contain the
tracepoint definition location (e.g. "tp.h:12") rather then the actual
callsite of that tracepoint.

Solution
========
When iterating over the Debugging Information Entries, if the current
entry contains the address to resolve _but_ is not a of the type
`DW_TAG_inlined_subroutine` try to iterate over the children of that
entry.

Known drawbacks
===============
None.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
plugins/lttng-utils/bin-info.c
plugins/lttng-utils/dwarf.c
plugins/lttng-utils/dwarf.h

index c810f8c6f8e738bcdf7ba57218b4d71169be95e8..c3e16cec9b97c3ff38ec5c8315f4acc548f27360 100644 (file)
@@ -1218,22 +1218,37 @@ int bin_info_child_die_has_address(struct bt_dwarf_die *die, uint64_t addr, bool
        }
 
        do {
-               int tag;
-
-               ret = bt_dwarf_die_get_tag(die, &tag);
+               ret = bt_dwarf_die_contains_addr(die, addr, &_contains);
                if (ret) {
                        goto error;
                }
 
-               if (tag == DW_TAG_inlined_subroutine) {
-                       ret = bt_dwarf_die_contains_addr(die, addr, &_contains);
+               if (_contains) {
+                       /*
+                        * The address is within the range of the current DIE
+                        * or its children.
+                        */
+                       int tag;
+
+                       ret = bt_dwarf_die_get_tag(die, &tag);
                        if (ret) {
                                goto error;
                        }
 
-                       if (_contains) {
+                       if (tag == DW_TAG_inlined_subroutine) {
+                               /* Found the tracepoint. */
                                goto end;
                        }
+
+                       if (bt_dwarf_die_has_children(die)) {
+                               /*
+                                * Look for the address in the children DIEs.
+                                */
+                               ret = bt_dwarf_die_child(die);
+                               if (ret) {
+                                       goto error;
+                               }
+                       }
                }
        } while (bt_dwarf_die_next(die) == 0);
 
index 3c7388a57679d8af953cf1b28649a597a58a6400..534d2883bd9f48d5333512135897d41da2c107c5 100644 (file)
@@ -131,6 +131,12 @@ void bt_dwarf_die_destroy(struct bt_dwarf_die *die)
        g_free(die);
 }
 
+BT_HIDDEN
+int bt_dwarf_die_has_children(struct bt_dwarf_die *die)
+{
+       return dwarf_haschildren(die->dwarf_die);
+}
+
 BT_HIDDEN
 int bt_dwarf_die_child(struct bt_dwarf_die *die)
 {
index c3d56b78cef36f5e7b1a7c9739de885301d46192..707431f9254c1aa79dc6b0f84d5b64c3c0c52b1f 100644 (file)
@@ -119,6 +119,15 @@ struct bt_dwarf_die *bt_dwarf_die_create(struct bt_dwarf_cu *cu);
 BT_HIDDEN
 void bt_dwarf_die_destroy(struct bt_dwarf_die *die);
 
+/**
+ * Indicates if the debug information entry `die` has children DIEs.
+ *
+ * @param die  bt_dwarf_die instance
+ * @returns    0 if the die no child, 1 otherwise
+ */
+BT_HIDDEN
+int bt_dwarf_die_has_children(struct bt_dwarf_die *die);
+
 /**
  * Advance the debug information entry `die` to its first child, if
  * any.
This page took 0.027631 seconds and 5 git commands to generate.