summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorJames Bottomley <James dot Bottomley at HansenPartnership dot com>2008-07-08 16:45:16 -0500
committerFrank Ch. Eigler <fche@elastic.org>2008-07-09 07:09:15 -0400
commit0b8f65798e0b454ccaab1d93925c3e034d4f5624 (patch)
treec55c5fe88afa3ffc5beddee997e19fa582a057ff /tapsets.cxx
parentd99a656a615dd78773316b7ac3972f3f1bcd5fca (diff)
downloadsystemtap-steved-0b8f65798e0b454ccaab1d93925c3e034d4f5624.tar.gz
systemtap-steved-0b8f65798e0b454ccaab1d93925c3e034d4f5624.tar.xz
systemtap-steved-0b8f65798e0b454ccaab1d93925c3e034d4f5624.zip
Fix semantic error: empty struct
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
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx93
1 files changed, 93 insertions, 0 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index c054d24c..cdc14d61 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";