From 228af5c49c06079e6bfe1daa64ead51b1dc979c7 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 16 Nov 2009 10:02:50 +0100 Subject: [PATCH] PR10622 Search for extern $variables in symbol table. * dwflpp.h (vardie_from_symtable): New method. * dwflpp.cxx (vardie_from_symtable): New method. (literal_stmt_for_local): Use vardie_from_symtable when no location attribute and DW_AT_external. * testsuite/buildok/xtime.stp: New testcase from PR10622. --- dwflpp.cxx | 68 +++++++++++++++++++++++++++++-------- dwflpp.h | 1 + testsuite/buildok/xtime.stp | 7 ++++ 3 files changed, 62 insertions(+), 14 deletions(-) create mode 100755 testsuite/buildok/xtime.stp diff --git a/dwflpp.cxx b/dwflpp.cxx index fbfe3f94e..92fe04c1d 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -2210,6 +2210,34 @@ dwflpp::express_as_string (string prelude, return result; } +Dwarf_Addr +dwflpp::vardie_from_symtable (Dwarf_Die *vardie, Dwarf_Addr *addr) +{ + const char *name = dwarf_diename (vardie); + if (sess.verbose > 2) + clog << "finding symtable address for " << name << "\n"; + + *addr = 0; + int syms = dwfl_module_getsymtab (module); + dwfl_assert ("Getting symbols", syms >= 0); + + for (int i = 0; *addr == 0 && i < syms; i++) + { + GElf_Sym sym; + GElf_Word shndxp; + const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp); + if (symname + && ! strcmp (name, symname) + && sym.st_shndx != SHN_UNDEF + && GELF_ST_TYPE (sym.st_info) == STT_OBJECT) + *addr = sym.st_value; + } + + if (sess.verbose > 2) + clog << "found " << name << "@0x" << hex << *addr << "\n"; + + return *addr; +} string dwflpp::literal_stmt_for_local (vector& scopes, @@ -2231,30 +2259,42 @@ dwflpp::literal_stmt_for_local (vector& scopes, << ", module bias 0x" << module_bias << dec << "\n"; +#define obstack_chunk_alloc malloc +#define obstack_chunk_free free + + struct obstack pool; + obstack_init (&pool); + struct location *tail = NULL; + + /* Given $foo->bar->baz[NN], translate the location of foo. */ + + struct location *head; + Dwarf_Attribute attr_mem; if (dwarf_attr_integrate (&vardie, DW_AT_const_value, &attr_mem) == NULL && dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL) { - throw semantic_error("failed to retrieve location " + Dwarf_Op addr_loc; + addr_loc.atom = DW_OP_addr; + // If it is an external variable try the symbol table. PR10622. + if (dwarf_attr_integrate (&vardie, DW_AT_external, &attr_mem) != NULL + && vardie_from_symtable (&vardie, &addr_loc.number) != 0) + { + head = c_translate_location (&pool, &loc2c_error, this, + &loc2c_emit_address, + 1, 0, pc, + NULL, &addr_loc, 1, &tail, NULL, NULL); + } + else + throw semantic_error("failed to retrieve location " "attribute for local '" + local + "' (dieoffset: " + lex_cast_hex(dwarf_dieoffset (&vardie)) + ")", e->tok); } - -#define obstack_chunk_alloc malloc -#define obstack_chunk_free free - - struct obstack pool; - obstack_init (&pool); - struct location *tail = NULL; - - /* Given $foo->bar->baz[NN], translate the location of foo. */ - - struct location *head = translate_location (&pool, - &attr_mem, pc, fb_attr, &tail, - e); + else + head = translate_location (&pool, &attr_mem, pc, fb_attr, &tail, e); if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL) throw semantic_error("failed to retrieve type " diff --git a/dwflpp.h b/dwflpp.h index 226b84d86..b3f71eb27 100644 --- a/dwflpp.h +++ b/dwflpp.h @@ -394,6 +394,7 @@ private: // Returns the call frame address operations for the given program counter. Dwarf_Op *get_cfa_ops (Dwarf_Addr pc); + Dwarf_Addr vardie_from_symtable(Dwarf_Die *vardie, Dwarf_Addr *addr); }; #endif // DWFLPP_H diff --git a/testsuite/buildok/xtime.stp b/testsuite/buildok/xtime.stp new file mode 100755 index 000000000..e41f9b164 --- /dev/null +++ b/testsuite/buildok/xtime.stp @@ -0,0 +1,7 @@ +#! stap -p4 + +# Test for getting at an external global variable PR10622 +probe kernel.function("do_gettimeofday") +{ + printf("xtime.tv_sec:%d\n", $xtime->tv_sec); exit(); +} -- 2.43.5