X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcompile%2Fcompile.c;h=20d81cb501dcd2abce88c358ae139abfa8102dab;hb=2b1ffcfd6fe5b88d50b6ad1c2ab3e9623ede5e35;hp=5269aaf613beaec834a86604b801c528969f3382;hpb=b80cf838447322778f04059a1f58b78ffbbeb597;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c index 5269aaf613..20d81cb501 100644 --- a/gdb/compile/compile.c +++ b/gdb/compile/compile.c @@ -1,6 +1,6 @@ /* General Compile and inject code - Copyright (C) 2014-2017 Free Software Foundation, Inc. + Copyright (C) 2014-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -41,6 +41,7 @@ #include "valprint.h" #include "common/gdb_optional.h" #include "common/gdb_unlinker.h" +#include "common/pathstuff.h" @@ -56,6 +57,173 @@ static struct cmd_list_element *compile_command_list; int compile_debug; +/* Object of this type are stored in the compiler's symbol_err_map. */ + +struct symbol_error +{ + /* The symbol. */ + + const struct symbol *sym; + + /* The error message to emit. This is malloc'd and owned by the + hash table. */ + + char *message; +}; + +/* Hash a type_map_instance. */ + +static hashval_t +hash_type_map_instance (const void *p) +{ + const struct type_map_instance *inst = (const struct type_map_instance *) p; + + return htab_hash_pointer (inst->type); +} + +/* Check two type_map_instance objects for equality. */ + +static int +eq_type_map_instance (const void *a, const void *b) +{ + const struct type_map_instance *insta = (const struct type_map_instance *) a; + const struct type_map_instance *instb = (const struct type_map_instance *) b; + + return insta->type == instb->type; +} + +/* Hash function for struct symbol_error. */ + +static hashval_t +hash_symbol_error (const void *a) +{ + const struct symbol_error *se = (const struct symbol_error *) a; + + return htab_hash_pointer (se->sym); +} + +/* Equality function for struct symbol_error. */ + +static int +eq_symbol_error (const void *a, const void *b) +{ + const struct symbol_error *sea = (const struct symbol_error *) a; + const struct symbol_error *seb = (const struct symbol_error *) b; + + return sea->sym == seb->sym; +} + +/* Deletion function for struct symbol_error. */ + +static void +del_symbol_error (void *a) +{ + struct symbol_error *se = (struct symbol_error *) a; + + xfree (se->message); + xfree (se); +} + +/* Constructor for compile_instance. */ + +compile_instance::compile_instance (struct gcc_base_context *gcc_fe, + const char *options) + : m_gcc_fe (gcc_fe), m_gcc_target_options (options), + m_type_map (htab_create_alloc (10, hash_type_map_instance, + eq_type_map_instance, + xfree, xcalloc, xfree)), + m_symbol_err_map (htab_create_alloc (10, hash_symbol_error, + eq_symbol_error, del_symbol_error, + xcalloc, xfree)) +{ +} + +/* See compile-internal.h. */ + +bool +compile_instance::get_cached_type (struct type *type, gcc_type &ret) const +{ + struct type_map_instance inst, *found; + + inst.type = type; + found = (struct type_map_instance *) htab_find (m_type_map.get (), &inst); + if (found != NULL) + { + ret = found->gcc_type_handle; + return true; + } + + return false; +} + +/* See compile-internal.h. */ + +void +compile_instance::insert_type (struct type *type, gcc_type gcc_type) +{ + struct type_map_instance inst, *add; + void **slot; + + inst.type = type; + inst.gcc_type_handle = gcc_type; + slot = htab_find_slot (m_type_map.get (), &inst, INSERT); + + add = (struct type_map_instance *) *slot; + /* The type might have already been inserted in order to handle + recursive types. */ + if (add != NULL && add->gcc_type_handle != gcc_type) + error (_("Unexpected type id from GCC, check you use recent enough GCC.")); + + if (add == NULL) + { + add = XNEW (struct type_map_instance); + *add = inst; + *slot = add; + } +} + +/* See compile-internal.h. */ + +void +compile_instance::insert_symbol_error (const struct symbol *sym, + const char *text) +{ + struct symbol_error e; + void **slot; + + e.sym = sym; + slot = htab_find_slot (m_symbol_err_map.get (), &e, INSERT); + if (*slot == NULL) + { + struct symbol_error *e = XNEW (struct symbol_error); + + e->sym = sym; + e->message = xstrdup (text); + *slot = e; + } +} + +/* See compile-internal.h. */ + +void +compile_instance::error_symbol_once (const struct symbol *sym) +{ + struct symbol_error search; + struct symbol_error *err; + + if (m_symbol_err_map == NULL) + return; + + search.sym = sym; + err = (struct symbol_error *) htab_find (m_symbol_err_map.get (), &search); + if (err == NULL || err->message == NULL) + return; + + gdb::unique_xmalloc_ptr message (err->message); + err->message = NULL; + error (_("%s"), message.get ()); +} + /* Implement "show debug compile". */ static void @@ -71,7 +239,7 @@ show_compile_debug (struct ui_file *file, int from_tty, Return 1 if seen and update *ARG. */ static int -check_raw_argument (char **arg) +check_raw_argument (const char **arg) { *arg = skip_spaces (*arg); @@ -87,11 +255,9 @@ check_raw_argument (char **arg) that may contain calls to the GCC compiler. */ static void -compile_file_command (char *arg, int from_tty) +compile_file_command (const char *arg, int from_tty) { enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE; - char *buffer; - struct cleanup *cleanup; scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0); @@ -115,12 +281,9 @@ compile_file_command (char *arg, int from_tty) error (_("Unknown argument specified.")); arg = skip_spaces (arg); - arg = gdb_abspath (arg); - cleanup = make_cleanup (xfree, arg); - buffer = xstrprintf ("#include \"%s\"\n", arg); - make_cleanup (xfree, buffer); - eval_compile_command (NULL, buffer, scope, NULL); - do_cleanups (cleanup); + gdb::unique_xmalloc_ptr abspath = gdb_abspath (arg); + std::string buffer = string_printf ("#include \"%s\"\n", abspath.get ()); + eval_compile_command (NULL, buffer.c_str (), scope, NULL); } /* Handle the input from the 'compile code' command. The @@ -129,7 +292,7 @@ compile_file_command (char *arg, int from_tty) compile command is the language currently set in GDB. */ static void -compile_code_command (char *arg, int from_tty) +compile_code_command (const char *arg, int from_tty) { enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE; @@ -153,7 +316,7 @@ compile_code_command (char *arg, int from_tty) eval_compile_command (NULL, arg, scope, NULL); else { - command_line_up l = get_command_line (compile_control, ""); + counted_command_line l = get_command_line (compile_control, ""); l->control_u.compile.scope = scope; execute_control_command_untraced (l.get ()); @@ -176,9 +339,8 @@ compile_print_value (struct value *val, void *data_voidp) compile command is the language currently set in GDB. */ static void -compile_print_command (char *arg_param, int from_tty) +compile_print_command (const char *arg, int from_tty) { - const char *arg = arg_param; enum compile_i_scope_types scope = COMPILE_I_PRINT_ADDRESS_SCOPE; struct format_data fmt; @@ -192,7 +354,7 @@ compile_print_command (char *arg_param, int from_tty) eval_compile_command (NULL, arg, scope, &fmt); else { - command_line_up l = get_command_line (compile_control, ""); + counted_command_line l = get_command_line (compile_control, ""); l->control_u.compile.scope = scope; l->control_u.compile.scope_data = &fmt; @@ -277,23 +439,25 @@ get_expr_block_and_pc (CORE_ADDR *pc) block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (cursal.symtab), STATIC_BLOCK); if (block != NULL) - *pc = BLOCK_START (block); + *pc = BLOCK_ENTRY_PC (block); } else - *pc = BLOCK_START (block); + *pc = BLOCK_ENTRY_PC (block); return block; } -/* Call gdb_buildargv, set its result for S into *ARGVP but calculate also the - number of parsed arguments into *ARGCP. If gdb_buildargv has returned NULL - then *ARGCP is set to zero. */ +/* Call buildargv (via gdb_argv), set its result for S into *ARGVP but + calculate also the number of parsed arguments into *ARGCP. If + buildargv has returned NULL then *ARGCP is set to zero. */ static void build_argc_argv (const char *s, int *argcp, char ***argvp) { - *argvp = gdb_buildargv (s); - *argcp = countargv (*argvp); + gdb_argv args (s); + + *argcp = args.count (); + *argvp = args.release (); } /* String for 'set compile-args' and 'show compile-args'. */ @@ -306,7 +470,7 @@ static char **compile_args_argv; /* Implement 'set compile-args'. */ static void -set_compile_args (char *args, int from_tty, struct cmd_list_element *c) +set_compile_args (const char *args, int from_tty, struct cmd_list_element *c) { freeargv (compile_args_argv); build_argc_argv (compile_args, &compile_args_argc, &compile_args_argv); @@ -338,6 +502,19 @@ append_args (int *argcp, char ***argvp, int argc, char **argv) (*argvp)[(*argcp)] = NULL; } +/* String for 'set compile-gcc' and 'show compile-gcc'. */ +static char *compile_gcc; + +/* Implement 'show compile-gcc'. */ + +static void +show_compile_gcc (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Compile command GCC driver filename is \"%s\".\n"), + value); +} + /* Return DW_AT_producer parsed for get_selected_frame () (if any). Return NULL otherwise. @@ -357,7 +534,7 @@ get_selected_pc_producer_options (void) cs = symtab->producer; while (*cs != 0 && *cs != '-') - cs = skip_spaces_const (skip_to_space_const (cs)); + cs = skip_spaces (skip_to_space (cs)); if (*cs != '-') return NULL; return cs; @@ -384,12 +561,28 @@ filter_args (int *argcp, char **argv) *destv = NULL; } -/* Produce final vector of GCC compilation options. First element is target - size ("-m64", "-m32" etc.), optionally followed by DW_AT_producer options - and then compile-args string GDB variable. */ +/* Produce final vector of GCC compilation options. + + The first element of the combined argument vector are arguments + relating to the target size ("-m64", "-m32" etc.). These are + sourced from the inferior's architecture. + + The second element of the combined argument vector are arguments + stored in the inferior DW_AT_producer section. If these are stored + in the inferior (there is no guarantee that they are), they are + added to the vector. + + The third element of the combined argument vector are argument + supplied by the language implementation provided by + compile-{lang}-support. These contain language specific arguments. + + The final element of the combined argument vector are arguments + supplied by the "set compile-args" command. These are always + appended last so as to override any of the arguments automatically + generated above. */ static void -get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, +get_args (const compile_instance *compiler, struct gdbarch *gdbarch, int *argcp, char ***argvp) { const char *cs_producer_options; @@ -411,7 +604,7 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, freeargv (argv_producer); } - build_argc_argv (compiler->gcc_target_options, + build_argc_argv (compiler->gcc_target_options ().c_str (), &argc_compiler, &argv_compiler); append_args (argcp, argvp, argc_compiler, argv_compiler); freeargv (argv_compiler); @@ -419,16 +612,6 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch, append_args (argcp, argvp, compile_args_argc, compile_args_argv); } -/* A cleanup function to destroy a gdb_gcc_instance. */ - -static void -cleanup_compile_instance (void *arg) -{ - struct compile_instance *inst = (struct compile_instance *) arg; - - inst->destroy (inst); -} - /* A helper function suitable for use as the "print_callback" in the compiler object. */ @@ -446,19 +629,13 @@ static compile_file_names compile_to_object (struct command_line *cmd, const char *cmd_string, enum compile_i_scope_types scope) { - struct compile_instance *compiler; - struct cleanup *cleanup; const struct block *expr_block; CORE_ADDR trash_pc, expr_pc; int argc; char **argv; int ok; - FILE *src; struct gdbarch *gdbarch = get_current_arch (); - const char *os_rx; - const char *arch_rx; - char *triplet_rx; - char *error_message; + std::string triplet_rx; if (!target_has_execution) error (_("The program must be running for the compile command to "\ @@ -471,13 +648,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, if (current_language->la_get_compile_instance == NULL) error (_("No compiler support for language %s."), current_language->la_name); - compiler = current_language->la_get_compile_instance (); - cleanup = make_cleanup (cleanup_compile_instance, compiler); - compiler->fe->ops->set_print_callback (compiler->fe, print_callback, NULL); - - compiler->scope = scope; - compiler->block = expr_block; + compile_instance *compiler_instance + = current_language->la_get_compile_instance (); + std::unique_ptr compiler (compiler_instance); + compiler->set_print_callback (print_callback, NULL); + compiler->set_scope (scope); + compiler->set_block (expr_block); /* From the provided expression, build a scope to pass to the compiler. */ @@ -489,7 +666,7 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, { struct command_line *iter; - for (iter = cmd->body_list[0]; iter; iter = iter->next) + for (iter = cmd->body_list_0.get (); iter; iter = iter->next) { input_buf.puts (iter->line); input_buf.puts ("\n"); @@ -503,29 +680,41 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, error (_("Neither a simple expression, or a multi-line specified.")); std::string code - = current_language->la_compute_program (compiler, input, gdbarch, + = current_language->la_compute_program (compiler.get (), input, gdbarch, expr_block, expr_pc); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ()); - os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch)); - arch_rx = gdbarch_gnu_triplet_regexp (gdbarch); + compiler->set_verbose (compile_debug); - /* Allow triplets with or without vendor set. */ - triplet_rx = concat (arch_rx, "(-[^-]*)?-", os_rx, (char *) NULL); - make_cleanup (xfree, triplet_rx); + if (compile_gcc[0] != 0) + { + if (compiler->version () < GCC_FE_VERSION_1) + error (_("Command 'set compile-gcc' requires GCC version 6 or higher " + "(libcc1 interface version 1 or higher)")); + + compiler->set_driver_filename (compile_gcc); + } + else + { + const char *os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch)); + const char *arch_rx = gdbarch_gnu_triplet_regexp (gdbarch); + + /* Allow triplets with or without vendor set. */ + triplet_rx = std::string (arch_rx) + "(-[^-]*)?-" + os_rx; + compiler->set_triplet_regexp (triplet_rx.c_str ()); + } /* Set compiler command-line arguments. */ - get_args (compiler, gdbarch, &argc, &argv); - make_cleanup_freeargv (argv); + get_args (compiler.get (), gdbarch, &argc, &argv); + gdb_argv argv_holder (argv); + + gdb::unique_xmalloc_ptr error_message; + error_message.reset (compiler->set_arguments (argc, argv, + triplet_rx.c_str ())); - error_message = compiler->fe->ops->set_arguments (compiler->fe, triplet_rx, - argc, argv); if (error_message != NULL) - { - make_cleanup (xfree, error_message); - error ("%s", error_message); - } + error ("%s", error_message.get ()); if (compile_debug) { @@ -557,10 +746,9 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, fnames.source_file ()); /* Call the compiler and start the compilation process. */ - compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ()); - - if (!compiler->fe->ops->compile (compiler->fe, fnames.object_file (), - compile_debug)) + compiler->set_source_file (fnames.source_file ()); + ok = compiler->compile (fnames.object_file (), compile_debug); + if (!ok) error (_("Compilation failed.")); if (compile_debug) @@ -569,16 +757,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string, /* Keep the source file. */ source_remover->keep (); - - do_cleanups (cleanup); - return fnames; } /* The "compile" prefix command. */ static void -compile_command (char *args, int from_tty) +compile_command (const char *args, int from_tty) { /* If a sub-command is not specified to the compile prefix command, assume it is a direct code compilation. */ @@ -616,12 +801,12 @@ eval_compile_command (struct command_line *cmd, const char *cmd_string, /* See compile/compile-internal.h. */ -char * +std::string compile_register_name_mangled (struct gdbarch *gdbarch, int regnum) { const char *regname = gdbarch_register_name (gdbarch, regnum); - return xstrprintf ("__%s", regname); + return string_printf ("__%s", regname); } /* See compile/compile-internal.h. */ @@ -643,7 +828,86 @@ compile_register_name_demangle (struct gdbarch *gdbarch, error (_("Cannot find gdbarch register \"%s\"."), regname); } -extern initialize_file_ftype _initialize_compile; +/* Forwards to the plug-in. */ + +#define FORWARD(OP,...) (m_gcc_fe->ops->OP (m_gcc_fe, ##__VA_ARGS__)) + +/* See compile-internal.h. */ + +void +compile_instance::set_print_callback + (void (*print_function) (void *, const char *), void *datum) +{ + FORWARD (set_print_callback, print_function, datum); +} + +/* See compile-internal.h. */ + +unsigned int +compile_instance::version () const +{ + return m_gcc_fe->ops->version; +} + +/* See compile-internal.h. */ + +void +compile_instance::set_verbose (int level) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_verbose, level); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_driver_filename (const char *filename) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_driver_filename, filename); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_triplet_regexp (const char *regexp) +{ + if (version () >= GCC_FE_VERSION_1) + FORWARD (set_triplet_regexp, regexp); +} + +/* See compile-internal.h. */ + +char * +compile_instance::set_arguments (int argc, char **argv, const char *regexp) +{ + if (version () >= GCC_FE_VERSION_1) + return FORWARD (set_arguments, argc, argv); + else + return FORWARD (set_arguments_v0, regexp, argc, argv); +} + +/* See compile-internal.h. */ + +void +compile_instance::set_source_file (const char *filename) +{ + FORWARD (set_source_file, filename); +} + +/* See compile-internal.h. */ + +bool +compile_instance::compile (const char *filename, int verbose_level) +{ + if (version () >= GCC_FE_VERSION_1) + return FORWARD (compile, filename); + else + return FORWARD (compile_v0, filename, verbose_level); +} + +#undef FORWARD + void _initialize_compile (void) @@ -738,4 +1002,17 @@ String quoting is parsed like in shell, for example:\n\ " -fno-stack-protector" ); set_compile_args (compile_args, 0, NULL); + + add_setshow_optional_filename_cmd ("compile-gcc", class_support, + &compile_gcc, + _("Set compile command " + "GCC driver filename"), + _("Show compile command " + "GCC driver filename"), + _("\ +It should be absolute filename of the gcc executable.\n\ +If empty the default target triplet will be searched in $PATH."), + NULL, show_compile_gcc, &setlist, + &showlist); + compile_gcc = xstrdup (""); }