X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Felfread.c;h=103b2144c3a152c9cbe05d8c924dcd2ce9864c24;hb=c113ed0ca238bbcbc161f059ffe9b064e3ece333;hp=7c4b17505ffa55ea4173a269a90a65c909222beb;hpb=77e371c079408e265f1dfd2b0620dd8e76c23371;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/elfread.c b/gdb/elfread.c index 7c4b17505f..103b2144c3 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1,6 +1,6 @@ /* Read ELF (Executable and Linking Format) object files for GDB. - Copyright (C) 1991-2014 Free Software Foundation, Inc. + Copyright (C) 1991-2018 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -21,7 +21,6 @@ #include "defs.h" #include "bfd.h" -#include #include "elf-bfd.h" #include "elf/common.h" #include "elf/internal.h" @@ -46,12 +45,13 @@ #include "bcache.h" #include "gdb_bfd.h" #include "build-id.h" - -extern void _initialize_elfread (void); +#include "location.h" +#include "auxv.h" /* Forward declarations. */ -static const struct sym_fns elf_sym_fns_gdb_index; -static const struct sym_fns elf_sym_fns_lazy_psyms; +extern const struct sym_fns elf_sym_fns_gdb_index; +extern const struct sym_fns elf_sym_fns_debug_names; +extern const struct sym_fns elf_sym_fns_lazy_psyms; /* The struct elfinfo is available only during ELF symbol table and psymtab reading. It is destroyed at the completion of psymtab-reading. @@ -63,11 +63,9 @@ struct elfinfo asection *mdebugsect; /* Section pointer for .mdebug section */ }; -/* Per-objfile data for probe info. */ - -static const struct objfile_data *probe_key = NULL; +/* Per-BFD data for probe info. */ -static void free_elfinfo (void *); +static const struct bfd_data *probe_key = NULL; /* Minimal symbols located at the GOT entries for .plt - that is the real pointer where the given entry will jump to. It gets updated by the real @@ -91,13 +89,13 @@ elf_symfile_segments (bfd *abfd) if (phdrs_size == -1) return NULL; - phdrs = alloca (phdrs_size); + phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size); num_phdrs = bfd_get_elf_phdrs (abfd, phdrs); if (num_phdrs == -1) return NULL; num_segments = 0; - segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs); + segments = XALLOCAVEC (Elf_Internal_Phdr *, num_phdrs); for (i = 0; i < num_phdrs; i++) if (phdrs[i].p_type == PT_LOAD) segments[num_segments++] = &phdrs[i]; @@ -192,7 +190,8 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip) } static struct minimal_symbol * -record_minimal_symbol (const char *name, int name_len, int copy_name, +record_minimal_symbol (minimal_symbol_reader &reader, + const char *name, int name_len, bool copy_name, CORE_ADDR address, enum minimal_symbol_type ms_type, asection *bfd_section, struct objfile *objfile) @@ -203,11 +202,10 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, || ms_type == mst_text_gnu_ifunc) address = gdbarch_addr_bits_remove (gdbarch, address); - return prim_record_minimal_symbol_full (name, name_len, copy_name, address, - ms_type, - gdb_bfd_section_index (objfile->obfd, - bfd_section), - objfile); + return reader.record_full (name, name_len, copy_name, address, + ms_type, + gdb_bfd_section_index (objfile->obfd, + bfd_section)); } /* Read the symbol table of an ELF file. @@ -227,27 +225,22 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, #define ST_SYNTHETIC 2 static void -elf_symtab_read (struct objfile *objfile, int type, +elf_symtab_read (minimal_symbol_reader &reader, + struct objfile *objfile, int type, long number_of_symbols, asymbol **symbol_table, - int copy_names) + bool copy_names) { struct gdbarch *gdbarch = get_objfile_arch (objfile); asymbol *sym; long i; CORE_ADDR symaddr; - CORE_ADDR offset; enum minimal_symbol_type ms_type; - /* If sectinfo is nonNULL, it contains section info that should end up - filed in the objfile. */ - struct stab_section_info *sectinfo = NULL; - /* If filesym is nonzero, it points to a file symbol, but we haven't - seen any section info for it yet. */ - asymbol *filesym = 0; - /* Name of filesym. This is either a constant string or is saved on - the objfile's filename cache. */ + /* Name of the last file symbol. This is either a constant string or is + saved on the objfile's filename cache. */ const char *filesymname = ""; - struct dbx_symfile_info *dbx = DBX_SYMFILE_INFO (objfile); int stripped = (bfd_get_symcount (objfile->obfd) == 0); + int elf_make_msymbol_special_p + = gdbarch_elf_make_msymbol_special_p (gdbarch); for (i = 0; i < number_of_symbols; i++) { @@ -269,8 +262,6 @@ elf_symtab_read (struct objfile *objfile, int type, continue; } - offset = ANOFFSET (objfile->section_offsets, - gdb_bfd_section_index (objfile->obfd, sym->section)); if (type == ST_DYNAMIC && sym->section == bfd_und_section_ptr && (sym->flags & BSF_FUNCTION)) @@ -321,18 +312,19 @@ elf_symtab_read (struct objfile *objfile, int type, for that section is ".plt". So, if there is a ".plt" section, and yet the section name of our symbol does not start with ".plt", we ignore that symbol. */ - if (strncmp (sect->name, ".plt", 4) != 0 + if (!startswith (sect->name, ".plt") && bfd_get_section_by_name (abfd, ".plt") != NULL) continue; - symaddr += ANOFFSET (objfile->section_offsets, - gdb_bfd_section_index (objfile->obfd, sect)); - msym = record_minimal_symbol - (sym->name, strlen (sym->name), copy_names, + (reader, sym->name, strlen (sym->name), copy_names, symaddr, mst_solib_trampoline, sect, objfile); if (msym != NULL) - msym->filename = filesymname; + { + msym->filename = filesymname; + if (elf_make_msymbol_special_p) + gdbarch_elf_make_msymbol_special (gdbarch, sym, msym); + } continue; } @@ -343,17 +335,9 @@ elf_symtab_read (struct objfile *objfile, int type, continue; if (sym->flags & BSF_FILE) { - /* STT_FILE debugging symbol that helps stabs-in-elf debugging. - Chain any old one onto the objfile; remember new sym. */ - if (sectinfo != NULL) - { - sectinfo->next = dbx->stab_section_info; - dbx->stab_section_info = sectinfo; - sectinfo = NULL; - } - filesym = sym; - filesymname = bcache (filesym->name, strlen (filesym->name) + 1, - objfile->per_bfd->filename_cache); + filesymname + = (const char *) bcache (sym->name, strlen (sym->name) + 1, + objfile->per_bfd->filename_cache); } else if (sym->flags & BSF_SECTION_SYM) continue; @@ -367,13 +351,6 @@ elf_symtab_read (struct objfile *objfile, int type, interested in will have a section. */ /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; - /* Relocate all non-absolute and non-TLS symbols by the - section offset. */ - if (sym->section != bfd_abs_section_ptr - && !(sym->section->flags & SEC_THREAD_LOCAL)) - { - symaddr += offset; - } /* For non-absolute symbols, use the type of the section they are relative to, to intuit text/data. Bfd provides no way of figuring this out for absolute symbols. */ @@ -409,7 +386,6 @@ elf_symtab_read (struct objfile *objfile, int type, { if (sym->name[0] == '.') continue; - symaddr += offset; } } else if (sym->section->flags & SEC_CODE) @@ -457,77 +433,6 @@ elf_symtab_read (struct objfile *objfile, int type, } else if (sym->flags & BSF_LOCAL) { - /* Named Local variable in a Data section. - Check its name for stabs-in-elf. */ - int special_local_sect; - - if (strcmp ("Bbss.bss", sym->name) == 0) - special_local_sect = SECT_OFF_BSS (objfile); - else if (strcmp ("Ddata.data", sym->name) == 0) - special_local_sect = SECT_OFF_DATA (objfile); - else if (strcmp ("Drodata.rodata", sym->name) == 0) - special_local_sect = SECT_OFF_RODATA (objfile); - else - special_local_sect = -1; - if (special_local_sect >= 0) - { - /* Found a special local symbol. Allocate a - sectinfo, if needed, and fill it in. */ - if (sectinfo == NULL) - { - int max_index; - size_t size; - - max_index = SECT_OFF_BSS (objfile); - if (objfile->sect_index_data > max_index) - max_index = objfile->sect_index_data; - if (objfile->sect_index_rodata > max_index) - max_index = objfile->sect_index_rodata; - - /* max_index is the largest index we'll - use into this array, so we must - allocate max_index+1 elements for it. - However, 'struct stab_section_info' - already includes one element, so we - need to allocate max_index aadditional - elements. */ - size = (sizeof (struct stab_section_info) - + (sizeof (CORE_ADDR) * max_index)); - sectinfo = (struct stab_section_info *) - xmalloc (size); - memset (sectinfo, 0, size); - sectinfo->num_sections = max_index; - if (filesym == NULL) - { - complaint (&symfile_complaints, - _("elf/stab section information %s " - "without a preceding file symbol"), - sym->name); - } - else - { - sectinfo->filename = - (char *) filesym->name; - } - } - if (sectinfo->sections[special_local_sect] != 0) - complaint (&symfile_complaints, - _("duplicated elf/stab section " - "information for %s"), - sectinfo->filename); - /* BFD symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - /* Relocate non-absolute symbols by the - section offset. */ - if (sym->section != bfd_abs_section_ptr) - symaddr += offset; - sectinfo->sections[special_local_sect] = symaddr; - /* The special local symbols don't go in the - minimal symbol table, so ignore this one. */ - continue; - } - /* Not a special stabs-in-elf symbol, do regular - symbol processing. */ if (sym->section->flags & SEC_LOAD) { ms_type = mst_file_data; @@ -552,7 +457,7 @@ elf_symtab_read (struct objfile *objfile, int type, continue; /* Skip this symbol. */ } msym = record_minimal_symbol - (sym->name, strlen (sym->name), copy_names, symaddr, + (reader, sym->name, strlen (sym->name), copy_names, symaddr, ms_type, sym->section, objfile); if (msym) @@ -567,7 +472,8 @@ elf_symtab_read (struct objfile *objfile, int type, } msym->filename = filesymname; - gdbarch_elf_make_msymbol_special (gdbarch, sym, msym); + if (elf_make_msymbol_special_p) + gdbarch_elf_make_msymbol_special (gdbarch, sym, msym); } /* If we see a default versioned symbol, install it under @@ -580,7 +486,7 @@ elf_symtab_read (struct objfile *objfile, int type, { int len = atsign - sym->name; - record_minimal_symbol (sym->name, len, 1, symaddr, + record_minimal_symbol (reader, sym->name, len, true, symaddr, ms_type, sym->section, objfile); } } @@ -597,8 +503,8 @@ elf_symtab_read (struct objfile *objfile, int type, { struct minimal_symbol *mtramp; - mtramp = record_minimal_symbol (sym->name, len - 4, 1, - symaddr, + mtramp = record_minimal_symbol (reader, sym->name, len - 4, + true, symaddr, mst_solib_trampoline, sym->section, objfile); if (mtramp) @@ -606,7 +512,9 @@ elf_symtab_read (struct objfile *objfile, int type, SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym)); mtramp->created_by_gdb = 1; mtramp->filename = filesymname; - gdbarch_elf_make_msymbol_special (gdbarch, sym, mtramp); + if (elf_make_msymbol_special_p) + gdbarch_elf_make_msymbol_special (gdbarch, + sym, mtramp); } } } @@ -622,16 +530,14 @@ elf_symtab_read (struct objfile *objfile, int type, DYN_SYMBOL_TABLE is no longer easily available for OBJFILE. */ static void -elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) +elf_rel_plt_read (minimal_symbol_reader &reader, + struct objfile *objfile, asymbol **dyn_symbol_table) { bfd *obfd = objfile->obfd; const struct elf_backend_data *bed = get_elf_backend_data (obfd); asection *plt, *relplt, *got_plt; int plt_elf_idx; bfd_size_type reloc_count, reloc; - char *string_buffer = NULL; - size_t string_buffer_size = 0; - struct cleanup *back_to; struct gdbarch *gdbarch = get_objfile_arch (objfile); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; size_t ptr_size = TYPE_LENGTH (ptr_type); @@ -665,7 +571,7 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) if (! bed->s->slurp_reloc_table (obfd, relplt, dyn_symbol_table, TRUE)) return; - back_to = make_cleanup (free_current_contents, &string_buffer); + std::string string_buffer; reloc_count = relplt->size / elf_section_data (relplt)->this_hdr.sh_entsize; for (reloc = 0; reloc < reloc_count; reloc++) @@ -673,11 +579,10 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) const char *name; struct minimal_symbol *msym; CORE_ADDR address; + const char *got_suffix = SYMBOL_GOT_PLT_SUFFIX; const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); - size_t name_len; name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr); - name_len = strlen (name); address = relplt->relocation[reloc].address; /* Does the pointer reside in the .got.plt section? */ @@ -690,23 +595,16 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) OBJFILE the symbol is undefined and the objfile having NAME defined may not yet have been loaded. */ - if (string_buffer_size < name_len + got_suffix_len + 1) - { - string_buffer_size = 2 * (name_len + got_suffix_len); - string_buffer = xrealloc (string_buffer, string_buffer_size); - } - memcpy (string_buffer, name, name_len); - memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX, - got_suffix_len + 1); + string_buffer.assign (name); + string_buffer.append (got_suffix, got_suffix + got_suffix_len); - msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len, - 1, address, mst_slot_got_plt, got_plt, + msym = record_minimal_symbol (reader, string_buffer.c_str (), + string_buffer.size (), + true, address, mst_slot_got_plt, got_plt, objfile); if (msym) SET_MSYMBOL_SIZE (msym, ptr_size); } - - do_cleanups (back_to); } /* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked. */ @@ -728,7 +626,8 @@ struct elf_gnu_ifunc_cache static hashval_t elf_gnu_ifunc_cache_hash (const void *a_voidp) { - const struct elf_gnu_ifunc_cache *a = a_voidp; + const struct elf_gnu_ifunc_cache *a + = (const struct elf_gnu_ifunc_cache *) a_voidp; return htab_hash_string (a->name); } @@ -738,8 +637,10 @@ elf_gnu_ifunc_cache_hash (const void *a_voidp) static int elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp) { - const struct elf_gnu_ifunc_cache *a = a_voidp; - const struct elf_gnu_ifunc_cache *b = b_voidp; + const struct elf_gnu_ifunc_cache *a + = (const struct elf_gnu_ifunc_cache *) a_voidp; + const struct elf_gnu_ifunc_cache *b + = (const struct elf_gnu_ifunc_cache *) b_voidp; return strcmp (a->name, b->name) == 0; } @@ -777,7 +678,7 @@ elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) if (strcmp (bfd_get_section_name (objfile->obfd, sect), ".plt") == 0) return 0; - htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); + htab = (htab_t) objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); if (htab == NULL) { htab = htab_create_alloc_ex (1, elf_gnu_ifunc_cache_hash, @@ -792,12 +693,14 @@ elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) obstack_grow (&objfile->objfile_obstack, &entry_local, offsetof (struct elf_gnu_ifunc_cache, name)); obstack_grow_str0 (&objfile->objfile_obstack, name); - entry_p = obstack_finish (&objfile->objfile_obstack); + entry_p + = (struct elf_gnu_ifunc_cache *) obstack_finish (&objfile->objfile_obstack); slot = htab_find_slot (htab, entry_p, INSERT); if (*slot != NULL) { - struct elf_gnu_ifunc_cache *entry_found_p = *slot; + struct elf_gnu_ifunc_cache *entry_found_p + = (struct elf_gnu_ifunc_cache *) *slot; struct gdbarch *gdbarch = get_objfile_arch (objfile); if (entry_found_p->addr != addr) @@ -836,17 +739,18 @@ elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p) struct elf_gnu_ifunc_cache *entry_p; void **slot; - htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); + htab = (htab_t) objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); if (htab == NULL) continue; - entry_p = alloca (sizeof (*entry_p) + strlen (name)); + entry_p = ((struct elf_gnu_ifunc_cache *) + alloca (sizeof (*entry_p) + strlen (name))); strcpy (entry_p->name, name); slot = htab_find_slot (htab, entry_p, NO_INSERT); if (slot == NULL) continue; - entry_p = *slot; + entry_p = (struct elf_gnu_ifunc_cache *) *slot; gdb_assert (entry_p != NULL); if (addr_p) @@ -872,7 +776,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) struct objfile *objfile; const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); - name_got_plt = alloca (strlen (name) + got_suffix_len + 1); + name_got_plt = (char *) alloca (strlen (name) + got_suffix_len + 1); sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name); ALL_PSPACE_OBJFILES (current_program_space, objfile) @@ -883,7 +787,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) size_t ptr_size = TYPE_LENGTH (ptr_type); CORE_ADDR pointer_address, addr; asection *plt; - gdb_byte *buf = alloca (ptr_size); + gdb_byte *buf = (gdb_byte *) alloca (ptr_size); struct bound_minimal_symbol msym; msym = lookup_minimal_symbol (name_got_plt, NULL, objfile); @@ -946,6 +850,8 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) CORE_ADDR start_at_pc, address; struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; struct value *function, *address_val; + CORE_ADDR hwcap = 0; + struct value *hwcap_val; /* Try first any non-intrusive methods without an inferior call. */ @@ -959,12 +865,17 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) name_at_pc = NULL; function = allocate_value (func_func_type); + VALUE_LVAL (function) = lval_memory; set_value_address (function, pc); - /* STT_GNU_IFUNC resolver functions have no parameters. FUNCTION is the - function entry address. ADDRESS may be a function descriptor. */ + /* STT_GNU_IFUNC resolver functions usually receive the HWCAP vector as + parameter. FUNCTION is the function entry address. ADDRESS may be a + function descriptor. */ - address_val = call_function_by_hand (function, 0, NULL); + target_auxv_search (¤t_target, AT_HWCAP, &hwcap); + hwcap_val = value_from_longest (builtin_type (gdbarch) + ->builtin_unsigned_long, hwcap); + address_val = call_function_by_hand (function, NULL, 1, &hwcap_val); address = value_as_address (address_val); address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, ¤t_target); @@ -985,7 +896,7 @@ elf_gnu_ifunc_resolver_stop (struct breakpoint *b) struct frame_info *prev_frame = get_prev_frame (get_current_frame ()); struct frame_id prev_frame_id = get_stack_frame_id (prev_frame); CORE_ADDR prev_pc = get_frame_pc (prev_frame); - int thread_id = pid_to_thread_id (inferior_ptid); + int thread_id = ptid_to_global_thread_id (inferior_ptid); gdb_assert (b->type == bp_gnu_ifunc_resolver); @@ -1004,19 +915,18 @@ elf_gnu_ifunc_resolver_stop (struct breakpoint *b) if (b_return == b) { - struct symtab_and_line sal; - /* No need to call find_pc_line for symbols resolving as this is only a helper breakpointer never shown to the user. */ - init_sal (&sal); + symtab_and_line sal; sal.pspace = current_inferior ()->pspace; sal.pc = prev_pc; sal.section = find_pc_overlay (sal.pc); sal.explicit_pc = 1; - b_return = set_momentary_breakpoint (get_frame_arch (prev_frame), sal, - prev_frame_id, - bp_gnu_ifunc_resolver_return); + b_return + = set_momentary_breakpoint (get_frame_arch (prev_frame), sal, + prev_frame_id, + bp_gnu_ifunc_resolver_return).release (); /* set_momentary_breakpoint invalidates PREV_FRAME. */ prev_frame = NULL; @@ -1040,8 +950,6 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) struct value *func_func; struct value *value; CORE_ADDR resolved_address, resolved_pc; - struct symtab_and_line sal; - struct symtabs_and_lines sals, sals_end; gdb_assert (b->type == bp_gnu_ifunc_resolver_return); @@ -1068,6 +976,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) gdb_assert (b->loc->next == NULL); func_func = allocate_value (func_func_type); + VALUE_LVAL (func_func) = lval_memory; set_value_address (func_func, b->loc->related_address); value = allocate_value (value_type); @@ -1080,51 +989,22 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc); gdb_assert (current_program_space == b->pspace || b->pspace == NULL); - elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc); - - sal = find_pc_line (resolved_pc, 0); - sals.nelts = 1; - sals.sals = &sal; - sals_end.nelts = 0; + elf_gnu_ifunc_record_cache (event_location_to_string (b->location.get ()), + resolved_pc); b->type = bp_breakpoint; - update_breakpoint_locations (b, sals, sals_end); + update_breakpoint_locations (b, current_program_space, + find_pc_line (resolved_pc, 0), {}); } -/* Scan and build partial symbols for a symbol file. - We have been initialized by a call to elf_symfile_init, which - currently does nothing. - - SECTION_OFFSETS is a set of offsets to apply to relocate the symbols - in each section. We simplify it down to a single offset for all - symbols. FIXME. - - This function only does the minimum work necessary for letting the - user "name" things symbolically; it does not read the entire symtab. - Instead, it reads the external and static symbols and puts them in partial - symbol tables. When more extensive information is requested of a - file, the corresponding partial symbol table is mutated into a full - fledged symbol table by going back and reading the symbols - for real. - - We look for sections with specific names, to tell us what debug - format to look for: FIXME!!! - - elfstab_build_psymtabs() handles STABS symbols; - mdebug_build_psymtabs() handles ECOFF debugging information. - - Note that ELF files have a "minimal" symbol table, which looks a lot - like a COFF symbol table, but has only the minimal information necessary - for linking. We process this also, and use the information to - build gdb's minimal symbol table. This gives us some minimal debugging - capability even for files compiled without -g. */ +/* A helper function for elf_symfile_read that reads the minimal + symbols. */ static void -elf_symfile_read (struct objfile *objfile, int symfile_flags) +elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags, + const struct elfinfo *ei) { bfd *synth_abfd, *abfd = objfile->obfd; - struct elfinfo ei; - struct cleanup *back_to; long symcount = 0, dynsymcount = 0, synthcount, storage_needed; asymbol **symbol_table = NULL, **dyn_symbol_table = NULL; asymbol *synthsyms; @@ -1137,19 +1017,28 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) objfile_name (objfile)); } - init_minimal_symbol_collection (); - back_to = make_cleanup_discard_minimal_symbols (); + /* If we already have minsyms, then we can skip some work here. + However, if there were stabs or mdebug sections, we go ahead and + redo all the work anyway, because the psym readers for those + kinds of debuginfo need extra information found here. This can + go away once all types of symbols are in the per-BFD object. */ + if (objfile->per_bfd->minsyms_read + && ei->stabsect == NULL + && ei->mdebugsect == NULL) + { + if (symtab_create_debug) + fprintf_unfiltered (gdb_stdlog, + "... minimal symbols previously read\n"); + return; + } - memset ((char *) &ei, 0, sizeof (ei)); + minimal_symbol_reader reader (objfile); /* Allocate struct to keep track of the symfile. */ dbx = XCNEW (struct dbx_symfile_info); set_objfile_data (objfile, dbx_objfile_data_key, dbx); - make_cleanup (free_elfinfo, (void *) objfile); - /* Process the normal ELF symbol table first. This may write some - chain of info into the dbx_symfile_info of the objfile, which can - later be used by elfstab_offset_sections. */ + /* Process the normal ELF symbol table first. */ storage_needed = bfd_get_symtab_upper_bound (objfile->obfd); if (storage_needed < 0) @@ -1159,8 +1048,10 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) if (storage_needed > 0) { - symbol_table = (asymbol **) xmalloc (storage_needed); - make_cleanup (xfree, symbol_table); + /* Memory gets permanently referenced from ABFD after + bfd_canonicalize_symtab so it must not get freed before ABFD gets. */ + + symbol_table = (asymbol **) bfd_alloc (abfd, storage_needed); symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table); if (symcount < 0) @@ -1168,7 +1059,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); - elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0); + elf_symtab_read (reader, objfile, ST_REGULAR, symcount, symbol_table, + false); } /* Add the dynamic symbols. */ @@ -1184,7 +1076,7 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) done by _bfd_elf_get_synthetic_symtab which is all a bfd implementation detail, though. */ - dyn_symbol_table = bfd_alloc (abfd, storage_needed); + dyn_symbol_table = (asymbol **) bfd_alloc (abfd, storage_needed); dynsymcount = bfd_canonicalize_dynamic_symtab (objfile->obfd, dyn_symbol_table); @@ -1193,9 +1085,10 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); - elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0); + elf_symtab_read (reader, objfile, ST_DYNAMIC, dynsymcount, + dyn_symbol_table, false); - elf_rel_plt_read (objfile, dyn_symbol_table); + elf_rel_plt_read (reader, objfile, dyn_symbol_table); } /* Contrary to binutils --strip-debug/--only-keep-debug the strip command from @@ -1222,16 +1115,17 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) &synthsyms); if (synthcount > 0) { - asymbol **synth_symbol_table; long i; - make_cleanup (xfree, synthsyms); - synth_symbol_table = xmalloc (sizeof (asymbol *) * synthcount); + std::unique_ptr + synth_symbol_table (new asymbol *[synthcount]); for (i = 0; i < synthcount; i++) synth_symbol_table[i] = synthsyms + i; - make_cleanup (xfree, synth_symbol_table); - elf_symtab_read (objfile, ST_SYNTHETIC, synthcount, - synth_symbol_table, 1); + elf_symtab_read (reader, objfile, ST_SYNTHETIC, synthcount, + synth_symbol_table.get (), true); + + xfree (synthsyms); + synthsyms = NULL; } /* Install any minimal symbols that have been collected as the current @@ -1240,17 +1134,47 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) responsibility to install them. "mdebug" appears to be the only one which will do this. */ - install_minimal_symbols (objfile); - do_cleanups (back_to); + reader.install (); if (symtab_create_debug) fprintf_unfiltered (gdb_stdlog, "Done reading minimal symbols.\n"); +} + +/* Scan and build partial symbols for a symbol file. + We have been initialized by a call to elf_symfile_init, which + currently does nothing. + + This function only does the minimum work necessary for letting the + user "name" things symbolically; it does not read the entire symtab. + Instead, it reads the external and static symbols and puts them in partial + symbol tables. When more extensive information is requested of a + file, the corresponding partial symbol table is mutated into a full + fledged symbol table by going back and reading the symbols + for real. + + We look for sections with specific names, to tell us what debug + format to look for: FIXME!!! + + elfstab_build_psymtabs() handles STABS symbols; + mdebug_build_psymtabs() handles ECOFF debugging information. - /* Now process debugging information, which is contained in - special ELF sections. */ + Note that ELF files have a "minimal" symbol table, which looks a lot + like a COFF symbol table, but has only the minimal information necessary + for linking. We process this also, and use the information to + build gdb's minimal symbol table. This gives us some minimal debugging + capability even for files compiled without -g. */ + +static void +elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) +{ + bfd *abfd = objfile->obfd; + struct elfinfo ei; - /* We first have to find them... */ - bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei); + memset ((char *) &ei, 0, sizeof (ei)); + if (!(objfile->flags & OBJF_READNEVER)) + bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei); + + elf_read_minimal_symbols (objfile, symfile_flags, &ei); /* ELF debugging information is inserted into the psymtab in the order of least informative first - most informative last. Since @@ -1292,13 +1216,24 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) if (dwarf2_has_info (objfile, NULL)) { - /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF debug - information present in OBJFILE. If there is such debug info present - never use .gdb_index. */ + dw_index_kind index_kind; + /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF + debug information present in OBJFILE. If there is such debug + info present never use an index. */ if (!objfile_has_partial_symbols (objfile) - && dwarf2_initialize_objfile (objfile)) - objfile_set_sym_fns (objfile, &elf_sym_fns_gdb_index); + && dwarf2_initialize_objfile (objfile, &index_kind)) + { + switch (index_kind) + { + case dw_index_kind::GDB_INDEX: + objfile_set_sym_fns (objfile, &elf_sym_fns_gdb_index); + break; + case dw_index_kind::DEBUG_NAMES: + objfile_set_sym_fns (objfile, &elf_sym_fns_debug_names); + break; + } + } else { /* It is ok to do this even if the stabs reader made some @@ -1324,21 +1259,18 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) && objfile->separate_debug_objfile == NULL && objfile->separate_debug_objfile_backlink == NULL) { - char *debugfile; - - debugfile = find_separate_debug_file_by_buildid (objfile); + gdb::unique_xmalloc_ptr debugfile + (find_separate_debug_file_by_buildid (objfile)); if (debugfile == NULL) - debugfile = find_separate_debug_file_by_debuglink (objfile); + debugfile.reset (find_separate_debug_file_by_debuglink (objfile)); - if (debugfile) + if (debugfile != NULL) { - struct cleanup *cleanup = make_cleanup (xfree, debugfile); - bfd *abfd = symfile_bfd_open (debugfile); + gdb_bfd_ref_ptr abfd (symfile_bfd_open (debugfile.get ())); - make_cleanup_bfd_unref (abfd); - symbol_file_add_separate (abfd, debugfile, symfile_flags, objfile); - do_cleanups (cleanup); + symbol_file_add_separate (abfd.get (), debugfile.get (), + symfile_flags, objfile); } } } @@ -1352,28 +1284,6 @@ read_psyms (struct objfile *objfile) dwarf2_build_psymtabs (objfile); } -/* This cleans up the objfile's dbx symfile info, and the chain of - stab_section_info's, that might be dangling from it. */ - -static void -free_elfinfo (void *objp) -{ - struct objfile *objfile = (struct objfile *) objp; - struct dbx_symfile_info *dbxinfo = DBX_SYMFILE_INFO (objfile); - struct stab_section_info *ssi, *nssi; - - ssi = dbxinfo->stab_section_info; - while (ssi) - { - nssi = ssi->next; - xfree (ssi); - ssi = nssi; - } - - dbxinfo->stab_section_info = 0; /* Just say No mo info about this. */ -} - - /* Initialize anything that needs initializing when a completely new symbol file is specified (not just adding some symbols from another file, e.g. a shared library). @@ -1399,14 +1309,7 @@ elf_symfile_finish (struct objfile *objfile) dwarf2_free_objfile (objfile); } -/* ELF specific initialization routine for reading symbols. - - It is passed a pointer to a struct sym_fns which contains, among other - things, the BFD for the file whose symbols are being read, and a slot for - a pointer to "private data" which we can fill with goodies. - - For now at least, we have nothing in particular to do, so this function is - just a stub. */ +/* ELF specific initialization routine for reading symbols. */ static void elf_symfile_init (struct objfile *objfile) @@ -1417,131 +1320,43 @@ elf_symfile_init (struct objfile *objfile) objfile->flags |= OBJF_REORDERED; } -/* When handling an ELF file that contains Sun STABS debug info, - some of the debug info is relative to the particular chunk of the - section that was generated in its individual .o file. E.g. - offsets to static variables are relative to the start of the data - segment *for that module before linking*. This information is - painfully squirreled away in the ELF symbol table as local symbols - with wierd names. Go get 'em when needed. */ - -void -elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) -{ - const char *filename = pst->filename; - struct dbx_symfile_info *dbx = DBX_SYMFILE_INFO (objfile); - struct stab_section_info *maybe = dbx->stab_section_info; - struct stab_section_info *questionable = 0; - int i; - - /* The ELF symbol info doesn't include path names, so strip the path - (if any) from the psymtab filename. */ - filename = lbasename (filename); - - /* FIXME: This linear search could speed up significantly - if it was chained in the right order to match how we search it, - and if we unchained when we found a match. */ - for (; maybe; maybe = maybe->next) - { - if (filename[0] == maybe->filename[0] - && filename_cmp (filename, maybe->filename) == 0) - { - /* We found a match. But there might be several source files - (from different directories) with the same name. */ - if (0 == maybe->found) - break; - questionable = maybe; /* Might use it later. */ - } - } - - if (maybe == 0 && questionable != 0) - { - complaint (&symfile_complaints, - _("elf/stab section information questionable for %s"), - filename); - maybe = questionable; - } - - if (maybe) - { - /* Found it! Allocate a new psymtab struct, and fill it in. */ - maybe->found++; - pst->section_offsets = (struct section_offsets *) - obstack_alloc (&objfile->objfile_obstack, - SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); - for (i = 0; i < maybe->num_sections; i++) - (pst->section_offsets)->offsets[i] = maybe->sections[i]; - return; - } - - /* We were unable to find any offsets for this file. Complain. */ - if (dbx->stab_section_info) /* If there *is* any info, */ - complaint (&symfile_complaints, - _("elf/stab section information missing for %s"), filename); -} - /* Implementation of `sym_get_probes', as documented in symfile.h. */ -static VEC (probe_p) * +static const std::vector & elf_get_probes (struct objfile *objfile) { - VEC (probe_p) *probes_per_objfile; + std::vector *probes_per_bfd; /* Have we parsed this objfile's probes already? */ - probes_per_objfile = objfile_data (objfile, probe_key); + probes_per_bfd = (std::vector *) bfd_data (objfile->obfd, probe_key); - if (!probes_per_objfile) + if (probes_per_bfd == NULL) { - int ix; - const struct probe_ops *probe_ops; + probes_per_bfd = new std::vector; /* Here we try to gather information about all types of probes from the objfile. */ - for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, probe_ops); - ix++) - probe_ops->get_probes (&probes_per_objfile, objfile); - - if (probes_per_objfile == NULL) - { - VEC_reserve (probe_p, probes_per_objfile, 1); - gdb_assert (probes_per_objfile != NULL); - } + for (const static_probe_ops *ops : all_static_probe_ops) + ops->get_probes (probes_per_bfd, objfile); - set_objfile_data (objfile, probe_key, probes_per_objfile); + set_bfd_data (objfile->obfd, probe_key, probes_per_bfd); } - return probes_per_objfile; -} - -/* Implementation of `sym_relocate_probe', as documented in symfile.h. */ - -static void -elf_symfile_relocate_probe (struct objfile *objfile, - const struct section_offsets *new_offsets, - const struct section_offsets *delta) -{ - int ix; - VEC (probe_p) *probes = objfile_data (objfile, probe_key); - struct probe *probe; - - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) - probe->pops->relocate (probe, ANOFFSET (delta, SECT_OFF_TEXT (objfile))); + return *probes_per_bfd; } /* Helper function used to free the space allocated for storing SystemTap probe information. */ static void -probe_key_free (struct objfile *objfile, void *d) +probe_key_free (bfd *abfd, void *d) { - int ix; - VEC (probe_p) *probes = d; - struct probe *probe; + std::vector *probes = (std::vector *) d; - for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) - probe->pops->destroy (probe); + for (probe *p : *probes) + delete p; - VEC_free (probe_p, probes); + delete probes; } @@ -1551,7 +1366,6 @@ probe_key_free (struct objfile *objfile, void *d) static const struct sym_probe_fns elf_probe_fns = { elf_get_probes, /* sym_get_probes */ - elf_symfile_relocate_probe, /* sym_relocate_probe */ }; /* Register that we are able to handle ELF object file formats. */ @@ -1574,7 +1388,7 @@ static const struct sym_fns elf_sym_fns = /* The same as elf_sym_fns, but not registered and lazily reads psymbols. */ -static const struct sym_fns elf_sym_fns_lazy_psyms = +const struct sym_fns elf_sym_fns_lazy_psyms = { elf_new_init, /* init anything gbl to entire symtab */ elf_symfile_init, /* read initial info, setup for sym_read() */ @@ -1591,7 +1405,7 @@ static const struct sym_fns elf_sym_fns_lazy_psyms = /* The same as elf_sym_fns, but not registered and uses the DWARF-specific GNU index rather than psymtab. */ -static const struct sym_fns elf_sym_fns_gdb_index = +const struct sym_fns elf_sym_fns_gdb_index = { elf_new_init, /* init anything gbl to entire symab */ elf_symfile_init, /* read initial info, setup for sym_red() */ @@ -1606,6 +1420,23 @@ static const struct sym_fns elf_sym_fns_gdb_index = &dwarf2_gdb_index_functions }; +/* The same as elf_sym_fns, but not registered and uses the + DWARF-specific .debug_names index rather than psymtab. */ +const struct sym_fns elf_sym_fns_debug_names = +{ + elf_new_init, /* init anything gbl to entire symab */ + elf_symfile_init, /* read initial info, setup for sym_red() */ + elf_symfile_read, /* read a symbol file into symtab */ + NULL, /* sym_read_psymbols */ + elf_symfile_finish, /* finished with file, cleanup */ + default_symfile_offsets, /* Translate ext. to int. relocatin */ + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ + &elf_probe_fns, /* sym_probe_fns */ + &dwarf2_debug_names_functions +}; + /* STT_GNU_IFUNC resolver vector to be installed to gnu_ifunc_fns_p. */ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = @@ -1619,7 +1450,7 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = void _initialize_elfread (void) { - probe_key = register_objfile_data_with_cleanup (NULL, probe_key_free); + probe_key = register_bfd_data_with_cleanup (NULL, probe_key_free); add_symtab_fns (bfd_target_elf_flavour, &elf_sym_fns); elf_objfile_gnu_ifunc_cache_data = register_objfile_data ();