This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCHv2 1/2] Fix semantic error: empty struct
- From: James Bottomley <James dot Bottomley at HansenPartnership dot com>
- To: systemtap at sourceware dot org
- Date: Tue, 08 Jul 2008 12:44:33 -0500
- Subject: [PATCHv2 1/2] Fix semantic error: empty struct
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1215539075; bh=JbSUHkkJ8Z6EVDyeYfEMDsYJdd3seWoovZ3LfB3iRi E=; l=5633; h=Subject:From:To:Content-Type:Date:Message-Id: Mime-Version:Content-Transfer-Encoding; b=DZC+q3XdKjkROOr0WZRxtzOP 7TjIYRZEs/q3i/hlqQhDAoapi7Ld/ObmqYpZ8U0JGsgkwGrIqlV8B1ls7d646jYJ/tF FTSZHDYyO1GEt9Bj7osPFEoyf0TzO9EOk/3FdHfHT7tqD2/DnfQH9BZeoR2pDgyKPuB M6VlACnoeQCls=
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=2007; t=1215539073; bh=JbSUHkkJ8Z6EVDyeYfEMDsYJdd3seWoovZ3LfB3iRi E=; l=5633; h=Subject:From:To:Content-Type:Date:Message-Id: Mime-Version:Content-Transfer-Encoding; b=CGoD24zUV0OuCLd0BxSEmalW wC0uijQryCqB9H8puDJyrWprs7CuL3rRcPoC1P950Fy9dFTTO5sQTnjDH3FcJXH/qcQ /TuiuLxk/Mzxps6ZS7FbtBpiCyp0h1aqYA/6tbdM97VrN9fyW3xJdPVaiPnS2EWZmfc d4Q6S9lh1zJBs=
I updated this and dumped the two pass resolution because it was causing
unexpected failures.
James
---
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 | 94
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/tapsets.cxx b/tapsets.cxx
index c054d24..6c66edd 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,46 @@ 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
+ */
+ static cu_function_cache_t global_alias_cache;
+
+ static int global_alias_caching_callback(Dwarf_Die *die, void *arg)
+ {
+ const char *name = dwarf_diename(die);
+
+ if (!name)
+ return DWARF_CB_OK;
+
+ string structure_name = name;
+
+ if (!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 +1210,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, NULL);
+ return rc;
+ }
bool has_single_line_record (dwarf_query * q, char const * srcfile,
int lineno);
@@ -1834,6 +1885,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 +2576,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 +3597,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