diff options
author | James Bottomley <James dot Bottomley at HansenPartnership dot com> | 2008-07-08 16:45:16 -0500 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-07-09 07:09:15 -0400 |
commit | 0b8f65798e0b454ccaab1d93925c3e034d4f5624 (patch) | |
tree | c55c5fe88afa3ffc5beddee997e19fa582a057ff | |
parent | d99a656a615dd78773316b7ac3972f3f1bcd5fca (diff) | |
download | systemtap-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
-rw-r--r-- | tapsets.cxx | 93 |
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"; |