This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC updated PATCH 1/2] Bug Translator 3016 : Error accessing members of anonymous structs / unions


Hi all,
I'm posting patch 1 of 2 after fixing a bug which was causing it to fail on x86_64.


@Masami, thanks for pointing me to it :-)

Masami Hiramatsu wrote:
Masami Hiramatsu wrote:
Masami Hiramatsu wrote:
Hi Prerna,

Prerna Saxena wrote:
Hi all,
This patch modifies tapsets.cxx to enable members of anonymous structs/ unions to be recognised by the systemtap translator.
Pls let me know your comments..
I'm interested in this feature.

I tested your patches on x86-64 with elfutils-0.137, and I got a SEGV
when I ran following command:

$ stap -e 'probe module("libsas").function("sas_ex_revalidate_domain") {print($port_dev->ex_dev->children)}' -vvvp2

Finally, I got a clue, here is a part of gdb log.


----
Starting program: /usr/bin/stap -e 'probe module("libsas").function("sas_ex_revalidate_domain"){print($port_dev->ex_dev->children)}' -vp2
Breakpoint 1 at 0x2ac797678930: file tapsets.cxx, line 2164.
Breakpoint 2 at 0x2ac79766e640: file tapsets.cxx, line 2002.
[Thread debugging using libthread_db enabled]
Pass 1: parsed user script and 45 library script(s) in 260usr/20sys/275real ms.
[New Thread 47036754412368 (LWP 4726)]
[Switching to Thread 47036754412368 (LWP 4726)]

Breakpoint 1, dwflpp::literal_stmt_for_local (this=0x2ac79a09c3d0,
    scope_die=0x2ac7a2757778, pc=123498677, local=@0x7fff13502350,
    components=@0x2ac7a2757c68, lvalue=false, ty=@0x2ac7a3062198)
    at tapsets.cxx:2164
2164				  exp_type & ty)
(gdb) c
Continuing.

Breakpoint 2, dwflpp::translate_final_fetch_or_store (this=0x2ac79a09c3d0,
    pool=0x7fff13501c90, tail=0x7fff13501d98, module_bias=0,
    die=0x7fff135017f0, attr_mem=0x7fff13501d30, lvalue=false,
    ty=@0x2ac7a3062198) at tapsets.cxx:2002
2002					  exp_type & ty)
(gdb) p *die
$13 = {addr = 0x2ac7a2f13adf, cu = 0x2ac7a2745e00, abbrev = 0x2ac7a2751088,
  padding__ = 0}
(gdb) p *die->cu
$14 = {dbg = 0x2ac7a2745ae0, start = 312246, end = 380691,
  address_size = 8 '\b', offset_size = 4 '\004', version = 2, abbrev_hash = {
    size = 167, filled = 120, table = 0x2ac7a2753580},
  orig_abbrev_offset = 6545, last_abbrev_offset = 8087,
  lines = 0x2ac7a3048028, files = 0x2ac7a27568a8, locs = 0x2ac7a3062200}
-----
Actually, this die->cu was broken when stap got a SEGV.
It's address(die->cu) is "0x7fff135017f0" + 8
-----
(gdb) watch die->cu
Watchpoint 3: die->cu
(gdb) c
Continuing.
Watchpoint 3: die->cu

Old value = (struct Dwarf_CU *) 0x2ac7a2745e00
New value = (struct Dwarf_CU *) 0x5ea1e000001f4600
0x00002ac797aecb9a in __libdw_formref (attr=0x7fff13501d30,
    return_offset=0x7fff13501818) at elfutils-0.137/libdw/dwarf_formref.c:62
62	elfutils-0.137/libdw/dwarf_formref.c: No such file or directory.
	in elfutils-0.137/libdw/dwarf_formref.c
Current language:  auto; currently c
----
Here, die->cu was overwritten.
----
(gdb) l
57	in elfutils-0.137/libdw/dwarf_formref.c

(gdb) disassemble
Dump of assembler code for function __libdw_formref:
0x00002ac797aecb80 <__libdw_formref+0>:	push   %rbx
0x00002ac797aecb81 <__libdw_formref+1>:	mov    %rsi,%rbx
0x00002ac797aecb84 <__libdw_formref+4>:	sub    $0x10,%rsp
0x00002ac797aecb88 <__libdw_formref+8>:	mov    0x8(%rdi),%rcx
0x00002ac797aecb8c <__libdw_formref+12>:	mov    %fs:0x28,%rax
0x00002ac797aecb95 <__libdw_formref+21>:	mov    %rax,0x8(%rsp)
0x00002ac797aecb9a <__libdw_formref+26>:	xor    %eax,%eax
-----
Curiously, the assembler code just push a value to stack,
-----
(gdb) p $rsp
$23 = (void *) 0x7fff135017f0
-----

