From 228af5c49c06079e6bfe1daa64ead51b1dc979c7 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 16 Nov 2009 10:02:50 +0100 Subject: 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 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 14 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index fbfe3f94..92fe04c1 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 " -- cgit From a295050e60affe0bb55fc2d46637314c0822f35d Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 16 Nov 2009 21:34:00 +0100 Subject: PR10010 Support $globals in shared libraries. * dwflpp.cxx (dwflpp::emit_address): Enable task finder and emit a _stp_module_relocate for the ".dynamic" section when seeing a user-space dso address. * runtime/sym.c (_stp_mod_sec_lookup): Remove .dynamic section addr cheat. (_stp_tf_mmap_cb): Add cheat here. --- dwflpp.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 92fe04c1..35637568 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1502,12 +1502,11 @@ dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) } else { - throw semantic_error ("cannot relocate user-space dso (?) address"); -#if 0 - // This would happen for a Dwfl_Module that's a user-level DSO. - obstack_printf (pool, " /* %s+%#" PRIx64 " */", - modname, address); -#endif + enable_task_finder (sess); + obstack_printf (pool, "({ static unsigned long addr = 0; "); + obstack_printf (pool, "if (addr==0) addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", + modname, ".dynamic", reloc_address); + obstack_printf (pool, "addr; })"); } } else -- cgit From f685b2fea262d1e517d75d69c84ec0d1edea6cf0 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 17 Nov 2009 10:10:31 +0100 Subject: Remove caching of emit_address for kernel modules and shared libraries. Caching of the address is only safe for kernel addresses that can never change. For kernel module or dynamic shared library addresses it isn't safe to cache the address since they can be unloaded, reloaded or mapped differently in separate executables. * dwflpp.cxx (emit_address): Remove static from addr definition for kernel and dynamic modules. --- dwflpp.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 35637568..53f3d8eb 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1484,8 +1484,8 @@ dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) { // This gives us the module name, and section name within the // module, for a kernel module (or other ET_REL module object). - obstack_printf (pool, "({ static unsigned long addr = 0; "); - obstack_printf (pool, "if (addr==0) addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", + obstack_printf (pool, "({ unsigned long addr = 0; "); + obstack_printf (pool, "addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", modname, secname, reloc_address); obstack_printf (pool, "addr; })"); } @@ -1495,6 +1495,9 @@ dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) // need to treat the same way here as dwarf_query::add_probe_point does: _stext. address -= sess.sym_stext; secname = "_stext"; + // Note we "cache" the result here through a static because the + // kernel will never move after being loaded (unlike modules and + // user-space dynamic share libraries). obstack_printf (pool, "({ static unsigned long addr = 0; "); obstack_printf (pool, "if (addr==0) addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", modname, secname, address); // PR10000 NB: not reloc_address @@ -1503,8 +1506,8 @@ dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) else { enable_task_finder (sess); - obstack_printf (pool, "({ static unsigned long addr = 0; "); - obstack_printf (pool, "if (addr==0) addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", + obstack_printf (pool, "({ unsigned long addr = 0; "); + obstack_printf (pool, "addr = _stp_module_relocate (\"%s\",\"%s\",%#" PRIx64 "); ", modname, ".dynamic", reloc_address); obstack_printf (pool, "addr; })"); } -- cgit From b0490786a904cbd19fb04c3d66ac3c277bfc2c71 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 17 Nov 2009 16:11:28 +0100 Subject: Use DW_AT_MIPS_linkage_name when available in vardie_from_symtable. If there is a DW_AT_MIPS_linkage_name it encodes the actual name of the variable as used in the symbol table. * dwflpp.cpp (vardie_from_symtable): Check whether there is a DW_AT_MIPS_linkage_name attribute and use its value if so. --- dwflpp.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index 53f3d8eb..fdbcddf4 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -2215,7 +2215,14 @@ dwflpp::express_as_string (string prelude, Dwarf_Addr dwflpp::vardie_from_symtable (Dwarf_Die *vardie, Dwarf_Addr *addr) { - const char *name = dwarf_diename (vardie); + const char *name; + Dwarf_Attribute attr_mem; + name = dwarf_formstring (dwarf_attr_integrate (vardie, + DW_AT_MIPS_linkage_name, + &attr_mem)); + if (!name) + name = dwarf_diename (vardie); + if (sess.verbose > 2) clog << "finding symtable address for " << name << "\n"; -- cgit From 063906a93ee3ea5b976f43e2dd1f73d29605fa4c Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 17 Nov 2009 22:20:32 +0100 Subject: Search other CUs of the module when resolving declarations. * dwflpp.h (declaration_resolve_other_cus): New method. (iterate_over_globals): Mark as static and takes a CU to iterate over. (global_alias_caching_callback_cus): New method. * dwflpp.cxx (global_alias_caching_callback_cus): New method. (declaration_resolve_other_cus): New method. (declaration_resolve): Call iterate_over_globals() with current cu. Call declaration_resolve_other_cus() when name not found. (iterate_over_globals): Takes cu_die to iterate over as argument. --- dwflpp.cxx | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'dwflpp.cxx') diff --git a/dwflpp.cxx b/dwflpp.cxx index fdbcddf4..0e8a352d 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -721,6 +721,37 @@ dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg) return DWARF_CB_OK; } +int +dwflpp::global_alias_caching_callback_cus(Dwarf_Die *die, void *arg) +{ + mod_cu_type_cache_t *global_alias_cache; + global_alias_cache = &static_cast(arg)->global_alias_cache; + + cu_type_cache_t *v = (*global_alias_cache)[die->addr]; + if (v != 0) + return DWARF_CB_OK; + + v = new cu_type_cache_t; + (*global_alias_cache)[die->addr] = v; + iterate_over_globals(die, global_alias_caching_callback, v); + + return DWARF_CB_OK; +} + +Dwarf_Die * +dwflpp::declaration_resolve_other_cus(const char *name) +{ + iterate_over_cus(global_alias_caching_callback_cus, this); + for (mod_cu_type_cache_t::iterator i = global_alias_cache.begin(); + i != global_alias_cache.end(); ++i) + { + cu_type_cache_t *v = (*i).second; + if (v->find(name) != v->end()) + return & ((*v)[name]); + } + + return NULL; +} Dwarf_Die * dwflpp::declaration_resolve(const char *name) @@ -733,7 +764,7 @@ dwflpp::declaration_resolve(const char *name) { v = new cu_type_cache_t; global_alias_cache[cu->addr] = v; - iterate_over_globals(global_alias_caching_callback, v); + iterate_over_globals(cu, global_alias_caching_callback, v); if (sess.verbose > 4) clog << "global alias cache " << module_name << ":" << cu_name() << " size " << v->size() << endl; @@ -744,11 +775,8 @@ dwflpp::declaration_resolve(const char *name) // forward-declared pointer type only, where the actual definition // may only be in vmlinux or the application. - // XXX: it is probably desirable to search other CU's declarations - // in the same module. - if (v->find(name) == v->end()) - return NULL; + return declaration_resolve_other_cus(name); return & ((*v)[name]); } @@ -839,17 +867,17 @@ dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * /* 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 *), +dwflpp::iterate_over_globals (Dwarf_Die *cu_die, + 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); + assert (cu_die); + assert (dwarf_tag(cu_die) == DW_TAG_compile_unit); - if (dwarf_child(cu, &die) != 0) + if (dwarf_child(cu_die, &die) != 0) return rc; do -- cgit