diff options
author | Alan Modra <amodra@gmail.com> | 2019-09-09 23:07:35 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2019-09-11 13:44:22 +0930 |
commit | d871d478061f10b0879c688e2fa941407e9137aa (patch) | |
tree | 4f564ccc452de8255f2eecfecfb931de03ad2093 /ld/emultempl | |
parent | cb7f4b298e5e0a3ab4fb6b13aa89e970478597bc (diff) | |
download | fsf-binutils-gdb-d871d478061f10b0879c688e2fa941407e9137aa.zip fsf-binutils-gdb-d871d478061f10b0879c688e2fa941407e9137aa.tar.gz fsf-binutils-gdb-d871d478061f10b0879c688e2fa941407e9137aa.tar.bz2 |
Move elf32.em and elf-generic.em functions
Many ELF linker targets support multiple "emulations" and thus have
multiple copies of elf32.em being compiled and linked into ld. This
patch moves much of elf32.em and elf-generic.em into files which will
be compiled just once, resulting in a 20% decrease in ld size for
--enable-targets=all.
* Makefile.am (ALL_EMUL_EXTRA_OFILES): Add ldelf and ldelfgen.
(CFILES, HFILES, EXTRA_ld_new_SOURCES): Likewise.
* configure.tgt: Formatting.
(targ_extra_ofiles): Init to ldelf.o ldelfgen.o, reset to just
ldelfgen.o for generic ELF targets, and empty for non-ELF.
* emultempl/aarch64elf.em (gldaarch64_layout_sections_again): Use
ldelf_map_segments.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, aarch64_for_each_input_file_wrapper),
(aarch64_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/alphaelf.em (alpha_after_parse): Use ldelf_map_segments.
* emultempl/armelf.em (gldarm_layout_sections_again): Likewise.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, arm_for_each_input_file_wrapper),
(arm_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/cr16elf.em (cr16elf_after_parse): Use ldelf_map_segments.
* emultempl/crxelf.em (crxelf_after_parse): Likewise. Delete
declaration.
* emultempl/cskyelf.em (gldcsky_layout_sections_again): Use
ldelf_map_segments.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, csky_for_each_input_file_wrapper),
(csky_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/genelf.em: Include ldelfgen.h.
(gld${EMULATION_NAME}_before_allocation): Use ldelf_map_segments.
* emultempl/hppaelf.em (hppaelf_after_parse): Likewise.
(hppaelf_layout_sections_again): Likewise.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, hppa_for_each_input_file_wrapper),
(hppa_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/ia64elf.em (ia64elf_after_parse): Use ldelf_map_segments.
* emultempl/m68hc1xelf.em (real_func),
(m68hc11_for_each_input_file_wrapper),
(m68hc11_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/metagelf.em (metagelf_layout_sections_again): Use
ldelf_map_segments.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, metag_for_each_input_file_wrapper),
(metag_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/mipself.em (real_func),
(mips_for_each_input_file_wrapper),
(mips_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/mmo.em: Don't include elf-bfd.h, do include ldelfgen.h.
(gld${EMULATION_NAME}_after_allocation): Use ldelf_map_segments.
* emultempl/nds32elf.em (nds32_elf_after_parse): Use ldelf_after_parse.
(nds32_elf_after_allocation): Comment fix.
* emultempl/nios2elf.em (nios2elf_layout_sections_again): Use
ldelf_map_segments.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, nios2_for_each_input_file_wrapper),
(nios2_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
* emultempl/ppc32elf.em (gld${EMULATION_NAME}_load_symbols): Delete
declaration.
(ppc_recognized_file): Call ldelf_load_symbols.
* emultempl/ppc64elf.em (ppc_layout_sections_again): Likewise.
(gld${EMULATION_NAME}_after_allocation): Likewise.
(real_func, ppc_for_each_input_file_wrapper),
(ppc_lang_for_each_input_file): Delete.
(lang_for_each_input_file): Don't define.
(gld${EMULATION_NAME}_load_symbols): Don't declare.
(ppc64_recognized_file): Call ldelf_load_symbols.
* emultempl/riscvelf.em (gld${EMULATION_NAME}_after_allocation):
Use ldelf_map_segments.
* emultempl/spuelf.em (spu_place_special_section): Use
ldelf_place_orphan.
* emultempl/tic6xdsbt.em (gld${EMULATION_NAME}_after_allocation):
Use ldelf_map_segments.
* emultempl/vms.em: Include ldelfgen.h.
(gld${EMULATION_NAME}_after_allocation): Use ldelf_map_segments.
* emultempl/elf32.em: Remove unnecessary headers, include ldelf.h
and ldelfgen.h. Move much of file content to..
* ldelf.c: ..here. New file.
* ldelf.h: New file.
* emultempl/elf-generic.em: Move gld${EMULATION_NAME}_map_segments..
* ldelfgen.c: ..to here.
* ldelfgen.h: New file.
* ldlang.c (lang_for_each_input_file): Adjust to only call func
on real files.
(lang_for_each_file): Likewise.
* po/SRC-POTFILES.in: Regenerate.
* Makefile.in: Regenerate.
Diffstat (limited to 'ld/emultempl')
-rw-r--r-- | ld/emultempl/aarch64elf.em | 24 | ||||
-rw-r--r-- | ld/emultempl/alphaelf.em | 2 | ||||
-rw-r--r-- | ld/emultempl/armelf.em | 24 | ||||
-rw-r--r-- | ld/emultempl/cr16elf.em | 2 | ||||
-rw-r--r-- | ld/emultempl/crxelf.em | 4 | ||||
-rw-r--r-- | ld/emultempl/cskyelf.em | 24 | ||||
-rw-r--r-- | ld/emultempl/elf-generic.em | 44 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 2237 | ||||
-rw-r--r-- | ld/emultempl/genelf.em | 3 | ||||
-rw-r--r-- | ld/emultempl/hppaelf.em | 27 | ||||
-rw-r--r-- | ld/emultempl/ia64elf.em | 2 | ||||
-rw-r--r-- | ld/emultempl/m68hc1xelf.em | 21 | ||||
-rw-r--r-- | ld/emultempl/metagelf.em | 25 | ||||
-rw-r--r-- | ld/emultempl/mipself.em | 20 | ||||
-rw-r--r-- | ld/emultempl/mmo.em | 7 | ||||
-rw-r--r-- | ld/emultempl/nds32elf.em | 4 | ||||
-rw-r--r-- | ld/emultempl/nios2elf.em | 25 | ||||
-rw-r--r-- | ld/emultempl/ppc32elf.em | 3 | ||||
-rw-r--r-- | ld/emultempl/ppc64elf.em | 28 | ||||
-rw-r--r-- | ld/emultempl/riscvelf.em | 2 | ||||
-rw-r--r-- | ld/emultempl/spuelf.em | 2 | ||||
-rw-r--r-- | ld/emultempl/tic6xdsbt.em | 2 | ||||
-rw-r--r-- | ld/emultempl/vms.em | 3 |
23 files changed, 65 insertions, 2470 deletions
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em index 93f60a9..022de08 100644 --- a/ld/emultempl/aarch64elf.em +++ b/ld/emultempl/aarch64elf.em @@ -206,7 +206,7 @@ gldaarch64_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -275,7 +275,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); } static void @@ -339,26 +339,6 @@ aarch64_elf_create_output_section_statements (void) ldlang_add_file (stub_file); } -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void aarch64_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -aarch64_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&aarch64_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file aarch64_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/alphaelf.em b/ld/emultempl/alphaelf.em index 55e01be..fbee01f 100644 --- a/ld/emultempl/alphaelf.em +++ b/ld/emultempl/alphaelf.em @@ -82,7 +82,7 @@ alpha_after_parse (void) exp_nameop (SIZEOF_HEADERS, NULL)), NULL); - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } static void diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 80effa4..29972f1 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -276,7 +276,7 @@ gldarm_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -413,7 +413,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); } static void @@ -553,26 +553,6 @@ arm_elf_create_output_section_statements (void) bfd_elf32_arm_get_bfd_for_interworking (stub_file->the_bfd, &link_info); } -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void arm_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -arm_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&arm_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file arm_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/cr16elf.em b/ld/emultempl/cr16elf.em index 6fb2062..6f97d41 100644 --- a/ld/emultempl/cr16elf.em +++ b/ld/emultempl/cr16elf.em @@ -120,7 +120,7 @@ cr16elf_after_parse (void) is true the link sometimes fails. */ config.magic_demand_paged = FALSE; - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } /* This is called after the sections have been attached to output diff --git a/ld/emultempl/crxelf.em b/ld/emultempl/crxelf.em index bd32173..22bacde 100644 --- a/ld/emultempl/crxelf.em +++ b/ld/emultempl/crxelf.em @@ -26,8 +26,6 @@ fragment <<EOF #include "ldctor.h" -static void crxelf_after_parse (void); - static void crxelf_after_parse (void) { @@ -42,7 +40,7 @@ crxelf_after_parse (void) is true the link sometimes fails. */ config.magic_demand_paged = FALSE; - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } /* This is called after the sections have been attached to output diff --git a/ld/emultempl/cskyelf.em b/ld/emultempl/cskyelf.em index 3651bb2..aaddd9c 100644 --- a/ld/emultempl/cskyelf.em +++ b/ld/emultempl/cskyelf.em @@ -208,7 +208,7 @@ gldcsky_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -269,7 +269,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); } static void @@ -283,26 +283,6 @@ gld${EMULATION_NAME}_finish (void) finish_default (); } -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void csky_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -csky_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&csky_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file csky_lang_for_each_input_file - EOF # This code gets inserted into the generic elf32.sc linker script diff --git a/ld/emultempl/elf-generic.em b/ld/emultempl/elf-generic.em index ac60f99..8392cea 100644 --- a/ld/emultempl/elf-generic.em +++ b/ld/emultempl/elf-generic.em @@ -24,48 +24,4 @@ # fragment <<EOF -static void -gld${EMULATION_NAME}_map_segments (bfd_boolean need_layout) -{ - int tries = 10; - - do - { - lang_relax_sections (need_layout); - need_layout = FALSE; - - if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour - && !bfd_link_relocatable (&link_info)) - { - bfd_size_type phdr_size; - - phdr_size = elf_program_header_size (link_info.output_bfd); - /* If we don't have user supplied phdrs, throw away any - previous linker generated program headers. */ - if (lang_phdr_list == NULL) - elf_seg_map (link_info.output_bfd) = NULL; - if (!_bfd_elf_map_sections_to_segments (link_info.output_bfd, - &link_info)) - einfo (_("%F%P: map sections to segments failed: %E\n")); - - if (phdr_size != elf_program_header_size (link_info.output_bfd)) - { - if (tries > 6) - /* The first few times we allow any change to - phdr_size . */ - need_layout = TRUE; - else if (phdr_size - < elf_program_header_size (link_info.output_bfd)) - /* After that we only allow the size to grow. */ - need_layout = TRUE; - else - elf_program_header_size (link_info.output_bfd) = phdr_size; - } - } - } - while (need_layout && --tries); - - if (tries == 0) - einfo (_("%F%P: looping in map_segments")); -} EOF diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 52db0fd..5a3cc2f 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -38,13 +38,8 @@ fragment <<EOF #include "sysdep.h" #include "bfd.h" #include "libiberty.h" -#include "safe-ctype.h" -#include "filenames.h" #include "getopt.h" -#include <fcntl.h> - #include "bfdlink.h" - #include "ld.h" #include "ldmain.h" #include "ldmisc.h" @@ -52,34 +47,18 @@ fragment <<EOF #include "ldlang.h" #include "ldfile.h" #include "ldemul.h" -#include "ldbuildid.h" #include <ldgram.h> -#include "elf/common.h" #include "elf-bfd.h" -#include "filenames.h" +#include "ldelf.h" +#include "ldelfgen.h" /* Declare functions used by various EXTRA_EM_FILEs. */ static void gld${EMULATION_NAME}_before_parse (void); -static void gld${EMULATION_NAME}_after_parse (void); static void gld${EMULATION_NAME}_after_open (void); static void gld${EMULATION_NAME}_before_allocation (void); static void gld${EMULATION_NAME}_after_allocation (void); -static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan - (asection *, const char *, int); EOF -if [ "x${USE_LIBPATH}" = xyes ] ; then - case ${target} in - *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) - fragment <<EOF -#ifdef HAVE_GLOB -#include <glob.h> -#endif -EOF - ;; - esac -fi - # Import any needed special functions and/or overrides. # source_em ${srcdir}/emultempl/elf-generic.em @@ -111,2218 +90,66 @@ gld${EMULATION_NAME}_before_parse (void) EOF fi -if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then fragment <<EOF -static void -gld${EMULATION_NAME}_after_parse (void) -{ - if (bfd_link_pie (&link_info)) - link_info.flags_1 |= (bfd_vma) DF_1_PIE; - - if (bfd_link_executable (&link_info) - && link_info.nointerp) - { - if (link_info.dynamic_undefined_weak > 0) - einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n")); - link_info.dynamic_undefined_weak = 0; - } - after_parse_default (); -} - -EOF -fi - -if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then -fragment <<EOF -/* Handle the generation of DT_NEEDED tags. */ - -static bfd_boolean -gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry) -{ - int link_class = 0; - - /* Tell the ELF linker that we don't want the output file to have a - DT_NEEDED entry for this file, unless it is used to resolve - references in a regular object. */ - if (entry->flags.add_DT_NEEDED_for_regular) - link_class = DYN_AS_NEEDED; - - /* Tell the ELF linker that we don't want the output file to have a - DT_NEEDED entry for any dynamic library in DT_NEEDED tags from - this file at all. */ - if (!entry->flags.add_DT_NEEDED_for_dynamic) - link_class |= DYN_NO_ADD_NEEDED; - - if (entry->flags.just_syms - && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0) - einfo (_("%F%P: %pB: --just-symbols may not be used on DSO\n"), - entry->the_bfd); - - if (link_class == 0 - || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0) - return FALSE; - - bfd_elf_set_dyn_lib_class (entry->the_bfd, - (enum dynamic_lib_link_class) link_class); - - /* Continue on with normal load_symbols processing. */ - return FALSE; -} -EOF -fi - -fragment <<EOF - -/* These variables are required to pass information back and forth - between after_open and check_needed and stat_needed and vercheck. */ - -static struct bfd_link_needed_list *global_needed; -static struct stat global_stat; -static lang_input_statement_type *global_found; -static struct bfd_link_needed_list *global_vercheck_needed; -static bfd_boolean global_vercheck_failed; - /* These variables are used to implement target options */ static char *audit; /* colon (typically) separated list of libs */ static char *depaudit; /* colon (typically) separated list of libs */ -/* Style of .note.gnu.build-id section. */ -static const char *emit_note_gnu_build_id; - -/* On Linux, it's possible to have different versions of the same - shared library linked against different versions of libc. The - dynamic linker somehow tags which libc version to use in - /etc/ld.so.cache, and, based on the libc that it sees in the - executable, chooses which version of the shared library to use. - - We try to do a similar check here by checking whether this shared - library needs any other shared libraries which may conflict with - libraries we have already included in the link. If it does, we - skip it, and try to find another shared library farther on down the - link path. - - This is called via lang_for_each_input_file. - GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object - which we are checking. This sets GLOBAL_VERCHECK_FAILED if we find - a conflicting version. */ - -static void -gld${EMULATION_NAME}_vercheck (lang_input_statement_type *s) -{ - const char *soname; - struct bfd_link_needed_list *l; - - if (global_vercheck_failed) - return; - if (s->the_bfd == NULL - || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) - return; - - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname == NULL) - soname = lbasename (bfd_get_filename (s->the_bfd)); - - for (l = global_vercheck_needed; l != NULL; l = l->next) - { - const char *suffix; - - if (filename_cmp (soname, l->name) == 0) - { - /* Probably can't happen, but it's an easy check. */ - continue; - } - - if (strchr (l->name, '/') != NULL) - continue; - - suffix = strstr (l->name, ".so."); - if (suffix == NULL) - continue; - - suffix += sizeof ".so." - 1; - - if (filename_ncmp (soname, l->name, suffix - l->name) == 0) - { - /* Here we know that S is a dynamic object FOO.SO.VER1, and - the object we are considering needs a dynamic object - FOO.SO.VER2, and VER1 and VER2 are different. This - appears to be a version mismatch, so we tell the caller - to try a different version of this library. */ - global_vercheck_failed = TRUE; - return; - } - } -} - - -/* See if an input file matches a DT_NEEDED entry by running stat on - the file. */ - -static void -gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s) -{ - struct stat st; - const char *suffix; - const char *soname; - - if (global_found != NULL) - return; - if (s->the_bfd == NULL) - return; - - /* If this input file was an as-needed entry, and wasn't found to be - needed at the stage it was linked, then don't say we have loaded it. */ - if ((bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0) - return; - - if (bfd_stat (s->the_bfd, &st) != 0) - { - einfo (_("%P: %pB: bfd_stat failed: %E\n"), s->the_bfd); - return; - } - - /* Some operating systems, e.g. Windows, do not provide a meaningful - st_ino; they always set it to zero. (Windows does provide a - meaningful st_dev.) Do not indicate a duplicate library in that - case. While there is no guarantee that a system that provides - meaningful inode numbers will never set st_ino to zero, this is - merely an optimization, so we do not need to worry about false - negatives. */ - if (st.st_dev == global_stat.st_dev - && st.st_ino == global_stat.st_ino - && st.st_ino != 0) - { - global_found = s; - return; - } - - /* We issue a warning if it looks like we are including two - different versions of the same shared library. For example, - there may be a problem if -lc picks up libc.so.6 but some other - shared library has a DT_NEEDED entry of libc.so.5. This is a - heuristic test, and it will only work if the name looks like - NAME.so.VERSION. FIXME: Depending on file names is error-prone. - If we really want to issue warnings about mixing version numbers - of shared libraries, we need to find a better way. */ - - if (strchr (global_needed->name, '/') != NULL) - return; - suffix = strstr (global_needed->name, ".so."); - if (suffix == NULL) - return; - suffix += sizeof ".so." - 1; - - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname == NULL) - soname = lbasename (s->filename); - - if (filename_ncmp (soname, global_needed->name, suffix - global_needed->name) == 0) - einfo (_("%P: warning: %s, needed by %pB, may conflict with %s\n"), - global_needed->name, global_needed->by, soname); -} - -struct dt_needed -{ - bfd *by; - const char *name; -}; - -/* This function is called for each possible name for a dynamic object - named by a DT_NEEDED entry. The FORCE parameter indicates whether - to skip the check for a conflicting version. */ - -static bfd_boolean -gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, - int force) -{ - bfd *abfd; - const char *name = needed->name; - const char *soname; - int link_class; - - abfd = bfd_openr (name, bfd_get_target (link_info.output_bfd)); - if (abfd == NULL) - { - if (verbose) - info_msg (_("attempt to open %s failed\n"), name); - return FALSE; - } - - /* Linker needs to decompress sections. */ - abfd->flags |= BFD_DECOMPRESS; - - if (! bfd_check_format (abfd, bfd_object)) - { - bfd_close (abfd); - return FALSE; - } - if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) - { - bfd_close (abfd); - return FALSE; - } - - /* For DT_NEEDED, they have to match. */ - if (abfd->xvec != link_info.output_bfd->xvec) - { - bfd_close (abfd); - return FALSE; - } - - /* Check whether this object would include any conflicting library - versions. If FORCE is set, then we skip this check; we use this - the second time around, if we couldn't find any compatible - instance of the shared library. */ - - if (! force) - { - struct bfd_link_needed_list *needs; - - if (! bfd_elf_get_bfd_needed_list (abfd, &needs)) - einfo (_("%F%P: %pB: bfd_elf_get_bfd_needed_list failed: %E\n"), abfd); - - if (needs != NULL) - { - global_vercheck_needed = needs; - global_vercheck_failed = FALSE; - lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); - if (global_vercheck_failed) - { - bfd_close (abfd); - /* Return FALSE to force the caller to move on to try - another file on the search path. */ - return FALSE; - } - - /* But wait! It gets much worse. On Linux, if a shared - library does not use libc at all, we are supposed to skip - it the first time around in case we encounter a shared - library later on with the same name which does use the - version of libc that we want. This is much too horrible - to use on any system other than Linux. */ - -EOF -case ${target} in - *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) - fragment <<EOF - { - struct bfd_link_needed_list *l; - - for (l = needs; l != NULL; l = l->next) - if (CONST_STRNEQ (l->name, "libc.so")) - break; - if (l == NULL) - { - bfd_close (abfd); - return FALSE; - } - } - -EOF - ;; -esac -fragment <<EOF - } - } - - /* We've found a dynamic object matching the DT_NEEDED entry. */ - - /* We have already checked that there is no other input file of the - same name. We must now check again that we are not including the - same file twice. We need to do this because on many systems - libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will - reference libc.so.1. If we have already included libc.so, we - don't want to include libc.so.1 if they are the same file, and we - can only check that using stat. */ - - if (bfd_stat (abfd, &global_stat) != 0) - einfo (_("%F%P: %pB: bfd_stat failed: %E\n"), abfd); - - /* First strip off everything before the last '/'. */ - soname = lbasename (abfd->filename); - - if (verbose) - info_msg (_("found %s at %s\n"), soname, name); - - global_found = NULL; - lang_for_each_input_file (gld${EMULATION_NAME}_stat_needed); - if (global_found != NULL) - { - /* Return TRUE to indicate that we found the file, even though - we aren't going to do anything with it. */ - return TRUE; - } - - /* Specify the soname to use. */ - bfd_elf_set_dt_needed_name (abfd, soname); - - /* Tell the ELF linker that we don't want the output file to have a - DT_NEEDED entry for this file, unless it is used to resolve - references in a regular object. */ - link_class = DYN_DT_NEEDED; - - /* Tell the ELF linker that we don't want the output file to have a - DT_NEEDED entry for this file at all if the entry is from a file - with DYN_NO_ADD_NEEDED. */ - if (needed->by != NULL - && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0) - link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED; - - bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class); - - /* Add this file into the symbol table. */ - if (! bfd_link_add_symbols (abfd, &link_info)) - einfo (_("%F%P: %pB: error adding symbols: %E\n"), abfd); - - return TRUE; -} - -/* Search for a needed file in a path. */ - -static bfd_boolean -gld${EMULATION_NAME}_search_needed (const char *path, - struct dt_needed *n, int force) -{ - const char *s; - const char *name = n->name; - size_t len; - struct dt_needed needed; - - if (name[0] == '/') - return gld${EMULATION_NAME}_try_needed (n, force); - - if (path == NULL || *path == '\0') - return FALSE; - - needed.by = n->by; - needed.name = n->name; - - len = strlen (name); - while (1) - { - unsigned offset = 0; - char * var; - char *filename, *sset; - - s = strchr (path, config.rpath_separator); - if (s == NULL) - s = path + strlen (path); - -#if HAVE_DOS_BASED_FILE_SYSTEM - /* Assume a match on the second char is part of drive specifier. */ - else if (config.rpath_separator == ':' - && s == path + 1 - && ISALPHA (*path)) - { - s = strchr (s + 1, config.rpath_separator); - if (s == NULL) - s = path + strlen (path); - } -#endif - filename = (char *) xmalloc (s - path + len + 2); - if (s == path) - sset = filename; - else - { - memcpy (filename, path, s - path); - filename[s - path] = '/'; - sset = filename + (s - path) + 1; - } - strcpy (sset, name); - - /* PR 20535: Support the same pseudo-environment variables that - are supported by ld.so. Namely, $ORIGIN, $LIB and $PLATFORM. - Since there can be more than one occurrence of these tokens in - the path we loop until no more are found. Since we might not - be able to substitute some of the tokens we maintain an offset - into the filename for where we should begin our scan. */ - while ((var = strchr (filename + offset, '$')) != NULL) - { - /* The ld.so manual page does not say, but I am going to assume that - these tokens are terminated by a directory separator character - (/) or the end of the string. There is also an implication that - $ORIGIN should only be used at the start of a path, but that is - not enforced here. - - The ld.so manual page also states that it allows ${ORIGIN}, - ${LIB} and ${PLATFORM}, so these are supported as well. - - FIXME: The code could be a lot cleverer about allocating space - for the processed string. */ - char * end = strchr (var, '/'); - const char *replacement = NULL; - char * v = var + 1; - char * freeme = NULL; - unsigned flen = strlen (filename); - - if (end != NULL) - /* Temporarily terminate the filename at the end of the token. */ - * end = 0; - - if (*v == '{') - ++ v; - switch (*v++) - { - case 'O': - if (strcmp (v, "RIGIN") == 0 || strcmp (v, "RIGIN}") == 0) - { - /* ORIGIN - replace with the full path to the directory - containing the program or shared object. */ - if (needed.by == NULL) - { - if (link_info.output_bfd == NULL) - { - break; - } - else - replacement = bfd_get_filename (link_info.output_bfd); - } - else - replacement = bfd_get_filename (needed.by); - - if (replacement) - { - char * slash; - - if (replacement[0] == '/') - freeme = xstrdup (replacement); - else - { - char * current_dir = getpwd (); - - freeme = xmalloc (strlen (replacement) + strlen (current_dir) + 2); - sprintf (freeme, "%s/%s", current_dir, replacement); - } - - replacement = freeme; - if ((slash = strrchr (replacement, '/')) != NULL) - * slash = 0; - } - } - break; - - case 'L': - if (strcmp (v, "IB") == 0 || strcmp (v, "IB}") == 0) - { - /* LIB - replace with "lib" in 32-bit environments - and "lib64" in 64-bit environments. */ - - /* Note - we could replace this switch statement by - conditional fragments of shell script, but that is messy. - Any compiler worth its salt is going to optimize away - all but one of these case statements anyway. */ - switch ($ELFSIZE) - { - case 32: replacement = "lib"; break; - case 64: replacement = "lib64"; break; - default: - /* $ELFSIZE is not 32 or 64 ... */ - abort (); - } - } - break; - - case 'P': - /* Supporting $PLATFORM in a cross-hosted environment is not - possible. Supporting it in a native environment involves - loading the <sys/auxv.h> header file which loads the - system <elf.h> header file, which conflicts with the - "include/elf/mips.h" header file. */ - /* Fall through. */ - default: - break; - } - - if (replacement) - { - char * filename2 = xmalloc (flen + strlen (replacement)); - - if (end) - { - sprintf (filename2, "%.*s%s/%s", - (int)(var - filename), filename, - replacement, end + 1); - offset = (var - filename) + 1 + strlen (replacement); - } - else - { - sprintf (filename2, "%.*s%s", - (int)(var - filename), filename, - replacement); - offset = var - filename + strlen (replacement); - } - - free (filename); - filename = filename2; - /* There is no need to restore the path separator (when - end != NULL) as we have replaced the entire string. */ - } - else - { - if (verbose) - /* We only issue an "unrecognised" message in verbose mode - as the $<foo> token might be a legitimate component of - a path name in the target's file system. */ - info_msg (_("unrecognised or unsupported token '%s' in search path\n"), var); - - if (end) - /* Restore the path separator. */ - * end = '/'; - - /* PR 20784: Make sure that we resume the scan *after* - the token that we could not replace. */ - offset = (var + 1) - filename; - } - - free (freeme); - } - - needed.name = filename; - - if (gld${EMULATION_NAME}_try_needed (&needed, force)) - return TRUE; - - free (filename); - - if (*s == '\0') - break; - path = s + 1; - } - - return FALSE; -} - EOF -if [ "x${USE_LIBPATH}" = xyes ] ; then - fragment <<EOF -/* Prefix the sysroot to absolute paths in PATH, a string containing - paths separated by config.rpath_separator. If running on a DOS - file system, paths containing a drive spec won't have the sysroot - prefix added, unless the sysroot also specifies the same drive. */ - -static const char * -gld${EMULATION_NAME}_add_sysroot (const char *path) -{ - size_t len, extra; - const char *p; - char *ret, *q; - int dos_drive_sysroot = HAS_DRIVE_SPEC (ld_sysroot); - - len = strlen (ld_sysroot); - for (extra = 0, p = path; ; ) - { - int dos_drive = HAS_DRIVE_SPEC (p); - - if (dos_drive) - p += 2; - if (IS_DIR_SEPARATOR (*p) - && (!dos_drive - || (dos_drive_sysroot - && ld_sysroot[0] == p[-2]))) - { - if (dos_drive && dos_drive_sysroot) - extra += len - 2; - else - extra += len; - } - p = strchr (p, config.rpath_separator); - if (!p) - break; - ++p; - } - - ret = xmalloc (strlen (path) + extra + 1); - - for (q = ret, p = path; ; ) - { - const char *end; - int dos_drive = HAS_DRIVE_SPEC (p); - - if (dos_drive) - { - *q++ = *p++; - *q++ = *p++; - } - if (IS_DIR_SEPARATOR (*p) - && (!dos_drive - || (dos_drive_sysroot - && ld_sysroot[0] == p[-2]))) - { - if (dos_drive && dos_drive_sysroot) - { - strcpy (q, ld_sysroot + 2); - q += len - 2; - } - else - { - strcpy (q, ld_sysroot); - q += len; - } - } - end = strchr (p, config.rpath_separator); - if (end) - { - size_t n = end - p + 1; - strncpy (q, p, n); - q += n; - p += n; - } - else - { - strcpy (q, p); - break; - } - } - - return ret; -} +if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then -EOF + IS_LINUX_TARGET=FALSE + IS_FREEBSD_TARGET=FALSE case ${target} in - *-*-freebsd* | *-*-dragonfly*) - fragment <<EOF -/* Read the system search path the FreeBSD way rather than the Linux way. */ -#ifdef HAVE_ELF_HINTS_H -#include <elf-hints.h> -#else -#include "elf-hints-local.h" -#endif - -static bfd_boolean -gld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l, - int force) -{ - static bfd_boolean initialized; - static const char *ld_elf_hints; - struct dt_needed needed; - - if (!initialized) - { - FILE *f; - char *tmppath; - - tmppath = concat (ld_sysroot, _PATH_ELF_HINTS, (const char *) NULL); - f = fopen (tmppath, FOPEN_RB); - free (tmppath); - if (f != NULL) - { - struct elfhints_hdr hdr; - - if (fread (&hdr, 1, sizeof (hdr), f) == sizeof (hdr) - && hdr.magic == ELFHINTS_MAGIC - && hdr.version == 1) - { - if (fseek (f, hdr.strtab + hdr.dirlist, SEEK_SET) != -1) - { - char *b; - - b = xmalloc (hdr.dirlistlen + 1); - if (fread (b, 1, hdr.dirlistlen + 1, f) == - hdr.dirlistlen + 1) - ld_elf_hints = gld${EMULATION_NAME}_add_sysroot (b); - - free (b); - } - } - fclose (f); - } - - initialized = TRUE; - } - - if (ld_elf_hints == NULL) - return FALSE; - - needed.by = l->by; - needed.name = l->name; - return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force); -} -EOF - # FreeBSD - ;; - *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) - fragment <<EOF -/* For a native linker, check the file /etc/ld.so.conf for directories - in which we may find shared libraries. /etc/ld.so.conf is really - only meaningful on Linux. */ - -struct gld${EMULATION_NAME}_ld_so_conf -{ - char *path; - size_t len, alloc; -}; - -static bfd_boolean -gld${EMULATION_NAME}_parse_ld_so_conf - (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename); - -static void -gld${EMULATION_NAME}_parse_ld_so_conf_include - (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename, - const char *pattern) -{ - char *newp = NULL; -#ifdef HAVE_GLOB - glob_t gl; -#endif - - if (pattern[0] != '/') - { - char *p = strrchr (filename, '/'); - size_t patlen = strlen (pattern) + 1; - - newp = xmalloc (p - filename + 1 + patlen); - memcpy (newp, filename, p - filename + 1); - memcpy (newp + (p - filename + 1), pattern, patlen); - pattern = newp; - } - -#ifdef HAVE_GLOB - if (glob (pattern, 0, NULL, &gl) == 0) - { - size_t i; - - for (i = 0; i < gl.gl_pathc; ++i) - gld${EMULATION_NAME}_parse_ld_so_conf (info, gl.gl_pathv[i]); - globfree (&gl); - } -#else - /* If we do not have glob, treat the pattern as a literal filename. */ - gld${EMULATION_NAME}_parse_ld_so_conf (info, pattern); -#endif - - if (newp) - free (newp); -} - -static bfd_boolean -gld${EMULATION_NAME}_parse_ld_so_conf - (struct gld${EMULATION_NAME}_ld_so_conf *info, const char *filename) -{ - FILE *f = fopen (filename, FOPEN_RT); - char *line; - size_t linelen; - - if (f == NULL) - return FALSE; - - linelen = 256; - line = xmalloc (linelen); - do - { - char *p = line, *q; - - /* Normally this would use getline(3), but we need to be portable. */ - while ((q = fgets (p, linelen - (p - line), f)) != NULL - && strlen (q) == linelen - (p - line) - 1 - && line[linelen - 2] != '\n') - { - line = xrealloc (line, 2 * linelen); - p = line + linelen - 1; - linelen += linelen; - } - - if (q == NULL && p == line) - break; - - p = strchr (line, '\n'); - if (p) - *p = '\0'; - - /* Because the file format does not know any form of quoting we - can search forward for the next '#' character and if found - make it terminating the line. */ - p = strchr (line, '#'); - if (p) - *p = '\0'; - - /* Remove leading whitespace. NUL is no whitespace character. */ - p = line; - while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v') - ++p; - - /* If the line is blank it is ignored. */ - if (p[0] == '\0') - continue; - - if (CONST_STRNEQ (p, "include") && (p[7] == ' ' || p[7] == '\t')) - { - char *dir, c; - p += 8; - do - { - while (*p == ' ' || *p == '\t') - ++p; - - if (*p == '\0') - break; - - dir = p; - - while (*p != ' ' && *p != '\t' && *p) - ++p; - - c = *p; - *p++ = '\0'; - if (dir[0] != '\0') - gld${EMULATION_NAME}_parse_ld_so_conf_include (info, filename, - dir); - } - while (c != '\0'); - } - else - { - char *dir = p; - while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f' - && *p != '\r' && *p != '\v') - ++p; - - while (p != dir && p[-1] == '/') - --p; - if (info->path == NULL) - { - info->alloc = p - dir + 1 + 256; - info->path = xmalloc (info->alloc); - info->len = 0; - } - else - { - if (info->len + 1 + (p - dir) >= info->alloc) - { - info->alloc += p - dir + 256; - info->path = xrealloc (info->path, info->alloc); - } - info->path[info->len++] = config.rpath_separator; - } - memcpy (info->path + info->len, dir, p - dir); - info->len += p - dir; - info->path[info->len] = '\0'; - } - } - while (! feof (f)); - free (line); - fclose (f); - return TRUE; -} - -static bfd_boolean -gld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l, - int force) -{ - static bfd_boolean initialized; - static const char *ld_so_conf; - struct dt_needed needed; - - if (! initialized) - { - char *tmppath; - struct gld${EMULATION_NAME}_ld_so_conf info; - - info.path = NULL; - info.len = info.alloc = 0; - tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", - (const char *) NULL); - if (!gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath)) - { - free (tmppath); - tmppath = concat (ld_sysroot, "/etc/ld.so.conf", - (const char *) NULL); - gld${EMULATION_NAME}_parse_ld_so_conf (&info, tmppath); - } - free (tmppath); - - if (info.path) - { - ld_so_conf = gld${EMULATION_NAME}_add_sysroot (info.path); - free (info.path); - } - initialized = TRUE; - } - - if (ld_so_conf == NULL) - return FALSE; - - - needed.by = l->by; - needed.name = l->name; - return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force); -} - -EOF - # Linux - ;; + IS_LINUX_TARGET=TRUE ;; + *-*-freebsd* | *-*-dragonfly*) + IS_FREEBSD_TARGET=TRUE ;; esac -fi -fragment <<EOF - -/* See if an input file matches a DT_NEEDED entry by name. */ - -static void -gld${EMULATION_NAME}_check_needed (lang_input_statement_type *s) -{ - const char *soname; - - /* Stop looking if we've found a loaded lib. */ - if (global_found != NULL - && (bfd_elf_get_dyn_lib_class (global_found->the_bfd) - & DYN_AS_NEEDED) == 0) - return; - - if (s->filename == NULL || s->the_bfd == NULL) - return; - - /* Don't look for a second non-loaded as-needed lib. */ - if (global_found != NULL - && (bfd_elf_get_dyn_lib_class (s->the_bfd) & DYN_AS_NEEDED) != 0) - return; - - if (filename_cmp (s->filename, global_needed->name) == 0) - { - global_found = s; - return; - } - - if (s->flags.search_dirs) - { - const char *f = strrchr (s->filename, '/'); - if (f != NULL - && filename_cmp (f + 1, global_needed->name) == 0) - { - global_found = s; - return; - } - } - - soname = bfd_elf_get_dt_soname (s->the_bfd); - if (soname != NULL - && filename_cmp (soname, global_needed->name) == 0) - { - global_found = s; - return; - } -} - -EOF + IS_LIBPATH=FALSE + if test "x${USE_LIBPATH}" = xyes; then + IS_LIBPATH=TRUE + fi + IS_NATIVE=FALSE + if test "x${NATIVE}" = xyes; then + IS_NATIVE=TRUE + fi -if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then fragment <<EOF -static bfd_size_type -id_note_section_size (bfd *abfd ATTRIBUTE_UNUSED) -{ - const char *style = emit_note_gnu_build_id; - bfd_size_type size; - bfd_size_type build_id_size; - - size = offsetof (Elf_External_Note, name[sizeof "GNU"]); - size = (size + 3) & -(bfd_size_type) 4; - - build_id_size = compute_build_id_size (style); - if (build_id_size) - size += build_id_size; - else - size = 0; - - return size; -} - -static bfd_boolean -write_build_id (bfd *abfd) -{ - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - struct elf_obj_tdata *t = elf_tdata (abfd); - const char *style; - asection *asec; - Elf_Internal_Shdr *i_shdr; - unsigned char *contents, *id_bits; - bfd_size_type size; - file_ptr position; - Elf_External_Note *e_note; - - style = t->o->build_id.style; - asec = t->o->build_id.sec; - if (bfd_is_abs_section (asec->output_section)) - { - einfo (_("%P: warning: .note.gnu.build-id section discarded," - " --build-id ignored\n")); - return TRUE; - } - i_shdr = &elf_section_data (asec->output_section)->this_hdr; - - if (i_shdr->contents == NULL) - { - if (asec->contents == NULL) - asec->contents = (unsigned char *) xmalloc (asec->size); - contents = asec->contents; - } - else - contents = i_shdr->contents + asec->output_offset; - - e_note = (Elf_External_Note *) contents; - size = offsetof (Elf_External_Note, name[sizeof "GNU"]); - size = (size + 3) & -(bfd_size_type) 4; - id_bits = contents + size; - size = asec->size - size; - - bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz); - bfd_h_put_32 (abfd, size, &e_note->descsz); - bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type); - memcpy (e_note->name, "GNU", sizeof "GNU"); - - generate_build_id (abfd, style, bed->s->checksum_contents, id_bits, size); - - position = i_shdr->sh_offset + asec->output_offset; - size = asec->size; - return (bfd_seek (abfd, position, SEEK_SET) == 0 - && bfd_bwrite (contents, size, abfd) == size); -} - -/* Make .note.gnu.build-id section, and set up elf_tdata->build_id. */ - -static bfd_boolean -setup_build_id (bfd *ibfd) -{ - asection *s; - bfd_size_type size; - flagword flags; - - size = id_note_section_size (ibfd); - if (size == 0) - { - einfo (_("%P: warning: unrecognized --build-id style ignored\n")); - return FALSE; - } - - flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY - | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA); - s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags); - if (s != NULL && bfd_set_section_alignment (ibfd, s, 2)) - { - struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); - t->o->build_id.after_write_object_contents = &write_build_id; - t->o->build_id.style = emit_note_gnu_build_id; - t->o->build_id.sec = s; - elf_section_type (s) = SHT_NOTE; - s->size = size; - return TRUE; - } - - einfo (_("%P: warning: cannot create .note.gnu.build-id section," - " --build-id ignored\n")); - return FALSE; -} - /* This is called after all the input files have been opened. */ static void gld${EMULATION_NAME}_after_open (void) { - struct bfd_link_needed_list *needed, *l; - struct elf_link_hash_table *htab; - asection *s; - bfd *abfd; - - after_open_default (); - - htab = elf_hash_table (&link_info); - if (!is_elf_hash_table (htab)) - return; - - if (command_line.out_implib_filename) - { - unlink_if_ordinary (command_line.out_implib_filename); - link_info.out_implib_bfd - = bfd_openw (command_line.out_implib_filename, - bfd_get_target (link_info.output_bfd)); - - if (link_info.out_implib_bfd == NULL) - { - einfo (_("%F%P: %s: can't open for writing: %E\n"), - command_line.out_implib_filename); - } - } - - if (emit_note_gnu_build_id != NULL) - { - /* Find an ELF input. */ - for (abfd = link_info.input_bfds; - abfd != (bfd *) NULL; abfd = abfd->link.next) - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour - && bfd_count_sections (abfd) != 0 - && !((lang_input_statement_type *) abfd->usrdata)->flags.just_syms) - break; - - /* PR 10555: If there are no ELF input files do not try to - create a .note.gnu-build-id section. */ - if (abfd == NULL - || !setup_build_id (abfd)) - { - free ((char *) emit_note_gnu_build_id); - emit_note_gnu_build_id = NULL; - } - } - - get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info); - - if (bfd_link_relocatable (&link_info)) - { - if (link_info.execstack == ! link_info.noexecstack) - /* PR ld/16744: If "-z [no]execstack" has been specified on the - command line and we are perfoming a relocatable link then no - PT_GNU_STACK segment will be created and so the - linkinfo.[no]execstack values set in _handle_option() will have no - effect. Instead we create a .note.GNU-stack section in much the - same way as the assembler does with its --[no]execstack option. */ - (void) bfd_make_section_with_flags (link_info.input_bfds, - ".note.GNU-stack", - SEC_READONLY | (link_info.execstack ? SEC_CODE : 0)); - - return; - } - - if (!link_info.traditional_format) - { - bfd *elfbfd = NULL; - bfd_boolean warn_eh_frame = FALSE; - int seen_type = 0; - - for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next) - { - int type = 0; - - if (((lang_input_statement_type *) abfd->usrdata)->flags.just_syms) - continue; - - for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next) - { - const char *name = bfd_get_section_name (abfd, s); - - if (bfd_is_abs_section (s->output_section)) - continue; - if (CONST_STRNEQ (name, ".eh_frame_entry")) - type = COMPACT_EH_HDR; - else if (strcmp (name, ".eh_frame") == 0 && s->size > 8) - type = DWARF2_EH_HDR; - } - - if (type != 0) - { - if (seen_type == 0) - { - seen_type = type; - } - else if (seen_type != type) - { - einfo (_("%F%P: compact frame descriptions incompatible with" - " DWARF2 .eh_frame from %pB\n"), - type == DWARF2_EH_HDR ? abfd : elfbfd); - break; - } - - if (!elfbfd - && (type == COMPACT_EH_HDR || link_info.eh_frame_hdr_type != 0)) - { - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - elfbfd = abfd; - - warn_eh_frame = TRUE; - } - } - - if (seen_type == COMPACT_EH_HDR) - link_info.eh_frame_hdr_type = COMPACT_EH_HDR; - } - if (elfbfd) - { - const struct elf_backend_data *bed; - - bed = get_elf_backend_data (elfbfd); - s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr", - bed->dynamic_sec_flags - | SEC_READONLY); - if (s != NULL - && bfd_set_section_alignment (elfbfd, s, 2)) - { - htab->eh_info.hdr_sec = s; - warn_eh_frame = FALSE; - } - } - if (warn_eh_frame) - einfo (_("%P: warning: cannot create .eh_frame_hdr section," - " --eh-frame-hdr ignored\n")); - } - - /* Get the list of files which appear in DT_NEEDED entries in - dynamic objects included in the link (often there will be none). - For each such file, we want to track down the corresponding - library, and include the symbol table in the link. This is what - the runtime dynamic linker will do. Tracking the files down here - permits one dynamic object to include another without requiring - special action by the person doing the link. Note that the - needed list can actually grow while we are stepping through this - loop. */ - needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info); - for (l = needed; l != NULL; l = l->next) - { - struct bfd_link_needed_list *ll; - struct dt_needed n, nn; - int force; - - /* If the lib that needs this one was --as-needed and wasn't - found to be needed, then this lib isn't needed either. */ - if (l->by != NULL - && (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0) - continue; - - /* Skip the lib if --no-copy-dt-needed-entries and - --allow-shlib-undefined is in effect. */ - if (l->by != NULL - && link_info.unresolved_syms_in_shared_libs == RM_IGNORE - && (bfd_elf_get_dyn_lib_class (l->by) & DYN_NO_ADD_NEEDED) != 0) - continue; - - /* If we've already seen this file, skip it. */ - for (ll = needed; ll != l; ll = ll->next) - if ((ll->by == NULL - || (bfd_elf_get_dyn_lib_class (ll->by) & DYN_AS_NEEDED) == 0) - && strcmp (ll->name, l->name) == 0) - break; - if (ll != l) - continue; - - /* See if this file was included in the link explicitly. */ - global_needed = l; - global_found = NULL; - lang_for_each_input_file (gld${EMULATION_NAME}_check_needed); - if (global_found != NULL - && (bfd_elf_get_dyn_lib_class (global_found->the_bfd) - & DYN_AS_NEEDED) == 0) - continue; - - n.by = l->by; - n.name = l->name; - nn.by = l->by; - if (verbose) - info_msg (_("%s needed by %pB\n"), l->name, l->by); - - /* As-needed libs specified on the command line (or linker script) - take priority over libs found in search dirs. */ - if (global_found != NULL) - { - nn.name = global_found->filename; - if (gld${EMULATION_NAME}_try_needed (&nn, TRUE)) - continue; - } - - /* We need to find this file and include the symbol table. We - want to search for the file in the same way that the dynamic - linker will search. That means that we want to use - rpath_link, rpath, then the environment variable - LD_LIBRARY_PATH (native only), then the DT_RPATH/DT_RUNPATH - entries (native only), then the linker script LIB_SEARCH_DIRS. - We do not search using the -L arguments. - - We search twice. The first time, we skip objects which may - introduce version mismatches. The second time, we force - their use. See gld${EMULATION_NAME}_vercheck comment. */ - for (force = 0; force < 2; force++) - { - size_t len; - search_dirs_type *search; -EOF -if [ "x${NATIVE}" = xyes ] || [ "x${USE_LIBPATH}" = xyes ] ; then -fragment <<EOF - const char *path; -EOF -fi -if [ "x${USE_LIBPATH}" = xyes ] ; then -fragment <<EOF - struct bfd_link_needed_list *rp; - int found; -EOF -fi -fragment <<EOF - - if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, - &n, force)) - break; -EOF -if [ "x${USE_LIBPATH}" = xyes ] ; then -fragment <<EOF - path = command_line.rpath; - if (path) - { - path = gld${EMULATION_NAME}_add_sysroot (path); - found = gld${EMULATION_NAME}_search_needed (path, &n, force); - free ((char *) path); - if (found) - break; - } -EOF -fi -if [ "x${NATIVE}" = xyes ] ; then -fragment <<EOF - if (command_line.rpath_link == NULL - && command_line.rpath == NULL) - { - path = (const char *) getenv ("LD_RUN_PATH"); - if (path - && gld${EMULATION_NAME}_search_needed (path, &n, force)) - break; - } - path = (const char *) getenv ("LD_LIBRARY_PATH"); - if (path - && gld${EMULATION_NAME}_search_needed (path, &n, force)) - break; -EOF -fi -if [ "x${USE_LIBPATH}" = xyes ] ; then -fragment <<EOF - found = 0; - rp = bfd_elf_get_runpath_list (link_info.output_bfd, &link_info); - for (; !found && rp != NULL; rp = rp->next) - { - path = gld${EMULATION_NAME}_add_sysroot (rp->name); - found = (rp->by == l->by - && gld${EMULATION_NAME}_search_needed (path, &n, - force)); - free ((char *) path); - } - if (found) - break; - -EOF -fi -if [ "x${USE_LIBPATH}" = xyes ] ; then - case ${target} in - *-*-freebsd* | *-*-dragonfly*) - fragment <<EOF - if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force)) - break; -EOF - # FreeBSD - ;; - - *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*) - fragment <<EOF - if (gld${EMULATION_NAME}_check_ld_so_conf (l, force)) - break; - -EOF - # Linux - ;; - esac -fi -fragment <<EOF - len = strlen (l->name); - for (search = search_head; search != NULL; search = search->next) - { - char *filename; - - if (search->cmdline) - continue; - filename = (char *) xmalloc (strlen (search->name) + len + 2); - sprintf (filename, "%s/%s", search->name, l->name); - nn.name = filename; - if (gld${EMULATION_NAME}_try_needed (&nn, force)) - break; - free (filename); - } - if (search != NULL) - break; -EOF -fragment <<EOF - } - - if (force < 2) - continue; - - einfo (_("%P: warning: %s, needed by %pB, not found " - "(try using -rpath or -rpath-link)\n"), - l->name, l->by); - } - - if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR) - if (!bfd_elf_parse_eh_frame_entries (NULL, &link_info)) - einfo (_("%F%P: failed to parse EH frame entries\n")); + ldelf_after_open ($IS_LIBPATH, $IS_NATIVE, + $IS_LINUX_TARGET, $IS_FREEBSD_TARGET, $ELFSIZE); } EOF fi -fragment <<EOF - -/* Look through an expression for an assignment statement. */ - -static void -gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp) -{ - bfd_boolean provide = FALSE; - - switch (exp->type.node_class) - { - case etree_provide: - case etree_provided: - provide = TRUE; - /* Fallthru */ - case etree_assign: - /* We call record_link_assignment even if the symbol is defined. - This is because if it is defined by a dynamic object, we - actually want to use the value defined by the linker script, - not the value from the dynamic object (because we are setting - symbols like etext). If the symbol is defined by a regular - object, then, as it happens, calling record_link_assignment - will do no harm. */ - if (strcmp (exp->assign.dst, ".") != 0) - { - if (!bfd_elf_record_link_assignment (link_info.output_bfd, - &link_info, - exp->assign.dst, provide, - exp->assign.hidden)) - einfo (_("%F%P: failed to record assignment to %s: %E\n"), - exp->assign.dst); - } - gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); - break; - - case etree_binary: - gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); - gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); - break; - - case etree_trinary: - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); - gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); - break; - - case etree_unary: - gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); - break; - - default: - break; - } -} - - -/* This is called by the before_allocation routine via - lang_for_each_statement. It locates any assignment statements, and - tells the ELF backend about them, in case they are assignments to - symbols which are referred to by dynamic objects. */ - -static void -gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s) -{ - if (s->header.type == lang_assignment_statement_enum) - gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp); -} - -EOF - if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then - if test x"${ELF_INTERPRETER_NAME+set}" = xset; then - ELF_INTERPRETER_SET_DEFAULT=" - if (sinterp != NULL) - { - sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME}; - sinterp->size = strlen ((char *) sinterp->contents) + 1; - } - -" - else - ELF_INTERPRETER_SET_DEFAULT= + if test x"${ELF_INTERPRETER_NAME}" = x; then + ELF_INTERPRETER_NAME=NULL fi fragment <<EOF -/* used by before_allocation and handle_option. */ -static void -gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg) -{ - if (*to == NULL) - *to = xstrdup (op_arg); - else - { - size_t to_len = strlen (*to); - size_t op_arg_len = strlen (op_arg); - char *buf; - char *cp = *to; - - /* First see whether OPTARG is already in the path. */ - do - { - if (strncmp (op_arg, cp, op_arg_len) == 0 - && (cp[op_arg_len] == 0 - || cp[op_arg_len] == config.rpath_separator)) - /* We found it. */ - break; - - /* Not yet found. */ - cp = strchr (cp, config.rpath_separator); - if (cp != NULL) - ++cp; - } - while (cp != NULL); - - if (cp == NULL) - { - buf = xmalloc (to_len + op_arg_len + 2); - sprintf (buf, "%s%c%s", *to, - config.rpath_separator, op_arg); - free (*to); - *to = buf; - } - } -} - /* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */ static void gld${EMULATION_NAME}_before_allocation (void) { - const char *rpath; - asection *sinterp; - bfd *abfd; - struct bfd_link_hash_entry *ehdr_start = NULL; - unsigned char ehdr_start_save_type = 0; - char ehdr_start_save_u[sizeof ehdr_start->u - - sizeof ehdr_start->u.def.next] = ""; - - if (is_elf_hash_table (link_info.hash)) - { - _bfd_elf_tls_setup (link_info.output_bfd, &link_info); - - /* Make __ehdr_start hidden if it has been referenced, to - prevent the symbol from being dynamic. */ - if (!bfd_link_relocatable (&link_info)) - { - struct elf_link_hash_table *htab = elf_hash_table (&link_info); - struct elf_link_hash_entry *h - = elf_link_hash_lookup (htab, "__ehdr_start", FALSE, FALSE, TRUE); - - /* Only adjust the export class if the symbol was referenced - and not defined, otherwise leave it alone. */ - if (h != NULL - && (h->root.type == bfd_link_hash_new - || h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_common)) - { - const struct elf_backend_data *bed; - bed = get_elf_backend_data (link_info.output_bfd); - (*bed->elf_backend_hide_symbol) (&link_info, h, TRUE); - if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL) - h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; - /* Don't leave the symbol undefined. Undefined hidden - symbols typically won't have dynamic relocations, but - we most likely will need dynamic relocations for - __ehdr_start if we are building a PIE or shared - library. */ - ehdr_start = &h->root; - ehdr_start_save_type = ehdr_start->type; - memcpy (ehdr_start_save_u, - (char *) &ehdr_start->u + sizeof ehdr_start->u.def.next, - sizeof ehdr_start_save_u); - ehdr_start->type = bfd_link_hash_defined; - ehdr_start->u.def.section = bfd_abs_section_ptr; - ehdr_start->u.def.value = 0; - } - } - - /* If we are going to make any variable assignments, we need to - let the ELF backend know about them in case the variables are - referred to by dynamic objects. */ - lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment); - } - - /* Let the ELF backend work out the sizes of any sections required - by dynamic linking. */ - rpath = command_line.rpath; - if (rpath == NULL) - rpath = (const char *) getenv ("LD_RUN_PATH"); - - for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next) - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - { - const char *audit_libs = elf_dt_audit (abfd); - - /* If the input bfd contains an audit entry, we need to add it as - a dep audit entry. */ - if (audit_libs && *audit_libs != '\0') - { - char *cp = xstrdup (audit_libs); - do - { - int more = 0; - char *cp2 = strchr (cp, config.rpath_separator); - - if (cp2) - { - *cp2 = '\0'; - more = 1; - } - - if (cp != NULL && *cp != '\0') - gld${EMULATION_NAME}_append_to_separated_string (&depaudit, cp); - - cp = more ? ++cp2 : NULL; - } - while (cp != NULL); - } - } - - if (! (bfd_elf_size_dynamic_sections - (link_info.output_bfd, command_line.soname, rpath, - command_line.filter_shlib, audit, depaudit, - (const char * const *) command_line.auxiliary_filters, - &link_info, &sinterp))) - einfo (_("%F%P: failed to set dynamic section sizes: %E\n")); - -${ELF_INTERPRETER_SET_DEFAULT} - /* Let the user override the dynamic linker we are using. */ - if (command_line.interpreter != NULL - && sinterp != NULL) - { - sinterp->contents = (bfd_byte *) command_line.interpreter; - sinterp->size = strlen (command_line.interpreter) + 1; - } - - /* Look for any sections named .gnu.warning. As a GNU extensions, - we treat such sections as containing warning messages. We print - out the warning message, and then zero out the section size so - that it does not get copied into the output file. */ - - { - LANG_FOR_EACH_INPUT_STATEMENT (is) - { - asection *s; - bfd_size_type sz; - char *msg; - - if (is->flags.just_syms) - continue; - - s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning"); - if (s == NULL) - continue; - - sz = s->size; - msg = (char *) xmalloc ((size_t) (sz + 1)); - if (! bfd_get_section_contents (is->the_bfd, s, msg, - (file_ptr) 0, sz)) - einfo (_("%F%P: %pB: can't read contents of section .gnu.warning: %E\n"), - is->the_bfd); - msg[sz] = '\0'; - (*link_info.callbacks->warning) (&link_info, msg, - (const char *) NULL, is->the_bfd, - (asection *) NULL, (bfd_vma) 0); - free (msg); - - /* Clobber the section size, so that we don't waste space - copying the warning into the output file. If we've already - sized the output section, adjust its size. The adjustment - is on rawsize because targets that size sections early will - have called lang_reset_memory_regions after sizing. */ - if (s->output_section != NULL - && s->output_section->rawsize >= s->size) - s->output_section->rawsize -= s->size; - - s->size = 0; - - /* Also set SEC_EXCLUDE, so that local symbols defined in the - warning section don't get copied to the output. */ - s->flags |= SEC_EXCLUDE | SEC_KEEP; - } - } - - before_allocation_default (); - - if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info)) - einfo (_("%F%P: failed to set dynamic section sizes: %E\n")); - - if (ehdr_start != NULL) - { - /* If we twiddled __ehdr_start to defined earlier, put it back - as it was. */ - ehdr_start->type = ehdr_start_save_type; - memcpy ((char *) &ehdr_start->u + sizeof ehdr_start->u.def.next, - ehdr_start_save_u, - sizeof ehdr_start_save_u); - } + ldelf_before_allocation (audit, depaudit, ${ELF_INTERPRETER_NAME}); } EOF fi -if test x"$LDEMUL_OPEN_DYNAMIC_ARCHIVE" != xgld"$EMULATION_NAME"_open_dynamic_archive; then -fragment <<EOF - -/* Try to open a dynamic archive. This is where we know that ELF - dynamic libraries have an extension of .so (or .sl on oddball systems - like hpux). */ - -static bfd_boolean -gld${EMULATION_NAME}_open_dynamic_archive - (const char *arch, search_dirs_type *search, lang_input_statement_type *entry) -{ - const char *filename; - char *string; - size_t len; - bfd_boolean opened = FALSE; - - if (! entry->flags.maybe_archive) - return FALSE; - - filename = entry->filename; - len = strlen (search->name) + strlen (filename); - if (entry->flags.full_name_provided) - { - len += sizeof "/"; - string = (char *) xmalloc (len); - sprintf (string, "%s/%s", search->name, filename); - } - else - { - size_t xlen = 0; - - len += strlen (arch) + sizeof "/lib.so"; -#ifdef EXTRA_SHLIB_EXTENSION - xlen = (strlen (EXTRA_SHLIB_EXTENSION) > 3 - ? strlen (EXTRA_SHLIB_EXTENSION) - 3 - : 0); -#endif - string = (char *) xmalloc (len + xlen); - sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); -#ifdef EXTRA_SHLIB_EXTENSION - /* Try the .so extension first. If that fails build a new filename - using EXTRA_SHLIB_EXTENSION. */ - opened = ldfile_try_open_bfd (string, entry); - if (!opened) - strcpy (string + len - 4, EXTRA_SHLIB_EXTENSION); -#endif - } - - if (!opened && !ldfile_try_open_bfd (string, entry)) - { - free (string); - return FALSE; - } - - entry->filename = string; - - /* We have found a dynamic object to include in the link. The ELF - backend linker will create a DT_NEEDED entry in the .dynamic - section naming this file. If this file includes a DT_SONAME - entry, it will be used. Otherwise, the ELF linker will just use - the name of the file. For an archive found by searching, like - this one, the DT_NEEDED entry should consist of just the name of - the file, without the path information used to find it. Note - that we only need to do this if we have a dynamic object; an - archive will never be referenced by a DT_NEEDED entry. - - FIXME: This approach--using bfd_elf_set_dt_needed_name--is not - very pretty. I haven't been able to think of anything that is - pretty, though. */ - if (bfd_check_format (entry->the_bfd, bfd_object) - && (entry->the_bfd->flags & DYNAMIC) != 0) - { - ASSERT (entry->flags.maybe_archive && entry->flags.search_dirs); - - /* Rather than duplicating the logic above. Just use the - filename we recorded earlier. */ - - if (!entry->flags.full_name_provided) - filename = lbasename (entry->filename); - bfd_elf_set_dt_needed_name (entry->the_bfd, filename); - } - - return TRUE; -} - -EOF -fi - -if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then -fragment <<EOF - -/* A variant of lang_output_section_find used by place_orphan. */ - -static lang_output_section_statement_type * -output_rel_find (int isdyn, int rela) -{ - lang_output_section_statement_type *lookup; - lang_output_section_statement_type *last = NULL; - lang_output_section_statement_type *last_alloc = NULL; - lang_output_section_statement_type *last_ro_alloc = NULL; - lang_output_section_statement_type *last_rel = NULL; - lang_output_section_statement_type *last_rel_alloc = NULL; - - for (lookup = &lang_os_list.head->output_section_statement; - lookup != NULL; - lookup = lookup->next) - { - if (lookup->constraint >= 0 - && CONST_STRNEQ (lookup->name, ".rel")) - { - int lookrela = lookup->name[4] == 'a'; - - /* .rel.dyn must come before all other reloc sections, to suit - GNU ld.so. */ - if (isdyn) - break; - - /* Don't place after .rel.plt as doing so results in wrong - dynamic tags. */ - if (strcmp (".plt", lookup->name + 4 + lookrela) == 0) - break; - - if (rela == lookrela || last_rel == NULL) - last_rel = lookup; - if ((rela == lookrela || last_rel_alloc == NULL) - && lookup->bfd_section != NULL - && (lookup->bfd_section->flags & SEC_ALLOC) != 0) - last_rel_alloc = lookup; - } - - last = lookup; - if (lookup->bfd_section != NULL - && (lookup->bfd_section->flags & SEC_ALLOC) != 0) - { - last_alloc = lookup; - if ((lookup->bfd_section->flags & SEC_READONLY) != 0) - last_ro_alloc = lookup; - } - } - - if (last_rel_alloc) - return last_rel_alloc; - - if (last_rel) - return last_rel; - - if (last_ro_alloc) - return last_ro_alloc; - - if (last_alloc) - return last_alloc; - - return last; -} - -/* Return whether IN is suitable to be part of OUT. */ - -static bfd_boolean -elf_orphan_compatible (asection *in, asection *out) -{ - /* Non-zero sh_info implies a section with SHF_INFO_LINK with - unknown semantics for the generic linker, or a SHT_REL/SHT_RELA - section where sh_info specifies a symbol table. (We won't see - SHT_GROUP, SHT_SYMTAB or SHT_DYNSYM sections here.) We clearly - can't merge SHT_REL/SHT_RELA using differing symbol tables, and - shouldn't merge sections with differing unknown semantics. */ - if (elf_section_data (out)->this_hdr.sh_info - != elf_section_data (in)->this_hdr.sh_info) - return FALSE; - /* We can't merge with member of output section group nor merge two - sections with differing SHF_EXCLUDE when doing a relocatable link. - */ - if (bfd_link_relocatable (&link_info) - && (elf_next_in_group (out) != NULL - || ((elf_section_flags (out) ^ elf_section_flags (in)) - & SHF_EXCLUDE) != 0)) - return FALSE; - return _bfd_elf_match_sections_by_type (link_info.output_bfd, out, - in->owner, in); -} - -/* Place an orphan section. We use this to put random SHF_ALLOC - sections in the right segment. */ - -static lang_output_section_statement_type * -gld${EMULATION_NAME}_place_orphan (asection *s, - const char *secname, - int constraint) -{ - static struct orphan_save hold[] = - { - { ".text", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE, - 0, 0, 0, 0 }, - { ".rodata", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, - 0, 0, 0, 0 }, - { ".tdata", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_THREAD_LOCAL, - 0, 0, 0, 0 }, - { ".data", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA, - 0, 0, 0, 0 }, - { ".bss", - SEC_ALLOC, - 0, 0, 0, 0 }, - { 0, - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, - 0, 0, 0, 0 }, - { ".interp", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA, - 0, 0, 0, 0 }, - { ".sdata", - SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA, - 0, 0, 0, 0 }, - { ".comment", - SEC_HAS_CONTENTS, - 0, 0, 0, 0 }, - }; - enum orphan_save_index - { - orphan_text = 0, - orphan_rodata, - orphan_tdata, - orphan_data, - orphan_bss, - orphan_rel, - orphan_interp, - orphan_sdata, - orphan_nonalloc - }; - static int orphan_init_done = 0; - struct orphan_save *place; - lang_output_section_statement_type *after; - lang_output_section_statement_type *os; - lang_output_section_statement_type *match_by_name = NULL; - int isdyn = 0; - int elfinput = s->owner->xvec->flavour == bfd_target_elf_flavour; - int elfoutput = link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour; - unsigned int sh_type = elfinput ? elf_section_type (s) : SHT_NULL; - flagword flags; - asection *nexts; - - if (!bfd_link_relocatable (&link_info) - && link_info.combreloc - && (s->flags & SEC_ALLOC)) - { - if (elfinput) - switch (sh_type) - { - case SHT_RELA: - secname = ".rela.dyn"; - isdyn = 1; - break; - case SHT_REL: - secname = ".rel.dyn"; - isdyn = 1; - break; - default: - break; - } - else if (CONST_STRNEQ (secname, ".rel")) - { - secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn"; - isdyn = 1; - } - } - - if (!bfd_link_relocatable (&link_info) - && elfinput - && elfoutput - && (s->flags & SEC_ALLOC) != 0 - && (elf_tdata (s->owner)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0 - && (elf_section_flags (s) & SHF_GNU_MBIND) != 0) - { - /* Find the output mbind section with the same type, attributes - and sh_info field. */ - for (os = &lang_os_list.head->output_section_statement; - os != NULL; - os = os->next) - if (os->bfd_section != NULL - && !bfd_is_abs_section (os->bfd_section) - && (elf_section_flags (os->bfd_section) & SHF_GNU_MBIND) != 0 - && ((s->flags & (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_READONLY - | SEC_CODE)) - == (os->bfd_section->flags & (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_READONLY - | SEC_CODE))) - && (elf_section_data (os->bfd_section)->this_hdr.sh_info - == elf_section_data (s)->this_hdr.sh_info)) - { - lang_add_section (&os->children, s, NULL, os); - return os; - } - - /* Create the output mbind section with the ".mbind." prefix - in section name. */ - if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) - secname = ".mbind.bss"; - else if ((s->flags & SEC_READONLY) == 0) - secname = ".mbind.data"; - else if ((s->flags & SEC_CODE) == 0) - secname = ".mbind.rodata"; - else - secname = ".mbind.text"; - elf_tdata (link_info.output_bfd)->has_gnu_osabi |= elf_gnu_osabi_mbind; - } - - /* Look through the script to see where to place this section. The - script includes entries added by previous lang_insert_orphan - calls, so this loop puts multiple compatible orphans of the same - name into a single output section. */ - if (constraint == 0) - for (os = lang_output_section_find (secname); - os != NULL; - os = next_matching_output_section_statement (os, 0)) - { - /* If we don't match an existing output section, tell - lang_insert_orphan to create a new output section. */ - constraint = SPECIAL; - - /* Check to see if we already have an output section statement - with this name, and its bfd section has compatible flags. - If the section already exists but does not have any flags - set, then it has been created by the linker, possibly as a - result of a --section-start command line switch. */ - if (os->bfd_section != NULL - && (os->bfd_section->flags == 0 - || (((s->flags ^ os->bfd_section->flags) - & (SEC_LOAD | SEC_ALLOC)) == 0 - && (!elfinput - || !elfoutput - || elf_orphan_compatible (s, os->bfd_section))))) - { - lang_add_section (&os->children, s, NULL, os); - return os; - } - - /* Save unused output sections in case we can match them - against orphans later. */ - if (os->bfd_section == NULL) - match_by_name = os; - } - - /* If we didn't match an active output section, see if we matched an - unused one and use that. */ - if (match_by_name) - { - lang_add_section (&match_by_name->children, s, NULL, match_by_name); - return match_by_name; - } - - if (!orphan_init_done) - { - struct orphan_save *ho; - - for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho) - if (ho->name != NULL) - { - ho->os = lang_output_section_find (ho->name); - if (ho->os != NULL && ho->os->flags == 0) - ho->os->flags = ho->flags; - } - orphan_init_done = 1; - } - - /* If this is a final link, then always put .gnu.warning.SYMBOL - sections into the .text section to get them out of the way. */ - if (bfd_link_executable (&link_info) - && CONST_STRNEQ (s->name, ".gnu.warning.") - && hold[orphan_text].os != NULL) - { - os = hold[orphan_text].os; - lang_add_section (&os->children, s, NULL, os); - return os; - } - - flags = s->flags; - if (!bfd_link_relocatable (&link_info)) - { - nexts = s; - while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)) - != NULL) - if (nexts->output_section == NULL - && (nexts->flags & SEC_EXCLUDE) == 0 - && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0 - && (nexts->owner->flags & DYNAMIC) == 0 - && nexts->owner->usrdata != NULL - && !(((lang_input_statement_type *) nexts->owner->usrdata) - ->flags.just_syms) - && _bfd_elf_match_sections_by_type (nexts->owner, nexts, - s->owner, s)) - flags = (((flags ^ SEC_READONLY) - | (nexts->flags ^ SEC_READONLY)) - ^ SEC_READONLY); - } - - /* Decide which segment the section should go in based on the - section name and section flags. We put loadable .note sections - right after the .interp section, so that the PT_NOTE segment is - stored right after the program headers where the OS can read it - in the first page. */ - - place = NULL; - if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) - place = &hold[orphan_nonalloc]; - else if ((flags & SEC_ALLOC) == 0) - ; - else if ((flags & SEC_LOAD) != 0 - && (elfinput - ? sh_type == SHT_NOTE - : CONST_STRNEQ (secname, ".note"))) - place = &hold[orphan_interp]; - else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) - place = &hold[orphan_bss]; - else if ((flags & SEC_SMALL_DATA) != 0) - place = &hold[orphan_sdata]; - else if ((flags & SEC_THREAD_LOCAL) != 0) - place = &hold[orphan_tdata]; - else if ((flags & SEC_READONLY) == 0) - place = &hold[orphan_data]; - else if ((flags & SEC_LOAD) != 0 - && (elfinput - ? sh_type == SHT_RELA || sh_type == SHT_REL - : CONST_STRNEQ (secname, ".rel"))) - place = &hold[orphan_rel]; - else if ((flags & SEC_CODE) == 0) - place = &hold[orphan_rodata]; - else - place = &hold[orphan_text]; - - after = NULL; - if (place != NULL) - { - if (place->os == NULL) - { - if (place->name != NULL) - place->os = lang_output_section_find (place->name); - else - { - int rela = elfinput ? sh_type == SHT_RELA : secname[4] == 'a'; - place->os = output_rel_find (isdyn, rela); - } - } - after = place->os; - if (after == NULL) - after - = lang_output_section_find_by_flags (s, flags, &place->os, - _bfd_elf_match_sections_by_type); - if (after == NULL) - /* *ABS* is always the first output section statement. */ - after = &lang_os_list.head->output_section_statement; - } - - return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL); -} -EOF -fi - if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then fragment <<EOF @@ -2334,7 +161,7 @@ gld${EMULATION_NAME}_after_allocation (void) if (need_layout < 0) einfo (_("%X%P: .eh_frame/.stab edit: %E\n")); else - gld${EMULATION_NAME}_map_segments (need_layout); + ldelf_map_segments (need_layout); } EOF fi @@ -2794,15 +621,15 @@ gld${EMULATION_NAME}_handle_option (int optc) return FALSE; case OPTION_BUILD_ID: - if (emit_note_gnu_build_id != NULL) + if (ldelf_emit_note_gnu_build_id != NULL) { - free ((char *) emit_note_gnu_build_id); - emit_note_gnu_build_id = NULL; + free ((char *) ldelf_emit_note_gnu_build_id); + ldelf_emit_note_gnu_build_id = NULL; } if (optarg == NULL) optarg = DEFAULT_BUILD_ID_STYLE; if (strcmp (optarg, "none")) - emit_note_gnu_build_id = xstrdup (optarg); + ldelf_emit_note_gnu_build_id = xstrdup (optarg); break; case OPTION_COMPRESS_DEBUG: @@ -2823,11 +650,11 @@ EOF if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then fragment <<EOF case OPTION_AUDIT: - gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg); + ldelf_append_to_separated_string (&audit, optarg); break; case 'P': - gld${EMULATION_NAME}_append_to_separated_string (&depaudit, optarg); + ldelf_append_to_separated_string (&depaudit, optarg); break; case OPTION_DISABLE_NEW_DTAGS: @@ -3051,7 +878,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse}, ${LDEMUL_SYSLIB-syslib_default}, ${LDEMUL_HLL-hll_default}, - ${LDEMUL_AFTER_PARSE-gld${EMULATION_NAME}_after_parse}, + ${LDEMUL_AFTER_PARSE-ldelf_after_parse}, ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open}, ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default}, ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation}, @@ -3063,15 +890,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = "${OUTPUT_FORMAT}", ${LDEMUL_FINISH-finish_default}, ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, - ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, - ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, + ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-ldelf_open_dynamic_archive}, + ${LDEMUL_PLACE_ORPHAN-ldelf_place_orphan}, ${LDEMUL_SET_SYMBOLS-NULL}, ${LDEMUL_PARSE_ARGS-NULL}, gld${EMULATION_NAME}_add_options, gld${EMULATION_NAME}_handle_option, ${LDEMUL_UNRECOGNIZED_FILE-NULL}, ${LDEMUL_LIST_OPTIONS-${gld_list_options}}, - ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols}, + ${LDEMUL_RECOGNIZED_FILE-ldelf_load_symbols}, ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, ${LDEMUL_NEW_VERS_PATTERN-NULL}, ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL} diff --git a/ld/emultempl/genelf.em b/ld/emultempl/genelf.em index 664a5b1..9c5898d 100644 --- a/ld/emultempl/genelf.em +++ b/ld/emultempl/genelf.em @@ -23,6 +23,7 @@ # fragment <<EOF #include "elf-bfd.h" +#include "ldelfgen.h" EOF source_em ${srcdir}/emultempl/elf-generic.em @@ -63,7 +64,7 @@ gld${EMULATION_NAME}_before_allocation (void) static void gld${EMULATION_NAME}_after_allocation (void) { - gld${EMULATION_NAME}_map_segments (FALSE); + ldelf_map_segments (FALSE); } EOF # Put these extra routines in ld_${EMULATION_NAME}_emulation diff --git a/ld/emultempl/hppaelf.em b/ld/emultempl/hppaelf.em index 3ae2bfd..547ab9b 100644 --- a/ld/emultempl/hppaelf.em +++ b/ld/emultempl/hppaelf.em @@ -59,7 +59,7 @@ hppaelf_after_parse (void) NULL); */ - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } /* This is called before the input files are opened. We create a new @@ -215,7 +215,7 @@ hppaelf_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -289,7 +289,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); if (!bfd_link_relocatable (&link_info)) { @@ -309,27 +309,6 @@ gld${EMULATION_NAME}_after_allocation (void) } } - -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void hppa_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -hppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&hppa_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file hppa_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/ia64elf.em b/ld/emultempl/ia64elf.em index f9a0604..e67a04c 100644 --- a/ld/emultempl/ia64elf.em +++ b/ld/emultempl/ia64elf.em @@ -36,7 +36,7 @@ ia64elf_after_parse (void) link_info.relax_pass = 2; bfd_elf${ELFSIZE}_ia64_after_parse (itanium); - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } EOF diff --git a/ld/emultempl/m68hc1xelf.em b/ld/emultempl/m68hc1xelf.em index 0dda5dd..3fa325a 100644 --- a/ld/emultempl/m68hc1xelf.em +++ b/ld/emultempl/m68hc1xelf.em @@ -319,27 +319,6 @@ m68hc11elf_after_allocation (void) gld${EMULATION_NAME}_after_allocation (); } - -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void m68hc11_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -m68hc11_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&m68hc11_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file m68hc11_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/metagelf.em b/ld/emultempl/metagelf.em index e989c58..966d19c 100644 --- a/ld/emultempl/metagelf.em +++ b/ld/emultempl/metagelf.em @@ -191,7 +191,7 @@ metagelf_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -264,7 +264,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); if (!bfd_link_relocatable (&link_info)) { @@ -277,27 +277,6 @@ gld${EMULATION_NAME}_after_allocation (void) } } - -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void metag_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -metag_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&metag_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file metag_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em index fe46e0d..108d33f 100644 --- a/ld/emultempl/mipself.em +++ b/ld/emultempl/mipself.em @@ -227,26 +227,6 @@ mips_before_allocation (void) gld${EMULATION_NAME}_before_allocation (); } -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void mips_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&mips_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file mips_lang_for_each_input_file - EOF # Define some shell vars to insert bits of code into the standard elf diff --git a/ld/emultempl/mmo.em b/ld/emultempl/mmo.em index 3e24e36..b4b4f1e 100644 --- a/ld/emultempl/mmo.em +++ b/ld/emultempl/mmo.em @@ -29,11 +29,10 @@ fragment <<EOF #define gldmmo_before_allocation before_allocation_default /* We include this header *not* because we expect to handle ELF here - but because we re-use the map_segments function in elf-generic.em, - a file which is rightly somewhat ELF-centric. But this is only to + but because we use the map_segments function. But this is only to get a weird testcase right; ld-mmix/bpo-22, forcing ELF to be output from the mmo emulation: -m mmo --oformat elf64-mmix! */ -#include "elf-bfd.h" +#include "ldelfgen.h" static void gld${EMULATION_NAME}_after_allocation (void); EOF @@ -205,7 +204,7 @@ static void gld${EMULATION_NAME}_after_allocation (void) { bfd_map_over_sections (link_info.output_bfd, mmo_wipe_sec_reloc_flag, NULL); - gld${EMULATION_NAME}_map_segments (FALSE); + ldelf_map_segments (FALSE); } /* To get on-demand global register allocation right, we need to parse the diff --git a/ld/emultempl/nds32elf.em b/ld/emultempl/nds32elf.em index cf30cbc..00e9975 100644 --- a/ld/emultempl/nds32elf.em +++ b/ld/emultempl/nds32elf.em @@ -68,7 +68,7 @@ nds32_elf_after_parse (void) if (!RELAXATION_ENABLED) relax_fp_as_gp = 0; - gld${EMULATION_NAME}_after_parse (); + ldelf_after_parse (); } static void @@ -123,7 +123,7 @@ nds32_elf_after_allocation (void) { /* Call default after allocation callback. 1. This is where relaxation is done. - 2. It calls gld${EMULATION_NAME}_map_segments to build ELF segment table. + 2. It calls ldelf_map_segments to build ELF segment table. 3. Any relaxation requires relax being done must be called after it. */ gld${EMULATION_NAME}_after_allocation (); } diff --git a/ld/emultempl/nios2elf.em b/ld/emultempl/nios2elf.em index 0f19525..676c1fb 100644 --- a/ld/emultempl/nios2elf.em +++ b/ld/emultempl/nios2elf.em @@ -208,7 +208,7 @@ nios2elf_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); need_laying_out = -1; } @@ -282,7 +282,7 @@ gld${EMULATION_NAME}_after_allocation (void) } if (need_laying_out != -1) - gld${EMULATION_NAME}_map_segments (need_laying_out); + ldelf_map_segments (need_laying_out); if (!bfd_link_relocatable (&link_info) && RELAXATION_ENABLED) { @@ -295,27 +295,6 @@ gld${EMULATION_NAME}_after_allocation (void) } } - -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void nios2_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -nios2_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&nios2_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file nios2_lang_for_each_input_file - EOF diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index 24a6368..eb75373 100644 --- a/ld/emultempl/ppc32elf.em +++ b/ld/emultempl/ppc32elf.em @@ -247,7 +247,6 @@ if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then fragment <<EOF /* Special handling for embedded SPU executables. */ extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *); -static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *); static bfd_boolean ppc_recognized_file (lang_input_statement_type *entry) @@ -255,7 +254,7 @@ ppc_recognized_file (lang_input_statement_type *entry) if (embedded_spu_file (entry, "-m32")) return TRUE; - return gld${EMULATION_NAME}_load_symbols (entry); + return ldelf_load_symbols (entry); } EOF diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 2a354ba..ef1fd0e 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -456,7 +456,7 @@ ppc_layout_sections_again (void) /* If we have changed sizes of the stub sections, then we need to recalculate all the section offsets. This may mean we need to add even more stubs. */ - gld${EMULATION_NAME}_map_segments (TRUE); + ldelf_map_segments (TRUE); if (!bfd_link_relocatable (&link_info)) ppc64_elf_set_toc (&link_info, link_info.output_bfd); @@ -565,7 +565,7 @@ gld${EMULATION_NAME}_after_allocation (void) unneeded, after ppc_layout_sections_again. Another call removes these sections from the segment map. Their presence is innocuous except for confusing ELF_SECTION_IN_SEGMENT. */ - gld${EMULATION_NAME}_map_segments (need_laying_out > 0); + ldelf_map_segments (need_laying_out > 0); if (need_laying_out != -1 && !bfd_link_relocatable (&link_info)) ppc64_elf_set_toc (&link_info, link_info.output_bfd); @@ -652,34 +652,12 @@ gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry) return dot_entry; } - -/* Avoid processing the fake stub_file in vercheck, stat_needed and - check_needed routines. */ - -static void (*real_func) (lang_input_statement_type *); - -static void ppc_for_each_input_file_wrapper (lang_input_statement_type *l) -{ - if (l != stub_file) - (*real_func) (l); -} - -static void -ppc_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) -{ - real_func = func; - lang_for_each_input_file (&ppc_for_each_input_file_wrapper); -} - -#define lang_for_each_input_file ppc_lang_for_each_input_file - EOF if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then fragment <<EOF /* Special handling for embedded SPU executables. */ extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *); -static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *); static bfd_boolean ppc64_recognized_file (lang_input_statement_type *entry) @@ -687,7 +665,7 @@ ppc64_recognized_file (lang_input_statement_type *entry) if (embedded_spu_file (entry, "-m64")) return TRUE; - return gld${EMULATION_NAME}_load_symbols (entry); + return ldelf_load_symbols (entry); } EOF LDEMUL_RECOGNIZED_FILE=ppc64_recognized_file diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em index 32f7584..ebc07df 100644 --- a/ld/emultempl/riscvelf.em +++ b/ld/emultempl/riscvelf.em @@ -62,7 +62,7 @@ gld${EMULATION_NAME}_after_allocation (void) } } - gld${EMULATION_NAME}_map_segments (need_layout); + ldelf_map_segments (need_layout); } /* This is a convenient point to tell BFD about target specific flags. diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em index 5ddf41c..54f9f8f 100644 --- a/ld/emultempl/spuelf.em +++ b/ld/emultempl/spuelf.em @@ -142,7 +142,7 @@ spu_place_special_section (asection *s, asection *o, const char *output_name) os = lang_output_section_find (output_name); if (os == NULL) { - os = gld${EMULATION_NAME}_place_orphan (s, output_name, 0); + os = ldelf_place_orphan (s, output_name, 0); os->addr_tree = NULL; } else if (params.ovly_flavour != ovly_soft_icache diff --git a/ld/emultempl/tic6xdsbt.em b/ld/emultempl/tic6xdsbt.em index 29b90e5..a6e2792 100644 --- a/ld/emultempl/tic6xdsbt.em +++ b/ld/emultempl/tic6xdsbt.em @@ -159,7 +159,7 @@ gld${EMULATION_NAME}_after_allocation (void) else if (ret > 0) layout_changed = 1; - gld${EMULATION_NAME}_map_segments (layout_changed); + ldelf_map_segments (layout_changed); } EOF diff --git a/ld/emultempl/vms.em b/ld/emultempl/vms.em index aadb327..c7e0b78 100644 --- a/ld/emultempl/vms.em +++ b/ld/emultempl/vms.em @@ -174,6 +174,7 @@ if test "$OUTPUT_FORMAT" = "elf64-ia64-vms"; then fragment <<EOF #include "elf-bfd.h" +#include "ldelfgen.h" EOF source_em ${srcdir}/emultempl/elf-generic.em @@ -212,7 +213,7 @@ gld${EMULATION_NAME}_after_allocation (void) if (need_layout < 0) einfo (_("%X%P: .eh_frame/.stab edit: %E\n")); else - gld${EMULATION_NAME}_map_segments (need_layout); + ldelf_map_segments (need_layout); } static void |