* [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).