gdb/compile/compile.c - gdb
Global variables defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "interps.h"
- #include "ui-out.h"
- #include "command.h"
- #include "cli/cli-script.h"
- #include "cli/cli-utils.h"
- #include "completer.h"
- #include "gdbcmd.h"
- #include "compile.h"
- #include "compile-internal.h"
- #include "compile-object-load.h"
- #include "compile-object-run.h"
- #include "language.h"
- #include "frame.h"
- #include "source.h"
- #include "block.h"
- #include "arch-utils.h"
- #include "filestuff.h"
- #include "target.h"
- #include "osabi.h"
- #include "gdb_wait.h"
- #define TMP_PREFIX "/tmp/gdbobj-"
- static struct cmd_list_element *compile_command_list;
- int compile_debug;
- static void
- show_compile_debug (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- fprintf_filtered (file, _("Compile debugging is %s.\n"), value);
- }
- static int
- check_raw_argument (char **arg)
- {
- *arg = skip_spaces (*arg);
- if (arg != NULL
- && (check_for_argument (arg, "-raw", sizeof ("-raw") - 1)
- || check_for_argument (arg, "-r", sizeof ("-r") - 1)))
- return 1;
- return 0;
- }
- static void
- compile_file_command (char *arg, int from_tty)
- {
- enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;
- char *buffer;
- struct cleanup *cleanup;
- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
-
- if (arg == NULL)
- error (_("You must provide a filename for this command."));
-
- if (arg != NULL && check_raw_argument (&arg))
- {
- scope = COMPILE_I_RAW_SCOPE;
- arg = skip_spaces (arg);
- }
-
- if (arg[0] == '\0')
- error (_("You must provide a filename with the raw option set."));
- if (arg[0] == '-')
- error (_("Unknown argument specified."));
- arg = skip_spaces (arg);
- arg = gdb_abspath (arg);
- make_cleanup (xfree, arg);
- buffer = xstrprintf ("#include \"%s\"\n", arg);
- make_cleanup (xfree, buffer);
- eval_compile_command (NULL, buffer, scope);
- do_cleanups (cleanup);
- }
- static void
- compile_code_command (char *arg, int from_tty)
- {
- struct cleanup *cleanup;
- enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;
- cleanup = make_cleanup_restore_integer (&interpreter_async);
- interpreter_async = 0;
- if (arg != NULL && check_raw_argument (&arg))
- {
- scope = COMPILE_I_RAW_SCOPE;
- arg = skip_spaces (arg);
- }
- arg = skip_spaces (arg);
- if (arg != NULL && !check_for_argument (&arg, "--", sizeof ("--") - 1))
- {
- if (arg[0] == '-')
- error (_("Unknown argument specified."));
- }
- if (arg && *arg)
- eval_compile_command (NULL, arg, scope);
- else
- {
- struct command_line *l = get_command_line (compile_control, "");
- make_cleanup_free_command_lines (&l);
- l->control_u.compile.scope = scope;
- execute_control_command_untraced (l);
- }
- do_cleanups (cleanup);
- }
- static void
- do_rmdir (void *arg)
- {
- const char *dir = arg;
- char *zap;
- int wstat;
- gdb_assert (strncmp (dir, TMP_PREFIX, strlen (TMP_PREFIX)) == 0);
- zap = concat ("rm -rf ", dir, (char *) NULL);
- wstat = system (zap);
- if (wstat == -1 || !WIFEXITED (wstat) || WEXITSTATUS (wstat) != 0)
- warning (_("Could not remove temporary directory %s"), dir);
- XDELETEVEC (zap);
- }
- static const char *
- get_compile_file_tempdir (void)
- {
- static char *tempdir_name;
- #define TEMPLATE TMP_PREFIX "XXXXXX"
- char tname[sizeof (TEMPLATE)];
- if (tempdir_name != NULL)
- return tempdir_name;
- strcpy (tname, TEMPLATE);
- #undef TEMPLATE
- #ifdef HAVE_MKDTEMP
- tempdir_name = mkdtemp (tname);
- #else
- error (_("Command not supported on this host."));
- #endif
- if (tempdir_name == NULL)
- perror_with_name (_("Could not make temporary directory"));
- tempdir_name = xstrdup (tempdir_name);
- make_final_cleanup (do_rmdir, tempdir_name);
- return tempdir_name;
- }
- static void
- get_new_file_names (char **source_file, char **object_file)
- {
- static int seq;
- const char *dir = get_compile_file_tempdir ();
- ++seq;
- *source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
- *object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq);
- }
- static const struct block *
- get_expr_block_and_pc (CORE_ADDR *pc)
- {
- const struct block *block = get_selected_block (pc);
- if (block == NULL)
- {
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
- if (cursal.symtab)
- block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (cursal.symtab),
- STATIC_BLOCK);
- if (block != NULL)
- *pc = BLOCK_START (block);
- }
- else
- *pc = BLOCK_START (block);
- return block;
- }
- static void
- build_argc_argv (const char *s, int *argcp, char ***argvp)
- {
- *argvp = gdb_buildargv (s);
- *argcp = countargv (*argvp);
- }
- static char *compile_args;
- static int compile_args_argc;
- static char **compile_args_argv;
- static void
- set_compile_args (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);
- }
- static void
- show_compile_args (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- fprintf_filtered (file, _("Compile command command-line arguments "
- "are \"%s\".\n"),
- value);
- }
- static void
- append_args (int *argcp, char ***argvp, int argc, char **argv)
- {
- int argi;
- *argvp = xrealloc (*argvp, (*argcp + argc + 1) * sizeof (**argvp));
- for (argi = 0; argi < argc; argi++)
- (*argvp)[(*argcp)++] = xstrdup (argv[argi]);
- (*argvp)[(*argcp)] = NULL;
- }
- static const char *
- get_selected_pc_producer_options (void)
- {
- CORE_ADDR pc = get_frame_pc (get_selected_frame (NULL));
- struct compunit_symtab *symtab = find_pc_compunit_symtab (pc);
- const char *cs;
- if (symtab == NULL || symtab->producer == NULL
- || strncmp (symtab->producer, "GNU ", strlen ("GNU ")) != 0)
- return NULL;
- cs = symtab->producer;
- while (*cs != 0 && *cs != '-')
- cs = skip_spaces_const (skip_to_space_const (cs));
- if (*cs != '-')
- return NULL;
- return cs;
- }
- static void
- get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
- int *argcp, char ***argvp)
- {
- const char *cs_producer_options;
- int argc_compiler;
- char **argv_compiler;
- build_argc_argv (gdbarch_gcc_target_options (gdbarch),
- argcp, argvp);
- cs_producer_options = get_selected_pc_producer_options ();
- if (cs_producer_options != NULL)
- {
- int argc_producer;
- char **argv_producer;
- build_argc_argv (cs_producer_options, &argc_producer, &argv_producer);
- append_args (argcp, argvp, argc_producer, argv_producer);
- freeargv (argv_producer);
- }
- build_argc_argv (compiler->gcc_target_options,
- &argc_compiler, &argv_compiler);
- append_args (argcp, argvp, argc_compiler, argv_compiler);
- freeargv (argv_compiler);
- append_args (argcp, argvp, compile_args_argc, compile_args_argv);
- }
- static void
- cleanup_compile_instance (void *arg)
- {
- struct compile_instance *inst = arg;
- inst->destroy (inst);
- }
- static void
- cleanup_unlink_file (void *arg)
- {
- const char *filename = arg;
- unlink (filename);
- }
- static void
- print_callback (void *ignore, const char *message)
- {
- fputs_filtered (message, gdb_stderr);
- }
- static char *
- compile_to_object (struct command_line *cmd, char *cmd_string,
- enum compile_i_scope_types scope,
- char **source_filep)
- {
- char *code;
- char *source_file, *object_file;
- struct compile_instance *compiler;
- struct cleanup *cleanup, *inner_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;
- if (!target_has_execution)
- error (_("The program must be running for the compile command to "\
- "work."));
- expr_block = get_expr_block_and_pc (&trash_pc);
- expr_pc = get_frame_address_in_block (get_selected_frame (NULL));
-
- if (current_language->la_get_compile_instance == NULL)
- error (_("No compiler support for this language."));
- 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;
-
- if (cmd != NULL)
- {
- struct ui_file *stream = mem_fileopen ();
- struct command_line *iter;
- make_cleanup_ui_file_delete (stream);
- for (iter = cmd->body_list[0]; iter; iter = iter->next)
- {
- fputs_unfiltered (iter->line, stream);
- fputs_unfiltered ("\n", stream);
- }
- code = ui_file_xstrdup (stream, NULL);
- make_cleanup (xfree, code);
- }
- else if (cmd_string != NULL)
- code = cmd_string;
- else
- error (_("Neither a simple expression, or a multi-line specified."));
- code = current_language->la_compute_program (compiler, code, gdbarch,
- expr_block, expr_pc);
- make_cleanup (xfree, code);
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout, "debug output:\n\n%s", code);
- os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch));
- arch_rx = gdbarch_gnu_triplet_regexp (gdbarch);
- triplet_rx = concat (arch_rx, "-[^-]*-", os_rx, (char *) NULL);
- make_cleanup (xfree, triplet_rx);
-
- get_args (compiler, gdbarch, &argc, &argv);
- make_cleanup_freeargv (argv);
- 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);
- }
- if (compile_debug)
- {
- int argi;
- fprintf_unfiltered (gdb_stdout, "Passing %d compiler options:\n", argc);
- for (argi = 0; argi < argc; argi++)
- fprintf_unfiltered (gdb_stdout, "Compiler option %d: <%s>\n",
- argi, argv[argi]);
- }
- get_new_file_names (&source_file, &object_file);
- inner_cleanup = make_cleanup (xfree, source_file);
- make_cleanup (xfree, object_file);
- src = gdb_fopen_cloexec (source_file, "w");
- if (src == NULL)
- perror_with_name (_("Could not open source file for writing"));
- make_cleanup (cleanup_unlink_file, source_file);
- if (fputs (code, src) == EOF)
- perror_with_name (_("Could not write to source file"));
- fclose (src);
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout, "source file produced: %s\n\n",
- source_file);
-
- compiler->fe->ops->set_source_file (compiler->fe, source_file);
- if (!compiler->fe->ops->compile (compiler->fe, object_file,
- compile_debug))
- error (_("Compilation failed."));
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout, "object file produced: %s\n\n",
- object_file);
- discard_cleanups (inner_cleanup);
- do_cleanups (cleanup);
- *source_filep = source_file;
- return object_file;
- }
- static void
- compile_command (char *args, int from_tty)
- {
-
- compile_code_command (args, from_tty);
- }
- void
- eval_compile_command (struct command_line *cmd, char *cmd_string,
- enum compile_i_scope_types scope)
- {
- char *object_file, *source_file;
- object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
- if (object_file != NULL)
- {
- struct cleanup *cleanup_xfree, *cleanup_unlink;
- struct compile_module *compile_module;
- cleanup_xfree = make_cleanup (xfree, object_file);
- make_cleanup (xfree, source_file);
- cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
- make_cleanup (cleanup_unlink_file, source_file);
- compile_module = compile_object_load (object_file, source_file);
- discard_cleanups (cleanup_unlink);
- do_cleanups (cleanup_xfree);
- compile_object_run (compile_module);
- }
- }
- char *
- compile_register_name_mangled (struct gdbarch *gdbarch, int regnum)
- {
- const char *regname = gdbarch_register_name (gdbarch, regnum);
- return xstrprintf ("__%s", regname);
- }
- int
- compile_register_name_demangle (struct gdbarch *gdbarch,
- const char *regname)
- {
- int regnum;
- if (regname[0] != '_' || regname[1] != '_')
- error (_("Invalid register name \"%s\"."), regname);
- regname += 2;
- for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
- if (strcmp (regname, gdbarch_register_name (gdbarch, regnum)) == 0)
- return regnum;
- error (_("Cannot find gdbarch register \"%s\"."), regname);
- }
- extern initialize_file_ftype _initialize_compile;
- void
- _initialize_compile (void)
- {
- struct cmd_list_element *c = NULL;
- add_prefix_cmd ("compile", class_obscure, compile_command,
- _("\
- Command to compile source code and inject it into the inferior."),
- &compile_command_list, "compile ", 1, &cmdlist);
- add_com_alias ("expression", "compile", class_obscure, 0);
- add_cmd ("code", class_obscure, compile_code_command,
- _("\
- Compile, inject, and execute code.\n\
- \n\
- Usage: compile code [-r|-raw] [--] [CODE]\n\
- -r|-raw: Suppress automatic 'void _gdb_expr () { CODE }' wrapping.\n\
- --: Do not parse any options beyond this delimiter. All text to the\n\
- right will be treated as source code.\n\
- \n\
- The source code may be specified as a simple one line expression, e.g.:\n\
- \n\
- compile code printf(\"Hello world\\n\");\n\
- \n\
- Alternatively, you can type the source code interactively.\n\
- You can invoke this mode when no argument is given to the command\n\
- (i.e.,\"compile code\" is typed with nothing after it). An\n\
- interactive prompt will be shown allowing you to enter multiple\n\
- lines of source code. Type a line containing \"end\" to indicate\n\
- the end of the source code."),
- &compile_command_list);
- c = add_cmd ("file", class_obscure, compile_file_command,
- _("\
- Evaluate a file containing source code.\n\
- \n\
- Usage: compile file [-r|-raw] [filename]\n\
- -r|-raw: Suppress automatic 'void _gdb_expr () { CODE }' wrapping."),
- &compile_command_list);
- set_cmd_completer (c, filename_completer);
- add_setshow_boolean_cmd ("compile", class_maintenance, &compile_debug, _("\
- Set compile command debugging."), _("\
- Show compile command debugging."), _("\
- When on, compile command debugging is enabled."),
- NULL, show_compile_debug,
- &setdebuglist, &showdebuglist);
- add_setshow_string_cmd ("compile-args", class_support,
- &compile_args,
- _("Set compile command GCC command-line arguments"),
- _("Show compile command GCC command-line arguments"),
- _("\
- Use options like -I (include file directory) or ABI settings.\n\
- String quoting is parsed like in shell, for example:\n\
- -mno-align-double \"-I/dir with a space/include\""),
- set_compile_args, show_compile_args, &setlist, &showlist);
-
- compile_args = xstrdup ("-O0 -gdwarf-4"
-
- " -fPIC"
-
- " -w"
-
- " -fno-stack-protector"
- );
- set_compile_args (compile_args, 0, NULL);
- }