public inbox for systemtap@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix sematic error: empty struct
@ 2008-06-27  0:18 James Bottomley
       [not found] ` <y0miqvwastl.fsf@ton.toronto.redhat.com>
  0 siblings, 1 reply; 4+ messages in thread
From: James Bottomley @ 2008-06-27  0:18 UTC (permalink / raw)
  To: systemtap

This error occurs when a particular module is in a file that never
used the elements of the structure (so it ends up being stubbed out
with DW_AT_declaration).  You can see this by trying to probe in
libata:ata_qc_issue:

probe module("libata").function("ata_qc_issue") {
      if ($qc->scsicmd->device->host->host_no  != 3 &&
          $qc->scsicmd->device->id != 0) {
      	 next;
      }
      ...
}

The fix is to collect a list of all such declarations globally and
allow them to be referred back to a defining instance of the structure
or union.  The patch implements this by having a global_alias_cache
which is used to cache defining DIEs for all structures or unions that
turn up wiht declarations elsewhere in the code.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 tapsets.cxx |  105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/tapsets.cxx b/tapsets.cxx
index 38b075d..800835a 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1157,6 +1157,52 @@ struct dwflpp
 
   // -----------------------------------------------------------------
 
+  /* The global alias cache is used to resolve any DIE found in a
+   * module that is stubbed out with DW_AT_declaration for a defining
+   * DIE found in a different module.  The current assumption is that
+   * this only applies to structures and unions, which have a global
+   * namespace (it deliberately only traverses program scope), so this
+   * cache is indexed by name.  If other declaration lookups were
+   * added to it, it would have to be indexed by name and tag
+   */
+  static cu_function_cache_t global_alias_cache;
+
+  static int global_alias_caching_callback(Dwarf_Die *die, void *arg)
+  {
+    int pass = (int)arg;
+    const char *name = dwarf_diename(die);
+
+    if (!name)
+      return DWARF_CB_OK;
+
+    string structure_name = name;
+
+    // add new declarations (don't replace: they might be resolved)
+    if (pass == 0 && dwarf_hasattr(die, DW_AT_declaration) &&
+	global_alias_cache.find(structure_name) ==
+	global_alias_cache.end())
+	global_alias_cache[structure_name] = *die;
+    else if (pass == 1 && !dwarf_hasattr(die, DW_AT_declaration) &&
+	     global_alias_cache.find(structure_name) !=
+	     global_alias_cache.end())
+	global_alias_cache[structure_name] = *die;
+
+    return DWARF_CB_OK;
+  }
+
+  static Dwarf_Die *declaration_resolve(Dwarf_Die *die)
+  {
+    const char *name = dwarf_diename(die);
+
+    if (!name)
+      return NULL;
+
+    if (global_alias_cache.find(name) == global_alias_cache.end())
+      return NULL;
+
+    return &global_alias_cache[name];
+  }
+
   mod_cu_function_cache_t cu_function_cache;
 
   static int cu_function_caching_callback (Dwarf_Die* func, void *arg)
@@ -1169,6 +1215,22 @@ struct dwflpp
 
   int iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg),
                               void * data);
+  int iterate_over_globals (int (* callback)(Dwarf_Die *, void *),
+				 void * data);
+
+  int update_alias_cache(void)
+  {
+    int rc;
+
+    // do a two pass iteration; pass 0 looks for declarations
+    rc = iterate_over_globals(global_alias_caching_callback, (void *)0);
+    if (rc != DWARF_CB_OK)
+      return rc;
+    // pass 1 takes found declarations and points them to defining DIEs
+    rc = iterate_over_globals(global_alias_caching_callback, (void *)1);
+
+    return rc;
+  }
 
   bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno);
 
@@ -1834,6 +1896,14 @@ struct dwflpp
 	  case DW_TAG_structure_type:
 	  case DW_TAG_union_type:
 	    struct_die = *die;
+	    if (dwarf_hasattr(die, DW_AT_declaration))
+	      {
+		Dwarf_Die *tmpdie = dwflpp::declaration_resolve(die);
+		if (tmpdie == NULL)
+		  throw semantic_error ("unresolved struct "
+					+ string (dwarf_diename_integrate (die) ?: "<anonymous>"));
+		*die_mem = *tmpdie;
+	      }
 	    switch (dwarf_child (die, die_mem))
 	      {
 	      case 1:		/* No children.  */
@@ -2517,6 +2587,39 @@ dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int linen
     return false;
   }
 
+cu_function_cache_t dwflpp::global_alias_cache;
+
+/* This basically only goes one level down from the compile unit so it
+ * only picks up top level stuff (i.e. nothing in a lower scope) */
+int
+dwflpp::iterate_over_globals (int (* callback)(Dwarf_Die *, void *),
+				   void * data)
+{
+  int rc = DWARF_CB_OK;
+  Dwarf_Die die;
+
+  assert (module);
+  assert (cu);
+  assert (dwarf_tag(cu) == DW_TAG_compile_unit);
+
+  if (dwarf_child(cu, &die) != 0)
+    return rc;
+
+  do {
+    /* We're only currently looking for structures and unions,
+     * although other types of declarations exist */
+    if (dwarf_tag(&die) != DW_TAG_structure_type &&
+	dwarf_tag(&die) != DW_TAG_union_type)
+      continue;
+
+    rc = (*callback)(&die, data);
+    if (rc != DWARF_CB_OK)
+      break;
+
+  } while (dwarf_siblingof(&die, &die) == 0);
+
+  return rc;
+}
 
 int
 dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg),
@@ -3505,6 +3608,8 @@ query_cu (Dwarf_Die * cudie, void * arg)
     {
       q->dw.focus_on_cu (cudie);
 
+      q->dw.update_alias_cache();
+
       if (false && q->sess.verbose>2)
         clog << "focused on CU '" << q->dw.cu_name
              << "', in module '" << q->dw.module_name << "'\n";
-- 
1.5.5.4



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix sematic error: empty struct
       [not found]   ` <1214576542.3394.5.camel@localhost.localdomain>
