This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCH] Fix sematic error: empty struct
- From: James Bottomley <James dot Bottomley at HansenPartnership dot com>
- To: systemtap at sourceware dot org
- Date: Thu, 26 Jun 2008 13:59:10 -0500
- Subject: [PATCH] Fix sematic error: empty struct
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1214506752; bh=PyITZQHS4X7/LUFle6a8petDsI1VYWRtAHx1r2Sm6t Q=; l=5613; h=Subject:From:To:Content-Type:Date:Message-Id: Mime-Version:Content-Transfer-Encoding; b=H1IoWN8/BTBxfsQKFfm0dvrU u0HHI5i+NiBuLUt7IOxiDChmAtzhAak2ipE7iPIh7FBP0SyyczfqiywDXteIXGWTL0D 52gO233k2rOyseFIaq69HFJU+mUTpJUq+0NdumT5uzC2T+0r2oJQ9uinwgEKpchnvYn /Kxuv6DNKrKhk=
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1214506751; bh=PyITZQHS4X7/LUFle6a8petDsI1VYWRtAHx1r2Sm6t Q=; l=5613; h=Subject:From:To:Content-Type:Date:Message-Id: Mime-Version:Content-Transfer-Encoding; b=Q7Gfj0IDwIKiuna6wchf6Ix6 bhvQApriEWsnuyUdVXaNNdnU85BZ+vOfQjAbZKhLyJHj8TffC0o+/oi4RrfEEjtVwq6 cF+BBZoFs90tdtaZfyIsrvVEG63qisJg4P0donl8rW73fpV833FMFBuuUDPPFzG8sdM uX+K67YQIIKxM=
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