This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: [PATCHv2 1/2] Fix semantic error: empty struct
- From: James Bottomley <James dot Bottomley at HansenPartnership dot com>
- To: "Frank Ch. Eigler" <fche at redhat dot com>
- Cc: systemtap at sources dot redhat dot com
- Date: Tue, 08 Jul 2008 16:45:16 -0500
- Subject: Re: [PATCHv2 1/2] Fix semantic error: empty struct
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1215553519; bh=u9M4OV9h1AWuUiXVl2OqA+0jkx81dSoP2O94dYwhxB w=; l=6635; h=Subject:From:To:Cc:In-Reply-To:References: Content-Type:Date:Message-Id:Mime-Version: Content-Transfer-Encoding; b=QB89MF3Gn6NCWvHW1NtAM43KnB9JC8qZ4pMZb IieNHlWyX1VZBjOPLwprDzDhGI3S4I3nzRWXjs7OitpjZ81SO8WXMY9q1wxnH65LeCR mcmOb/+p1pvCmJ16Eb8mKGqDorIZSbx63Zcb74jGZoGRc2w2p/pFheX4TUOd29GcEBw =
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1215553517; bh=u9M4OV9h1AWuUiXVl2OqA+0jkx81dSoP2O94dYwhxB w=; l=6635; h=Subject:From:To:Cc:In-Reply-To:References: Content-Type:Date:Message-Id:Mime-Version: Content-Transfer-Encoding; b=pGrgSuS0h3kJql5TyNInPp9ET3MvBdcUdrobf VVleqRnlXBhXyYXJ4dTe2R/Nrv/fy00yl9x35908QKIsRWhcxLWDX9+ibOuDInlMgWi i6GEnSFQMN/C72iwT/zG7PX09asWepB44iLfoTrqs6ECFAZoy4YyVW1wrQpJfcB3CbI =
- References: <1215539073.3214.26.camel@localhost.localdomain> <y0mr6a4qm15.fsf@ton.toronto.redhat.com> <1215541804.3214.36.camel@localhost.localdomain> <20080708185716.GI9580@redhat.com>
On Tue, 2008-07-08 at 14:57 -0400, Frank Ch. Eigler wrote:
> Hi -
>
> > you need a global cache for resolution ... it's not tied to any local
> > class instance. For class dwflpp it probably doesn't matter, since that
> > class is effectively static (by its survival for a session) but
> > logically because the DW_AT_declaration resolution is global, so should
> > the cache that does it.
>
> .. except it's not actually global, in that the kernel is not the only
> code that will go through the dwarf family of probe processors -
> user-space dwarf files are coming its way soon. Plus, if in the
> future the systemtap frontend attempts distributed probing of multiple
> target systems concurrently, "global" will be even more local.
In that context its as global as a lot of the other static data in that
structure (like this_session) which would also have to be fixed to do a
multiple target system.
Regardless, it can become per instance: it will only screw up if dwflpp
moves to being short lived.
James
---
>From 9b86f86f9929671b0885d9df918d57895d8b611b Mon Sep 17 00:00:00 2001
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Date: Thu, 26 Jun 2008 13:53:39 -0500
Subject: Fix semantic error: empty struct
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 for later use with declarations.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
tapsets.cxx | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 93 insertions(+), 0 deletions(-)
diff --git a/tapsets.cxx b/tapsets.cxx
index c054d24..cdc14d6 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1,6 +1,7 @@
// tapset resolution
// Copyright (C) 2005-2008 Red Hat Inc.
// Copyright (C) 2005-2007 Intel Corporation.
+// Copyright (C) 2008 James.Bottomley@HansenPartnership.com
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
@@ -1157,6 +1158,47 @@ struct dwflpp
// -----------------------------------------------------------------
+ /* The global alias cache is used to resolve any DIE found in a
+ * module that is stubbed out with DW_AT_declaration with 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
+ */
+ cu_function_cache_t global_alias_cache;
+
+ static int global_alias_caching_callback(Dwarf_Die *die, void *arg)
+ {
+ dwflpp *dw = static_cast<struct dwflpp *>(arg);
+ const char *name = dwarf_diename(die);
+
+ if (!name)
+ return DWARF_CB_OK;
+
+ string structure_name = name;
+
+ if (!dwarf_hasattr(die, DW_AT_declaration) &&
+ dw->global_alias_cache.find(structure_name) ==
+ dw->global_alias_cache.end())
+ dw->global_alias_cache[structure_name] = *die;
+
+ return DWARF_CB_OK;
+ }
+
+ 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 +1211,16 @@ 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;
+
+ rc = iterate_over_globals(global_alias_caching_callback, this);
+ return rc;
+ }
bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno);
@@ -1834,6 +1886,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 +2577,37 @@ dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int linen
return false;
}
+/* 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 +3596,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.6