gdb/compile/compile-c-symbols.c - gdb
Data types defined
Functions defined
Source code
- #include "defs.h"
- #include "compile-internal.h"
- #include "gdb_assert.h"
- #include "symtab.h"
- #include "parser-defs.h"
- #include "block.h"
- #include "objfiles.h"
- #include "compile.h"
- #include "value.h"
- #include "exceptions.h"
- #include "gdbtypes.h"
- #include "dwarf2loc.h"
- struct symbol_error
- {
-
- const struct symbol *sym;
-
- char *message;
- };
- static hashval_t
- hash_symbol_error (const void *a)
- {
- const struct symbol_error *se = a;
- return htab_hash_pointer (se->sym);
- }
- static int
- eq_symbol_error (const void *a, const void *b)
- {
- const struct symbol_error *sea = a;
- const struct symbol_error *seb = b;
- return sea->sym == seb->sym;
- }
- static void
- del_symbol_error (void *a)
- {
- struct symbol_error *se = a;
- xfree (se->message);
- xfree (se);
- }
- static void
- insert_symbol_error (htab_t hash, const struct symbol *sym, const char *text)
- {
- struct symbol_error e;
- void **slot;
- e.sym = sym;
- slot = htab_find_slot (hash, &e, INSERT);
- if (*slot == NULL)
- {
- struct symbol_error *e = XNEW (struct symbol_error);
- e->sym = sym;
- e->message = xstrdup (text);
- *slot = e;
- }
- }
- static void
- error_symbol_once (struct compile_c_instance *context,
- const struct symbol *sym)
- {
- struct symbol_error search;
- struct symbol_error *err;
- char *message;
- if (context->symbol_err_map == NULL)
- return;
- search.sym = sym;
- err = htab_find (context->symbol_err_map, &search);
- if (err == NULL || err->message == NULL)
- return;
- message = err->message;
- err->message = NULL;
- make_cleanup (xfree, message);
- error (_("%s"), message);
- }
- static char *
- symbol_substitution_name (struct symbol *sym)
- {
- return concat ("__", SYMBOL_NATURAL_NAME (sym), "_ptr", (char *) NULL);
- }
- static void
- convert_one_symbol (struct compile_c_instance *context,
- struct symbol *sym,
- int is_global,
- int is_local)
- {
- gcc_type sym_type;
- const char *filename = symbol_symtab (sym)->filename;
- unsigned short line = SYMBOL_LINE (sym);
- error_symbol_once (context, sym);
- if (SYMBOL_CLASS (sym) == LOC_LABEL)
- sym_type = 0;
- else
- sym_type = convert_type (context, SYMBOL_TYPE (sym));
- if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN)
- {
-
- C_CTX (context)->c_ops->tagbind (C_CTX (context),
- SYMBOL_NATURAL_NAME (sym),
- sym_type, filename, line);
- }
- else
- {
- gcc_decl decl;
- enum gcc_c_symbol_kind kind;
- CORE_ADDR addr = 0;
- char *symbol_name = NULL;
- switch (SYMBOL_CLASS (sym))
- {
- case LOC_TYPEDEF:
- kind = GCC_C_SYMBOL_TYPEDEF;
- break;
- case LOC_LABEL:
- kind = GCC_C_SYMBOL_LABEL;
- addr = SYMBOL_VALUE_ADDRESS (sym);
- break;
- case LOC_BLOCK:
- kind = GCC_C_SYMBOL_FUNCTION;
- addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- break;
- case LOC_CONST:
- if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM)
- {
-
- return;
- }
- C_CTX (context)->c_ops->build_constant (C_CTX (context), sym_type,
- SYMBOL_NATURAL_NAME (sym),
- SYMBOL_VALUE (sym),
- filename, line);
- return;
- case LOC_CONST_BYTES:
- error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."),
- SYMBOL_PRINT_NAME (sym));
- case LOC_UNDEF:
- internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."),
- SYMBOL_PRINT_NAME (sym));
- case LOC_COMMON_BLOCK:
- error (_("Fortran common block is unsupported for compilation "
- "evaluaton of symbol \"%s\"."),
- SYMBOL_PRINT_NAME (sym));
- case LOC_OPTIMIZED_OUT:
- error (_("Symbol \"%s\" cannot be used for compilation evaluation "
- "as it is optimized out."),
- SYMBOL_PRINT_NAME (sym));
- case LOC_COMPUTED:
- if (is_local)
- goto substitution;
-
- warning (_("Symbol \"%s\" is thread-local and currently can only "
- "be referenced from the current thread in "
- "compiled code."),
- SYMBOL_PRINT_NAME (sym));
-
- case LOC_UNRESOLVED:
-
- {
- struct value *val;
- struct frame_info *frame = NULL;
- if (symbol_read_needs_frame (sym))
- {
- frame = get_selected_frame (NULL);
- if (frame == NULL)
- error (_("Symbol \"%s\" cannot be used because "
- "there is no selected frame"),
- SYMBOL_PRINT_NAME (sym));
- }
- val = read_var_value (sym, frame);
- if (VALUE_LVAL (val) != lval_memory)
- error (_("Symbol \"%s\" cannot be used for compilation "
- "evaluation as its address has not been found."),
- SYMBOL_PRINT_NAME (sym));
- kind = GCC_C_SYMBOL_VARIABLE;
- addr = value_address (val);
- }
- break;
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM_ADDR:
- case LOC_LOCAL:
- substitution:
- kind = GCC_C_SYMBOL_VARIABLE;
- symbol_name = symbol_substitution_name (sym);
- break;
- case LOC_STATIC:
- kind = GCC_C_SYMBOL_VARIABLE;
- addr = SYMBOL_VALUE_ADDRESS (sym);
- break;
- case LOC_FINAL_VALUE:
- default:
- gdb_assert_not_reached ("Unreachable case in convert_one_symbol.");
- }
-
- if (context->base.scope != COMPILE_I_RAW_SCOPE
- || symbol_name == NULL)
- {
- decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
- SYMBOL_NATURAL_NAME (sym),
- kind,
- sym_type,
- symbol_name, addr,
- filename, line);
- C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global);
- }
- xfree (symbol_name);
- }
- }
- static void
- convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
- struct symbol *sym, domain_enum domain)
- {
- const struct block *static_block, *found_block;
- int is_local_symbol;
- found_block = block_found;
-
- static_block = block_static_block (found_block);
-
- is_local_symbol = (found_block != static_block && static_block != NULL);
- if (is_local_symbol)
- {
- struct symbol *global_sym;
- global_sym = lookup_symbol (identifier, NULL, domain, NULL);
-
- if (global_sym != NULL
- && block_found != block_static_block (block_found))
- {
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout,
- "gcc_convert_symbol \"%s\": global symbol\n",
- identifier);
- convert_one_symbol (context, global_sym, 1, 0);
- }
- }
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout,
- "gcc_convert_symbol \"%s\": local symbol\n",
- identifier);
- convert_one_symbol (context, sym, 0, is_local_symbol);
- }
- static void
- convert_symbol_bmsym (struct compile_c_instance *context,
- struct bound_minimal_symbol bmsym)
- {
- struct minimal_symbol *msym = bmsym.minsym;
- struct objfile *objfile = bmsym.objfile;
- struct type *type;
- enum gcc_c_symbol_kind kind;
- gcc_type sym_type;
- gcc_decl decl;
- CORE_ADDR addr;
-
- switch (MSYMBOL_TYPE (msym))
- {
- case mst_text:
- case mst_file_text:
- case mst_solib_trampoline:
- type = objfile_type (objfile)->nodebug_text_symbol;
- kind = GCC_C_SYMBOL_FUNCTION;
- break;
- case mst_text_gnu_ifunc:
- type = objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol;
- kind = GCC_C_SYMBOL_FUNCTION;
- break;
- case mst_data:
- case mst_file_data:
- case mst_bss:
- case mst_file_bss:
- type = objfile_type (objfile)->nodebug_data_symbol;
- kind = GCC_C_SYMBOL_VARIABLE;
- break;
- case mst_slot_got_plt:
- type = objfile_type (objfile)->nodebug_got_plt_symbol;
- kind = GCC_C_SYMBOL_FUNCTION;
- break;
- default:
- type = objfile_type (objfile)->nodebug_unknown_symbol;
- kind = GCC_C_SYMBOL_VARIABLE;
- break;
- }
- sym_type = convert_type (context, type);
- addr = MSYMBOL_VALUE_ADDRESS (objfile, msym);
- decl = C_CTX (context)->c_ops->build_decl (C_CTX (context),
- MSYMBOL_NATURAL_NAME (msym),
- kind, sym_type, NULL, addr,
- NULL, 0);
- C_CTX (context)->c_ops->bind (C_CTX (context), decl, 1 );
- }
- void
- gcc_convert_symbol (void *datum,
- struct gcc_c_context *gcc_context,
- enum gcc_c_oracle_request request,
- const char *identifier)
- {
- struct compile_c_instance *context = datum;
- domain_enum domain;
- volatile struct gdb_exception e;
- int found = 0;
- switch (request)
- {
- case GCC_C_ORACLE_SYMBOL:
- domain = VAR_DOMAIN;
- break;
- case GCC_C_ORACLE_TAG:
- domain = STRUCT_DOMAIN;
- break;
- case GCC_C_ORACLE_LABEL:
- domain = LABEL_DOMAIN;
- break;
- default:
- gdb_assert_not_reached ("Unrecognized oracle request.");
- }
-
- TRY_CATCH (e, RETURN_MASK_ALL)
- {
- struct symbol *sym;
- sym = lookup_symbol (identifier, context->base.block, domain, NULL);
- if (sym != NULL)
- {
- convert_symbol_sym (context, identifier, sym, domain);
- found = 1;
- }
- else if (domain == VAR_DOMAIN)
- {
- struct bound_minimal_symbol bmsym;
- bmsym = lookup_minimal_symbol (identifier, NULL, NULL);
- if (bmsym.minsym != NULL)
- {
- convert_symbol_bmsym (context, bmsym);
- found = 1;
- }
- }
- }
- if (e.reason < 0)
- C_CTX (context)->c_ops->error (C_CTX (context), e.message);
- if (compile_debug && !found)
- fprintf_unfiltered (gdb_stdout,
- "gcc_convert_symbol \"%s\": lookup_symbol failed\n",
- identifier);
- return;
- }
- gcc_address
- gcc_symbol_address (void *datum, struct gcc_c_context *gcc_context,
- const char *identifier)
- {
- struct compile_c_instance *context = datum;
- volatile struct gdb_exception e;
- gcc_address result = 0;
- int found = 0;
-
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- struct symbol *sym;
-
- sym = lookup_symbol (identifier, NULL, VAR_DOMAIN, NULL);
- if (sym != NULL && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout,
- "gcc_symbol_address \"%s\": full symbol\n",
- identifier);
- result = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- found = 1;
- }
- else
- {
- struct bound_minimal_symbol msym;
- msym = lookup_bound_minimal_symbol (identifier);
- if (msym.minsym != NULL)
- {
- if (compile_debug)
- fprintf_unfiltered (gdb_stdout,
- "gcc_symbol_address \"%s\": minimal "
- "symbol\n",
- identifier);
- result = BMSYMBOL_VALUE_ADDRESS (msym);
- found = 1;
- }
- }
- }
- if (e.reason < 0)
- C_CTX (context)->c_ops->error (C_CTX (context), e.message);
- if (compile_debug && !found)
- fprintf_unfiltered (gdb_stdout,
- "gcc_symbol_address \"%s\": failed\n",
- identifier);
- return result;
- }
- static hashval_t
- hash_symname (const void *a)
- {
- const struct symbol *sym = a;
- return htab_hash_string (SYMBOL_NATURAL_NAME (sym));
- }
- static int
- eq_symname (const void *a, const void *b)
- {
- const struct symbol *syma = a;
- const struct symbol *symb = b;
- return strcmp (SYMBOL_NATURAL_NAME (syma), SYMBOL_NATURAL_NAME (symb)) == 0;
- }
- static int
- symbol_seen (htab_t hashtab, struct symbol *sym)
- {
- void **slot;
- slot = htab_find_slot (hashtab, sym, INSERT);
- if (*slot != NULL)
- return 1;
- *slot = sym;
- return 0;
- }
- static void
- generate_vla_size (struct compile_c_instance *compiler,
- struct ui_file *stream,
- struct gdbarch *gdbarch,
- unsigned char *registers_used,
- CORE_ADDR pc,
- struct type *type,
- struct symbol *sym)
- {
- type = check_typedef (type);
- if (TYPE_CODE (type) == TYPE_CODE_REF)
- type = check_typedef (TYPE_TARGET_TYPE (type));
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_RANGE:
- {
- if (TYPE_HIGH_BOUND_KIND (type) == PROP_LOCEXPR
- || TYPE_HIGH_BOUND_KIND (type) == PROP_LOCLIST)
- {
- const struct dynamic_prop *prop = &TYPE_RANGE_DATA (type)->high;
- char *name = c_get_range_decl_name (prop);
- struct cleanup *cleanup = make_cleanup (xfree, name);
- dwarf2_compile_property_to_c (stream, name,
- gdbarch, registers_used,
- prop, pc, sym);
- do_cleanups (cleanup);
- }
- }
- break;
- case TYPE_CODE_ARRAY:
- generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
- TYPE_INDEX_TYPE (type), sym);
- generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
- TYPE_TARGET_TYPE (type), sym);
- break;
- case TYPE_CODE_UNION:
- case TYPE_CODE_STRUCT:
- {
- int i;
- for (i = 0; i < TYPE_NFIELDS (type); ++i)
- if (!field_is_static (&TYPE_FIELD (type, i)))
- generate_vla_size (compiler, stream, gdbarch, registers_used, pc,
- TYPE_FIELD_TYPE (type, i), sym);
- }
- break;
- }
- }
- static void
- generate_c_for_for_one_variable (struct compile_c_instance *compiler,
- struct ui_file *stream,
- struct gdbarch *gdbarch,
- unsigned char *registers_used,
- CORE_ADDR pc,
- struct symbol *sym)
- {
- volatile struct gdb_exception e;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- if (is_dynamic_type (SYMBOL_TYPE (sym)))
- {
- struct ui_file *size_file = mem_fileopen ();
- struct cleanup *cleanup = make_cleanup_ui_file_delete (size_file);
- generate_vla_size (compiler, size_file, gdbarch, registers_used, pc,
- SYMBOL_TYPE (sym), sym);
- ui_file_put (size_file, ui_file_write_for_put, stream);
- do_cleanups (cleanup);
- }
- if (SYMBOL_COMPUTED_OPS (sym) != NULL)
- {
- char *generated_name = symbol_substitution_name (sym);
- struct cleanup *cleanup = make_cleanup (xfree, generated_name);
-
- struct ui_file *local_file = mem_fileopen ();
- make_cleanup_ui_file_delete (local_file);
- SYMBOL_COMPUTED_OPS (sym)->generate_c_location (sym, local_file,
- gdbarch,
- registers_used,
- pc, generated_name);
- ui_file_put (local_file, ui_file_write_for_put, stream);
- do_cleanups (cleanup);
- }
- else
- {
- switch (SYMBOL_CLASS (sym))
- {
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM_ADDR:
- case LOC_LOCAL:
- error (_("Local symbol unhandled when generating C code."));
- case LOC_COMPUTED:
- gdb_assert_not_reached (_("LOC_COMPUTED variable "
- "missing a method."));
- default:
-
- break;
- }
- }
- }
- if (e.reason >= 0)
- return;
- if (compiler->symbol_err_map == NULL)
- compiler->symbol_err_map = htab_create_alloc (10,
- hash_symbol_error,
- eq_symbol_error,
- del_symbol_error,
- xcalloc,
- xfree);
- insert_symbol_error (compiler->symbol_err_map, sym, e.message);
- }
- unsigned char *
- generate_c_for_variable_locations (struct compile_c_instance *compiler,
- struct ui_file *stream,
- struct gdbarch *gdbarch,
- const struct block *block,
- CORE_ADDR pc)
- {
- struct cleanup *cleanup, *outer;
- htab_t symhash;
- const struct block *static_block = block_static_block (block);
- unsigned char *registers_used;
-
- if (static_block == NULL || block == static_block)
- return NULL;
- registers_used = XCNEWVEC (unsigned char, gdbarch_num_regs (gdbarch));
- outer = make_cleanup (xfree, registers_used);
-
- symhash = htab_create_alloc (1, hash_symname, eq_symname, NULL,
- xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (symhash);
- while (1)
- {
- struct symbol *sym;
- struct block_iterator iter;
-
- for (sym = block_iterator_first (block, &iter);
- sym != NULL;
- sym = block_iterator_next (&iter))
- {
- if (!symbol_seen (symhash, sym))
- generate_c_for_for_one_variable (compiler, stream, gdbarch,
- registers_used, pc, sym);
- }
-
- if (BLOCK_FUNCTION (block) != NULL)
- break;
- block = BLOCK_SUPERBLOCK (block);
- }
- do_cleanups (cleanup);
- discard_cleanups (outer);
- return registers_used;
- }