int inside_main_func (CORE_ADDR pc) { if (pc == 0) return 1; if (symfile_objfile == 0) return 0; /* If the addr range is not set up at symbol reading time, set it up now. This is for FRAME_CHAIN_VALID_ALTERNATE. I do this for coff, because it is unable to set it up and symbol reading time. */ if (symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { struct symbol *mainsym; mainsym = lookup_symbol (main_name (), NULL, VAR_NAMESPACE, NULL, NULL); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } } return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); }
static int there_is_a_visible_common_named (char *comname) { SAVED_F77_COMMON_PTR the_common; struct frame_info *fi; char *funname = 0; struct symbol *func; if (comname == NULL) error (_("Cannot deal with NULL common name!")); fi = deprecated_selected_frame; if (fi == NULL) error (_("No frame selected")); /* The following is generally ripped off from stack.c's routine print_frame_info() */ func = find_pc_function (fi->pc); if (func) { /* In certain pathological cases, the symtabs give the wrong function (when we are in the first function in a file which is compiled without debugging symbols, the previous function is compiled with debugging symbols, and the "foo.o" symbol that is supposed to tell us where the file with debugging symbols ends has been truncated by ar because it is longer than 15 characters). So look in the minimal symbol tables as well, and if it comes up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. FIXME: (Not necessarily true. What about text labels) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); /* APPLE LOCAL begin address ranges */ if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (func)))) /* APPLE LOCAL end address ranges */ funname = DEPRECATED_SYMBOL_NAME (msymbol); else funname = DEPRECATED_SYMBOL_NAME (func); } else { struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc); if (msymbol != NULL) funname = DEPRECATED_SYMBOL_NAME (msymbol); } the_common = find_common_for_function (comname, funname); return (the_common ? 1 : 0); }
CORE_ADDR get_pc_function_start (CORE_ADDR pc) { struct block *bl; struct minimal_symbol *msymbol; bl = block_for_pc (pc); if (bl) { struct symbol *symbol = block_function (bl); if (symbol) { bl = SYMBOL_BLOCK_VALUE (symbol); /* APPLE LOCAL begin address ranges */ return BLOCK_LOWEST_PC (bl); /* APPLE LOCAL end address ranges */ } } msymbol = lookup_minimal_symbol_by_pc (pc); if (msymbol) { CORE_ADDR fstart = SYMBOL_VALUE_ADDRESS (msymbol); if (find_pc_section (fstart)) return fstart; } return 0; }
CORE_ADDR get_pc_function_start (CORE_ADDR pc) { struct block *bl; struct minimal_symbol *msymbol; bl = block_for_pc (pc); if (bl) { struct symbol *symbol = block_linkage_function (bl); if (symbol) { bl = SYMBOL_BLOCK_VALUE (symbol); return BLOCK_START (bl); } } msymbol = lookup_minimal_symbol_by_pc (pc); if (msymbol) { CORE_ADDR fstart = SYMBOL_VALUE_ADDRESS (msymbol); if (find_pc_section (fstart)) return fstart; } return 0; }
struct type * find_function_type (CORE_ADDR pc) { struct symbol *sym = find_pc_function (pc); if (sym != NULL && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == pc) return SYMBOL_TYPE (sym); return NULL; }
static struct type * find_function_return_type (CORE_ADDR pc) { struct symbol *sym = find_pc_function (pc); if (sym != NULL && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == pc && SYMBOL_TYPE (sym) != NULL) return TYPE_TARGET_TYPE (SYMBOL_TYPE (sym)); return NULL; }
static void nlm_symfile_read (struct objfile *objfile, int mainline) { bfd *abfd = objfile->obfd; struct cleanup *back_to; CORE_ADDR offset; struct symbol *mainsym; init_minimal_symbol_collection (); back_to = make_cleanup_discard_minimal_symbols (); /* FIXME, should take a section_offsets param, not just an offset. */ offset = ANOFFSET (objfile->section_offsets, 0); /* Process the NLM export records, which become the bfd's canonical symbol table. */ nlm_symtab_read (abfd, offset, objfile); /* Install any minimal symbols that have been collected as the current minimal symbols for this objfile. */ install_minimal_symbols (objfile); do_cleanups (back_to); stabsect_build_psymtabs (objfile, mainline, ".stab", ".stabstr", ".text"); mainsym = lookup_symbol (main_name (), NULL, VAR_DOMAIN, NULL, NULL); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } /* FIXME: We could locate and read the optional native debugging format here and add the symbols to the minimal symbol table. */ }
CORE_ADDR get_pc_function_start (CORE_ADDR pc) { register struct block *bl; register struct symbol *symbol; register struct minimal_symbol *msymbol; CORE_ADDR fstart; if ((bl = block_for_pc (pc)) != NULL && (symbol = block_function (bl)) != NULL) { bl = SYMBOL_BLOCK_VALUE (symbol); fstart = BLOCK_START (bl); } else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL) { fstart = SYMBOL_VALUE_ADDRESS (msymbol); } else { fstart = 0; } return (fstart); }
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); } }
static void info_common_command (char *comname, int from_tty) { SAVED_F77_COMMON_PTR the_common; COMMON_ENTRY_PTR entry; struct frame_info *fi; char *funname = 0; struct symbol *func; /* We have been told to display the contents of F77 COMMON block supposedly visible in this function. Let us first make sure that it is visible and if so, let us display its contents */ fi = deprecated_selected_frame; if (fi == NULL) error ("No frame selected"); /* The following is generally ripped off from stack.c's routine print_frame_info() */ func = find_pc_function (get_frame_pc (fi)); if (func) { /* In certain pathological cases, the symtabs give the wrong function (when we are in the first function in a file which is compiled without debugging symbols, the previous function is compiled with debugging symbols, and the "foo.o" symbol that is supposed to tell us where the file with debugging symbols ends has been truncated by ar because it is longer than 15 characters). So look in the minimal symbol tables as well, and if it comes up with a larger address for the function use that instead. I don't think this can ever cause any problems; there shouldn't be any minimal symbols in the middle of a function. FIXME: (Not necessarily true. What about text labels) */ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL && (SYMBOL_VALUE_ADDRESS (msymbol) > BLOCK_START (SYMBOL_BLOCK_VALUE (func)))) funname = DEPRECATED_SYMBOL_NAME (msymbol); else funname = DEPRECATED_SYMBOL_NAME (func); } else { struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi)); if (msymbol != NULL) funname = DEPRECATED_SYMBOL_NAME (msymbol); } /* If comname is NULL, we assume the user wishes to see the which COMMON blocks are visible here and then return */ if (comname == 0) { list_all_visible_commons (funname); return; } the_common = find_common_for_function (comname, funname); if (the_common) { if (strcmp (comname, BLANK_COMMON_NAME_LOCAL) == 0) printf_filtered ("Contents of blank COMMON block:\n"); else printf_filtered ("Contents of F77 COMMON block '%s':\n", comname); printf_filtered ("\n"); entry = the_common->entries; while (entry != NULL) { printf_filtered ("%s = ", DEPRECATED_SYMBOL_NAME (entry->symbol)); print_variable_value (entry->symbol, fi, gdb_stdout); printf_filtered ("\n"); entry = entry->next; } } else printf_filtered ("Cannot locate the common block %s in function '%s'\n", comname, funname); }
int find_pc_sect_partial_function (CORE_ADDR pc, asection *section, char **name, CORE_ADDR *address, CORE_ADDR *endaddr) { struct partial_symtab *pst; struct symbol *f; struct minimal_symbol *msymbol; struct partial_symbol *psb; struct obj_section *osect; int i; CORE_ADDR mapped_pc; mapped_pc = overlay_mapped_address (pc, section); if (mapped_pc >= cache_pc_function_low && mapped_pc < cache_pc_function_high && section == cache_pc_function_section) goto return_cached_value; /* If sigtramp is in the u area, it counts as a function (especially important for step_1). */ if (SIGTRAMP_START_P () && PC_IN_SIGTRAMP (mapped_pc, (char *) NULL)) { cache_pc_function_low = SIGTRAMP_START (mapped_pc); cache_pc_function_high = SIGTRAMP_END (mapped_pc); cache_pc_function_name = "<sigtramp>"; cache_pc_function_section = section; goto return_cached_value; } msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section); pst = find_pc_sect_psymtab (mapped_pc, section); if (pst) { /* Need to read the symbols to get a good value for the end address. */ if (endaddr != NULL && !pst->readin) { /* Need to get the terminal in case symbol-reading produces output. */ target_terminal_ours_for_output (); PSYMTAB_TO_SYMTAB (pst); } if (pst->readin) { /* Checking whether the msymbol has a larger value is for the "pathological" case mentioned in print_frame_info. */ f = find_pc_sect_function (mapped_pc, section); if (f != NULL && (msymbol == NULL || (BLOCK_START (SYMBOL_BLOCK_VALUE (f)) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_name = DEPRECATED_SYMBOL_NAME (f); cache_pc_function_section = section; goto return_cached_value; } } else { /* Now that static symbols go in the minimal symbol table, perhaps we could just ignore the partial symbols. But at least for now we use the partial or minimal symbol, whichever is larger. */ psb = find_pc_sect_psymbol (pst, mapped_pc, section); if (psb && (msymbol == NULL || (SYMBOL_VALUE_ADDRESS (psb) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { /* This case isn't being cached currently. */ if (address) *address = SYMBOL_VALUE_ADDRESS (psb); if (name) *name = DEPRECATED_SYMBOL_NAME (psb); /* endaddr non-NULL can't happen here. */ return 1; } } } /* Not in the normal symbol tables, see if the pc is in a known section. If it's not, then give up. This ensures that anything beyond the end of the text seg doesn't appear to be part of the last function in the text segment. */ osect = find_pc_sect_section (mapped_pc, section); if (!osect) msymbol = NULL; /* Must be in the minimal symbol table. */ if (msymbol == NULL) { /* No available symbol. */ if (name != NULL) *name = 0; if (address != NULL) *address = 0; if (endaddr != NULL) *endaddr = 0; return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = DEPRECATED_SYMBOL_NAME (msymbol); cache_pc_function_section = section; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol) && SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol)) break; } if (DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ cache_pc_function_high = osect->endaddr; return_cached_value: if (address) { if (pc_in_unmapped_range (pc, section)) *address = overlay_unmapped_address (cache_pc_function_low, section); else *address = cache_pc_function_low; } if (name) *name = cache_pc_function_name; if (endaddr) { if (pc_in_unmapped_range (pc, section)) { /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and then add one to that. */ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); } else *endaddr = cache_pc_function_high; } return 1; }
int find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr, int *is_gnu_ifunc_p) { struct obj_section *section; struct symbol *f; struct minimal_symbol *msymbol; struct symtab *symtab = NULL; struct objfile *objfile; int i; CORE_ADDR mapped_pc; /* To ensure that the symbol returned belongs to the correct setion (and that the last [random] symbol from the previous section isn't returned) try to find the section containing PC. First try the overlay code (which by default returns NULL); and second try the normal section code (which almost always succeeds). */ section = find_pc_overlay (pc); if (section == NULL) section = find_pc_section (pc); mapped_pc = overlay_mapped_address (pc, section); if (mapped_pc >= cache_pc_function_low && mapped_pc < cache_pc_function_high && section == cache_pc_function_section) goto return_cached_value; msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section); ALL_OBJFILES (objfile) { if (objfile->sf) symtab = objfile->sf->qf->find_pc_sect_symtab (objfile, msymbol, mapped_pc, section, 0); if (symtab) break; } if (symtab) { /* Checking whether the msymbol has a larger value is for the "pathological" case mentioned in print_frame_info. */ f = find_pc_sect_function (mapped_pc, section); if (f != NULL && (msymbol == NULL || (BLOCK_START (SYMBOL_BLOCK_VALUE (f)) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_name = SYMBOL_LINKAGE_NAME (f); cache_pc_function_section = section; cache_pc_function_is_gnu_ifunc = TYPE_GNU_IFUNC (SYMBOL_TYPE (f)); goto return_cached_value; } } /* Not in the normal symbol tables, see if the pc is in a known section. If it's not, then give up. This ensures that anything beyond the end of the text seg doesn't appear to be part of the last function in the text segment. */ if (!section) msymbol = NULL; /* Must be in the minimal symbol table. */ if (msymbol == NULL) { /* No available symbol. */ if (name != NULL) *name = 0; if (address != NULL) *address = 0; if (endaddr != NULL) *endaddr = 0; if (is_gnu_ifunc_p != NULL) *is_gnu_ifunc_p = 0; return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = SYMBOL_LINKAGE_NAME (msymbol); cache_pc_function_section = section; cache_pc_function_is_gnu_ifunc = MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; /* If the minimal symbol has a size, use it for the cache. Otherwise use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ if (MSYMBOL_SIZE (msymbol) != 0) cache_pc_function_high = cache_pc_function_low + MSYMBOL_SIZE (msymbol); else { /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol) && SYMBOL_OBJ_SECTION (msymbol + i) == SYMBOL_OBJ_SECTION (msymbol)) break; } if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < obj_section_endaddr (section)) cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ cache_pc_function_high = obj_section_endaddr (section); } return_cached_value: if (address) { if (pc_in_unmapped_range (pc, section)) *address = overlay_unmapped_address (cache_pc_function_low, section); else *address = cache_pc_function_low; } if (name) *name = cache_pc_function_name; if (endaddr) { if (pc_in_unmapped_range (pc, section)) { /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and then add one to that. */ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); } else *endaddr = cache_pc_function_high; } if (is_gnu_ifunc_p) *is_gnu_ifunc_p = cache_pc_function_is_gnu_ifunc; return 1; }
int inside_main_func (CORE_ADDR pc) { struct minimal_symbol *msymbol; if (symfile_objfile == 0) return 0; msymbol = lookup_minimal_symbol (main_name (), NULL, symfile_objfile); /* If the address range hasn't been set up at symbol reading time, set it up now. */ if (msymbol != NULL && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { /* brobecker/2003-10-10: We used to rely on lookup_symbol() to search the symbol associated to the "main" function. Unfortunately, lookup_symbol() uses the current-language la_lookup_symbol_nonlocal function to do the global symbol search. Depending on the language, this can introduce certain side-effects, because certain languages, for instance Ada, may find more than one match. Therefore we prefer to search the "main" function symbol using its address rather than its name. */ struct symbol *mainsym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } } /* Not in the normal symbol tables, see if "main" is in the partial symbol table. If it's not, then give up. */ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text) { CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol); asection *msect = SYMBOL_BFD_SECTION (msymbol); struct obj_section *osect = find_pc_sect_section (maddr, msect); if (osect != NULL) { int i; /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr && SYMBOL_BFD_SECTION (msymbol + i) == msect) break; } symfile_objfile->ei.main_func_lowpc = maddr; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) symfile_objfile->ei.main_func_highpc = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ symfile_objfile->ei.main_func_highpc = osect->endaddr; } } return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); }
int addr_inside_main_func (CORE_ADDR pc) { struct minimal_symbol *msymbol; if (symfile_objfile == 0) return 0; /* APPLE LOCAL begin don't recompute start/end of main */ /* If we've already found the start/end addrs of main, don't recompute them. This will probably be fixed in the FSF sources soon too, in which case this change can be dropped. jmolenda/2004-04-28 */ if (symfile_objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc != INVALID_ENTRY_LOWPC) return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); /* APPLE LOCAL end don't recompute start/end of main */ /* APPLE LOCAL begin don't restrict lookup_minimal_symbol's object file */ /* Don't restrict lookup_minimal_symbol's object file to symfile_objfile -- this will fail for ZeroLink apps where symfile_objfile is just the ZL launcher stub. */ msymbol = lookup_minimal_symbol (main_name (), NULL, NULL); /* APPLE LOCAL end don't restrict lookup_minimal_symbol's object file */ /* If the address range hasn't been set up at symbol reading time, set it up now. */ if (msymbol != NULL && symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC && symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC) { /* brobecker/2003-10-10: We used to rely on lookup_symbol() to search the symbol associated to the "main" function. Unfortunately, lookup_symbol() uses the current-language la_lookup_symbol_nonlocal function to do the global symbol search. Depending on the language, this can introduce certain side-effects, because certain languages, for instance Ada, may find more than one match. Therefore we prefer to search the "main" function symbol using its address rather than its name. */ struct symbol *mainsym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK) { /* APPLE LOCAL begin address ranges */ struct block *bl = SYMBOL_BLOCK_VALUE (mainsym); if (BLOCK_RANGES (bl)) { symfile_objfile->ei.main_func_lowpc = BLOCK_LOWEST_PC (bl); symfile_objfile->ei.main_func_highpc = BLOCK_HIGHEST_PC (bl); } else { symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym)); symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym)); } /* APPLE LOCAL end address ranges */ } } /* Not in the normal symbol tables, see if "main" is in the partial symbol table. If it's not, then give up. */ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text) { CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol); asection *msect = SYMBOL_BFD_SECTION (msymbol); struct obj_section *osect = find_pc_sect_section (maddr, msect); if (osect != NULL) { int i; /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr && SYMBOL_BFD_SECTION (msymbol + i) == msect) break; } symfile_objfile->ei.main_func_lowpc = maddr; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) symfile_objfile->ei.main_func_highpc = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ symfile_objfile->ei.main_func_highpc = osect->endaddr; } } return (symfile_objfile->ei.main_func_lowpc <= pc && symfile_objfile->ei.main_func_highpc > pc); }
static int find_pc_partial_function_impl (CORE_ADDR pc, char **name, CORE_ADDR *address, CORE_ADDR *endaddr, int inlining_flag) { struct bfd_section *section; struct partial_symtab *pst; struct symbol *f; struct minimal_symbol *msymbol; struct partial_symbol *psb; struct obj_section *osect; int i; CORE_ADDR mapped_pc; /* To ensure that the symbol returned belongs to the correct setion (and that the last [random] symbol from the previous section isn't returned) try to find the section containing PC. First try the overlay code (which by default returns NULL); and second try the normal section code (which almost always succeeds). */ section = find_pc_overlay (pc); if (section == NULL) { struct obj_section *obj_section = find_pc_section (pc); if (obj_section == NULL) section = NULL; else section = obj_section->the_bfd_section; } mapped_pc = overlay_mapped_address (pc, section); if (mapped_pc >= cache_pc_function_low && mapped_pc < cache_pc_function_high && section == cache_pc_function_section && inlining_flag == cache_pc_function_inlining) goto return_cached_value; cache_pc_function_inlining = inlining_flag; msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section); pst = find_pc_sect_psymtab (mapped_pc, section); if (pst) { /* Need to read the symbols to get a good value for the end address. */ if (endaddr != NULL && !pst->readin) { /* Need to get the terminal in case symbol-reading produces output. */ target_terminal_ours_for_output (); PSYMTAB_TO_SYMTAB (pst); } if (pst->readin) { /* Checking whether the msymbol has a larger value is for the "pathological" case mentioned in print_frame_info. */ if (inlining_flag) f = find_pc_sect_function (mapped_pc, section); else f = find_pc_sect_function_no_inlined (mapped_pc, section); /* APPLE LOCAL begin address ranges */ if (f != NULL && (msymbol == NULL || (BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (f)) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { cache_pc_function_low = BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (f)); if (BLOCK_RANGES (SYMBOL_BLOCK_VALUE (f))) cache_pc_function_high = BLOCK_HIGHEST_PC (SYMBOL_BLOCK_VALUE (f)); else cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); /* APPLE LOCAL end address ranges */ cache_pc_function_name = DEPRECATED_SYMBOL_NAME (f); cache_pc_function_section = section; goto return_cached_value; } } else { /* Now that static symbols go in the minimal symbol table, perhaps we could just ignore the partial symbols. But at least for now we use the partial or minimal symbol, whichever is larger. */ psb = find_pc_sect_psymbol (pst, mapped_pc, section); if (psb && (msymbol == NULL || (SYMBOL_VALUE_ADDRESS (psb) >= SYMBOL_VALUE_ADDRESS (msymbol)))) { /* This case isn't being cached currently. */ if (address) *address = SYMBOL_VALUE_ADDRESS (psb); if (name) *name = DEPRECATED_SYMBOL_NAME (psb); /* endaddr non-NULL can't happen here. */ return 1; } } } /* Not in the normal symbol tables, see if the pc is in a known section. If it's not, then give up. This ensures that anything beyond the end of the text seg doesn't appear to be part of the last function in the text segment. */ osect = find_pc_sect_section (mapped_pc, section); if (!osect) msymbol = NULL; /* Must be in the minimal symbol table. */ if (msymbol == NULL) { /* No available symbol. */ if (name != NULL) *name = 0; if (address != NULL) *address = 0; if (endaddr != NULL) *endaddr = 0; return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = DEPRECATED_SYMBOL_NAME (msymbol); cache_pc_function_section = section; /* Use the lesser of the next minimal symbol in the same section, or the end of the section, as the end of the function. */ /* Step over other symbols at this same address, and symbols in other sections, to find the next symbol in this section with a different address. */ for (i = 1; DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL; i++) { if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol) && SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol)) break; } if (DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr) cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i); else /* We got the start address from the last msymbol in the objfile. So the end address is the end of the section. */ cache_pc_function_high = osect->endaddr; return_cached_value: if (address) { if (pc_in_unmapped_range (pc, section)) *address = overlay_unmapped_address (cache_pc_function_low, section); else *address = cache_pc_function_low; } if (name) *name = cache_pc_function_name; if (endaddr) { if (pc_in_unmapped_range (pc, section)) { /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and then add one to that. */ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); } else *endaddr = cache_pc_function_high; } return 1; }
static void compile_cplus_convert_struct_or_union_methods (compile_cplus_instance *instance, struct type *type, gcc_type class_type) { for (int i = 0; i < TYPE_NFN_FIELDS (type); ++i) { struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i); gdb::unique_xmalloc_ptr<char> overloaded_name = compile_cplus_instance::decl_name (TYPE_FN_FIELDLIST_NAME (type, i)); /* Loop through the fieldlist, adding decls to the compiler's representation of the class. */ for (int j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j) { /* Skip artificial methods. */ if (TYPE_FN_FIELD_ARTIFICIAL (methods, j)) continue; gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION; gcc_type method_type; struct block_symbol sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j), instance->block (), VAR_DOMAIN, nullptr); if (sym.symbol == nullptr) { if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) { /* This is beyond hacky, and is really only a workaround for detecting pure virtual methods. */ method_type = compile_cplus_convert_method (instance, type, TYPE_FN_FIELD_TYPE (methods, j)); instance->plugin ().build_decl ("pure virtual method", overloaded_name.get (), (sym_kind | get_method_access_flag (type, i, j) | GCC_CP_FLAG_VIRTUAL_FUNCTION | GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION), method_type, nullptr, 0, nullptr, 0); continue; } /* This can happen if we have a DW_AT_declaration DIE for the method, but no "definition"-type DIE (with DW_AT_specification referencing the decl DIE), i.e., the compiler has probably optimized the method away. In this case, all we can hope to do is issue a warning to the user letting him know. If the user has not actually requested using this method, things should still work. */ warning (_("Method %s appears to be optimized out.\n" "All references to this method will be undefined."), TYPE_FN_FIELD_PHYSNAME (methods, j)); continue; } const char *filename = symbol_symtab (sym.symbol)->filename; unsigned int line = SYMBOL_LINE (sym.symbol); CORE_ADDR address = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); const char *kind; if (TYPE_FN_FIELD_STATIC_P (methods, j)) { kind = "static method"; method_type = compile_cplus_convert_func (instance, TYPE_FN_FIELD_TYPE (methods, j), true); } else { kind = "method"; method_type = (compile_cplus_convert_method (instance, type, TYPE_FN_FIELD_TYPE (methods, j))); } if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION; instance->plugin ().build_decl (kind, overloaded_name.get (), sym_kind | get_method_access_flag (type, i, j), method_type, nullptr, address, filename, line); } } }
int find_pc_partial_function (CORE_ADDR pc, const char **name, CORE_ADDR *address, CORE_ADDR *endaddr, const struct block **block) { struct obj_section *section; struct symbol *f; struct bound_minimal_symbol msymbol; struct compunit_symtab *compunit_symtab = NULL; CORE_ADDR mapped_pc; /* To ensure that the symbol returned belongs to the correct setion (and that the last [random] symbol from the previous section isn't returned) try to find the section containing PC. First try the overlay code (which by default returns NULL); and second try the normal section code (which almost always succeeds). */ section = find_pc_overlay (pc); if (section == NULL) section = find_pc_section (pc); mapped_pc = overlay_mapped_address (pc, section); if (mapped_pc >= cache_pc_function_low && mapped_pc < cache_pc_function_high && section == cache_pc_function_section) goto return_cached_value; msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section); for (objfile *objfile : current_program_space->objfiles ()) { if (objfile->sf) { compunit_symtab = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile, msymbol, mapped_pc, section, 0); } if (compunit_symtab != NULL) break; } if (compunit_symtab != NULL) { /* Checking whether the msymbol has a larger value is for the "pathological" case mentioned in stack.c:find_frame_funname. We use BLOCK_ENTRY_PC instead of BLOCK_START_PC for this comparison because the minimal symbol should refer to the function's entry pc which is not necessarily the lowest address of the function. This will happen when the function has more than one range and the entry pc is not within the lowest range of addresses. */ f = find_pc_sect_function (mapped_pc, section); if (f != NULL && (msymbol.minsym == NULL || (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (f)) >= BMSYMBOL_VALUE_ADDRESS (msymbol)))) { const struct block *b = SYMBOL_BLOCK_VALUE (f); cache_pc_function_name = SYMBOL_LINKAGE_NAME (f); cache_pc_function_section = section; cache_pc_function_block = b; /* For blocks occupying contiguous addresses (i.e. no gaps), the low and high cache addresses are simply the start and end of the block. For blocks with non-contiguous ranges, we have to search for the range containing mapped_pc and then use the start and end of that range. This causes the returned *ADDRESS and *ENDADDR values to be limited to the range in which mapped_pc is found. See comment preceding declaration of find_pc_partial_function in symtab.h for more information. */ if (BLOCK_CONTIGUOUS_P (b)) { cache_pc_function_low = BLOCK_START (b); cache_pc_function_high = BLOCK_END (b); } else { int i; for (i = 0; i < BLOCK_NRANGES (b); i++) { if (BLOCK_RANGE_START (b, i) <= mapped_pc && mapped_pc < BLOCK_RANGE_END (b, i)) { cache_pc_function_low = BLOCK_RANGE_START (b, i); cache_pc_function_high = BLOCK_RANGE_END (b, i); break; } } /* Above loop should exit via the break. */ gdb_assert (i < BLOCK_NRANGES (b)); } goto return_cached_value; } } /* Not in the normal symbol tables, see if the pc is in a known section. If it's not, then give up. This ensures that anything beyond the end of the text seg doesn't appear to be part of the last function in the text segment. */ if (!section) msymbol.minsym = NULL; /* Must be in the minimal symbol table. */ if (msymbol.minsym == NULL) { /* No available symbol. */ if (name != NULL) *name = 0; if (address != NULL) *address = 0; if (endaddr != NULL) *endaddr = 0; return 0; } cache_pc_function_low = BMSYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = MSYMBOL_LINKAGE_NAME (msymbol.minsym); cache_pc_function_section = section; cache_pc_function_high = minimal_symbol_upper_bound (msymbol); cache_pc_function_block = nullptr; return_cached_value: if (address) { if (pc_in_unmapped_range (pc, section)) *address = overlay_unmapped_address (cache_pc_function_low, section); else *address = cache_pc_function_low; } if (name) *name = cache_pc_function_name; if (endaddr) { if (pc_in_unmapped_range (pc, section)) { /* Because the high address is actually beyond the end of the function (and therefore possibly beyond the end of the overlay), we must actually convert (high - 1) and then add one to that. */ *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1, section); } else *endaddr = cache_pc_function_high; } if (block != nullptr) *block = cache_pc_function_block; return 1; }