diff options
author | Thomas Preud'homme <thomas.preudhomme@arm.com> | 2016-07-15 17:49:08 +0100 |
---|---|---|
committer | Thomas Preud'homme <thomas.preudhomme@arm.com> | 2016-07-15 17:50:48 +0100 |
commit | 76359541825cf36ecd14ab6b5974ee56e1c59eff (patch) | |
tree | 2043ac1a958572f267df5fabf168bca70300900b /bfd/elflink.c | |
parent | bc7b765ab71f967eb2a9c3da111d7529eec46fbe (diff) | |
download | gdb-76359541825cf36ecd14ab6b5974ee56e1c59eff.zip gdb-76359541825cf36ecd14ab6b5974ee56e1c59eff.tar.gz gdb-76359541825cf36ecd14ab6b5974ee56e1c59eff.tar.bz2 |
Add support for creating ELF import libraries
2016-07-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
bfd/
* elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend hook.
(_bfd_elf_filter_global_symbols): Declare.
* elf.c (_bfd_elf_filter_global_symbols): New function.
* elflink.c (elf_filter_global_symbols): Likewise.
(elf_output_implib): Likewise.
(bfd_elf_final_link): Call above function, failing if it does.
* elfxx-target.h (elf_backend_filter_implib_symbols): Define macro and
default it to NULL.
(elf_backend_copy_indirect_symbol): Fix spacing.
(elf_backend_hide_symbol): Likewise.
(elfNN_bed): Initialize elf_backend_filter_implib_symbols backend hook.
include/
* bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
out_implib_bfd fields.
2016-07-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
Nick Clifton <nickc@redhat.com>
ld/
* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
library file for writing and initialize implib_bfd field of link_info
structure.
* emultempl/pe.em (pe_implib_filename): Remove variable declaration.
(OPTION_IMPLIB_FILENAME): Remove macro definition.
(gld${EMULATION_NAME}_add_options): Remove --out-implib option.
(gld_${EMULATION_NAME}_list_options): Likewise.
(gld${EMULATION_NAME}_handle_option): Likewise.
(gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
instead of pe_implib_filename.
* emultempl/pep.em (pep_implib_filename): Remove variable declaration.
(OPTION_IMPLIB_FILENAME): Remove enumerator.
(gld${EMULATION_NAME}_add_options): Remove --out-implib option.
(gld_${EMULATION_NAME}_list_options): Likewise.
(gld${EMULATION_NAME}_handle_option): Likewise.
(gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
instead of pep_implib_filename.
* ld.h (args_type): Declare new out_implib_filename field.
* ld.texinfo (--out-implib): Move documentation to arch-independent
part and rephrase to apply to ELF targets.
* ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
defined in linker scripts.
* ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
enumerator.
* lexsup.c (ld_options): Add entry for new --out-implib switch.
(parse_args): Handle OPTION_OUT_IMPLIB case.
* testsuite/ld-elf/elf.exp (Generate empty import library): New test.
(Generate import library): Likewise.
* testsuite/ld-elf/implib.s: Likewise.
* testsuite/ld-elf/implib.rd: New file.
* testsuite/ld-elf/empty-implib.out: Likewise
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 3e24940..b2a814f 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11028,6 +11028,107 @@ elf_fixup_link_order (bfd *abfd, asection *o) return TRUE; } +/* Generate an import library in INFO->implib_bfd from symbols in ABFD. + Returns TRUE upon success, FALSE otherwise. */ + +static bfd_boolean +elf_output_implib (bfd *abfd, struct bfd_link_info *info) +{ + bfd_boolean ret = FALSE; + bfd *implib_bfd; + const struct elf_backend_data *bed; + flagword flags; + enum bfd_architecture arch; + unsigned int mach; + asymbol **sympp = NULL; + long symsize; + long symcount; + long src_count; + elf_symbol_type *osymbuf; + + implib_bfd = info->out_implib_bfd; + bed = get_elf_backend_data (abfd); + + if (!bfd_set_format (implib_bfd, bfd_object)) + return FALSE; + + flags = bfd_get_file_flags (abfd); + flags &= ~HAS_RELOC; + if (!bfd_set_start_address (implib_bfd, 0) + || !bfd_set_file_flags (implib_bfd, flags)) + return FALSE; + + /* Copy architecture of output file to import library file. */ + arch = bfd_get_arch (abfd); + mach = bfd_get_mach (abfd); + if (!bfd_set_arch_mach (implib_bfd, arch, mach) + && (abfd->target_defaulted + || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd))) + return FALSE; + + /* Get symbol table size. */ + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + return FALSE; + + /* Read in the symbol table. */ + sympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (abfd, sympp); + if (symcount < 0) + goto free_sym_buf; + + /* Allow the BFD backend to copy any private header data it + understands from the output BFD to the import library BFD. */ + if (! bfd_copy_private_header_data (abfd, implib_bfd)) + goto free_sym_buf; + + /* Filter symbols to appear in the import library. */ + if (bed->elf_backend_filter_implib_symbols) + symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp, + symcount); + else + symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount); + if (symcount == 0) + { + (*_bfd_error_handler) (_("%B: no symbol found for import library"), + implib_bfd); + goto free_sym_buf; + } + + + /* Make symbols absolute. */ + osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount, + sizeof (*osymbuf)); + for (src_count = 0; src_count < symcount; src_count++) + { + memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count], + sizeof (*osymbuf)); + osymbuf[src_count].symbol.section = bfd_abs_section_ptr; + osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS; + osymbuf[src_count].symbol.value += sympp[src_count]->section->vma; + osymbuf[src_count].internal_elf_sym.st_value = + osymbuf[src_count].symbol.value; + sympp[src_count] = &osymbuf[src_count].symbol; + } + + bfd_set_symtab (implib_bfd, sympp, symcount); + + /* Allow the BFD backend to copy any private data it understands + from the output BFD to the import library BFD. This is done last + to permit the routine to look at the filtered symbol table. */ + if (! bfd_copy_private_bfd_data (abfd, implib_bfd)) + goto free_sym_buf; + + if (!bfd_close (implib_bfd)) + goto free_sym_buf; + + ret = TRUE; + +free_sym_buf: + free (sympp); + return ret; +} + static void elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo) { @@ -11830,6 +11931,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) return FALSE; } + if (info->out_implib_bfd && !elf_output_implib (abfd, info)) + { + (*_bfd_error_handler) (_("%B: failed to generate import library"), + info->out_implib_bfd); + return FALSE; + } + /* Adjust the relocs to have the correct symbol indices. */ for (o = abfd->sections; o != NULL; o = o->next) { |