You can see the current stack pointer is same as the address of 'die'.
This means, the 'die' originally has been stored on the stack
memory (as a local variable) and passed it back to caller, and caller
reuse this stack.

I think below code is a suspicious code.

+ Dwarf_Die *result_die = translate_components(pool, tail,
pc, components, &temp_die, &temp_die, &temp_attr );

Since temp_die is just a local variable, I think secound &temp_die(6th argument) should be die_mem as same as original function.


Thank you,



-- Prerna Saxena

Linux Technology Centre,
IBM Systems and Technology Lab,
Bangalore, India


Signed-off-by: Prerna Saxena <prerna@linux.vnet.ibm.com>

Index: systemtap/tapsets.cxx
===================================================================
--- systemtap.orig/tapsets.cxx
+++ systemtap/tapsets.cxx
@@ -64,6 +64,7 @@ extern "C" {
 using namespace std;
 using namespace __gnu_cxx;
 
+static string error_msg("");
 // ------------------------------------------------------------------------
 // Generic derived_probe_group: contains an ordinary vector of the
 // given type.  It provides only the enrollment function.
@@ -1866,6 +1867,8 @@ struct dwflpp
   {
     Dwarf_Die *die = vardie;
     Dwarf_Die struct_die;
+    Dwarf_Attribute temp_attr;
+
     unsigned i = 0;
     while (i < components.size())
       {
@@ -1924,9 +1927,9 @@ struct dwflpp
 	    switch (dwarf_child (die, die_mem))
 	      {
 	      case 1:		/* No children.  */
-		throw semantic_error ("empty struct "
-				      + string (dwarf_diename_integrate (die) ?: "<anonymous>"));
-		break;
+		clog<<"\n Empty Struct "
+		    <<(dwarf_diename_integrate(die)?:"<anonymous>");
+		return NULL;
 	      case -1:		/* Error.  */
 	      default:		/* Shouldn't happen */
 		throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct")
@@ -1941,14 +1944,35 @@ struct dwflpp
 	    while (dwarf_tag (die) != DW_TAG_member
 		   || ({ const char *member = dwarf_diename_integrate (die);
 		       member == NULL || string(member) != components[i].second; }))
+	    {
+	      if ( dwarf_diename (die) == NULL )  // handling Anonymous structs/unions
+		{ 
+		   Dwarf_Die temp_die = *die;
+		   Dwarf_Die temp_die_2;
+		   
+		   if (!dwarf_attr_integrate (&temp_die, DW_AT_type, &temp_attr))
+                      	{ 
+			  error_msg = "\n Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"<anonymous>");
+                	  return NULL;
+                	}
+
+	           if ( !dwarf_formref_die (&temp_attr,&temp_die) )
+        	        { 
+			  error_msg = "\n Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"<anonymous>");
+                	  return NULL;
+                	}
+
+                   Dwarf_Die *result_die = translate_components(pool, tail, pc, components, &temp_die, &temp_die_2, &temp_attr );
+
+		   if (result_die != NULL)
+			{ 
+			  *attr_mem = temp_attr;
+			  return result_die;
+			}
+		}
 	      if (dwarf_siblingof (die, die_mem) != 0)
-	      {
-		  stringstream alternatives;
-		  print_members (&struct_die, alternatives);
-		  throw semantic_error ("field '" + components[i].second
-					+ "' not found (alternatives:"
-					+ alternatives.str () + ")");
-	      }
+		return NULL;
+	    }
 
 	    if (dwarf_attr_integrate (die, DW_AT_data_member_location,
 				      attr_mem) == NULL)
@@ -2228,8 +2252,11 @@ struct dwflpp
     /* Translate the ->bar->baz[NN] parts. */
 
     Dwarf_Die die_mem, *die = NULL;
+    error_msg = "";
     die = translate_components (&pool, &tail, pc, components,
 				&vardie, &die_mem, &attr_mem);
+    if(!die)
+	throw semantic_error("Translation failure");
 
     /* Translate the assignment part, either
        x = $foo->bar->baz[NN]
@@ -2295,8 +2322,11 @@ struct dwflpp
     Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem);
 
     Dwarf_Die die_mem, *die = NULL;
+    error_msg = "";
     die = translate_components (&pool, &tail, pc, components,
 				vardie, &die_mem, &attr_mem);
+    if(!die)
+	throw semantic_error("Translation Failure");
 
     /* Translate the assignment part, either
        x = $return->bar->baz[NN]

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]