bfd_boolean ldfile_open_file_search (const char *arch, lang_input_statement_type *entry, const char *lib, const char *suffix) { search_dirs_type *search; /* If this is not an archive, try to open it in the current directory first. */ if (! entry->flags.maybe_archive) { if (entry->flags.sysrooted && IS_ABSOLUTE_PATH (entry->filename)) { char *name = concat (ld_sysroot, entry->filename, (const char *) NULL); if (ldfile_try_open_bfd (name, entry)) { entry->filename = name; return TRUE; } free (name); } else if (ldfile_try_open_bfd (entry->filename, entry)) return TRUE; if (IS_ABSOLUTE_PATH (entry->filename)) return FALSE; } for (search = search_head; search != NULL; search = search->next) { char *string; if (entry->flags.dynamic && !bfd_link_relocatable (&link_info)) { if (ldemul_open_dynamic_archive (arch, search, entry)) return TRUE; } if (entry->flags.maybe_archive && !entry->flags.full_name_provided) string = concat (search->name, slash, lib, entry->filename, arch, suffix, (const char *) NULL); else string = concat (search->name, slash, entry->filename, (const char *) 0); if (ldfile_try_open_bfd (string, entry)) { entry->filename = string; return TRUE; } free (string); } return FALSE; }
/* Return TRUE if a defined symbol might be reachable from outside the universe of claimed objects. */ static inline bfd_boolean is_visible_from_outside (struct ld_plugin_symbol *lsym, struct bfd_link_hash_entry *blhe) { struct bfd_sym_chain *sym; if (bfd_link_relocatable (&link_info)) return TRUE; if (link_info.export_dynamic || bfd_link_dll (&link_info)) { /* Check if symbol is hidden by version script. */ if (bfd_hide_sym_by_version (link_info.version_info, blhe->root.string)) return FALSE; /* Only ELF symbols really have visibility. */ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) { struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe; int vis = ELF_ST_VISIBILITY (el->other); return vis == STV_DEFAULT || vis == STV_PROTECTED; } /* On non-ELF targets, we can safely make inferences by considering what visibility the plugin would have liked to apply when it first sent us the symbol. During ELF symbol processing, visibility only ever becomes more restrictive, not less, when symbols are merged, so this is a conservative estimate; it may give false positives, declaring something visible from outside when it in fact would not have been, but this will only lead to missed optimisation opportunities during LTRANS at worst; it will not give false negatives, which can lead to the disastrous conclusion that the related symbol is IRONLY. (See GCC PR46319 for an example.) */ return (lsym->visibility == LDPV_DEFAULT || lsym->visibility == LDPV_PROTECTED); } for (sym = &entry_symbol; sym != NULL; sym = sym->next) if (sym->name && strcmp (sym->name, blhe->root.string) == 0) return TRUE; return FALSE; }
bfd_boolean bfd_coff_reloc16_relax_section (bfd *abfd, asection *input_section, struct bfd_link_info *link_info, bfd_boolean *again) { /* Get enough memory to hold the stuff. */ bfd *input_bfd = input_section->owner; unsigned *shrinks; unsigned shrink = 0; long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); arelent **reloc_vector = NULL; long reloc_count; if (bfd_link_relocatable (link_info)) (*link_info->callbacks->einfo) (_("%P%F: --relax and -r may not be used together\n")); /* We only do global relaxation once. It is not safe to do it multiple times (see discussion of the "shrinks" array below). */ *again = FALSE; if (reloc_size < 0) return FALSE; reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); if (!reloc_vector && reloc_size > 0) return FALSE; /* Get the relocs and think about them. */ reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, _bfd_generic_link_get_symbols (input_bfd)); if (reloc_count < 0) { free (reloc_vector); return FALSE; } /* The reloc16.c and related relaxing code is very simple, the price for that simplicity is we can only call this function once for each section. So, to get the best results within that limitation, we do multiple relaxing passes over each section here. That involves keeping track of the "shrink" at each reloc in the section. This allows us to accurately determine the relative location of two relocs within this section. In theory, if we kept the "shrinks" array for each section for the entire link, we could use the generic relaxing code in the linker and get better results, particularly for jsr->bsr and 24->16 bit memory reference relaxations. */ if (reloc_count > 0) { int another_pass = 0; bfd_size_type amt; /* Allocate and initialize the shrinks array for this section. The last element is used as an accumulator of shrinks. */ amt = reloc_count + 1; amt *= sizeof (unsigned); shrinks = (unsigned *) bfd_zmalloc (amt); /* Loop until nothing changes in this section. */ do { arelent **parent; unsigned int i; long j; another_pass = 0; for (i = 0, parent = reloc_vector; *parent; parent++, i++) { /* Let the target/machine dependent code examine each reloc in this section and attempt to shrink it. */ shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent, shrinks[i], link_info); /* If it shrunk, note it in the shrinks array and set up for another pass. */ if (shrink != shrinks[i]) { another_pass = 1; for (j = i + 1; j <= reloc_count; j++) shrinks[j] += shrink - shrinks[i]; } } } while (another_pass); shrink = shrinks[reloc_count]; free ((char *) shrinks); } input_section->rawsize = input_section->size; input_section->size -= shrink; free ((char *) reloc_vector); return TRUE; }
/* Helper to size leading part of tv array and set it up. */ static void set_tv_header (struct ld_plugin_tv *tv) { size_t i; /* Version info. */ static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL); static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100; for (i = 0; i < tv_header_size; i++) { tv[i].tv_tag = tv_header_tags[i]; #define TVU(x) tv[i].tv_u.tv_ ## x switch (tv[i].tv_tag) { case LDPT_MESSAGE: TVU(message) = message; break; case LDPT_API_VERSION: TVU(val) = LD_PLUGIN_API_VERSION; break; case LDPT_GNU_LD_VERSION: TVU(val) = major * 100 + minor; break; case LDPT_LINKER_OUTPUT: TVU(val) = (bfd_link_relocatable (&link_info) ? LDPO_REL : bfd_link_pde (&link_info) ? LDPO_EXEC : bfd_link_pie (&link_info) ? LDPO_PIE : LDPO_DYN); break; case LDPT_OUTPUT_NAME: TVU(string) = output_filename; break; case LDPT_REGISTER_CLAIM_FILE_HOOK: TVU(register_claim_file) = register_claim_file; break; case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: TVU(register_all_symbols_read) = register_all_symbols_read; break; case LDPT_REGISTER_CLEANUP_HOOK: TVU(register_cleanup) = register_cleanup; break; case LDPT_ADD_SYMBOLS: TVU(add_symbols) = add_symbols; break; case LDPT_GET_INPUT_FILE: TVU(get_input_file) = get_input_file; break; case LDPT_GET_VIEW: TVU(get_view) = get_view; break; case LDPT_RELEASE_INPUT_FILE: TVU(release_input_file) = release_input_file; break; case LDPT_GET_SYMBOLS: TVU(get_symbols) = get_symbols_v1; break; case LDPT_GET_SYMBOLS_V2: TVU(get_symbols) = get_symbols_v2; break; case LDPT_ADD_INPUT_FILE: TVU(add_input_file) = add_input_file; break; case LDPT_ADD_INPUT_LIBRARY: TVU(add_input_library) = add_input_library; break; case LDPT_SET_EXTRA_LIBRARY_PATH: TVU(set_extra_library_path) = set_extra_library_path; break; default: /* Added a new entry to the array without adding a new case to set up its value is a bug. */ FAIL (); } #undef TVU } }
int main (int argc, char **argv) { char *emulation; long start_time = get_run_time (); #ifdef HAVE_SBRK char *start_sbrk = (char *) sbrk (0); #endif #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); #endif #if defined (HAVE_SETLOCALE) setlocale (LC_CTYPE, ""); #endif bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); program_name = argv[0]; xmalloc_set_program_name (program_name); START_PROGRESS (program_name, 0); expandargv (&argc, &argv); bfd_init (); bfd_set_error_program_name (program_name); /* We want to notice and fail on those nasty BFD assertions which are likely to signal incorrect output being generated but otherwise may leave no trace. */ default_bfd_assert_handler = bfd_set_assert_handler (ld_bfd_assert_handler); xatexit (ld_cleanup); /* Set up the sysroot directory. */ ld_sysroot = get_sysroot (argc, argv); if (*ld_sysroot) ld_canon_sysroot = lrealpath (ld_sysroot); if (ld_canon_sysroot) ld_canon_sysroot_len = strlen (ld_canon_sysroot); else ld_canon_sysroot_len = -1; /* Set the default BFD target based on the configured target. Doing this permits the linker to be configured for a particular target, and linked against a shared BFD library which was configured for a different target. The macro TARGET is defined by Makefile. */ if (! bfd_set_default_target (TARGET)) { einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET); xexit (1); } #if YYDEBUG { extern int yydebug; yydebug = 1; } #endif config.build_constructors = TRUE; config.rpath_separator = ':'; config.split_by_reloc = (unsigned) -1; config.split_by_file = (bfd_size_type) -1; config.make_executable = TRUE; config.magic_demand_paged = TRUE; config.text_read_only = TRUE; link_info.disable_target_specific_optimizations = -1; command_line.warn_mismatch = TRUE; command_line.warn_search_mismatch = TRUE; command_line.check_section_addresses = -1; /* We initialize DEMANGLING based on the environment variable COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the output of the linker, unless COLLECT_NO_DEMANGLE is set in the environment. Acting the same way here lets us provide the same interface by default. */ demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL; link_info.allow_undefined_version = TRUE; link_info.keep_memory = TRUE; link_info.combreloc = TRUE; link_info.strip_discarded = TRUE; link_info.emit_hash = TRUE; link_info.callbacks = &link_callbacks; link_info.input_bfds_tail = &link_info.input_bfds; /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init and _fini symbols. We are compatible. */ link_info.init_function = "_init"; link_info.fini_function = "_fini"; link_info.relax_pass = 1; link_info.extern_protected_data = -1; link_info.dynamic_undefined_weak = -1; link_info.pei386_auto_import = -1; link_info.spare_dynamic_tags = 5; link_info.path_separator = ':'; #ifdef DEFAULT_FLAG_COMPRESS_DEBUG link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB; #endif ldfile_add_arch (""); emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); default_target = ldemul_choose_target (argc, argv); config.maxpagesize = bfd_emul_get_maxpagesize (default_target); config.commonpagesize = bfd_emul_get_commonpagesize (default_target); lang_init (); ldexp_init (); ldemul_before_parse (); lang_has_input_file = FALSE; parse_args (argc, argv); if (config.hash_table_size != 0) bfd_hash_set_default_size (config.hash_table_size); #ifdef ENABLE_PLUGINS /* Now all the plugin arguments have been gathered, we can load them. */ plugin_load_plugins (); #endif /* ENABLE_PLUGINS */ ldemul_set_symbols (); /* If we have not already opened and parsed a linker script, try the default script from command line first. */ if (saved_script_handle == NULL && command_line.default_script != NULL) { ldfile_open_command_file (command_line.default_script); parser_input = input_script; yyparse (); } /* If we have not already opened and parsed a linker script read the emulation's appropriate default script. */ if (saved_script_handle == NULL) { int isfile; char *s = ldemul_get_script (&isfile); if (isfile) ldfile_open_default_command_file (s); else { lex_string = s; lex_redirect (s, _("built in linker script"), 1); } parser_input = input_script; yyparse (); lex_string = NULL; } if (verbose) { if (saved_script_handle) info_msg (_("using external linker script:")); else info_msg (_("using internal linker script:")); info_msg ("\n==================================================\n"); if (saved_script_handle) { static const int ld_bufsz = 8193; size_t n; char *buf = (char *) xmalloc (ld_bufsz); rewind (saved_script_handle); while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) { buf[n] = 0; info_msg (buf); } rewind (saved_script_handle); free (buf); } else { int isfile; info_msg (ldemul_get_script (&isfile)); } info_msg ("\n==================================================\n"); } if (command_line.print_output_format) info_msg ("%s\n", lang_get_output_target ()); lang_final (); /* If the only command line argument has been -v or --version or --verbose then ignore any input files provided by linker scripts and exit now. We do not want to create an output file when the linker is just invoked to provide version information. */ if (argc == 2 && version_printed) xexit (0); if (!lang_has_input_file) { if (version_printed || command_line.print_output_format) xexit (0); einfo (_("%P%F: no input files\n")); } if (trace_files) info_msg (_("%P: mode %s\n"), emulation); ldemul_after_parse (); if (config.map_filename) { if (strcmp (config.map_filename, "-") == 0) { config.map_file = stdout; } else { config.map_file = fopen (config.map_filename, FOPEN_WT); if (config.map_file == (FILE *) NULL) { bfd_set_error (bfd_error_system_call); einfo (_("%P%F: cannot open map file %s: %E\n"), config.map_filename); } } } lang_process (); /* Print error messages for any missing symbols, for any warning symbols, and possibly multiple definitions. */ if (bfd_link_relocatable (&link_info)) link_info.output_bfd->flags &= ~EXEC_P; else link_info.output_bfd->flags |= EXEC_P; if ((link_info.compress_debug & COMPRESS_DEBUG)) { link_info.output_bfd->flags |= BFD_COMPRESS; if (link_info.compress_debug == COMPRESS_DEBUG_GABI_ZLIB) link_info.output_bfd->flags |= BFD_COMPRESS_GABI; } ldwrite (); if (config.map_file != NULL) lang_map (); if (command_line.cref) output_cref (config.map_file != NULL ? config.map_file : stdout); if (nocrossref_list != NULL) check_nocrossrefs (); if (command_line.print_memory_usage) lang_print_memory_usage (); #if 0 { struct bfd_link_hash_entry * h; h = bfd_link_hash_lookup (link_info.hash, "__image_base__", 0,0,1); fprintf (stderr, "lookup = %p val %lx\n", h, h ? h->u.def.value : 1); } #endif ldexp_finish (); lang_finish (); /* Even if we're producing relocatable output, some non-fatal errors should be reported in the exit status. (What non-fatal errors, if any, do we want to ignore for relocatable output?) */ if (!config.make_executable && !force_make_executable) { if (trace_files) einfo (_("%P: link errors found, deleting executable `%s'\n"), output_filename); /* The file will be removed by ld_cleanup. */ xexit (1); } else { if (! bfd_close (link_info.output_bfd)) einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd); /* If the --force-exe-suffix is enabled, and we're making an executable file and it doesn't end in .exe, copy it to one which does. */ if (!bfd_link_relocatable (&link_info) && command_line.force_exe_suffix) { int len = strlen (output_filename); if (len < 4 || (strcasecmp (output_filename + len - 4, ".exe") != 0 && strcasecmp (output_filename + len - 4, ".dll") != 0)) { FILE *src; FILE *dst; const int bsize = 4096; char *buf = (char *) xmalloc (bsize); int l; char *dst_name = (char *) xmalloc (len + 5); strcpy (dst_name, output_filename); strcat (dst_name, ".exe"); src = fopen (output_filename, FOPEN_RB); dst = fopen (dst_name, FOPEN_WB); if (!src) einfo (_("%P%F: unable to open for source of copy `%s'\n"), output_filename); if (!dst) einfo (_("%P%F: unable to open for destination of copy `%s'\n"), dst_name); while ((l = fread (buf, 1, bsize, src)) > 0) { int done = fwrite (buf, 1, l, dst); if (done != l) einfo (_("%P: Error writing file `%s'\n"), dst_name); } fclose (src); if (fclose (dst) == EOF) einfo (_("%P: Error closing file `%s'\n"), dst_name); free (dst_name); free (buf); } } } END_PROGRESS (program_name); if (config.stats) { #ifdef HAVE_SBRK char *lim = (char *) sbrk (0); #endif long run_time = get_run_time () - start_time; fflush (stdout); fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"), program_name, run_time / 1000000, run_time % 1000000); #ifdef HAVE_SBRK fprintf (stderr, _("%s: data size %ld\n"), program_name, (long) (lim - start_sbrk)); #endif fflush (stderr); } /* Prevent ld_cleanup from doing anything, after a successful link. */ output_filename = NULL; xexit (0); return 0; }
void ldctor_build_sets (void) { static bfd_boolean called; bfd_boolean header_printed; struct set_info *p; /* The emulation code may call us directly, but we only want to do this once. */ if (called) return; called = TRUE; if (constructors_sorted) { for (p = sets; p != NULL; p = p->next) { int c, i; struct set_element *e; struct set_element **array; if (p->elements == NULL) continue; c = 0; for (e = p->elements; e != NULL; e = e->next) ++c; array = (struct set_element **) xmalloc (c * sizeof *array); i = 0; for (e = p->elements; e != NULL; e = e->next) { array[i] = e; ++i; } qsort (array, c, sizeof *array, ctor_cmp); e = array[0]; p->elements = e; for (i = 0; i < c - 1; i++) array[i]->next = array[i + 1]; array[i]->next = NULL; free (array); } } lang_list_init (&constructor_list); push_stat_ptr (&constructor_list); header_printed = FALSE; for (p = sets; p != NULL; p = p->next) { struct set_element *e; reloc_howto_type *howto; int reloc_size, size; /* If the symbol is defined, we may have been invoked from collect, and the sets may already have been built, so we do not do anything. */ if (p->h->type == bfd_link_hash_defined || p->h->type == bfd_link_hash_defweak) continue; /* For each set we build: set: .long number_of_elements .long element0 ... .long elementN .long 0 except that we use the right size instead of .long. When generating relocatable output, we generate relocs instead of addresses. */ howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc); if (howto == NULL) { if (bfd_link_relocatable (&link_info)) { einfo (_("%P%X: %s does not support reloc %s for set %s\n"), bfd_get_target (link_info.output_bfd), bfd_get_reloc_code_name (p->reloc), p->h->root.string); continue; } /* If this is not a relocatable link, all we need is the size, which we can get from the input BFD. */ if (p->elements->section->owner != NULL) howto = bfd_reloc_type_lookup (p->elements->section->owner, p->reloc); if (howto == NULL) { einfo (_("%P%X: %s does not support reloc %s for set %s\n"), bfd_get_target (p->elements->section->owner), bfd_get_reloc_code_name (p->reloc), p->h->root.string); continue; } } reloc_size = bfd_get_reloc_size (howto); switch (reloc_size) { case 1: size = BYTE; break; case 2: size = SHORT; break; case 4: size = LONG; break; case 8: if (howto->complain_on_overflow == complain_overflow_signed) size = SQUAD; else size = QUAD; break; default: einfo (_("%P%X: Unsupported size %d for set %s\n"), bfd_get_reloc_size (howto), p->h->root.string); size = LONG; break; } lang_add_assignment (exp_assign (".", exp_unop (ALIGN_K, exp_intop (reloc_size)), FALSE)); lang_add_assignment (exp_assign (p->h->root.string, exp_nameop (NAME, "."), FALSE)); lang_add_data (size, exp_intop (p->count)); for (e = p->elements; e != NULL; e = e->next) { if (config.map_file != NULL) { int len; if (! header_printed) { minfo (_("\nSet Symbol\n\n")); header_printed = TRUE; } minfo ("%s", p->h->root.string); len = strlen (p->h->root.string); if (len >= 19) { print_nl (); len = 0; } while (len < 20) { print_space (); ++len; } if (e->name != NULL) minfo ("%T\n", e->name); else minfo ("%G\n", e->section->owner, e->section, e->value); } /* Need SEC_KEEP for --gc-sections. */ if (! bfd_is_abs_section (e->section)) e->section->flags |= SEC_KEEP; if (bfd_link_relocatable (&link_info)) lang_add_reloc (p->reloc, howto, e->section, e->name, exp_intop (e->value)); else lang_add_data (size, exp_relop (e->section, e->value)); } lang_add_data (size, exp_intop (0)); } pop_stat_ptr (); }