diff options
author | Tom Tromey <tom@tromey.com> | 2017-07-06 06:44:38 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2017-11-17 14:34:14 -0700 |
commit | 71a3c36949407eafea744bf00334c4e0c136f927 (patch) | |
tree | 2449b4419ef190f549e5bd0f4bbc1c210b67076f /gdb/psymtab.c | |
parent | 7468702dcb37013edbbbc62e247e23c4b2632379 (diff) | |
download | gdb-71a3c36949407eafea744bf00334c4e0c136f927.zip gdb-71a3c36949407eafea744bf00334c4e0c136f927.tar.gz gdb-71a3c36949407eafea744bf00334c4e0c136f927.tar.bz2 |
Handle dereferencing Rust trait objects
In Rust, virtual tables work a bit differently than they do in C++. In
C++, as you know, they are connected to a particular class hierarchy.
Rust, instead, can generate a virtual table for potentially any type --
in fact, one such virtual table for each trait (a trait is similar to an
abstract class or to a Java interface) that a type implements.
Objects that are referenced via a trait can't currently be inspected by
gdb. This patch implements the Rust equivalent of "set print object".
gdb relies heavily on the C++ ABI to decode virtual tables; primarily to
make "set print object" work; but also "info vtbl". However, Rust does
not currently have a specified ABI, so this approach seems unwise to
emulate.
Instead, I've changed the Rust compiler to emit some DWARF that
describes trait objects (previously their internal structure was
opaque), vtables (currently just a size -- but I hope to expand this in
the future), and the concrete type for which a vtable was emitted.
The concrete type is expressed as a DW_AT_containing_type on the
vtable's type. This is a small extension to DWARF.
This patch adds a new entry to quick_symbol_functions to return the
symtab that holds a data address. Previously there was no way in gdb to
look up a full (only minimal) non-text symbol by address. The psymbol
implementation of this method works by lazily filling in a map that is
added to the objfile. This avoids slowing down psymbol reading for a
feature that is likely to not be used too frequently.
I did not update .gdb_index. My thinking here is that the DWARF 5
indices will obsolete .gdb_index soon-ish, meaning that adding a new
feature to them is probably wasted work. If necessary I can update the
DWARF 5 index code when it lands in gdb.
Regression tested on x86-64 Fedora 25.
2017-11-17 Tom Tromey <tom@tromey.com>
* symtab.h (struct symbol) <is_rust_vtable>: New member.
(struct rust_vtable_symbol): New.
(find_symbol_at_address): Declare.
* symtab.c (find_symbol_at_address): New function.
* symfile.h (struct quick_symbol_functions)
<find_compunit_symtab_by_address>: New member.
* symfile-debug.c (debug_qf_find_compunit_symtab_by_address): New
function.
(debug_sym_quick_functions): Link to
debug_qf_find_compunit_symtab_by_address.
* rust-lang.c (rust_get_trait_object_pointer): New function.
(rust_evaluate_subexp) <case UNOP_IND>: New case. Call
rust_get_trait_object_pointer.
* psymtab.c (psym_relocate): Clear psymbol_map.
(psym_fill_psymbol_map, psym_find_compunit_symtab_by_address): New
functions.
(psym_functions): Link to psym_find_compunit_symtab_by_address.
* objfiles.h (struct objfile) <psymbol_map>: New member.
* dwarf2read.c (dwarf2_gdb_index_functions): Update.
(process_die) <DW_TAG_variable>: New case. Call read_variable.
(rust_containing_type, read_variable): New functions.
2017-11-17 Tom Tromey <tom@tromey.com>
* gdb.rust/traits.rs: New file.
* gdb.rust/traits.exp: New file.
Diffstat (limited to 'gdb/psymtab.c')
-rw-r--r-- | gdb/psymtab.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 06a65bf..c74ea21 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -36,6 +36,7 @@ #include "cp-support.h" #include "gdbcmd.h" #include <algorithm> +#include <set> struct psymbol_bcache { @@ -823,6 +824,8 @@ psym_relocate (struct objfile *objfile, if (SYMBOL_SECTION (psym) >= 0) SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym)); } + + objfile->psymbol_map.clear (); } /* Psymtab version of find_last_source_symtab. See its definition in @@ -1458,6 +1461,84 @@ psym_has_symbols (struct objfile *objfile) return objfile->psymtabs != NULL; } +/* Helper function for psym_find_compunit_symtab_by_address that fills + in psymbol_map for a given range of psymbols. */ + +static void +psym_fill_psymbol_map (struct objfile *objfile, + struct partial_symtab *psymtab, + std::set<CORE_ADDR> *seen_addrs, + const std::vector<partial_symbol *> &symbols, + int start, + int length) +{ + for (int i = 0; i < length; ++i) + { + struct partial_symbol *psym = symbols[start + i]; + + if (PSYMBOL_CLASS (psym) == LOC_STATIC) + { + CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (psym); + if (seen_addrs->find (addr) == seen_addrs->end ()) + { + seen_addrs->insert (addr); + objfile->psymbol_map.emplace_back (addr, psymtab); + } + } + } +} + +/* See find_compunit_symtab_by_address in quick_symbol_functions, in + symfile.h. */ + +static compunit_symtab * +psym_find_compunit_symtab_by_address (struct objfile *objfile, + CORE_ADDR address) +{ + if (objfile->psymbol_map.empty ()) + { + struct partial_symtab *pst; + + std::set<CORE_ADDR> seen_addrs; + + ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) + { + psym_fill_psymbol_map (objfile, pst, + &seen_addrs, + objfile->global_psymbols, + pst->globals_offset, + pst->n_global_syms); + psym_fill_psymbol_map (objfile, pst, + &seen_addrs, + objfile->static_psymbols, + pst->statics_offset, + pst->n_static_syms); + } + + objfile->psymbol_map.shrink_to_fit (); + + std::sort (objfile->psymbol_map.begin (), objfile->psymbol_map.end (), + [] (const std::pair<CORE_ADDR, partial_symtab *> &a, + const std::pair<CORE_ADDR, partial_symtab *> &b) + { + return a.first < b.first; + }); + } + + auto iter = std::lower_bound + (objfile->psymbol_map.begin (), objfile->psymbol_map.end (), address, + [] (const std::pair<CORE_ADDR, partial_symtab *> &a, + CORE_ADDR b) + { + return a.first < b; + }); + + if (iter == objfile->psymbol_map.end () || iter->first != address) + return NULL; + + return psymtab_to_symtab (objfile, iter->second); +} + const struct quick_symbol_functions psym_functions = { psym_has_symbols, @@ -1474,6 +1555,7 @@ const struct quick_symbol_functions psym_functions = psym_map_matching_symbols, psym_expand_symtabs_matching, psym_find_pc_sect_compunit_symtab, + psym_find_compunit_symtab_by_address, psym_map_symbol_filenames }; |