summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-05-08 17:50:28 -0700
committerJosh Stone <jistone@redhat.com>2009-05-08 18:11:34 -0700
commit0730bfbd2665aef93d6fae287f3623a51f243540 (patch)
treed3def4975bc8416109cfc9803b63188699091465 /tapsets.cxx
parent620c2105eb1d928b97769006eb6eed79d6998531 (diff)
downloadsystemtap-steved-0730bfbd2665aef93d6fae287f3623a51f243540.tar.gz
systemtap-steved-0730bfbd2665aef93d6fae287f3623a51f243540.tar.xz
systemtap-steved-0730bfbd2665aef93d6fae287f3623a51f243540.zip
Refactor anonymous lookups in translate_components
The previous code recursed the entirety of translate_components, and it seemed to be restarting the components list every time, so it would only work if the anonymous portion was the first component. Even then, examining the code output by semok/thirtythree revealed that it wasn't fully translating the locations when multiple anonymous pieces were involved. Instead, it now recurses in a separate function, find_struct_member, which does just enough to find the member die and return. It also builds a vector of the locations passed through, so translate_components can output code for the full chain of anonymity. The generated code for semok/thirtythree's $page->mapping now appears to match the offsets from my manual inspection of struct page. I also added a test for $page->first_page->mapping, which works now but would segfault the old code.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx207
1 files changed, 94 insertions, 113 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index f0002073..a3ad8436 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1667,38 +1667,104 @@ struct dwflpp
while (dwarf_tag (die) == DW_TAG_member)
{
const char *member = dwarf_diename_integrate (die) ;
-
- if ( member != NULL )
-
- o << " " << member;
+ if ( member != NULL )
+ o << " " << member;
else
- {
- Dwarf_Die temp_die = *die;
- Dwarf_Attribute temp_attr ;
-
- if (!dwarf_attr_integrate (&temp_die, DW_AT_type, &temp_attr))
- {
- clog<<"\n Error in obtaining type attribute for "
- <<(dwarf_diename(&temp_die)?:"<anonymous>");
- return ;
- }
+ {
+ Dwarf_Die temp_die = *die;
+ Dwarf_Attribute temp_attr ;
- if ( ! dwarf_formref_die (&temp_attr,&temp_die))
- {
- clog<<"\n Error in decoding type attribute for "
- <<(dwarf_diename(&temp_die)?:"<anonymous>");
- return ;
- }
- print_members(&temp_die,o);
+ if (!dwarf_attr_integrate (&temp_die, DW_AT_type, &temp_attr))
+ {
+ clog << "\n Error in obtaining type attribute for "
+ << (dwarf_diename(&temp_die)?:"<anonymous>");
+ return;
+ }
- }
+ if (!dwarf_formref_die (&temp_attr, &temp_die))
+ {
+ clog << "\n Error in decoding type attribute for "
+ << (dwarf_diename(&temp_die)?:"<anonymous>");
+ return;
+ }
+
+ print_members(&temp_die,o);
+ }
if (dwarf_siblingof (die, &die_mem) != 0)
break;
}
}
+ bool
+ find_struct_member(const string& member,
+ Dwarf_Die *parentdie,
+ const target_symbol *e,
+ Dwarf_Die *memberdie,
+ vector<Dwarf_Attribute>& locs)
+ {
+ Dwarf_Attribute attr;
+ Dwarf_Die die = *parentdie;
+
+ switch (dwarf_child (&die, &die))
+ {
+ case 0: /* First child found. */
+ break;
+ case 1: /* No children. */
+ return false;
+ case -1: /* Error. */
+ default: /* Shouldn't happen */
+ throw semantic_error (string (dwarf_tag(&die) == DW_TAG_union_type ? "union" : "struct")
+ + string (dwarf_diename_integrate (&die) ?: "<anonymous>")
+ + string (dwarf_errmsg (-1)),
+ e->tok);
+ }
+
+ do
+ {
+ if (dwarf_tag(&die) != DW_TAG_member)
+ continue;
+
+ const char *name = dwarf_diename_integrate(&die);
+ if (name == NULL)
+ {
+ // need to recurse for anonymous structs/unions
+ Dwarf_Die subdie;
+
+ if (!dwarf_attr_integrate (&die, DW_AT_type, &attr) ||
+ !dwarf_formref_die (&attr, &subdie))
+ continue;
+
+ if (find_struct_member(member, &subdie, e, memberdie, locs))
+ goto success;
+ }
+ else if (name == member)
+ {
+ *memberdie = die;
+ goto success;
+ }
+ }
+ while (dwarf_siblingof (&die, &die) == 0);
+
+ return false;
+
+success:
+ /* As we unwind the recursion, we need to build the chain of
+ * locations that got to the final answer. */
+ if (dwarf_attr_integrate (&die, DW_AT_data_member_location, &attr))
+ locs.insert(locs.begin(), attr);
+
+ /* Union members don't usually have a location,
+ * but just use the containing union's location. */
+ else if (dwarf_tag(parentdie) != DW_TAG_union_type)
+ throw semantic_error ("no location for field '" + member
+ + "': " + string(dwarf_errmsg (-1)),
+ e->tok);
+
+ return true;
+ }
+
Dwarf_Die *
translate_components(struct obstack *pool,
struct location **tail,
@@ -1709,8 +1775,6 @@ struct dwflpp
Dwarf_Attribute *attr_mem)
{
Dwarf_Die *die = NULL;
- Dwarf_Die struct_die;
- Dwarf_Attribute temp_attr;
unsigned i = 0;
@@ -1720,11 +1784,6 @@ struct dwflpp
if (e->components.empty())
return die_mem;
- static unsigned int func_call_level ;
- static unsigned int dwarf_error_flag ; // indicates current error is dwarf error
- static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors
- static semantic_error saved_dwarf_error("");
-
while (i < e->components.size())
{
/* XXX: This would be desirable, but we don't get the target_symbol token,
@@ -1771,7 +1830,6 @@ 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(dwarf_diename(die));
@@ -1781,93 +1839,16 @@ struct dwflpp
e->tok);
*die_mem = *tmpdie;
}
- switch (dwarf_child (die, die_mem))
+
{
- case 1: /* No children. */
- return NULL;
- case -1: /* Error. */
- default: /* Shouldn't happen */
- throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct")
- + string (dwarf_diename_integrate (die) ?: "<anonymous>")
- + string (dwarf_errmsg (-1)),
- e->tok);
- break;
+ vector<Dwarf_Attribute> locs;
+ if (!find_struct_member(e->components[i].second, die, e, die, locs))
+ return NULL;
- case 0:
- break;
+ for (unsigned j = 0; j < locs.size(); ++j)
+ translate_location (pool, &locs[j], pc, NULL, tail, e);
}
- while (dwarf_tag (die) != DW_TAG_member
- || ({ const char *member = dwarf_diename_integrate (die);
- member == NULL || string(member) != e->components[i].second; }))
- {
- if ( dwarf_diename (die) == NULL ) // handling Anonymous structs/unions
- {
- Dwarf_Die temp_die = *die;
- Dwarf_Die temp_die_2;
-
- try
- {
- if (!dwarf_attr_integrate (&temp_die, DW_AT_type, &temp_attr))
- {
- dwarf_error_flag ++ ;
- dwarf_error_count ++;
- throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
- }
-
- if ( !dwarf_formref_die (&temp_attr, &temp_die))
- {
- dwarf_error_flag ++ ;
- dwarf_error_count ++;
- throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>"), e->tok);
- }
-
- func_call_level ++ ;
-
- Dwarf_Die *result_die = translate_components(pool, tail, pc, e, &temp_die, &temp_die_2, &temp_attr);
-
- func_call_level -- ;
-
- if (result_die != NULL)
- {
- memcpy(die_mem, &temp_die_2, sizeof(Dwarf_Die));
- memcpy(attr_mem, &temp_attr, sizeof(Dwarf_Attribute));
- return die_mem;
- }
- }
- catch (const semantic_error& e)
- {
- if ( !dwarf_error_flag ) //not a dwarf error
- throw;
- else
- {
- dwarf_error_flag = 0 ;
- saved_dwarf_error = e ;
- }
- }
- }
- if (dwarf_siblingof (die, die_mem) != 0)
- {
- if ( func_call_level == 0 && dwarf_error_count ) // this is parent call & a dwarf error has been reported in a branch somewhere
- throw semantic_error( saved_dwarf_error );
- else
- return NULL;
- }
- }
-
- if (dwarf_attr_integrate (die, DW_AT_data_member_location,
- attr_mem) == NULL)
- {
- /* Union members don't usually have a location,
- but just use the containing union's location. */
- if (typetag != DW_TAG_union_type)
- throw semantic_error ("no location for field '"
- + e->components[i].second
- + "' :" + string(dwarf_errmsg (-1)),
- e->tok);
- }
- else
- translate_location (pool, attr_mem, pc, NULL, tail, e);
++i;
break;