- /* C language support for compilation.
- Copyright (C) 2014-2015 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "compile-internal.h"
- #include "compile.h"
- #include "gdb-dlfcn.h"
- #include "c-lang.h"
- #include "macrotab.h"
- #include "macroscope.h"
- #include "regcache.h"
- /* See compile-internal.h. */
- const char *
- c_get_mode_for_size (int size)
- {
- const char *mode = NULL;
- switch (size)
- {
- case 1:
- mode = "QI";
- break;
- case 2:
- mode = "HI";
- break;
- case 4:
- mode = "SI";
- break;
- case 8:
- mode = "DI";
- break;
- default:
- internal_error (__FILE__, __LINE__, _("Invalid GCC mode size %d."), size);
- }
- return mode;
- }
- /* See compile-internal.h. */
- char *
- c_get_range_decl_name (const struct dynamic_prop *prop)
- {
- return xstrprintf ("__gdb_prop_%s", host_address_to_string (prop));
- }
- #define STR(x) #x
- #define STRINGIFY(x) STR(x)
- /* Helper function for c_get_compile_context. Open the GCC front-end
- shared library and return the symbol specified by the current
- GCC_C_FE_CONTEXT. */
- static gcc_c_fe_context_function *
- load_libcc (void)
- {
- void *handle;
- gcc_c_fe_context_function *func;
- /* gdb_dlopen will call error () on an error, so no need to check
- value. */
- handle = gdb_dlopen (STRINGIFY (GCC_C_FE_LIBCC));
- func = (gcc_c_fe_context_function *) gdb_dlsym (handle,
- STRINGIFY (GCC_C_FE_CONTEXT));
- if (func == NULL)
- error (_("could not find symbol %s in library %s"),
- STRINGIFY (GCC_C_FE_CONTEXT),
- STRINGIFY (GCC_C_FE_LIBCC));
- return func;
- }
- /* Return the compile instance associated with the current context.
- This function calls the symbol returned from the load_libcc
- function. This will provide the gcc_c_context. */
- struct compile_instance *
- c_get_compile_context (void)
- {
- static gcc_c_fe_context_function *func;
- struct gcc_c_context *context;
- if (func == NULL)
- {
- func = load_libcc ();
- gdb_assert (func != NULL);
- }
- context = (*func) (GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
- if (context == NULL)
- error (_("The loaded version of GCC does not support the required version "
- "of the API."));
- return new_compile_instance (context);
- }
- /* Write one macro definition. */
- static void
- print_one_macro (const char *name, const struct macro_definition *macro,
- struct macro_source_file *source, int line,
- void *user_data)
- {
- struct ui_file *file = user_data;
- /* Don't print command-line defines. They will be supplied another
- way. */
- if (line == 0)
- return;
- fprintf_filtered (file, "#define %s", name);
- if (macro->kind == macro_function_like)
- {
- int i;
- fputs_filtered ("(", file);
- for (i = 0; i < macro->argc; i++)
- {
- fputs_filtered (macro->argv[i], file);
- if (i + 1 < macro->argc)
- fputs_filtered (", ", file);
- }
- fputs_filtered (")", file);
- }
- fprintf_filtered (file, " %s\n", macro->replacement);
- }
- /* Write macro definitions at PC to FILE. */
- static void
- write_macro_definitions (const struct block *block, CORE_ADDR pc,
- struct ui_file *file)
- {
- struct macro_scope *scope;
- if (block != NULL)
- scope = sal_macro_scope (find_pc_line (pc, 0));
- else
- scope = default_macro_scope ();
- if (scope == NULL)
- scope = user_macro_scope ();
- if (scope != NULL && scope->file != NULL && scope->file->table != NULL)
- macro_for_each_in_scope (scope->file, scope->line, print_one_macro, file);
- }
- /* Helper function to construct a header scope for a block of code.
- Takes a scope argument which selects the correct header to
- insert into BUF. */
- static void
- add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
- {
- switch (type)
- {
- case COMPILE_I_SIMPLE_SCOPE:
- fputs_unfiltered ("void "
- GCC_FE_WRAPPER_FUNCTION
- " (struct "
- COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
- " *"
- COMPILE_I_SIMPLE_REGISTER_ARG_NAME
- ") {\n",
- buf);
- break;
- case COMPILE_I_RAW_SCOPE:
- break;
- default:
- gdb_assert_not_reached (_("Unknown compiler scope reached."));
- }
- }
- /* Helper function to construct a footer scope for a block of code.
- Takes a scope argument which selects the correct footer to
- insert into BUF. */
- static void
- add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
- {
- switch (type)
- {
- case COMPILE_I_SIMPLE_SCOPE:
- fputs_unfiltered ("}\n", buf);
- break;
- case COMPILE_I_RAW_SCOPE:
- break;
- default:
- gdb_assert_not_reached (_("Unknown compiler scope reached."));
- }
- }
- /* Generate a structure holding all the registers used by the function
- we're generating. */
- static void
- generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
- const unsigned char *registers_used)
- {
- int i;
- int seen = 0;
- fputs_unfiltered ("struct " COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG " {\n",
- stream);
- if (registers_used != NULL)
- for (i = 0; i < gdbarch_num_regs (gdbarch); ++i)
- {
- if (registers_used[i])
- {
- struct type *regtype = check_typedef (register_type (gdbarch, i));
- char *regname = compile_register_name_mangled (gdbarch, i);
- struct cleanup *cleanups = make_cleanup (xfree, regname);
- seen = 1;
- /* You might think we could use type_print here. However,
- target descriptions often use types with names like
- "int64_t", which may not be defined in the inferior
- (and in any case would not be looked up due to the
- #pragma business). So, we take a much simpler
- approach: for pointer- or integer-typed registers, emit
- the field in the most direct way; and for other
- register types (typically flags or vectors), emit a
- maximally-aligned array of the correct size. */
- fputs_unfiltered (" ", stream);
- switch (TYPE_CODE (regtype))
- {
- case TYPE_CODE_PTR:
- fprintf_filtered (stream, "void *%s", regname);
- break;
- case TYPE_CODE_INT:
- {
- const char *mode
- = c_get_mode_for_size (TYPE_LENGTH (regtype));
- if (mode != NULL)
- {
- if (TYPE_UNSIGNED (regtype))
- fputs_unfiltered ("unsigned ", stream);
- fprintf_unfiltered (stream,
- "int %s"
- " __attribute__ ((__mode__(__%s__)))",
- regname,
- mode);
- break;
- }
- }
- /* Fall through. */
- default:
- fprintf_unfiltered (stream,
- " unsigned char %s[%d]"
- " __attribute__((__aligned__("
- "__BIGGEST_ALIGNMENT__)))",
- regname,
- TYPE_LENGTH (regtype));
- }
- fputs_unfiltered (";\n", stream);
- do_cleanups (cleanups);
- }
- }
- if (!seen)
- fputs_unfiltered (" char " COMPILE_I_SIMPLE_REGISTER_DUMMY ";\n",
- stream);
- fputs_unfiltered ("};\n\n", stream);
- }
- /* Take the source code provided by the user with the 'compile'
- command, and compute the additional wrapping, macro, variable and
- register operations needed. INPUT is the source code derived from
- the 'compile' command, GDBARCH is the architecture to use when
- computing above, EXPR_BLOCK denotes the block relevant contextually
- to the inferior when the expression was created, and EXPR_PC
- indicates the value of $PC. */
- char *
- c_compute_program (struct compile_instance *inst,
- const char *input,
- struct gdbarch *gdbarch,
- const struct block *expr_block,
- CORE_ADDR expr_pc)
- {
- struct ui_file *buf, *var_stream = NULL;
- char *code;
- struct cleanup *cleanup;
- struct compile_c_instance *context = (struct compile_c_instance *) inst;
- buf = mem_fileopen ();
- cleanup = make_cleanup_ui_file_delete (buf);
- write_macro_definitions (expr_block, expr_pc, buf);
- /* Do not generate local variable information for "raw"
- compilations. In this case we aren't emitting our own function
- and the user's code may only refer to globals. */
- if (inst->scope != COMPILE_I_RAW_SCOPE)
- {
- unsigned char *registers_used;
- int i;
- /* Generate the code to compute variable locations, but do it
- before generating the function header, so we can define the
- register struct before the function body. This requires a
- temporary stream. */
- var_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (var_stream);
- registers_used = generate_c_for_variable_locations (context,
- var_stream, gdbarch,
- expr_block, expr_pc);
- make_cleanup (xfree, registers_used);
- generate_register_struct (buf, gdbarch, registers_used);
- fputs_unfiltered ("typedef unsigned int"
- " __attribute__ ((__mode__(__pointer__)))"
- " __gdb_uintptr;\n",
- buf);
- fputs_unfiltered ("typedef int"
- " __attribute__ ((__mode__(__pointer__)))"
- " __gdb_intptr;\n",
- buf);
- // Iterate all log2 sizes in bytes supported by c_get_mode_for_size.
- for (i = 0; i < 4; ++i)
- {
- const char *mode = c_get_mode_for_size (1 << i);
- gdb_assert (mode != NULL);
- fprintf_unfiltered (buf,
- "typedef int"
- " __attribute__ ((__mode__(__%s__)))"
- " __gdb_int_%s;\n",
- mode, mode);
- }
- }
- add_code_header (inst->scope, buf);
- if (inst->scope == COMPILE_I_SIMPLE_SCOPE)
- {
- ui_file_put (var_stream, ui_file_write_for_put, buf);
- fputs_unfiltered ("#pragma GCC user_expression\n", buf);
- }
- /* The user expression has to be in its own scope, so that "extern"
- works properly. Otherwise gcc thinks that the "extern"
- declaration is in the same scope as the declaration provided by
- gdb. */
- if (inst->scope != COMPILE_I_RAW_SCOPE)
- fputs_unfiltered ("{\n", buf);
- fputs_unfiltered ("#line 1 \"gdb command line\"\n", buf);
- fputs_unfiltered (input, buf);
- fputs_unfiltered ("\n", buf);
- /* For larger user expressions the automatic semicolons may be
- confusing. */
- if (strchr (input, '\n') == NULL)
- fputs_unfiltered (";\n", buf);
- if (inst->scope != COMPILE_I_RAW_SCOPE)
- fputs_unfiltered ("}\n", buf);
- add_code_footer (inst->scope, buf);
- code = ui_file_xstrdup (buf, NULL);
- do_cleanups (cleanup);
- return code;
- }