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; addr = MSYMBOL_VALUE_ADDRESS (objfile, msym); /* Conversion copied from write_exp_msymbol. */ 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: /* nodebug_text_gnu_ifunc_symbol would cause: function return type cannot be function */ type = objfile_type (objfile)->nodebug_text_symbol; kind = GCC_C_SYMBOL_FUNCTION; addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); 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); 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 /* is_global */); }
CORE_ADDR find_function_addr (struct value *function, struct type **retval_type) { struct type *ftype = check_typedef (value_type (function)); struct gdbarch *gdbarch = get_type_arch (ftype); struct type *value_type = NULL; /* Initialize it just to avoid a GCC false warning. */ CORE_ADDR funaddr = 0; /* If it's a member function, just look at the function part of it. */ /* Determine address to call. */ if (TYPE_CODE (ftype) == TYPE_CODE_FUNC || TYPE_CODE (ftype) == TYPE_CODE_METHOD) funaddr = value_address (function); else if (TYPE_CODE (ftype) == TYPE_CODE_PTR) { funaddr = value_as_address (function); ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); if (TYPE_CODE (ftype) == TYPE_CODE_FUNC || TYPE_CODE (ftype) == TYPE_CODE_METHOD) funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr, ¤t_target); } if (TYPE_CODE (ftype) == TYPE_CODE_FUNC || TYPE_CODE (ftype) == TYPE_CODE_METHOD) { value_type = TYPE_TARGET_TYPE (ftype); if (TYPE_GNU_IFUNC (ftype)) { funaddr = gnu_ifunc_resolve_addr (gdbarch, funaddr); /* Skip querying the function symbol if no RETVAL_TYPE has been asked for. */ if (retval_type) value_type = find_function_return_type (funaddr); } } else if (TYPE_CODE (ftype) == TYPE_CODE_INT) { /* Handle the case of functions lacking debugging info. Their values are characters since their addresses are char. */ if (TYPE_LENGTH (ftype) == 1) funaddr = value_as_address (value_addr (function)); else { /* Handle function descriptors lacking debug info. */ int found_descriptor = 0; funaddr = 0; /* pacify "gcc -Werror" */ if (VALUE_LVAL (function) == lval_memory) { CORE_ADDR nfunaddr; funaddr = value_as_address (value_addr (function)); nfunaddr = funaddr; funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr, ¤t_target); if (funaddr != nfunaddr) found_descriptor = 1; } if (!found_descriptor) /* Handle integer used as address of a function. */ funaddr = (CORE_ADDR) value_as_long (function); } } else error (_("Invalid data type for function to be called.")); if (retval_type != NULL) *retval_type = value_type; return funaddr + gdbarch_deprecated_function_start_offset (gdbarch); }
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) { /* Binding a tag, so we don't need to build a decl. */ 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)); if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym))) addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); break; case LOC_CONST: if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM) { /* Already handled by convert_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; /* Probably TLS here. */ warning (_("Symbol \"%s\" is thread-local and currently can only " "be referenced from the current thread in " "compiled code."), SYMBOL_PRINT_NAME (sym)); /* FALLTHROUGH */ case LOC_UNRESOLVED: /* 'symbol_name' cannot be used here as that one is used only for local variables from compile_dwarf_expr_to_c. Global variables can be accessed by GCC only by their address, not by their name. */ { 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."); } /* Don't emit local variable decls for a raw expression. */ 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); } }
struct compile_module * compile_object_load (const char *object_file, const char *source_file, enum compile_i_scope_types scope, void *scope_data) { struct cleanup *cleanups, *cleanups_free_objfile; bfd *abfd; struct setup_sections_data setup_sections_data; CORE_ADDR addr, regs_addr, out_value_addr = 0; struct symbol *func_sym; struct type *func_type; struct bound_minimal_symbol bmsym; long storage_needed; asymbol **symbol_table, **symp; long number_of_symbols, missing_symbols; struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; unsigned dptr_type_len = TYPE_LENGTH (dptr_type); struct compile_module *retval; struct type *regs_type, *out_value_type = NULL; char *filename, **matching; struct objfile *objfile; int expect_parameters; struct type *expect_return_type; struct munmap_list *munmap_list_head = NULL; filename = tilde_expand (object_file); cleanups = make_cleanup (xfree, filename); abfd = gdb_bfd_open (filename, gnutarget, -1); if (abfd == NULL) error (_("\"%s\": could not open as compiled module: %s"), filename, bfd_errmsg (bfd_get_error ())); make_cleanup_bfd_unref (abfd); if (!bfd_check_format_matches (abfd, bfd_object, &matching)) error (_("\"%s\": not in loadable format: %s"), filename, gdb_bfd_errmsg (bfd_get_error (), matching)); if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0) error (_("\"%s\": not in object format."), filename); setup_sections_data.last_size = 0; setup_sections_data.last_section_first = abfd->sections; setup_sections_data.last_prot = -1; setup_sections_data.last_max_alignment = 1; setup_sections_data.munmap_list_headp = &munmap_list_head; make_cleanup (munmap_listp_free_cleanup, &munmap_list_head); bfd_map_over_sections (abfd, setup_sections, &setup_sections_data); setup_sections (abfd, NULL, &setup_sections_data); storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed < 0) error (_("Cannot read symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in "Reading symbols from ..." message for automatically generated file. */ objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL); cleanups_free_objfile = make_cleanup_free_objfile (objfile); func_sym = lookup_global_symbol_from_objfile (objfile, GCC_FE_WRAPPER_FUNCTION, VAR_DOMAIN).symbol; if (func_sym == NULL) error (_("Cannot find function \"%s\" in compiled module \"%s\"."), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); func_type = SYMBOL_TYPE (func_sym); if (TYPE_CODE (func_type) != TYPE_CODE_FUNC) error (_("Invalid type code %d of function \"%s\" in compiled " "module \"%s\"."), TYPE_CODE (func_type), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); switch (scope) { case COMPILE_I_SIMPLE_SCOPE: expect_parameters = 1; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; case COMPILE_I_RAW_SCOPE: expect_parameters = 0; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: expect_parameters = 2; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; default: internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope); } if (TYPE_NFIELDS (func_type) != expect_parameters) error (_("Invalid %d parameters of function \"%s\" in compiled " "module \"%s\"."), TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); if (!types_deeply_equal (expect_return_type, TYPE_TARGET_TYPE (func_type))) error (_("Invalid return type of function \"%s\" in compiled " "module \"%s\"."), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); /* The memory may be later needed by bfd_generic_get_relocated_section_contents called from default_symfile_relocate. */ symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); if (number_of_symbols < 0) error (_("Cannot parse symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); missing_symbols = 0; for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++) { asymbol *sym = *symp; if (sym->flags != 0) continue; sym->flags = BSF_GLOBAL; sym->section = bfd_abs_section_ptr; if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0) { if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF symbol \"%s\" relocated to zero\n", sym->name); /* It seems to be a GCC bug, with -mcmodel=large there should be no need for _GLOBAL_OFFSET_TABLE_. Together with -fPIE the data remain PC-relative even with _GLOBAL_OFFSET_TABLE_ as zero. */ sym->value = 0; continue; } bmsym = lookup_minimal_symbol (sym->name, NULL, NULL); switch (bmsym.minsym == NULL ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym)) { case mst_text: sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF mst_text symbol \"%s\" relocated to %s\n", sym->name, paddress (target_gdbarch (), sym->value)); break; case mst_text_gnu_ifunc: sym->value = gnu_ifunc_resolve_addr (target_gdbarch (), BMSYMBOL_VALUE_ADDRESS (bmsym)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF mst_text_gnu_ifunc symbol \"%s\" " "relocated to %s\n", sym->name, paddress (target_gdbarch (), sym->value)); break; default: warning (_("Could not find symbol \"%s\" " "for compiled module \"%s\"."), sym->name, filename); missing_symbols++; } } if (missing_symbols) error (_("%ld symbols were missing, cannot continue."), missing_symbols); bfd_map_over_sections (abfd, copy_sections, symbol_table); regs_type = get_regs_type (func_sym, objfile); if (regs_type == NULL) regs_addr = 0; else { /* Use read-only non-executable memory protection. */ regs_addr = gdbarch_infcall_mmap (target_gdbarch (), TYPE_LENGTH (regs_type), GDB_MMAP_PROT_READ); gdb_assert (regs_addr != 0); munmap_list_add (&munmap_list_head, regs_addr, TYPE_LENGTH (regs_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for registers\n", paddress (target_gdbarch (), TYPE_LENGTH (regs_type)), paddress (target_gdbarch (), regs_addr)); store_regs (regs_type, regs_addr); } if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE || scope == COMPILE_I_PRINT_VALUE_SCOPE) { out_value_type = get_out_value_type (func_sym, objfile, scope); if (out_value_type == NULL) { do_cleanups (cleanups); return NULL; } check_typedef (out_value_type); out_value_addr = gdbarch_infcall_mmap (target_gdbarch (), TYPE_LENGTH (out_value_type), (GDB_MMAP_PROT_READ | GDB_MMAP_PROT_WRITE)); gdb_assert (out_value_addr != 0); munmap_list_add (&munmap_list_head, out_value_addr, TYPE_LENGTH (out_value_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for printed value\n", paddress (target_gdbarch (), TYPE_LENGTH (out_value_type)), paddress (target_gdbarch (), out_value_addr)); } discard_cleanups (cleanups_free_objfile); retval = xmalloc (sizeof (*retval)); retval->objfile = objfile; retval->source_file = xstrdup (source_file); retval->func_sym = func_sym; retval->regs_addr = regs_addr; retval->scope = scope; retval->scope_data = scope_data; retval->out_value_type = out_value_type; retval->out_value_addr = out_value_addr; /* CLEANUPS will free MUNMAP_LIST_HEAD. */ retval->munmap_list_head = munmap_list_head; munmap_list_head = NULL; do_cleanups (cleanups); return retval; }