@ 2008-06-27 20:50     ` Frank Ch. Eigler
  2008-06-27 20:50       ` James Bottomley
  0 siblings, 1 reply; 4+ messages in thread
From: Frank Ch. Eigler @ 2008-06-27 20:50 UTC (permalink / raw)
  To: James Bottomley; +Cc: systemtap

Hi -

By the way, for the $qc->scsi.... expression problem in the first
case, did you consider/try using embedded-C code to do the pointer
dereferencing?

as in:

%{
#include "linux/scsi-whatever."
%}
function filter_p:long (ptr:long)  %{ 
   struct scsi_device* q = (struct scsi_device*) THIS->ptr;
   THIS->__retvalue = (q->scsicmd->.... & ... );
%}

probe module("libata").function("ata_qc_issue") {
   if (filter_p ($qc)) next;
}


- FChE

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix sematic error: empty struct
  2008-06-27 20:50       ` James Bottomley
@ 2008-06-27 20:50         ` Frank Ch. Eigler
  0 siblings, 0 replies; 4+ messages in thread
From: Frank Ch. Eigler @ 2008-06-27 20:50 UTC (permalink / raw)
  To: James Bottomley; +Cc: systemtap

Hi -

> > By the way, for the $qc->scsi.... expression problem in the first
> > case, did you consider/try using embedded-C code to do the pointer
> > dereferencing?
> 
> Yes, but it's a completely awful solution ... 

It is obviously undesirable, and is never prescribed for naive users,
but I thought you might find it useful.

> it's also what led to the crashes on FC9.

(Do you know how?)

> If a structure is resolvable it should be usable via the systemtap
> language.  [...]

Indeed, and we're working on that.  Your patch will be a step in that
direction.


- FChE

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] Fix sematic error: empty struct
  2008-06-27 20:50     ` Frank Ch. Eigler
@ 2008-06-27 20:50       ` James Bottomley
  2008-06-27 20:50         ` Frank Ch. Eigler
  0 siblings, 1 reply; 4+ messages in thread
From: James Bottomley @ 2008-06-27 20:50 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: systemtap

On Fri, 2008-06-27 at 14:13 -0400, Frank Ch. Eigler wrote:
> Hi -
> 
> By the way, for the $qc->scsi.... expression problem in the first
> case, did you consider/try using embedded-C code to do the pointer
> dereferencing?

Yes, but it's a completely awful solution ... it's also what led to the
crashes on FC9.

If a structure is resolvable it should be usable via the systemtap
language.  Users complain enough about the interface anyway, telling
them they have to use ad hoc C fragment constructions in certain cases
they won't even be able to distinguish until they run into them is a
recipe for usability problems.

> as in:
> 
> %{
> #include "linux/scsi-whatever."
> %}
> function filter_p:long (ptr:long)  %{ 
>    struct scsi_device* q = (struct scsi_device*) THIS->ptr;

Actually, it has to be

struct scsi_device* q = (struct scsi_device*)(unsigned long) THIS->ptr;

because of systemtap and C on x86 differning on the sizeof long.

>    THIS->__retvalue = (q->scsicmd->.... & ... );
> %}
> 
> probe module("libata").function("ata_qc_issue") {
>    if (filter_p ($qc)) next;
> }

James


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-06-27 20:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-27  0:18 [PATCH] Fix sematic error: empty struct James Bottomley
     [not found] ` <y0miqvwastl.fsf@ton.toronto.redhat.com>
     [not found]   ` <1214576542.3394.5.camel@localhost.localdomain>
2008-06-27 20:50     ` Frank Ch. Eigler
2008-06-27 20:50       ` James Bottomley
2008-06-27 20:50         ` Frank Ch. Eigler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).