X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fsymtab.c;h=cd208ab921b22954396c861f6bab1010df4310c1;hb=973961bda3cdf79e4c0768a5a5fd4eb6ab4acad2;hp=130d5cd48fff120e3770f7e4230575f629932cb0;hpb=3017b94d60f1e8929886be6992547973ad354f4c;p=external%2Fbinutils.git diff --git a/gdb/symtab.c b/gdb/symtab.c index 130d5cd..cd208ab 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -64,11 +64,11 @@ #include "parser-defs.h" #include "completer.h" #include "progspace-and-thread.h" -#include "common/gdb_optional.h" +#include "gdbsupport/gdb_optional.h" #include "filename-seen-cache.h" #include "arch-utils.h" #include -#include "common/pathstuff.h" +#include "gdbsupport/pathstuff.h" /* Forward declarations for local functions. */ @@ -92,7 +92,8 @@ struct block_symbol lookup_local_symbol (const char *name, enum language language); static struct block_symbol - lookup_symbol_in_objfile (struct objfile *objfile, int block_index, + lookup_symbol_in_objfile (struct objfile *objfile, + enum block_enum block_index, const char *name, const domain_enum domain); /* Type of the data stored on the program space. */ @@ -713,6 +714,7 @@ symbol_set_language (struct general_symbol_info *gsymbol, struct demangled_name_entry { const char *mangled; + ENUM_BITFIELD(language) language : LANGUAGE_BITS; char demangled[1]; }; @@ -853,11 +855,6 @@ symbol_set_names (struct general_symbol_info *gsymbol, else linkage_name_copy = linkage_name; - /* Set the symbol language. */ - char *demangled_name_ptr - = symbol_find_demangled_name (gsymbol, linkage_name_copy); - gdb::unique_xmalloc_ptr demangled_name (demangled_name_ptr); - entry.mangled = linkage_name_copy; slot = ((struct demangled_name_entry **) htab_find_slot (per_bfd->demangled_names_hash.get (), @@ -870,6 +867,9 @@ symbol_set_names (struct general_symbol_info *gsymbol, || (gsymbol->language == language_go && (*slot)->demangled[0] == '\0')) { + char *demangled_name_ptr + = symbol_find_demangled_name (gsymbol, linkage_name_copy); + gdb::unique_xmalloc_ptr demangled_name (demangled_name_ptr); int demangled_len = demangled_name ? strlen (demangled_name.get ()) : 0; /* Suppose we have demangled_name==NULL, copy_name==0, and @@ -906,12 +906,16 @@ symbol_set_names (struct general_symbol_info *gsymbol, strcpy (mangled_ptr, linkage_name_copy); (*slot)->mangled = mangled_ptr; } + (*slot)->language = gsymbol->language; if (demangled_name != NULL) - strcpy ((*slot)->demangled, demangled_name.get()); + strcpy ((*slot)->demangled, demangled_name.get ()); else (*slot)->demangled[0] = '\0'; } + else if (gsymbol->language == language_unknown + || gsymbol->language == language_auto) + gsymbol->language = (*slot)->language; gsymbol->name = (*slot)->mangled; if ((*slot)->demangled[0] != '\0') @@ -1299,7 +1303,7 @@ set_symbol_cache_size_handler (const char *args, int from_tty, static struct block_symbol symbol_cache_lookup (struct symbol_cache *cache, - struct objfile *objfile_context, int block, + struct objfile *objfile_context, enum block_enum block, const char *name, domain_enum domain, struct block_symbol_cache **bsc_ptr, struct symbol_cache_slot **slot_ptr) @@ -2220,15 +2224,18 @@ lookup_symbol_in_block (const char *name, symbol_name_match_type match_type, struct block_symbol lookup_global_symbol_from_objfile (struct objfile *main_objfile, + enum block_enum block_index, const char *name, const domain_enum domain) { + gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK); + for (objfile *objfile : main_objfile->separate_debug_objfiles ()) { struct block_symbol result - = lookup_symbol_in_objfile (objfile, GLOBAL_BLOCK, name, domain); + = lookup_symbol_in_objfile (objfile, block_index, name, domain); - if (result.symbol != NULL) + if (result.symbol != nullptr) return result; } @@ -2241,8 +2248,9 @@ lookup_global_symbol_from_objfile (struct objfile *main_objfile, static symbols. */ static struct block_symbol -lookup_symbol_in_objfile_symtabs (struct objfile *objfile, int block_index, - const char *name, const domain_enum domain) +lookup_symbol_in_objfile_symtabs (struct objfile *objfile, + enum block_enum block_index, const char *name, + const domain_enum domain) { gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK); @@ -2330,7 +2338,7 @@ lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile, in a psymtab but not in a symtab. */ static void ATTRIBUTE_NORETURN -error_in_psymtab_expansion (int block_index, const char *name, +error_in_psymtab_expansion (enum block_enum block_index, const char *name, struct compunit_symtab *cust) { error (_("\ @@ -2347,8 +2355,9 @@ Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n\ the "quick" symbol table functions. */ static struct block_symbol -lookup_symbol_via_quick_fns (struct objfile *objfile, int block_index, - const char *name, const domain_enum domain) +lookup_symbol_via_quick_fns (struct objfile *objfile, + enum block_enum block_index, const char *name, + const domain_enum domain) { struct compunit_symtab *cust; const struct blockvector *bv; @@ -2513,11 +2522,13 @@ lookup_symbol_in_static_block (const char *name, BLOCK_INDEX is one of GLOBAL_BLOCK or STATIC_BLOCK. */ static struct block_symbol -lookup_symbol_in_objfile (struct objfile *objfile, int block_index, +lookup_symbol_in_objfile (struct objfile *objfile, enum block_enum block_index, const char *name, const domain_enum domain) { struct block_symbol result; + gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK); + if (symbol_lookup_debug) { fprintf_unfiltered (gdb_stdlog, @@ -2715,7 +2726,8 @@ lookup_transparent_type (const char *name) "quick" symbol table functions. */ static struct type * -basic_lookup_transparent_type_quick (struct objfile *objfile, int block_index, +basic_lookup_transparent_type_quick (struct objfile *objfile, + enum block_enum block_index, const char *name) { struct compunit_symtab *cust; @@ -2745,7 +2757,8 @@ basic_lookup_transparent_type_quick (struct objfile *objfile, int block_index, BLOCK_INDEX is either GLOBAL_BLOCK or STATIC_BLOCK. */ static struct type * -basic_lookup_transparent_type_1 (struct objfile *objfile, int block_index, +basic_lookup_transparent_type_1 (struct objfile *objfile, + enum block_enum block_index, const char *name) { const struct blockvector *bv; @@ -3670,8 +3683,10 @@ skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab) /* Adjust SAL to the first instruction past the function prologue. If the PC was explicitly specified, the SAL is not changed. - If the line number was explicitly specified, at most the SAL's PC - is updated. If SAL is already past the prologue, then do nothing. */ + If the line number was explicitly specified then the SAL can still be + updated, unless the language for SAL is assembler, in which case the SAL + will be left unchanged. + If SAL is already past the prologue, then do nothing. */ void skip_prologue_sal (struct symtab_and_line *sal) @@ -3690,6 +3705,15 @@ skip_prologue_sal (struct symtab_and_line *sal) if (sal->explicit_pc) return; + /* In assembly code, if the user asks for a specific line then we should + not adjust the SAL. The user already has instruction level + visibility in this case, so selecting a line other than one requested + is likely to be the wrong choice. */ + if (sal->symtab != nullptr + && sal->explicit_line + && SYMTAB_LANGUAGE (sal->symtab) == language_asm) + return; + scoped_restore_current_pspace_and_thread restore_pspace_thread; switch_to_program_space_and_thread (sal->pspace); @@ -3809,12 +3833,6 @@ skip_prologue_sal (struct symtab_and_line *sal) sal->pc = pc; sal->section = section; - - /* Unless the explicit_line flag was set, update the SAL line - and symtab to correspond to the modified PC location. */ - if (sal->explicit_line) - return; - sal->symtab = start_sal.symtab; sal->line = start_sal.line; sal->end = start_sal.end; @@ -4111,10 +4129,28 @@ operator_chars (const char *p, const char **end) } +/* What part to match in a file name. */ + +struct filename_partial_match_opts +{ + /* Only match the directory name part. */ + int dirname = false; + + /* Only match the basename part. */ + int basename = false; +}; + /* Data structure to maintain printing state for output_source_filename. */ struct output_source_filename_data { + /* Output only filenames matching REGEXP. */ + std::string regexp; + gdb::optional c_regexp; + /* Possibly only match a part of the filename. */ + filename_partial_match_opts partial_match; + + /* Cache of what we've seen so far. */ struct filename_seen_cache *filename_seen_cache; @@ -4146,7 +4182,27 @@ output_source_filename (const char *name, return; } - /* No; print it and reset *FIRST. */ + /* Does it match data->regexp? */ + if (data->c_regexp.has_value ()) + { + const char *to_match; + std::string dirname; + + if (data->partial_match.dirname) + { + dirname = ldirname (name); + to_match = dirname.c_str (); + } + else if (data->partial_match.basename) + to_match = lbasename (name); + else + to_match = name; + + if (data->c_regexp->exec (to_match, 0, NULL, 0) != 0) + return; + } + + /* Print it and reset *FIRST. */ if (! data->first) printf_filtered (", "); data->first = 0; @@ -4165,8 +4221,74 @@ output_partial_symbol_filename (const char *filename, const char *fullname, (struct output_source_filename_data *) data); } +using isrc_flag_option_def + = gdb::option::flag_option_def; + +static const gdb::option::option_def info_sources_option_defs[] = { + + isrc_flag_option_def { + "dirname", + [] (filename_partial_match_opts *opts) { return &opts->dirname; }, + N_("Show only the files having a dirname matching REGEXP."), + }, + + isrc_flag_option_def { + "basename", + [] (filename_partial_match_opts *opts) { return &opts->basename; }, + N_("Show only the files having a basename matching REGEXP."), + }, + +}; + +/* Create an option_def_group for the "info sources" options, with + ISRC_OPTS as context. */ + +static inline gdb::option::option_def_group +make_info_sources_options_def_group (filename_partial_match_opts *isrc_opts) +{ + return {{info_sources_option_defs}, isrc_opts}; +} + +/* Prints the header message for the source files that will be printed + with the matching info present in DATA. SYMBOL_MSG is a message + that tells what will or has been done with the symbols of the + matching source files. */ + +static void +print_info_sources_header (const char *symbol_msg, + const struct output_source_filename_data *data) +{ + puts_filtered (symbol_msg); + if (!data->regexp.empty ()) + { + if (data->partial_match.dirname) + printf_filtered (_("(dirname matching regular expression \"%s\")"), + data->regexp.c_str ()); + else if (data->partial_match.basename) + printf_filtered (_("(basename matching regular expression \"%s\")"), + data->regexp.c_str ()); + else + printf_filtered (_("(filename matching regular expression \"%s\")"), + data->regexp.c_str ()); + } + puts_filtered ("\n"); +} + +/* Completer for "info sources". */ + +static void +info_sources_command_completer (cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char *word) +{ + const auto group = make_info_sources_options_def_group (nullptr); + if (gdb::option::complete_options + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group)) + return; +} + static void -info_sources_command (const char *ignore, int from_tty) +info_sources_command (const char *args, int from_tty) { struct output_source_filename_data data; @@ -4177,11 +4299,38 @@ info_sources_command (const char *ignore, int from_tty) filename_seen_cache filenames_seen; - data.filename_seen_cache = &filenames_seen; + auto group = make_info_sources_options_def_group (&data.partial_match); - printf_filtered ("Source files for which symbols have been read in:\n\n"); + gdb::option::process_options + (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group); + if (args != NULL && *args != '\000') + data.regexp = args; + + data.filename_seen_cache = &filenames_seen; data.first = 1; + + if (data.partial_match.dirname && data.partial_match.basename) + error (_("You cannot give both -basename and -dirname to 'info sources'.")); + if ((data.partial_match.dirname || data.partial_match.basename) + && data.regexp.empty ()) + error (_("Missing REGEXP for 'info sources'.")); + + if (data.regexp.empty ()) + data.c_regexp.reset (); + else + { + int cflags = REG_NOSUB; +#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM + cflags |= REG_ICASE; +#endif + data.c_regexp.emplace (data.regexp.c_str (), cflags, + _("Invalid regexp")); + } + + print_info_sources_header + (_("Source files for which symbols have been read in:\n"), &data); + for (objfile *objfile : current_program_space->objfiles ()) { for (compunit_symtab *cu : objfile->compunits ()) @@ -4196,8 +4345,8 @@ info_sources_command (const char *ignore, int from_tty) } printf_filtered ("\n\n"); - printf_filtered ("Source files for which symbols " - "will be read in on demand:\n\n"); + print_info_sources_header + (_("Source files for which symbols will be read in on demand:\n"), &data); filenames_seen.clear (); data.first = 1; @@ -4331,13 +4480,13 @@ search_symbols (const char *regexp, enum search_domain kind, struct symbol *sym; int found_misc = 0; static const enum minimal_symbol_type types[] - = {mst_data, mst_text, mst_abs}; + = {mst_data, mst_text, mst_unknown}; static const enum minimal_symbol_type types2[] - = {mst_bss, mst_file_text, mst_abs}; + = {mst_bss, mst_file_text, mst_unknown}; static const enum minimal_symbol_type types3[] - = {mst_file_data, mst_solib_trampoline, mst_abs}; + = {mst_file_data, mst_solib_trampoline, mst_unknown}; static const enum minimal_symbol_type types4[] - = {mst_file_bss, mst_text_gnu_ifunc, mst_abs}; + = {mst_file_bss, mst_text_gnu_ifunc, mst_unknown}; enum minimal_symbol_type ourtype; enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; @@ -4620,7 +4769,23 @@ print_symbol_info (enum search_domain kind, /* Typedef that is not a C++ class. */ if (kind == TYPES_DOMAIN && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN) - typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout); + { + /* FIXME: For C (and C++) we end up with a difference in output here + between how a typedef is printed, and non-typedefs are printed. + The TYPEDEF_PRINT code places a ";" at the end in an attempt to + appear C-like, while TYPE_PRINT doesn't. + + For the struct printing case below, things are worse, we force + printing of the ";" in this function, which is going to be wrong + for languages that don't require a ";" between statements. */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_TYPEDEF) + typedef_print (SYMBOL_TYPE (sym), sym, gdb_stdout); + else + { + type_print (SYMBOL_TYPE (sym), "", gdb_stdout, -1); + printf_filtered ("\n"); + } + } /* variable, func, or typedef-that-is-c++-class. */ else if (kind < TYPES_DOMAIN || (kind == TYPES_DOMAIN @@ -4679,6 +4844,9 @@ symtab_symbol_info (bool quiet, gdb_assert (kind <= TYPES_DOMAIN); + if (regexp != nullptr && *regexp == '\0') + regexp = nullptr; + /* Must make sure that if we're interrupted, symbols gets freed. */ std::vector symbols = search_symbols (regexp, kind, t_regexp, 0, NULL); @@ -4734,54 +4902,86 @@ symtab_symbol_info (bool quiet, } } +/* Implement the 'info variables' command. */ + static void info_variables_command (const char *args, int from_tty) { - std::string regexp; - std::string t_regexp; - bool quiet = false; - - while (args != NULL - && extract_info_print_args (&args, &quiet, ®exp, &t_regexp)) - ; - - if (args != NULL) - report_unrecognized_option_error ("info variables", args); + info_print_options opts; + extract_info_print_options (&opts, &args); - symtab_symbol_info (quiet, - regexp.empty () ? NULL : regexp.c_str (), - VARIABLES_DOMAIN, - t_regexp.empty () ? NULL : t_regexp.c_str (), - from_tty); + symtab_symbol_info (opts.quiet, args, VARIABLES_DOMAIN, + opts.type_regexp, from_tty); } +/* Implement the 'info functions' command. */ static void info_functions_command (const char *args, int from_tty) { - std::string regexp; - std::string t_regexp; - bool quiet = false; + info_print_options opts; + extract_info_print_options (&opts, &args); - while (args != NULL - && extract_info_print_args (&args, &quiet, ®exp, &t_regexp)) - ; + symtab_symbol_info (opts.quiet, args, FUNCTIONS_DOMAIN, + opts.type_regexp, from_tty); +} - if (args != NULL) - report_unrecognized_option_error ("info functions", args); +/* Holds the -q option for the 'info types' command. */ - symtab_symbol_info (quiet, - regexp.empty () ? NULL : regexp.c_str (), - FUNCTIONS_DOMAIN, - t_regexp.empty () ? NULL : t_regexp.c_str (), - from_tty); +struct info_types_options +{ + int quiet = false; +}; + +/* The options used by the 'info types' command. */ + +static const gdb::option::option_def info_types_options_defs[] = { + gdb::option::boolean_option_def { + "q", + [] (info_types_options *opt) { return &opt->quiet; }, + nullptr, /* show_cmd_cb */ + nullptr /* set_doc */ + } +}; + +/* Returns the option group used by 'info types'. */ + +static gdb::option::option_def_group +make_info_types_options_def_group (info_types_options *opts) +{ + return {{info_types_options_defs}, opts}; } +/* Implement the 'info types' command. */ static void -info_types_command (const char *regexp, int from_tty) +info_types_command (const char *args, int from_tty) { - symtab_symbol_info (false, regexp, TYPES_DOMAIN, NULL, from_tty); + info_types_options opts; + + auto grp = make_info_types_options_def_group (&opts); + gdb::option::process_options + (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp); + if (args != nullptr && *args == '\0') + args = nullptr; + symtab_symbol_info (opts.quiet, args, TYPES_DOMAIN, NULL, from_tty); +} + +/* Command completer for 'info types' command. */ + +static void +info_types_command_completer (struct cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char * /* word */) +{ + const auto group + = make_info_types_options_def_group (nullptr); + if (gdb::option::complete_options + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group)) + return; + + const char *word = advance_to_expression_complete_word_point (tracker, text); + symbol_completer (ignore, tracker, text, word); } /* Breakpoint all functions matching regular expression. */ @@ -5749,8 +5949,10 @@ find_main_name (void) set_main_name ("main", language_unknown); } -char * -main_name (void) +/* See symtab.h. */ + +const char * +main_name () { struct main_info *info = get_main_info (); @@ -6005,42 +6207,57 @@ symbol_set_symtab (struct symbol *symbol, struct symtab *symtab) void _initialize_symtab (void) { + cmd_list_element *c; + initialize_ordinary_address_classes (); - add_info ("variables", info_variables_command, - info_print_args_help (_("\ + c = add_info ("variables", info_variables_command, + info_print_args_help (_("\ All global and static variable names or those matching REGEXPs.\n\ Usage: info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the global and static variables.\n"), _("global and static variables"))); + set_cmd_completer_handle_brkchars (c, info_print_command_completer); if (dbx_commands) - add_com ("whereis", class_info, info_variables_command, - info_print_args_help (_("\ + { + c = add_com ("whereis", class_info, info_variables_command, + info_print_args_help (_("\ All global and static variable names, or those matching REGEXPs.\n\ Usage: whereis [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the global and static variables.\n"), _("global and static variables"))); + set_cmd_completer_handle_brkchars (c, info_print_command_completer); + } - add_info ("functions", info_functions_command, - info_print_args_help (_("\ + c = add_info ("functions", info_functions_command, + info_print_args_help (_("\ All function names or those matching REGEXPs.\n\ Usage: info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\ Prints the functions.\n"), _("functions"))); - - /* FIXME: This command has at least the following problems: - 1. It prints builtin types (in a very strange and confusing fashion). - 2. It doesn't print right, e.g. with - typedef struct foo *FOO - type_print prints "FOO" when we want to make it (in this situation) - print "struct foo *". - I also think "ptype" or "whatis" is more likely to be useful (but if - there is much disagreement "info types" can be fixed). */ - add_info ("types", info_types_command, - _("All type names, or those matching REGEXP.")); - - add_info ("sources", info_sources_command, - _("Source files in the program.")); + set_cmd_completer_handle_brkchars (c, info_print_command_completer); + + c = add_info ("types", info_types_command, _("\ +All type names, or those matching REGEXP.\n\ +Usage: info types [-q] [REGEXP]\n\ +Print information about all types matching REGEXP, or all types if no\n\ +REGEXP is given. The optional flag -q disables printing of headers.")); + set_cmd_completer_handle_brkchars (c, info_types_command_completer); + + const auto info_sources_opts = make_info_sources_options_def_group (nullptr); + + static std::string info_sources_help + = gdb::option::build_help (_("\ +All source files in the program or those matching REGEXP.\n\ +Usage: info sources [OPTION]... [REGEXP]\n\ +By default, REGEXP is used to match anywhere in the filename.\n\ +\n\ +Options:\n\ +%OPTIONS%"), + info_sources_opts); + + c = add_info ("sources", info_sources_command, info_sources_help.c_str ()); + set_cmd_completer_handle_brkchars (c, info_sources_command_completer); add_com ("rbreak", class_breakpoint, rbreak_command, _("Set a breakpoint for all functions matching REGEXP.")); @@ -6048,8 +6265,7 @@ Prints the functions.\n"), add_setshow_enum_cmd ("multiple-symbols", no_class, multiple_symbols_modes, &multiple_symbols_mode, _("\ -Set the debugger behavior when more than one symbol are possible matches\n\ -in an expression."), _("\ +Set how the debugger handles ambiguities in expressions."), _("\ Show how the debugger handles ambiguities in expressions."), _("\ Valid values are \"ask\", \"all\", \"cancel\", and the default is \"all\"."), NULL, NULL, &setlist, &showlist);