diff options
36 files changed, 363 insertions, 133 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2aa89d0..b2553a6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2020-11-20 Nick Alcock <nick.alcock@oracle.com> + + * elflink.c (elf_finalize_dynstr): Call examine_strtab after + dynstr finalization. + (elf_link_swap_symbols_out): Don't call it here. Call + ctf_new_symbol before swap_symbol_out. + (elf_link_output_extsym): Call ctf_new_dynsym before + swap_symbol_out. + (bfd_elf_final_link): Likewise. + * elf.c (swap_out_syms): Pass in bfd_link_info. Call + ctf_new_symbol before swap_symbol_out. + (_bfd_elf_compute_section_file_positions): Adjust. + 2020-11-19 Nick Clifton <nickc@redhat.com> PR 26918 @@ -51,7 +51,8 @@ SECTION static int elf_sort_sections (const void *, const void *); static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); -static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ; +static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int, + struct bfd_link_info *); static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset, size_t align); @@ -4302,7 +4303,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd, /* Non-zero if doing a relocatable link. */ int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC)); - if (! swap_out_syms (abfd, &strtab, relocatable_p)) + if (! swap_out_syms (abfd, &strtab, relocatable_p, link_info)) return FALSE; } @@ -8050,7 +8051,8 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd, static bfd_boolean swap_out_syms (bfd *abfd, struct elf_strtab_hash **sttp, - int relocatable_p) + int relocatable_p, + struct bfd_link_info *info) { const struct elf_backend_data *bed; unsigned int symcount; @@ -8402,6 +8404,12 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."), else elfsym->sym.st_name = _bfd_elf_strtab_offset (stt, elfsym->sym.st_name); + if (info && info->callbacks->ctf_new_symbol) + info->callbacks->ctf_new_symbol (elfsym->dest_index, + &elfsym->sym); + + /* Inform the linker of the addition of this symbol. */ + bed->s->swap_symbol_out (abfd, &elfsym->sym, (outbound_syms + (elfsym->dest_index diff --git a/bfd/elflink.c b/bfd/elflink.c index 6cc6361..7ba667a 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3779,6 +3779,11 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) _bfd_elf_strtab_finalize (dynstr); size = _bfd_elf_strtab_size (dynstr); + /* Allow the linker to examine the dynsymtab now it's fully populated. */ + + if (info->callbacks->examine_strtab) + info->callbacks->examine_strtab (dynstr); + bed = get_elf_backend_data (dynobj); sdyn = bfd_get_linker_section (dynobj, ".dynamic"); BFD_ASSERT (sdyn != NULL); @@ -9853,6 +9858,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) } } + /* Now swap out the symbols. */ for (i = 0; i < hash_table->strtabcount; i++) { struct elf_sym_strtab *elfsym = &hash_table->strtab[i]; @@ -9862,6 +9868,13 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) elfsym->sym.st_name = (unsigned long) _bfd_elf_strtab_offset (flinfo->symstrtab, elfsym->sym.st_name); + + /* Inform the linker of the addition of this symbol. */ + + if (flinfo->info->callbacks->ctf_new_symbol) + flinfo->info->callbacks->ctf_new_symbol (elfsym->dest_index, + &elfsym->sym); + bed->s->swap_symbol_out (flinfo->output_bfd, &elfsym->sym, ((bfd_byte *) symbuf + (elfsym->dest_index @@ -9870,14 +9883,6 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) + elfsym->destshndx_index)); } - /* Allow the linker to examine the strtab and symtab now they are - populated. */ - - if (flinfo->info->callbacks->examine_strtab) - flinfo->info->callbacks->examine_strtab (hash_table->strtab, - hash_table->strtabcount, - flinfo->symstrtab); - hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; pos = hdr->sh_offset + hdr->sh_size; amt = hash_table->strtabcount * bed->s->sizeof_sym; @@ -10485,6 +10490,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) eoinfo->failed = TRUE; return FALSE; } + + /* Inform the linker of the addition of this symbol. */ + + if (flinfo->info->callbacks->ctf_new_dynsym) + flinfo->info->callbacks->ctf_new_dynsym (h->dynindx, &sym); + bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0); if (flinfo->hash_sec != NULL) @@ -12761,6 +12772,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } sym.st_value = s->vma; dest = dynsym + dynindx * bed->s->sizeof_sym; + + /* Inform the linker of the addition of this symbol. */ + + if (info->callbacks->ctf_new_dynsym) + info->callbacks->ctf_new_dynsym (dynindx, &sym); + bed->s->swap_symbol_out (abfd, &sym, dest, 0); } } @@ -12799,6 +12816,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) + e->isym.st_value); } + /* Inform the linker of the addition of this symbol. */ + + if (info->callbacks->ctf_new_dynsym) + info->callbacks->ctf_new_dynsym (e->dynindx, &sym); + dest = dynsym + e->dynindx * bed->s->sizeof_sym; bed->s->swap_symbol_out (abfd, &sym, dest, 0); } diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 6555615..f899b6d 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,10 @@ 2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * readelf.c (dump_section_as_ctf): Use .dynsym and .dynstr, not + .symtab and .strtab. + +2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * objdump.c (dump_ctf): Report errors from ctf_archive_iter. * readelf.c (dump_section_as_ctf): Likewise. diff --git a/binutils/readelf.c b/binutils/readelf.c index 4d484db..e4d96bb 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -14695,10 +14695,10 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) ctfsect.cts_data = data; if (!dump_ctf_symtab_name) - dump_ctf_symtab_name = strdup (".symtab"); + dump_ctf_symtab_name = strdup (".dynsym"); if (!dump_ctf_strtab_name) - dump_ctf_strtab_name = strdup (".strtab"); + dump_ctf_strtab_name = strdup (".dynstr"); if (dump_ctf_symtab_name && dump_ctf_symtab_name[0] != 0) { diff --git a/include/ChangeLog b/include/ChangeLog index 11ec1f4..5c0f6b9 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,5 +1,24 @@ 2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * bfdlink.h (struct elf_sym_strtab): Replace with... + (struct elf_internal_sym): ... this. + (struct bfd_link_callbacks) <examine_strtab>: Take only a + symstrtab argument. + <ctf_new_symbol>: New. + <ctf_new_dynsym>: Likewise. + * ctf-api.h (struct ctf_link_sym) <st_symidx>: New. + <st_nameidx>: Likewise. + <st_nameidx_set>: Likewise. + (ctf_link_iter_symbol_f): Removed. + (ctf_link_shuffle_syms): Remove most parameters, just takes a + ctf_dict_t now. + (ctf_link_add_linker_symbol): New, split from + ctf_link_shuffle_syms. + * ctf.h (CTF_F_DYNSTR): New. + (CTF_F_MAX): Adjust. + +2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * ctf-api.h (ctf_arc_open_by_name): Rename to... (ctf_dict_open): ... this, keeping compatibility function. (ctf_arc_open_by_name_sections): Rename to... diff --git a/include/bfdlink.h b/include/bfdlink.h index 55020e3..b92ef54 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -671,7 +671,7 @@ struct bfd_link_info /* Some forward-definitions used by some callbacks. */ struct elf_strtab_hash; -struct elf_sym_strtab; +struct elf_internal_sym; /* This structures holds a set of callback functions. These are called by the BFD linker routines. */ @@ -795,11 +795,17 @@ struct bfd_link_callbacks asection * current_section, asection * previous_section, bfd_boolean new_segment); /* This callback provides a chance for callers of the BFD to examine the - ELF string table and symbol table once they are complete and indexes and - offsets assigned. */ + ELF (dynamic) string table once it is complete. */ void (*examine_strtab) - (struct elf_sym_strtab *syms, bfd_size_type symcount, - struct elf_strtab_hash *symstrtab); + (struct elf_strtab_hash *symstrtab); + /* This callback is called just before a symbol is swapped out, so that the + CTF machinery can look up symbols during construction. The name is + already an external strtab offset at this point. */ + void (*ctf_new_symbol) + (int symidx, struct elf_internal_sym *sym); + /* Likewise, for dynamic symbols. */ + void (*ctf_new_dynsym) + (int symidx, struct elf_internal_sym *sym); /* This callback should emit the CTF section into a non-loadable section in the output BFD named .ctf or a name beginning with ".ctf.". */ void (*emit_ctf) diff --git a/include/ctf-api.h b/include/ctf-api.h index 38d7758..93bd5f3 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -65,14 +65,20 @@ typedef struct ctf_sect } ctf_sect_t; /* A minimal symbol extracted from a linker's internal symbol table - representation. */ + representation. The symbol name can be given either via st_name or via a + strtab offset in st_nameidx, which corresponds to one of the string offsets + communicated via the ctf_link_add_strtab callback. */ typedef struct ctf_link_sym { - /* The st_name will not be accessed outside the call to - ctf_link_shuffle_syms(). */ + /* The st_name and st_nameidx will not be accessed outside the call to + ctf_link_shuffle_syms(). If you set st_nameidx to offset zero, make sure + to set st_nameidx_set as well. */ const char *st_name; + size_t st_nameidx; + int st_nameidx_set; + uint32_t st_symidx; uint32_t st_shndx; uint32_t st_type; uint32_t st_value; @@ -485,10 +491,8 @@ extern int ctf_link (ctf_dict_t *, int flags); typedef const char *ctf_link_strtab_string_f (uint32_t *offset, void *arg); extern int ctf_link_add_strtab (ctf_dict_t *, ctf_link_strtab_string_f *, void *); -typedef ctf_link_sym_t *ctf_link_iter_symbol_f (ctf_link_sym_t *dest, - void *arg); -extern int ctf_link_shuffle_syms (ctf_dict_t *, ctf_link_iter_symbol_f *, - void *); +extern int ctf_link_add_linker_symbol (ctf_dict_t *, ctf_link_sym_t *); +extern int ctf_link_shuffle_syms (ctf_dict_t *); extern unsigned char *ctf_link_write (ctf_dict_t *, size_t *size, size_t threshold); diff --git a/include/ctf.h b/include/ctf.h index 6b8aa53..d0a21f1 100644 --- a/include/ctf.h +++ b/include/ctf.h @@ -200,7 +200,8 @@ typedef struct ctf_header #define CTF_VERSION CTF_VERSION_3 /* Current version. */ #define CTF_F_COMPRESS 0x1 /* Data buffer is compressed by libctf. */ -#define CTF_F_MAX CTF_F_COMPRESS /* The greatest flag value in use. */ +#define CTF_F_DYNSTR 0x8 /* Strings come from .dynstr. */ +#define CTF_F_MAX (CTF_F_COMPRESS | CTF_F_DYNSTR) typedef struct ctf_lblent { diff --git a/ld/ChangeLog b/ld/ChangeLog index a00cfe9..f8265f4 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,47 @@ 2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * ldelfgen.c (struct ctf_strsym_iter_cb_arg): Rename to... + (struct ctf_strtab_iter_cb_arg): ... this, changing fields: + <syms>: Remove. + <symcount>: Remove. + <symstrtab>: Rename to... + <strtab>: ... this. + (ldelf_ctf_strtab_iter_cb): Adjust. + (ldelf_ctf_symbols_iter_cb): Remove. + (ldelf_new_dynsym_for_ctf): New, tell libctf about a single + symbol. + (ldelf_examine_strtab_for_ctf): Rename to... + (ldelf_acquire_strings_for_ctf): ... this, only doing the strtab + portion and not symbols. + * ldelfgen.h: Adjust declarations accordingly. + * ldemul.c (ldemul_examine_strtab_for_ctf): Rename to... + (ldemul_acquire_strings_for_ctf): ... this. + (ldemul_new_dynsym_for_ctf): New. + * ldemul.h: Adjust declarations accordingly. + * ldlang.c (ldlang_ctf_apply_strsym): Rename to... + (ldlang_ctf_acquire_strings): ... this. + (ldlang_ctf_new_dynsym): New. + (lang_write_ctf): Call ldemul_new_dynsym_for_ctf with NULL to do + the actual symbol shuffle. + * ldlang.h (struct elf_strtab_hash): Adjust accordingly. + * ldmain.c (bfd_link_callbacks): Wire up new/renamed callbacks. + + * emultempl/aix.em: Adjust for emulation changes: + ldemul_examine_strtab_for_ctf renamed to + ldemul_acquire_strings_for_ctf, new ldemul_new_dynsym_for_ctf. + * emultempl/armcoff.em: Likewise. + * emultempl/beos.em: Likewise. + * emultempl/elf.em: Likewise. + * emultempl/elf-generic.em: Likewise. + * emultempl/linux.em: Likewise. + * emultempl/msp430.em: Likewise. + * emultempl/pe.em: Likewise. + * emultempl/pep.em: Likewise. + * emultempl/ticoff.em: Likewise. + * emultempl/vanilla.em: Likewise. + +2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index c1fe705..df7471b 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -1595,7 +1595,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, gld${EMULATION_NAME}_print_symbol }; EOF diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em index ff22af4..3a86af9 100644 --- a/ld/emultempl/armcoff.em +++ b/ld/emultempl/armcoff.em @@ -286,7 +286,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em index ace6e3a..d025f21 100644 --- a/ld/emultempl/beos.em +++ b/ld/emultempl/beos.em @@ -768,7 +768,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/elf-generic.em b/ld/emultempl/elf-generic.em index 7e0923b..a404148 100644 --- a/ld/emultempl/elf-generic.em +++ b/ld/emultempl/elf-generic.em @@ -28,4 +28,5 @@ EOF # Put these extra routines in ld${EMULATION_NAME}_emulation # LDEMUL_EMIT_CTF_EARLY=ldelf_emit_ctf_early -LDEMUL_EXAMINE_STRTAB_FOR_CTF=ldelf_examine_strtab_for_ctf +LDEMUL_ACQUIRE_STRINGS_FOR_CTF=ldelf_acquire_strings_for_ctf +LDEMUL_NEW_DYNSYM_FOR_CTF=ldelf_new_dynsym_for_ctf diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index 59eed70..cfdf60e 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -931,7 +931,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_NEW_VERS_PATTERN-NULL}, ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}, ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/generic.em b/ld/emultempl/generic.em index 24d3c1d..5a69c01 100644 --- a/ld/emultempl/generic.em +++ b/ld/emultempl/generic.em @@ -161,7 +161,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_NEW_VERS_PATTERN-NULL}, ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}, ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/linux.em b/ld/emultempl/linux.em index 1444610..0cff374 100644 --- a/ld/emultempl/linux.em +++ b/ld/emultempl/linux.em @@ -219,7 +219,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em index 7b78a53..31cba4a 100644 --- a/ld/emultempl/msp430.em +++ b/ld/emultempl/msp430.em @@ -936,7 +936,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_NEW_VERS_PATTERN-NULL}, ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}, ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 00db3d0..e07dc9c 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -2415,7 +2415,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern. */ NULL, /* extra_map_file_text. */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 2f4bdfb..74468be 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -2235,7 +2235,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern. */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/ticoff.em b/ld/emultempl/ticoff.em index 11ddd0c..1cf82be 100644 --- a/ld/emultempl/ticoff.em +++ b/ld/emultempl/ticoff.em @@ -186,7 +186,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ ${LDEMUL_EMIT_CTF_EARLY-NULL}, - ${LDEMUL_EXAMINE_STRTAB_FOR_CTF-NULL}, + ${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL}, + ${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL}, ${LDEMUL_PRINT_SYMBOL-NULL} }; EOF diff --git a/ld/emultempl/vanilla.em b/ld/emultempl/vanilla.em index 70d193c..324e38a 100644 --- a/ld/emultempl/vanilla.em +++ b/ld/emultempl/vanilla.em @@ -87,7 +87,8 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation = NULL, /* new_vers_pattern */ NULL, /* extra_map_file_text */ NULL, /* emit_ctf_early */ - NULL, /* examine_strtab_for_ctf */ + NULL, /* acquire_strings_for_ctf */ + NULL, /* new_dynsym_for_ctf */ NULL /* print_symbol */ }; EOF diff --git a/ld/ldelfgen.c b/ld/ldelfgen.c index e9496f9..ca531ee 100644 --- a/ld/ldelfgen.c +++ b/ld/ldelfgen.c @@ -28,6 +28,7 @@ #include "ldexp.h" #include "ldlang.h" #include "elf-bfd.h" +#include "elf/internal.h" #include "ldelfgen.h" void @@ -103,11 +104,9 @@ ldelf_emit_ctf_early (void) /* Callbacks used to map from bfd types to libctf types, under libctf's control. */ -struct ctf_strsym_iter_cb_arg +struct ctf_strtab_iter_cb_arg { - struct elf_sym_strtab *syms; - bfd_size_type symcount; - struct elf_strtab_hash *symstrtab; + struct elf_strtab_hash *strtab; size_t next_i; size_t next_idx; }; @@ -121,20 +120,20 @@ ldelf_ctf_strtab_iter_cb (uint32_t *offset, void *arg_) bfd_size_type off; const char *ret; - struct ctf_strsym_iter_cb_arg *arg = - (struct ctf_strsym_iter_cb_arg *) arg_; + struct ctf_strtab_iter_cb_arg *arg = + (struct ctf_strtab_iter_cb_arg *) arg_; /* There is no zeroth string. */ if (arg->next_i == 0) arg->next_i = 1; - if (arg->next_i >= _bfd_elf_strtab_len (arg->symstrtab)) + if (arg->next_i >= _bfd_elf_strtab_len (arg->strtab)) { arg->next_i = 0; return NULL; } - ret = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i++, &off); + ret = _bfd_elf_strtab_str (arg->strtab, arg->next_i++, &off); *offset = off; /* If we've overflowed, we cannot share any further strings: the CTF @@ -145,69 +144,74 @@ ldelf_ctf_strtab_iter_cb (uint32_t *offset, void *arg_) return ret; } -/* Return symbols from the symbol table to libctf, one by one. We assume (and - assert) that the symbols in the elf_link_hash_table are in strictly ascending - order, and that none will be added in between existing ones. Returns NULL - when iteration is complete. */ - -static struct ctf_link_sym * -ldelf_ctf_symbols_iter_cb (struct ctf_link_sym *dest, - void *arg_) +void +ldelf_acquire_strings_for_ctf + (struct ctf_dict *ctf_output, struct elf_strtab_hash *strtab) { - struct ctf_strsym_iter_cb_arg *arg = - (struct ctf_strsym_iter_cb_arg *) arg_; + struct ctf_strtab_iter_cb_arg args = { strtab, 0, 0 }; + if (!ctf_output) + return; - if (arg->next_i > arg->symcount) + if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) { - arg->next_i = 0; - arg->next_idx = 0; - return NULL; + if (ctf_link_add_strtab (ctf_output, ldelf_ctf_strtab_iter_cb, + &args) < 0) + einfo (_("%F%P: warning: CTF strtab association failed; strings will " + "not be shared: %s\n"), + ctf_errmsg (ctf_errno (ctf_output))); } - - ASSERT (arg->syms[arg->next_i].dest_index == arg->next_idx); - dest->st_name = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i, NULL); - dest->st_shndx = arg->syms[arg->next_i].sym.st_shndx; - dest->st_type = ELF_ST_TYPE (arg->syms[arg->next_i].sym.st_info); - dest->st_value = arg->syms[arg->next_i].sym.st_value; - arg->next_i++; - return dest; } void -ldelf_examine_strtab_for_ctf - (struct ctf_dict *ctf_output, struct elf_sym_strtab *syms, - bfd_size_type symcount, struct elf_strtab_hash *symstrtab) +ldelf_new_dynsym_for_ctf (struct ctf_dict *ctf_output, int symidx, + struct elf_internal_sym *sym) { - struct ctf_strsym_iter_cb_arg args = { syms, symcount, symstrtab, - 0, 0 }; - if (!ctf_output) + ctf_link_sym_t lsym; + + if (!ctf_output) return; - if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour - && !bfd_link_relocatable (&link_info)) + /* New symbol. */ + if (sym != NULL) { - if (ctf_link_add_strtab (ctf_output, ldelf_ctf_strtab_iter_cb, - &args) < 0) - einfo (_("%F%P: warning: CTF strtab association failed; strings will " - "not be shared: %s\n"), - ctf_errmsg (ctf_errno (ctf_output))); + lsym.st_name = NULL; + lsym.st_nameidx = sym->st_name; + lsym.st_nameidx_set = 1; + lsym.st_symidx = symidx; + lsym.st_shndx = sym->st_shndx; + lsym.st_type = ELF_ST_TYPE (sym->st_info); + lsym.st_value = sym->st_value; + if (ctf_link_add_linker_symbol (ctf_output, &lsym) < 0) + { + einfo (_("%F%P: warning: CTF symbol addition failed; CTF will " + "not be tied to symbols: %s\n"), + ctf_errmsg (ctf_errno (ctf_output))); + } + } + else + { + /* Shuffle all the symbols. */ - if (ctf_link_shuffle_syms (ctf_output, ldelf_ctf_symbols_iter_cb, - &args) < 0) - einfo (_("%F%P: warning: CTF symbol shuffling failed; slight space " - "cost: %s\n"), ctf_errmsg (ctf_errno (ctf_output))); + if (ctf_link_shuffle_syms (ctf_output) < 0) + einfo (_("%F%P: warning: CTF symbol shuffling failed; CTF will " + "not be tied to symbols: %s\n"), + ctf_errmsg (ctf_errno (ctf_output))); } } #else -extern int ldelf_emit_ctf_early (void) +int +ldelf_emit_ctf_early (void) { return 0; } -extern void ldelf_examine_strtab_for_ctf - (struct ctf_dict *ctf_output ATTRIBUTE_UNUSED, - struct elf_sym_strtab *syms ATTRIBUTE_UNUSED, - bfd_size_type symcount ATTRIBUTE_UNUSED, - struct elf_strtab_hash *symstrtab ATTRIBUTE_UNUSED) +void +ldelf_acquire_strings_for_ctf (struct ctf_dict *ctf_output ATTRIBUTE_UNUSED, + struct elf_strtab_hash *strtab ATTRIBUTE_UNUSED) +{} +void +ldelf_new_dynsym_for_ctf (struct ctf_dict *ctf_output ATTRIBUTE_UNUSED, + int symidx ATTRIBUTE_UNUSED, + struct elf_internal_sym *sym ATTRIBUTE_UNUSED) {} #endif diff --git a/ld/ldelfgen.h b/ld/ldelfgen.h index 93bdf29..3392c2b 100644 --- a/ld/ldelfgen.h +++ b/ld/ldelfgen.h @@ -18,12 +18,13 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -struct elf_sym_strtab; +struct elf_internal_sym; struct elf_strtab_hash; struct ctf_dict; extern void ldelf_map_segments (bfd_boolean); extern int ldelf_emit_ctf_early (void); -extern void ldelf_examine_strtab_for_ctf - (struct ctf_dict *ctf_output, struct elf_sym_strtab *syms, - bfd_size_type symcount, struct elf_strtab_hash *symstrtab); +extern void ldelf_acquire_strings_for_ctf + (struct ctf_dict *ctf_output, struct elf_strtab_hash *strtab); +extern void ldelf_new_dynsym_for_ctf + (struct ctf_dict *ctf_output, int symidx, struct elf_internal_sym *sym); diff --git a/ld/ldemul.c b/ld/ldemul.c index 6dc5112..920afc8 100644 --- a/ld/ldemul.c +++ b/ld/ldemul.c @@ -418,15 +418,19 @@ ldemul_emit_ctf_early (void) } void -ldemul_examine_strtab_for_ctf (struct ctf_dict *ctf_output, - struct elf_sym_strtab *syms, - bfd_size_type symcount, - struct elf_strtab_hash *symstrtab) +ldemul_acquire_strings_for_ctf (struct ctf_dict *ctf_output, + struct elf_strtab_hash *symstrtab) +{ + if (ld_emulation->acquire_strings_for_ctf) + ld_emulation->acquire_strings_for_ctf (ctf_output, symstrtab); +} +void +ldemul_new_dynsym_for_ctf (struct ctf_dict *ctf_output, int symidx, + struct elf_internal_sym *sym) { - if (ld_emulation->examine_strtab_for_ctf) - ld_emulation->examine_strtab_for_ctf (ctf_output, syms, - symcount, symstrtab); + if (ld_emulation->new_dynsym_for_ctf) + ld_emulation->new_dynsym_for_ctf (ctf_output, symidx, sym); } bfd_boolean diff --git a/ld/ldemul.h b/ld/ldemul.h index 5efe4aa..0b9653e 100644 --- a/ld/ldemul.h +++ b/ld/ldemul.h @@ -109,9 +109,11 @@ extern void ldemul_extra_map_file_text extern int ldemul_emit_ctf_early (void); /* Called from per-target code to examine the strtab and symtab. */ -extern void ldemul_examine_strtab_for_ctf - (struct ctf_dict *, struct elf_sym_strtab *, bfd_size_type, - struct elf_strtab_hash *); +extern void ldemul_acquire_strings_for_ctf + (struct ctf_dict *, struct elf_strtab_hash *); +extern void ldemul_new_dynsym_for_ctf + (struct ctf_dict *, int symidx, struct elf_internal_sym *); + extern bfd_boolean ldemul_print_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr); @@ -230,14 +232,22 @@ typedef struct ld_emulation_xfer_struct { int (*emit_ctf_early) (void); - /* Called to examine the string and symbol table late enough in linking that - they are finally laid out. If emit_ctf_early returns true, this is not - called and ldemul_maybe_emit_ctf() emits CTF in 'early' mode: otherwise, it - waits until 'late'. (Late mode needs explicit support at per-target link - time to get called at all). If set, called by ld when the examine_strtab + /* Called to examine the string table late enough in linking that it is + finally laid out. If emit_ctf_early returns true, this is not called, and + ldemul_maybe_emit_ctf emits CTF in 'early' mode: otherwise, it waits + until 'late'. (Late mode needs explicit support at per-target link time to + get called at all). If set, called by ld when the examine_strtab bfd_link_callback is invoked by per-target code. */ - void (*examine_strtab_for_ctf) (struct ctf_dict *, struct elf_sym_strtab *, - bfd_size_type, struct elf_strtab_hash *); + void (*acquire_strings_for_ctf) (struct ctf_dict *, struct elf_strtab_hash *); + + /* Called when a new symbol is added to the dynamic symbol table. If + emit_ctf_early returns true, this is not called, and ldemul_maybe_emit_ctf + emits CTF in 'early' mode: otherwise, it waits until 'late'. (Late mode + needs explicit support at per-target link time to get called at all). If + set, called by ld when the ctf_new_symbol bfd_link_callback is invoked by + per-target code. Called with a NULL symbol when no further symbols will be + provided. */ + void (*new_dynsym_for_ctf) (struct ctf_dict *, int, struct elf_internal_sym *); /* Called when printing a symbol to the map file. AIX uses this hook to flag gc'd symbols. */ diff --git a/ld/ldlang.c b/ld/ldlang.c index eaf90a6..b70937a 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -3826,14 +3826,20 @@ lang_merge_ctf (void) lang_ctf_errs_warnings (ctf_output); } -/* Let the emulation examine the symbol table and strtab to help it optimize the - CTF, if supported. */ +/* Let the emulation acquire strings from the dynamic strtab to help it optimize + the CTF, if supported. */ void -ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms, bfd_size_type symcount, - struct elf_strtab_hash *symstrtab) +ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab) { - ldemul_examine_strtab_for_ctf (ctf_output, syms, symcount, symstrtab); + ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab); +} + +/* Inform the emulation about the addition of a new dynamic symbol, in BFD + internal format. */ +void ldlang_ctf_new_dynsym (int symidx, struct elf_internal_sym *sym) +{ + ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym); } /* Write out the CTF section. Called early, if the emulation isn't going to @@ -3860,6 +3866,11 @@ lang_write_ctf (int late) return; } + /* Inform the emulation that all the symbols that will be received have + been. */ + + ldemul_new_dynsym_for_ctf (ctf_output, 0, NULL); + /* Emit CTF. */ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf"); @@ -3922,11 +3933,11 @@ ldlang_open_ctf (void) static void lang_merge_ctf (void) {} void -ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms ATTRIBUTE_UNUSED, - bfd_size_type symcount ATTRIBUTE_UNUSED, - struct elf_strtab_hash *symstrtab ATTRIBUTE_UNUSED) -{ -} +ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab + ATTRIBUTE_UNUSED) {} +void +ldlang_ctf_new_dynsym (int symidx ATTRIBUTE_UNUSED, + struct elf_internal_sym *sym ATTRIBUTE_UNUSED) {} static void lang_write_ctf (int late ATTRIBUTE_UNUSED) {} void ldlang_write_ctf_late (void) {} #endif diff --git a/ld/ldlang.h b/ld/ldlang.h index 196debf..6675c57 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -689,8 +689,10 @@ extern bfd_boolean load_symbols struct elf_sym_strtab; struct elf_strtab_hash; -extern void ldlang_ctf_apply_strsym - (struct elf_sym_strtab *, bfd_size_type, struct elf_strtab_hash *); +extern void ldlang_ctf_acquire_strings + (struct elf_strtab_hash *); +extern void ldlang_ctf_new_dynsym + (int symidx, struct elf_internal_sym *); extern void ldlang_write_ctf_late (void); extern bfd_boolean diff --git a/ld/ldmain.c b/ld/ldmain.c index cc3df76..f8a03c6 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -151,7 +151,9 @@ static struct bfd_link_callbacks link_callbacks = info_msg, minfo, ldlang_override_segment_assignment, - ldlang_ctf_apply_strsym, + ldlang_ctf_acquire_strings, + NULL, + ldlang_ctf_new_dynsym, ldlang_write_ctf_late }; diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 804f131..6670a6a 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,5 +1,18 @@ 2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * ctf-link.c (ctf_link_shuffle_syms): Adjust. + (ctf_link_add_linker_symbol): New, unimplemented stub. + * libctf.ver: Add it. + * ctf-create.c (ctf_serialize): Set CTF_F_DYNSTR on newly-serialized + dicts. + * ctf-open-bfd.c (ctf_bfdopen_ctfsect): Check for the flag: open the + symtab/strtab if not present, dynsym/dynstr otherwise. + * ctf-archive.c (ctf_arc_bufpreamble): New, get the preamble from + some arbitrary member of a CTF archive. + * ctf-impl.h (ctf_arc_bufpreamble): Declare it. + +2020-11-20 Nick Alcock <nick.alcock@oracle.com> + * ctf-archive.c (ctf_arc_open_by_offset): Rename to... (ctf_dict_open_by_offset): ... this. Adjust callers. (ctf_arc_open_by_name_internal): Rename to... diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index 72cdef9..25c30f6 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -377,6 +377,25 @@ ctf_new_archive_internal (int is_archive, int unmap_on_close, return arci; } +/* Get the CTF preamble from data in a buffer, which may be either an archive or + a CTF dict. If multiple dicts are present in an archive, the preamble comes + from an arbitrary dict. The preamble is a pointer into the ctfsect passed + in. */ + +const ctf_preamble_t * +ctf_arc_bufpreamble (const ctf_sect_t *ctfsect) +{ + if (ctfsect->cts_size > sizeof (uint64_t) && + (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC)) + { + struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data; + return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs) + + sizeof (uint64_t)); + } + else + return (const ctf_preamble_t *) ctfsect->cts_data; +} + /* Open a CTF archive or dictionary from data in a buffer (which the caller must preserve until ctf_arc_close() time). Returns the archive, or NULL and an error in *err (if not NULL). */ diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index c1a7a8a..384e8cf 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -298,6 +298,8 @@ ctf_serialize (ctf_dict_t *fp) hdr.cth_magic = CTF_MAGIC; hdr.cth_version = CTF_VERSION; + hdr.cth_flags = CTF_F_DYNSTR; + /* Iterate through the dynamic type definition list and compute the size of the CTF type section we will need to generate. */ diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 3f4cfac..0e09a45 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -683,6 +683,7 @@ ctf_new_archive_internal (int is_archive, int unmap_on_close, const ctf_sect_t *strsect, int *errp); extern struct ctf_archive *ctf_arc_open_internal (const char *, int *); extern void ctf_arc_close_internal (struct ctf_archive *); +extern const ctf_preamble_t *ctf_arc_bufpreamble (const ctf_sect_t *); extern void *ctf_set_open_errno (int *, int); extern unsigned long ctf_set_errno (ctf_dict_t *, int); diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c index 192d4fd..3f4f2ee 100644 --- a/libctf/ctf-link.c +++ b/libctf/ctf-link.c @@ -1596,9 +1596,12 @@ ctf_link_add_strtab (ctf_dict_t *fp, ctf_link_strtab_string_f *add_string, /* Not yet implemented. */ int -ctf_link_shuffle_syms (ctf_dict_t *fp _libctf_unused_, - ctf_link_iter_symbol_f *add_sym _libctf_unused_, - void *arg _libctf_unused_) +ctf_link_add_linker_symbol (ctf_dict_t *fp, ctf_link_sym_t *sym) +{ + return 0; +} +int +ctf_link_shuffle_syms (ctf_dict_t *fp) { return 0; } diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c index 449347e..a6f0d3f 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -100,12 +100,36 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, #ifdef HAVE_BFD_ELF ctf_sect_t symsect, strsect; - Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd); + Elf_Internal_Shdr *symhdr; size_t symcount; Elf_Internal_Sym *isymbuf; bfd_byte *symtab = NULL; + const char *symtab_name; const char *strtab = NULL; + const char *strtab_name; size_t strsize; + const ctf_preamble_t *preamble; + + if (ctfsect->cts_data == NULL) + { + bfderrstr = N_("CTF section is NULL"); + goto err; + } + preamble = ctf_arc_bufpreamble (ctfsect); + + if (preamble->ctp_flags & CTF_F_DYNSTR) + { + symhdr = &elf_tdata (abfd)->dynsymtab_hdr; + strtab_name = ".dynstr"; + symtab_name = ".dynsym"; + } + else + { + symhdr = &elf_tdata (abfd)->symtab_hdr; + strtab_name = ".strtab"; + symtab_name = ".symtab"; + } + /* TODO: handle SYMTAB_SHNDX. */ /* Get the symtab, and the strtab associated with it. */ @@ -145,12 +169,12 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, strtab = (const char *) strhdr->contents; } } - else /* No symtab: just try getting .strtab by name. */ + else /* No symtab: just try getting .strtab or .dynstr by name. */ { bfd_byte *str_bcontents; asection *str_asect; - if ((str_asect = bfd_get_section_by_name (abfd, ".strtab")) != NULL) + if ((str_asect = bfd_get_section_by_name (abfd, strtab_name)) != NULL) { if (bfd_malloc_and_get_section (abfd, str_asect, &str_bcontents)) { @@ -168,7 +192,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, use it for anything but debugging. */ strsect.cts_data = strtab; - strsect.cts_name = ".strtab"; + strsect.cts_name = strtab_name; strsect.cts_size = strsize; strsectp = &strsect; } @@ -176,7 +200,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, if (symtab) { assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym); - symsect.cts_name = ".symtab"; + symsect.cts_name = symtab_name; symsect.cts_entsize = symhdr->sh_entsize; symsect.cts_size = symhdr->sh_size; symsect.cts_data = symtab; diff --git a/libctf/libctf.ver b/libctf/libctf.ver index cf4fa73..317913e 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -181,4 +181,6 @@ LIBCTF_1.1 { ctf_dict_open_sections; ctf_dict_close; ctf_parent_dict; + + ctf_link_add_linker_symbol; } LIBCTF_1.0; |