X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fldlang.c;h=14a6a577d224ecd32a5b1d00fb194d00f12f017f;hb=37a141bfed4dd3c33d77c15dfde00e4b4f5b24c7;hp=7b381ef2d5e6f3a640584573589ae9d1e9b0b6a8;hpb=0d41d9a2aa059e89d46e549d7d3a367a35a4b739;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldlang.c b/ld/ldlang.c index 7b381ef2d5..14a6a577d2 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,5 +1,5 @@ /* Linker command language support. - Copyright (C) 1991-2019 Free Software Foundation, Inc. + Copyright (C) 1991-2020 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -19,12 +19,14 @@ MA 02110-1301, USA. */ #include "sysdep.h" +#include #include "bfd.h" #include "libiberty.h" #include "filenames.h" #include "safe-ctype.h" #include "obstack.h" #include "bfdlink.h" +#include "ctf-api.h" #include "ld.h" #include "ldmain.h" @@ -115,6 +117,8 @@ lang_statement_list_type file_chain = { NULL, NULL }; lang_input_statement_type statement (reached via input_statement field in a lang_statement_union). */ lang_statement_list_type input_file_chain; +static const char *current_input_file; +struct bfd_elf_dynamic_list **current_dynamic_list_p; struct bfd_sym_chain entry_symbol = { NULL, NULL }; const char *entry_section = ".text"; struct lang_input_statement_flags input_flags; @@ -127,11 +131,15 @@ bfd_boolean delete_output_file_on_failure = FALSE; struct lang_phdr *lang_phdr_list; struct lang_nocrossrefs *nocrossref_list; struct asneeded_minfo **asneeded_list_tail; +static ctf_file_t *ctf_output; - /* Functions that traverse the linker script and might evaluate - DEFINED() need to increment this at the start of the traversal. */ +/* Functions that traverse the linker script and might evaluate + DEFINED() need to increment this at the start of the traversal. */ int lang_statement_iteration = 0; +/* Count times through one_lang_size_sections_pass after mark phase. */ +static int lang_sizing_iteration = 0; + /* Return TRUE if the PATTERN argument is a wildcard pattern. Although backslashes are treated specially if a pattern contains wildcards, we do not consider the mere presence of a backslash to @@ -148,7 +156,11 @@ int lang_statement_iteration = 0; #define outside_symbol_address(q) \ ((q)->value + outside_section_address (q->section)) -#define SECTION_NAME_MAP_LENGTH (16) +/* CTF sections smaller than this are not compressed: compression of + dictionaries this small doesn't gain much, and this lets consumers mmap the + sections directly out of the ELF file and use them with no decompression + overhead if they want to. */ +#define CTF_COMPRESSION_THRESHOLD 4096 void * stat_alloc (size_t size) @@ -164,6 +176,21 @@ name_match (const char *pattern, const char *name) return strcmp (pattern, name); } +static char * +ldirname (const char *name) +{ + const char *base = lbasename (name); + char *dirname; + + while (base > name && IS_DIR_SEPARATOR (base[-1])) + --base; + if (base == name) + return strdup ("."); + dirname = strdup (name); + dirname[base - name] = '\0'; + return dirname; +} + /* If PATTERN is of the form archive:file, return a pointer to the separator. If not, return NULL. */ @@ -206,7 +233,7 @@ input_statement_is_archive_path (const char *file_spec, char *sep, if (sep != file_spec) { - const char *aname = f->the_bfd->my_archive->filename; + const char *aname = bfd_get_filename (f->the_bfd->my_archive); *sep = 0; match = name_match (file_spec, aname) == 0; *sep = link_info.path_separator; @@ -268,7 +295,7 @@ walk_wild_file_in_exclude_list (struct name_list *exclude_list, else if (file->the_bfd != NULL && file->the_bfd->my_archive != NULL && name_match (list_tmp->name, - file->the_bfd->my_archive->filename) == 0) + bfd_get_filename (file->the_bfd->my_archive)) == 0) return TRUE; } @@ -319,7 +346,7 @@ walk_wild_section_general (lang_wild_statement_type *ptr, if (sec->spec.name != NULL) { - const char *sname = bfd_get_section_name (file->the_bfd, s); + const char *sname = bfd_section_name (s); skip = name_match (sec->spec.name, sname) != 0; } @@ -403,39 +430,50 @@ match_simple_wild (const char *pattern, const char *name) /* Return the numerical value of the init_priority attribute from section name NAME. */ -static unsigned long -get_init_priority (const char *name) +static int +get_init_priority (const asection *sec) { - char *end; - unsigned long init_priority; + const char *name = bfd_section_name (sec); + const char *dot; /* GCC uses the following section names for the init_priority - attribute with numerical values 101 and 65535 inclusive. A + attribute with numerical values 101 to 65535 inclusive. A lower value means a higher priority. - 1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the + 1: .init_array.NNNNN/.fini_array.NNNNN: Where NNNNN is the decimal numerical value of the init_priority attribute. The order of execution in .init_array is forward and .fini_array is backward. - 2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the + 2: .ctors.NNNNN/.dtors.NNNNN: Where NNNNN is 65535 minus the decimal numerical value of the init_priority attribute. The order of execution in .ctors is backward and .dtors is forward. - */ - if (strncmp (name, ".init_array.", 12) == 0 - || strncmp (name, ".fini_array.", 12) == 0) - { - init_priority = strtoul (name + 12, &end, 10); - return *end ? 0 : init_priority; - } - else if (strncmp (name, ".ctors.", 7) == 0 - || strncmp (name, ".dtors.", 7) == 0) - { - init_priority = strtoul (name + 7, &end, 10); - return *end ? 0 : 65535 - init_priority; - } - return 0; + .init_array.NNNNN sections would normally be placed in an output + .init_array section, .fini_array.NNNNN in .fini_array, + .ctors.NNNNN in .ctors, and .dtors.NNNNN in .dtors. This means + we should sort by increasing number (and could just use + SORT_BY_NAME in scripts). However if .ctors.NNNNN sections are + being placed in .init_array (which may also contain + .init_array.NNNNN sections) or .dtors.NNNNN sections are being + placed in .fini_array then we need to extract the init_priority + attribute and sort on that. */ + dot = strrchr (name, '.'); + if (dot != NULL && ISDIGIT (dot[1])) + { + char *end; + unsigned long init_priority = strtoul (dot + 1, &end, 10); + if (*end == 0) + { + if (dot == name + 6 + && (strncmp (name, ".ctors", 6) == 0 + || strncmp (name, ".dtors", 6) == 0)) + init_priority = 65535 - init_priority; + if (init_priority <= INT_MAX) + return init_priority; + } + } + return -1; } /* Compare sections ASEC and BSEC according to SORT. */ @@ -444,7 +482,7 @@ static int compare_section (sort_type sort, asection *asec, asection *bsec) { int ret; - unsigned long ainit_priority, binit_priority; + int a_priority, b_priority; switch (sort) { @@ -452,41 +490,35 @@ compare_section (sort_type sort, asection *asec, asection *bsec) abort (); case by_init_priority: - ainit_priority - = get_init_priority (bfd_get_section_name (asec->owner, asec)); - binit_priority - = get_init_priority (bfd_get_section_name (bsec->owner, bsec)); - if (ainit_priority == 0 || binit_priority == 0) + a_priority = get_init_priority (asec); + b_priority = get_init_priority (bsec); + if (a_priority < 0 || b_priority < 0) goto sort_by_name; - ret = ainit_priority - binit_priority; + ret = a_priority - b_priority; if (ret) break; else goto sort_by_name; case by_alignment_name: - ret = (bfd_section_alignment (bsec->owner, bsec) - - bfd_section_alignment (asec->owner, asec)); + ret = bfd_section_alignment (bsec) - bfd_section_alignment (asec); if (ret) break; /* Fall through. */ case by_name: -sort_by_name: - ret = strcmp (bfd_get_section_name (asec->owner, asec), - bfd_get_section_name (bsec->owner, bsec)); + sort_by_name: + ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec)); break; case by_name_alignment: - ret = strcmp (bfd_get_section_name (asec->owner, asec), - bfd_get_section_name (bsec->owner, bsec)); + ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec)); if (ret) break; /* Fall through. */ case by_alignment: - ret = (bfd_section_alignment (bsec->owner, bsec) - - bfd_section_alignment (asec->owner, asec)); + ret = bfd_section_alignment (bsec) - bfd_section_alignment (asec); break; } @@ -610,7 +642,7 @@ walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr, for (s = file->the_bfd->sections; s != NULL; s = s->next) { - const char *sname = bfd_get_section_name (file->the_bfd, s); + const char *sname = bfd_section_name (s); bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname); if (!skip) @@ -647,7 +679,7 @@ walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr, walk_wild_consider_section (ptr, file, s, sec0, callback, data); else { - const char *sname = bfd_get_section_name (file->the_bfd, s); + const char *sname = bfd_section_name (s); bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); if (!skip) @@ -682,7 +714,7 @@ walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr, walk_wild_consider_section (ptr, file, s, sec0, callback, data); else { - const char *sname = bfd_get_section_name (file->the_bfd, s); + const char *sname = bfd_section_name (s); bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); if (!skip) @@ -734,7 +766,7 @@ walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr, walk_wild_consider_section (ptr, file, s, sec1, callback, data); else { - const char *sname = bfd_get_section_name (file->the_bfd, s); + const char *sname = bfd_section_name (s); bfd_boolean skip = !match_simple_wild (wildsec2->spec.name, sname); @@ -908,12 +940,8 @@ walk_wild_file (lang_wild_statement_type *s, archive which is included, BFD will call ldlang_add_file, which will set the usrdata field of the member to the lang_input_statement. */ - if (member->usrdata != NULL) - { - walk_wild_section (s, - (lang_input_statement_type *) member->usrdata, - callback, data); - } + if (bfd_usrdata (member) != NULL) + walk_wild_section (s, bfd_usrdata (member), callback, data); member = bfd_openr_next_archived_file (f->the_bfd, member); } @@ -1081,23 +1109,16 @@ static lang_input_statement_type * new_afile (const char *name, lang_input_file_enum_type file_type, const char *target, - bfd_boolean add_to_list) + const char *from_filename) { lang_input_statement_type *p; lang_has_input_file = TRUE; - if (add_to_list) - p = new_stat (lang_input_statement, stat_ptr); - else - { - p = stat_alloc (sizeof (lang_input_statement_type)); - p->header.type = lang_input_statement_enum; - p->header.next = NULL; - } - + p = new_stat (lang_input_statement, stat_ptr); memset (&p->the_bfd, 0, sizeof (*p) - offsetof (lang_input_statement_type, the_bfd)); + p->extra_search_path = NULL; p->target = target; p->flags.dynamic = input_flags.dynamic; p->flags.add_DT_NEEDED_for_dynamic = input_flags.add_DT_NEEDED_for_dynamic; @@ -1138,6 +1159,10 @@ new_afile (const char *name, case lang_input_file_is_search_file_enum: p->filename = name; p->local_sym_name = name; + /* If name is a relative path, search the directory of the current linker + script first. */ + if (from_filename && !IS_ABSOLUTE_PATH (name)) + p->extra_search_path = ldirname (from_filename); p->flags.real = TRUE; p->flags.search_dirs = TRUE; break; @@ -1177,12 +1202,12 @@ lang_add_input_file (const char *name, within the sysroot subdirectory.) */ unsigned int outer_sysrooted = input_flags.sysrooted; input_flags.sysrooted = 0; - ret = new_afile (sysrooted_name, file_type, target, TRUE); + ret = new_afile (sysrooted_name, file_type, target, NULL); input_flags.sysrooted = outer_sysrooted; return ret; } - return new_afile (name, file_type, target, TRUE); + return new_afile (name, file_type, target, current_input_file); } struct out_section_hash_entry @@ -1433,7 +1458,7 @@ lang_memory_default (asection *section) lang_output_section_statement_type * lang_output_section_get (const asection *output_section) { - return get_userdata (output_section); + return bfd_section_userdata (output_section); } /* Find or create an output_section_statement with the given NAME. @@ -1551,7 +1576,7 @@ lang_output_section_find_by_flags (const asection *sec, /* We know the first statement on this list is *ABS*. May as well skip it. */ - first = &lang_os_list.head->output_section_statement; + first = (void *) lang_os_list.head; first = first->next; /* First try for an exact match. */ @@ -1779,7 +1804,7 @@ insert_os_after (lang_output_section_statement_type *after) lang_statement_union_type **assign = NULL; bfd_boolean ignore_first; - ignore_first = after == &lang_os_list.head->output_section_statement; + ignore_first = after == (void *) lang_os_list.head; for (where = &after->header.next; *where != NULL; @@ -1903,7 +1928,7 @@ lang_insert_orphan (asection *s, /* Shuffle the bfd section list to make the output file look neater. This is really only cosmetic. */ if (place->section == NULL - && after != &lang_os_list.head->output_section_statement) + && after != (void *) lang_os_list.head) { asection *bfd_section = after->bfd_section; @@ -2335,12 +2360,11 @@ sort_def_symbol (struct bfd_link_hash_entry *hash_entry, input_section_userdata_type *ud; struct map_symbol_def *def; - ud = ((input_section_userdata_type *) - get_userdata (hash_entry->u.def.section)); + ud = bfd_section_userdata (hash_entry->u.def.section); if (!ud) { ud = stat_alloc (sizeof (*ud)); - get_userdata (hash_entry->u.def.section) = ud; + bfd_set_section_userdata (hash_entry->u.def.section, ud); ud->map_symbol_def_tail = &ud->map_symbol_def_head; ud->map_symbol_def_count = 0; } @@ -2380,7 +2404,7 @@ init_os (lang_output_section_statement_type *s, flagword flags) /* Set the userdata of the output section to the output section statement to avoid lookup. */ - get_userdata (s->bfd_section) = s; + bfd_set_section_userdata (s->bfd_section, s); /* If there is a base address, make sure that any sections it might mention are initialized. */ @@ -2537,6 +2561,11 @@ lang_add_section (lang_statement_list_type *ptr, /* This prevents future calls from assigning this section. */ section->output_section = bfd_abs_section_ptr; } + else if (link_info.non_contiguous_regions_warnings) + einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes " + "section `%pA' from '%pB' match /DISCARD/ clause.\n"), + NULL, section, section->owner); + return; } @@ -2550,7 +2579,33 @@ lang_add_section (lang_statement_list_type *ptr, } if (section->output_section != NULL) - return; + { + if (!link_info.non_contiguous_regions) + return; + + /* SECTION has already been handled in a special way + (eg. LINK_ONCE): skip it. */ + if (bfd_is_abs_section (section->output_section)) + return; + + /* Already assigned to the same output section, do not process + it again, to avoid creating loops between duplicate sections + later. */ + if (section->output_section == output->bfd_section) + return; + + if (link_info.non_contiguous_regions_warnings && output->bfd_section) + einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may " + "change behaviour for section `%pA' from '%pB' (assigned to " + "%pA, but additional match: %pA)\n"), + NULL, section, section->owner, section->output_section, + output->bfd_section); + + /* SECTION has already been assigned to an output section, but + the user allows it to be mapped to another one in case it + overflows. We'll later update the actual output section in + size_input_section as appropriate. */ + } /* We don't copy the SEC_NEVER_LOAD flag from an input section to an output section, because we want to be able to include a @@ -2722,7 +2777,7 @@ wild_sort (lang_wild_statement_type *wild, } else { - ln = ls->section->owner->filename; + ln = bfd_get_filename (ls->section->owner); la = FALSE; } @@ -2737,7 +2792,7 @@ wild_sort (lang_wild_statement_type *wild, if (fa) fn = file->filename; if (la) - ln = ls->section->owner->filename; + ln = bfd_get_filename (ls->section->owner); i = filename_cmp (fn, ln); if (i > 0) @@ -2846,7 +2901,7 @@ lookup_name (const char *name) { lang_input_statement_type *search; - for (search = &input_file_chain.head->input_statement; + for (search = (void *) input_file_chain.head; search != NULL; search = search->next_real_file) { @@ -2861,8 +2916,25 @@ lookup_name (const char *name) } if (search == NULL) - search = new_afile (name, lang_input_file_is_search_file_enum, - default_target, FALSE); + { + /* Arrange to splice the input statement added by new_afile into + statement_list after the current input_file_chain tail. + We know input_file_chain is not an empty list, and that + lookup_name was called via open_input_bfds. Later calls to + lookup_name should always match an existing input_statement. */ + lang_statement_union_type **tail = stat_ptr->tail; + lang_statement_union_type **after + = (void *) ((char *) input_file_chain.tail + - offsetof (lang_input_statement_type, next_real_file) + + offsetof (lang_input_statement_type, header.next)); + lang_statement_union_type *rest = *after; + stat_ptr->tail = after; + search = new_afile (name, lang_input_file_is_search_file_enum, + default_target, NULL); + *stat_ptr->tail = rest; + if (*tail == NULL) + stat_ptr->tail = tail; + } /* If we have already added this file, or this file is not real don't add this file. */ @@ -2915,7 +2987,7 @@ check_excluded_libs (bfd *abfd) while (lib) { int len = strlen (lib->name); - const char *filename = lbasename (abfd->filename); + const char *filename = lbasename (bfd_get_filename (abfd)); if (strcmp (lib->name, "ALL") == 0) { @@ -3000,7 +3072,9 @@ load_symbols (lang_input_statement_type *entry, ldfile_assumed_script = TRUE; parser_input = input_script; + current_input_file = entry->filename; yyparse (); + current_input_file = NULL; ldfile_assumed_script = FALSE; /* missing_file is sticky. sysrooted will already have been @@ -3036,7 +3110,7 @@ load_symbols (lang_input_statement_type *entry, case bfd_archive: check_excluded_libs (entry->the_bfd); - entry->the_bfd->usrdata = entry; + bfd_set_usrdata (entry->the_bfd, entry); if (entry->flags.whole_archive) { bfd *member = NULL; @@ -3141,7 +3215,7 @@ get_target (const bfd_target *target, void *data) /* Like strcpy() but convert to lower case as well. */ static void -stricpy (char *dest, char *src) +stricpy (char *dest, const char *src) { char c; @@ -3155,7 +3229,7 @@ stricpy (char *dest, char *src) from haystack. */ static void -strcut (char *haystack, char *needle) +strcut (char *haystack, const char *needle) { haystack = strstr (haystack, needle); @@ -3174,7 +3248,7 @@ strcut (char *haystack, char *needle) Return a value indicating how "similar" they are. */ static int -name_compare (char *first, char *second) +name_compare (const char *first, const char *second) { char *copy1; char *copy2; @@ -3259,10 +3333,10 @@ closest_target_match (const bfd_target *target, void *data) /* Return the BFD target format of the first input file. */ -static char * +static const char * get_first_input_target (void) { - char *target = NULL; + const char *target = NULL; LANG_FOR_EACH_INPUT_STATEMENT (s) { @@ -3423,11 +3497,18 @@ ldlang_open_output (lang_statement_union_type *statement) } static void -init_opb (void) +init_opb (asection *s) { - unsigned x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + unsigned int x; + opb_shift = 0; + if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour + && s != NULL + && (s->flags & SEC_ELF_OCTETS) != 0) + return; + + x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); if (x > 1) while ((x & 1) == 0) { @@ -3588,6 +3669,186 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode) einfo ("%F"); } +/* Open the CTF sections in the input files with libctf: if any were opened, + create a fake input file that we'll write the merged CTF data to later + on. */ + +static void +ldlang_open_ctf (void) +{ + int any_ctf = 0; + int err; + + LANG_FOR_EACH_INPUT_STATEMENT (file) + { + asection *sect; + + /* Incoming files from the compiler have a single ctf_file_t in them + (which is presented to us by the libctf API in a ctf_archive_t + wrapper): files derived from a previous relocatable link have a CTF + archive containing possibly many CTF files. */ + + if ((file->the_ctf = ctf_bfdopen (file->the_bfd, &err)) == NULL) + { + if (err != ECTF_NOCTFDATA) + einfo (_("%P: warning: CTF section in `%pI' not loaded: " + "its types will be discarded: `%s'\n"), file, + ctf_errmsg (err)); + continue; + } + + /* Prevent the contents of this section from being written, while + requiring the section itself to be duplicated in the output. */ + /* This section must exist if ctf_bfdopen() succeeded. */ + sect = bfd_get_section_by_name (file->the_bfd, ".ctf"); + sect->size = 0; + sect->flags |= SEC_NEVER_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED; + + any_ctf = 1; + } + + if (!any_ctf) + { + ctf_output = NULL; + return; + } + + if ((ctf_output = ctf_create (&err)) != NULL) + return; + + einfo (_("%P: warning: CTF output not created: `%s'\n"), + ctf_errmsg (err)); + + LANG_FOR_EACH_INPUT_STATEMENT (errfile) + ctf_close (errfile->the_ctf); +} + +/* Merge together CTF sections. After this, only the symtab-dependent + function and data object sections need adjustment. */ + +static void +lang_merge_ctf (void) +{ + asection *output_sect; + + if (!ctf_output) + return; + + output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf"); + + /* If the section was discarded, don't waste time merging. */ + if (output_sect == NULL) + { + ctf_file_close (ctf_output); + ctf_output = NULL; + + LANG_FOR_EACH_INPUT_STATEMENT (file) + { + ctf_close (file->the_ctf); + file->the_ctf = NULL; + } + return; + } + + LANG_FOR_EACH_INPUT_STATEMENT (file) + { + if (!file->the_ctf) + continue; + + /* Takes ownership of file->u.the_ctfa. */ + if (ctf_link_add_ctf (ctf_output, file->the_ctf, file->filename) < 0) + { + einfo (_("%F%P: cannot link with CTF in %pB: %s\n"), file->the_bfd, + ctf_errmsg (ctf_errno (ctf_output))); + ctf_close (file->the_ctf); + file->the_ctf = NULL; + continue; + } + } + + if (ctf_link (ctf_output, CTF_LINK_SHARE_UNCONFLICTED) < 0) + { + einfo (_("%F%P: CTF linking failed; output will have no CTF section: %s\n"), + ctf_errmsg (ctf_errno (ctf_output))); + if (output_sect) + { + output_sect->size = 0; + output_sect->flags |= SEC_EXCLUDE; + } + } +} + +/* Let the emulation examine the symbol table and strtab to help it optimize the + CTF, if supported. */ + +void +ldlang_ctf_apply_strsym (struct elf_sym_strtab *syms, bfd_size_type symcount, + struct elf_strtab_hash *symstrtab) +{ + ldemul_examine_strtab_for_ctf (ctf_output, syms, symcount, symstrtab); +} + +/* Write out the CTF section. Called early, if the emulation isn't going to + need to dedup against the strtab and symtab, then possibly called from the + target linker code if the dedup has happened. */ +static void +lang_write_ctf (int late) +{ + size_t output_size; + asection *output_sect; + + if (!ctf_output) + return; + + if (late) + { + /* Emit CTF late if this emulation says it can do so. */ + if (ldemul_emit_ctf_early ()) + return; + } + else + { + if (!ldemul_emit_ctf_early ()) + return; + } + + /* Emit CTF. */ + + output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf"); + if (output_sect) + { + output_sect->contents = ctf_link_write (ctf_output, &output_size, + CTF_COMPRESSION_THRESHOLD); + output_sect->size = output_size; + output_sect->flags |= SEC_IN_MEMORY | SEC_KEEP; + + if (!output_sect->contents) + { + einfo (_("%F%P: CTF section emission failed; output will have no " + "CTF section: %s\n"), ctf_errmsg (ctf_errno (ctf_output))); + output_sect->size = 0; + output_sect->flags |= SEC_EXCLUDE; + } + } + + /* This also closes every CTF input file used in the link. */ + ctf_file_close (ctf_output); + ctf_output = NULL; + + LANG_FOR_EACH_INPUT_STATEMENT (file) + file->the_ctf = NULL; +} + +/* Write out the CTF section late, if the emulation needs that. */ + +void +ldlang_write_ctf_late (void) +{ + /* Trigger a "late call", if the emulation needs one. */ + + lang_write_ctf (1); +} + /* Add the supplied name to the symbol table as an undefined reference. This is a two step process as the symbol table doesn't even exist at the time the ld command line is processed. First we put the name @@ -3990,6 +4251,12 @@ process_insert_statements (lang_statement_union_type **start) lang_statement_union_type **ptr; lang_statement_union_type *first; + if (link_info.non_contiguous_regions) + { + einfo (_("warning: INSERT statement in linker script is " + "incompatible with --enable-non-contiguous-regions.\n")); + } + where = lang_output_section_find (i->where); if (where != NULL && i->is_before) { @@ -4125,7 +4392,7 @@ strip_excluded_output_sections (void) lang_reset_memory_regions (); } - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -4186,7 +4453,7 @@ lang_clear_os_map (void) if (map_head_is_link_order) return; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -4351,7 +4618,7 @@ print_input_statement (lang_input_statement_type *statm) /* Print all symbols defined in a particular section. This is called via bfd_link_hash_traverse, or by print_all_symbols. */ -static bfd_boolean +bfd_boolean print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) { asection *sec = (asection *) ptr; @@ -4392,8 +4659,7 @@ hash_entry_addr_cmp (const void *a, const void *b) static void print_all_symbols (asection *sec) { - input_section_userdata_type *ud - = (input_section_userdata_type *) get_userdata (sec); + input_section_userdata_type *ud = bfd_section_userdata (sec); struct map_symbol_def *def; struct bfd_link_hash_entry **entries; unsigned int i; @@ -4416,7 +4682,7 @@ print_all_symbols (asection *sec) /* Print the symbols. */ for (i = 0; i < ud->map_symbol_def_count; i++) - print_one_symbol (entries[i], sec); + ldemul_print_symbol (entries[i], sec); obstack_free (&map_obstack, entries); } @@ -4430,7 +4696,7 @@ print_input_section (asection *i, bfd_boolean is_discarded) int len; bfd_vma addr; - init_opb (); + init_opb (i); print_space (); minfo ("%s", i->name); @@ -4457,7 +4723,7 @@ print_input_section (asection *i, bfd_boolean is_discarded) size = 0; } - minfo ("0x%V %W %pB\n", addr, size, i->owner); + minfo ("0x%V %W %pB\n", addr, TO_ADDR (size), i->owner); if (size != i->rawsize && i->rawsize != 0) { @@ -4473,14 +4739,14 @@ print_input_section (asection *i, bfd_boolean is_discarded) --len; } - minfo (_("%W (size before relaxing)\n"), i->rawsize); + minfo (_("%W (size before relaxing)\n"), TO_ADDR (i->rawsize)); } if (i->output_section != NULL && i->output_section->owner == link_info.output_bfd) { if (link_info.reduce_memory_overheads) - bfd_link_hash_traverse (link_info.hash, print_one_symbol, i); + bfd_link_hash_traverse (link_info.hash, ldemul_print_symbol, i); else print_all_symbols (i); @@ -4511,7 +4777,7 @@ print_data_statement (lang_data_statement_type *data) bfd_size_type size; const char *name; - init_opb (); + init_opb (data->output_section); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -4580,7 +4846,7 @@ print_reloc_statement (lang_reloc_statement_type *reloc) bfd_vma addr; bfd_size_type size; - init_opb (); + init_opb (reloc->output_section); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -4610,7 +4876,7 @@ print_padding_statement (lang_padding_statement_type *s) int len; bfd_vma addr; - init_opb (); + init_opb (s->output_section); minfo (" *fill*"); len = sizeof " *fill*" - 1; @@ -4913,11 +5179,27 @@ size_input_section (lang_statement_union_type **this_ptr, lang_output_section_statement_type *output_section_statement, fill_type *fill, + bfd_boolean *removed, bfd_vma dot) { lang_input_section_type *is = &((*this_ptr)->input_section); asection *i = is->section; asection *o = output_section_statement->bfd_section; + *removed = 0; + + if (link_info.non_contiguous_regions) + { + /* If the input section I has already been successfully assigned + to an output section other than O, don't bother with it and + let the caller remove it from the list. Keep processing in + case we have already handled O, because the repeated passes + have reinitialized its size. */ + if (i->already_assigned && i->already_assigned != o) + { + *removed = 1; + return dot; + } + } if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) i->output_offset = i->vma - o->vma; @@ -4949,6 +5231,36 @@ size_input_section dot += alignment_needed; } + if (link_info.non_contiguous_regions) + { + /* If I would overflow O, let the caller remove I from the + list. */ + if (output_section_statement->region) + { + bfd_vma end = output_section_statement->region->origin + + output_section_statement->region->length; + + if (dot + TO_ADDR (i->size) > end) + { + if (i->flags & SEC_LINKER_CREATED) + einfo (_("%F%P: Output section '%s' not large enough for the " + "linker-created stubs section '%s'.\n"), + i->output_section->name, i->name); + + if (i->rawsize && i->rawsize != i->size) + einfo (_("%F%P: Relaxation not supported with " + "--enable-non-contiguous-regions (section '%s' " + "would overflow '%s' after it changed size).\n"), + i->name, i->output_section->name); + + *removed = 1; + dot = end; + i->output_section = NULL; + return dot; + } + } + } + /* Remember where in the output section this input section goes. */ i->output_offset = dot - o->vma; @@ -4956,6 +5268,14 @@ size_input_section dot += TO_ADDR (i->size); if (!(o->flags & SEC_FIXED_SIZE)) o->size = TO_SIZE (dot - o->vma); + + if (link_info.non_contiguous_regions) + { + /* Record that I was successfully assigned to O, and update + its actual output section too. */ + i->already_assigned = o; + i->output_section = o; + } } return dot; @@ -5080,6 +5400,7 @@ lang_check_section_addresses (void) for (p = NULL, i = 0; i < count; i++) { s = sections[i].sec; + init_opb (s); if ((s->flags & SEC_LOAD) != 0) { s_start = s->lma; @@ -5130,6 +5451,7 @@ lang_check_section_addresses (void) for (p = NULL, i = 0; i < count; i++) { s = sections[i].sec; + init_opb (s); s_start = s->vma; s_end = s_start + TO_ADDR (s->size) - 1; @@ -5240,10 +5562,14 @@ lang_size_sections_1 bfd_boolean check_regions) { lang_statement_union_type *s; + lang_statement_union_type *prev_s = NULL; + bfd_boolean removed_prev_s = FALSE; /* Size up the sections from their constituent parts. */ - for (s = *prev; s != NULL; s = s->header.next) + for (s = *prev; s != NULL; prev_s = s, s = s->header.next) { + bfd_boolean removed=FALSE; + switch (s->header.type) { case lang_output_section_statement_enum: @@ -5254,6 +5580,7 @@ lang_size_sections_1 int section_alignment = 0; os = &s->output_section_statement; + init_opb (os->bfd_section); if (os->constraint == -1) break; @@ -5306,9 +5633,8 @@ lang_size_sections_1 " section %s\n"), os->name); input = os->children.head->input_section.section; - bfd_set_section_vma (os->bfd_section->owner, - os->bfd_section, - bfd_section_vma (input->owner, input)); + bfd_set_section_vma (os->bfd_section, + bfd_section_vma (input)); if (!(os->bfd_section->flags & SEC_FIXED_SIZE)) os->bfd_section->size = input->size; break; @@ -5349,7 +5675,7 @@ lang_size_sections_1 && (strcmp (lang_memory_region_list->name_list.name, DEFAULT_MEMORY_REGION) != 0 || lang_memory_region_list->next != NULL) - && expld.phase != lang_mark_phase_enum) + && lang_sizing_iteration == 1) { /* By default this is an error rather than just a warning because if we allocate the section to the @@ -5363,13 +5689,11 @@ lang_size_sections_1 if (command_line.check_section_addresses) einfo (_("%F%P: error: no memory region specified" " for loadable section `%s'\n"), - bfd_get_section_name (link_info.output_bfd, - os->bfd_section)); + bfd_section_name (os->bfd_section)); else einfo (_("%P: warning: no memory region specified" " for loadable section `%s'\n"), - bfd_get_section_name (link_info.output_bfd, - os->bfd_section)); + bfd_section_name (os->bfd_section)); } newdot = os->region->current; @@ -5383,22 +5707,30 @@ lang_size_sections_1 if (section_alignment > 0) { bfd_vma savedot = newdot; - newdot = align_power (newdot, section_alignment); + bfd_vma diff = 0; + newdot = align_power (newdot, section_alignment); dotdelta = newdot - savedot; - if (dotdelta != 0 + + if (lang_sizing_iteration == 1) + diff = dotdelta; + else if (lang_sizing_iteration > 1) + { + /* Only report adjustments that would change + alignment from what we have already reported. */ + diff = newdot - os->bfd_section->vma; + if (!(diff & (((bfd_vma) 1 << section_alignment) - 1))) + diff = 0; + } + if (diff != 0 && (config.warn_section_align - || os->addr_tree != NULL) - && expld.phase != lang_mark_phase_enum) - einfo (ngettext ("%P: warning: changing start of " - "section %s by %lu byte\n", - "%P: warning: changing start of " - "section %s by %lu bytes\n", - (unsigned long) dotdelta), - os->name, (unsigned long) dotdelta); + || os->addr_tree != NULL)) + einfo (_("%P: warning: " + "start of section %s changed by %ld\n"), + os->name, (long) diff); } - bfd_set_section_vma (0, os->bfd_section, newdot); + bfd_set_section_vma (os->bfd_section, newdot); os->bfd_section->output_offset = 0; } @@ -5498,7 +5830,7 @@ lang_size_sections_1 /* Otherwise, keep the same lma to vma relationship as the previous section. */ else - lma = dot + last->lma - last->vma; + lma = os->bfd_section->vma + last->lma - last->vma; if (section_alignment > 0) lma = align_power (lma, section_alignment); @@ -5671,7 +6003,7 @@ lang_size_sections_1 *relax = TRUE; } dot = size_input_section (prev, output_section_statement, - fill, dot); + fill, &removed, dot); } break; @@ -5776,7 +6108,43 @@ lang_size_sections_1 FAIL (); break; } - prev = &s->header.next; + + /* If an input section doesn't fit in the current output + section, remove it from the list. Handle the case where we + have to remove an input_section statement here: there is a + special case to remove the first element of the list. */ + if (link_info.non_contiguous_regions && removed) + { + /* If we removed the first element during the previous + iteration, override the loop assignment of prev_s. */ + if (removed_prev_s) + prev_s = NULL; + + if (prev_s) + { + /* If there was a real previous input section, just skip + the current one. */ + prev_s->header.next=s->header.next; + s = prev_s; + removed_prev_s = FALSE; + } + else + { + /* Remove the first input section of the list. */ + *prev = s->header.next; + removed_prev_s = TRUE; + } + + /* Move to next element, unless we removed the head of the + list. */ + if (!removed_prev_s) + prev = &s->header.next; + } + else + { + prev = &s->header.next; + removed_prev_s = FALSE; + } } return dot; } @@ -5833,6 +6201,8 @@ void one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions) { lang_statement_iteration++; + if (expld.phase != lang_mark_phase_enum) + lang_sizing_iteration++; lang_size_sections_1 (&statement_list.head, abs_output_section, 0, 0, relax, check_regions); } @@ -5998,6 +6368,7 @@ lang_do_assignments_1 (lang_statement_union_type *s, os = &(s->output_section_statement); os->after_end = *found_end; + init_opb (os->bfd_section); if (os->bfd_section != NULL && !os->ignored) { if ((os->bfd_section->flags & SEC_ALLOC) != 0) @@ -6456,8 +6827,7 @@ lang_end (void) bfd_vma val; val = (h->u.def.value - + bfd_get_section_vma (link_info.output_bfd, - h->u.def.section->output_section) + + bfd_section_vma (h->u.def.section->output_section) + h->u.def.section->output_offset); if (!bfd_set_start_address (link_info.output_bfd, val)) einfo (_("%F%P: %s: can't set start address\n"), entry_symbol.name); @@ -6488,10 +6858,9 @@ lang_end (void) einfo (_("%P: warning: cannot find entry symbol %s;" " defaulting to %V\n"), entry_symbol.name, - bfd_get_section_vma (link_info.output_bfd, ts)); - if (!(bfd_set_start_address - (link_info.output_bfd, - bfd_get_section_vma (link_info.output_bfd, ts)))) + bfd_section_vma (ts)); + if (!bfd_set_start_address (link_info.output_bfd, + bfd_section_vma (ts))) einfo (_("%F%P: can't set start address\n")); } else @@ -6526,7 +6895,7 @@ lang_check (void) bfd *input_bfd; const bfd_arch_info_type *compatible; - for (file = &file_chain.head->input_statement; + for (file = (void *) file_chain.head; file != NULL; file = file->next) { @@ -6568,11 +6937,12 @@ lang_check (void) bfd_printable_name (input_bfd), input_bfd, bfd_printable_name (link_info.output_bfd)); } - else if (bfd_count_sections (input_bfd)) - { - /* If the input bfd has no contents, it shouldn't set the - private data of the output bfd. */ + /* If the input bfd has no contents, it shouldn't set the + private data of the output bfd. */ + else if ((input_bfd->flags & DYNAMIC) != 0 + || bfd_count_sections (input_bfd) != 0) + { bfd_error_handler_type pfn = NULL; /* If we aren't supposed to warn about mismatched input @@ -6868,7 +7238,7 @@ lang_for_each_input_file (void (*func) (lang_input_statement_type *)) { lang_input_statement_type *f; - for (f = &input_file_chain.head->input_statement; + for (f = (void *) input_file_chain.head; f != NULL; f = f->next_real_file) if (f->flags.real) @@ -6901,7 +7271,7 @@ ldlang_add_file (lang_input_statement_type *entry) *link_info.input_bfds_tail = entry->the_bfd; link_info.input_bfds_tail = &entry->the_bfd->link.next; - entry->the_bfd->usrdata = entry; + bfd_set_usrdata (entry->the_bfd, entry); bfd_set_gp_size (entry->the_bfd, g_switch_value); /* Look through the sections and check for any which should not be @@ -6994,7 +7364,7 @@ lang_reset_memory_regions (void) p->last_os = NULL; } - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -7231,8 +7601,8 @@ static lang_input_statement_type * find_replacements_insert_point (bfd_boolean *before) { lang_input_statement_type *claim1, *lastobject; - lastobject = &input_file_chain.head->input_statement; - for (claim1 = &file_chain.head->input_statement; + lastobject = (void *) input_file_chain.head; + for (claim1 = (void *) file_chain.head; claim1 != NULL; claim1 = claim1->next) { @@ -7274,7 +7644,7 @@ find_rescan_insertion (lang_input_statement_type *add) file chain if it is full of archive elements. Archives don't appear on the file chain, but if an element has been extracted then their input_statement->next points at it. */ - for (f = &input_file_chain.head->input_statement; + for (f = (void *) input_file_chain.head; f != NULL; f = f->next_real_file) { @@ -7407,7 +7777,7 @@ lang_propagate_lma_regions (void) { lang_output_section_statement_type *os; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -7431,7 +7801,7 @@ lang_process (void) /* Open the output file. */ lang_for_each_statement (ldlang_open_output); - init_opb (); + init_opb (NULL); ldemul_create_output_section_statements (); @@ -7501,8 +7871,7 @@ lang_process (void) if (*prev != (void *) plugin_insert->next_real_file) { /* We didn't find the expected input statement. - This can happen due to lookup_name creating input - statements not linked into the statement list. */ + Fall back to adding after plugin_insert. */ prev = &plugin_insert->header.next; } } @@ -7544,7 +7913,7 @@ lang_process (void) *iter = temp; if (my_arch != NULL) { - lang_input_statement_type *parent = my_arch->usrdata; + lang_input_statement_type *parent = bfd_usrdata (my_arch); if (parent != NULL) parent->next = (lang_input_statement_type *) ((char *) iter @@ -7583,6 +7952,8 @@ lang_process (void) if (config.map_file != NULL) lang_print_asneeded (); + ldlang_open_ctf (); + bfd_section_already_linked_table_free (); /* Make sure that we're not mixing architectures. We call this @@ -7634,6 +8005,8 @@ lang_process (void) output statement, so that it isn't reordered. */ process_insert_statements (&lang_os_list.head->header.next); + ldemul_before_place_orphans (); + /* Find any sections not attached explicitly and handle them. */ lang_place_orphans (); @@ -7659,6 +8032,14 @@ lang_process (void) } } + /* Merge together CTF sections. After this, only the symtab-dependent + function and data object sections need adjustment. */ + lang_merge_ctf (); + + /* Emit the CTF, iff the emulation doesn't need to do late emission after + examining things laid out late, like the strtab. */ + lang_write_ctf (0); + /* Copy forward lma regions for output sections in same lma region. */ lang_propagate_lma_regions (); @@ -8075,7 +8456,7 @@ lang_record_phdrs (void) bfd_vma at; c = 0; - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -8161,7 +8542,7 @@ lang_record_phdrs (void) free (secs); /* Make sure all the phdr assignments succeeded. */ - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) { @@ -8944,15 +9325,16 @@ lang_add_unique (const char *name) /* Append the list of dynamic symbols to the existing one. */ void -lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic) +lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p, + struct bfd_elf_version_expr *dynamic) { - if (link_info.dynamic_list) + if (*list_p) { struct bfd_elf_version_expr *tail; for (tail = dynamic; tail->next != NULL; tail = tail->next) ; - tail->next = link_info.dynamic_list->head.list; - link_info.dynamic_list->head.list = dynamic; + tail->next = (*list_p)->head.list; + (*list_p)->head.list = dynamic; } else { @@ -8961,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic) d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d); d->head.list = dynamic; d->match = lang_vers_match; - link_info.dynamic_list = d; + *list_p = d; } } @@ -8983,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void) dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++", FALSE); - lang_append_dynamic_list (dynamic); + lang_append_dynamic_list (&link_info.dynamic_list, dynamic); } /* Append the list of C++ operator new and delete dynamic symbols to the @@ -9004,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void) dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++", FALSE); - lang_append_dynamic_list (dynamic); + lang_append_dynamic_list (&link_info.dynamic_list, dynamic); } /* Scan a space and/or comma separated string of features. */ @@ -9062,14 +9444,16 @@ lang_print_memory_usage (void) for (r = lang_memory_region_list; r->next != NULL; r = r->next) { bfd_vma used_length = r->current - r->origin; - double percent; printf ("%16s: ",r->name_list.name); lang_print_memory_size (used_length); lang_print_memory_size ((bfd_vma) r->length); - percent = used_length * 100.0 / r->length; - - printf (" %6.2f%%\n", percent); + if (r->length != 0) + { + double percent = used_length * 100.0 / r->length; + printf (" %6.2f%%", percent); + } + printf ("\n"); } }