diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-11-16 10:02:50 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-11-16 10:47:38 +0100 |
commit | 228af5c49c06079e6bfe1daa64ead51b1dc979c7 (patch) | |
tree | 006a8c43562f1170ceda08b4584ca318f0b0b746 | |
parent | 7b76473cbad92366721defee51d93396cb101134 (diff) | |
download | systemtap-steved-228af5c49c06079e6bfe1daa64ead51b1dc979c7.tar.gz systemtap-steved-228af5c49c06079e6bfe1daa64ead51b1dc979c7.tar.xz systemtap-steved-228af5c49c06079e6bfe1daa64ead51b1dc979c7.zip |
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.
-rw-r--r-- | dwflpp.cxx | 68 | ||||
-rw-r--r-- | dwflpp.h | 1 | ||||
-rwxr-xr-x | testsuite/buildok/xtime.stp | 7 |
3 files changed, 62 insertions, 14 deletions
@@ -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<Dwarf_Die>& scopes, @@ -2231,30 +2259,42 @@ dwflpp::literal_stmt_for_local (vector<Dwarf_Die>& 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 " @@ -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 00000000..e41f9b16 --- /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(); +} |