X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Felfread.c;h=1dea226242db07a6158e163877a14ab287a0ca21;hb=61c4e60495146e1115cc9e8710c5abccdc821a9d;hp=d2a7bcf8aa6130caa89dae074ddda85bd5f92fd1;hpb=4b610737f02338b2aea7641ab771aa5e137d067c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/elfread.c b/gdb/elfread.c index d2a7bcf8aa..1dea226242 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-2019 Free Software Foundation, Inc. + Copyright (C) 1991-2021 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -47,11 +47,11 @@ #include "location.h" #include "auxv.h" #include "mdebugread.h" - -/* Forward declarations. */ -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; +#include "ctfread.h" +#include "gdbsupport/gdb_string_view.h" +#include "gdbsupport/scoped_fd.h" +#include "debuginfod-support.h" +#include "dwarf2/public.h" /* The struct elfinfo is available only during ELF symbol table and psymtab reading. It is destroyed at the completion of psymtab-reading. @@ -61,6 +61,7 @@ struct elfinfo { asection *stabsect; /* Section pointer for .stab section */ asection *mdebugsect; /* Section pointer for .mdebug section */ + asection *ctfsect; /* Section pointer for .ctf section */ }; /* Type for per-BFD data. */ @@ -80,14 +81,13 @@ static const struct bfd_key probe_key; /* Locate the segments in ABFD. */ -static struct symfile_segment_data * +static symfile_segment_data_up elf_symfile_segments (bfd *abfd) { Elf_Internal_Phdr *phdrs, **segments; long phdrs_size; int num_phdrs, num_segments, num_sections, i; asection *sect; - struct symfile_segment_data *data; phdrs_size = bfd_get_elf_phdr_upper_bound (abfd); if (phdrs_size == -1) @@ -107,19 +107,16 @@ elf_symfile_segments (bfd *abfd) if (num_segments == 0) return NULL; - data = XCNEW (struct symfile_segment_data); - data->num_segments = num_segments; - data->segment_bases = XCNEWVEC (CORE_ADDR, num_segments); - data->segment_sizes = XCNEWVEC (CORE_ADDR, num_segments); + symfile_segment_data_up data (new symfile_segment_data); + data->segments.reserve (num_segments); for (i = 0; i < num_segments; i++) - { - data->segment_bases[i] = segments[i]->p_vaddr; - data->segment_sizes[i] = segments[i]->p_memsz; - } + data->segments.emplace_back (segments[i]->p_vaddr, segments[i]->p_memsz); num_sections = bfd_count_sections (abfd); - data->segment_info = XCNEWVEC (int, num_sections); + + /* All elements are initialized to 0 (map to no segment). */ + data->segment_info.resize (num_sections); for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next) { @@ -146,10 +143,15 @@ elf_symfile_segments (bfd *abfd) RealView) use SHT_NOBITS for uninitialized data. Since it is uninitialized, it doesn't need a program header. Such binaries are not relocatable. */ - if (bfd_section_size (sect) > 0 && j == num_segments + + /* Exclude debuginfo files from this warning, too, since those + are often not strictly compliant with the standard. See, e.g., + ld/24717 for more discussion. */ + if (!is_debuginfo_file (abfd) + && bfd_section_size (sect) > 0 && j == num_segments && (bfd_section_flags (sect) & SEC_LOAD) != 0) - warning (_("Loadable section \"%s\" outside of ELF segments"), - bfd_section_name (sect)); + warning (_("Loadable section \"%s\" outside of ELF segments\n in %s"), + bfd_section_name (sect), bfd_get_filename (abfd)); } return data; @@ -175,11 +177,8 @@ elf_symfile_segments (bfd *abfd) -kingdon). */ static void -elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip) +elf_locate_sections (asection *sectp, struct elfinfo *ei) { - struct elfinfo *ei; - - ei = (struct elfinfo *) eip; if (strcmp (sectp->name, ".stab") == 0) { ei->stabsect = sectp; @@ -188,26 +187,35 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip) { ei->mdebugsect = sectp; } + else if (strcmp (sectp->name, ".ctf") == 0) + { + ei->ctfsect = sectp; + } } static struct minimal_symbol * record_minimal_symbol (minimal_symbol_reader &reader, - const char *name, int name_len, bool copy_name, + gdb::string_view name, bool copy_name, CORE_ADDR address, enum minimal_symbol_type ms_type, asection *bfd_section, struct objfile *objfile) { - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); if (ms_type == mst_text || ms_type == mst_file_text || ms_type == mst_text_gnu_ifunc) address = gdbarch_addr_bits_remove (gdbarch, address); + /* We only setup section information for allocatable sections. Usually + we'd only expect to find msymbols for allocatable sections, but if the + ELF is malformed then this might not be the case. In that case don't + create an msymbol that references an uninitialised section object. */ + int section_index = 0; + if ((bfd_section_flags (bfd_section) & SEC_ALLOC) == SEC_ALLOC) + section_index = gdb_bfd_section_index (objfile->obfd, bfd_section); + struct minimal_symbol *result - = reader.record_full (name, name_len, copy_name, address, - ms_type, - gdb_bfd_section_index (objfile->obfd, - bfd_section)); + = reader.record_full (name, copy_name, address, ms_type, section_index); if ((objfile->flags & OBJF_MAINLINE) == 0 && (ms_type == mst_data || ms_type == mst_bss)) result->maybe_copied = 1; @@ -237,7 +245,7 @@ elf_symtab_read (minimal_symbol_reader &reader, long number_of_symbols, asymbol **symbol_table, bool copy_names) { - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); asymbol *sym; long i; CORE_ADDR symaddr; @@ -324,7 +332,7 @@ elf_symtab_read (minimal_symbol_reader &reader, continue; msym = record_minimal_symbol - (reader, sym->name, strlen (sym->name), copy_names, + (reader, sym->name, copy_names, symaddr, mst_solib_trampoline, sect, objfile); if (msym != NULL) { @@ -341,11 +349,7 @@ elf_symtab_read (minimal_symbol_reader &reader, if (type == ST_DYNAMIC && !stripped) continue; if (sym->flags & BSF_FILE) - { - filesymname - = ((const char *) objfile->per_bfd->filename_cache.insert - (sym->name, strlen (sym->name) + 1)); - } + filesymname = objfile->intern (sym->name); else if (sym->flags & BSF_SECTION_SYM) continue; else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK @@ -468,7 +472,7 @@ elf_symtab_read (minimal_symbol_reader &reader, continue; /* Skip this symbol. */ } msym = record_minimal_symbol - (reader, sym->name, strlen (sym->name), copy_names, symaddr, + (reader, sym->name, copy_names, symaddr, ms_type, sym->section, objfile); if (msym) @@ -497,8 +501,10 @@ elf_symtab_read (minimal_symbol_reader &reader, { int len = atsign - sym->name; - record_minimal_symbol (reader, sym->name, len, true, symaddr, - ms_type, sym->section, objfile); + record_minimal_symbol (reader, + gdb::string_view (sym->name, len), + true, symaddr, ms_type, sym->section, + objfile); } } @@ -514,10 +520,9 @@ elf_symtab_read (minimal_symbol_reader &reader, { struct minimal_symbol *mtramp; - mtramp = record_minimal_symbol (reader, sym->name, len - 4, - true, symaddr, - mst_solib_trampoline, - sym->section, objfile); + mtramp = record_minimal_symbol + (reader, gdb::string_view (sym->name, len - 4), true, + symaddr, mst_solib_trampoline, sym->section, objfile); if (mtramp) { SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym)); @@ -548,7 +553,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader, const struct elf_backend_data *bed = get_elf_backend_data (obfd); asection *relplt, *got_plt; bfd_size_type reloc_count, reloc; - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; size_t ptr_size = TYPE_LENGTH (ptr_type); @@ -633,8 +638,7 @@ elf_rel_plt_read (minimal_symbol_reader &reader, string_buffer.assign (name); string_buffer.append (got_suffix, got_suffix + got_suffix_len); - msym = record_minimal_symbol (reader, string_buffer.c_str (), - string_buffer.size (), + msym = record_minimal_symbol (reader, string_buffer, true, address, mst_slot_got_plt, msym_section, objfile); if (msym) @@ -707,7 +711,7 @@ elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) /* If .plt jumps back to .plt the symbol is still deferred for later resolution and it has no use for GDB. */ - const char *target_name = MSYMBOL_LINKAGE_NAME (msym.minsym); + const char *target_name = msym.minsym->linkage_name (); size_t len = strlen (target_name); /* Note we check the symbol's name instead of checking whether the @@ -737,7 +741,7 @@ elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) { struct elf_gnu_ifunc_cache *entry_found_p = (struct elf_gnu_ifunc_cache *) *slot; - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); if (entry_found_p->addr != addr) { @@ -815,7 +819,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) for (objfile *objfile : current_program_space->objfiles ()) { bfd *obfd = objfile->obfd; - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct gdbarch *gdbarch = objfile->arch (); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; size_t ptr_size = TYPE_LENGTH (ptr_type); CORE_ADDR pointer_address, addr; @@ -839,8 +843,8 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) if (target_read_memory (pointer_address, buf, ptr_size) != 0) continue; addr = extract_typed_address (buf, ptr_type); - addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, - current_top_target ()); + addr = gdbarch_convert_from_func_ptr_addr + (gdbarch, addr, current_inferior ()->top_target ()); addr = gdbarch_addr_bits_remove (gdbarch, addr); if (elf_gnu_ifunc_record_cache (name, addr)) @@ -907,12 +911,13 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) parameter. FUNCTION is the function entry address. ADDRESS may be a function descriptor. */ - target_auxv_search (current_top_target (), AT_HWCAP, &hwcap); + target_auxv_search (current_inferior ()->top_target (), AT_HWCAP, &hwcap); hwcap_val = value_from_longest (builtin_type (gdbarch) ->builtin_unsigned_long, hwcap); address_val = call_function_by_hand (function, NULL, hwcap_val); address = value_as_address (address_val); - address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, current_top_target ()); + address = gdbarch_convert_from_func_ptr_addr + (gdbarch, address, current_inferior ()->top_target ()); address = gdbarch_addr_bits_remove (gdbarch, address); if (name_at_pc) @@ -1018,9 +1023,8 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) gdbarch_return_value (gdbarch, func_func, value_type, regcache, value_contents_raw (value), NULL); resolved_address = value_as_address (value); - resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, - resolved_address, - current_top_target ()); + resolved_pc = gdbarch_convert_from_func_ptr_addr + (gdbarch, resolved_address, current_inferior ()->top_target ()); resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc); gdb_assert (current_program_space == b->pspace || b->pspace == NULL); @@ -1059,7 +1063,8 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags, 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) + && ei->mdebugsect == NULL + && ei->ctfsect == NULL) { if (symtab_create_debug) fprintf_unfiltered (gdb_stdlog, @@ -1200,10 +1205,14 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) { bfd *abfd = objfile->obfd; struct elfinfo ei; + bool has_dwarf2 = true; memset ((char *) &ei, 0, sizeof (ei)); if (!(objfile->flags & OBJF_READNEVER)) - bfd_map_over_sections (abfd, elf_locate_sections, (void *) & ei); + { + for (asection *sect : gdb_bfd_sections (abfd)) + elf_locate_sections (sect, &ei); + } elf_read_minimal_symbols (objfile, symfile_flags, &ei); @@ -1224,7 +1233,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) const struct ecoff_debug_swap *swap; /* .mdebug section, presumably holding ECOFF debugging - information. */ + information. */ swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; if (swap) elfmdebug_build_psymtabs (objfile, swap, ei.mdebugsect); @@ -1234,7 +1243,7 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) asection *str_sect; /* Stab sections have an associated string table that looks like - a separate section. */ + a separate section. */ str_sect = bfd_get_section_by_name (abfd, ".stabstr"); /* FIXME should probably warn about a stab section without a stabstr. */ @@ -1246,47 +1255,20 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) } if (dwarf2_has_info (objfile, NULL, true)) - { - 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, &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 - partial symbols, because OBJF_PSYMTABS_READ has not been - set, and so our lazy reader function will still be called - when needed. */ - objfile_set_sym_fns (objfile, &elf_sym_fns_lazy_psyms); - } - } + dwarf2_initialize_objfile (objfile); /* If the file has its own symbol tables it has no separate debug info. `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS. `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. - .gnu_debugdata is !objfile_has_partial_symbols because it contains only + .gnu_debugdata is !objfile::has_partial_symbols because it contains only .symtab, not .debug_* section. But if we already added .gnu_debugdata as an objfile via find_separate_debug_file_in_section there was no separate debug info available. Therefore do not attempt to search for another one, objfile->separate_debug_objfile->separate_debug_objfile GDB guarantees to be NULL and we would possibly violate it. */ - else if (!objfile_has_partial_symbols (objfile) + else if (!objfile->has_partial_symbols () && objfile->separate_debug_objfile == NULL && objfile->separate_debug_objfile_backlink == NULL) { @@ -1302,16 +1284,43 @@ elf_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) symbol_file_add_separate (debug_bfd.get (), debugfile.c_str (), symfile_flags, objfile); } - } -} + else + { + has_dwarf2 = false; + const struct bfd_build_id *build_id = build_id_bfd_get (objfile->obfd); -/* Callback to lazily read psymtabs. */ + if (build_id != nullptr) + { + gdb::unique_xmalloc_ptr symfile_path; + scoped_fd fd (debuginfod_debuginfo_query (build_id->data, + build_id->size, + objfile->original_name, + &symfile_path)); -static void -read_psyms (struct objfile *objfile) -{ - if (dwarf2_has_info (objfile, NULL)) - dwarf2_build_psymtabs (objfile); + if (fd.get () >= 0) + { + /* File successfully retrieved from server. */ + gdb_bfd_ref_ptr debug_bfd (symfile_bfd_open (symfile_path.get ())); + + if (debug_bfd == nullptr) + warning (_("File \"%s\" from debuginfod cannot be opened as bfd"), + objfile->original_name); + else if (build_id_verify (debug_bfd.get (), build_id->size, build_id->data)) + { + symbol_file_add_separate (debug_bfd.get (), symfile_path.get (), + symfile_flags, objfile); + has_dwarf2 = true; + } + } + } + } + } + + /* Read the CTF section only if there is no DWARF info. */ + if (!has_dwarf2 && ei.ctfsect) + { + elfctf_build_psymtabs (objfile); + } } /* Initialize anything that needs initializing when a completely new symbol @@ -1380,66 +1389,12 @@ static const struct sym_fns elf_sym_fns = elf_new_init, /* init anything gbl to entire symtab */ elf_symfile_init, /* read initial info, setup for sym_read() */ 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. relocation */ - elf_symfile_segments, /* Get segment information from a file. */ - NULL, - default_symfile_relocate, /* Relocate a debug section. */ - &elf_probe_fns, /* sym_probe_fns */ - &psym_functions -}; - -/* The same as elf_sym_fns, but not registered and lazily reads - psymbols. */ - -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() */ - elf_symfile_read, /* read a symbol file into symtab */ - read_psyms, /* sym_read_psymbols */ elf_symfile_finish, /* finished with file, cleanup */ default_symfile_offsets, /* Translate ext. to int. relocation */ elf_symfile_segments, /* Get segment information from a file. */ NULL, default_symfile_relocate, /* Relocate a debug section. */ &elf_probe_fns, /* sym_probe_fns */ - &psym_functions -}; - -/* The same as elf_sym_fns, but not registered and uses the - DWARF-specific GNU index rather than psymtab. */ -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() */ - 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_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. */ @@ -1452,8 +1407,9 @@ static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = elf_gnu_ifunc_resolver_return_stop }; +void _initialize_elfread (); void -_initialize_elfread (void) +_initialize_elfread () { add_symtab_fns (bfd_target_elf_flavour, &elf_sym_fns);